SCIP Doxygen Documentation
 
Loading...
Searching...
No Matches
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);
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 */
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;
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 {
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 */
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);
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 */
847 {
849 }
850 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
852 {
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);
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 */
889 {
891 }
892 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
894 {
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);
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);
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
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 {
3743
3745 col->unchangedobj = newobj;
3746
3747 /* update the objective function vector norms */
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);
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);
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);
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);
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);
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);
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);
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 sbitlim = col->sbitlim;
4355 nsbcalls = col->nsbcalls;
4356
4357 validsblp = stat->nlps;
4358 sbsolval = col->primsol;
4359 sblpobjval = SCIPlpGetObjval(lp, set, prob);
4360 sbnode = stat->nnodes;
4361 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4362
4363 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4364 if( lp->looseobjvalinf > 0 )
4365 {
4366 sbdown = -SCIPsetInfinity(set);
4367 sbup = -SCIPsetInfinity(set);
4368 sbdownvalid = FALSE;
4369 sbupvalid = FALSE;
4370 }
4371 else
4372 {
4373 SCIP_RETCODE retcode;
4374 int iter;
4375
4376 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4377 SCIPvarGetName(col->var), col->primsol, itlim);
4378
4379 /* start timing */
4381
4382 /* call LPI strong branching */
4383 sbitlim = itlim;
4384 nsbcalls++;
4385
4386 sbdown = lp->lpobjval;
4387 sbup = lp->lpobjval;
4388 sbdownvalid = col->sbdownvalid;
4389 sbupvalid = col->sbupvalid;
4390
4391 if( integral )
4392 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4393 else
4394 {
4395 assert( ! SCIPsetIsIntegral(set, col->primsol) );
4396 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4397 }
4398
4399 /* check return code for errors */
4400 if( retcode == SCIP_LPERROR )
4401 {
4402 *lperror = TRUE;
4403 sbdown = SCIP_INVALID;
4404 sbup = SCIP_INVALID;
4405 sbdownvalid = FALSE;
4406 sbupvalid = FALSE;
4407 validsblp = -1;
4408 sbsolval = SCIP_INVALID;
4409 sblpobjval = SCIP_INVALID;
4410 sbnode = -1;
4411 }
4412 else
4413 {
4414 SCIP_Real looseobjval;
4415
4416 *lperror = FALSE;
4417 SCIP_CALL( retcode );
4418
4419 looseobjval = getFiniteLooseObjval(lp, set, prob);
4420 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4421 sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4422
4423 /* update strong branching statistics */
4424 if( updatestat )
4425 {
4426 if( iter == -1 )
4427 {
4428 /* calculate average iteration number */
4429 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4430 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4431 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4432 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4433 : 0;
4434 if( iter/2 >= itlim )
4435 iter = 2*itlim;
4436 }
4437 SCIPstatIncrement(stat, set, nstrongbranchs);
4438 SCIPstatAdd(stat, set, nsblpiterations, iter);
4439 if( stat->nnodes == 1 )
4440 {
4441 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4442 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4443 }
4444 }
4445 }
4446
4447 /* stop timing */
4449 }
4450 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/
4451 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/
4452
4453 if( down != NULL)
4454 *down = sbdown;
4455 if( up != NULL )
4456 *up = sbup;
4457 if( downvalid != NULL )
4458 *downvalid = sbdownvalid;
4459 if( upvalid != NULL )
4460 *upvalid = sbupvalid;
4461
4462 if( updatecol )
4463 {
4464 col->sbdown = sbdown;
4465 col->sbup = sbup;
4466 col->sbdownvalid = sbdownvalid;
4467 col->sbupvalid = sbupvalid;
4468 col->validsblp = validsblp;
4469 col->sbsolval = sbsolval;
4470 col->sblpobjval = sblpobjval;
4471 col->sbnode = sbnode;
4472 col->sbitlim = sbitlim;
4473 col->nsbcalls = nsbcalls;
4474 }
4475
4476 return SCIP_OKAY;
4477}
4478
4479/** gets strong branching information on column variables */
4481 SCIP_COL** cols, /**< LP columns */
4482 int ncols, /**< number of columns */
4483 SCIP_Bool integral, /**< should integral strong branching be performed? */
4484 SCIP_SET* set, /**< global SCIP settings */
4485 SCIP_STAT* stat, /**< dynamic problem statistics */
4486 SCIP_PROB* prob, /**< problem data */
4487 SCIP_LP* lp, /**< LP data */
4488 int itlim, /**< iteration limit for strong branchings */
4489 SCIP_Real* down, /**< stores dual bounds after branching columns down */
4490 SCIP_Real* up, /**< stores dual bounds after branching columns up */
4491 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4492 * otherwise, they can only be used as an estimate value */
4493 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4494 * otherwise, they can only be used as an estimate value */
4495 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4496 )
4497{
4498 SCIP_RETCODE retcode;
4499 SCIP_Real* sbdown;
4500 SCIP_Real* sbup;
4501 SCIP_Bool* sbdownvalid;
4502 SCIP_Bool* sbupvalid;
4503 SCIP_Real* primsols;
4504 SCIP_COL** subcols;
4505 int* lpipos;
4506 int* subidx;
4507 int nsubcols;
4508 int iter;
4509 int j;
4510
4511 assert(cols != NULL);
4512 assert(set != NULL);
4513 assert(stat != NULL);
4514 assert(lp != NULL);
4515 assert(lp->flushed);
4516 assert(lp->solved);
4518 assert(lp->validsollp == stat->lpcount);
4519 assert(itlim >= 1);
4520 assert(down != NULL);
4521 assert(up != NULL);
4522 assert(lperror != NULL);
4523
4524 *lperror = FALSE;
4525
4526 if ( ncols <= 0 )
4527 return SCIP_OKAY;
4528
4529 /* start timing */
4531
4532 /* initialize storage */
4533 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4534 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4535 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4536 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4541
4542 nsubcols = 0;
4543 for( j = 0; j < ncols; ++j )
4544 {
4545 SCIP_COL* col;
4546 col = cols[j];
4547
4548 assert(col->lppos < lp->ncols);
4549 assert(lp->cols[col->lppos] == col);
4553 assert(SCIPvarGetCol(col->var) == col);
4554 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4555 assert(col->lpipos >= 0);
4556 assert(col->lppos >= 0);
4557
4558 col->validsblp = stat->nlps;
4559 col->sbsolval = col->primsol;
4560 col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4561 col->sbnode = stat->nnodes;
4563
4564 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4565 if( lp->looseobjvalinf > 0 )
4566 {
4567 /* directly set up column and result vectors*/
4568 col->sbdown = -SCIPsetInfinity(set);
4569 col->sbup = -SCIPsetInfinity(set);
4570 col->sbdownvalid = FALSE;
4571 col->sbupvalid = FALSE;
4572 down[j] = col->sbdown;
4573 up[j] = col->sbup;
4574 if( downvalid != NULL )
4575 downvalid[j] = col->sbdownvalid;
4576 if( upvalid != NULL )
4577 upvalid[j] = col->sbupvalid;
4578 }
4579 else
4580 {
4581 col->sbitlim = itlim;
4582 col->nsbcalls++;
4583
4584 lpipos[nsubcols] = col->lpipos;
4585 primsols[nsubcols] = col->primsol;
4586 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4587 subidx[nsubcols] = j;
4588 subcols[nsubcols++] = col;
4589 }
4590 }
4591
4592 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4593
4594 /* call LPI strong branching */
4595 if ( integral )
4596 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4597 else
4598 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4599
4600 /* check return code for errors */
4601 if( retcode == SCIP_LPERROR )
4602 {
4603 *lperror = TRUE;
4604
4605 for( j = 0; j < nsubcols; ++j )
4606 {
4607 SCIP_COL* col;
4608 int idx;
4609
4610 col = subcols[j];
4611 idx = subidx[j];
4612
4613 col->sbdown = SCIP_INVALID;
4614 col->sbup = SCIP_INVALID;
4615 col->sbdownvalid = FALSE;
4616 col->sbupvalid = FALSE;
4617 col->validsblp = -1;
4618 col->sbsolval = SCIP_INVALID;
4619 col->sblpobjval = SCIP_INVALID;
4620 col->sbnode = -1;
4621
4622 down[idx] = col->sbdown;
4623 up[idx] = col->sbup;
4624 if( downvalid != NULL )
4625 downvalid[idx] = col->sbdownvalid;
4626 if( upvalid != NULL )
4627 upvalid[idx] = col->sbupvalid;
4628 }
4629 }
4630 else
4631 {
4632 SCIP_Real looseobjval;
4633
4634 *lperror = FALSE;
4635 SCIP_CALL( retcode );
4636
4637 looseobjval = getFiniteLooseObjval(lp, set, prob);
4638
4639 for( j = 0; j < nsubcols; ++j )
4640 {
4641 SCIP_COL* col;
4642 int idx;
4643
4644 col = subcols[j];
4645 idx = subidx[j];
4646
4647 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/
4648 assert( col->sbup != SCIP_INVALID); /*lint !e777*/
4649
4650 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4651 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4652 col->sbdownvalid = sbdownvalid[j];
4653 col->sbupvalid = sbupvalid[j];
4654
4655 down[idx] = col->sbdown;
4656 up[idx] = col->sbup;
4657 if( downvalid != NULL )
4658 downvalid[idx] = col->sbdownvalid;
4659 if( upvalid != NULL )
4660 upvalid[idx] = col->sbupvalid;
4661 }
4662
4663 /* update strong branching statistics */
4664 if( iter == -1 )
4665 {
4666 /* calculate average iteration number */
4667 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4668 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4669 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4670 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4671 : 0;
4672 if( iter/2 >= itlim )
4673 iter = 2*itlim;
4674 }
4675 SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4676 SCIPstatAdd(stat, set, nsblpiterations, iter);
4677 if( stat->nnodes == 1 )
4678 {
4679 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4680 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4681 }
4682 }
4683
4684 SCIPsetFreeBufferArray(set, &sbupvalid);
4685 SCIPsetFreeBufferArray(set, &sbdownvalid);
4687 SCIPsetFreeBufferArray(set, &sbdown);
4688 SCIPsetFreeBufferArray(set, &primsols);
4689 SCIPsetFreeBufferArray(set, &lpipos);
4690 SCIPsetFreeBufferArray(set, &subidx);
4691 SCIPsetFreeBufferArray(set, &subcols);
4692
4693 /* stop timing */
4695
4696 return SCIP_OKAY;
4697}
4698
4699/** gets last strong branching information available for a column variable;
4700 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4701 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4702 */
4704 SCIP_COL* col, /**< LP column */
4705 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4706 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4707 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4708 * otherwise, it can only be used as an estimate value */
4709 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4710 * otherwise, it can only be used as an estimate value */
4711 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4712 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4713 )
4714{
4715 assert(col != NULL);
4716
4717 if( down != NULL )
4718 *down = col->sbdown;
4719 if( up != NULL )
4720 *up = col->sbup;
4721 if( downvalid != NULL )
4722 *downvalid = col->sbdownvalid;
4723 if( upvalid != NULL )
4724 *upvalid = col->sbupvalid;
4725 if( solval != NULL )
4726 *solval = col->sbsolval;
4727 if( lpobjval != NULL )
4728 *lpobjval = col->sblpobjval;
4729}
4730
4731/** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4732 * the LP where the strong branching on this column was applied;
4733 * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4734 */
4736 SCIP_COL* col, /**< LP column */
4737 SCIP_STAT* stat /**< dynamic problem statistics */
4738 )
4739{
4740 assert(col != NULL);
4741 assert(stat != NULL);
4742
4743 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4744}
4745
4746/** marks a column to be not removable from the LP in the current node because it became obsolete */
4748 SCIP_COL* col, /**< LP column */
4749 SCIP_STAT* stat /**< problem statistics */
4750 )
4751{
4752 assert(col != NULL);
4753 assert(stat != NULL);
4754 assert(stat->nnodes > 0);
4755
4756 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4757 col->obsoletenode = stat->nnodes;
4758}
4759
4760
4761/*
4762 * Row methods
4763 */
4764
4765/** calculates row norms and min/maxidx from scratch, and checks for sorting */
4766static
4768 SCIP_ROW* row, /**< LP row */
4769 SCIP_SET* set /**< global SCIP settings */
4770 )
4771{
4772 int i;
4773
4774 assert(row != NULL);
4775 assert(set != NULL);
4776
4777 row->sqrnorm = 0.0;
4778 row->sumnorm = 0.0;
4779 row->objprod = 0.0;
4780 row->maxval = 0.0;
4781 row->nummaxval = 1;
4782 row->minval = SCIPsetInfinity(set);
4783 row->numminval = 1;
4784 row->minidx = INT_MAX;
4785 row->maxidx = INT_MIN;
4786 row->validminmaxidx = TRUE;
4787 row->lpcolssorted = TRUE;
4788 row->nonlpcolssorted = TRUE;
4789
4790 /* check, if row is sorted
4791 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4792 */
4793 for( i = 0; i < row->nlpcols; ++i )
4794 {
4795 assert(row->cols[i] != NULL);
4796 assert(!SCIPsetIsZero(set, row->vals[i]));
4797 assert(row->cols[i]->lppos >= 0);
4798 assert(row->linkpos[i] >= 0);
4799 assert(row->cols[i]->index == row->cols_index[i]);
4800
4801 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4802 if( i > 0 )
4803 {
4804 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4805 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4806 }
4807 }
4808 for( i = row->nlpcols; i < row->len; ++i )
4809 {
4810 assert(row->cols[i] != NULL);
4811 assert(!SCIPsetIsZero(set, row->vals[i]));
4812 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4813 assert(row->cols[i]->index == row->cols_index[i]);
4814
4815 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4816 if( i > row->nlpcols )
4817 {
4818 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4819 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4820 }
4821 }
4822}
4823
4824/** calculates min/maxval and min/maxidx from scratch */
4825static
4827 SCIP_ROW* row, /**< LP row */
4828 SCIP_SET* set /**< global SCIP settings */
4829 )
4830{
4831 SCIP_COL* col;
4832 SCIP_Real absval;
4833 int i;
4834
4835 assert(row != NULL);
4836 assert(set != NULL);
4837
4838 row->maxval = 0.0;
4839 row->nummaxval = 1;
4840 row->numintcols = 0;
4841 row->minval = SCIPsetInfinity(set);
4842 row->numminval = 1;
4843 row->minidx = INT_MAX;
4844 row->maxidx = INT_MIN;
4845 row->validminmaxidx = TRUE;
4846
4847 /* calculate maxval, minval, minidx, and maxidx */
4848 for( i = 0; i < row->len; ++i )
4849 {
4850 col = row->cols[i];
4851 assert(col != NULL);
4852 assert(!SCIPsetIsZero(set, row->vals[i]));
4853
4854 absval = REALABS(row->vals[i]);
4855 assert(!SCIPsetIsZero(set, absval));
4856
4857 /* update min/maxidx */
4858 row->minidx = MIN(row->minidx, col->index);
4859 row->maxidx = MAX(row->maxidx, col->index);
4860 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4861
4862 /* update maximal and minimal non-zero value */
4863 if( row->nummaxval > 0 )
4864 {
4865 if( SCIPsetIsGT(set, absval, row->maxval) )
4866 {
4867 row->maxval = absval;
4868 row->nummaxval = 1;
4869 }
4870 else if( SCIPsetIsGE(set, absval, row->maxval) )
4871 {
4872 /* make sure the maxval is always exactly the same */
4873 row->maxval = MAX(absval, row->maxval);
4874 row->nummaxval++;
4875 }
4876 }
4877 if( row->numminval > 0 )
4878 {
4879 if( SCIPsetIsLT(set, absval, row->minval) )
4880 {
4881 row->minval = absval;
4882 row->numminval = 1;
4883 }
4884 else if( SCIPsetIsLE(set, absval, row->minval) )
4885 {
4886 /* make sure the minval is always exactly the same */
4887 row->minval = MIN(absval, row->minval);
4888 row->numminval++;
4889 }
4890 }
4891 }
4892}
4893
4894/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4895static
4897 SCIP_Real val, /**< value that should be scaled to an integral value */
4898 SCIP_Real scalar, /**< scalar that should be tried */
4899 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4900 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4901 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4902 )
4903{
4904 SCIP_Real sval;
4905 SCIP_Real downval;
4906 SCIP_Real upval;
4907
4908 assert(mindelta <= 0.0);
4909 assert(maxdelta >= 0.0);
4910
4911 sval = val * scalar;
4912 downval = floor(sval);
4913 upval = ceil(sval);
4914
4915 if( SCIPrelDiff(sval, downval) <= maxdelta )
4916 {
4917 if( intval != NULL )
4918 *intval = downval;
4919 return TRUE;
4920 }
4921 else if( SCIPrelDiff(sval, upval) >= mindelta )
4922 {
4923 if( intval != NULL )
4924 *intval = upval;
4925 return TRUE;
4926 }
4927
4928 return FALSE;
4929}
4930
4931/** scales row with given factor, and rounds coefficients to integers if close enough;
4932 * the constant is automatically moved to the sides;
4933 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4934 */
4935static
4937 SCIP_ROW* row, /**< LP row */
4938 BMS_BLKMEM* blkmem, /**< block memory */
4939 SCIP_SET* set, /**< global SCIP settings */
4940 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4941 SCIP_STAT* stat, /**< problem statistics */
4942 SCIP_LP* lp, /**< current LP data */
4943 SCIP_Real scaleval, /**< value to scale row with */
4944 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4945 * if they are close to integral values? */
4946 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4947 * upto which the integral is used instead of the scaled real coefficient */
4948 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4949 * upto which the integral is used instead of the scaled real coefficient */
4950 )
4951{
4952 SCIP_COL* col;
4953 SCIP_Real val;
4954 SCIP_Real newval;
4955 SCIP_Real intval;
4956 SCIP_Real mindelta;
4957 SCIP_Real maxdelta;
4958 SCIP_Real lb;
4959 SCIP_Real ub;
4960 SCIP_Bool mindeltainf;
4961 SCIP_Bool maxdeltainf;
4962 int oldlen;
4963 int c;
4964
4965 assert(row != NULL);
4966 assert(row->len == 0 || row->cols != NULL);
4967 assert(row->len == 0 || row->vals != NULL);
4968 assert(SCIPsetIsPositive(set, scaleval));
4969 assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4970 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4971
4972 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4973
4974 mindelta = 0.0;
4975 maxdelta = 0.0;
4976 mindeltainf = FALSE;
4977 maxdeltainf = FALSE;
4978 oldlen = row->len;
4979
4980 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4981 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4982 * this rounding can lead to
4983 */
4984 row->integral = TRUE;
4985
4986 c = 0;
4987 while( c < row->len )
4988 {
4989 col = row->cols[c];
4990 val = row->vals[c];
4991 assert(!SCIPsetIsZero(set, val));
4992
4993 /* get local or global bounds for column, depending on the local or global feasibility of the row */
4994 if( row->local )
4995 {
4996 lb = col->lb;
4997 ub = col->ub;
4998 }
4999 else
5000 {
5001 lb = SCIPvarGetLbGlobal(col->var);
5002 ub = SCIPvarGetUbGlobal(col->var);
5003 }
5004
5005 /* calculate scaled coefficient */
5006 newval = val * scaleval;
5007 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5008 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5009 {
5010 if( !SCIPsetIsEQ(set, intval, newval) )
5011 {
5012 if( intval < newval )
5013 {
5014 mindelta += (intval - newval)*ub;
5015 maxdelta += (intval - newval)*lb;
5016 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5017 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5018 }
5019 else
5020 {
5021 mindelta += (intval - newval)*lb;
5022 maxdelta += (intval - newval)*ub;
5023 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5024 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5025 }
5026 }
5027 newval = intval;
5028 }
5029
5030 if( !SCIPsetIsEQ(set, val, newval) )
5031 {
5032 /* if column knows of the row, change the corresponding coefficient in the column */
5033 if( row->linkpos[c] >= 0 )
5034 {
5035 assert(col->rows[row->linkpos[c]] == row);
5036 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5037 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5038 }
5039
5040 /* change the coefficient in the row, and update the norms and integrality status */
5041 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5042
5043 /* current coefficient has been deleted from the row because it was almost zero */
5044 if( oldlen != row->len )
5045 {
5046 assert(row->len == oldlen - 1);
5047 c--;
5048 oldlen = row->len;
5049 }
5050 }
5051 else
5052 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5053
5054 ++c;
5055 }
5056
5057 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5058 * to not destroy feasibility due to rounding
5059 */
5060 /**@todo ensure that returned cut does not have infinite lhs and rhs */
5061 if( !SCIPsetIsInfinity(set, -row->lhs) )
5062 {
5063 if( mindeltainf )
5064 newval = -SCIPsetInfinity(set);
5065 else
5066 {
5067 newval = (row->lhs - row->constant) * scaleval + mindelta;
5068 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5069 newval = SCIPsetSumCeil(set, newval);
5070 }
5071 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5072 }
5073 if( !SCIPsetIsInfinity(set, row->rhs) )
5074 {
5075 if( maxdeltainf )
5076 newval = SCIPsetInfinity(set);
5077 else
5078 {
5079 newval = (row->rhs - row->constant) * scaleval + maxdelta;
5080 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5081 newval = SCIPsetSumFloor(set, newval);
5082 }
5083 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5084 }
5085
5086 /* clear the row constant */
5087 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5088
5089 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5090 debugRowPrint(set, row);
5091
5092#ifdef SCIP_DEBUG
5093 /* check integrality status of row */
5094 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5095 {}
5096 assert(row->integral == (c == row->len));
5097#endif
5098
5099 /* invalid the activity */
5100 row->validactivitylp = -1;
5101
5102 return SCIP_OKAY;
5103}
5104
5105/** creates and captures an LP row */
5107 SCIP_ROW** row, /**< pointer to LP row data */
5108 BMS_BLKMEM* blkmem, /**< block memory */
5109 SCIP_SET* set, /**< global SCIP settings */
5110 SCIP_STAT* stat, /**< problem statistics */
5111 const char* name, /**< name of row */
5112 int len, /**< number of nonzeros in the row */
5113 SCIP_COL** cols, /**< array with columns of row entries */
5114 SCIP_Real* vals, /**< array with coefficients of row entries */
5115 SCIP_Real lhs, /**< left hand side of row */
5116 SCIP_Real rhs, /**< right hand side of row */
5117 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
5118 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5119 SCIP_Bool local, /**< is row only valid locally? */
5120 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
5121 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
5122 )
5123{
5124 assert(row != NULL);
5125 assert(blkmem != NULL);
5126 assert(stat != NULL);
5127 assert(len >= 0);
5128 assert(len == 0 || (cols != NULL && vals != NULL));
5129 /* note, that the assert tries to avoid numerical troubles in the LP solver.
5130 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5131 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5132 */
5133 assert(lhs <= rhs);
5134
5135 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5136
5137 (*row)->integral = TRUE;
5138 if( len > 0 )
5139 {
5140 SCIP_VAR* var;
5141 int i;
5142
5143 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5144 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5145 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5146 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5147
5148 for( i = 0; i < len; ++i )
5149 {
5150 assert(cols[i] != NULL);
5151 assert(!SCIPsetIsZero(set, vals[i]));
5152
5153 var = cols[i]->var;
5154 (*row)->cols_index[i] = cols[i]->index;
5155 (*row)->linkpos[i] = -1;
5156 if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5157 {
5158 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5159 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5160 }
5161 else
5162 {
5163 (*row)->integral = FALSE;
5164 }
5165 }
5166 }
5167 else
5168 {
5169 (*row)->cols = NULL;
5170 (*row)->cols_index = NULL;
5171 (*row)->vals = NULL;
5172 (*row)->linkpos = NULL;
5173 }
5174
5175 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5176 (*row)->constant = 0.0;
5177 (*row)->lhs = lhs;
5178 (*row)->rhs = rhs;
5179 (*row)->flushedlhs = -SCIPsetInfinity(set);
5180 (*row)->flushedrhs = SCIPsetInfinity(set);
5181 (*row)->sqrnorm = 0.0;
5182 (*row)->sumnorm = 0.0;
5183 (*row)->objprod = 0.0;
5184 (*row)->maxval = 0.0;
5185 (*row)->minval = SCIPsetInfinity(set);
5186 (*row)->dualsol = 0.0;
5187 (*row)->activity = SCIP_INVALID;
5188 (*row)->dualfarkas = 0.0;
5189 (*row)->pseudoactivity = SCIP_INVALID;
5190 (*row)->minactivity = SCIP_INVALID;
5191 (*row)->maxactivity = SCIP_INVALID;
5192 (*row)->origin = origin;
5193 (*row)->eventfilter = NULL;
5194 (*row)->index = stat->nrowidx;
5195 SCIPstatIncrement(stat, set, nrowidx);
5196 (*row)->size = len;
5197 (*row)->len = len;
5198 (*row)->nlpcols = 0;
5199 (*row)->nunlinked = len;
5200 (*row)->nuses = 0;
5201 (*row)->lppos = -1;
5202 (*row)->lpipos = -1;
5203 (*row)->lpdepth = -1;
5204 (*row)->minidx = INT_MAX;
5205 (*row)->maxidx = INT_MIN;
5206 (*row)->nummaxval = 0;
5207 (*row)->numminval = 0;
5208 (*row)->numintcols = -1;
5209 (*row)->validactivitylp = -1;
5210 (*row)->validpsactivitydomchg = -1;
5211 (*row)->validactivitybdsdomchg = -1;
5212 (*row)->nlpsaftercreation = 0L;
5213 (*row)->activeinlpcounter = 0L;
5214 (*row)->age = 0;
5215 (*row)->rank = 0;
5216 (*row)->obsoletenode = -1;
5217 (*row)->fromcutpool = FALSE;
5218 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5219 (*row)->lpcolssorted = TRUE;
5220 (*row)->nonlpcolssorted = (len <= 1);
5221 (*row)->delaysort = FALSE;
5222 (*row)->validminmaxidx = FALSE;
5223 (*row)->lhschanged = FALSE;
5224 (*row)->rhschanged = FALSE;
5225 (*row)->coefchanged = FALSE;
5226 (*row)->local = local;
5227 (*row)->modifiable = modifiable;
5228 (*row)->nlocks = 0;
5229 (*row)->origintype = origintype; /*lint !e641*/
5230 (*row)->removable = removable;
5231 (*row)->inglobalcutpool = FALSE;
5232 (*row)->storedsolvals = NULL;
5233
5234 /* calculate row norms and min/maxidx, and check if row is sorted */
5235 rowCalcNorms(*row, set);
5236
5237 /* capture the row */
5238 SCIProwCapture(*row);
5239
5240 /* create event filter */
5241 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5242
5243 /* capture origin constraint if available */
5244 if( origintype == SCIP_ROWORIGINTYPE_CONS )
5245 {
5246 SCIP_CONS* cons = (SCIP_CONS*) origin;
5247 assert(cons != NULL);
5248 SCIPconsCapture(cons);
5249 }
5250
5251 return SCIP_OKAY;
5252} /*lint !e715*/
5253
5254/** frees an LP row */
5256 SCIP_ROW** row, /**< pointer to LP row */
5257 BMS_BLKMEM* blkmem, /**< block memory */
5258 SCIP_SET* set, /**< global SCIP settings */
5259 SCIP_LP* lp /**< current LP data */
5260 )
5261{
5262 assert(blkmem != NULL);
5263 assert(row != NULL);
5264 assert(*row != NULL);
5265 assert((*row)->nuses == 0);
5266 assert((*row)->lppos == -1);
5267 assert((*row)->eventfilter != NULL);
5268
5269 /* release constraint that has been used for creating the row */
5270 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5271 {
5272 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5273 assert(cons != NULL);
5274 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5275 }
5276
5277 /* remove column indices from corresponding rows */
5278 SCIP_CALL( rowUnlink(*row, set, lp) );
5279
5280 /* free event filter */
5281 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5282
5283 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5284 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5285 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5286 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5287 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5288 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5289 BMSfreeBlockMemory(blkmem, row);
5290
5291 return SCIP_OKAY;
5292}
5293
5294/** output row to file stream */
5296 SCIP_ROW* row, /**< LP row */
5297 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5298 FILE* file /**< output file (or NULL for standard output) */
5299 )
5300{
5301 int i;
5302
5303 assert(row != NULL);
5304
5305 /* print row name */
5306 if( row->name != NULL && row->name[0] != '\0' )
5307 {
5308 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5309 }
5310
5311 /* print left hand side */
5312 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5313
5314 /* print coefficients */
5315 if( row->len == 0 )
5316 SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5317 for( i = 0; i < row->len; ++i )
5318 {
5319 assert(row->cols[i] != NULL);
5320 assert(row->cols[i]->var != NULL);
5321 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5323 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5324 }
5325
5326 /* print constant */
5328 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5329
5330 /* print right hand side */
5331 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5332}
5333
5334/** increases usage counter of LP row */
5336 SCIP_ROW* row /**< LP row */
5337 )
5338{
5339 assert(row != NULL);
5340 assert(row->nuses >= 0);
5341 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5342
5343 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5344 row->nuses++;
5345}
5346
5347/** decreases usage counter of LP row, and frees memory if necessary */
5349 SCIP_ROW** row, /**< pointer to LP row */
5350 BMS_BLKMEM* blkmem, /**< block memory */
5351 SCIP_SET* set, /**< global SCIP settings */
5352 SCIP_LP* lp /**< current LP data */
5353 )
5354{
5355 assert(blkmem != NULL);
5356 assert(row != NULL);
5357 assert(*row != NULL);
5358 assert((*row)->nuses >= 1);
5359 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5360
5361 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5362 (*row)->nuses--;
5363 if( (*row)->nuses == 0 )
5364 {
5365 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5366 }
5367
5368 *row = NULL;
5369
5370 return SCIP_OKAY;
5371}
5372
5373/** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5375 SCIP_ROW* row /**< LP row */
5376 )
5377{
5378 assert(row != NULL);
5379
5380 /* check, if row is modifiable */
5381 if( !row->modifiable )
5382 {
5383 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5384 row->nlocks++;
5385 }
5386}
5387
5388/** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5390 SCIP_ROW* row /**< LP row */
5391 )
5392{
5393 assert(row != NULL);
5394
5395 /* check, if row is modifiable */
5396 if( !row->modifiable )
5397 {
5398 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5399 assert(row->nlocks > 0);
5400 row->nlocks--;
5401 }
5402}
5403
5404/** adds a previously non existing coefficient to an LP row */
5406 SCIP_ROW* row, /**< LP row */
5407 BMS_BLKMEM* blkmem, /**< block memory */
5408 SCIP_SET* set, /**< global SCIP settings */
5409 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5410 SCIP_LP* lp, /**< current LP data */
5411 SCIP_COL* col, /**< LP column */
5412 SCIP_Real val /**< value of coefficient */
5413 )
5414{
5415 assert(lp != NULL);
5416 assert(!lp->diving || row->lppos == -1);
5417
5418 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5419
5420 checkLinks(lp);
5421
5422 return SCIP_OKAY;
5423}
5424
5425/** deletes coefficient from row */
5427 SCIP_ROW* row, /**< row to be changed */
5428 BMS_BLKMEM* blkmem, /**< block memory */
5429 SCIP_SET* set, /**< global SCIP settings */
5430 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5431 SCIP_LP* lp, /**< current LP data */
5432 SCIP_COL* col /**< coefficient to be deleted */
5433 )
5434{
5435 int pos;
5436
5437 assert(row != NULL);
5438 assert(!row->delaysort);
5439 assert(lp != NULL);
5440 assert(!lp->diving || row->lppos == -1);
5441 assert(col != NULL);
5442 assert(col->var != NULL);
5443
5444 /* search the position of the column in the row's col vector */
5445 pos = rowSearchCoef(row, col);
5446 if( pos == -1 )
5447 {
5448 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5449 return SCIP_INVALIDDATA;
5450 }
5451 assert(0 <= pos && pos < row->len);
5452 assert(row->cols[pos] == col);
5453 assert(row->cols_index[pos] == col->index);
5454
5455 /* if column knows of the row, remove the row from the column's row vector */
5456 if( row->linkpos[pos] >= 0 )
5457 {
5458 assert(col->rows[row->linkpos[pos]] == row);
5459 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5460 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5461 }
5462
5463 /* delete the column from the row's col vector */
5464 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5465
5466 checkLinks(lp);
5467
5468 return SCIP_OKAY;
5469}
5470
5471/** changes or adds a coefficient to an LP row */
5473 SCIP_ROW* row, /**< LP row */
5474 BMS_BLKMEM* blkmem, /**< block memory */
5475 SCIP_SET* set, /**< global SCIP settings */
5476 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5477 SCIP_LP* lp, /**< current LP data */
5478 SCIP_COL* col, /**< LP column */
5479 SCIP_Real val /**< value of coefficient */
5480 )
5481{
5482 int pos;
5483
5484 assert(row != NULL);
5485 assert(!row->delaysort);
5486 assert(lp != NULL);
5487 assert(!lp->diving || row->lppos == -1);
5488 assert(col != NULL);
5489
5490 /* search the position of the column in the row's col vector */
5491 pos = rowSearchCoef(row, col);
5492
5493 /* check, if column already exists in the row's col vector */
5494 if( pos == -1 )
5495 {
5496 /* add previously not existing coefficient */
5497 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5498 }
5499 else
5500 {
5501 /* modify already existing coefficient */
5502 assert(0 <= pos && pos < row->len);
5503 assert(row->cols[pos] == col);
5504 assert(row->cols_index[pos] == col->index);
5505
5506 /* if column knows of the row, change the corresponding coefficient in the column */
5507 if( row->linkpos[pos] >= 0 )
5508 {
5509 assert(col->rows[row->linkpos[pos]] == row);
5510 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5511 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5512 }
5513
5514 /* change the coefficient in the row */
5515 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5516 }
5517
5518 checkLinks(lp);
5519
5520 return SCIP_OKAY;
5521}
5522
5523/** increases value of an existing or non-existing coefficient in an LP row */
5525 SCIP_ROW* row, /**< LP row */
5526 BMS_BLKMEM* blkmem, /**< block memory */
5527 SCIP_SET* set, /**< global SCIP settings */
5528 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5529 SCIP_LP* lp, /**< current LP data */
5530 SCIP_COL* col, /**< LP column */
5531 SCIP_Real incval /**< value to add to the coefficient */
5532 )
5533{
5534 int pos;
5535
5536 assert(row != NULL);
5537 assert(lp != NULL);
5538 assert(!lp->diving || row->lppos == -1);
5539 assert(col != NULL);
5540
5541 if( SCIPsetIsZero(set, incval) )
5542 return SCIP_OKAY;
5543
5544 /* search the position of the column in the row's col vector */
5545 pos = rowSearchCoef(row, col);
5546
5547 /* check, if column already exists in the row's col vector */
5548 if( pos == -1 )
5549 {
5550 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5551 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5552 }
5553 else
5554 {
5555 /* modify already existing coefficient */
5556 assert(0 <= pos && pos < row->len);
5557 assert(row->cols[pos] == col);
5558 assert(row->cols_index[pos] == col->index);
5559
5560 /* if column knows of the row, change the corresponding coefficient in the column */
5561 if( row->linkpos[pos] >= 0 )
5562 {
5563 assert(col->rows[row->linkpos[pos]] == row);
5564 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5565 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5566 }
5567
5568 /* change the coefficient in the row */
5569 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5570 }
5571
5572 checkLinks(lp);
5573
5574 /* invalid the activity */
5575 row->validactivitylp = -1;
5576
5577 return SCIP_OKAY;
5578}
5579
5580/** changes constant value of a row */
5582 SCIP_ROW* row, /**< LP row */
5583 BMS_BLKMEM* blkmem, /**< block memory */
5584 SCIP_SET* set, /**< global SCIP settings */
5585 SCIP_STAT* stat, /**< problem statistics */
5586 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5587 SCIP_LP* lp, /**< current LP data */
5588 SCIP_Real constant /**< new constant value */
5589 )
5590{
5591 assert(row != NULL);
5592 assert(row->lhs <= row->rhs);
5593 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5594 assert(stat != NULL);
5595 assert(lp != NULL);
5596 assert(!lp->diving || row->lppos == -1);
5597
5598 if( !SCIPsetIsEQ(set, constant, row->constant) )
5599 {
5600 SCIP_Real oldconstant;
5601
5602 if( row->validpsactivitydomchg == stat->domchgcount )
5603 {
5604 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
5605 row->pseudoactivity += constant - row->constant;
5606 }
5607 if( row->validactivitybdsdomchg == stat->domchgcount )
5608 {
5609 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
5610 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
5611 row->minactivity += constant - row->constant;
5612 row->maxactivity += constant - row->constant;
5613 }
5614
5615 if( !SCIPsetIsInfinity(set, -row->lhs) )
5616 {
5618 }
5619 if( !SCIPsetIsInfinity(set, row->rhs) )
5620 {
5622 }
5623
5624 oldconstant = row->constant;
5625
5626 row->constant = constant;
5627
5628 /* issue row constant changed event */
5629 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5630 }
5631
5632 return SCIP_OKAY;
5633}
5634
5635/** add constant value to a row */
5637 SCIP_ROW* row, /**< LP row */
5638 BMS_BLKMEM* blkmem, /**< block memory */
5639 SCIP_SET* set, /**< global SCIP settings */
5640 SCIP_STAT* stat, /**< problem statistics */
5641 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5642 SCIP_LP* lp, /**< current LP data */
5643 SCIP_Real addval /**< constant value to add to the row */
5644 )
5645{
5646 assert(row != NULL);
5647 assert(row->lhs <= row->rhs);
5648 assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5649 assert(stat != NULL);
5650 assert(lp != NULL);
5651 assert(!lp->diving || row->lppos == -1);
5652
5653 if( !SCIPsetIsZero(set, addval) )
5654 {
5655 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5656 }
5657
5658 return SCIP_OKAY;
5659}
5660
5661/** changes left hand side of LP row */
5663 SCIP_ROW* row, /**< LP row */
5664 BMS_BLKMEM* blkmem, /**< block memory */
5665 SCIP_SET* set, /**< global SCIP settings */
5666 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5667 SCIP_LP* lp, /**< current LP data */
5668 SCIP_Real lhs /**< new left hand side */
5669 )
5670{
5671 assert(row != NULL);
5672 assert(lp != NULL);
5673
5674 if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5675 {
5676 SCIP_Real oldlhs;
5677
5678 oldlhs = row->lhs;
5679
5680 row->lhs = lhs;
5682
5683 if( !lp->diving )
5684 {
5685 /* issue row side changed event */
5686 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5687 }
5688 }
5689
5690 return SCIP_OKAY;
5691}
5692
5693/** changes right hand side of LP row */
5695 SCIP_ROW* row, /**< LP row */
5696 BMS_BLKMEM* blkmem, /**< block memory */
5697 SCIP_SET* set, /**< global SCIP settings */
5698 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5699 SCIP_LP* lp, /**< current LP data */
5700 SCIP_Real rhs /**< new right hand side */
5701 )
5702{
5703 assert(row != NULL);
5704 assert(lp != NULL);
5705
5706 if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5707 {
5708 SCIP_Real oldrhs;
5709
5710 oldrhs = row->rhs;
5711
5712 row->rhs = rhs;
5714
5715 if( !lp->diving )
5716 {
5717 /* issue row side changed event */
5718 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5719 }
5720 }
5721
5722 return SCIP_OKAY;
5723}
5724
5725/** changes the local flag of LP row */
5727 SCIP_ROW* row, /**< LP row */
5728 SCIP_Bool local /**< new value for local flag */
5729 )
5730{
5731 assert(row != NULL);
5732
5733 row->local = local;
5734
5735 return SCIP_OKAY;
5736}
5737
5738/** additional scalars that are tried in integrality scaling */
5739static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5740static const int nscalars = 9;
5741
5742/** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5744 SCIP_ROW* row, /**< LP row */
5745 SCIP_SET* set, /**< global SCIP settings */
5746 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5747 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5748 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5749 SCIP_Real maxscale, /**< maximal allowed scalar */
5750 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5751 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5752 SCIP_Bool* success /**< stores whether returned value is valid */
5753 )
5754{
5755#ifndef NDEBUG
5756 SCIP_COL* col;
5757#endif
5758 SCIP_Longint gcd;
5759 SCIP_Longint scm;
5760 SCIP_Longint numerator;
5761 SCIP_Longint denominator;
5762 SCIP_Real val;
5763 SCIP_Real absval;
5764 SCIP_Real minval;
5765 SCIP_Real scaleval;
5766 SCIP_Real twomultval;
5767 SCIP_Bool scalable;
5768 SCIP_Bool twomult;
5769 SCIP_Bool rational;
5770 int c;
5771 int s;
5772
5773 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5774 assert(row != NULL);
5775 assert(row->len == 0 || row->cols != NULL);
5776 assert(row->len == 0 || row->cols_index != NULL);
5777 assert(row->len == 0 || row->vals != NULL);
5778 assert(maxdnom >= 1);
5779 assert(mindelta < 0.0);
5780 assert(maxdelta > 0.0);
5781 assert(success != NULL);
5782
5783 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5784 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5785
5786 if( intscalar != NULL )
5787 *intscalar = SCIP_INVALID;
5788 *success = FALSE;
5789
5790 /* get minimal absolute non-zero value */
5791 minval = SCIP_REAL_MAX;
5792 for( c = 0; c < row->len; ++c )
5793 {
5794#ifndef NDEBUG
5795 col = row->cols[c];
5796 assert(col != NULL);
5797 assert(col->var != NULL);
5799 assert(SCIPvarGetCol(col->var) == col);
5800#endif
5801 val = row->vals[c];
5802 assert(!SCIPsetIsZero(set, val));
5803
5804 if( val < mindelta || val > maxdelta )
5805 {
5806 absval = REALABS(val);
5807 minval = MIN(minval, absval);
5808 }
5809 }
5810 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5811 {
5812 /* all coefficients are zero (inside tolerances) */
5813 if( intscalar != NULL )
5814 *intscalar = 1.0;
5815 *success = TRUE;
5816 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5817
5818 return SCIP_OKAY;
5819 }
5820 assert(minval > MIN(-mindelta, maxdelta));
5821 assert(SCIPsetIsPositive(set, minval));
5822 assert(!SCIPsetIsInfinity(set, minval));
5823
5824 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5825 * and a power of 2
5826 */
5827 scaleval = 1.0/minval;
5828 scalable = (scaleval <= maxscale);
5829 for( c = 0; c < row->len && scalable; ++c )
5830 {
5831 /* don't look at continuous variables, if we don't have to */
5832 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5833 continue;
5834
5835 /* check, if the coefficient can be scaled with a simple scalar */
5836 val = row->vals[c];
5837 absval = REALABS(val);
5838 while( scaleval <= maxscale
5839 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5840 {
5841 for( s = 0; s < nscalars; ++s )
5842 {
5843 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5844 {
5845 scaleval *= scalars[s];
5846 break;
5847 }
5848 }
5849 if( s >= nscalars )
5850 scaleval *= 2.0;
5851 }
5852 scalable = (scaleval <= maxscale);
5853 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5854 }
5855 if( scalable )
5856 {
5857 /* make row coefficients integral by dividing them by the smallest coefficient
5858 * (and multiplying them with a power of 2)
5859 */
5860 assert(scaleval <= maxscale);
5861 if( intscalar != NULL )
5862 *intscalar = scaleval;
5863 *success = TRUE;
5864 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5865
5866 return SCIP_OKAY;
5867 }
5868
5869 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5870 twomultval = 1.0;
5871 twomult = (twomultval <= maxscale);
5872 for( c = 0; c < row->len && twomult; ++c )
5873 {
5874 /* don't look at continuous variables, if we don't have to */
5875 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5876 continue;
5877
5878 /* check, if the coefficient can be scaled with a simple scalar */
5879 val = row->vals[c];
5880 absval = REALABS(val);
5881 while( twomultval <= maxscale
5882 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5883 {
5884 for( s = 0; s < nscalars; ++s )
5885 {
5886 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5887 {
5888 twomultval *= scalars[s];
5889 break;
5890 }
5891 }
5892 if( s >= nscalars )
5893 twomultval *= 2.0;
5894 }
5895 twomult = (twomultval <= maxscale);
5896 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5897 val, twomultval, val*twomultval, twomult);
5898 }
5899 if( twomult )
5900 {
5901 /* make row coefficients integral by multiplying them with a power of 2 */
5902 assert(twomultval <= maxscale);
5903 if( intscalar != NULL )
5904 *intscalar = twomultval;
5905 *success = TRUE;
5906 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5907
5908 return SCIP_OKAY;
5909 }
5910
5911 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5912 * and the smallest common multiple of the denominators
5913 */
5914 gcd = 1;
5915 scm = 1;
5916 rational = (maxdnom > 1);
5917
5918 /* first coefficient (to initialize gcd) */
5919 for( c = 0; c < row->len && rational; ++c )
5920 {
5921 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5922 {
5923 val = row->vals[c];
5924 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
5925 if( rational && numerator != 0 )
5926 {
5927 assert(denominator > 0);
5928 gcd = ABS(numerator);
5929 scm = denominator;
5930 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5931 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5932 val, numerator, denominator, gcd, scm, rational);
5933 break;
5934 }
5935 }
5936 }
5937
5938 /* remaining coefficients */
5939 for( ++c; c < row->len && rational; ++c )
5940 {
5941 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5942 {
5943 val = row->vals[c];
5944 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
5945 if( rational && numerator != 0 )
5946 {
5947 assert(denominator > 0);
5948 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
5949 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5950 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5951 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5952 val, numerator, denominator, gcd, scm, rational);
5953 }
5954 }
5955 }
5956
5957 if( rational )
5958 {
5959 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5960 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5961 if( intscalar != NULL )
5962 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5963 *success = TRUE;
5964 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5965 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5966 }
5967 else
5968 {
5969 assert(!(*success));
5970 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5971 }
5972
5973 return SCIP_OKAY;
5974}
5975
5976/** tries to scale row, s.t. all coefficients become integral */
5978 SCIP_ROW* row, /**< LP row */
5979 BMS_BLKMEM* blkmem, /**< block memory */
5980 SCIP_SET* set, /**< global SCIP settings */
5981 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5982 SCIP_STAT* stat, /**< problem statistics */
5983 SCIP_LP* lp, /**< current LP data */
5984 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5985 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5986 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5987 SCIP_Real maxscale, /**< maximal value to scale row with */
5988 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5989 SCIP_Bool* success /**< stores whether row could be made rational */
5990 )
5991{
5992 SCIP_Real intscalar;
5993
5994 assert(success != NULL);
5995
5996 /* calculate scalar to make coefficients integral */
5997 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
5998 &intscalar, success) );
5999
6000 if( *success )
6001 {
6002 /* scale the row */
6003 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6004 }
6005
6006 return SCIP_OKAY;
6007}
6008
6009/** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6010 * higher ones
6011 */
6013 SCIP_ROW* row /**< row to be sorted */
6014 )
6015{
6016 assert(row != NULL);
6017
6018 /* sort LP columns */
6019 rowSortLP(row);
6020
6021 /* sort non-LP columns */
6022 rowSortNonLP(row);
6023
6024#ifdef SCIP_MORE_DEBUG
6025 /* check the sorting */
6026 {
6027 int c;
6028 if( !row->delaysort )
6029 {
6030 for( c = 1; c < row->nlpcols; ++c )
6031 assert(row->cols[c]->index >= row->cols[c-1]->index);
6032 for( c = row->nlpcols + 1; c < row->len; ++c )
6033 assert(row->cols[c]->index >= row->cols[c-1]->index);
6034 }
6035 }
6036#endif
6037}
6038
6039/** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6040 * zero entries from row
6041 * the row must not be linked to the columns; otherwise, we would need to update the columns as
6042 * well, which is too expensive
6043 */
6044static
6046 SCIP_ROW* row, /**< row to be sorted */
6047 SCIP_SET* set /**< global SCIP settings */
6048 )
6049{
6050 assert(row != NULL);
6051 assert(!row->delaysort);
6052 assert(row->nunlinked == row->len);
6053 assert(row->nlpcols == 0);
6054
6055 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6056
6057 /* do nothing on empty rows; if row is sorted, nothing has to be done */
6058 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6059 {
6060 SCIP_COL** cols;
6061 int* cols_index;
6062 SCIP_Real* vals;
6063 int s;
6064 int t;
6065
6066 /* make sure, the row is sorted */
6067 SCIProwSort(row);
6068 assert(row->lpcolssorted);
6069 assert(row->nonlpcolssorted);
6070
6071 /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6072 cols = row->cols;
6073 cols_index = row->cols_index;
6074 vals = row->vals;
6075 assert(cols != NULL);
6076 assert(cols_index != NULL);
6077 assert(vals != NULL);
6078
6079 t = 0;
6080 row->integral = TRUE;
6081 assert(!SCIPsetIsZero(set, vals[0]));
6082 assert(row->linkpos[0] == -1);
6083
6084 for( s = 1; s < row->len; ++s )
6085 {
6086 assert(!SCIPsetIsZero(set, vals[s]));
6087 assert(row->linkpos[s] == -1);
6088
6089 if( cols[s] == cols[t] )
6090 {
6091 /* merge entries with equal column */
6092 vals[t] += vals[s];
6093 }
6094 else
6095 {
6096 /* go to the next entry, overwriting current entry if coefficient is zero */
6097 if( !SCIPsetIsZero(set, vals[t]) )
6098 {
6099 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6100 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6101
6102 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6103 t++;
6104 }
6105 cols[t] = cols[s];
6106 cols_index[t] = cols_index[s];
6107 vals[t] = vals[s];
6108 }
6109 }
6110 if( !SCIPsetIsZero(set, vals[t]) )
6111 {
6112 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6113 t++;
6114 }
6115 assert(s == row->len);
6116 assert(t <= row->len);
6117
6118 row->len = t;
6119 row->nunlinked = t;
6120
6121 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6122 if( t < s )
6123 rowCalcNorms(row, set);
6124 }
6125
6126#ifndef NDEBUG
6127 /* check for double entries */
6128 {
6129 int i;
6130 int j;
6131
6132 for( i = 0; i < row->len; ++i )
6133 {
6134 assert(row->cols[i] != NULL);
6135 assert(row->cols[i]->index == row->cols_index[i]);
6136 for( j = i+1; j < row->len; ++j )
6137 assert(row->cols[i] != row->cols[j]);
6138 }
6139 }
6140#endif
6141}
6142
6143/** enables delaying of row sorting */
6145 SCIP_ROW* row /**< LP row */
6146 )
6147{
6148 assert(row != NULL);
6149 assert(!row->delaysort);
6150
6151 row->delaysort = TRUE;
6152}
6153
6154/** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6156 SCIP_ROW* row, /**< LP row */
6157 SCIP_SET* set /**< global SCIP settings */
6158 )
6159{
6160 assert(row != NULL);
6161 assert(row->delaysort);
6162
6163 row->delaysort = FALSE;
6164 rowMerge(row, set);
6165}
6166
6167/** recalculates the current activity of a row */
6169 SCIP_ROW* row, /**< LP row */
6170 SCIP_STAT* stat /**< problem statistics */
6171 )
6172{
6173 SCIP_COL* col;
6174 int c;
6175
6176 assert(row != NULL);
6177 assert(stat != NULL);
6178
6179 row->activity = row->constant;
6180 for( c = 0; c < row->nlpcols; ++c )
6181 {
6182 col = row->cols[c];
6183 assert(col != NULL);
6184 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
6185 assert(col->lppos >= 0);
6186 assert(row->linkpos[c] >= 0);
6187 row->activity += row->vals[c] * col->primsol;
6188 }
6189
6190 if( row->nunlinked > 0 )
6191 {
6192 for( c = row->nlpcols; c < row->len; ++c )
6193 {
6194 col = row->cols[c];
6195 assert(col != NULL);
6196 assert(col->lppos >= 0 || col->primsol == 0.0);
6197 assert(col->lppos == -1 || row->linkpos[c] == -1);
6198 if( col->lppos >= 0 )
6199 row->activity += row->vals[c] * col->primsol;
6200 }
6201 }
6202#ifndef NDEBUG
6203 else
6204 {
6205 for( c = row->nlpcols; c < row->len; ++c )
6206 {
6207 col = row->cols[c];
6208 assert(col != NULL);
6209 assert(col->primsol == 0.0);
6210 assert(col->lppos == -1);
6211 assert(row->linkpos[c] >= 0);
6212 }
6213 }
6214#endif
6215
6216 row->validactivitylp = stat->lpcount;
6217}
6218
6219/** returns the activity of a row in the current LP solution */
6221 SCIP_ROW* row, /**< LP row */
6222 SCIP_SET* set, /**< global SCIP settings */
6223 SCIP_STAT* stat, /**< problem statistics */
6224 SCIP_LP* lp /**< current LP data */
6225 )
6226{
6227 SCIP_Real inf;
6228 SCIP_Real activity;
6229
6230 assert(row != NULL);
6231 assert(stat != NULL);
6232 assert(lp != NULL);
6233 assert(row->validactivitylp <= stat->lpcount);
6234 assert(lp->validsollp == stat->lpcount);
6235
6236 if( row->validactivitylp != stat->lpcount )
6237 SCIProwRecalcLPActivity(row, stat);
6238 assert(row->validactivitylp == stat->lpcount);
6239 assert(row->activity != SCIP_INVALID); /*lint !e777*/
6240
6241 activity = row->activity;
6242 inf = SCIPsetInfinity(set);
6243 activity = MAX(activity, -inf);
6244 activity = MIN(activity, +inf);
6245
6246 return activity;
6247}
6248
6249/** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6251 SCIP_ROW* row, /**< LP row */
6252 SCIP_SET* set, /**< global SCIP settings */
6253 SCIP_STAT* stat, /**< problem statistics */
6254 SCIP_LP* lp /**< current LP data */
6255 )
6256{
6257 SCIP_Real activity;
6258
6259 assert(row != NULL);
6260
6261 activity = SCIProwGetLPActivity(row, set, stat, lp);
6262
6263 return MIN(row->rhs - activity, activity - row->lhs);
6264}
6265
6266/** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6267 *
6268 * @todo Implement calculation of activities similar to LPs.
6269 */
6271 SCIP_ROW* row, /**< LP row */
6272 SCIP_SET* set, /**< global SCIP settings */
6273 SCIP_STAT* stat /**< problem statistics */
6274 )
6275{
6276 SCIP_Real inf;
6277 SCIP_Real activity;
6278 SCIP_COL* col;
6279 int c;
6280
6281 assert( row != NULL );
6282 assert( stat != NULL );
6283
6284 activity = row->constant;
6285 for (c = 0; c < row->nlpcols; ++c)
6286 {
6287 col = row->cols[c];
6288 assert( col != NULL );
6289 assert( col->lppos >= 0 );
6290 assert( col->var != NULL );
6291 assert( row->linkpos[c] >= 0 );
6292 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6293 }
6294
6295 if ( row->nunlinked > 0 )
6296 {
6297 for (c = row->nlpcols; c < row->len; ++c)
6298 {
6299 col = row->cols[c];
6300 assert( col != NULL );
6301 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6302 if ( col->lppos >= 0 )
6303 {
6304 assert( col->var != NULL );
6305 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6306 }
6307 }
6308 }
6309#ifndef NDEBUG
6310 else
6311 {
6312 for (c = row->nlpcols; c < row->len; ++c)
6313 {
6314 col = row->cols[c];
6315 assert( col != NULL );
6316 assert( col->lppos == -1 );
6317 assert( row->linkpos[c] >= 0 );
6318 }
6319 }
6320#endif
6321 inf = SCIPsetInfinity(set);
6322 activity = MAX(activity, -inf);
6323 activity = MIN(activity, +inf);
6324
6325 return MIN(row->rhs - activity, activity - row->lhs);
6326}
6327
6328/** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6329 *
6330 * @todo Implement calculation of activities similar to LPs.
6331 */
6333 SCIP_ROW* row, /**< LP row */
6334 SCIP_SET* set, /**< global SCIP settings */
6335 SCIP_STAT* stat /**< problem statistics */
6336 )
6337{
6338 SCIP_Real inf;
6339 SCIP_Real activity;
6340 SCIP_COL* col;
6341 int c;
6342
6343 assert( row != NULL );
6344 assert( stat != NULL );
6345
6346 activity = row->constant;
6347 for (c = 0; c < row->nlpcols; ++c)
6348 {
6349 col = row->cols[c];
6350 assert( col != NULL );
6351 assert( col->lppos >= 0 );
6352 assert( col->var != NULL );
6353 assert( row->linkpos[c] >= 0 );
6354 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6355 }
6356
6357 if ( row->nunlinked > 0 )
6358 {
6359 for (c = row->nlpcols; c < row->len; ++c)
6360 {
6361 col = row->cols[c];
6362 assert( col != NULL );
6363 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6364 if ( col->lppos >= 0 )
6365 {
6366 assert( col->var != NULL );
6367 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6368 }
6369 }
6370 }
6371#ifndef NDEBUG
6372 else
6373 {
6374 for (c = row->nlpcols; c < row->len; ++c)
6375 {
6376 col = row->cols[c];
6377 assert( col != NULL );
6378 assert( col->lppos == -1 );
6379 assert( row->linkpos[c] >= 0 );
6380 }
6381 }
6382#endif
6383 inf = SCIPsetInfinity(set);
6384 activity = MAX(activity, -inf);
6385 activity = MIN(activity, +inf);
6386
6387 return MIN(row->rhs - activity, activity - row->lhs);
6388}
6389
6390/** calculates the current pseudo activity of a row */
6392 SCIP_ROW* row, /**< row data */
6393 SCIP_STAT* stat /**< problem statistics */
6394 )
6395{
6396 SCIP_COL* col;
6397 int i;
6398
6399 assert(row != NULL);
6400 assert(stat != NULL);
6401
6402 row->pseudoactivity = row->constant;
6403 for( i = 0; i < row->len; ++i )
6404 {
6405 col = row->cols[i];
6406 assert(col != NULL);
6407 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6408 assert(col->var != NULL);
6410
6411 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6412 }
6415}
6416
6417/** returns the pseudo activity of a row in the current pseudo solution */
6419 SCIP_ROW* row, /**< LP row */
6420 SCIP_SET* set, /**< global SCIP settings */
6421 SCIP_STAT* stat /**< problem statistics */
6422 )
6423{
6424 SCIP_Real inf;
6425 SCIP_Real activity;
6426
6427 assert(row != NULL);
6428 assert(stat != NULL);
6430
6431 /* check, if pseudo activity has to be calculated */
6432 if( row->validpsactivitydomchg != stat->domchgcount )
6433 SCIProwRecalcPseudoActivity(row, stat);
6435 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
6436
6437 activity = row->pseudoactivity;
6438 inf = SCIPsetInfinity(set);
6439 activity = MAX(activity, -inf);
6440 activity = MIN(activity, +inf);
6441
6442 return activity;
6443}
6444
6445/** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6447 SCIP_ROW* row, /**< LP row */
6448 SCIP_SET* set, /**< global SCIP settings */
6449 SCIP_STAT* stat /**< problem statistics */
6450 )
6451{
6452 SCIP_Real pseudoactivity;
6453
6454 assert(row != NULL);
6455
6456 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6457
6458 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6459}
6460
6461/** returns the activity of a row for a given solution */
6463 SCIP_ROW* row, /**< LP row */
6464 SCIP_SET* set, /**< global SCIP settings */
6465 SCIP_STAT* stat, /**< problem statistics data */
6466 SCIP_SOL* sol /**< primal CIP solution */
6467 )
6468{
6469 SCIP_COL* col;
6470 SCIP_Real inf;
6471 SCIP_Real activity;
6472 SCIP_Real solval;
6473 int i;
6474
6475 assert(row != NULL);
6476
6477 activity = row->constant;
6478 for( i = 0; i < row->len; ++i )
6479 {
6480 col = row->cols[i];
6481 assert(col != NULL);
6482 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6483 solval = SCIPsolGetVal(sol, set, stat, col->var);
6484 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6485 {
6486 if( SCIPsetIsInfinity(set, -row->lhs) )
6487 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6488 else if( SCIPsetIsInfinity(set, row->rhs) )
6489 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6490 else
6491 solval = (col->lb + col->ub)/2.0;
6492 }
6493 activity += row->vals[i] * solval;
6494 }
6495
6496 inf = SCIPsetInfinity(set);
6497 activity = MAX(activity, -inf);
6498 activity = MIN(activity, +inf);
6499
6500 return activity;
6501}
6502
6503/** returns the feasibility of a row for the given solution */
6505 SCIP_ROW* row, /**< LP row */
6506 SCIP_SET* set, /**< global SCIP settings */
6507 SCIP_STAT* stat, /**< problem statistics data */
6508 SCIP_SOL* sol /**< primal CIP solution */
6509 )
6510{
6511 SCIP_Real activity;
6512
6513 assert(row != NULL);
6514
6515 activity = SCIProwGetSolActivity(row, set, stat, sol);
6516
6517 return MIN(row->rhs - activity, activity - row->lhs);
6518}
6519
6520/** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6521static
6523 SCIP_ROW* row, /**< row data */
6524 SCIP_SET* set, /**< global SCIP settings */
6525 SCIP_STAT* stat /**< problem statistics data */
6526 )
6527{
6528 SCIP_COL* col;
6529 SCIP_Real val;
6530 SCIP_Bool mininfinite;
6531 SCIP_Bool maxinfinite;
6532 int i;
6533
6534 assert(row != NULL);
6536 assert(stat != NULL);
6537
6538 /* calculate activity bounds */
6539 mininfinite = FALSE;
6540 maxinfinite = FALSE;
6541 row->minactivity = row->constant;
6542 row->maxactivity = row->constant;
6543 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6544 {
6545 col = row->cols[i];
6546 assert(col != NULL);
6547 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6548 val = row->vals[i];
6549 if( val >= 0.0 )
6550 {
6551 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6552 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6553 if( !mininfinite )
6554 row->minactivity += val * col->lb;
6555 if( !maxinfinite )
6556 row->maxactivity += val * col->ub;
6557 }
6558 else
6559 {
6560 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6561 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6562 if( !mininfinite )
6563 row->minactivity += val * col->ub;
6564 if( !maxinfinite )
6565 row->maxactivity += val * col->lb;
6566 }
6567 }
6568
6569 if( mininfinite )
6571 if( maxinfinite )
6574
6575#ifndef NDEBUG
6576 {
6577 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6578
6579 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6580 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6581 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6582 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6583 * tolerance as a proxy to account for the accumulation effect
6584 */
6585 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6586 || EPSISINT(row->minactivity - row->constant, inttol));
6587 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6588 || EPSISINT(row->maxactivity - row->constant, inttol));
6589 }
6590#endif
6591}
6592
6593/** returns the minimal activity of a row w.r.t. the columns' bounds */
6595 SCIP_ROW* row, /**< LP row */
6596 SCIP_SET* set, /**< global SCIP settings */
6597 SCIP_STAT* stat /**< problem statistics data */
6598 )
6599{
6600 assert(row != NULL);
6601 assert(stat != NULL);
6603
6604 /* check, if activity bounds has to be calculated */
6605 if( row->validactivitybdsdomchg != stat->domchgcount )
6606 rowCalcActivityBounds(row, set, stat);
6608 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6609 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6610
6611 return row->minactivity;
6612}
6613
6614/** returns the maximal activity of a row w.r.t. the columns' bounds */
6616 SCIP_ROW* row, /**< LP row */
6617 SCIP_SET* set, /**< global SCIP settings */
6618 SCIP_STAT* stat /**< problem statistics data */
6619 )
6620{
6621 assert(row != NULL);
6622 assert(stat != NULL);
6624
6625 /* check, if activity bounds has to be calculated */
6626 if( row->validactivitybdsdomchg != stat->domchgcount )
6627 rowCalcActivityBounds(row, set, stat);
6629 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6630 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6631
6632 return row->maxactivity;
6633}
6634
6635/** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6637 SCIP_ROW* row, /**< LP row */
6638 SCIP_SET* set, /**< global SCIP settings */
6639 SCIP_STAT* stat /**< problem statistics data */
6640 )
6641{
6642 assert(row != NULL);
6643
6644 if( row->modifiable )
6645 return FALSE;
6646 if( !SCIPsetIsInfinity(set, -row->lhs) )
6647 {
6648 SCIP_Real minactivity;
6649
6650 minactivity = SCIProwGetMinActivity(row, set, stat);
6651 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6652 return FALSE;
6653 }
6654 if( !SCIPsetIsInfinity(set, row->rhs) )
6655 {
6656 SCIP_Real maxactivity;
6657
6658 maxactivity = SCIProwGetMaxActivity(row, set, stat);
6659 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6660 return FALSE;
6661 }
6662
6663 return TRUE;
6664}
6665
6666/** gets maximal absolute value of row vector coefficients */
6668 SCIP_ROW* row, /**< LP row */
6669 SCIP_SET* set /**< global SCIP settings */
6670 )
6671{
6672 assert(row != NULL);
6673
6674 if( row->nummaxval == 0 )
6675 rowCalcIdxsAndVals(row, set);
6676 assert(row->nummaxval > 0);
6677 assert(row->maxval >= 0.0 || row->len == 0);
6678
6679 return row->maxval;
6680}
6681
6682/** gets minimal absolute value of row vector's non-zero coefficients */
6684 SCIP_ROW* row, /**< LP row */
6685 SCIP_SET* set /**< global SCIP settings */
6686 )
6687{
6688 assert(row != NULL);
6689
6690 if( row->numminval == 0 )
6691 rowCalcIdxsAndVals(row, set);
6692 assert(row->numminval > 0);
6693 assert(row->minval >= 0.0 || row->len == 0);
6694
6695 return row->minval;
6696}
6697
6698/** gets maximal column index of row entries */
6700 SCIP_ROW* row, /**< LP row */
6701 SCIP_SET* set /**< global SCIP settings */
6702 )
6703{
6704 assert(row != NULL);
6705
6706 if( row->validminmaxidx == 0 )
6707 rowCalcIdxsAndVals(row, set);
6708 assert(row->maxidx >= 0 || row->len == 0);
6709 assert(row->validminmaxidx);
6710
6711 return row->maxidx;
6712}
6713
6714/** gets minimal column index of row entries */
6716 SCIP_ROW* row, /**< LP row */
6717 SCIP_SET* set /**< global SCIP settings */
6718 )
6719{
6720 assert(row != NULL);
6721
6722 if( row->validminmaxidx == 0 )
6723 rowCalcIdxsAndVals(row, set);
6724 assert(row->minidx >= 0 || row->len == 0);
6725 assert(row->validminmaxidx);
6726
6727 return row->minidx;
6728}
6729
6730/** gets number of integral columns in row */
6732 SCIP_ROW* row, /**< LP row */
6733 SCIP_SET* set /**< global SCIP settings */
6734 )
6735{
6736 assert(row != NULL);
6737
6738 if( row->numintcols == -1 )
6739 rowCalcIdxsAndVals(row, set);
6740
6741 assert(row->numintcols <= row->len && row->numintcols >= 0);
6742
6743 return row->numintcols;
6744}
6745
6746/** returns row's cutoff distance in the direction of the given primal solution */
6748 SCIP_ROW* row, /**< LP row */
6749 SCIP_SET* set, /**< global SCIP settings */
6750 SCIP_STAT* stat, /**< problem statistics data */
6751 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
6752 SCIP_LP* lp /**< current LP data */
6753 )
6754{
6755 SCIP_Real solcutoffdist;
6756 int k;
6757
6758 assert(sol != NULL);
6759
6760 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6761 {
6762 SCIP_Real scale = 0.0;
6763
6764 lp->validsoldirlp = stat->lpcount;
6765 lp->validsoldirsol = sol;
6766
6768
6769 for( k = 0; k < lp->ncols; ++k )
6770 {
6771 assert(lp->cols[k]->lppos == k);
6772 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6773 scale += SQR(lp->soldirection[k]);
6774 }
6775
6776 if( scale > 0.0 )
6777 {
6778 scale = 1.0 / sqrt(scale);
6779
6780 for( k = 0; k < lp->ncols; ++k )
6781 lp->soldirection[k] *= scale;
6782 }
6783 }
6784
6785 solcutoffdist = 0.0;
6786 for( k = 0; k < row->nlpcols; ++k )
6787 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6788
6789 for( k = row->nlpcols; k < row->len; ++k )
6790 {
6791 if( row->cols[k]->lppos >= 0 )
6792 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6793 }
6794
6795 if( SCIPsetIsSumZero(set, solcutoffdist) )
6796 solcutoffdist = set->num_sumepsilon;
6797
6798 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6799
6800 return solcutoffdist;
6801}
6802
6803/** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6805 SCIP_ROW* row, /**< LP row */
6806 SCIP_SET* set, /**< global SCIP settings */
6807 SCIP_STAT* stat, /**< problem statistics data */
6808 SCIP_LP* lp /**< current LP data */
6809 )
6810{
6811 SCIP_Real norm;
6812 SCIP_Real feasibility;
6813 SCIP_Real eps;
6814
6815 assert(set != NULL);
6816
6817 switch( set->sepa_efficacynorm )
6818 {
6819 case 'e':
6820 norm = SCIProwGetNorm(row);
6821 break;
6822 case 'm':
6823 norm = SCIProwGetMaxval(row, set);
6824 break;
6825 case 's':
6826 norm = SCIProwGetSumNorm(row);
6827 break;
6828 case 'd':
6829 norm = (row->len == 0 ? 0.0 : 1.0);
6830 break;
6831 default:
6832 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6833 SCIPABORT();
6834 norm = 0.0; /*lint !e527*/
6835 }
6836
6838 norm = MAX(norm, eps);
6839 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6840
6841 return -feasibility / norm;
6842}
6843
6844/** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6846 SCIP_ROW* row, /**< LP row */
6847 SCIP_SET* set, /**< global SCIP settings */
6848 SCIP_STAT* stat, /**< problem statistics data */
6849 SCIP_LP* lp, /**< current LP data */
6850 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6851 )
6852{
6853 SCIP_Real efficacy;
6854
6855 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6856
6857 return SCIPsetIsEfficacious(set, root, efficacy);
6858}
6859
6860/** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6862 SCIP_ROW* row, /**< LP row */
6863 SCIP_SET* set, /**< global SCIP settings */
6864 SCIP_STAT* stat, /**< problem statistics data */
6865 SCIP_SOL* sol /**< primal CIP solution */
6866 )
6867{
6868 SCIP_Real norm;
6869 SCIP_Real feasibility;
6870 SCIP_Real eps;
6871
6872 assert(set != NULL);
6873
6874 switch( set->sepa_efficacynorm )
6875 {
6876 case 'e':
6877 norm = SCIProwGetNorm(row);
6878 break;
6879 case 'm':
6880 norm = SCIProwGetMaxval(row, set);
6881 break;
6882 case 's':
6883 norm = SCIProwGetSumNorm(row);
6884 break;
6885 case 'd':
6886 norm = (row->len == 0 ? 0.0 : 1.0);
6887 break;
6888 default:
6889 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6890 SCIPABORT();
6891 norm = 0.0; /*lint !e527*/
6892 }
6893
6895 norm = MAX(norm, eps);
6896 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6897
6898 return -feasibility / norm;
6899}
6900
6901/** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6902 * efficacy
6903 */
6905 SCIP_ROW* row, /**< LP row */
6906 SCIP_SET* set, /**< global SCIP settings */
6907 SCIP_STAT* stat, /**< problem statistics data */
6908 SCIP_SOL* sol, /**< primal CIP solution */
6909 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6910 )
6911{
6912 SCIP_Real efficacy;
6913
6914 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6915
6916 return SCIPsetIsEfficacious(set, root, efficacy);
6917}
6918
6919/** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6921 SCIP_ROW* row, /**< LP row */
6922 SCIP_SET* set, /**< global SCIP settings */
6923 SCIP_STAT* stat /**< problem statistics data */
6924 )
6925{
6926 SCIP_Real norm;
6927 SCIP_Real feasibility;
6928 SCIP_Real eps;
6929
6930 assert(set != NULL);
6931
6932 switch( set->sepa_efficacynorm )
6933 {
6934 case 'e':
6935 norm = SCIProwGetNorm(row);
6936 break;
6937 case 'm':
6938 norm = SCIProwGetMaxval(row, set);
6939 break;
6940 case 's':
6941 norm = SCIProwGetSumNorm(row);
6942 break;
6943 case 'd':
6944 norm = (row->len == 0 ? 0.0 : 1.0);
6945 break;
6946 default:
6947 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6948 SCIPABORT();
6949 norm = 0.0; /*lint !e527*/
6950 }
6951
6953 norm = MAX(norm, eps);
6954 feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6955
6956 return -feasibility / norm;
6957}
6958
6959/** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6961 SCIP_ROW* row, /**< LP row */
6962 SCIP_SET* set, /**< global SCIP settings */
6963 SCIP_STAT* stat /**< problem statistics data */
6964 )
6965{
6966 SCIP_Real norm;
6967 SCIP_Real feasibility;
6968 SCIP_Real eps;
6969
6970 assert(set != NULL);
6971
6972 switch( set->sepa_efficacynorm )
6973 {
6974 case 'e':
6975 norm = SCIProwGetNorm(row);
6976 break;
6977 case 'm':
6978 norm = SCIProwGetMaxval(row, set);
6979 break;
6980 case 's':
6981 norm = SCIProwGetSumNorm(row);
6982 break;
6983 case 'd':
6984 norm = (row->len == 0 ? 0.0 : 1.0);
6985 break;
6986 default:
6987 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6988 SCIPABORT();
6989 norm = 0.0; /*lint !e527*/
6990 }
6991
6993 norm = MAX(norm, eps);
6994 feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6995
6996 return -feasibility / norm;
6997}
6998
6999/** returns the scalar product of the coefficient vectors of the two given rows
7000 *
7001 * @note the scalar product is computed w.r.t. the current LP columns only
7002 * @todo also consider non-LP columns for the computation?
7003 */
7005 SCIP_ROW* row1, /**< first LP row */
7006 SCIP_ROW* row2 /**< second LP row */
7007 )
7008{
7009 SCIP_Real scalarprod;
7010 int* row1colsidx;
7011 int* row2colsidx;
7012 int i1;
7013 int i2;
7014
7015 assert(row1 != NULL);
7016 assert(row2 != NULL);
7017
7018 /* Sort the column indices of both rows.
7019 *
7020 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7021 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7022 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7023 * for both or one of the non-LP columns for both.
7024 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7025 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7026 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7027 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7028 *
7029 * We distinguish the following cases:
7030 *
7031 * 1) both rows have no unlinked columns
7032 * -> we just check the LP partitions
7033 *
7034 * 2) exactly one row is completely unlinked, the other one is completely linked
7035 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7036 * (thus all common LP columns are regarded)
7037 *
7038 * 3) we have unlinked and LP columns in both rows
7039 * -> we need to compare four partitions at once
7040 *
7041 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7042 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7043 * other row
7044 *
7045 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7046 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7047 *
7048 * 5) both rows are completely unlinked
7049 * -> we need to compare two partitions: both complete rows
7050 */
7051 SCIProwSort(row1);
7052 assert(row1->lpcolssorted);
7053 assert(row1->nonlpcolssorted);
7054 SCIProwSort(row2);
7055 assert(row2->lpcolssorted);
7056 assert(row2->nonlpcolssorted);
7057
7058 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7059 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7060
7061 row1colsidx = row1->cols_index;
7062 row2colsidx = row2->cols_index;
7063
7064#ifndef NDEBUG
7065 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7066 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7067 {
7068 i1 = 0;
7069 i2 = row2->nlpcols;
7070 while( i1 < row1->nlpcols && i2 < row2->len )
7071 {
7072 assert(row1->cols[i1] != row2->cols[i2]);
7073 if( row1->cols[i1]->index < row2->cols[i2]->index )
7074 ++i1;
7075 else
7076 {
7077 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7078 ++i2;
7079 }
7080 }
7081 assert(i1 == row1->nlpcols || i2 == row2->len);
7082
7083 i1 = row1->nlpcols;
7084 i2 = 0;
7085 while( i1 < row1->len && i2 < row2->nlpcols )
7086 {
7087 assert(row1->cols[i1] != row2->cols[i2]);
7088 if( row1->cols[i1]->index < row2->cols[i2]->index )
7089 ++i1;
7090 else
7091 {
7092 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7093 ++i2;
7094 }
7095 }
7096 assert(i1 == row1->len || i2 == row2->nlpcols);
7097 }
7098#endif
7099
7100 /* The "easy" cases 1) and 2) */
7101 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7102 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7103 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7104 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7105 {
7106 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7107 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7108
7109 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7110 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7111 */
7112 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7113 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7114 scalarprod = 0.0;
7115
7116 /* calculate the scalar product */
7117 while( i1 >= 0 && i2 >= 0 )
7118 {
7119 assert(row1->cols[i1]->index == row1colsidx[i1]);
7120 assert(row2->cols[i2]->index == row2colsidx[i2]);
7121 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7122 if( row1colsidx[i1] < row2colsidx[i2] )
7123 --i2;
7124 else if( row1colsidx[i1] > row2colsidx[i2] )
7125 --i1;
7126 else
7127 {
7128 scalarprod += row1->vals[i1] * row2->vals[i2];
7129 --i1;
7130 --i2;
7131 }
7132 }
7133 }
7134 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7135 else
7136 {
7137 SCIP_Bool lpcols;
7138 int ilp1;
7139 int inlp1;
7140 int ilp2;
7141 int inlp2;
7142 int end1;
7143 int end2;
7144
7145 scalarprod = 0;
7146 ilp1 = 0;
7147 ilp2 = 0;
7148
7149 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7150 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7151 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7152
7153 /* handle the case of four partitions (case 3) until one partition is finished;
7154 * cases 4a), 4b), and 5) will fail the while-condition
7155 */
7156 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7157 {
7158 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7159 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7160 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7161 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7162 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7163 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7164 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7165 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7166
7167 /* rows have the same linked LP columns */
7168 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7169 {
7170 scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7171 ++ilp1;
7172 ++ilp2;
7173 }
7174 /* LP column of row1 is the same as unlinked column of row2 */
7175 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7176 {
7177 scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7178 ++ilp1;
7179 ++inlp2;
7180 }
7181 /* unlinked column of row1 is the same as LP column of row2 */
7182 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7183 {
7184 scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7185 ++inlp1;
7186 ++ilp2;
7187 }
7188 /* two unlinked LP columns are the same */
7189 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7190 {
7191 scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7192 ++inlp1;
7193 ++inlp2;
7194 }
7195 /* increase smallest counter */
7196 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7197 {
7198 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7199 {
7200 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7201 ++ilp1;
7202 else
7203 ++ilp2;
7204 }
7205 else
7206 {
7207 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7208 ++ilp1;
7209 else
7210 ++inlp2;
7211 }
7212 }
7213 else
7214 {
7215 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7216 {
7217 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7218 ++inlp1;
7219 else
7220 ++ilp2;
7221 }
7222 else
7223 {
7224 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7225 ++inlp1;
7226 else
7227 ++inlp2;
7228 }
7229 }
7230 }
7231
7232 /* One partition was completely handled, we just have to handle the three remaining partitions:
7233 * the remaining partition of this row and the two partitions of the other row.
7234 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7235 */
7236 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7237 {
7238 int tmpilp;
7239 int tmpinlp;
7240
7241 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7242
7243 SCIPswapPointers((void**) &row1, (void**) &row2);
7244 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7245 tmpilp = ilp1;
7246 tmpinlp = inlp1;
7247 ilp1 = ilp2;
7248 inlp1 = inlp2;
7249 ilp2 = tmpilp;
7250 inlp2 = tmpinlp;
7251 }
7252
7253 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7254 * -> this merges cases 4a) and 4b)
7255 */
7256 if( ilp1 == row1->nlpcols )
7257 {
7258 i1 = inlp1;
7259 end1 = row1->len;
7260 lpcols = FALSE;
7261 }
7262 else
7263 {
7264 assert(inlp1 == row1->len);
7265
7266 i1 = ilp1;
7267 end1 = row1->nlpcols;
7268 lpcols = TRUE;
7269 }
7270
7271 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7272 * case 5) will fail the while-condition
7273 */
7274 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7275 {
7276 assert(row1->cols[i1]->index == row1colsidx[i1]);
7277 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7278 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7279 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7280 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7281
7282 /* current column in row 1 is the same as the current LP column in row 2 */
7283 if( row1colsidx[i1] == row2colsidx[ilp2] )
7284 {
7285 scalarprod += row1->vals[i1] * row2->vals[ilp2];
7286 ++i1;
7287 ++ilp2;
7288 }
7289 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7290 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7291 {
7292 scalarprod += row1->vals[i1] * row2->vals[inlp2];
7293 ++i1;
7294 ++inlp2;
7295 }
7296 /* increase smallest counter */
7297 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7298 {
7299 if( row1colsidx[i1] < row2colsidx[ilp2] )
7300 ++i1;
7301 else
7302 ++ilp2;
7303 }
7304 else
7305 {
7306 if( row1colsidx[i1] < row2colsidx[inlp2] )
7307 ++i1;
7308 else
7309 ++inlp2;
7310 }
7311 }
7312
7313 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7314 * the two rows
7315 */
7316 if( i1 < end1 )
7317 {
7318 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7319 if( ilp2 == row2->nlpcols )
7320 {
7321 i2 = inlp2;
7322 end2 = row2->len;
7323 lpcols = FALSE;
7324 }
7325 else
7326 {
7327 assert(inlp2 == row2->len);
7328
7329 i2 = ilp2;
7330 end2 = row2->nlpcols;
7331 }
7332
7333 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7334 while( i1 < end1 && i2 < end2 )
7335 {
7336 assert(row1->cols[i1]->index == row1colsidx[i1]);
7337 assert(row2->cols[i2]->index == row2colsidx[i2]);
7338 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7339
7340 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7341 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7342 {
7343 scalarprod += row1->vals[i1] * row2->vals[i2];
7344 ++i1;
7345 ++i2;
7346 }
7347 /* increase smallest counter */
7348 else if( row1colsidx[i1] < row2colsidx[i2] )
7349 ++i1;
7350 else
7351 ++i2;
7352 }
7353 }
7354 }
7355
7356 return scalarprod;
7357}
7358
7359/** returns the discrete scalar product of the coefficient vectors of the two given rows */
7360static
7362 SCIP_ROW* row1, /**< first LP row */
7363 SCIP_ROW* row2 /**< second LP row */
7364 )
7365{
7366 int prod;
7367 int* row1colsidx;
7368 int* row2colsidx;
7369 int i1;
7370 int i2;
7371
7372 assert(row1 != NULL);
7373 assert(row2 != NULL);
7374
7375 /* Sort the column indices of both rows.
7376 *
7377 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7378 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7379 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7380 * for both or one of the non-LP columns for both.
7381 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7382 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7383 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7384 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7385 *
7386 * We distinguish the following cases:
7387 *
7388 * 1) both rows have no unlinked columns
7389 * -> we just check the LP partitions
7390 *
7391 * 2) exactly one row is completely unlinked, the other one is completely linked
7392 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7393 * (thus all common LP columns are regarded)
7394 *
7395 * 3) we have unlinked and LP columns in both rows
7396 * -> we need to compare four partitions at once
7397 *
7398 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7399 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7400 * other row
7401 *
7402 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7403 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7404 *
7405 * 5) both rows are completely unlinked
7406 * -> we need to compare two partitions: both complete rows
7407 */
7408 SCIProwSort(row1);
7409 assert(row1->lpcolssorted);
7410 assert(row1->nonlpcolssorted);
7411 SCIProwSort(row2);
7412 assert(row2->lpcolssorted);
7413 assert(row2->nonlpcolssorted);
7414
7415 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7416 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7417
7418 row1colsidx = row1->cols_index;
7419 row2colsidx = row2->cols_index;
7420
7421#ifndef NDEBUG
7422 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7423 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7424 {
7425 i1 = 0;
7426 i2 = row2->nlpcols;
7427 while( i1 < row1->nlpcols && i2 < row2->len )
7428 {
7429 assert(row1->cols[i1] != row2->cols[i2]);
7430 if( row1->cols[i1]->index < row2->cols[i2]->index )
7431 ++i1;
7432 else
7433 {
7434 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7435 ++i2;
7436 }
7437 }
7438 assert(i1 == row1->nlpcols || i2 == row2->len);
7439
7440 i1 = row1->nlpcols;
7441 i2 = 0;
7442 while( i1 < row1->len && i2 < row2->nlpcols )
7443 {
7444 assert(row1->cols[i1] != row2->cols[i2]);
7445 if( row1->cols[i1]->index < row2->cols[i2]->index )
7446 ++i1;
7447 else
7448 {
7449 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7450 ++i2;
7451 }
7452 }
7453 assert(i1 == row1->len || i2 == row2->nlpcols);
7454 }
7455#endif
7456
7457 /* The "easy" cases 1) and 2) */
7458 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7459 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7460 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7461 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7462 {
7463 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7464 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7465
7466 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7467 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7468 */
7469 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7470 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7471 prod = 0;
7472
7473 /* calculate the scalar product */
7474 while( i1 >= 0 && i2 >= 0 )
7475 {
7476 assert(row1->cols[i1]->index == row1colsidx[i1]);
7477 assert(row2->cols[i2]->index == row2colsidx[i2]);
7478 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7479 if( row1colsidx[i1] < row2colsidx[i2] )
7480 --i2;
7481 else if( row1colsidx[i1] > row2colsidx[i2] )
7482 --i1;
7483 else
7484 {
7485 ++prod;
7486 --i1;
7487 --i2;
7488 }
7489 }
7490 }
7491 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7492 else
7493 {
7494 SCIP_Bool lpcols;
7495 int ilp1;
7496 int inlp1;
7497 int ilp2;
7498 int inlp2;
7499 int end1;
7500 int end2;
7501
7502 prod = 0;
7503 ilp1 = 0;
7504 ilp2 = 0;
7505
7506 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7507 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7508 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7509
7510 /* handle the case of four partitions (case 3) until one partition is finished;
7511 * cases 4a), 4b), and 5) will fail the while-condition
7512 */
7513 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7514 {
7515 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7516 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7517 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7518 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7519 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7520 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7521 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7522 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7523
7524 /* rows have the same linked LP columns */
7525 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7526 {
7527 ++prod;
7528 ++ilp1;
7529 ++ilp2;
7530 }
7531 /* LP column of row1 is the same as unlinked column of row2 */
7532 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7533 {
7534 ++prod;
7535 ++ilp1;
7536 ++inlp2;
7537 }
7538 /* unlinked column of row1 is the same as LP column of row2 */
7539 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7540 {
7541 ++prod;
7542 ++inlp1;
7543 ++ilp2;
7544 }
7545 /* two unlinked LP columns are the same */
7546 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7547 {
7548 ++prod;
7549 ++inlp1;
7550 ++inlp2;
7551 }
7552 /* increase smallest counter */
7553 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7554 {
7555 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7556 {
7557 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7558 ++ilp1;
7559 else
7560 ++ilp2;
7561 }
7562 else
7563 {
7564 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7565 ++ilp1;
7566 else
7567 ++inlp2;
7568 }
7569 }
7570 else
7571 {
7572 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7573 {
7574 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7575 ++inlp1;
7576 else
7577 ++ilp2;
7578 }
7579 else
7580 {
7581 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7582 ++inlp1;
7583 else
7584 ++inlp2;
7585 }
7586 }
7587 }
7588
7589 /* One partition was completely handled, we just have to handle the three remaining partitions:
7590 * the remaining partition of this row and the two partitions of the other row.
7591 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7592 */
7593 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7594 {
7595 int tmpilp;
7596 int tmpinlp;
7597
7598 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7599
7600 SCIPswapPointers((void**) &row1, (void**) &row2);
7601 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7602 tmpilp = ilp1;
7603 tmpinlp = inlp1;
7604 ilp1 = ilp2;
7605 inlp1 = inlp2;
7606 ilp2 = tmpilp;
7607 inlp2 = tmpinlp;
7608 }
7609
7610 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7611 * -> this merges cases 4a) and 4b)
7612 */
7613 if( ilp1 == row1->nlpcols )
7614 {
7615 i1 = inlp1;
7616 end1 = row1->len;
7617 lpcols = FALSE;
7618 }
7619 else
7620 {
7621 assert(inlp1 == row1->len);
7622
7623 i1 = ilp1;
7624 end1 = row1->nlpcols;
7625 lpcols = TRUE;
7626 }
7627
7628 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7629 * case 5) will fail the while-condition
7630 */
7631 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7632 {
7633 assert(row1->cols[i1]->index == row1colsidx[i1]);
7634 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7635 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7636 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7637 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7638
7639 /* current column in row 1 is the same as the current LP column in row 2 */
7640 if( row1colsidx[i1] == row2colsidx[ilp2] )
7641 {
7642 ++prod;
7643 ++i1;
7644 ++ilp2;
7645 }
7646 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7647 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7648 {
7649 ++prod;
7650 ++i1;
7651 ++inlp2;
7652 }
7653 /* increase smallest counter */
7654 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7655 {
7656 if( row1colsidx[i1] < row2colsidx[ilp2] )
7657 ++i1;
7658 else
7659 ++ilp2;
7660 }
7661 else
7662 {
7663 if( row1colsidx[i1] < row2colsidx[inlp2] )
7664 ++i1;
7665 else
7666 ++inlp2;
7667 }
7668 }
7669
7670 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7671 * the two rows
7672 */
7673 if( i1 < end1 )
7674 {
7675 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7676 if( ilp2 == row2->nlpcols )
7677 {
7678 i2 = inlp2;
7679 end2 = row2->len;
7680 lpcols = FALSE;
7681 }
7682 else
7683 {
7684 assert(inlp2 == row2->len);
7685
7686 i2 = ilp2;
7687 end2 = row2->nlpcols;
7688 }
7689
7690 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7691 while( i1 < end1 && i2 < end2 )
7692 {
7693 assert(row1->cols[i1]->index == row1colsidx[i1]);
7694 assert(row2->cols[i2]->index == row2colsidx[i2]);
7695 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7696
7697 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7698 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7699 {
7700 ++prod;
7701 ++i1;
7702 ++i2;
7703 }
7704 /* increase smallest counter */
7705 else if( row1colsidx[i1] < row2colsidx[i2] )
7706 ++i1;
7707 else
7708 ++i2;
7709 }
7710 }
7711 }
7712
7713 return prod;
7714}
7715
7716/** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7717 * p = |v*w|/(|v|*|w|);
7718 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7719 */
7721 SCIP_ROW* row1, /**< first LP row */
7722 SCIP_ROW* row2, /**< second LP row */
7723 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7724 )
7725{
7726 SCIP_Real parallelism;
7727 SCIP_Real scalarprod;
7728
7729 switch( orthofunc )
7730 {
7731 case 'e':
7732 scalarprod = SCIProwGetScalarProduct(row1, row2);
7733 if( scalarprod == 0.0 )
7734 {
7735 parallelism = 0.0;
7736 break;
7737 }
7738
7739 if( SCIProwGetNorm(row1) == 0.0 )
7740 {
7741 /* In theory, this should not happen if the scalarproduct is not zero
7742 * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7743 * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7744 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7745 */
7746 int i;
7747 for( i = 0; i < row1->len; ++i )
7748 if( row1->cols[i]->lppos >= 0 )
7749 row1->sqrnorm += SQR(row1->vals[i]);
7750 assert(SCIProwGetNorm(row1) != 0.0);
7751 }
7752
7753 if( SCIProwGetNorm(row2) == 0.0 )
7754 {
7755 /* same as for row1 above: reeval norms if it is 0, which is wrong */
7756 int i;
7757 for( i = 0; i < row2->len; ++i )
7758 if( row2->cols[i]->lppos >= 0 )
7759 row2->sqrnorm += SQR(row2->vals[i]);
7760 assert(SCIProwGetNorm(row2) != 0.0);
7761 }
7762
7763 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7764 break;
7765
7766 case 'd':
7767 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7768 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7769 break;
7770
7771 default:
7772 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7773 SCIPABORT();
7774 parallelism = 0.0; /*lint !e527*/
7775 }
7776
7777 return parallelism;
7778}
7779
7780/** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7781 * o = 1 - |v*w|/(|v|*|w|);
7782 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7783 */
7785 SCIP_ROW* row1, /**< first LP row */
7786 SCIP_ROW* row2, /**< second LP row */
7787 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7788 )
7789{
7790 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7791}
7792
7793/** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7794 * function, if the value is 0, it is orthogonal to the objective function
7795 */
7797 SCIP_ROW* row, /**< LP row */
7798 SCIP_SET* set, /**< global SCIP settings */
7799 SCIP_LP* lp /**< current LP data */
7800 )
7801{
7802 SCIP_Real prod;
7803 SCIP_Real parallelism;
7804
7805 assert(row != NULL);
7806 assert(lp != NULL);
7807
7808 if( lp->objsqrnormunreliable )
7810
7812 assert(lp->objsqrnorm >= 0.0);
7813
7814 checkRowSqrnorm(row);
7815 checkRowObjprod(row);
7816
7817 prod = row->sqrnorm * lp->objsqrnorm;
7818
7819 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / sqrt(prod) : 0.0;
7820 assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7821 assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7822 parallelism = MIN(parallelism, 1.0);
7823 parallelism = MAX(parallelism, 0.0);
7824
7825 return parallelism;
7826}
7827
7828/** includes event handler with given data in row's event filter */
7830 SCIP_ROW* row, /**< row */
7831 BMS_BLKMEM* blkmem, /**< block memory */
7832 SCIP_SET* set, /**< global SCIP settings */
7833 SCIP_EVENTTYPE eventtype, /**< event type to catch */
7834 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7835 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7836 int* filterpos /**< pointer to store position of event filter entry, or NULL */
7837 )
7838{
7839 assert(row != NULL);
7840 assert(row->eventfilter != NULL);
7841 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7842 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7843
7844 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7845 eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7846
7847 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7848
7849 return SCIP_OKAY;
7850}
7851
7852/** deletes event handler with given data from row's event filter */
7854 SCIP_ROW* row, /**< row */
7855 BMS_BLKMEM* blkmem, /**< block memory */
7856 SCIP_SET* set, /**< global SCIP settings */
7857 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7858 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7859 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7860 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7861 )
7862{
7863 assert(row != NULL);
7864 assert(row->eventfilter != NULL);
7865
7866 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7867
7868 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7869
7870 return SCIP_OKAY;
7871}
7872
7873/** marks a row to be not removable from the LP in the current node because it became obsolete */
7875 SCIP_ROW* row, /**< LP row */
7876 SCIP_STAT* stat /**< problem statistics */
7877 )
7878{
7879 assert(row != NULL);
7880 assert(stat != NULL);
7881 assert(stat->nnodes > 0);
7882
7883 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7884 row->obsoletenode = stat->nnodes;
7885}
7886
7887/*
7888 * LP solver data update
7889 */
7890
7891/** resets column data to represent a column not in the LP solver */
7892static
7894 SCIP_COL* col /**< column to be marked deleted */
7895 )
7896{
7897 assert(col != NULL);
7898
7899 col->lpipos = -1;
7900 col->primsol = 0.0;
7901 col->redcost = SCIP_INVALID;
7902 col->farkascoef = SCIP_INVALID;
7903 col->sbdown = SCIP_INVALID;
7904 col->sbup = SCIP_INVALID;
7905 col->sbdownvalid = FALSE;
7906 col->sbupvalid = FALSE;
7907 col->validredcostlp = -1;
7908 col->validfarkaslp = -1;
7909 col->sbitlim = -1;
7910 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7911}
7912
7913/** applies all cached column removals to the LP solver */
7914static
7916 SCIP_LP* lp /**< current LP data */
7917 )
7918{
7919 assert(lp != NULL);
7920 assert(lp->lpifirstchgcol <= lp->nlpicols);
7921 assert(lp->lpifirstchgcol <= lp->ncols);
7922
7923 /* find the first column to change */
7924 while( lp->lpifirstchgcol < lp->nlpicols
7925 && lp->lpifirstchgcol < lp->ncols
7926 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7927 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7928 {
7929 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7930 lp->lpifirstchgcol++;
7931 }
7932
7933 /* shrink LP to the part which didn't change */
7934 if( lp->lpifirstchgcol < lp->nlpicols )
7935 {
7936 int i;
7937
7938 assert(!lp->diving);
7939 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7941 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7942 {
7943 markColDeleted(lp->lpicols[i]);
7944 }
7945 lp->nlpicols = lp->lpifirstchgcol;
7946 lp->flushdeletedcols = TRUE;
7947 lp->updateintegrality = TRUE;
7948
7949 /* mark the LP unsolved */
7950 lp->solved = FALSE;
7951 lp->primalfeasible = FALSE;
7952 lp->primalchecked = FALSE;
7953 lp->lpobjval = SCIP_INVALID;
7955 }
7956 assert(lp->nlpicols == lp->lpifirstchgcol);
7957
7958 return SCIP_OKAY;
7959}
7960
7961/** computes for the given column the lower and upper bound that should be flushed into the LP
7962 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7963 * the bounds are explicitly added to the LP in any case
7964 */
7965static
7967 SCIP_LP* lp, /**< current LP data */
7968 SCIP_SET* set, /**< global SCIP settings */
7969 SCIP_COL* col, /**< column to compute bounds for */
7970 SCIP_Real lpiinf, /**< infinity value if the LP solver */
7971 SCIP_Real* lb, /**< pointer to store the new lower bound */
7972 SCIP_Real* ub /**< pointer to store the new upper bound */
7973 )
7974{
7975 assert(lp != NULL);
7976 assert(set != NULL);
7977 assert(col != NULL);
7978 assert(lb != NULL);
7979 assert(ub != NULL);
7980
7981 /* get the correct new lower bound:
7982 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7983 * if we are in diving mode, ignore lazy bounds and always take the lower bound
7984 */
7985 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7986 (*lb) = -lpiinf;
7987 else
7988 (*lb) = col->lb;
7989 /* get the correct new upper bound:
7990 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7991 * if we are in diving mode, ignore lazy bounds and always take the upper bound
7992 */
7993 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7994 (*ub) = lpiinf;
7995 else
7996 (*ub) = col->ub;
7997}
7998
7999/** applies all cached column additions to the LP solver */
8000static
8002 SCIP_LP* lp, /**< current LP data */
8003 BMS_BLKMEM* blkmem, /**< block memory */
8004 SCIP_SET* set, /**< global SCIP settings */
8005 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8006 )
8007{
8008 SCIP_Real* obj;
8009 SCIP_Real* lb;
8010 SCIP_Real* ub;
8011 int* beg;
8012 int* ind;
8013 SCIP_Real* val;
8014 char** name;
8015 SCIP_COL* col;
8016 SCIP_Real lpiinf;
8017 int c;
8018 int pos;
8019 int nnonz;
8020 int naddcols;
8021 int naddcoefs;
8022 int i;
8023 int lpipos;
8024
8025 assert(lp != NULL);
8026 assert(lp->lpifirstchgcol == lp->nlpicols);
8027 assert(blkmem != NULL);
8028 assert(set != NULL);
8029
8030 /* if there are no columns to add, we are ready */
8031 if( lp->ncols == lp->nlpicols )
8032 return SCIP_OKAY;
8033
8034 /* add the additional columns */
8035 assert(!lp->diving);
8036 assert(lp->ncols > lp->nlpicols);
8037 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8038
8039 /* get the solver's infinity value */
8040 lpiinf = SCIPlpiInfinity(lp->lpi);
8041
8042 /* count the (maximal) number of added coefficients, calculate the number of added columns */
8043 naddcols = lp->ncols - lp->nlpicols;
8044 naddcoefs = 0;
8045 for( c = lp->nlpicols; c < lp->ncols; ++c )
8046 naddcoefs += lp->cols[c]->len;
8047 assert(naddcols > 0);
8048
8049 /* get temporary memory for changes */
8050 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8051 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8052 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8053 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8057
8058 /* fill temporary memory with column data */
8059 nnonz = 0;
8060 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8061 {
8062 col = lp->cols[c];
8063 assert(col != NULL);
8064 assert(col->var != NULL);
8066 assert(SCIPvarGetCol(col->var) == col);
8067 assert(col->lppos == c);
8068 assert(nnonz + col->nlprows <= naddcoefs);
8069
8070 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8071 debugColPrint(set, col);
8072
8073 /* Because the column becomes a member of the LP solver, it now can take values
8074 * different from zero. That means, we have to include the column in the corresponding
8075 * row vectors.
8076 */
8077 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8078
8079 lp->lpicols[c] = col;
8080 col->lpipos = c;
8081 col->primsol = SCIP_INVALID;
8082 col->redcost = SCIP_INVALID;
8083 col->farkascoef = SCIP_INVALID;
8084 col->sbdown = SCIP_INVALID;
8085 col->sbup = SCIP_INVALID;
8086 col->sbdownvalid = FALSE;
8087 col->sbupvalid = FALSE;
8088 col->validredcostlp = -1;
8089 col->validfarkaslp = -1;
8090 col->sbitlim = -1;
8091 col->objchanged = FALSE;
8092 col->lbchanged = FALSE;
8093 col->ubchanged = FALSE;
8094 col->coefchanged = FALSE;
8095 obj[pos] = col->obj;
8096
8097 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8098 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8099
8100 beg[pos] = nnonz;
8101 name[pos] = (char*)SCIPvarGetName(col->var);
8102
8103 col->flushedobj = obj[pos];
8104 col->flushedlb = lb[pos];
8105 col->flushedub = ub[pos];
8106
8107 for( i = 0; i < col->nlprows; ++i )
8108 {
8109 assert(col->rows[i] != NULL);
8110 lpipos = col->rows[i]->lpipos;
8111 if( lpipos >= 0 )
8112 {
8113 assert(lpipos < lp->nrows);
8114 assert(nnonz < naddcoefs);
8115 ind[nnonz] = lpipos;
8116 val[nnonz] = col->vals[i];
8117 nnonz++;
8118 }
8119 }
8120#ifndef NDEBUG
8121 for( i = col->nlprows; i < col->len; ++i )
8122 {
8123 assert(col->rows[i] != NULL);
8124 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8125 }
8126#endif
8127 }
8128
8129 /* call LP interface */
8130 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8131 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8132 lp->nlpicols = lp->ncols;
8133 lp->lpifirstchgcol = lp->nlpicols;
8134
8135 /* free temporary memory */
8143
8144 lp->flushaddedcols = TRUE;
8145 lp->updateintegrality = TRUE;
8146
8147 /* mark the LP unsolved */
8148 lp->solved = FALSE;
8149 lp->dualfeasible = FALSE;
8150 lp->dualchecked = FALSE;
8151 lp->lpobjval = SCIP_INVALID;
8153
8154 return SCIP_OKAY;
8155}
8156
8157/** resets row data to represent a row not in the LP solver */
8158static
8160 SCIP_ROW* row /**< row to be marked deleted */
8161 )
8162{
8163 assert(row != NULL);
8164
8165 row->lpipos = -1;
8166 row->dualsol = 0.0;
8167 row->activity = SCIP_INVALID;
8168 row->dualfarkas = 0.0;
8169 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8170 row->validactivitylp = -1;
8171}
8172
8173/** applies all cached row removals to the LP solver */
8174static
8176 SCIP_LP* lp, /**< current LP data */
8177 BMS_BLKMEM* blkmem, /**< block memory */
8178 SCIP_SET* set /**< global SCIP settings */
8179 )
8180{
8181 assert(lp != NULL);
8182 assert(lp->lpifirstchgrow <= lp->nlpirows);
8183 assert(lp->lpifirstchgrow <= lp->nrows);
8184
8185 /* find the first row to change */
8186 while( lp->lpifirstchgrow < lp->nlpirows
8187 && lp->lpifirstchgrow < lp->nrows
8188 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8189 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8190 {
8191 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8192 lp->lpifirstchgrow++;
8193 }
8194
8195 /* shrink LP to the part which didn't change */
8196 if( lp->lpifirstchgrow < lp->nlpirows )
8197 {
8198 int i;
8199
8200 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8202 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8203 {
8204 markRowDeleted(lp->lpirows[i]);
8205 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8206 }
8207 lp->nlpirows = lp->lpifirstchgrow;
8208 lp->flushdeletedrows = TRUE;
8209
8210 /* mark the LP unsolved */
8211 lp->solved = FALSE;
8212 lp->dualfeasible = FALSE;
8213 lp->dualchecked = FALSE;
8214 lp->lpobjval = SCIP_INVALID;
8216 }
8217 assert(lp->nlpirows == lp->lpifirstchgrow);
8218
8219 return SCIP_OKAY;
8220}
8221
8222/** applies all cached row additions and removals to the LP solver */
8223static
8225 SCIP_LP* lp, /**< current LP data */
8226 BMS_BLKMEM* blkmem, /**< block memory */
8227 SCIP_SET* set, /**< global SCIP settings */
8228 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8229 )
8230{
8231 SCIP_Real* lhs;
8232 SCIP_Real* rhs;
8233 int* beg;
8234 int* ind;
8235 SCIP_Real* val;
8236 char** name;
8237 SCIP_ROW* row;
8238 SCIP_Real lpiinf;
8239 int r;
8240 int pos;
8241 int nnonz;
8242 int naddrows;
8243 int naddcoefs;
8244 int i;
8245 int lpipos;
8246
8247 assert(lp != NULL);
8248 assert(lp->lpifirstchgrow == lp->nlpirows);
8249 assert(blkmem != NULL);
8250
8251 /* if there are no rows to add, we are ready */
8252 if( lp->nrows == lp->nlpirows )
8253 return SCIP_OKAY;
8254
8255 /* add the additional rows */
8256 assert(lp->nrows > lp->nlpirows);
8257 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8258
8259 /* get the solver's infinity value */
8260 lpiinf = SCIPlpiInfinity(lp->lpi);
8261
8262 /* count the (maximal) number of added coefficients, calculate the number of added rows */
8263 naddrows = lp->nrows - lp->nlpirows;
8264 naddcoefs = 0;
8265 for( r = lp->nlpirows; r < lp->nrows; ++r )
8266 naddcoefs += lp->rows[r]->len;
8267 assert(naddrows > 0);
8268
8269 /* get temporary memory for changes */
8270 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8271 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8272 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8273 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8276
8277 /* fill temporary memory with row data */
8278 nnonz = 0;
8279 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8280 {
8281 row = lp->rows[r];
8282 assert(row != NULL);
8283 assert(row->lppos == r);
8284 assert(nnonz + row->nlpcols <= naddcoefs);
8285
8286 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8287 debugRowPrint(set, row);
8288
8289 /* Because the row becomes a member of the LP solver, its dual variable now can take values
8290 * different from zero. That means, we have to include the row in the corresponding
8291 * column vectors.
8292 */
8293 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8294
8295 SCIProwCapture(row);
8296 lp->lpirows[r] = row;
8297 row->lpipos = r;
8298 row->dualsol = SCIP_INVALID;
8299 row->activity = SCIP_INVALID;
8300 row->dualfarkas = SCIP_INVALID;
8301 row->validactivitylp = -1;
8302 row->lhschanged = FALSE;
8303 row->rhschanged = FALSE;
8304 row->coefchanged = FALSE;
8305 if( SCIPsetIsInfinity(set, -row->lhs) )
8306 lhs[pos] = -lpiinf;
8307 else
8308 lhs[pos] = row->lhs - row->constant;
8309 if( SCIPsetIsInfinity(set, row->rhs) )
8310 rhs[pos] = lpiinf;
8311 else
8312 rhs[pos] = row->rhs - row->constant;
8313 beg[pos] = nnonz;
8314 name[pos] = row->name;
8315
8316 row->flushedlhs = lhs[pos];
8317 row->flushedrhs = rhs[pos];
8318
8319 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8320 for( i = 0; i < row->nlpcols; ++i )
8321 {
8322 assert(row->cols[i] != NULL);
8323 lpipos = row->cols[i]->lpipos;
8324 if( lpipos >= 0 )
8325 {
8326 assert(lpipos < lp->ncols);
8327 assert(nnonz < naddcoefs);
8328 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8329 ind[nnonz] = lpipos;
8330 val[nnonz] = row->vals[i];
8331 nnonz++;
8332 }
8333 }
8334 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8335#ifndef NDEBUG
8336 for( i = row->nlpcols; i < row->len; ++i )
8337 {
8338 assert(row->cols[i] != NULL);
8339 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8340 }
8341#endif
8342 }
8343
8344 /* call LP interface */
8345 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8346 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8347 lp->nlpirows = lp->nrows;
8348 lp->lpifirstchgrow = lp->nlpirows;
8349
8350 /* free temporary memory */
8357
8358 lp->flushaddedrows = TRUE;
8359
8360 /* mark the LP unsolved */
8361 lp->solved = FALSE;
8362 lp->primalfeasible = FALSE;
8363 lp->primalchecked = FALSE;
8364 lp->lpobjval = SCIP_INVALID;
8366
8367 return SCIP_OKAY;
8368}
8369
8370/** applies all cached column bound and objective changes to the LP */
8371static
8373 SCIP_LP* lp, /**< current LP data */
8374 SCIP_SET* set /**< global SCIP settings */
8375 )
8376{
8377#ifndef NDEBUG
8378 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8379#endif
8380 SCIP_COL* col;
8381 int* objind;
8382 int* bdind;
8383 SCIP_Real* obj;
8384 SCIP_Real* lb;
8385 SCIP_Real* ub;
8386 SCIP_Real lpiinf;
8387 int nobjchg;
8388 int nbdchg;
8389 int i;
8390
8391 assert(lp != NULL);
8392
8393 if( lp->nchgcols == 0 )
8394 return SCIP_OKAY;
8395
8396 /* get the solver's infinity value */
8397 lpiinf = SCIPlpiInfinity(lp->lpi);
8398
8399 /* get temporary memory for changes */
8400 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8402 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8405
8406 /* collect all cached bound and objective changes */
8407 nobjchg = 0;
8408 nbdchg = 0;
8409 for( i = 0; i < lp->nchgcols; ++i )
8410 {
8411 col = lp->chgcols[i];
8412 assert(col != NULL);
8413 assert(col->var != NULL);
8415 assert(SCIPvarGetCol(col->var) == col);
8416
8417 if( col->lpipos >= 0 )
8418 {
8419#ifndef NDEBUG
8420 /* do not check consistency of data with LPI in case of LPI=none */
8421 if( !lpinone )
8422 {
8423 SCIP_Real lpiobj;
8424 SCIP_Real lpilb;
8425 SCIP_Real lpiub;
8426
8427 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8428 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8429 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8431 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8433 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8434 }
8435#endif
8436
8437 if( col->objchanged )
8438 {
8440
8441 newobj = col->obj;
8442 if( col->flushedobj != newobj ) /*lint !e777*/
8443 {
8444 assert(nobjchg < lp->ncols);
8445 objind[nobjchg] = col->lpipos;
8446 obj[nobjchg] = newobj;
8447 nobjchg++;
8448 col->flushedobj = newobj;
8449 }
8450 col->objchanged = FALSE;
8451 }
8452
8453 if( col->lbchanged || col->ubchanged )
8454 {
8455 SCIP_Real newlb;
8456 SCIP_Real newub;
8457
8458 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8459 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8460
8461 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8462 {
8463 assert(nbdchg < lp->ncols);
8464 bdind[nbdchg] = col->lpipos;
8465 lb[nbdchg] = newlb;
8466 ub[nbdchg] = newub;
8467 nbdchg++;
8468 col->flushedlb = newlb;
8469 col->flushedub = newub;
8470 }
8471 col->lbchanged = FALSE;
8472 col->ubchanged = FALSE;
8473 }
8474 }
8475 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8476 }
8477
8478 /* change objective values in LP */
8479 if( nobjchg > 0 )
8480 {
8481 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8482 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8483
8484 /* mark the LP unsolved */
8485 lp->solved = FALSE;
8486 lp->dualfeasible = FALSE;
8487 lp->dualchecked = FALSE;
8488 lp->lpobjval = SCIP_INVALID;
8490 }
8491
8492 /* change bounds in LP */
8493 if( nbdchg > 0 )
8494 {
8495 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8496 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8497
8498 /* mark the LP unsolved */
8499 lp->solved = FALSE;
8500 lp->primalfeasible = FALSE;
8501 lp->primalchecked = FALSE;
8502 lp->lpobjval = SCIP_INVALID;
8504 }
8505
8506 lp->nchgcols = 0;
8507
8508 /* free temporary memory */
8511 SCIPsetFreeBufferArray(set, &bdind);
8513 SCIPsetFreeBufferArray(set, &objind);
8514
8515 return SCIP_OKAY;
8516}
8517
8518/** applies all cached row side changes to the LP */
8519static
8521 SCIP_LP* lp, /**< current LP data */
8522 SCIP_SET* set /**< global SCIP settings */
8523 )
8524{
8525#ifndef NDEBUG
8526 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8527#endif
8528 SCIP_ROW* row;
8529 int* ind;
8530 SCIP_Real* lhs;
8531 SCIP_Real* rhs;
8532 SCIP_Real lpiinf;
8533 int i;
8534 int nchg;
8535
8536 assert(lp != NULL);
8537
8538 if( lp->nchgrows == 0 )
8539 return SCIP_OKAY;
8540
8541 /* get the solver's infinity value */
8542 lpiinf = SCIPlpiInfinity(lp->lpi);
8543
8544 /* get temporary memory for changes */
8548
8549 /* collect all cached left and right hand side changes */
8550 nchg = 0;
8551 for( i = 0; i < lp->nchgrows; ++i )
8552 {
8553 row = lp->chgrows[i];
8554 assert(row != NULL);
8555
8556 if( row->lpipos >= 0 )
8557 {
8558#ifndef NDEBUG
8559 /* do not check consistency of data with LPI in case of LPI=none */
8560 if( !lpinone )
8561 {
8562 SCIP_Real lpilhs;
8563 SCIP_Real lpirhs;
8564
8565 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8566 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8567 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8568 }
8569#endif
8570 if( row->lhschanged || row->rhschanged )
8571 {
8572 SCIP_Real newlhs;
8573 SCIP_Real newrhs;
8574
8575 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8576 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8577 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8578 {
8579 assert(nchg < lp->nrows);
8580 ind[nchg] = row->lpipos;
8581 lhs[nchg] = newlhs;
8582 rhs[nchg] = newrhs;
8583 nchg++;
8584 row->flushedlhs = newlhs;
8585 row->flushedrhs = newrhs;
8586 }
8587 row->lhschanged = FALSE;
8588 row->rhschanged = FALSE;
8589 }
8590 }
8591 }
8592
8593 /* change left and right hand sides in LP */
8594 if( nchg > 0 )
8595 {
8596 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8597 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8598
8599 /* mark the LP unsolved */
8600 lp->solved = FALSE;
8601 lp->primalfeasible = FALSE;
8602 lp->primalchecked = FALSE;
8603 lp->lpobjval = SCIP_INVALID;
8605 }
8606
8607 lp->nchgrows = 0;
8608
8609 /* free temporary memory */
8613
8614 return SCIP_OKAY;
8615}
8616
8617/** copy integrality information to the LP */
8618static
8620 SCIP_LP* lp, /**< current LP data */
8621 SCIP_SET* set /**< global SCIP settings */
8622 )
8623{
8624 int i;
8625 int nintegers;
8626 int* integerInfo;
8627 SCIP_VAR* var;
8628
8629 assert(lp != NULL);
8630
8631 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8632
8633 /* count total number of integralities */
8634 nintegers = 0;
8635
8636 for( i = 0; i < lp->ncols; ++i )
8637 {
8638 var = SCIPcolGetVar(lp->cols[i]);
8640 {
8641 integerInfo[i] = 1;
8642 ++nintegers;
8643 }
8644 else
8645 integerInfo[i] = 0;
8646 }
8647
8648 /* only pass integrality information if integer variables are present */
8649 if( nintegers > 0 )
8650 {
8651 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8652 }
8653 else
8654 {
8656 }
8657
8658 SCIPsetFreeBufferArray(set, &integerInfo);
8659
8660 /* mark integralities to be updated */
8662
8663 return SCIP_OKAY;
8664}
8665
8666/** applies all cached changes to the LP solver */
8668 SCIP_LP* lp, /**< current LP data */
8669 BMS_BLKMEM* blkmem, /**< block memory */
8670 SCIP_SET* set, /**< global SCIP settings */
8671 SCIP_PROB* prob, /**< problem data */
8672 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8673 )
8674{
8675 assert(lp != NULL);
8676 assert(blkmem != NULL);
8677
8678 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",
8679 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8680
8681 if( !lp->flushed )
8682 {
8683 lp->flushdeletedcols = FALSE;
8684 lp->flushaddedcols = FALSE;
8685 lp->flushdeletedrows = FALSE;
8686 lp->flushaddedrows = FALSE;
8687
8689 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8692 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8693 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8694
8695 lp->flushed = TRUE;
8696
8697 checkLinks(lp);
8698 }
8699
8700 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8701 * we want to re-optimize the LP even if nothing else has changed
8702 */
8703 if( !lpCutoffDisabled(set, prob, lp) && lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 ) /*lint !e777*/
8704 {
8705 lp->solved = FALSE;
8707 }
8708
8709 assert(lp->nlpicols == lp->ncols);
8710 assert(lp->lpifirstchgcol == lp->nlpicols);
8711 assert(lp->nlpirows == lp->nrows);
8712 assert(lp->lpifirstchgrow == lp->nlpirows);
8713 assert(lp->nchgcols == 0);
8714 assert(lp->nchgrows == 0);
8715#ifndef NDEBUG
8716 {
8717 int ncols;
8718 int nrows;
8719
8720 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8721 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8722 assert(ncols == lp->ncols);
8723 assert(nrows == lp->nrows);
8724 }
8725#endif
8726
8727 return SCIP_OKAY;
8728}
8729
8730/** marks the LP to be flushed, even if the LP thinks it is not flushed */
8732 SCIP_LP* lp, /**< current LP data */
8733 SCIP_SET* set /**< global SCIP settings */
8734 )
8735{
8736#ifndef NDEBUG
8737 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8738#endif
8739 int i;
8740
8741 assert(lp != NULL);
8742
8743#ifndef NDEBUG
8744 /* check, if there are really no column or row deletions or coefficient changes left */
8745 while( lp->lpifirstchgcol < lp->nlpicols
8746 && lp->lpifirstchgcol < lp->ncols
8747 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8748 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8749 {
8750 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8751 lp->lpifirstchgcol++;
8752 }
8753 assert(lp->nlpicols == lp->lpifirstchgcol);
8754
8755 while( lp->lpifirstchgrow < lp->nlpirows
8756 && lp->lpifirstchgrow < lp->nrows
8757 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8758 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8759 {
8760 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8761 lp->lpifirstchgrow++;
8762 }
8763 assert(lp->nlpirows == lp->lpifirstchgrow);
8764#endif
8765
8766 lp->lpifirstchgcol = lp->nlpicols;
8767 lp->lpifirstchgrow = lp->nlpirows;
8768
8769 /* check, if there are really no column or row additions left */
8770 assert(lp->ncols == lp->nlpicols);
8771 assert(lp->nrows == lp->nlpirows);
8772
8773 /* mark the changed columns to be unchanged, and check, if this is really correct */
8774 for( i = 0; i < lp->nchgcols; ++i )
8775 {
8776 SCIP_COL* col;
8777
8778 col = lp->chgcols[i];
8779 assert(col != NULL);
8780 assert(col->var != NULL);
8782 assert(SCIPvarGetCol(col->var) == col);
8783
8784 if( col->lpipos >= 0 )
8785 {
8786#ifndef NDEBUG
8787 /* do not check consistency of data with LPI in case of LPI=none */
8788 if( !lpinone )
8789 {
8790 SCIP_Real lpiobj;
8791 SCIP_Real lpilb;
8792 SCIP_Real lpiub;
8793
8794 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8795 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8796 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8797 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8798 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8799 assert(col->flushedobj == col->obj); /*lint !e777*/
8800 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8801 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8802 }
8803#endif
8804 col->objchanged = FALSE;
8805 col->lbchanged = FALSE;
8806 col->ubchanged = FALSE;
8807 }
8808 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8809 }
8810 lp->nchgcols = 0;
8811
8812 /* mark the changed rows to be unchanged, and check, if this is really correct */
8813 for( i = 0; i < lp->nchgrows; ++i )
8814 {
8815 SCIP_ROW* row;
8816
8817 row = lp->chgrows[i];
8818 assert(row != NULL);
8819
8820 if( row->lpipos >= 0 )
8821 {
8822#ifndef NDEBUG
8823 /* do not check consistency of data with LPI in case of LPI=none */
8824 if( !lpinone )
8825 {
8826 SCIP_Real lpilhs;
8827 SCIP_Real lpirhs;
8828
8829 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8830 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8831 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8832 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8833 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8834 }
8835#endif
8836 row->lhschanged = FALSE;
8837 row->rhschanged = FALSE;
8838 }
8839 }
8840 lp->nchgrows = 0;
8841
8842 /* mark the LP to be flushed */
8843 lp->flushed = TRUE;
8844
8845 checkLinks(lp);
8846
8847 return SCIP_OKAY;
8848}
8849
8850
8851
8852
8853/*
8854 * LP methods
8855 */
8856
8857/** updates link data after addition of column */
8858static
8860 SCIP_COL* col, /**< LP column */
8861 SCIP_SET* set /**< global SCIP settings */
8862 )
8863{
8864 SCIP_ROW* row;
8865 int i;
8866 int pos;
8867
8868 assert(col != NULL);
8869 assert(col->lppos >= 0);
8870
8871 /* update column arrays of all linked rows */
8872 for( i = 0; i < col->len; ++i )
8873 {
8874 pos = col->linkpos[i];
8875 if( pos >= 0 )
8876 {
8877 row = col->rows[i];
8878 assert(row != NULL);
8879 assert(row->linkpos[pos] == i);
8880 assert(row->cols[pos] == col);
8881 assert(row->nlpcols <= pos && pos < row->len);
8882
8883 row->nlpcols++;
8884 rowSwapCoefs(row, pos, row->nlpcols-1);
8885 assert(row->cols[row->nlpcols-1] == col);
8886
8887 /* if no swap was necessary, mark lpcols to be unsorted */
8888 if( pos == row->nlpcols-1 )
8889 row->lpcolssorted = FALSE;
8890
8891 /* update norms */
8892 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8893 }
8894 }
8895}
8896
8897/** updates link data after addition of row */
8898static
8900 SCIP_ROW* row /**< LP row */
8901 )
8902{
8903 SCIP_COL* col;
8904 int i;
8905 int pos;
8906
8907 assert(row != NULL);
8908 assert(row->lppos >= 0);
8909
8910 /* update row arrays of all linked columns */
8911 for( i = 0; i < row->len; ++i )
8912 {
8913 pos = row->linkpos[i];
8914 if( pos >= 0 )
8915 {
8916 col = row->cols[i];
8917 assert(col != NULL);
8918 assert(col->linkpos[pos] == i);
8919 assert(col->rows[pos] == row);
8920 assert(col->nlprows <= pos && pos < col->len);
8921
8922 col->nlprows++;
8923 colSwapCoefs(col, pos, col->nlprows-1);
8924
8925 /* if no swap was necessary, mark lprows to be unsorted */
8926 if( pos == col->nlprows-1 )
8927 col->lprowssorted = FALSE;
8928 }
8929 }
8930}
8931
8932/** updates link data after removal of column */
8933static
8935 SCIP_COL* col, /**< LP column */
8936 SCIP_SET* set /**< global SCIP settings */
8937 )
8938{
8939 SCIP_ROW* row;
8940 int i;
8941 int pos;
8942
8943 assert(col != NULL);
8944 assert(col->lppos == -1);
8945
8946 /* update column arrays of all linked rows */
8947 for( i = 0; i < col->len; ++i )
8948 {
8949 pos = col->linkpos[i];
8950 if( pos >= 0 )
8951 {
8952 row = col->rows[i];
8953 assert(row != NULL);
8954 assert(row->linkpos[pos] == i);
8955 assert(row->cols[pos] == col);
8956 assert(0 <= pos && pos < row->nlpcols);
8957
8958 /* update norms */
8959 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8960
8961 row->nlpcols--;
8962 rowSwapCoefs(row, pos, row->nlpcols);
8963
8964 /* if no swap was necessary, mark nonlpcols to be unsorted */
8965 if( pos == row->nlpcols )
8966 row->nonlpcolssorted = FALSE;
8967 }
8968 }
8969}
8970
8971/** updates link data after removal of row */
8972static
8974 SCIP_ROW* row /**< LP row */
8975 )
8976{
8977 SCIP_COL* col;
8978 int i;
8979 int pos;
8980
8981 assert(row != NULL);
8982 assert(row->lppos == -1);
8983
8984 /* update row arrays of all linked columns */
8985 for( i = 0; i < row->len; ++i )
8986 {
8987 pos = row->linkpos[i];
8988 if( pos >= 0 )
8989 {
8990 col = row->cols[i];
8991 assert(col != NULL);
8992 assert(0 <= pos && pos < col->nlprows);
8993 assert(col->linkpos[pos] == i);
8994 assert(col->rows[pos] == row);
8995
8996 col->nlprows--;
8997 colSwapCoefs(col, pos, col->nlprows);
8998
8999 /* if no swap was necessary, mark lprows to be unsorted */
9000 if( pos == col->nlprows )
9001 col->nonlprowssorted = FALSE;
9002 }
9003 }
9004}
9005
9006static
9008 SCIP_LP* lp, /**< LP data object */
9009 int initsize /**< initial size of the arrays */
9010 )
9011{
9012 assert(lp != NULL);
9013 assert(lp->divechgsides == NULL);
9015 assert(lp->divechgrows == NULL);
9016 assert(lp->ndivechgsides == 0);
9017 assert(lp->divechgsidessize == 0);
9018 assert(initsize > 0);
9019
9020 lp->divechgsidessize = initsize;
9024
9025 return SCIP_OKAY;
9026}
9027
9028static
9030 SCIP_LP* lp, /**< LP data object */
9031 int minsize, /**< minimal number of elements */
9032 SCIP_Real growfact /**< growing factor */
9033 )
9034{
9035 assert(lp != NULL);
9036 assert(lp->divechgsides != NULL);
9038 assert(lp->divechgrows != NULL);
9039 assert(lp->ndivechgsides > 0);
9040 assert(lp->divechgsidessize > 0);
9041 assert(minsize > 0);
9042
9043 if( minsize <= lp->divechgsidessize )
9044 return SCIP_OKAY;
9045
9046 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9050
9051 return SCIP_OKAY;
9052}
9053
9054static
9056 SCIP_LP* lp /**< LP data object */
9057 )
9058{
9059 assert(lp != NULL);
9060 assert(lp->divechgsides != NULL);
9062 assert(lp->divechgrows != NULL);
9063 assert(lp->ndivechgsides == 0);
9064 assert(lp->divechgsidessize > 0);
9065
9069 lp->divechgsidessize = 0;
9070}
9071
9072#define DIVESTACKINITSIZE 100
9073
9074/** creates empty LP data object */
9076 SCIP_LP** lp, /**< pointer to LP data object */
9077 SCIP_SET* set, /**< global SCIP settings */
9078 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
9079 SCIP_STAT* stat, /**< problem statistics */
9080 const char* name /**< problem name */
9081 )
9082{
9083 SCIP_Bool success;
9084
9085 assert(lp != NULL);
9086 assert(set != NULL);
9087 assert(stat != NULL);
9088 assert(name != NULL);
9089
9091
9092 /* open LP Solver interface */
9093 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9094
9095 (*lp)->lpicols = NULL;
9096 (*lp)->lpirows = NULL;
9097 (*lp)->chgcols = NULL;
9098 (*lp)->chgrows = NULL;
9099 (*lp)->cols = NULL;
9100 (*lp)->soldirection = NULL;
9101 (*lp)->lazycols = NULL;
9102 (*lp)->rows = NULL;
9103 (*lp)->lpobjval = 0.0;
9104 (*lp)->glbpseudoobjval = 0.0;
9105 (*lp)->relglbpseudoobjval = 0.0;
9106 (*lp)->glbpseudoobjvalid = TRUE;
9107 (*lp)->glbpseudoobjvalinf = 0;
9108 (*lp)->pseudoobjval = 0.0;
9109 (*lp)->relpseudoobjval = 0.0;
9110 (*lp)->pseudoobjvalid = TRUE;
9111 (*lp)->pseudoobjvalinf = 0;
9112 (*lp)->looseobjval = 0.0;
9113 (*lp)->rellooseobjval = 0.0;
9114 (*lp)->looseobjvalid = TRUE;
9115 (*lp)->looseobjvalinf = 0;
9116 (*lp)->nloosevars = 0;
9117 (*lp)->rootlpobjval = SCIP_INVALID;
9118 (*lp)->rootlooseobjval = SCIP_INVALID;
9119 (*lp)->cutoffbound = SCIPsetInfinity(set);
9120 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9121 SCIPlpResetFeastol(*lp, set);
9122 (*lp)->validdegeneracylp = -1;
9123 (*lp)->objsqrnorm = 0.0;
9124 (*lp)->objsumnorm = 0.0;
9125 (*lp)->lpicolssize = 0;
9126 (*lp)->nlpicols = 0;
9127 (*lp)->lpirowssize = 0;
9128 (*lp)->nlpirows = 0;
9129 (*lp)->lpifirstchgcol = 0;
9130 (*lp)->lpifirstchgrow = 0;
9131 (*lp)->colssize = 0;
9132 (*lp)->soldirectionsize = 0;
9133 (*lp)->ncols = 0;
9134 (*lp)->lazycolssize = 0;
9135 (*lp)->nlazycols = 0;
9136 (*lp)->rowssize = 0;
9137 (*lp)->nrows = 0;
9138 (*lp)->chgcolssize = 0;
9139 (*lp)->nchgcols = 0;
9140 (*lp)->chgrowssize = 0;
9141 (*lp)->nchgrows = 0;
9142 (*lp)->firstnewcol = 0;
9143 (*lp)->firstnewrow = 0;
9144 (*lp)->nremovablecols = 0;
9145 (*lp)->nremovablerows = 0;
9146 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9147 (*lp)->validfarkaslp = -1;
9148 (*lp)->validsoldirlp = -1;
9149 (*lp)->validsoldirsol = NULL;
9150 (*lp)->objsqrnormunreliable = FALSE;
9151 (*lp)->flushdeletedcols = FALSE;
9152 (*lp)->flushaddedcols = FALSE;
9153 (*lp)->flushdeletedrows = FALSE;
9154 (*lp)->flushaddedrows = FALSE;
9155 (*lp)->updateintegrality = TRUE;
9156 (*lp)->flushed = TRUE;
9157 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9158 (*lp)->solved = TRUE;
9159 (*lp)->primalfeasible = TRUE;
9160 (*lp)->primalchecked = TRUE;
9161 (*lp)->dualfeasible = TRUE;
9162 (*lp)->dualchecked = TRUE;
9163 (*lp)->solisbasic = FALSE;
9164 (*lp)->rootlpisrelax = TRUE;
9165 (*lp)->isrelax = TRUE;
9166 (*lp)->installing = FALSE;
9167 (*lp)->strongbranching = FALSE;
9168 (*lp)->strongbranchprobing = FALSE;
9169 (*lp)->probing = FALSE;
9170 (*lp)->diving = FALSE;
9171 (*lp)->divingobjchg = FALSE;
9172 (*lp)->divinglazyapplied = FALSE;
9173 (*lp)->divelpistate = NULL;
9174 (*lp)->divelpwasprimfeas = TRUE;
9175 (*lp)->divelpwasprimchecked = TRUE;
9176 (*lp)->divelpwasdualfeas = TRUE;
9177 (*lp)->divelpwasdualchecked = TRUE;
9178 (*lp)->divechgsides = NULL;
9179 (*lp)->divechgsidetypes = NULL;
9180 (*lp)->divechgrows = NULL;
9181 (*lp)->ndivechgsides = 0;
9182 (*lp)->divechgsidessize = 0;
9183 (*lp)->ndivingrows = 0;
9184 (*lp)->divinglpiitlim = INT_MAX;
9185 (*lp)->resolvelperror = FALSE;
9186 (*lp)->divenolddomchgs = 0;
9187 (*lp)->adjustlpval = FALSE;
9188 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9189 (*lp)->lpifeastol = (*lp)->feastol;
9190 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9191 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9192 (*lp)->lpifromscratch = FALSE;
9193 (*lp)->lpifastmip = set->lp_fastmip;
9194 (*lp)->lpiscaling = set->lp_scaling;
9195 (*lp)->lpipresolving = set->lp_presolving;
9196 (*lp)->lpilpinfo = set->disp_lpinfo;
9197 (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9198 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9199 (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9200 (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9201 (*lp)->lpimarkowitz = set->lp_markowitz;
9202 (*lp)->lpiitlim = INT_MAX;
9203 (*lp)->lpipricing = SCIP_PRICING_AUTO;
9204 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9205 (*lp)->lpithreads = set->lp_threads;
9206 (*lp)->lpitiming = (int) set->time_clocktype;
9207 (*lp)->lpirandomseed = set->random_randomseed;
9208 (*lp)->storedsolvals = NULL;
9209
9210 /* allocate arrays for diving */
9212
9213 /* set default parameters in LP solver */
9214 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9215 if( !success )
9216 {
9217 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9218 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9220 }
9221 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9222 (*lp)->lpihasfeastol = success;
9223 if( !success )
9224 {
9225 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9226 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9228 }
9229 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9230 (*lp)->lpihasdualfeastol = success;
9231 if( !success )
9232 {
9233 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9234 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9236 }
9237 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9238 (*lp)->lpihasbarrierconvtol = success;
9239 if( !success )
9240 {
9241 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9242 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9244 }
9245 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9246 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9247 (*lp)->lpihasfastmip = success;
9248 if( !success )
9249 {
9250 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9251 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9253 }
9254 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9255 (*lp)->lpihasscaling = success;
9256 if( !success )
9257 {
9258 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9259 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9261 }
9262 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9263 (*lp)->lpihaspresolving = success;
9264 if( !success )
9265 {
9266 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9267 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9269 }
9270 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9271 if( !success )
9272 {
9273 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9274 "LP Solver <%s>: clock type cannot be set\n",
9276 }
9277 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9278 if( !success )
9279 {
9280 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9281 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9283 }
9284 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9285 if( !success )
9286 {
9287 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9288 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9290 }
9291 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9292 if( !success )
9293 {
9294 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9295 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9297 }
9298 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9299 (*lp)->lpihasrowrep = success;
9300 if( !success )
9301 {
9302 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9303 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9305 }
9306 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9307 (*lp)->lpihaspolishing = success;
9308 if( !success )
9309 {
9310 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9311 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9313 }
9314 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9315 (*lp)->lpihasrefactor = success;
9316 if( !success )
9317 {
9318 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9319 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9321 }
9322 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9323 if( !success )
9324 {
9325 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9326 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9328 }
9329 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9330 if( !success )
9331 {
9332 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9333 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9335 }
9336 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9337 if( !success )
9338 {
9339 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9340 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9342 }
9343 /* keep the default LP random seed if this parameter is set to 0 (current default) */
9344 if( (*lp)->lpirandomseed != 0 )
9345 {
9346 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9347 if( !success )
9348 {
9349 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9350 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9352 }
9353 }
9354
9355 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9356 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9357 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9358 {
9359 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9361 }
9362
9363 return SCIP_OKAY;
9364}
9365
9366/** frees LP data object */
9368 SCIP_LP** lp, /**< pointer to LP data object */
9369 BMS_BLKMEM* blkmem, /**< block memory */
9370 SCIP_SET* set, /**< global SCIP settings */
9371 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9372 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9373 )
9374{
9375 int i;
9376
9377 assert(lp != NULL);
9378 assert(*lp != NULL);
9379
9380 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9381
9383
9384 /* release LPI rows */
9385 for( i = 0; i < (*lp)->nlpirows; ++i )
9386 {
9387 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9388 }
9389
9390 if( (*lp)->lpi != NULL )
9391 {
9392 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9393 }
9394
9395 BMSfreeMemoryNull(&(*lp)->storedsolvals);
9396 BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9397 BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9398 BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9399 BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9400 BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9401 BMSfreeMemoryArrayNull(&(*lp)->cols);
9402 BMSfreeMemoryArrayNull(&(*lp)->rows);
9403 BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9404 BMSfreeMemory(lp);
9405
9406 return SCIP_OKAY;
9407}
9408
9409/** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9410 * changes to the LP solver
9411 */
9413 SCIP_LP* lp, /**< LP data */
9414 BMS_BLKMEM* blkmem, /**< block memory */
9415 SCIP_SET* set, /**< global SCIP settings */
9416 SCIP_PROB* prob, /**< problem data */
9417 SCIP_STAT* stat, /**< problem statistics */
9418 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9419 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9420 )
9421{
9422 assert(stat != NULL);
9423
9424 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9425 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9426
9427 /* mark the empty LP to be solved */
9429 lp->lpobjval = 0.0;
9430 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9431 lp->validfarkaslp = -1;
9432 lp->validdegeneracylp = -1;
9433 lp->validsoldirlp = -1;
9434 lp->validsoldirsol = NULL;
9435 lp->solved = TRUE;
9436 lp->primalfeasible = TRUE;
9437 lp->primalchecked = TRUE;
9438 lp->dualfeasible = TRUE;
9439 lp->dualchecked = TRUE;
9440 lp->solisbasic = FALSE;
9442
9443 return SCIP_OKAY;
9444}
9445
9446/** adds a column to the LP */
9448 SCIP_LP* lp, /**< LP data */
9449 SCIP_SET* set, /**< global SCIP settings */
9450 SCIP_COL* col, /**< LP column */
9451 int depth /**< depth in the tree where the column addition is performed */
9452 )
9453{
9454 assert(lp != NULL);
9455 assert(!lp->diving);
9456 assert(col != NULL);
9457 assert(col->len == 0 || col->rows != NULL);
9458 assert(col->lppos == -1);
9459 assert(col->var != NULL);
9461 assert(SCIPvarGetCol(col->var) == col);
9462 assert(SCIPvarIsIntegral(col->var) == col->integral);
9463
9464 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9465#ifdef SCIP_DEBUG
9466 {
9467 int i;
9468 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9469 for( i = 0; i < col->len; ++i )
9470 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9472 }
9473#endif
9474
9475 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9476 lp->cols[lp->ncols] = col;
9477 col->lppos = lp->ncols;
9478 col->lpdepth = depth;
9479 col->age = 0;
9480 lp->ncols++;
9481 if( col->removable )
9482 lp->nremovablecols++;
9483
9484 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9485 {
9487 lp->lazycols[lp->nlazycols] = col;
9488 lp->nlazycols++;
9489 }
9490
9491 /* mark the current LP unflushed */
9492 lp->flushed = FALSE;
9493
9494 /* update column arrays of all linked rows */
9495 colUpdateAddLP(col, set);
9496
9497 /* update the objective function vector norms */
9498 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9499
9500 checkLinks(lp);
9501
9502 return SCIP_OKAY;
9503}
9504
9505/** adds a row to the LP and captures it */
9507 SCIP_LP* lp, /**< LP data */
9508 BMS_BLKMEM* blkmem, /**< block memory buffers */
9509 SCIP_SET* set, /**< global SCIP settings */
9510 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9511 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9512 SCIP_ROW* row, /**< LP row */
9513 int depth /**< depth in the tree where the row addition is performed */
9514 )
9515{
9516 assert(lp != NULL);
9517 assert(row != NULL);
9518 assert(row->len == 0 || row->cols != NULL);
9519 assert(row->lppos == -1);
9520
9521 SCIProwCapture(row);
9522 SCIProwLock(row);
9523
9524 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9525#ifdef SCIP_DEBUG
9526 {
9527 int i;
9528 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs);
9529 for( i = 0; i < row->len; ++i )
9530 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9531 if( !SCIPsetIsZero(set, row->constant) )
9532 SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9533 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9534 }
9535#endif
9536
9537 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9538 lp->rows[lp->nrows] = row;
9539 row->lppos = lp->nrows;
9540 row->lpdepth = depth;
9541 row->age = 0;
9542 lp->nrows++;
9543 if( row->removable )
9544 lp->nremovablerows++;
9545
9546 /* mark the current LP unflushed */
9547 lp->flushed = FALSE;
9548
9549 /* update row arrays of all linked columns */
9550 rowUpdateAddLP(row);
9551
9552 checkLinks(lp);
9553
9554 rowCalcNorms(row, set);
9555
9556 /* check, if row addition to LP events are tracked
9557 * if so, issue ROWADDEDLP event
9558 */
9559 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9560 {
9561 SCIP_EVENT* event;
9562
9563 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9564 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9565 }
9566
9567 return SCIP_OKAY;
9568}
9569
9570
9571#ifndef NDEBUG
9572/** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9573 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9574 * the lazycols array
9575 */
9576static
9578 SCIP_LP* lp, /**< LP data */
9579 SCIP_SET* set /**< global SCIP settings */
9580 )
9581{
9582 SCIP_Bool contained;
9583 int c;
9584 int i;
9585
9586 assert(lp != NULL);
9587
9588 /* check if each column in the lazy column array has a counter part in the column array */
9589 for( i = 0; i < lp->nlazycols; ++i )
9590 {
9591 /* check if each lazy column has at least on lazy bound */
9592 assert(lp->lazycols[i] != NULL);
9594
9595 contained = FALSE;
9596 for( c = 0; c < lp->ncols; ++c )
9597 {
9598 if( lp->lazycols[i] == lp->cols[c] )
9599 {
9601 contained = TRUE;
9602 }
9603 }
9604 assert(contained);
9605 }
9606
9607 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9608 * array */
9609 for( c = 0; c < lp->ncols; ++c )
9610 {
9611 contained = FALSE;
9612 assert(lp->cols[c] != NULL);
9613
9614 for( i = 0; i < lp->nlazycols; ++i )
9615 {
9616 if( lp->lazycols[i] == lp->cols[c] )
9617 {
9618 contained = TRUE;
9619 }
9620 }
9621
9622 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9623 }
9624}
9625#else
9626#define checkLazyColArray(lp, set) /**/
9627#endif
9628
9629/** removes all columns after the given number of cols from the LP */
9631 SCIP_LP* lp, /**< LP data */
9632 SCIP_SET* set, /**< global SCIP settings */
9633 int newncols /**< new number of columns in the LP */
9634 )
9635{
9636 SCIP_COL* col;
9637 int c;
9638
9639 assert(lp != NULL);
9640
9641 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9642 assert(0 <= newncols);
9643 assert(newncols <= lp->ncols);
9644
9645 if( newncols < lp->ncols )
9646 {
9647 assert(!lp->diving);
9648
9649 for( c = lp->ncols-1; c >= newncols; --c )
9650 {
9651 col = lp->cols[c];
9652 assert(col != NULL);
9653 assert(col->len == 0 || col->rows != NULL);
9654 assert(col->var != NULL);
9656 assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9657 assert(col->lppos == c);
9658
9659 /* mark column to be removed from the LP */
9660 col->lppos = -1;
9661 col->lpdepth = -1;
9662 lp->ncols--;
9663
9664 /* count removable columns */
9665 if( col->removable )
9666 lp->nremovablecols--;
9667
9668 /* update column arrays of all linked rows */
9669 colUpdateDelLP(col, set);
9670
9671 /* update the objective function vector norms */
9672 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9673 }
9674 assert(lp->ncols == newncols);
9675 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9676
9677 /* remove columns which are deleted from the lazy column array */
9678 c = 0;
9679 while( c < lp->nlazycols )
9680 {
9681 if( lp->lazycols[c]->lppos < 0 )
9682 {
9683 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9684 lp->nlazycols--;
9685 }
9686 else
9687 c++;
9688 }
9689
9690 /* mark the current LP unflushed */
9691 lp->flushed = FALSE;
9692
9694 checkLinks(lp);
9695 }
9696 assert(lp->nremovablecols <= lp->ncols);
9697
9698 return SCIP_OKAY;
9699}
9700
9701/** removes and releases all rows after the given number of rows from the LP */
9703 SCIP_LP* lp, /**< LP data */
9704 BMS_BLKMEM* blkmem, /**< block memory */
9705 SCIP_SET* set, /**< global SCIP settings */
9706 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9707 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9708 int newnrows /**< new number of rows in the LP */
9709 )
9710{
9711 SCIP_ROW* row;
9712 int r;
9713
9714 assert(lp != NULL);
9715 assert(0 <= newnrows && newnrows <= lp->nrows);
9716
9717 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9718 if( newnrows < lp->nrows )
9719 {
9720 for( r = lp->nrows-1; r >= newnrows; --r )
9721 {
9722 row = lp->rows[r];
9723 assert(row != NULL);
9724 assert(row->len == 0 || row->cols != NULL);
9725 assert(row->lppos == r);
9726
9727 /* mark row to be removed from the LP */
9728 row->lppos = -1;
9729 row->lpdepth = -1;
9730 lp->nrows--;
9731
9732 /* count removable rows */
9733 if( row->removable )
9734 lp->nremovablerows--;
9735
9736 /* update row arrays of all linked columns */
9737 rowUpdateDelLP(row);
9738
9739 SCIProwUnlock(lp->rows[r]);
9740
9741 /* check, if row deletion events are tracked
9742 * if so, issue ROWDELETEDLP event
9743 */
9744 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9745 {
9746 SCIP_EVENT* event;
9747
9748 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9749 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9750 }
9751
9752 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9753 }
9754 assert(lp->nrows == newnrows);
9755 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9756
9757 /* mark the current LP unflushed */
9758 lp->flushed = FALSE;
9759
9760 checkLinks(lp);
9761 }
9762 assert(lp->nremovablerows <= lp->nrows);
9763
9764 return SCIP_OKAY;
9765}
9766
9767/** removes all columns and rows from LP, releases all rows */
9769 SCIP_LP* lp, /**< LP data */
9770 BMS_BLKMEM* blkmem, /**< block memory */
9771 SCIP_SET* set, /**< global SCIP settings */
9772 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9773 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9774 )
9775{
9776 assert(lp != NULL);
9777 assert(!lp->diving);
9778
9779 SCIPsetDebugMsg(set, "clearing LP\n");
9780 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9781 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9782
9783 return SCIP_OKAY;
9784}
9785
9786/** remembers number of columns and rows to track the newly added ones */
9788 SCIP_LP* lp /**< current LP data */
9789 )
9790{
9791 assert(lp != NULL);
9792 assert(!lp->diving);
9793
9794 lp->firstnewrow = lp->nrows;
9795 lp->firstnewcol = lp->ncols;
9796}
9797
9798/** sets the remembered number of columns and rows to the given values */
9800 SCIP_LP* lp, /**< current LP data */
9801 int nrows, /**< number of rows to set the size marker to */
9802 int ncols /**< number of columns to set the size marker to */
9803 )
9804{
9805 assert(lp != NULL);
9806 assert(!lp->diving);
9807
9808 lp->firstnewrow = nrows;
9809 lp->firstnewcol = ncols;
9810}
9811
9812/** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9814 SCIP_LP* lp, /**< LP data */
9815 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9816 )
9817{
9818 assert(lp != NULL);
9819 assert(lp->flushed);
9820 assert(lp->solved);
9821 assert(lp->solisbasic);
9822 assert(basisind != NULL);
9823
9824 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9825
9826 return SCIP_OKAY;
9827}
9828
9829/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9831 SCIP_LP* lp, /**< LP data */
9832 int* cstat, /**< array to store column basis status, or NULL */
9833 int* rstat /**< array to store row basis status, or NULL */
9834 )
9835{
9836 assert(lp != NULL);
9837 assert(lp->flushed);
9838 assert(lp->solved);
9839 assert(lp->solisbasic);
9840
9841 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9842
9843 return SCIP_OKAY;
9844}
9845
9846/** gets a row from the inverse basis matrix B^-1 */
9848 SCIP_LP* lp, /**< LP data */
9849 int r, /**< row number */
9850 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9851 int* inds, /**< array to store the non-zero indices, or NULL */
9852 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9853 * (-1: if we do not store sparsity informations) */
9854 )
9855{
9856 assert(lp != NULL);
9857 assert(lp->flushed);
9858 assert(lp->solved);
9859 assert(lp->solisbasic);
9860 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9861 assert(coef != NULL);
9862
9863 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9864
9865 return SCIP_OKAY;
9866}
9867
9868/** gets a column from the inverse basis matrix B^-1 */
9870 SCIP_LP* lp, /**< LP data */
9871 int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9872 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9873 * to get the array which links the B^-1 column numbers to the row and
9874 * column numbers of the LP! c must be between 0 and nrows-1, since the
9875 * basis has the size nrows * nrows */
9876 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9877 int* inds, /**< array to store the non-zero indices, or NULL */
9878 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9879 * (-1: if we do not store sparsity informations) */
9880 )
9881{
9882 assert(lp != NULL);
9883 assert(lp->flushed);
9884 assert(lp->solved);
9885 assert(lp->solisbasic);
9886 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9887 assert(coef != NULL);
9888
9889 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9890
9891 return SCIP_OKAY;
9892}
9893
9894/** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9896 SCIP_LP* lp, /**< LP data */
9897 int r, /**< row number */
9898 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9899 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9900 int* inds, /**< array to store the non-zero indices, or NULL */
9901 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9902 * (-1: if we do not store sparsity informations) */
9903 )
9904{
9905 assert(lp != NULL);
9906 assert(lp->flushed);
9907 assert(lp->solved);
9908 assert(lp->solisbasic);
9909 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9910 assert(coef != NULL);
9911
9912 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9913
9914 return SCIP_OKAY;
9915}
9916
9917/** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9918 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9919 */
9921 SCIP_LP* lp, /**< LP data */
9922 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9923 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9924 int* inds, /**< array to store the non-zero indices, or NULL */
9925 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9926 * (-1: if we do not store sparsity informations) */
9927 )
9928{
9929 assert(lp != NULL);
9930 assert(lp->flushed);
9931 assert(lp->solved);
9932 assert(lp->solisbasic);
9933 assert(0 <= c && c < lp->ncols);
9934 assert(coef != NULL);
9935
9936 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9937
9938 return SCIP_OKAY;
9939}
9940
9941/** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9942 * LP row are swapped in the summation
9943 */
9945 SCIP_LP* lp, /**< LP data */
9946 SCIP_SET* set, /**< global SCIP settings */
9947 SCIP_PROB* prob, /**< problem data */
9948 SCIP_Real* weights, /**< row weights in row summation */
9949 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9950 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9951 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9952 )
9953{
9954 SCIP_ROW* row;
9955 int r;
9956 int i;
9957 int idx;
9958 SCIP_Bool lhsinfinite;
9959 SCIP_Bool rhsinfinite;
9960
9961 assert(lp != NULL);
9962 assert(prob != NULL);
9963 assert(weights != NULL);
9964 assert(sumcoef != NULL);
9965 assert(sumlhs != NULL);
9966 assert(sumrhs != NULL);
9967
9968 /**@todo test, if a column based summation is faster */
9969
9970 SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9971 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9972 *sumlhs = 0.0;
9973 *sumrhs = 0.0;
9974 lhsinfinite = FALSE;
9975 rhsinfinite = FALSE;
9976 for( r = 0; r < lp->nrows; ++r )
9977 {
9978 if( !SCIPsetIsZero(set, weights[r]) )
9979 {
9980 row = lp->rows[r];
9981 assert(row != NULL);
9982 assert(row->len == 0 || row->cols != NULL);
9983 assert(row->len == 0 || row->cols_index != NULL);
9984 assert(row->len == 0 || row->vals != NULL);
9985
9986 /* add the row coefficients to the sum */
9987 for( i = 0; i < row->len; ++i )
9988 {
9989 assert(row->cols[i] != NULL);
9990 assert(row->cols[i]->var != NULL);
9992 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9994 idx = row->cols[i]->var_probindex;
9995 assert(0 <= idx && idx < prob->nvars);
9996 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
9997 }
9998
9999 /* add the row sides to the sum, depending on the sign of the weight */
10000 if( weights[r] > 0.0 )
10001 {
10002 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10003 if( !lhsinfinite )
10004 (*sumlhs) += weights[r] * (row->lhs - row->constant);
10005 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10006 if( !rhsinfinite )
10007 (*sumrhs) += weights[r] * (row->rhs - row->constant);
10008 }
10009 else
10010 {
10011 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10012 if( !lhsinfinite )
10013 (*sumlhs) += weights[r] * (row->rhs - row->constant);
10014 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10015 if( !rhsinfinite )
10016 (*sumrhs) += weights[r] * (row->lhs - row->constant);
10017 }
10018 }
10019 }
10020
10021 if( lhsinfinite )
10022 *sumlhs = -SCIPsetInfinity(set);
10023 if( rhsinfinite )
10024 *sumrhs = SCIPsetInfinity(set);
10025
10026 return SCIP_OKAY;
10027}
10028
10029/** stores LP state (like basis information) into LP state object */
10031 SCIP_LP* lp, /**< LP data */
10032 BMS_BLKMEM* blkmem, /**< block memory */
10033 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10034 )
10035{
10036 assert(lp != NULL);
10037 assert(lp->flushed);
10038 assert(lp->solved);
10039 assert(blkmem != NULL);
10040 assert(lpistate != NULL);
10041
10042 /* check whether there is no lp */
10043 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10044 *lpistate = NULL;
10045 else
10046 {
10047 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10048 }
10049
10050 return SCIP_OKAY;
10051}
10052
10053/** loads LP state (like basis information) into solver */
10055 SCIP_LP* lp, /**< LP data */
10056 BMS_BLKMEM* blkmem, /**< block memory */
10057 SCIP_SET* set, /**< global SCIP settings */
10058 SCIP_PROB* prob, /**< problem data */
10059 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10060 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
10061 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
10062 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */
10063 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */
10064 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */
10065 )
10066{
10067 assert(lp != NULL);
10068 assert(blkmem != NULL);
10069
10070 /* flush changes to the LP solver */
10071 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10072 assert(lp->flushed);
10073
10074 if( lp->solved && lp->solisbasic )
10075 return SCIP_OKAY;
10076
10077 /* set LPI state in the LP solver */
10078 if( lpistate == NULL )
10079 lp->solisbasic = FALSE;
10080 else
10081 {
10082 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10083 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10084 }
10085 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10086 * flushed and solved, also, e.g., when we hit the iteration limit
10087 */
10088 lp->primalfeasible = wasprimfeas;
10089 lp->primalchecked = wasprimchecked;
10090 lp->dualfeasible = wasdualfeas;
10091 lp->dualchecked = wasdualchecked;
10092
10093 return SCIP_OKAY;
10094}
10095
10096/** frees LP state information */
10098 SCIP_LP* lp, /**< LP data */
10099 BMS_BLKMEM* blkmem, /**< block memory */
10100 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10101 )
10102{
10103 assert(lp != NULL);
10104
10105 if( *lpistate != NULL )
10106 {
10107 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10108 }
10109
10110 return SCIP_OKAY;
10111}
10112
10113/** interrupts the currently ongoing lp solve, or disables the interrupt */
10115 SCIP_LP* lp, /**< LP data */
10116 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10117 )
10118{
10119 assert(lp != NULL);
10120
10121 if( lp->lpi == NULL )
10122 return SCIP_OKAY;
10123
10124 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10125
10126 return SCIP_OKAY;
10127}
10128
10129/** stores pricing norms into LP norms object */
10131 SCIP_LP* lp, /**< LP data */
10132 BMS_BLKMEM* blkmem, /**< block memory */
10133 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10134 )
10135{
10136 assert(lp != NULL);
10137 assert(lp->flushed);
10138 assert(lp->solved);
10139 assert(blkmem != NULL);
10140 assert(lpinorms != NULL);
10141
10142 /* check whether there is no lp */
10143 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10144 *lpinorms = NULL;
10145 else
10146 {
10147 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10148 }
10149
10150 return SCIP_OKAY;
10151}
10152
10153/** loads pricing norms from LP norms object into solver */
10155 SCIP_LP* lp, /**< LP data */
10156 BMS_BLKMEM* blkmem, /**< block memory */
10157 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
10158 )
10159{
10160 assert(lp != NULL);
10161 assert(blkmem != NULL);
10162 assert(lp->flushed);
10163
10164 /* set LPI norms in the LP solver */
10165 if( lpinorms != NULL )
10166 {
10167 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10168 }
10169
10170 return SCIP_OKAY;
10171}
10172
10173/** frees pricing norms information */
10175 SCIP_LP* lp, /**< LP data */
10176 BMS_BLKMEM* blkmem, /**< block memory */
10177 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10178 )
10179{
10180 assert(lp != NULL);
10181
10182 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10183
10184 return SCIP_OKAY;
10185}
10186
10187/** return the current cutoff bound of the lp */
10189 SCIP_LP* lp /**< current LP data */
10190 )
10191{
10192 assert(lp != NULL);
10193
10194 return lp->cutoffbound;
10195}
10196
10197/** sets the upper objective limit of the LP solver */
10199 SCIP_LP* lp, /**< current LP data */
10200 SCIP_SET* set, /**< global SCIP settings */
10201 SCIP_PROB* prob, /**< problem data */
10202 SCIP_Real cutoffbound /**< new upper objective limit */
10203 )
10204{
10205 assert(lp != NULL);
10206
10207 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10208
10209 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10210 * in SCIPendDive())
10211 */
10212 if( SCIPlpDivingObjChanged(lp) )
10213 {
10215 return SCIP_OKAY;
10216 }
10217
10218 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10219 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10220 {
10221 /* mark the current solution invalid */
10222 lp->solved = FALSE;
10223 lp->lpobjval = SCIP_INVALID;
10225 }
10226 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10227 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10228 */
10229 else if( !lpCutoffDisabled(set, prob, lp) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
10230 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10231 {
10232 assert(lp->flushed);
10233 assert(lp->solved);
10235 }
10236
10237 lp->cutoffbound = cutoffbound;
10238
10239 return SCIP_OKAY;
10240}
10241
10242/** gets current primal feasibility tolerance of LP solver */
10244 SCIP_LP* lp /**< current LP data */
10245 )
10246{
10247 assert(lp != NULL);
10248
10249 return lp->feastol;
10250}
10251
10252/** sets primal feasibility tolerance of LP solver */
10254 SCIP_LP* lp, /**< current LP data */
10255 SCIP_SET* set, /**< global SCIP settings */
10256 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */
10257 )
10258{
10259 assert(lp != NULL);
10260 assert(newfeastol > 0.0);
10261
10262 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10263
10264 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10265 if( newfeastol < lp->feastol )
10266 {
10267 lp->solved = FALSE;
10269 }
10270
10271 lp->feastol = newfeastol;
10272}
10273
10274/** resets primal feasibility tolerance of LP solver
10275 *
10276 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10277 */
10279 SCIP_LP* lp, /**< current LP data */
10280 SCIP_SET* set /**< global SCIP settings */
10281 )
10282{
10283 assert(lp != NULL);
10284
10285 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10286
10287 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10289 else
10291}
10292
10293/** returns the name of the given LP algorithm */
10294static
10295const char* lpalgoName(
10296 SCIP_LPALGO lpalgo /**< LP algorithm */
10297 )
10298{
10299 switch( lpalgo )
10300 {
10302 return "primal simplex";
10304 return "dual simplex";
10306 return "barrier";
10308 return "barrier/crossover";
10309 default:
10310 SCIPerrorMessage("invalid LP algorithm\n");
10311 SCIPABORT();
10312 return "invalid"; /*lint !e527*/
10313 }
10314}
10315
10316/** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10317static
10319 SCIP_LP* lp, /**< current LP data */
10320 SCIP_SET* set, /**< global SCIP settings */
10321 SCIP_STAT* stat, /**< problem statistics */
10322 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10323 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10324 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10325 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10326 )
10327{
10328 SCIP_Real timedelta;
10329 SCIP_RETCODE retcode;
10330 int iterations;
10331
10332 assert(lp != NULL);
10333 assert(lp->flushed);
10334 assert(set != NULL);
10335 assert(stat != NULL);
10336 assert(lperror != NULL);
10337
10338 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",
10339 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10340
10341 *lperror = FALSE;
10342
10343#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10344 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10345 {
10346 char fname[SCIP_MAXSTRLEN];
10347 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10348 SCIP_CALL( SCIPlpWrite(lp, fname) );
10349 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10350 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10352 }
10353#endif
10354
10355 /* start timing */
10356 if( lp->diving || lp->probing )
10357 {
10358 if( lp->strongbranchprobing )
10360 else
10362
10363 timedelta = 0.0; /* unused for diving or probing */
10364 }
10365 else
10366 {
10368 timedelta = -SCIPclockGetTime(stat->primallptime);
10369 }
10370
10371 /* if this is a call to resolve an instable LP, collect time */
10372 if( instable )
10373 {
10375 }
10376
10377 /* call primal simplex */
10378 retcode = SCIPlpiSolvePrimal(lp->lpi);
10379 if( retcode == SCIP_LPERROR )
10380 {
10381 *lperror = TRUE;
10382 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10383 }
10384 else
10385 {
10386 SCIP_CALL( retcode );
10387 }
10389 lp->solisbasic = TRUE;
10390
10391 /* stop timing */
10392 if( lp->diving || lp->probing )
10393 {
10394 if( lp->strongbranchprobing )
10396 else
10398 }
10399 else
10400 {
10401 timedelta += SCIPclockGetTime(stat->primallptime);
10403 }
10404
10405 if ( instable )
10406 {
10408 }
10409
10410 /* count number of iterations */
10411 SCIPstatIncrement(stat, set, lpcount);
10412 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10413 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10414 {
10415 if( !lp->strongbranchprobing )
10416 {
10417 SCIPstatIncrement(stat, set, nlps);
10418 SCIPstatAdd( stat, set, nlpiterations, iterations );
10419 }
10420 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10421 {
10422 SCIPstatIncrement(stat, set, nprimalresolvelps );
10423 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10424 }
10425 if ( instable )
10426 {
10427 SCIPstatIncrement(stat, set, nresolveinstablelps);
10428 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10429 }
10430 if( lp->diving || lp->probing )
10431 {
10432 if( lp->strongbranchprobing )
10433 {
10434 SCIPstatIncrement(stat, set, nsbdivinglps);
10435 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10436 }
10437 else
10438 {
10439 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10440 SCIPstatIncrement(stat, set, ndivinglps);
10441 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10442 }
10443 }
10444 else
10445 {
10446 SCIPstatIncrement(stat, set, nprimallps);
10447 SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10448 }
10449 }
10450 else
10451 {
10452 if ( ! lp->diving && ! lp->probing )
10453 {
10454 SCIPstatIncrement(stat, set, nprimalzeroitlps);
10455 SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10456 }
10457
10458 if ( keepsol && !(*lperror) )
10459 {
10460 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10461 if( lp->validsollp == stat->lpcount-1 )
10462 lp->validsollp = stat->lpcount;
10463 if( lp->validfarkaslp == stat->lpcount-1 )
10464 lp->validfarkaslp = stat->lpcount;
10465 }
10466 }
10467
10468 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10469 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10470
10471 return SCIP_OKAY;
10472}
10473
10474/** calls LPI to perform dual simplex, measures time and counts iterations */
10475static
10477 SCIP_LP* lp, /**< current LP data */
10478 SCIP_SET* set, /**< global SCIP settings */
10479 SCIP_STAT* stat, /**< problem statistics */
10480 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10481 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10482 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10483 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10484 )
10485{
10486 SCIP_Real timedelta;
10487 SCIP_RETCODE retcode;
10488 int iterations;
10489
10490 assert(lp != NULL);
10491 assert(lp->flushed);
10492 assert(set != NULL);
10493 assert(stat != NULL);
10494 assert(lperror != NULL);
10495
10496 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",
10497 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10498
10499 *lperror = FALSE;
10500
10501#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10502 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10503 {
10504 char fname[SCIP_MAXSTRLEN];
10505 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10506 SCIP_CALL( SCIPlpWrite(lp, fname) );
10507 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10508 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10510 }
10511#endif
10512
10513 /* start timing */
10514 if( lp->diving || lp->probing )
10515 {
10516 if( lp->strongbranchprobing )
10518 else
10520
10521 timedelta = 0.0; /* unused for diving or probing */
10522 }
10523 else
10524 {
10526 timedelta = -SCIPclockGetTime(stat->duallptime);
10527 }
10528
10529 /* if this is a call to resolve an instable LP, collect time */
10530 if ( instable )
10531 {
10533 }
10534
10535 /* call dual simplex */
10536 retcode = SCIPlpiSolveDual(lp->lpi);
10537 if( retcode == SCIP_LPERROR )
10538 {
10539 *lperror = TRUE;
10540 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10541 }
10542 else
10543 {
10544 SCIP_CALL( retcode );
10545 }
10547 lp->solisbasic = TRUE;
10548
10549 /* stop timing */
10550 if( lp->diving || lp->probing )
10551 {
10552 if( lp->strongbranchprobing )
10554 else
10556 }
10557 else
10558 {
10559 timedelta += SCIPclockGetTime(stat->duallptime);
10561 }
10562
10563 if ( instable )
10564 {
10566 }
10567
10568 /* count number of iterations */
10569 SCIPstatIncrement(stat, set, lpcount);
10570 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10571 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10572 {
10573 if( !lp->strongbranchprobing )
10574 {
10575 SCIPstatIncrement(stat, set, nlps);
10576 SCIPstatAdd(stat, set, nlpiterations, iterations);
10577 }
10578 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10579 {
10580 SCIPstatIncrement(stat, set, ndualresolvelps);
10581 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10582 }
10583 if ( instable )
10584 {
10585 SCIPstatIncrement(stat, set, nresolveinstablelps);
10586 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10587 }
10588 if( lp->diving || lp->probing )
10589 {
10590 if( lp->strongbranchprobing )
10591 {
10592 SCIPstatIncrement(stat, set, nsbdivinglps);
10593 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10594 }
10595 else
10596 {
10597 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10598 SCIPstatIncrement(stat, set, ndivinglps);
10599 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10600 }
10601 }
10602 else
10603 {
10604 SCIPstatIncrement(stat, set, nduallps);
10605 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10606 }
10607 }
10608 else
10609 {
10610 if ( ! lp->diving && ! lp->probing )
10611 {
10612 SCIPstatIncrement(stat, set, ndualzeroitlps);
10613 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10614 }
10615
10616 if( keepsol && !(*lperror) )
10617 {
10618 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10619 if( lp->validsollp == stat->lpcount-1 )
10620 lp->validsollp = stat->lpcount;
10621 if( lp->validfarkaslp == stat->lpcount-1 )
10622 lp->validfarkaslp = stat->lpcount;
10623 }
10624 }
10625
10626 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10627 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10628
10629 return SCIP_OKAY;
10630}
10631
10632/** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10633 *
10634 * We follow the approach of the following paper to find a lexicographically minimal optimal
10635 * solution:
10636 *
10637 * Zanette, Fischetti, Balas@n
10638 * Can pure cutting plane algorithms work?@n
10639 * IPCO 2008, Bertinoro, Italy.
10640 *
10641 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10642 * heuristic, i.e., we limit the number of components which are minimized.
10643 *
10644 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10645 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10646 * variables) that have nonzero reduced cost. This fixes the objective function value, because only
10647 * pivots that will not change the objective are allowed afterwards.
10648 *
10649 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10650 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10651 * candidate is found, we set the objective to minimize this variable. We run the primal simplex
10652 * algorithm (since the objective is changed the solution is not dual feasible anymore; if
10653 * variables out of the basis have been fixed to their lower bound, the basis is also not primal
10654 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10655 * reduced cost. We then choose the next variable and iterate.
10656 *
10657 * We stop the process once we do not find candidates or have performed a maximum number of
10658 * iterations.
10659 *
10660 * @todo Does this really produce a lexicographically minimal solution?
10661 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10662 * guarantee that these variables will not be changed in later stages? We can fix these variables
10663 * to their lower bound, but this destroys the basis.
10664 * @todo Should we use lexicographical minimization in diving/probing or not?
10665 */
10666static
10668 SCIP_LP* lp, /**< current LP data */
10669 SCIP_SET* set, /**< global SCIP settings */
10670 SCIP_STAT* stat, /**< problem statistics */
10671 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10672 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10673 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10674 )
10675{
10676 SCIP_Real timedelta;
10677 SCIP_RETCODE retcode;
10678 int totalIterations;
10679 int lexIterations;
10680 int iterations;
10681 int rounds;
10682
10683 assert(lp != NULL);
10684 assert(lp->flushed);
10685 assert(set != NULL);
10686 assert(stat != NULL);
10687 assert(lperror != NULL);
10688
10689 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",
10690 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10691
10692 *lperror = FALSE;
10693
10694 /* start timing */
10695 if( lp->diving || lp->probing )
10696 {
10697 if( lp->strongbranchprobing )
10699 else
10701
10702 timedelta = 0.0; /* unused for diving or probing */
10703 }
10704 else
10705 {
10707 timedelta = -SCIPclockGetTime(stat->duallptime);
10708 }
10709
10710 /* call dual simplex for first lp */
10711 retcode = SCIPlpiSolveDual(lp->lpi);
10712 if( retcode == SCIP_LPERROR )
10713 {
10714 *lperror = TRUE;
10715 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10716 }
10717 else
10718 {
10719 SCIP_CALL( retcode );
10720 }
10721 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10722 totalIterations = iterations;
10723
10724 /* stop timing */
10725 if( lp->diving || lp->probing )
10726 {
10727 if( lp->strongbranchprobing )
10729 else
10731 }
10732 else
10733 {
10734 timedelta += SCIPclockGetTime(stat->duallptime);
10736 }
10737
10738 /* count number of iterations */
10739 SCIPstatIncrement(stat, set, lpcount);
10740 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10741 {
10742 if( lp->strongbranchprobing )
10743 {
10744 SCIPstatAdd(stat, set, nlpiterations, iterations);
10745 }
10746 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10747 {
10748 SCIPstatIncrement(stat, set, ndualresolvelps);
10749 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10750 }
10751 if( lp->diving || lp->probing )
10752 {
10753 if( lp->strongbranchprobing )
10754 {
10755 SCIPstatIncrement(stat, set, nsbdivinglps);
10756 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10757 }
10758 else
10759 {
10760 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10761 SCIPstatIncrement(stat, set, ndivinglps);
10762 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10763 }
10764 }
10765 else
10766 {
10767 SCIPstatIncrement(stat, set, nduallps);
10768 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10769 }
10770 }
10771 else
10772 {
10773 if ( ! lp->diving && ! lp->probing )
10774 {
10775 SCIPstatIncrement(stat, set, ndualzeroitlps);
10776 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10777 }
10778 }
10779 lexIterations = 0;
10780
10781 /* search for lexicographically minimal optimal solution */
10782 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10783 {
10785 SCIP_Real* dualsol;
10786 SCIP_Real* redcost;
10787 int* cstat;
10788 int* rstat;
10790 SCIP_Real* newlb;
10791 SCIP_Real* newub;
10792 SCIP_Real* newlhs;
10793 SCIP_Real* newrhs;
10794 SCIP_Real* oldlb;
10795 SCIP_Real* oldub;
10796 SCIP_Real* oldlhs;
10797 SCIP_Real* oldrhs;
10799 SCIP_Bool* fixedc;
10800 SCIP_Bool* fixedr;
10801 int* indcol;
10802 int* indrow;
10803 int* indallcol;
10804 int* indallrow;
10805 SCIP_Bool chooseBasic;
10806 SCIP_Bool success;
10807 int nDualDeg;
10808 int r, c;
10809 int cntcol;
10810 int cntrow;
10811 int nruns;
10812 int pos;
10813
10814 chooseBasic = set->lp_lexdualbasic;
10815
10816 /* start timing */
10818
10819 /* get all solution information */
10820 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10821 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10822 if( chooseBasic )
10823 {
10825 }
10826 else
10827 primsol = NULL;
10828
10829 /* get basic and nonbasic information */
10832
10833 /* save bounds, lhs/rhs, and objective */
10839 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10840 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10841 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10842
10843 /* get storage for several arrays */
10847
10851
10852 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10853 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10854
10857
10858 /* initialize: set objective to 0, get fixed variables */
10860 for( c = 0; c < lp->nlpicols; ++c )
10861 {
10862 newobj[c] = 0.0;
10863 indallcol[c] = c;
10864 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10865 fixedc[c] = TRUE;
10866 else
10867 fixedc[c] = FALSE;
10868 }
10869
10870 /* initialize: get fixed slack variables */
10871 for( r = 0; r < lp->nlpirows; ++r )
10872 {
10873 indallrow[r] = r;
10874 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10875 fixedr[r] = TRUE;
10876 else
10877 fixedr[r] = FALSE;
10878 }
10879
10880#ifdef DEBUG_LEXDUAL
10881 {
10882 int j;
10883
10884 if( !chooseBasic )
10885 {
10886 assert(primsol == NULL);
10888 }
10889 assert(primsol != NULL);
10891 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10892
10893 for( j = 0; j < lp->nlpicols; ++j )
10894 {
10895 if( fixedc[j] )
10896 {
10897 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10898 }
10899 else
10900 {
10901 char type;
10902 switch( (SCIP_BASESTAT) cstat[j] )
10903 {
10905 type = 'l';
10906 break;
10908 type = 'u';
10909 break;
10910 case SCIP_BASESTAT_ZERO:
10911 type = 'z';
10912 break;
10914 type = 'b';
10915 break;
10916 default:
10917 type = '?';
10918 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10919 SCIPABORT();
10920 }
10921 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10922 }
10923 }
10924 SCIPsetDebugMsg(set, "\n\n");
10925
10926 if( !chooseBasic )
10927 {
10929 assert(primsol == NULL);
10930 }
10931 }
10932#endif
10933
10934 /* disable objective limit */
10936 assert(success);
10937
10938 /* perform lexicographic rounds */
10939 pos = -1;
10940 nruns = 0;
10941 rounds = 0;
10942 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10943 do
10944 {
10945 int oldpos;
10946
10947 /* get current solution */
10948 if( chooseBasic )
10949 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10950 else
10951 {
10952 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10953 assert(primsol == NULL);
10954 }
10955
10956 /* get current basis */
10957 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10958
10959 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10960 nDualDeg = 0;
10961 cntcol = 0;
10962 oldpos = pos;
10963 pos = -1;
10964 for( c = 0; c < lp->nlpicols; ++c )
10965 {
10966 if( !fixedc[c] )
10967 {
10968 /* check whether variable is in basis */
10969 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10970 {
10971 /* store first candidate */
10972 if( pos == -1 && c > oldpos )
10973 {
10974 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10975 pos = c;
10976 }
10977 }
10978 else
10979 {
10980 /* reduced cost == 0 -> possible candidate */
10981 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10982 {
10983 ++nDualDeg;
10984 /* only if we have not yet found a candidate */
10985 if( pos == -1 && c > oldpos )
10986 {
10987 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10988 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10989 {
10990 newlb[cntcol] = oldlb[c];
10991 newub[cntcol] = oldlb[c];
10992 indcol[cntcol++] = c;
10993 fixedc[c] = TRUE;
10994 }
10995 else /* found a non-fixed candidate */
10996 {
10997 if( !chooseBasic )
10998 pos = c;
10999 }
11000 }
11001 }
11002 else
11003 {
11004 /* nonzero reduced cost -> variable can be fixed */
11005 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11006 {
11007 newlb[cntcol] = oldlb[c];
11008 newub[cntcol] = oldlb[c];
11009 }
11010 else
11011 {
11012 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11013 {
11014 newlb[cntcol] = oldub[c];
11015 newub[cntcol] = oldub[c];
11016 }
11017 else
11018 {
11020 newlb[cntcol] = 0.0;
11021 newub[cntcol] = 0.0;
11022 }
11023 }
11024 indcol[cntcol++] = c;
11025 fixedc[c] = TRUE;
11026 }
11027 }
11028 }
11029 }
11030
11031 /* check rows */
11032 cntrow = 0;
11033 for( r = 0; r < lp->nlpirows; ++r )
11034 {
11035 if( !fixedr[r] )
11036 {
11037 /* consider only nonbasic rows */
11038 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11039 {
11041 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11042 ++nDualDeg;
11043 else
11044 {
11045 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11046 {
11047 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11048 newlhs[cntrow] = oldlhs[r];
11049 newrhs[cntrow] = oldlhs[r];
11050 }
11051 else
11052 {
11053 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11054 newlhs[cntrow] = oldrhs[r];
11055 newrhs[cntrow] = oldrhs[r];
11056 }
11057 indrow[cntrow++] = r;
11058 fixedr[r] = TRUE;
11059 }
11060 }
11061 }
11062 }
11063
11064 if( nDualDeg > 0 && pos >= 0 )
11065 {
11066 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11067
11068 /* change objective */
11069 if( nruns == 0 )
11070 {
11071 /* set objective to appropriate unit vector for first run */
11072 newobj[pos] = 1.0;
11073 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11074 }
11075 else
11076 {
11077 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11078 SCIP_Real obj = 1.0;
11079 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11080 }
11081
11082 /* fix variables */
11083 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11084 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11085
11086 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11087 retcode = SCIPlpiSolvePrimal(lp->lpi);
11088 if( retcode == SCIP_LPERROR )
11089 {
11090 *lperror = TRUE;
11091 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11092 }
11093 else
11094 {
11095 SCIP_CALL( retcode );
11096 }
11097 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11098 lexIterations += iterations;
11099
11100 if( iterations > 0 )
11101 {
11102#ifdef DEBUG_LEXDUAL
11103 int j;
11104
11105 if( !chooseBasic )
11106 {
11107 assert(primsol == NULL);
11109 }
11110 assert(primsol != NULL);
11112
11113 for( j = 0; j < lp->nlpicols; ++j )
11114 {
11115 if( fixedc[j] )
11116 {
11117 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11118 }
11119 else
11120 {
11121 char cstart = '[';
11122 char cend = ']';
11123 char type;
11124
11125 if(j == pos)
11126 {
11127 cstart = '*';
11128 cend = '*';
11129 }
11130
11131 switch( (SCIP_BASESTAT) cstat[j] )
11132 {
11134 type = 'l';
11135 break;
11137 type = 'u';
11138 break;
11139 case SCIP_BASESTAT_ZERO:
11140 type = 'z';
11141 break;
11143 type = 'b';
11144 break;
11145 default:
11146 type = '?';
11147 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11148 SCIPABORT();
11149 }
11150 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11151 }
11152 }
11153 SCIPsetDebugMsg(set, "\n\n");
11154
11155 if( !chooseBasic )
11156 {
11158 assert(primsol == NULL);
11159 }
11160#endif
11161
11162 /* count only as round if iterations have been performed */
11163 ++rounds;
11164 }
11165
11166 ++nruns;
11167 }
11168 }
11169 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11170
11171 /* reset bounds, lhs/rhs, and obj */
11172 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11173 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11174 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11175
11176 /* resolve to update solvers internal data structures - should only produce few pivots */
11177 retcode = SCIPlpiSolveDual(lp->lpi);
11178 if( retcode == SCIP_LPERROR )
11179 {
11180 *lperror = TRUE;
11181 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11182 }
11183 else
11184 {
11185 SCIP_CALL( retcode );
11186 }
11188
11189 /* reset objective limit */
11190 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, lp->lpiobjlim, &success) );
11191 assert(success);
11192
11193 /* add LP iterations */
11194 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11195 lexIterations += iterations;
11196
11197 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11198
11199 /* count number of iterations */
11200 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11201 SCIPstatIncrement(stat, set, nlps);
11202
11203 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11204 {
11205 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11206 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11207 {
11208 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11209 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11210 }
11211 SCIPstatIncrement(stat, set, nlexduallps);
11212 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11213
11214 totalIterations += lexIterations;
11215 }
11216
11217 /* free space */
11219
11220 SCIPsetFreeBufferArray(set, &fixedr);
11221 SCIPsetFreeBufferArray(set, &fixedc);
11222
11223 SCIPsetFreeBufferArray(set, &indallrow);
11224 SCIPsetFreeBufferArray(set, &indallcol);
11225
11226 SCIPsetFreeBufferArray(set, &indrow);
11227 SCIPsetFreeBufferArray(set, &newrhs);
11228 SCIPsetFreeBufferArray(set, &newlhs);
11229
11230 SCIPsetFreeBufferArray(set, &indcol);
11231 SCIPsetFreeBufferArray(set, &newub);
11232 SCIPsetFreeBufferArray(set, &newlb);
11233
11235 SCIPsetFreeBufferArray(set, &oldrhs);
11236 SCIPsetFreeBufferArray(set, &oldlhs);
11237 SCIPsetFreeBufferArray(set, &oldub);
11238 SCIPsetFreeBufferArray(set, &oldlb);
11239
11240 SCIPsetFreeBufferArray(set, &rstat);
11241 SCIPsetFreeBufferArray(set, &cstat);
11242
11243 SCIPsetFreeBufferArray(set, &redcost);
11244 SCIPsetFreeBufferArray(set, &dualsol);
11245 if( chooseBasic )
11247
11248 /* stop timing */
11250
11251 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11252 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11253 }
11255 lp->solisbasic = TRUE;
11256
11257 if( totalIterations > 0 && !lp->strongbranchprobing )
11258 SCIPstatIncrement(stat, set, nlps);
11259 else
11260 {
11261 if( keepsol && !(*lperror) )
11262 {
11263 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11264 if( lp->validsollp == stat->lpcount-1 )
11265 lp->validsollp = stat->lpcount;
11266 if( lp->validfarkaslp == stat->lpcount-1 )
11267 lp->validfarkaslp = stat->lpcount;
11268 }
11269 }
11270
11271 return SCIP_OKAY;
11272}
11273
11274/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11275static
11277 SCIP_LP* lp, /**< current LP data */
11278 SCIP_SET* set, /**< global SCIP settings */
11279 SCIP_STAT* stat, /**< problem statistics */
11280 SCIP_Bool crossover, /**< should crossover be performed? */
11281 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11282 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11283 )
11284{
11285 SCIP_Real timedelta;
11286 SCIP_RETCODE retcode;
11287 int iterations;
11288
11289 assert(lp != NULL);
11290 assert(lp->flushed);
11291 assert(set != NULL);
11292 assert(stat != NULL);
11293 assert(lperror != NULL);
11294
11295 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",
11296 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11297 stat->nbarrierlps, stat->ndivinglps);
11298
11299 *lperror = FALSE;
11300
11301#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11302 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11303 {
11304 char fname[SCIP_MAXSTRLEN];
11305 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11306 SCIP_CALL( SCIPlpWrite(lp, fname) );
11307 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11308 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11310 }
11311#endif
11312
11313 /* start timing */
11314 if( lp->diving || lp->probing )
11315 {
11316 if( lp->strongbranchprobing )
11318 else
11320
11321 timedelta = 0.0; /* unused for diving or probing */
11322 }
11323 else
11324 {
11326 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11327 }
11328
11329 /* call barrier algorithm */
11330 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11331 if( retcode == SCIP_LPERROR )
11332 {
11333 *lperror = TRUE;
11334 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11335 }
11336 else
11337 {
11338 SCIP_CALL( retcode );
11339 }
11341 lp->solisbasic = crossover;
11342
11343 /* stop timing */
11344 if( lp->diving || lp->probing )
11345 {
11346 if( lp->strongbranchprobing )
11348 else
11350 }
11351 else
11352 {
11354 timedelta += SCIPclockGetTime(stat->barrierlptime);
11355 }
11356
11357 /* count number of iterations */
11358 SCIPstatIncrement(stat, set, lpcount);
11359 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11360 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11361 {
11362 if( !lp->strongbranchprobing )
11363 {
11364 SCIPstatIncrement(stat, set, nlps);
11365 SCIPstatAdd(stat, set, nlpiterations, iterations);
11366 }
11367 if( lp->diving || lp->probing )
11368 {
11369 if( lp->strongbranchprobing )
11370 {
11371 SCIPstatIncrement(stat, set, nsbdivinglps);
11372 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11373 }
11374 else
11375 {
11376 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11377 SCIPstatIncrement(stat, set, ndivinglps);
11378 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11379 }
11380 }
11381 else
11382 {
11383 SCIPstatIncrement(stat, set, nbarrierlps);
11384 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11385 }
11386 }
11387 else
11388 {
11389 if ( ! lp->diving && ! lp->probing )
11390 {
11391 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11392 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11393 }
11394
11395 if( keepsol && !(*lperror) )
11396 {
11397 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11398 if( lp->validsollp == stat->lpcount-1 )
11399 lp->validsollp = stat->lpcount;
11400 if( lp->validfarkaslp == stat->lpcount-1 )
11401 lp->validfarkaslp = stat->lpcount;
11402 }
11403 }
11404
11405 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11406 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11407
11408 return SCIP_OKAY;
11409}
11410
11411/** solves the LP with the given algorithm */
11412static
11414 SCIP_LP* lp, /**< current LP data */
11415 SCIP_SET* set, /**< global SCIP settings */
11416 SCIP_STAT* stat, /**< problem statistics */
11417 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11418 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11419 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11420 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11421 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11422 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11423 )
11424{
11425 SCIP_Real lptimelimit;
11426 SCIP_Bool success;
11427
11428 assert(lp != NULL);
11429 assert(lp->flushed);
11430 assert(lperror != NULL);
11431
11432 /* check if a time limit is set, and set time limit for LP solver accordingly */
11433 lptimelimit = SCIPlpiInfinity(lp->lpi);
11434 if( set->istimelimitfinite )
11435 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11436
11437 success = FALSE;
11438 if( lptimelimit > 0.0 )
11439 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11440
11441 if( lptimelimit <= 0.0 || !success )
11442 {
11443 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11444 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11445 *timelimit = TRUE;
11446 return SCIP_OKAY;
11447 }
11448 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11449
11450 /* call appropriate LP algorithm */
11451 switch( lpalgo )
11452 {
11454 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11455 break;
11456
11458 /* run dual lexicographic simplex if required */
11459 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11460 {
11461 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11462 }
11463 else
11464 {
11465 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11466 }
11467 break;
11468
11470 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11471 break;
11472
11474 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11475 break;
11476
11477 default:
11478 SCIPerrorMessage("invalid LP algorithm\n");
11479 return SCIP_INVALIDDATA;
11480 }
11481
11482 if( !(*lperror) )
11483 {
11484 /* check for primal and dual feasibility */
11486
11487 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11488 }
11489
11490 return SCIP_OKAY;
11491}
11492
11493/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11494 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11495 */
11496#define MAXNUMTROUBLELPMSGS 10
11497
11498/** prints message about numerical trouble
11499 *
11500 * If message has verblevel at most high and display/verblevel is not full,
11501 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11502 * were printed before in the current run.
11503 */
11504static
11506 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11507 SCIP_SET* set, /**< global SCIP settings */
11508 SCIP_STAT* stat, /**< problem statistics */
11509 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11510 const char* formatstr, /**< message format string */
11511 ... /**< arguments to format string */
11512 )
11513{
11514 va_list ap;
11515
11516 assert(verblevel > SCIP_VERBLEVEL_NONE);
11517 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11518 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11519
11520 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11521 {
11522 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11523 {
11524 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11526 return;
11527
11528 /* increase count on messages with verblevel high */
11529 ++stat->nnumtroublelpmsgs ;
11530 }
11531
11532 /* if messages wouldn't be printed, then return already */
11533 if( verblevel > set->disp_verblevel )
11534 return;
11535 }
11536
11537 /* print common begin of message */
11538 SCIPmessagePrintInfo(messagehdlr,
11539 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11540 stat->nnodes, stat->nlps);
11541
11542 /* print individual part of message */
11543 va_start(ap, formatstr); /*lint !e838*/
11544 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11545 va_end(ap);
11546
11547 /* warn that further messages will be suppressed */
11548 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11549 {
11550 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11551 }
11552
11553 /* print closing new-line */
11554 SCIPmessagePrintInfo(messagehdlr, "\n");
11555}
11556
11557static
11559 SCIP_LP* lp, /**< current LP data */
11560 SCIP_SET* set, /**< global SCIP settings */
11561 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11562 SCIP_STAT* stat, /**< problem statistics */
11563 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11564 SCIP_Bool* success /**< was instability successfully ignored */
11565 )
11566{
11567 assert(lp != NULL);
11568 assert(set != NULL);
11569
11570 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11571
11572 if( *success )
11573 {
11574 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11575 if( !set->lp_checkdualfeas )
11576 lp->dualfeasible = TRUE;
11577 if( !set->lp_checkprimfeas )
11578 lp->primalchecked = TRUE;
11579 }
11580
11581 return SCIP_OKAY;
11582}
11583
11584#define FEASTOLTIGHTFAC 0.001
11585/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11586static
11588 SCIP_LP* lp, /**< current LP data */
11589 SCIP_SET* set, /**< global SCIP settings */
11590 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11591 SCIP_STAT* stat, /**< problem statistics */
11592 SCIP_PROB* prob, /**< problem data */
11593 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11594 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11595 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11596 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11597 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11598 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11599 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11600 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11601 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11602 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11603 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11604 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11605 )
11606{
11607 SCIP_Bool success;
11608 SCIP_Bool success2;
11609 SCIP_Bool success3;
11610 SCIP_Bool simplex;
11611 SCIP_Bool itlimishard;
11612 SCIP_Bool usepolishing;
11613
11614 assert(lp != NULL);
11615 assert(lp->flushed);
11616 assert(set != NULL);
11617 assert(stat != NULL);
11618 assert(lperror != NULL);
11619 assert(timelimit != NULL);
11620
11621 *lperror = FALSE;
11622
11623 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11624 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11625 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11626 * SCIP_LP such that we can return a primal ray
11627 */
11628 if( lp->looseobjvalinf > 0 )
11629 {
11630 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11631 return SCIP_ERROR;
11632 }
11633
11634 /* check, whether we solve with a simplex algorithm */
11635 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11636
11637 /* check whether the iteration limit is a hard one */
11638 itlimishard = (itlim == harditlim);
11639
11640 /* check whether solution polishing should be used */
11641 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11642 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11643 {
11644 usepolishing = TRUE;
11645 if( lp->updateintegrality )
11646 {
11648 }
11649 }
11650 else
11651 usepolishing = FALSE;
11652
11653 /* solve with given settings (usually fast but imprecise) */
11655 {
11656 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11657 }
11658 else
11659 {
11660 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11661 }
11662 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11663 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11665 &success) );
11666 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11667 : SCIPsetBarrierconvtol(set), &success) );
11668 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11669 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11670 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11671 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11672 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11673 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11674 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11675 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11676 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11677 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11678 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11679 SCIP_CALL( lpSetRandomseed(lp, (int) (SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed) % INT_MAX), &success) );
11680 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11681 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11682
11683 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11684
11685 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11686 * optimal without preforming scaling/change tolerances/presolving */
11687 resolve = FALSE;
11688
11689 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11690 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11691 return SCIP_OKAY;
11692
11693 if( !set->lp_checkstability )
11694 {
11695 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11696
11697 if( success )
11698 return SCIP_OKAY;
11699 }
11700
11701 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11702 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11703 */
11704
11705 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11706 * do this only if the iteration limit was not exceeded in the last LP solving call
11707 */
11708 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11709 {
11710 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11711 if( success )
11712 {
11713 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11714 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11715
11716 /* check for stability */
11717 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11718 return SCIP_OKAY;
11719
11720 if( !set->lp_checkstability )
11721 {
11722 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11723
11724 if( success )
11725 return SCIP_OKAY;
11726 }
11727 }
11728 }
11729
11730 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11731 * and go directly to solving the LP from scratch
11732 */
11733 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11734 {
11735 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11736 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11737 if( success )
11738 {
11739 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11740 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11741 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11742
11743 /* check for stability */
11744 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11745 return SCIP_OKAY;
11746
11747 if( !set->lp_checkstability )
11748 {
11749 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11750
11751 if( success )
11752 return SCIP_OKAY;
11753 }
11754
11755 /* reset scaling */
11756 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11757 assert(success);
11758 }
11759 }
11760
11761 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11762 * and go directly to solving the LP from scratch */
11763 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11764 {
11765 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11766 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11767 if( success )
11768 {
11769 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11770 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11771 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11772
11773 /* check for stability */
11774 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11775 return SCIP_OKAY;
11776
11777 if( !set->lp_checkstability )
11778 {
11779 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11780
11781 if( success )
11782 return SCIP_OKAY;
11783 }
11784
11785 /* reset presolving */
11786 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11787 assert(success);
11788 }
11789 }
11790
11791 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11792 * do this only if the iteration limit was not exceeded in the last LP solving call
11793 */
11794 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11795 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11796 {
11797 success = FALSE;
11798 if( !tightprimfeastol )
11799 {
11800 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11801 }
11802
11803 success2 = FALSE;
11804 if( !tightdualfeastol )
11805 {
11807 }
11808
11809 success3 = FALSE;
11810 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11811 {
11813 }
11814
11815 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11816 if( success || success2 || success3 )
11817 {
11818 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11819 lpalgoName(lpalgo));
11820 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11821
11822 /* check for stability */
11823 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11824 return SCIP_OKAY;
11825
11826 if( !set->lp_checkstability )
11827 {
11828 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11829
11830 if( success )
11831 return SCIP_OKAY;
11832 }
11833
11834 /* reset feasibility tolerance */
11835 if( !tightprimfeastol )
11836 {
11837 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11838 }
11839 if( !tightdualfeastol )
11840 {
11842 }
11843 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11844 {
11846 }
11847 }
11848 }
11849
11850 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11851 * the given iteration limit might be a soft one to restrict resolving calls only */
11852 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11853
11854 /* if not already done, solve again from scratch */
11855 if( !fromscratch && simplex )
11856 {
11857 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11858 if( success )
11859 {
11860 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11861 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11862
11863 /* check for stability */
11864 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11865 return SCIP_OKAY;
11866
11867 if( !set->lp_checkstability )
11868 {
11869 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11870
11871 if( success )
11872 return SCIP_OKAY;
11873 }
11874 }
11875 }
11876
11877 /* solve again, use other simplex this time */
11878 if( simplex )
11879 {
11881 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11882 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11883
11884 /* check for stability */
11885 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11886 return SCIP_OKAY;
11887
11888 if( !set->lp_checkstability )
11889 {
11890 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11891
11892 if( success )
11893 return SCIP_OKAY;
11894 }
11895
11896 /* solve again with opposite scaling and other simplex */
11897 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11898 if( success )
11899 {
11900 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11901 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11902 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11903
11904 /* check for stability */
11905 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11906 return SCIP_OKAY;
11907
11908 if( !set->lp_checkstability )
11909 {
11910 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11911
11912 if( success )
11913 return SCIP_OKAY;
11914 }
11915
11916 /* reset scaling */
11917 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11918 assert(success);
11919 }
11920
11921 /* solve again with opposite presolving and other simplex */
11922 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11923 if( success )
11924 {
11925 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11926 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11927 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11928
11929 /* check for stability */
11930 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11931 return SCIP_OKAY;
11932
11933 if( !set->lp_checkstability )
11934 {
11935 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11936
11937 if( success )
11938 return SCIP_OKAY;
11939 }
11940
11941 /* reset presolving */
11942 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11943 assert(success);
11944 }
11945
11946 /* solve again with tighter feasibility tolerance, use other simplex this time */
11947 if( !tightprimfeastol || !tightdualfeastol )
11948 {
11949 success = FALSE;
11950 if( !tightprimfeastol )
11951 {
11952 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11953 }
11954
11955 success2 = FALSE;
11956 if( !tightdualfeastol )
11957 {
11959 }
11960
11961 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11962 if( success || success2 )
11963 {
11964 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11965 lpalgoName(lpalgo));
11966 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11967
11968 /* check for stability */
11969 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11970 return SCIP_OKAY;
11971
11972 if( !set->lp_checkstability )
11973 {
11974 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11975
11976 if( success )
11977 return SCIP_OKAY;
11978 }
11979
11980 /* reset feasibility tolerance */
11981 if( !tightprimfeastol )
11982 {
11983 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11984 }
11985 if( !tightdualfeastol )
11986 {
11988 }
11989 SCIP_UNUSED(success);
11990 }
11991 }
11992 }
11993
11994 /* nothing worked -- exit with an LPERROR */
11995 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11996 *lperror = TRUE;
11997
11998 return SCIP_OKAY;
11999}
12000
12001/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
12002static
12004 SCIP_LP* lp, /**< current LP data */
12005 SCIP_SET* set, /**< global SCIP settings */
12006 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
12007 )
12008{
12009 assert(lp != NULL);
12010 assert(set != NULL);
12011
12012 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 above SCIP's infinity value\n");
12017 lp->adjustlpval = TRUE;
12018 }
12020 }
12021 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12022 {
12023 if( !lp->adjustlpval && messagehdlr != NULL )
12024 {
12025 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12026 lp->adjustlpval = TRUE;
12027 }
12029 }
12030}
12031
12032/** solves the LP with the given algorithm and evaluates return status */
12033static
12035 SCIP_LP* lp, /**< current LP data */
12036 SCIP_SET* set, /**< global SCIP settings */
12037 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12038 SCIP_STAT* stat, /**< problem statistics */
12039 SCIP_PROB* prob, /**< problem data */
12040 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12041 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12042 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12043 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12044 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12045 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12046 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12047 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12048 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12049 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12050 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12051 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12052 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12053 )
12054{
12055 SCIP_Bool solvedprimal;
12056 SCIP_Bool solveddual;
12057 SCIP_Bool timelimit;
12058 int itlim;
12059
12060 assert(lp != NULL);
12061 assert(lp->flushed);
12062 assert(set != NULL);
12063 assert(stat != NULL);
12064 assert(lperror != NULL);
12065
12066 checkLinks(lp);
12067
12068 solvedprimal = FALSE;
12069 solveddual = FALSE;
12070 timelimit = FALSE;
12071
12072 /* select the basic iteration limit depending on whether this is a resolving call or not */
12073 itlim = ( resolve ? resolveitlim : harditlim );
12074
12075 SOLVEAGAIN:
12076 /* call simplex */
12077 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12078 scaling, keepsol, &timelimit, lperror) );
12079 resolve = FALSE; /* only the first solve should be counted as resolving call */
12080 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12081 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12082
12083 /* check, if an error occurred */
12084 if( *lperror )
12085 {
12086 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12087 lp->solved = FALSE;
12089 return SCIP_OKAY;
12090 }
12091
12092 /* check, if a time limit was exceeded */
12093 if( timelimit )
12094 {
12095 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12096 lp->solved = TRUE;
12099 return SCIP_OKAY;
12100 }
12101
12102 /* only one should return true */
12105
12106 /* evaluate solution status */
12107 if( SCIPlpiIsOptimal(lp->lpi) )
12108 {
12110 assert(lp->dualfeasible);
12112 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12113 adjustLPobjval(lp, set, messagehdlr);
12114
12116 {
12117 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12118 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12121 }
12122 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12123 * reached if the LP objective value is greater than the cutoff bound
12124 */
12127 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12128 }
12129 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12130 {
12131 assert(!lpCutoffDisabled(set, prob, lp));
12132
12133#ifndef NDEBUG
12134 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12135 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12136 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12137 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12138#endif
12139
12142 }
12143 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12144 {
12145 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12146 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12147 {
12149 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12150 goto SOLVEAGAIN;
12151 }
12154 }
12155 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12156 {
12157 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12158 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12159 {
12160 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12163 goto SOLVEAGAIN;
12164 }
12167 }
12168 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12169 {
12170 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12171
12172 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12173 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12174 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12175 adjustLPobjval(lp, set, NULL);
12176 else
12177 adjustLPobjval(lp, set, messagehdlr);
12178
12180 }
12181 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12182 {
12185 }
12186 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12187 {
12189 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
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 if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12196 {
12199 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12200 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12201 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12202 goto SOLVEAGAIN;
12203 }
12204 else
12205 {
12206 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12207 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12209 return SCIP_LPERROR;
12210 }
12211
12212 lp->solved = TRUE;
12213
12214 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12217
12218 return SCIP_OKAY;
12219}
12220
12221/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12222static
12224 SCIP_LP* lp, /**< current LP data */
12225 BMS_BLKMEM* blkmem, /**< block memory */
12226 SCIP_SET* set, /**< global SCIP settings */
12227 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12228 SCIP_STAT* stat, /**< problem statistics */
12229 SCIP_PROB* prob, /**< problem data */
12230 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12231 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12232 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12233 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12234 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12235 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12236 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12237 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12238 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12239 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12240 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12241 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12242 )
12243{
12244 SCIP_Bool resolve;
12245 char algo;
12246
12247 assert(lp != NULL);
12248 assert(set != NULL);
12249 assert(lperror != NULL);
12250
12251 /* flush changes to the LP solver */
12252 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12253 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12254
12255 /* select LP algorithm to apply */
12256 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12257 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12258
12259 switch( algo )
12260 {
12261 case 's':
12262 /* select simplex method */
12263 if( lp->dualfeasible || !lp->primalfeasible )
12264 {
12265 SCIPsetDebugMsg(set, "solving dual LP\n");
12266 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12267 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12268 }
12269 else
12270 {
12271 SCIPsetDebugMsg(set, "solving primal LP\n");
12272 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12273 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12274 }
12275 break;
12276
12277 case 'p':
12278 SCIPsetDebugMsg(set, "solving primal LP\n");
12279 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12280 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12281 break;
12282
12283 case 'd':
12284 SCIPsetDebugMsg(set, "solving dual LP\n");
12285 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12286 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12287 break;
12288
12289 case 'b':
12290 SCIPsetDebugMsg(set, "solving barrier LP\n");
12291 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12292 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12293 break;
12294
12295 case 'c':
12296 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12297 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12298 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12299 break;
12300
12301 default:
12302 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12304 }
12305 assert(!(*lperror) || !lp->solved);
12306
12307 return SCIP_OKAY;
12308}
12309
12310#ifndef NDEBUG
12311/** checks if the lazy bounds are valid */
12312static
12314 SCIP_LP* lp, /**< LP data */
12315 SCIP_SET* set /**< global SCIP settings */
12316 )
12317{
12318 SCIP_COL* col;
12319 int c;
12320
12321 assert(lp->flushed);
12322
12323 for( c = 0; c < lp->nlazycols; ++c )
12324 {
12325 col = lp->lazycols[c];
12326
12327 /* in case lazy bounds are given, check that the primal solution satisfies them */
12330 }
12331}
12332#else
12333#define checkLazyBounds(lp, set) /**/
12334#endif
12335
12336/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12337 * diving
12338 */
12339static
12341 SCIP_LP* lp, /**< LP data */
12342 SCIP_SET* set /**< global SCIP settings */
12343 )
12344{
12345 SCIP_COL* col;
12346 int c;
12347
12348 assert(lp->nlazycols > 0);
12349
12350 /* return, if we are in diving, and bounds were already applied
12351 * or if we are not in diving and bounds were not applied
12352 */
12353 if( lp->diving == lp->divinglazyapplied )
12354 return SCIP_OKAY;
12355
12356 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12357 lp->diving, lp->divinglazyapplied);
12358
12359 for( c = 0; c < lp->nlazycols; ++c )
12360 {
12361 col = lp->lazycols[c];
12362
12363 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12364 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12365 {
12366 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12367 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12368 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12369
12370 /* insert column in the chgcols list (if not already there) */
12371 SCIP_CALL( insertColChgcols(col, set, lp) );
12372
12373 /* mark bound change in the column */
12374 col->lbchanged = TRUE;
12375 }
12376
12377 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12378 if( !SCIPsetIsInfinity(set, col->lazyub) )
12379 {
12380 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12381 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12382 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12383
12384 /* insert column in the chgcols list (if not already there) */
12385 SCIP_CALL( insertColChgcols(col, set, lp) );
12386
12387 /* mark bound change in the column */
12388 col->ubchanged = TRUE;
12389 }
12390 }
12391
12392 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12393 * if not, we just removed them
12394 */
12395 lp->divinglazyapplied = lp->diving;
12396
12397 return SCIP_OKAY;
12398}
12399
12400/** returns the iteration limit for an LP resolving call */
12401static
12403 SCIP_SET* set, /**< global SCIP settings */
12404 SCIP_STAT* stat, /**< dynamic problem statistics */
12405 int itlim /**< hard iteration limit */
12406 )
12407{
12408 /* no limit set or average not yet reliable */
12409 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12410 return itlim;
12411 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12412 if( itlim == -1 )
12413 itlim = INT_MAX;
12414 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12415 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12416 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12417}
12418
12419
12420
12421/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12423 SCIP_LP* lp, /**< LP data */
12424 SCIP_SET* set, /**< global SCIP settings */
12425 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12426 BMS_BLKMEM* blkmem, /**< block memory buffers */
12427 SCIP_STAT* stat, /**< problem statistics */
12428 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12429 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12430 SCIP_PROB* prob, /**< problem data */
12431 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12432 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12433 * (limit is computed within the method w.r.t. the average LP iterations) */
12434 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12435 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12436 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
12437 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12438 )
12439{
12440 SCIP_RETCODE retcode;
12441 SCIP_Bool needprimalray;
12442 SCIP_Bool needdualray;
12443 int harditlim;
12444 int resolveitlim;
12445
12446 assert(lp != NULL);
12447 assert(prob != NULL);
12448 assert(prob->nvars >= lp->ncols);
12449 assert(lperror != NULL);
12450
12451 retcode = SCIP_OKAY;
12452 *lperror = FALSE;
12453
12454 if( lp->flushed && lp->solved )
12455 {
12456 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12457 return SCIP_OKAY;
12458 }
12459
12460 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12461 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12462
12463 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12464 needprimalray = TRUE;
12465 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12466 || (set->conf_enable && set->conf_useinflp != 'o'));
12467
12468 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12469 harditlim = (int) MIN(itlim, INT_MAX);
12470 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12471 assert(harditlim == -1 || (resolveitlim <= harditlim));
12472
12473 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12474 * or removed from the LP (diving was ended)
12475 */
12476 if( lp->nlazycols > 0 )
12477 {
12478 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12479 * first resolve LP?
12480 */
12482 assert(lp->diving == lp->divinglazyapplied);
12483 }
12484
12485 /* flush changes to the LP solver */
12486 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12487 assert(lp->flushed);
12488
12489 /* 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
12490 * to run again anyway, since there seems to be some time left / the time limit was increased
12491 */
12492 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12493 {
12494 SCIP_Bool* primalfeaspointer;
12495 SCIP_Bool* dualfeaspointer;
12496 SCIP_Bool primalfeasible;
12497 SCIP_Bool dualfeasible;
12498 SCIP_Bool farkasvalid;
12499 SCIP_Bool rayfeasible;
12500 SCIP_Bool tightprimfeastol;
12501 SCIP_Bool tightdualfeastol;
12502 SCIP_Bool fromscratch;
12503 SCIP_Bool wasfromscratch;
12504 int scaling;
12505 SCIP_Longint oldnlps;
12506 int fastmip;
12507
12508 /* set initial LP solver settings */
12509 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12510 tightprimfeastol = FALSE;
12511 tightdualfeastol = FALSE;
12512 fromscratch = FALSE;
12513 primalfeasible = FALSE;
12514 dualfeasible = FALSE;
12515 wasfromscratch = (stat->nlps == 0);
12516 scaling = set->lp_scaling;
12517
12518 SOLVEAGAIN:
12519 /* solve the LP */
12520 oldnlps = stat->nlps;
12521 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12522 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12523 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12524 assert(!(*lperror) || !lp->solved);
12525
12526 /* check for error */
12527 if( *lperror )
12528 {
12529 retcode = SCIP_OKAY;
12530 goto TERMINATE;
12531 }
12532
12533 /* evaluate solution status */
12534 switch( SCIPlpGetSolstat(lp) )
12535 {
12537 /* get LP solution and possibly check the solution's feasibility again */
12538 if( set->lp_checkprimfeas )
12539 {
12540 primalfeaspointer = &primalfeasible;
12541 lp->primalchecked = TRUE;
12542 }
12543 else
12544 {
12545 /* believe in the primal feasibility of the LP solution */
12546 primalfeasible = TRUE;
12547 primalfeaspointer = NULL;
12548 lp->primalchecked = FALSE;
12549 }
12550 if( set->lp_checkdualfeas )
12551 {
12552 dualfeaspointer = &dualfeasible;
12553 lp->dualchecked = TRUE;
12554 }
12555 else
12556 {
12557 /* believe in the dual feasibility of the LP solution */
12558 dualfeasible = TRUE;
12559 dualfeaspointer = NULL;
12560 lp->dualchecked = FALSE;
12561 }
12562
12563 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12564
12565 /* in debug mode, check that lazy bounds (if present) are not violated */
12566 checkLazyBounds(lp, set);
12567
12568 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12569 {
12570 /* update ages and remove obsolete columns and rows from LP */
12571 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12572 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12573 {
12574 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12575 }
12576
12577 if( !lp->solved )
12578 {
12579 /* resolve LP after removing obsolete columns and rows */
12580 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12581 aging = FALSE; /* to prevent infinite loops */
12582 goto SOLVEAGAIN;
12583 }
12584 }
12585 if( !primalfeasible || !dualfeasible )
12586 {
12588
12589 if( (fastmip > 0) && simplex )
12590 {
12591 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12592 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12593 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12594 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12595 fastmip = 0;
12596 goto SOLVEAGAIN;
12597 }
12598 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12599 {
12600 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12601 * tolerance
12602 */
12603 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12604 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12605 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12606 tightprimfeastol = tightprimfeastol || !primalfeasible;
12607 tightdualfeastol = tightdualfeastol || !dualfeasible;
12608 goto SOLVEAGAIN;
12609 }
12610 else if( !fromscratch && !wasfromscratch && simplex )
12611 {
12612 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12613 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12614 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12615 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12616 fromscratch = TRUE;
12617 goto SOLVEAGAIN;
12618 }
12619 else
12620 {
12621 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12622 lp->solved = FALSE;
12624 *lperror = TRUE;
12625 }
12626 }
12627 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12628 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12629 lp->lpsolstat, lp->cutoffbound);
12630 break;
12631
12633 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12634 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->lp_alwaysgetduals || set->misc_exactsolve )
12635 {
12636 if( SCIPlpiHasDualRay(lp->lpi) )
12637 {
12638 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12639 }
12640 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12641 * with the primal simplex due to numerical problems) - treat this case like an LP error
12642 */
12643 else
12644 {
12645 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12646 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12647 lp->solved = FALSE;
12649 farkasvalid = FALSE;
12650 *lperror = TRUE;
12651 }
12652 }
12653 else
12654 farkasvalid = TRUE;
12655
12656 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12657 if( !farkasvalid && !(*lperror) )
12658 {
12660
12661 if( (fastmip > 0) && simplex )
12662 {
12663 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12664 * without FASTMIP
12665 */
12666 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12667 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12668 stat->nnodes, stat->nlps);
12669 fastmip = 0;
12670 goto SOLVEAGAIN;
12671 }
12672 else if( !tightdualfeastol )
12673 {
12674 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12675 * solve again with tighter feasibility tolerance
12676 */
12677 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12678 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12679 stat->nnodes, stat->nlps);
12680 tightdualfeastol = TRUE;
12681 goto SOLVEAGAIN;
12682 }
12683 else if( !fromscratch && simplex )
12684 {
12685 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12686 * from scratch
12687 */
12688 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12689 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12690 stat->nnodes, stat->nlps);
12691 fromscratch = TRUE;
12692 goto SOLVEAGAIN;
12693 }
12694 else
12695 {
12696 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12697 * helped forget about the LP at this node and mark it to be unsolved
12698 */
12699 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12700 lp->solved = FALSE;
12702 *lperror = TRUE;
12703 }
12704 }
12705
12706 break;
12707
12709 if( set->lp_checkprimfeas )
12710 {
12711 /* get unbounded LP solution and check the solution's feasibility again */
12712 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12713
12714 lp->primalchecked = TRUE;
12715 }
12716 else
12717 {
12718 /* get unbounded LP solution believing in the feasibility of the LP solution */
12720
12721 primalfeasible = TRUE;
12722 rayfeasible = TRUE;
12723 lp->primalchecked = FALSE;
12724 }
12725
12726 /* in debug mode, check that lazy bounds (if present) are not violated */
12727 checkLazyBounds(lp, set);
12728
12729 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12730 primalfeasible, rayfeasible);
12731
12732 if( !primalfeasible || !rayfeasible )
12733 {
12735
12736 if( (fastmip > 0) && simplex )
12737 {
12738 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12739 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12740 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12741 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12742 fastmip = 0;
12743 goto SOLVEAGAIN;
12744 }
12745 else if( !tightprimfeastol )
12746 {
12747 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12748 * tolerance
12749 */
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 with tighter primal feasibility tolerance\n",
12752 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12753 tightprimfeastol = TRUE;
12754 goto SOLVEAGAIN;
12755 }
12756 else if( !fromscratch && simplex )
12757 {
12758 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
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 again from scratch\n",
12761 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12762 fromscratch = TRUE;
12763 goto SOLVEAGAIN;
12764 }
12765 else if( scaling > 0 )
12766 {
12767 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12768 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12769 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12770 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12771 scaling = 0;
12772 goto SOLVEAGAIN;
12773 }
12774 else
12775 {
12776 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12777 * forget about the LP at this node and mark it to be unsolved
12778 */
12779 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12780 lp->solved = FALSE;
12782 *lperror = TRUE;
12783 }
12784 }
12785
12786 break;
12787
12789 assert(!lpCutoffDisabled(set, prob, lp));
12790 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12791 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12792 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12793 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12794 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12795 * FASTMIP and solve again.
12796 */
12797 if( !SCIPprobAllColsInLP(prob, set, lp) )
12798 {
12799 SCIP_LPI* lpi;
12801
12802 lpi = SCIPlpGetLPI(lp);
12803
12804 assert(lpi != NULL);
12805 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12806 * the assert by using !SCIPsetIsFeasNegative()
12807 */
12809
12811
12812 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12813 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12814 {
12815 SCIP_Real tmpcutoff;
12816 char tmppricingchar;
12817 SCIP_LPSOLSTAT solstat;
12818
12819 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12820
12821 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12822 fromscratch = FALSE;
12823
12824 /* temporarily disable cutoffbound, which also disables the objective limit */
12825 tmpcutoff = lp->cutoffbound;
12826 lp->cutoffbound = SCIPlpiInfinity(lpi);
12827
12828 /* set lp pricing strategy to steepest edge */
12829 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12830 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12831
12832 /* resolve LP with an iteration limit of 1 */
12833 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12834 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12835
12836 /* reinstall old cutoff bound and lp pricing strategy */
12837 lp->cutoffbound = tmpcutoff;
12838 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12839
12840 /* get objective value */
12842
12843 /* get solution status for the lp */
12844 solstat = SCIPlpGetSolstat(lp);
12845 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12846
12847 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12848
12849 /* the solution is still not exceeding the objective limit and the solving process
12850 * was stopped due to time or iteration limit, solve again with fastmip turned off
12851 */
12852 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12854 {
12856 if( !(*lperror) && (fastmip > 0) && simplex )
12857 {
12858 fastmip = 0;
12859 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12860 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12861
12862 /* get objective value */
12864
12865 /* get solution status for the lp */
12866 solstat = SCIPlpGetSolstat(lp);
12867
12868 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12869 }
12870 }/*lint !e438*/
12871
12872 /* check for lp errors */
12873 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12874 {
12875 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12876 lp->solved = FALSE;
12878
12879 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12880 goto TERMINATE;
12881 }
12882
12883 lp->solved = TRUE;
12884
12885 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12886 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12887 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12888 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12889 {
12890 /* get LP solution and possibly check the solution's feasibility again */
12891 if( set->lp_checkprimfeas )
12892 {
12893 primalfeaspointer = &primalfeasible;
12894 lp->primalchecked = TRUE;
12895 }
12896 else
12897 {
12898 /* believe in the primal feasibility of the LP solution */
12899 primalfeasible = TRUE;
12900 primalfeaspointer = NULL;
12901 lp->primalchecked = FALSE;
12902 }
12903 if( set->lp_checkdualfeas )
12904 {
12905 dualfeaspointer = &dualfeasible;
12906 lp->dualchecked = TRUE;
12907 }
12908 else
12909 {
12910 /* believe in the dual feasibility of the LP solution */
12911 dualfeasible = TRUE;
12912 dualfeaspointer = NULL;
12913 lp->dualchecked = FALSE;
12914 }
12915
12916 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12917
12918 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12919 if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12920 {
12921 checkLazyBounds(lp, set);
12922 }
12923
12924 /* if objective value is larger than the cutoff bound, set solution status to objective
12925 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12926 * this was already done in the lpSolve() method
12927 */
12928 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12929 {
12932 }
12933
12934 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12935 * the cutoffbound; mark the LP to be unsolved
12936 */
12937 if( !primalfeasible || !dualfeasible
12938 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12940 {
12941 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12942 lp->solved = FALSE;
12944 *lperror = TRUE;
12945 }
12946
12947 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12948 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12949 lp->lpsolstat, lp->cutoffbound);
12950 }
12951 /* infeasible solution */
12952 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12953 {
12954 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12955
12956 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas )
12957 {
12958 if( SCIPlpiHasDualRay(lp->lpi) )
12959 {
12960 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12961 }
12962 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12963 * with the primal simplex due to numerical problems) - treat this case like an LP error
12964 */
12965 else
12966 {
12967 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12968 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12969 lp->solved = FALSE;
12971 farkasvalid = FALSE;
12972 *lperror = TRUE;
12973 }
12974 }
12975 else
12976 farkasvalid = TRUE;
12977
12978 if( !farkasvalid )
12979 {
12981
12982 if( !tightprimfeastol )
12983 {
12984 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12985 * solve again with tighter feasibility tolerance
12986 */
12987 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12988 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12989 stat->nnodes, stat->nlps);
12990 tightprimfeastol = TRUE;
12991 goto SOLVEAGAIN;
12992 }
12993 else if( simplex )
12994 {
12995 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12996 * from scratch
12997 */
12998 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12999 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
13000 stat->nnodes, stat->nlps);
13001 fromscratch = TRUE;
13002 goto SOLVEAGAIN;
13003 }
13004 else
13005 {
13006 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
13007 * helped forget about the LP at this node and mark it to be unsolved
13008 */
13009 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
13010 lp->solved = FALSE;
13012 *lperror = TRUE;
13013 }
13014 }
13015 }
13016 /* unbounded solution */
13017 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13018 {
13019 if( set->lp_checkprimfeas )
13020 {
13021 /* get unbounded LP solution and check the solution's feasibility again */
13022 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13023
13024 lp->primalchecked = TRUE;
13025 }
13026 else
13027 {
13028 /* get unbounded LP solution believing in its feasibility */
13030
13031 primalfeasible = TRUE;
13032 rayfeasible = TRUE;
13033 lp->primalchecked = FALSE;
13034 }
13035
13036 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13037
13038 /* in debug mode, check that lazy bounds (if present) are not violated */
13039 checkLazyBounds(lp, set);
13040
13041 if( !primalfeasible || !rayfeasible )
13042 {
13043 /* unbounded solution is infeasible (this can happen due to numerical problems):
13044 * forget about the LP at this node and mark it to be unsolved
13045 *
13046 * @todo: like in the default LP solving evaluation, solve without fastmip,
13047 * with tighter feasibility tolerance and from scratch
13048 */
13049 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13050 lp->solved = FALSE;
13052 *lperror = TRUE;
13053 }
13054 }
13055
13059 }
13060 else
13061 {
13062 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13063 }
13064 }
13065 SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13066 break;
13067
13069 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13070 break;
13071
13073 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13074
13075 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13076 stat->nclockskipsleft = 0;
13077 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13078 {
13079 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13080 "you might consider switching the clock type of SCIP\n");
13082 }
13083 break;
13084
13087 SCIPerrorMessage("error in LP solver\n");
13088 retcode = SCIP_LPERROR;
13089 goto TERMINATE;
13090
13091 default:
13092 SCIPerrorMessage("unknown LP solution status\n");
13093 retcode = SCIP_ERROR;
13094 goto TERMINATE;
13095 }
13096 }
13097 assert(!(*lperror) || !lp->solved);
13098
13099 TERMINATE:
13100 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13101 * may happen that we continue to solve from scratch during strong branching */
13102 if( lp->lpifromscratch )
13103 {
13104 SCIP_Bool success;
13105 (void) lpSetFromscratch(lp, FALSE, &success);
13106 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13107 SCIP_UNUSED(success);
13108 }
13109
13110 return retcode;
13111}
13112
13113/** gets solution status of current LP */
13115 SCIP_LP* lp /**< current LP data */
13116 )
13117{
13118 assert(lp != NULL);
13120
13121 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13122}
13123
13124/** gets objective value of current LP
13125 *
13126 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13127 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13128 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13129 */
13131 SCIP_LP* lp, /**< current LP data */
13132 SCIP_SET* set, /**< global SCIP settings */
13133 SCIP_PROB* prob /**< problem data */
13134 )
13135{
13136 assert(lp != NULL);
13137 assert(lp->solved);
13138 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13139 assert(set != NULL);
13140
13141 if( !lp->flushed )
13142 return SCIP_INVALID;
13144 return lp->lpobjval;
13145 else if( lp->looseobjvalinf > 0 )
13146 return -SCIPsetInfinity(set);
13147 else
13148 {
13149 /* recalculate the loose objective value, if needed */
13150 if( !lp->looseobjvalid )
13152
13153 return lp->lpobjval + lp->looseobjval;
13154 }
13155}
13156
13157/** gets part of objective value of current LP that results from COLUMN variables only */
13159 SCIP_LP* lp /**< current LP data */
13160 )
13161{
13162 assert(lp != NULL);
13163 assert(lp->solved);
13164
13165 return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13166}
13167
13168/** gets part of objective value of current LP that results from LOOSE variables only */
13170 SCIP_LP* lp, /**< current LP data */
13171 SCIP_SET* set, /**< global SCIP settings */
13172 SCIP_PROB* prob /**< problem data */
13173 )
13174{
13175 assert(lp != NULL);
13176 assert(lp->solved);
13177 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13178 assert(set != NULL);
13179
13180 if( !lp->flushed )
13181 return SCIP_INVALID;
13182 else if( lp->looseobjvalinf > 0 )
13183 return -SCIPsetInfinity(set);
13184 else
13185 return getFiniteLooseObjval(lp, set, prob);
13186}
13187
13188/** remembers the current LP objective value as root solution value */
13190 SCIP_LP* lp, /**< current LP data */
13191 SCIP_SET* set, /**< global SCIP settings */
13192 SCIP_PROB* prob /**< problem data */
13193 )
13194{
13195 assert(lp != NULL);
13196
13198 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13199}
13200
13201/** invalidates the root LP solution value */
13203 SCIP_LP* lp /**< current LP data */
13204 )
13205{
13206 assert(lp != NULL);
13207
13210}
13211
13212/** recomputes local and global pseudo objective values */
13214 SCIP_LP* lp, /**< current LP data */
13215 SCIP_SET* set, /**< global SCIP settings */
13216 SCIP_PROB* prob /**< problem data */
13217 )
13218{
13219 SCIP_VAR** vars;
13220 int nvars;
13221 int v;
13222
13223 assert(lp != NULL);
13224 assert(set != NULL);
13225 assert(prob != NULL);
13226
13227 vars = prob->vars;
13228 nvars = prob->nvars;
13229
13230 lp->glbpseudoobjvalinf = 0;
13231 lp->glbpseudoobjval = 0.0;
13232
13233 lp->pseudoobjvalinf = 0;
13234 lp->pseudoobjval = 0.0;
13235
13236 for( v = 0; v < nvars; ++v )
13237 {
13239
13240 if( SCIPsetIsPositive(set, obj) )
13241 {
13242 /* update the global pseudo objective value */
13244 ++(lp->glbpseudoobjvalinf);
13245 else
13247
13248 /* update the local pseudo objective value */
13250 ++(lp->pseudoobjvalinf);
13251 else
13253 }
13254
13255 if( SCIPsetIsNegative(set, obj) )
13256 {
13257 /* update the global pseudo objective value */
13259 ++(lp->glbpseudoobjvalinf);
13260 else
13262
13263 /* update the local pseudo objective value */
13265 ++(lp->pseudoobjvalinf);
13266 else
13268 }
13269 }
13270
13271 /* the recomputed values are reliable */
13273 lp->glbpseudoobjvalid = TRUE;
13274 lp->relpseudoobjval = lp->pseudoobjval;
13275 lp->pseudoobjvalid = TRUE;
13276}
13277
13278/** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13279 * global bound
13280 */
13282 SCIP_LP* lp, /**< current LP data */
13283 SCIP_SET* set, /**< global SCIP settings */
13284 SCIP_PROB* prob /**< problem data */
13285 )
13286{
13287 assert(lp != NULL);
13288 assert(lp->glbpseudoobjvalinf >= 0);
13289 assert(set != NULL);
13290
13291 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13292 return -SCIPsetInfinity(set);
13293 else
13294 {
13295 /* recalculate the global pseudo solution value, if needed */
13296 if( !lp->glbpseudoobjvalid )
13298
13299 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13301 return -SCIPsetInfinity(set);
13302
13304 return SCIPsetInfinity(set);
13305
13306 return lp->glbpseudoobjval;
13307 }
13308}
13309
13310/** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13311 * objective function) local bound
13312 */
13314 SCIP_LP* lp, /**< current LP data */
13315 SCIP_SET* set, /**< global SCIP settings */
13316 SCIP_PROB* prob /**< problem data */
13317 )
13318{
13319 assert(lp != NULL);
13320 assert(lp->pseudoobjvalinf >= 0);
13321 assert(set != NULL);
13322
13323 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13324 return -SCIPsetInfinity(set);
13325 else
13326 {
13327 /* recalculate the pseudo solution value, if needed */
13328 if( !lp->pseudoobjvalid )
13330
13331 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13333 return -SCIPsetInfinity(set);
13334
13336 return SCIPsetInfinity(set);
13337
13338 return lp->pseudoobjval;
13339 }
13340}
13341
13342/** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13344 SCIP_LP* lp, /**< current LP data */
13345 SCIP_SET* set, /**< global SCIP settings */
13346 SCIP_PROB* prob, /**< problem data */
13347 SCIP_VAR* var, /**< problem variable */
13348 SCIP_Real oldbound, /**< old value for bound */
13349 SCIP_Real newbound, /**< new value for bound */
13350 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13351 )
13352{
13353 SCIP_Real pseudoobjval;
13354 int pseudoobjvalinf;
13355 SCIP_Real obj;
13356
13357 pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13358 pseudoobjvalinf = lp->pseudoobjvalinf;
13360 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13361 {
13362 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13363 pseudoobjvalinf--;
13364 else
13365 pseudoobjval -= oldbound * obj;
13366 assert(pseudoobjvalinf >= 0);
13367 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13368 pseudoobjvalinf++;
13369 else
13370 pseudoobjval += newbound * obj;
13371 }
13372 assert(pseudoobjvalinf >= 0);
13373
13374 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13375 return -SCIPsetInfinity(set);
13376 else
13377 return pseudoobjval;
13378}
13379
13380/** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13381 * perform calculations with interval arithmetic to get an exact lower bound
13382 */
13384 SCIP_LP* lp, /**< current LP data */
13385 SCIP_SET* set, /**< global SCIP settings */
13386 SCIP_VAR* var, /**< problem variable */
13387 SCIP_Real oldbound, /**< old value for bound */
13388 SCIP_Real newbound, /**< new value for bound */
13389 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13390 )
13391{
13392 SCIP_Real pseudoobjval;
13393 int pseudoobjvalinf;
13394 SCIP_Real obj;
13395
13397
13398 pseudoobjval = lp->pseudoobjval;
13399 pseudoobjvalinf = lp->pseudoobjvalinf;
13401 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13402 {
13403 SCIP_INTERVAL objint;
13404 SCIP_INTERVAL bd;
13405 SCIP_INTERVAL prod;
13406 SCIP_INTERVAL psval;
13407
13408 SCIPintervalSet(&psval, pseudoobjval);
13410
13411 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13412 pseudoobjvalinf--;
13413 else
13414 {
13415 SCIPintervalSet(&bd, oldbound);
13416 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13417 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13418 }
13419 assert(pseudoobjvalinf >= 0);
13420 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13421 pseudoobjvalinf++;
13422 else
13423 {
13424 SCIPintervalSet(&bd, newbound);
13425 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13426 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13427 }
13428
13429 pseudoobjval = SCIPintervalGetInf(psval);
13430 }
13431 assert(pseudoobjvalinf >= 0);
13432
13433 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13434 return -SCIPsetInfinity(set);
13435 else
13436 return pseudoobjval;
13437}
13438
13439/** compute the objective delta due the new objective coefficient */
13440static
13442 SCIP_SET* set, /**< global SCIP settings */
13443 SCIP_Real oldobj, /**< old objective value of variable */
13444 SCIP_Real newobj, /**< new objective value of variable */
13445 SCIP_Real lb, /**< lower bound of variable */
13446 SCIP_Real ub, /**< upper bound of variable */
13447 SCIP_Real* deltaval, /**< pointer to store the delta value */
13448 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13449 )
13450{
13456
13457 (*deltaval) = 0.0;
13458 (*deltainf) = 0;
13459
13461 {
13462 /* sign of objective did not change */
13464 {
13465 /* if the bound is finite, calculate the deltaval */
13466 if( !SCIPsetIsInfinity(set, -lb) )
13467 (*deltaval) = lb * (newobj - oldobj);
13468 }
13469 /* sign of objective did change, so the best bound does change */
13470 else if( SCIPsetIsNegative(set, newobj) )
13471 {
13472 if( SCIPsetIsInfinity(set, -lb) )
13473 {
13474 /* old best bound was infinite while new one is not */
13475 if( !SCIPsetIsInfinity(set, ub) )
13476 {
13477 (*deltainf) = -1;
13478 (*deltaval) = ub * newobj;
13479 }
13480 }
13481 else
13482 {
13483 /* new best bound is infinite while old one was not */
13484 if( SCIPsetIsInfinity(set, ub) )
13485 {
13486 (*deltainf) = 1;
13487 (*deltaval) = -lb * oldobj;
13488 }
13489 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13490 else
13491 {
13492 (*deltaval) = (ub * newobj) - (lb * oldobj);
13493 }
13494 }
13495 }
13496 /* new objective is 0.0 */
13497 else
13498 {
13499 if( SCIPsetIsInfinity(set, -lb) )
13500 (*deltainf) = -1;
13501 else
13502 (*deltaval) = -lb * oldobj;
13503 }
13504 }
13505 else if( SCIPsetIsNegative(set, oldobj) )
13506 {
13507 /* sign of objective did not change */
13509 {
13510 /* if the bound is finite, calculate the deltaval */
13511 if( !SCIPsetIsInfinity(set, ub) )
13512 (*deltaval) = ub * (newobj - oldobj);
13513 }
13514 /* sign of objective did change, so the best bound does change */
13515 else if( SCIPsetIsPositive(set, newobj) )
13516 {
13517 if( SCIPsetIsInfinity(set, ub) )
13518 {
13519 /* old best bound was infinite while new one is not */
13520 if( !SCIPsetIsInfinity(set, -lb) )
13521 {
13522 (*deltainf) = -1;
13523 (*deltaval) = lb * newobj;
13524 }
13525 }
13526 else
13527 {
13528 /* new best bound is infinite while old one was not */
13529 if( SCIPsetIsInfinity(set, -lb) )
13530 {
13531 (*deltainf) = 1;
13532 (*deltaval) = -ub * oldobj;
13533 }
13534 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13535 else
13536 {
13537 (*deltaval) = (lb * newobj) - (ub * oldobj);
13538 }
13539 }
13540 }
13541 /* new objective is 0.0 */
13542 else
13543 {
13544 if( SCIPsetIsInfinity(set, ub) )
13545 (*deltainf) = -1;
13546 else
13547 (*deltaval) = -ub * oldobj;
13548 }
13549 }
13550 /* old objective was 0.0 */
13551 else
13552 {
13554 {
13555 if( SCIPsetIsInfinity(set, ub) )
13556 (*deltainf) = 1;
13557 else
13558 (*deltaval) = ub * newobj;
13559 }
13560 else if( SCIPsetIsPositive(set, newobj) )
13561 {
13562 if( SCIPsetIsInfinity(set, -lb) )
13563 (*deltainf) = 1;
13564 else
13565 (*deltaval) = lb * newobj;
13566 }
13567 }
13568}
13569
13570/** compute the objective delta due the new lower bound */
13571static
13573 SCIP_SET* set, /**< global SCIP settings */
13574 SCIP_Real obj, /**< objective value of variable */
13575 SCIP_Real oldlb, /**< old lower bound of variable */
13576 SCIP_Real newlb, /**< new lower bound of variable */
13577 SCIP_Real* deltaval, /**< pointer to store the delta value */
13578 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13579 )
13580{
13581 assert(obj > 0.0);
13583 assert(!SCIPsetIsInfinity(set, oldlb));
13584 assert(!SCIPsetIsInfinity(set, newlb));
13585 assert(newlb != oldlb); /*lint !e777*/
13586
13587 if( SCIPsetIsInfinity(set, -newlb) )
13588 {
13589 assert(!SCIPsetIsInfinity(set, -oldlb));
13590
13591 *deltainf = 1;
13592 *deltaval = -obj * oldlb;
13593 }
13594 else if( SCIPsetIsInfinity(set, -oldlb) )
13595 {
13596 assert(!SCIPsetIsInfinity(set, -newlb));
13597
13598 *deltainf = -1;
13599 *deltaval = obj * newlb;
13600 }
13601 else
13602 {
13603 *deltainf = 0;
13604 *deltaval = obj * (newlb - oldlb);
13605 }
13606}
13607
13608/** compute the objective delta due the new upper bound */
13609static
13611 SCIP_SET* set, /**< global SCIP settings */
13612 SCIP_Real obj, /**< objective value of variable */
13613 SCIP_Real oldub, /**< old upper bound of variable */
13614 SCIP_Real newub, /**< new upper bound of variable */
13615 SCIP_Real* deltaval, /**< pointer to store the delta value */
13616 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13617 )
13618{
13619 assert(obj < 0.0);
13621 assert(!SCIPsetIsInfinity(set, -oldub));
13622 assert(!SCIPsetIsInfinity(set, -newub));
13623 assert(newub != oldub); /*lint !e777*/
13624
13625 if( SCIPsetIsInfinity(set, newub) )
13626 {
13627 assert(!SCIPsetIsInfinity(set, oldub));
13628
13629 *deltainf = 1;
13630 *deltaval = -obj * oldub;
13631 }
13632 else if( SCIPsetIsInfinity(set, oldub) )
13633 {
13634 assert(!SCIPsetIsInfinity(set, newub));
13635
13636 *deltainf = -1;
13637 *deltaval = obj * newub;
13638 }
13639 else
13640 {
13641 *deltainf = 0;
13642 *deltaval = obj * (newub - oldub);
13643 }
13644}
13645
13646/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13647static
13649 SCIP_LP* lp, /**< current LP data */
13650 SCIP_SET* set, /**< global SCIP settings */
13651 SCIP_VAR* var, /**< problem variable that changed */
13652 SCIP_Real deltaval, /**< delta value in the objective function */
13653 int deltainf, /**< delta value for the number of variables with infinite best bound */
13654 SCIP_Bool local, /**< should the local pseudo objective value be updated? */
13655 SCIP_Bool loose, /**< should the loose objective value be updated? */
13656 SCIP_Bool global /**< should the global pseudo objective value be updated? */
13657 )
13658{
13659 assert(lp != NULL);
13660 assert(lp->looseobjvalinf >= 0);
13661 assert(lp->pseudoobjvalinf >= 0);
13662 assert(lp->glbpseudoobjvalinf >= 0);
13663
13664 /* update the pseudo objective value */
13665 if( local )
13666 {
13667 lp->pseudoobjvalinf += deltainf;
13668 if( lp->pseudoobjvalid )
13669 {
13670 lp->pseudoobjval += deltaval;
13671
13672 /* if the absolute value was increased, this is regarded as reliable,
13673 * otherwise, we check whether we can still trust the updated value
13674 */
13676 lp->relpseudoobjval = lp->pseudoobjval;
13678 lp->pseudoobjvalid = FALSE;
13679 }
13680
13681 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13683 loose = TRUE;
13684 }
13685 /* update the loose objective value */
13686 if( loose )
13687 {
13688 lp->looseobjvalinf += deltainf;
13689
13690 if( deltaval != 0.0 && lp->looseobjvalid )
13691 {
13692 lp->looseobjval += deltaval;
13693
13694 /* if the absolute value was increased, this is regarded as reliable,
13695 * otherwise, we check whether we can still trust the updated value
13696 */
13697 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13698 lp->rellooseobjval = lp->looseobjval;
13700 lp->looseobjvalid = FALSE;
13701 }
13702 }
13703 /* update the root pseudo objective values */
13704 if( global )
13705 {
13706 lp->glbpseudoobjvalinf += deltainf;
13707 if( lp->glbpseudoobjvalid )
13708 {
13709 lp->glbpseudoobjval += deltaval;
13710
13711 /* if the absolute value was increased, this is regarded as reliable,
13712 * otherwise, we check whether we can still trust the updated value
13713 */
13718 }
13719 }
13720
13721 assert(lp->looseobjvalinf >= 0);
13722 assert(lp->pseudoobjvalinf >= 0);
13723 assert(lp->glbpseudoobjvalinf >= 0);
13724}
13725
13726/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13727 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13728 */
13729static
13731 SCIP_LP* lp, /**< current LP data */
13732 SCIP_SET* set, /**< global SCIP settings */
13733 SCIP_VAR* var, /**< problem variable that changed */
13734 SCIP_Real oldobj, /**< old objective value of variable */
13735 SCIP_Real oldlb, /**< old objective value of variable */
13736 SCIP_Real oldub, /**< old objective value of variable */
13737 SCIP_Real newobj, /**< new objective value of variable */
13738 SCIP_Real newlb, /**< new objective value of variable */
13739 SCIP_Real newub /**< new objective value of variable */
13740 )
13741{
13742 SCIP_INTERVAL deltaval;
13743 SCIP_INTERVAL bd;
13745 SCIP_INTERVAL prod;
13746 SCIP_INTERVAL psval;
13747 int deltainf;
13748
13749 assert(lp != NULL);
13750 assert(lp->pseudoobjvalinf >= 0);
13751 assert(lp->looseobjvalinf >= 0);
13753 assert(!SCIPsetIsInfinity(set, oldlb));
13754 assert(!SCIPsetIsInfinity(set, -oldub));
13756 assert(!SCIPsetIsInfinity(set, newlb));
13757 assert(!SCIPsetIsInfinity(set, -newub));
13758 assert(var != NULL);
13759
13761 {
13762 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13763 return SCIP_INVALIDDATA;
13764 }
13765
13767
13768 SCIPintervalSet(&deltaval, 0.0);
13769 deltainf = 0;
13770
13771 /* subtract old pseudo objective value */
13772 if( oldobj > 0.0 )
13773 {
13774 if( SCIPsetIsInfinity(set, -oldlb) )
13775 deltainf--;
13776 else
13777 {
13778 SCIPintervalSet(&bd, oldlb);
13780 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13781 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
13782 }
13783 }
13784 else if( oldobj < 0.0 )
13785 {
13786 if( SCIPsetIsInfinity(set, oldub) )
13787 deltainf--;
13788 else
13789 {
13790 SCIPintervalSet(&bd, oldub);
13792 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13793 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
13794 }
13795 }
13796
13797 /* add new pseudo objective value */
13798 if( newobj > 0.0 )
13799 {
13800 if( SCIPsetIsInfinity(set, -newlb) )
13801 deltainf++;
13802 else
13803 {
13804 SCIPintervalSet(&bd, newlb);
13806 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13807 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
13808 }
13809 }
13810 else if( newobj < 0.0 )
13811 {
13812 if( SCIPsetIsInfinity(set, newub) )
13813 deltainf++;
13814 else
13815 {
13816 SCIPintervalSet(&bd, newub);
13818 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13819 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
13820 }
13821 }
13822
13823 /* update the pseudo and loose objective values */
13824 SCIPintervalSet(&psval, lp->pseudoobjval);
13825 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13826 lp->pseudoobjval = SCIPintervalGetInf(psval);
13827 lp->pseudoobjvalinf += deltainf;
13829 {
13830 SCIPintervalSet(&psval, lp->looseobjval);
13831 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13832 lp->looseobjval = SCIPintervalGetInf(psval);
13833 lp->looseobjvalinf += deltainf;
13834 }
13835
13836 assert(lp->pseudoobjvalinf >= 0);
13837 assert(lp->looseobjvalinf >= 0);
13838
13839 return SCIP_OKAY;
13840}
13841
13842/** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13844 SCIP_LP* lp, /**< current LP data */
13845 SCIP_SET* set, /**< global SCIP settings */
13846 SCIP_VAR* var, /**< problem variable that changed */
13847 SCIP_Real oldobj, /**< old objective coefficient of variable */
13848 SCIP_Real newobj /**< new objective coefficient of variable */
13849 )
13850{
13851 assert(set != NULL);
13852 assert(var != NULL);
13853
13854 if( set->misc_exactsolve )
13855 {
13856 if( oldobj != newobj ) /*lint !e777*/
13857 {
13860 }
13861 }
13862 else
13863 {
13864 if( !SCIPsetIsEQ(set, oldobj, newobj) )
13865 {
13866 SCIP_Real deltaval;
13867 int deltainf;
13868
13871
13872 /* the objective coefficient can only be changed during presolving, that implies that the global and local
13873 * domain of the variable are the same
13874 */
13877
13878 /* compute the pseudo objective delta due the new objective coefficient */
13880
13881 /* update the local pseudo objective value */
13882 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13883
13884 /* compute the pseudo objective delta due the new objective coefficient */
13886
13887 /* update the global pseudo objective value */
13888 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13889 }
13890 }
13891
13892 return SCIP_OKAY;
13893}
13894
13895
13896/** updates current root pseudo objective value for a global change in a variable's lower bound */
13898 SCIP_LP* lp, /**< current LP data */
13899 SCIP_SET* set, /**< global SCIP settings */
13900 SCIP_VAR* var, /**< problem variable that changed */
13901 SCIP_Real oldlb, /**< old lower bound of variable */
13902 SCIP_Real newlb /**< new lower bound of variable */
13903 )
13904{
13905 assert(set != NULL);
13906 assert(var != NULL);
13907
13908 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13909 {
13910 SCIP_Real deltaval;
13911 int deltainf;
13912
13913 /* compute the pseudo objective delta due the new lower bound */
13914 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13915
13916 /* update the root pseudo objective values */
13917 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13918 }
13919
13920 return SCIP_OKAY;
13921}
13922
13923/** updates current pseudo and loose objective value for a change in a variable's lower bound */
13925 SCIP_LP* lp, /**< current LP data */
13926 SCIP_SET* set, /**< global SCIP settings */
13927 SCIP_VAR* var, /**< problem variable that changed */
13928 SCIP_Real oldlb, /**< old lower bound of variable */
13929 SCIP_Real newlb /**< new lower bound of variable */
13930 )
13931{
13932 assert(set != NULL);
13933 assert(var != NULL);
13934
13935 if( set->misc_exactsolve )
13936 {
13937 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13938 {
13941 }
13942 }
13943 else
13944 {
13945 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13946 {
13947 SCIP_Real deltaval;
13948 int deltainf;
13949
13952
13953 /* compute the pseudo objective delta due the new lower bound */
13954 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13955
13956 /* update the pseudo and loose objective values */
13957 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13958 }
13959 }
13960
13961 return SCIP_OKAY;
13962}
13963
13964/** updates current root pseudo objective value for a global change in a variable's upper bound */
13966 SCIP_LP* lp, /**< current LP data */
13967 SCIP_SET* set, /**< global SCIP settings */
13968 SCIP_VAR* var, /**< problem variable that changed */
13969 SCIP_Real oldub, /**< old upper bound of variable */
13970 SCIP_Real newub /**< new upper bound of variable */
13971 )
13972{
13973 assert(set != NULL);
13974 assert(var != NULL);
13975
13976 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13977 {
13978 SCIP_Real deltaval;
13979 int deltainf;
13980
13981 /* compute the pseudo objective delta due the new upper bound */
13982 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13983
13984 /* update the root pseudo objective values */
13985 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13986 }
13987
13988 return SCIP_OKAY;
13989}
13990
13991/** updates current pseudo objective value for a change in a variable's upper bound */
13993 SCIP_LP* lp, /**< current LP data */
13994 SCIP_SET* set, /**< global SCIP settings */
13995 SCIP_VAR* var, /**< problem variable that changed */
13996 SCIP_Real oldub, /**< old upper bound of variable */
13997 SCIP_Real newub /**< new upper bound of variable */
13998 )
13999{
14000 assert(set != NULL);
14001 assert(var != NULL);
14002
14003 if( set->misc_exactsolve )
14004 {
14005 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14006 {
14009 }
14010 }
14011 else
14012 {
14013 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14014 {
14015 SCIP_Real deltaval;
14016 int deltainf;
14017
14020
14021 /* compute the pseudo objective delta due the new upper bound */
14022 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14023
14024 /* update the pseudo and loose objective values */
14025 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14026 }
14027 }
14028
14029 return SCIP_OKAY;
14030}
14031
14032/** informs LP, that given variable was added to the problem */
14034 SCIP_LP* lp, /**< current LP data */
14035 SCIP_SET* set, /**< global SCIP settings */
14036 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
14037 )
14038{
14039 assert(lp != NULL);
14042
14043 /* add the variable to the loose objective value sum */
14045
14046 /* update the loose variables counter */
14048 lp->nloosevars++;
14049
14050 return SCIP_OKAY;
14051}
14052
14053/** informs LP, that given variable is to be deleted from the problem */
14055 SCIP_LP* lp, /**< current LP data */
14056 SCIP_SET* set, /**< global SCIP settings */
14057 SCIP_VAR* var /**< variable that will be deleted from the problem */
14058 )
14059{
14060 assert(lp != NULL);
14063
14064 /* subtract the variable from the loose objective value sum */
14066
14067 /* update the loose variables counter */
14069 {
14071 }
14072
14073 return SCIP_OKAY;
14074}
14075
14076/** informs LP, that given formerly loose problem variable is now a column variable */
14077static
14079 SCIP_LP* lp, /**< current LP data */
14080 SCIP_SET* set, /**< global SCIP settings */
14081 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14082 )
14083{
14084 SCIP_Real obj;
14085 SCIP_Real lb;
14086 SCIP_Real ub;
14087
14088 assert(lp != NULL);
14089 assert(lp->nloosevars > 0);
14092 assert(lp->looseobjvalinf >= 0);
14093
14095
14096 /* update loose objective value */
14097 if( SCIPsetIsPositive(set, obj) )
14098 {
14099 lb = SCIPvarGetLbLocal(var);
14100 if( SCIPsetIsInfinity(set, -lb) )
14101 lp->looseobjvalinf--;
14102 else
14103 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14104 }
14105 else if( SCIPsetIsNegative(set, obj) )
14106 {
14107 ub = SCIPvarGetUbLocal(var);
14108 if( SCIPsetIsInfinity(set, ub) )
14109 lp->looseobjvalinf--;
14110 else
14111 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14112 }
14113
14115
14116 assert(lp->looseobjvalinf >= 0);
14117
14118 return SCIP_OKAY;
14119}
14120
14121/** informs LP, that given formerly loose problem variable is now a column variable
14122 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14123 */
14124static
14126 SCIP_LP* lp, /**< current LP data */
14127 SCIP_SET* set, /**< global SCIP settings */
14128 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14129 )
14130{
14131 SCIP_INTERVAL bd;
14132 SCIP_INTERVAL ob;
14133 SCIP_INTERVAL prod;
14134 SCIP_INTERVAL loose;
14135 SCIP_Real obj;
14136 SCIP_Real lb;
14137 SCIP_Real ub;
14138
14139 assert(lp != NULL);
14140 assert(lp->nloosevars > 0);
14143
14145
14146 SCIPintervalSet(&loose, lp->looseobjval);
14147
14148 /* update loose objective value corresponding to the deletion of variable */
14149 if( obj > 0.0 )
14150 {
14151 lb = SCIPvarGetLbLocal(var);
14152 if( SCIPsetIsInfinity(set, -lb) )
14153 lp->looseobjvalinf--;
14154 else
14155 {
14156 SCIPintervalSet(&bd, lb);
14157 SCIPintervalSet(&ob, obj);
14158 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14159 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
14160 }
14161 }
14162 else if( SCIPsetIsNegative(set, obj) )
14163 {
14164 ub = SCIPvarGetUbLocal(var);
14165 if( SCIPsetIsInfinity(set, ub) )
14166 lp->looseobjvalinf--;
14167 else
14168 {
14169 SCIPintervalSet(&bd, ub);
14170 SCIPintervalSet(&ob, obj);
14171 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14172 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
14173 }
14174 }
14175 lp->nloosevars--;
14176
14177 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14178 if( lp->nloosevars == 0 )
14179 {
14180 assert(lp->looseobjvalinf == 0);
14181 lp->looseobjval = 0.0;
14182 }
14183 else
14184 lp->looseobjval = SCIPintervalGetInf(loose);
14185
14186 return SCIP_OKAY;
14187}
14188
14189/** informs LP, that given formerly loose problem variable is now a column variable */
14191 SCIP_LP* lp, /**< current LP data */
14192 SCIP_SET* set, /**< global SCIP settings */
14193 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14194 )
14195{
14196 assert(set != NULL);
14197
14198 if( set->misc_exactsolve )
14199 {
14201 }
14202 else
14203 {
14205 }
14206
14207 return SCIP_OKAY;
14208}
14209
14210/** informs LP, that given formerly column problem variable is now again a loose variable */
14211static
14213 SCIP_LP* lp, /**< current LP data */
14214 SCIP_SET* set, /**< global SCIP settings */
14215 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14216 )
14217{
14218 SCIP_Real obj;
14219 SCIP_Real lb;
14220 SCIP_Real ub;
14221
14222 assert(lp != NULL);
14225 assert(lp->looseobjvalinf >= 0);
14226
14228
14229 /* update loose objective value corresponding to the addition of variable */
14230 if( SCIPsetIsPositive(set, obj) )
14231 {
14232 lb = SCIPvarGetLbLocal(var);
14233 if( SCIPsetIsInfinity(set, -lb) )
14234 lp->looseobjvalinf++;
14235 else
14236 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14237 }
14238 else if( SCIPsetIsNegative(set, obj) )
14239 {
14240 ub = SCIPvarGetUbLocal(var);
14241 if( SCIPsetIsInfinity(set, ub) )
14242 lp->looseobjvalinf++;
14243 else
14244 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14245 }
14246 lp->nloosevars++;
14247
14248 assert(lp->looseobjvalinf >= 0);
14249
14250 return SCIP_OKAY;
14251}
14252
14253/** informs LP, that given formerly column problem variable is now again a loose variable
14254 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14255 */
14256static
14258 SCIP_LP* lp, /**< current LP data */
14259 SCIP_SET* set, /**< global SCIP settings */
14260 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14261 )
14262{
14263 SCIP_INTERVAL bd;
14264 SCIP_INTERVAL ob;
14265 SCIP_INTERVAL prod;
14266 SCIP_INTERVAL loose;
14267 SCIP_Real obj;
14268 SCIP_Real lb;
14269 SCIP_Real ub;
14270
14271 assert(lp != NULL);
14274
14276
14277 SCIPintervalSet(&loose, lp->looseobjval);
14278
14279 /* update loose objective value corresponding to the deletion of variable */
14280 if( obj > 0.0 )
14281 {
14282 lb = SCIPvarGetLbLocal(var);
14283 if( SCIPsetIsInfinity(set, -lb) )
14284 lp->looseobjvalinf++;
14285 else
14286 {
14287 SCIPintervalSet(&bd, lb);
14288 SCIPintervalSet(&ob, obj);
14289 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14290 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
14291 }
14292 }
14293 else if( SCIPsetIsNegative(set, obj) )
14294 {
14295 ub = SCIPvarGetUbLocal(var);
14296 if( SCIPsetIsInfinity(set, ub) )
14297 lp->looseobjvalinf++;
14298 else
14299 {
14300 SCIPintervalSet(&bd, ub);
14301 SCIPintervalSet(&ob, obj);
14302 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14303 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
14304 }
14305 }
14306 lp->nloosevars++;
14307
14308 lp->looseobjval = SCIPintervalGetInf(loose);
14309
14310 return SCIP_OKAY;
14311}
14312
14313/** informs LP, that given formerly column problem variable is now again a loose variable */
14315 SCIP_LP* lp, /**< current LP data */
14316 SCIP_SET* set, /**< global SCIP settings */
14317 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14318 )
14319{
14320 assert(set != NULL);
14321
14322 if( set->misc_exactsolve )
14323 {
14325 }
14326 else
14327 {
14329 }
14330
14331 return SCIP_OKAY;
14332}
14333
14334/** decrease the number of loose variables by one */
14336 SCIP_LP* lp /**< current LP data */
14337 )
14338{
14339 assert(lp != NULL);
14340 assert(lp->nloosevars > 0);
14341
14342 lp->nloosevars--;
14343
14344 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14345 if( lp->nloosevars == 0 )
14346 {
14347 assert(lp->looseobjvalinf == 0);
14348 lp->looseobjval = 0.0;
14349 }
14350}
14351
14352/** stores the LP solution in the columns and rows */
14354 SCIP_LP* lp, /**< current LP data */
14355 SCIP_SET* set, /**< global SCIP settings */
14356 SCIP_STAT* stat, /**< problem statistics */
14357 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14358 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
14359 )
14360{
14361 SCIP_COL** lpicols;
14362 SCIP_ROW** lpirows;
14364 SCIP_Real* dualsol;
14365 SCIP_Real* activity = NULL;
14366 SCIP_Real* redcost;
14367 SCIP_Real primalbound;
14368 SCIP_Real dualbound;
14369 SCIP_Bool stillprimalfeasible;
14370 SCIP_Bool stilldualfeasible;
14371 int* cstat;
14372 int* rstat;
14373 SCIP_Longint lpcount;
14374 int nlpicols;
14375 int nlpirows;
14376 int c;
14377 int r;
14378
14379 assert(lp != NULL);
14380 assert(lp->flushed);
14381 assert(lp->solved);
14382 assert(set != NULL);
14383 assert(stat != NULL);
14384 assert(lp->validsollp <= stat->lpcount);
14385
14387
14388 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14389 * corresponding flag immediately to FALSE to skip all checks
14390 */
14391 if( primalfeasible == NULL )
14392 stillprimalfeasible = FALSE;
14393 else
14394 {
14395 *primalfeasible = TRUE;
14396 stillprimalfeasible = TRUE;
14397 }
14398 if( dualfeasible == NULL )
14399 stilldualfeasible = FALSE;
14400 else
14401 {
14402 *dualfeasible = TRUE;
14403 stilldualfeasible = TRUE;
14404 }
14405
14406 /* check if the values are already calculated */
14407 if( lp->validsollp == stat->lpcount )
14408 return SCIP_OKAY;
14409 lp->validsollp = stat->lpcount;
14410
14411 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14412 stat->lpcount, SCIPlpGetSolstat(lp));
14413
14414 lpicols = lp->lpicols;
14415 lpirows = lp->lpirows;
14416 nlpicols = lp->nlpicols;
14417 nlpirows = lp->nlpirows;
14418 lpcount = stat->lpcount;
14419
14420 /* get temporary memory */
14422 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14423#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14424 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14425#endif
14426 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14427 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14428 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14429
14430 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14431 if( lp->solisbasic )
14432 {
14433 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14434 }
14435 else
14436 {
14437 BMSclearMemoryArray(cstat, nlpicols);
14438 BMSclearMemoryArray(rstat, nlpirows);
14439 }
14440
14441 primalbound = 0.0;
14442 dualbound = 0.0;
14443
14444 /* copy primal solution and reduced costs into columns */
14445 for( c = 0; c < nlpicols; ++c )
14446 {
14447 assert( 0 <= cstat[c] && cstat[c] < 4 );
14448 lpicols[c]->primsol = primsol[c];
14449 if( !SCIPisFinite(lpicols[c]->primsol) )
14450 {
14451 /* calculating with nan or +/-inf can have many unexpected effects
14452 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14453 * this should trigger a resolve of the LP, or a stop with an LP error
14454 */
14455 stillprimalfeasible = FALSE;
14456 stilldualfeasible = FALSE;
14457 lpicols[c]->primsol = 0.0;
14458 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14459 }
14460 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14461 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14462 lpicols[c]->redcost = redcost[c];
14463 lpicols[c]->basisstatus = (unsigned int) cstat[c];
14464 lpicols[c]->validredcostlp = lpcount;
14465 if( stillprimalfeasible )
14466 {
14467 stillprimalfeasible =
14468 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14469 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14470 primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14471 }
14472 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14473 {
14474 double compslack;
14475
14476 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14477 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14478 * variables, which would magnify even the tiniest violation in the dual multiplier
14479 */
14480 if( stilldualfeasible )
14481 {
14482 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14483 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14484 }
14485 if( stilldualfeasible )
14486 {
14487 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14488 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14489 }
14490
14491 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14492 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14493 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14494 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14495 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14496 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14497 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14498 dualfeasible != NULL ? stilldualfeasible : TRUE);
14499 }
14500 else
14501 {
14502 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14503 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14504 {
14505 lpicols[c]->redcost = 0.0;
14506 }
14507
14508 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14509 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14510 * bounds, its reduced cost must be zero
14511 */
14512 if( stilldualfeasible
14513 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14514 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14515 if( stilldualfeasible
14516 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14517 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14518
14519 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14520 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14521 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14522 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14523 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14524 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14525 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14526 dualfeasible != NULL ? stilldualfeasible : TRUE);
14527 }
14528
14529 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14530 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14531 * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14532 */
14533 if( stilldualfeasible )
14534 {
14535 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14536 dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14537 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14538 dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14539 }
14540 }
14541
14542 /* copy dual solution and activities into rows */
14543 for( r = 0; r < nlpirows; ++r )
14544 {
14545 assert( 0 <= rstat[r] && rstat[r] < 4 );
14546 lpirows[r]->dualsol = dualsol[r];
14547#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14548 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14549#else
14550 /* calculate row activity if invalid */
14551 if( lpirows[r]->validactivitylp != stat->lpcount )
14552 SCIProwRecalcLPActivity(lpirows[r], stat);
14553#endif
14554 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14555 lpirows[r]->validactivitylp = lpcount;
14556 if( stillprimalfeasible )
14557 {
14558 stillprimalfeasible =
14559 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14560 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14561 }
14562 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14563 {
14564 double compslack;
14565
14566 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14567 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14568 * variables, which would magnify even the tiniest violation in the dual multiplier
14569 */
14570 if( stilldualfeasible )
14571 {
14572 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14573 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14574 }
14575 if( stilldualfeasible )
14576 {
14577 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14578 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14579 }
14580
14581 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14582 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14583 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14584 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14585 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14586 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14587 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14588 dualfeasible != NULL ? stilldualfeasible : TRUE);
14589 }
14590 else
14591 {
14592 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14593 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14594 * strictly within left-hand and right-hand side, its dual multiplier must be zero
14595 */
14596 if( stilldualfeasible &&
14597 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14598 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14599 if( stilldualfeasible &&
14600 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14601 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14602
14603 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14604 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14605 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14606 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14607 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14608 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14609 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14610 dualfeasible != NULL ? stilldualfeasible : TRUE);
14611 }
14612
14613 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14614 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14615 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14616 */
14617 if( stilldualfeasible )
14618 {
14619 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14620 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14621 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14622 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14623 }
14624 }
14625
14626 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14627 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14628 * infinity
14629 */
14630 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14631 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14632 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14633 {
14634 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14635 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14636 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14637 }
14638
14639 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14640 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14641 */
14642 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14643 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14644 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14645 {
14646 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14647 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14648 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14649 }
14650
14651 if( primalfeasible != NULL )
14652 *primalfeasible = stillprimalfeasible;
14653 if( dualfeasible != NULL )
14654 *dualfeasible = stilldualfeasible;
14655
14656 /* free temporary memory */
14657 SCIPsetFreeBufferArray(set, &rstat);
14658 SCIPsetFreeBufferArray(set, &cstat);
14659 SCIPsetFreeBufferArray(set, &redcost);
14660#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14661 SCIPsetFreeBufferArray(set, &activity);
14662#endif
14663 SCIPsetFreeBufferArray(set, &dualsol);
14665
14666 return SCIP_OKAY;
14667}
14668
14669/** stores LP solution with infinite objective value in the columns and rows */
14671 SCIP_LP* lp, /**< current LP data */
14672 SCIP_SET* set, /**< global SCIP settings */
14673 SCIP_STAT* stat, /**< problem statistics */
14674 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14675 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14676 )
14677{
14678 SCIP_COL** lpicols;
14679 SCIP_ROW** lpirows;
14681 SCIP_Real* activity;
14682 SCIP_Real* ray;
14683 SCIP_Real rayobjval;
14684 SCIP_Real rayscale;
14685 SCIP_Longint lpcount;
14686 SCIP_COL* col;
14687 int nlpicols;
14688 int nlpirows;
14689 int c;
14690 int r;
14691
14692 assert(lp != NULL);
14693 assert(lp->flushed);
14694 assert(lp->solved);
14697 assert(set != NULL);
14698 assert(stat != NULL);
14699 assert(lp->validsollp <= stat->lpcount);
14700
14701 if( primalfeasible != NULL )
14702 *primalfeasible = TRUE;
14703 if( rayfeasible != NULL )
14704 *rayfeasible = TRUE;
14705
14706 /* check if the values are already calculated */
14707 if( lp->validsollp == stat->lpcount )
14708 return SCIP_OKAY;
14709 lp->validsollp = stat->lpcount;
14710
14711 /* check if the LP solver is able to provide a primal unbounded ray */
14712 if( !SCIPlpiHasPrimalRay(lp->lpi) )
14713 {
14714 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14715 return SCIP_LPERROR;
14716 }
14717
14718 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14719
14720 /* get temporary memory */
14722 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14724
14725 /* get primal unbounded ray */
14726 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14727
14728 lpicols = lp->lpicols;
14729 lpirows = lp->lpirows;
14730 nlpicols = lp->nlpicols;
14731 nlpirows = lp->nlpirows;
14732 lpcount = stat->lpcount;
14733
14734 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14735 rayobjval = 0.0;
14736 for( c = 0; c < nlpicols; ++c )
14737 {
14738 assert(lpicols[c] != NULL);
14739 assert(lpicols[c]->var != NULL);
14740
14741 col = lpicols[c];
14742
14743 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14744 if( rayfeasible != NULL )
14745 {
14746 *rayfeasible = *rayfeasible
14747 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14748 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub));
14749 }
14750
14751 if( ! SCIPsetIsZero(set, ray[c]) )
14752 rayobjval += ray[c] * col->obj;
14753
14754 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14755 * heuristically try to construct a primal solution.
14756 */
14757 primsol[c] = 0.0;
14758 if( SCIPsetIsFeasZero(set, ray[c]) )
14759 {
14760 /* if the ray component is 0, we try to satisfy as many rows as possible */
14761 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14762 primsol[c] = col->lb;
14763 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14764 primsol[c] = col->ub;
14765 }
14766
14767 /* make sure we respect the bounds */
14768 primsol[c] = MAX(primsol[c], col->lb);
14769 primsol[c] = MIN(primsol[c], col->ub);
14770
14771 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14772 }
14773
14774 /* check feasibility of heuristic primal solution */
14775 for( r = 0; r < nlpirows; ++r )
14776 {
14777 SCIP_Real act;
14778 SCIP_ROW* row;
14779
14780 row = lpirows[r];
14781 assert( row != NULL );
14782 act = row->constant;
14783
14784 for( c = 0; c < row->nlpcols; ++c )
14785 {
14786 col = row->cols[c];
14787
14788 assert( col != NULL );
14789 assert( col->lppos >= 0 );
14790 assert( row->linkpos[c] >= 0 );
14791 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14792
14793 act += row->vals[c] * primsol[col->lppos];
14794 }
14795
14796 if( row->nunlinked > 0 )
14797 {
14798 for( c = row->nlpcols; c < row->len; ++c )
14799 {
14800 col = row->cols[c];
14801 assert( col != NULL );
14802
14803 if( col->lppos >= 0 )
14804 act += row->vals[c] * primsol[col->lppos];
14805 }
14806 }
14807
14808 /* check feasibility */
14809 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14810 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14811 break;
14812 }
14813
14814 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14815 if( r < nlpirows )
14816 {
14817 /* get primal feasible point */
14819
14820 /* check bounds of primal solution */
14821 if( primalfeasible != NULL )
14822 {
14823 assert( *primalfeasible );
14824 for( c = 0; c < nlpicols; ++c )
14825 {
14826 assert( lpicols[c] != NULL );
14827 assert( lpicols[c]->var != NULL );
14828
14829 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14830 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14831 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14832 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14833 {
14834 *primalfeasible = FALSE;
14835 break;
14836 }
14837 }
14838 }
14839 }
14840
14841 /* compute activity and check feasibility of primal solution and ray */
14842 for( r = 0; r < nlpirows; ++r )
14843 {
14844 SCIP_Real primact;
14845 SCIP_Real rayact = 0.0;
14846 SCIP_ROW* row;
14847
14848 row = lpirows[r];
14849 assert( row != NULL );
14850
14851 primact = row->constant;
14852
14853 for( c = 0; c < row->nlpcols; ++c )
14854 {
14855 col = row->cols[c];
14856
14857 assert( col != NULL );
14858 assert( col->lppos >= 0 );
14859 assert( row->linkpos[c] >= 0 );
14860 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14861
14862 primact += row->vals[c] * primsol[col->lppos];
14863 rayact += row->vals[c] * ray[col->lppos];
14864 }
14865
14866 if( row->nunlinked > 0 )
14867 {
14868 for( c = row->nlpcols; c < row->len; ++c )
14869 {
14870 col = row->cols[c];
14871 assert( col != NULL );
14872
14873 if( col->lppos >= 0 )
14874 {
14875 primact += row->vals[c] * primsol[col->lppos];
14876 rayact += row->vals[c] * ray[col->lppos];
14877 }
14878 }
14879 }
14880
14881 /* check feasibility of primal solution */
14882 if( primalfeasible != NULL && *primalfeasible )
14883 {
14884 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14885 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14886 *primalfeasible = FALSE;
14887 }
14888
14889 /* check feasibility of ray */
14890 if( rayfeasible != NULL && *rayfeasible )
14891 {
14892 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14893 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14894 *rayfeasible = FALSE;
14895 }
14896
14897 /* store activity of primal solution */
14898 activity[r] = primact;
14899 }
14900
14901 if( primalfeasible != NULL && !(*primalfeasible) )
14902 {
14903 /* if the finite point is already infeasible, we do not have to add the ray */
14904 rayscale = 0.0;
14905 }
14906 else if( rayfeasible != NULL && !(*rayfeasible) )
14907 {
14908 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14909 rayscale = 0.0;
14910 }
14911 else if( !SCIPsetIsNegative(set, rayobjval) )
14912 {
14913 /* due to numerical problems, the objective of the ray might be nonnegative
14914 *
14915 * @todo How to check for negative objective value here?
14916 */
14917 if( rayfeasible != NULL )
14918 *rayfeasible = FALSE;
14919
14920 rayscale = 0.0;
14921 }
14922 else
14923 {
14924 assert(rayobjval != 0.0);
14925
14926 /* scale the ray, such that the resulting point has infinite objective value */
14927 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14928 assert(SCIPsetIsFeasPositive(set, rayscale));
14929
14930 /* ensure that unbounded point does not violate the bounds of the variables */
14931 for( c = 0; c < nlpicols; ++c )
14932 {
14933 if( SCIPsetIsPositive(set, ray[c]) )
14934 {
14935 if( !SCIPsetIsInfinity(set, primsol[c]) )
14936 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14937 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14938 else
14939 {
14940 assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14941 rayscale = MIN(rayscale, 1.0 / ray[c]);
14942 }
14943 }
14944 else if( SCIPsetIsNegative(set, ray[c]) )
14945 {
14946 if( !SCIPsetIsInfinity(set, -primsol[c]) )
14947 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14948 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14949 else
14950 {
14951 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14952 rayscale = MIN(rayscale, -1.0 / ray[c]);
14953 }
14954 }
14955
14956 assert(SCIPsetIsFeasPositive(set, rayscale));
14957 }
14958 }
14959
14960 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14961
14962 /* calculate the unbounded point: x' = x + rayscale * ray */
14963 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14964 * typically large values in scaling. */
14965 for( c = 0; c < nlpicols; ++c )
14966 {
14967 if( SCIPsetIsZero(set, ray[c]) )
14968 lpicols[c]->primsol = primsol[c];
14969 else
14970 {
14971 SCIP_Real primsolval;
14972 primsolval = primsol[c] + rayscale * ray[c];
14973 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14974 }
14975 lpicols[c]->redcost = SCIP_INVALID;
14976 lpicols[c]->validredcostlp = -1;
14977 }
14978
14979 /* transfer solution */
14980 for( r = 0; r < nlpirows; ++r )
14981 {
14982 lpirows[r]->dualsol = SCIP_INVALID;
14983 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14984 lpirows[r]->validactivitylp = lpcount;
14985 }
14986
14987 /* free temporary memory */
14989 SCIPsetFreeBufferArray(set, &activity);
14991
14992 return SCIP_OKAY;
14993}
14994
14995/** returns primal ray proving the unboundedness of the current LP */
14997 SCIP_LP* lp, /**< current LP data */
14998 SCIP_SET* set, /**< global SCIP settings */
14999 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
15000 * so the size of this array should be at least number of active variables
15001 * (all entries have to be initialized to 0 before) */
15002 )
15003{
15004 SCIP_COL** lpicols;
15005 SCIP_Real* lpiray;
15006 SCIP_VAR* var;
15007 int nlpicols;
15008 int c;
15009
15010 assert(lp != NULL);
15011 assert(set != NULL);
15012 assert(ray != NULL);
15013 assert(lp->flushed);
15014 assert(lp->solved);
15017
15018 /* check if the LP solver is able to provide a primal unbounded ray */
15019 if( !SCIPlpiHasPrimalRay(lp->lpi) )
15020 {
15021 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15022 return SCIP_LPERROR;
15023 }
15024
15025 /* get temporary memory */
15027
15028 SCIPsetDebugMsg(set, "getting primal ray values\n");
15029
15030 /* get primal unbounded ray */
15031 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15032
15033 lpicols = lp->lpicols;
15034 nlpicols = lp->nlpicols;
15035
15036 /* store the ray values of active problem variables */
15037 for( c = 0; c < nlpicols; c++ )
15038 {
15039 assert(lpicols[c] != NULL);
15040
15041 var = lpicols[c]->var;
15042 assert(var != NULL);
15044 ray[SCIPvarGetProbindex(var)] = lpiray[c];
15045 }
15046
15047 SCIPsetFreeBufferArray(set, &lpiray);
15048
15049 return SCIP_OKAY;
15050}
15051
15052/** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15053 * lp/checkfarkas = TRUE.
15054 *
15055 * @note the check will not be performed if @p valid is NULL.
15056 */
15058 SCIP_LP* lp, /**< current LP data */
15059 SCIP_SET* set, /**< global SCIP settings */
15060 SCIP_STAT* stat, /**< problem statistics */
15061 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
15062 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */
15063 )
15064{
15065 SCIP_COL** lpicols;
15066 SCIP_ROW** lpirows;
15067 SCIP_Real* dualfarkas;
15068 SCIP_Real* farkascoefs;
15069 SCIP_Real farkaslhs;
15070 SCIP_Real maxactivity;
15071 SCIP_Bool checkfarkas;
15072 int nlpicols;
15073 int nlpirows;
15074 int c;
15075 int r;
15076
15077 assert(lp != NULL);
15078 assert(lp->flushed);
15079 assert(lp->solved);
15081 assert(set != NULL);
15082 assert(stat != NULL);
15083 assert(lp->validfarkaslp <= stat->lpcount);
15084
15085 if( valid != NULL )
15086 *valid = TRUE;
15087
15088 /* check if the values are already calculated */
15089 if( lp->validfarkaslp == stat->lpcount )
15090 return SCIP_OKAY;
15091 lp->validfarkaslp = stat->lpcount;
15092
15093 farkascoefs = NULL;
15094 maxactivity = 0.0;
15095 farkaslhs = 0.0;
15096 checkfarkas = set->lp_checkfarkas && valid != NULL;
15097
15098 /* get temporary memory */
15099 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15100
15101 if( checkfarkas )
15102 {
15103 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15104 BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15105 }
15106
15107 /* get dual Farkas infeasibility proof */
15108 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15109
15110 lpicols = lp->lpicols;
15111 lpirows = lp->lpirows;
15112 nlpicols = lp->nlpicols;
15113 nlpirows = lp->nlpirows;
15114
15115 /* store infeasibility proof in rows */
15116 SCIPsetDebugMsg(set, "LP is infeasible:\n");
15117 for( r = 0; r < nlpirows; ++r )
15118 {
15119 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15120 lpirows[r]->dualfarkas = dualfarkas[r];
15121 lpirows[r]->dualsol = SCIP_INVALID;
15122 lpirows[r]->activity = 0.0;
15123 lpirows[r]->validactivitylp = -1L;
15124 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15125
15126 if( checkfarkas && dualfarkas[r] != 0.0 ) /*lint !e777*/
15127 {
15128 assert(valid != NULL);
15129 assert(farkascoefs != NULL);
15130
15131 /* the infeasibility proof would be invalid if
15132 * (i) dualfarkas[r] > 0 and lhs = -inf
15133 * (ii) dualfarkas[r] < 0 and rhs = inf
15134 * however, due to numerics we accept slightly negative / positive values
15135 */
15136 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15137 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15138 {
15139 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15140 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15141
15142 *valid = FALSE;
15143 goto TERMINATE;
15144 }
15145
15146 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15147 * within tolerances (see above) but slighty positive / negative
15148 */
15149 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15150 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15151 continue;
15152
15153 /* iterate over all columns and scale with dual solution */
15154 for( c = 0; c < lpirows[r]->len; c++ )
15155 {
15156 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15157
15158 if( pos == -1 )
15159 continue;
15160
15161 assert(pos >= 0 && pos < nlpicols);
15162
15163 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15164 }
15165
15166 /* the row contributes with its left-hand side to the proof */
15167 if( dualfarkas[r] > 0.0 )
15168 {
15169 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15170
15171 farkaslhs += dualfarkas[r] * lpirows[r]->lhs;
15172 }
15173 /* the row contributes with its right-hand side to the proof */
15174 else if( dualfarkas[r] < 0.0 )
15175 {
15176 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15177
15178 farkaslhs += dualfarkas[r] * lpirows[r]->rhs;
15179 }
15180
15181 maxactivity += dualfarkas[r] * lpirows[r]->constant;
15182 }
15183 }
15184
15185 /* set columns as invalid */
15186 for( c = 0; c < nlpicols; ++c )
15187 {
15188 lpicols[c]->primsol = SCIP_INVALID;
15189 lpicols[c]->redcost = SCIP_INVALID;
15190 lpicols[c]->validredcostlp = -1L;
15191 lpicols[c]->validfarkaslp = -1L;
15192
15193 if( checkfarkas )
15194 {
15195 assert(valid != NULL);
15196 assert(farkascoefs != NULL);
15197 assert(SCIPcolGetLPPos(lpicols[c]) == c);
15198
15199 /* skip coefficients that are too close to zero */
15200 if( SCIPsetIsDualfeasZero(set, farkascoefs[c]) )
15201 continue;
15202
15203 /* calculate the maximal activity */
15204 if( farkascoefs[c] > 0.0 )
15205 {
15206 maxactivity += farkascoefs[c] * lpicols[c]->ub;
15207
15208 if( SCIPsetIsInfinity(set, lpicols[c]->ub) )
15209 {
15210 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15211 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15212
15213 *valid = FALSE;
15214 goto TERMINATE;
15215 }
15216 }
15217 else
15218 {
15219 maxactivity += farkascoefs[c] * lpicols[c]->lb;
15220
15221 if( SCIPsetIsInfinity(set, -lpicols[c]->lb) )
15222 {
15223 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15224 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15225
15226 *valid = FALSE;
15227 goto TERMINATE;
15228 }
15229 }
15230 }
15231 }
15232
15233 /* check whether the farkasproof is valid for relative epsilon tolerance to allow feasibility tightening */
15234 if( checkfarkas
15235 && ( SCIPsetIsInfinity(set, maxactivity) || SCIPsetIsInfinity(set, -farkaslhs) || SCIPsetIsRelGE(set, maxactivity, farkaslhs) ) )
15236 {
15237 assert(valid != NULL);
15238
15239 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15240
15241 if( forcedlpsolve && SCIPsetIsLT(set, maxactivity, farkaslhs) )
15242 SCIPmessagePrintWarning(set->scip->messagehdlr, "Unreliable farkas proof forced valid, result might not be optimal.\n");
15243 else
15244 *valid = FALSE;
15245 }
15246
15247 TERMINATE:
15248 /* free temporary memory */
15249 if( checkfarkas )
15250 SCIPsetFreeBufferArray(set, &farkascoefs);
15251
15252 SCIPsetFreeBufferArray(set, &dualfarkas);
15253
15254 return SCIP_OKAY;
15255}
15256
15257/** get number of iterations used in last LP solve */
15259 SCIP_LP* lp, /**< current LP data */
15260 int* iterations /**< pointer to store the iteration count */
15261 )
15262{
15263 assert(lp != NULL);
15264
15265 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15266
15267 return SCIP_OKAY;
15268}
15269
15270/** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15271 * resets age of non-zero columns and sharp rows
15272 */
15274 SCIP_LP* lp, /**< current LP data */
15275 SCIP_STAT* stat /**< problem statistics */
15276 )
15277{
15278 SCIP_COL** lpicols;
15279 SCIP_ROW** lpirows;
15280 int nlpicols;
15281 int nlpirows;
15282 int c;
15283 int r;
15284
15285 assert(lp != NULL);
15286 assert(lp->flushed);
15287 assert(lp->solved);
15288 assert(lp->nlpicols == lp->ncols);
15289 assert(lp->nlpirows == lp->nrows);
15290 assert(stat != NULL);
15291 assert(lp->validsollp == stat->lpcount);
15292
15293 SCIPdebugMessage("updating LP ages\n");
15294
15295 lpicols = lp->lpicols;
15296 lpirows = lp->lpirows;
15297 nlpicols = lp->nlpicols;
15298 nlpirows = lp->nlpirows;
15299
15300 for( c = 0; c < nlpicols; ++c )
15301 {
15302 assert(lpicols[c] == lp->cols[c]);
15303 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
15304 lpicols[c]->age++;
15305 else
15306 lpicols[c]->age = 0;
15307 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15308 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15309 }
15310
15311 for( r = 0; r < nlpirows; ++r )
15312 {
15313 lpirows[r]->nlpsaftercreation++;
15314 assert(lpirows[r] == lp->rows[r]);
15315
15316 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15317 {
15318 lpirows[r]->age++;
15319 }
15320 else
15321 {
15322 lpirows[r]->activeinlpcounter++;
15323 lpirows[r]->age = 0;
15324 }
15325 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15326 }
15327
15328 return SCIP_OKAY;
15329}
15330
15331/* deletes the marked columns from the LP and the LP interface */
15332static
15334 SCIP_LP* lp, /**< current LP data */
15335 SCIP_SET* set, /**< global SCIP settings */
15336 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
15337 )
15338{
15339 SCIP_COL* col;
15340 int ncols;
15341 int c;
15342
15343 assert(lp != NULL);
15344 assert(lp->flushed);
15345 assert(lp->ncols == lp->nlpicols);
15346 assert(!lp->diving);
15347 assert(coldstat != NULL);
15348 assert(lp->nlazycols <= lp->ncols);
15349
15350 ncols = lp->ncols;
15351
15352 /* delete columns in LP solver */
15353 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15354
15355 /* update LP data respectively */
15356 for( c = 0; c < ncols; ++c )
15357 {
15358 col = lp->cols[c];
15359 assert(col != NULL);
15360 assert(col == lp->lpicols[c]);
15361 assert(coldstat[c] <= c);
15362 col->lppos = coldstat[c];
15363 if( coldstat[c] == -1 )
15364 {
15365 assert(col->removable);
15366
15367 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15368 * function vector norms
15369 */
15370 markColDeleted(col);
15371 colUpdateDelLP(col, set);
15372 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15373 col->lpdepth = -1;
15374
15375 lp->cols[c] = NULL;
15376 lp->lpicols[c] = NULL;
15377 lp->ncols--;
15378 lp->nremovablecols--;
15379 lp->nlpicols--;
15380 }
15381 else if( coldstat[c] < c )
15382 {
15383 assert(lp->cols[coldstat[c]] == NULL);
15384 assert(lp->lpicols[coldstat[c]] == NULL);
15385 lp->cols[coldstat[c]] = col;
15386 lp->lpicols[coldstat[c]] = col;
15387 lp->cols[coldstat[c]]->lppos = coldstat[c];
15388 lp->cols[coldstat[c]]->lpipos = coldstat[c];
15389 lp->cols[c] = NULL;
15390 lp->lpicols[c] = NULL;
15391 }
15392 }
15393
15394 /* remove columns which are deleted from the lazy column array */
15395 c = 0;
15396 while( c < lp->nlazycols )
15397 {
15398 if( lp->lazycols[c]->lpipos < 0 )
15399 {
15400 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15401 lp->nlazycols--;
15402 }
15403 else
15404 c++;
15405 }
15406
15407 /* mark LP to be unsolved */
15408 if( lp->ncols < ncols )
15409 {
15410 assert(lp->ncols == lp->nlpicols);
15411 assert(lp->nchgcols == 0);
15412 assert(lp->flushed);
15413
15414 lp->lpifirstchgcol = lp->nlpicols;
15415
15416 /* mark the current solution invalid */
15417 lp->solved = FALSE;
15418 lp->primalfeasible = FALSE;
15419 lp->primalchecked = FALSE;
15420 lp->lpobjval = SCIP_INVALID;
15422 }
15423
15425 checkLinks(lp);
15426
15427 return SCIP_OKAY;
15428}
15429
15430/* deletes the marked rows from the LP and the LP interface */
15431static
15433 SCIP_LP* lp, /**< current LP data */
15434 BMS_BLKMEM* blkmem, /**< block memory buffers */
15435 SCIP_SET* set, /**< global SCIP settings */
15436 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15437 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15438 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
15439 )
15440{
15441 SCIP_ROW* row;
15442 int nrows;
15443 int r;
15444
15445 assert(lp != NULL);
15446 assert(lp->flushed);
15447 assert(lp->nrows == lp->nlpirows);
15448 assert(!lp->diving);
15449 assert(rowdstat != NULL);
15450
15451 nrows = lp->nrows;
15452
15453 /* delete rows in LP solver */
15454 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15455
15456 /* update LP data respectively */
15457 for( r = 0; r < nrows; ++r )
15458 {
15459 row = lp->rows[r];
15460 assert(row == lp->lpirows[r]);
15461 assert(rowdstat[r] <= r);
15462 assert(row != NULL);
15463 row->lppos = rowdstat[r];
15464 if( rowdstat[r] == -1 )
15465 {
15466 if( row->removable )
15467 lp->nremovablerows--;
15468
15469 /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15470 markRowDeleted(row);
15471 rowUpdateDelLP(row);
15472 row->lpdepth = -1;
15473
15474 /* check, if row deletion events are tracked
15475 * if so, issue ROWDELETEDLP event
15476 */
15477 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15478 {
15479 SCIP_EVENT* event;
15480
15481 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15482 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15483 }
15484
15485 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15486 SCIProwUnlock(lp->rows[r]);
15487 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15488 assert(lp->lpirows[r] == NULL);
15489 assert(lp->rows[r] == NULL);
15490 lp->nrows--;
15491 lp->nlpirows--;
15492 }
15493 else if( rowdstat[r] < r )
15494 {
15495 assert(lp->rows[rowdstat[r]] == NULL);
15496 assert(lp->lpirows[rowdstat[r]] == NULL);
15497 lp->rows[rowdstat[r]] = row;
15498 lp->lpirows[rowdstat[r]] = row;
15499 lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15500 lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15501 lp->rows[r] = NULL;
15502 lp->lpirows[r] = NULL;
15503 }
15504 }
15505
15506 /* mark LP to be unsolved */
15507 if( lp->nrows < nrows )
15508 {
15509 assert(lp->nrows == lp->nlpirows);
15510 assert(lp->nchgrows == 0);
15511 assert(lp->flushed);
15512
15513 lp->lpifirstchgrow = lp->nlpirows;
15514
15515 /* mark the current solution invalid */
15516 lp->solved = FALSE;
15517 lp->dualfeasible = FALSE;
15518 lp->dualchecked = FALSE;
15519 lp->lpobjval = SCIP_INVALID;
15521 }
15522
15523 checkLinks(lp);
15524
15525 return SCIP_OKAY;
15526}
15527
15528/** removes all non-basic columns, that are too old, beginning with the given firstcol */
15529static
15531 SCIP_LP* lp, /**< current LP data */
15532 SCIP_SET* set, /**< global SCIP settings */
15533 SCIP_STAT* stat, /**< problem statistics */
15534 int firstcol /**< first column to check for clean up */
15535 )
15536{
15537 SCIP_COL** cols;
15538#ifndef NDEBUG
15539 SCIP_COL** lpicols;
15540#endif
15541 int* coldstat;
15542 int ncols;
15543 int ndelcols;
15544 int c;
15545
15546 assert(lp != NULL);
15547 assert(lp->flushed);
15548 assert(lp->ncols == lp->nlpicols);
15549 assert(lp->nremovablecols <= lp->ncols);
15550 assert(!lp->diving);
15551 assert(set != NULL);
15552 assert(stat != NULL);
15553
15554 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15555 return SCIP_OKAY;
15556
15557 ncols = lp->ncols;
15558 cols = lp->cols;
15559#ifndef NDEBUG
15560 lpicols = lp->lpicols;
15561#endif
15562
15563 /* get temporary memory */
15564 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15565
15566 /* mark obsolete columns to be deleted */
15567 ndelcols = 0;
15568 BMSclearMemoryArray(coldstat, ncols);
15569 for( c = firstcol; c < ncols; ++c )
15570 {
15571 assert(cols[c] == lpicols[c]);
15572 assert(cols[c]->lppos == c);
15573 assert(cols[c]->lpipos == c);
15574 if( cols[c]->removable
15575 && 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 */
15576 && cols[c]->age > set->lp_colagelimit
15578 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15579 {
15580 assert(cols[c]->primsol == 0.0);
15581 coldstat[c] = 1;
15582 ndelcols++;
15583 cols[c]->obsoletenode = stat->nnodes;
15584 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15585 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15586 }
15587 }
15588
15589 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15590
15591 /* delete the marked columns in the LP solver interface, update the LP respectively */
15592 if( ndelcols > 0 )
15593 {
15594 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15595 }
15596 assert(lp->ncols == ncols - ndelcols);
15597
15598 /* release temporary memory */
15599 SCIPsetFreeBufferArray(set, &coldstat);
15600
15601 return SCIP_OKAY;
15602}
15603
15604/** removes all basic rows, that are too old, beginning with the given firstrow */
15605static
15607 SCIP_LP* lp, /**< current LP data */
15608 BMS_BLKMEM* blkmem, /**< block memory buffers */
15609 SCIP_SET* set, /**< global SCIP settings */
15610 SCIP_STAT* stat, /**< problem statistics */
15611 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15612 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15613 int firstrow /**< first row to check for clean up */
15614 )
15615{
15616 SCIP_ROW** rows;
15617#ifndef NDEBUG
15618 SCIP_ROW** lpirows;
15619#endif
15620 int* rowdstat;
15621 int nrows;
15622 int ndelrows;
15623 int r;
15624
15625 assert(lp != NULL);
15626 assert(lp->flushed);
15627 assert(lp->nrows == lp->nlpirows);
15628 assert(lp->nremovablerows <= lp->nrows);
15629 assert(!lp->diving);
15630 assert(set != NULL);
15631 assert(stat != NULL);
15632
15633 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15634 return SCIP_OKAY;
15635
15636 nrows = lp->nrows;
15637 rows = lp->rows;
15638#ifndef NDEBUG
15639 lpirows = lp->lpirows;
15640#endif
15641
15642 /* get temporary memory */
15643 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15644
15645 /* mark obsolete rows to be deleted */
15646 ndelrows = 0;
15647 BMSclearMemoryArray(rowdstat, nrows);
15648 for( r = firstrow; r < nrows; ++r )
15649 {
15650 assert(rows[r] == lpirows[r]);
15651 assert(rows[r]->lppos == r);
15652 assert(rows[r]->lpipos == r);
15653 if( rows[r]->removable
15654 && 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 */
15655 && rows[r]->age > set->lp_rowagelimit
15657 {
15658 rowdstat[r] = 1;
15659 ndelrows++;
15660 rows[r]->obsoletenode = stat->nnodes;
15661 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15662 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15663 }
15664 }
15665
15666 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15667
15668 /* delete the marked rows in the LP solver interface, update the LP respectively */
15669 if( ndelrows > 0 )
15670 {
15671 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15672 }
15673 assert(lp->nrows == nrows - ndelrows);
15674
15675 /* release temporary memory */
15676 SCIPsetFreeBufferArray(set, &rowdstat);
15677
15678 return SCIP_OKAY;
15679}
15680
15681/** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15683 SCIP_LP* lp, /**< current LP data */
15684 BMS_BLKMEM* blkmem, /**< block memory buffers */
15685 SCIP_SET* set, /**< global SCIP settings */
15686 SCIP_STAT* stat, /**< problem statistics */
15687 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15688 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15689 )
15690{
15691 assert(lp != NULL);
15692 assert(lp->solved);
15693 assert(!lp->diving);
15695 assert(set != NULL);
15696
15697 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15698 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15699
15700 if( lp->firstnewcol < lp->ncols )
15701 {
15702 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15703 }
15704 if( lp->firstnewrow < lp->nrows )
15705 {
15706 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15707 }
15708
15709 return SCIP_OKAY;
15710}
15711
15712/** removes all non-basic columns and basic rows in whole LP, that are too old */
15714 SCIP_LP* lp, /**< current LP data */
15715 BMS_BLKMEM* blkmem, /**< block memory buffers */
15716 SCIP_SET* set, /**< global SCIP settings */
15717 SCIP_STAT* stat, /**< problem statistics */
15718 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15719 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15720 )
15721{
15722 assert(lp != NULL);
15723 assert(lp->solved);
15724 assert(!lp->diving);
15726 assert(set != NULL);
15727
15728 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15729
15730 if( 0 < lp->ncols )
15731 {
15732 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15733 }
15734 if( 0 < lp->nrows )
15735 {
15736 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15737 }
15738
15739 return SCIP_OKAY;
15740}
15741
15742/** removes all non-basic columns at 0.0 beginning with the given firstcol */
15743static
15745 SCIP_LP* lp, /**< current LP data */
15746 SCIP_SET* set, /**< global SCIP settings */
15747 SCIP_STAT* stat, /**< problem statistics */
15748 int firstcol /**< first column to check for clean up */
15749 )
15750{
15751 SCIP_COL** cols;
15752 SCIP_COL** lpicols;
15753 int* coldstat;
15754 int ncols;
15755 int ndelcols;
15756 int c;
15757
15758 assert(lp != NULL);
15759 assert(lp->flushed);
15760 assert(lp->ncols == lp->nlpicols);
15761 assert(!lp->diving);
15762 assert(stat != NULL);
15763 assert(lp->validsollp == stat->lpcount);
15764 assert(0 <= firstcol && firstcol < lp->ncols);
15765
15766 if( lp->nremovablecols == 0 || !lp->solisbasic )
15767 return SCIP_OKAY;
15768
15769 ncols = lp->ncols;
15770 cols = lp->cols;
15771 lpicols = lp->lpicols;
15772
15773 /* get temporary memory */
15774 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15775
15776 /* mark unused columns to be deleted */
15777 ndelcols = 0;
15778 BMSclearMemoryArray(coldstat, ncols);
15779 for( c = firstcol; c < ncols; ++c )
15780 {
15781 assert(cols[c] == lpicols[c]);
15782 assert(cols[c]->lppos == c);
15783 assert(cols[c]->lpipos == c);
15784 if( lpicols[c]->removable
15785 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15786 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15787 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15788 {
15789 coldstat[c] = 1;
15790 ndelcols++;
15791 }
15792 }
15793
15794 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15795
15796 /* delete the marked columns in the LP solver interface, update the LP respectively */
15797 if( ndelcols > 0 )
15798 {
15799 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15800 }
15801 assert(lp->ncols == ncols - ndelcols);
15802
15803 /* release temporary memory */
15804 SCIPsetFreeBufferArray(set, &coldstat);
15805
15806 return SCIP_OKAY;
15807}
15808
15809/** removes all basic rows beginning with the given firstrow */
15810static
15812 SCIP_LP* lp, /**< current LP data */
15813 BMS_BLKMEM* blkmem, /**< block memory buffers */
15814 SCIP_SET* set, /**< global SCIP settings */
15815 SCIP_STAT* stat, /**< problem statistics */
15816 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15817 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15818 int firstrow /**< first row to check for clean up */
15819 )
15820{
15821#ifndef NDEBUG
15822 SCIP_ROW** rows;
15823#endif
15824 SCIP_ROW** lpirows;
15825 int* rowdstat;
15826 int nrows;
15827 int ndelrows;
15828 int r;
15829
15830 assert(lp != NULL);
15831 assert(lp->flushed);
15832 assert(lp->ncols == lp->nlpicols);
15833 assert(lp->nrows == lp->nlpirows);
15834 assert(!lp->diving);
15835 assert(stat != NULL);
15836 assert(lp->validsollp == stat->lpcount);
15837 assert(0 <= firstrow && firstrow < lp->nrows);
15838
15839 if( lp->nremovablerows == 0 || !lp->solisbasic )
15840 return SCIP_OKAY;
15841
15842#ifndef NDEBUG
15843 rows = lp->rows;
15844#endif
15845 nrows = lp->nrows;
15846 lpirows = lp->lpirows;
15847
15848 /* get temporary memory */
15849 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15850
15851 /* mark unused rows to be deleted */
15852 ndelrows = 0;
15853 BMSclearMemoryArray(rowdstat, nrows);
15854 for( r = firstrow; r < nrows; ++r )
15855 {
15856 assert(rows[r] == lpirows[r]);
15857 assert(rows[r]->lppos == r);
15858 assert(rows[r]->lpipos == r);
15859 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15860 {
15861 rowdstat[r] = 1;
15862 ndelrows++;
15863 }
15864 }
15865
15866 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15867
15868 /* delete the marked rows in the LP solver interface, update the LP respectively */
15869 if( ndelrows > 0 )
15870 {
15871 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15872 }
15873 assert(lp->nrows == nrows - ndelrows);
15874
15875 /* release temporary memory */
15876 SCIPsetFreeBufferArray(set, &rowdstat);
15877
15878 return SCIP_OKAY;
15879}
15880
15881/** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15883 SCIP_LP* lp, /**< current LP data */
15884 BMS_BLKMEM* blkmem, /**< block memory buffers */
15885 SCIP_SET* set, /**< global SCIP settings */
15886 SCIP_STAT* stat, /**< problem statistics */
15887 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15888 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15889 SCIP_Bool root /**< are we at the root node? */
15890 )
15891{
15892 SCIP_Bool cleanupcols;
15893 SCIP_Bool cleanuprows;
15894
15895 assert(lp != NULL);
15896 assert(lp->solved);
15897 assert(!lp->diving);
15899 assert(set != NULL);
15900
15901 /* check, if we want to clean up the columns and rows */
15902 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15903 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15904
15905 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15906 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15907
15908 if( cleanupcols && lp->firstnewcol < lp->ncols )
15909 {
15910 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15911 }
15912 if( cleanuprows && lp->firstnewrow < lp->nrows )
15913 {
15914 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15915 }
15916
15917 return SCIP_OKAY;
15918}
15919
15920/** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15922 SCIP_LP* lp, /**< current LP data */
15923 BMS_BLKMEM* blkmem, /**< block memory buffers */
15924 SCIP_SET* set, /**< global SCIP settings */
15925 SCIP_STAT* stat, /**< problem statistics */
15926 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15927 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15928 SCIP_Bool root /**< are we at the root node? */
15929 )
15930{
15931 SCIP_Bool cleanupcols;
15932 SCIP_Bool cleanuprows;
15933
15934 assert(lp != NULL);
15935 assert(lp->solved);
15936 assert(!lp->diving);
15938 assert(set != NULL);
15939
15940 /* check, if we want to clean up the columns and rows */
15941 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15942 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15943
15944 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15945 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15946
15947 if( cleanupcols && 0 < lp->ncols )
15948 {
15949 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15950 }
15951 if( cleanuprows && 0 < lp->nrows )
15952 {
15953 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15954 }
15955
15956 return SCIP_OKAY;
15957}
15958
15959/** removes all redundant rows that were added at the current node */
15961 SCIP_LP* lp, /**< current LP data */
15962 BMS_BLKMEM* blkmem, /**< block memory buffers */
15963 SCIP_SET* set, /**< global SCIP settings */
15964 SCIP_STAT* stat, /**< problem statistics */
15965 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15966 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15967 )
15968{
15969#ifndef NDEBUG
15970 SCIP_ROW** rows;
15971#endif
15972 SCIP_ROW** lpirows;
15973 int* rowdstat;
15974 int nrows;
15975 int ndelrows;
15976 int r;
15977
15978 assert(lp != NULL);
15979 assert(lp->flushed);
15980 assert(lp->ncols == lp->nlpicols);
15981 assert(lp->nrows == lp->nlpirows);
15982 assert(!lp->diving);
15983 assert(stat != NULL);
15984 assert(lp->validsollp == stat->lpcount);
15985 assert(lp->firstnewrow <= lp->nrows);
15986
15987 if( lp->firstnewrow == lp->nrows )
15988 return SCIP_OKAY;
15989
15990#ifndef NDEBUG
15991 rows = lp->rows;
15992#endif
15993 nrows = lp->nrows;
15994 lpirows = lp->lpirows;
15995
15996 /* get temporary memory */
15997 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15998
15999 /* mark redundant rows to be deleted (only delete basic rows!) */
16000 ndelrows = 0;
16001 BMSclearMemoryArray(rowdstat, nrows);
16002 for( r = lp->firstnewrow; r < nrows; ++r )
16003 {
16004 assert(rows[r] == lpirows[r]);
16005 assert(rows[r]->lppos == r);
16006 assert(rows[r]->lpipos == r);
16007 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
16008 && SCIProwIsRedundant(lpirows[r], set, stat) )
16009 {
16010 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
16011 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
16012 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
16013 rowdstat[r] = 1;
16014 ndelrows++;
16015 }
16016 }
16017
16018 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
16019
16020 /* delete the marked rows in the LP solver interface, update the LP respectively */
16021 if( ndelrows > 0 )
16022 {
16023 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
16024 }
16025 assert(lp->nrows == nrows - ndelrows);
16026
16027 /* release temporary memory */
16028 SCIPsetFreeBufferArray(set, &rowdstat);
16029
16030 return SCIP_OKAY;
16031}
16032
16033/** initiates LP diving */
16035 SCIP_LP* lp, /**< current LP data */
16036 BMS_BLKMEM* blkmem, /**< block memory */
16037 SCIP_SET* set, /**< global SCIP settings */
16038 SCIP_STAT* stat /**< problem statistics */
16039 )
16040{
16041 int c;
16042 int r;
16043
16044 assert(lp != NULL);
16045 assert(lp->flushed || !lp->solved);
16046 assert(!lp->diving);
16047 assert(!lp->probing);
16048 assert(lp->divelpistate == NULL);
16051 assert(lp->validsollp <= stat->lpcount);
16052 assert(blkmem != NULL);
16053 assert(set != NULL);
16054 assert(lp->ndivechgsides == 0);
16055
16056 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16057 lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16058
16059#ifndef NDEBUG
16060 for( c = 0; c < lp->ncols; ++c )
16061 {
16062 assert(lp->cols[c] != NULL);
16063 assert(lp->cols[c]->var != NULL);
16065 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16069 }
16070#endif
16071
16072 /* save current LPI state (basis information) */
16073 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16078
16079 /* save current LP values dependent on the solution */
16080 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16081 assert(lp->storedsolvals != NULL);
16082 if( !set->lp_resolverestore && lp->solved )
16083 {
16084 SCIP_Bool store = TRUE;
16085
16086 switch ( lp->lpsolstat )
16087 {
16089 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16090 assert(lp->validsollp == stat->lpcount);
16091 break;
16094 assert(lp->validsollp == stat->lpcount);
16095 break;
16099 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16100 assert(lp->validsollp == stat->lpcount);
16101 break;
16103 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, FALSE, NULL) );
16104 break;
16107 default:
16108 store = FALSE;
16109 }
16110
16111 if ( store )
16112 {
16113 for( c = 0; c < lp->ncols; ++c )
16114 {
16115 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16116 }
16117 for( r = 0; r < lp->nrows; ++r )
16118 {
16120 }
16121 }
16122 }
16123
16124 /* store LPI iteration limit */
16126
16127 /* remember the number of domain changes */
16128 lp->divenolddomchgs = stat->domchgcount;
16129
16130 /* store current number of rows */
16131 lp->ndivingrows = lp->nrows;
16132
16133 /* switch to diving mode */
16134 lp->diving = TRUE;
16135
16136 return SCIP_OKAY;
16137}
16138
16139/** quits LP diving and resets bounds and objective values of columns to the current node's values */
16141 SCIP_LP* lp, /**< current LP data */
16142 BMS_BLKMEM* blkmem, /**< block memory */
16143 SCIP_SET* set, /**< global SCIP settings */
16144 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16145 SCIP_STAT* stat, /**< problem statistics */
16146 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16147 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16148 SCIP_PROB* prob, /**< problem data */
16149 SCIP_VAR** vars, /**< array with all active variables */
16150 int nvars /**< number of active variables */
16151 )
16152{
16153 SCIP_VAR* var;
16154 int v;
16155
16156 assert(lp != NULL);
16157 assert(lp->diving);
16158 assert(blkmem != NULL);
16159 assert(nvars == 0 || vars != NULL);
16160
16161 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16162
16163 /* reset all columns' objective values and bounds to its original values */
16164 for( v = 0; v < nvars; ++v )
16165 {
16166 var = vars[v];
16167 assert(var != NULL);
16169 {
16173 }
16174 }
16175
16176 /* remove rows which were added in diving mode */
16177 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16178
16179 /* undo changes to left hand sides and right hand sides */
16180 while( lp->ndivechgsides > 0 )
16181 {
16182 SCIP_Real oldside;
16183 SCIP_SIDETYPE sidetype;
16184 SCIP_ROW* row;
16185
16186 lp->ndivechgsides--;
16187 oldside = lp->divechgsides[lp->ndivechgsides];
16188 sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16189 row = lp->divechgrows[lp->ndivechgsides];
16190
16191 if( sidetype == SCIP_SIDETYPE_LEFT )
16192 {
16193 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16194 }
16195 else
16196 {
16197 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16198 }
16199 }
16200
16201 /* restore LPI iteration limit */
16203
16204 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16205 * happens
16206 */
16207 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16209 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16210 lp->divelpwasprimfeas = TRUE;
16211 lp->divelpwasdualfeas = TRUE;
16214 assert(lp->divelpistate == NULL);
16215
16216 /* switch to standard (non-diving) mode */
16217 lp->diving = FALSE;
16218 lp->divingobjchg = FALSE;
16219
16220 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16221 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16222 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16223 * the parameter resolverestore to TRUE
16224 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16225 */
16226 assert(lp->storedsolvals != NULL);
16227 if( lp->storedsolvals->lpissolved
16228 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16229 {
16231
16232 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, FALSE, &lperror) );
16233 if( lperror )
16234 {
16235 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16236 lp->resolvelperror = TRUE;
16237 }
16242 {
16243 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16244 "LP was not resolved to a sufficient status after diving\n");
16245 lp->resolvelperror = TRUE;
16246 }
16247 }
16248 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16249 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16250 * re-solve as above can lead to a different LP status
16251 */
16252 else
16253 {
16254 int c;
16255 int r;
16256
16257 /* if there are lazy bounds, remove them from the LP */
16258 if( lp->nlazycols > 0 )
16259 {
16260 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16261 * first resolve LP?
16262 */
16264 assert(lp->diving == lp->divinglazyapplied);
16265
16266 /* flush changes to the LP solver */
16267 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16268 }
16269
16270 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16271 SCIPstatIncrement(stat, set, lpcount);
16272
16273 /* restore LP solution values in lp data, columns and rows */
16274 if( lp->storedsolvals->lpissolved &&
16281 )
16282 {
16283 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16284
16285 for( c = 0; c < lp->ncols; ++c )
16286 {
16287 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16288 }
16289 for( r = 0; r < lp->nrows; ++r )
16290 {
16291 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16292 }
16293 }
16294 else
16295 {
16296 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16297 }
16298 }
16299
16300#ifndef NDEBUG
16301 {
16302 int c;
16303 for( c = 0; c < lp->ncols; ++c )
16304 {
16305 assert(lp->cols[c] != NULL);
16306 assert(lp->cols[c]->var != NULL);
16308 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16309 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16312 }
16313 }
16314#endif
16315
16316 return SCIP_OKAY;
16317}
16318
16319#define DIVESTACKGROWFACT 1.5
16320
16321/** records a current row side such that any change will be undone after diving */
16323 SCIP_LP* lp, /**< LP data object */
16324 SCIP_ROW* row, /**< row affected by the change */
16325 SCIP_SIDETYPE sidetype /**< side type */
16326 )
16327{
16328 assert(lp != NULL);
16329 assert(row != NULL);
16330
16331 if( lp->ndivechgsides == lp->divechgsidessize )
16332 {
16334 }
16336
16337 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16338 lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16339 lp->divechgrows[lp->ndivechgsides] = row;
16340 lp->ndivechgsides++;
16341
16342 return SCIP_OKAY;
16343}
16344
16345/** informs the LP that probing mode was initiated */
16347 SCIP_LP* lp /**< current LP data */
16348 )
16349{
16350 assert(lp != NULL);
16351 assert(!lp->probing);
16352 assert(!lp->strongbranching);
16354
16355 lp->probing = TRUE;
16356
16357 return SCIP_OKAY;
16358}
16359
16360/** informs the LP that probing mode was finished */
16362 SCIP_LP* lp /**< current LP data */
16363 )
16364{
16365 assert(lp != NULL);
16366 assert(lp->probing);
16367 assert(!lp->strongbranching);
16369
16370 lp->probing = FALSE;
16371
16372 return SCIP_OKAY;
16373}
16374
16375/** informs the LP that the probing mode is now used for strongbranching */
16377 SCIP_LP* lp /**< current LP data */
16378 )
16379{
16380 assert(lp != NULL);
16381 assert(lp->probing);
16382 assert(!lp->strongbranching);
16384
16386}
16387
16388/** informs the LP that the probing mode is not used for strongbranching anymore */
16390 SCIP_LP* lp /**< current LP data */
16391 )
16392{
16393 assert(lp != NULL);
16394 assert(lp->probing);
16395 assert(!lp->strongbranching);
16397
16399}
16400
16401/** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16402 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16403 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16404 * we have only left hand sides):
16405 * min{cx | b <= Ax, lb <= x <= ub}
16406 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
16407 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
16408 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
16409 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
16410 */
16411static
16413 SCIP_LP* lp, /**< current LP data */
16414 SCIP_SET* set, /**< global SCIP settings */
16415 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16416 SCIP_Real* bound /**< result of interval arithmetic minimization */
16417 )
16418{
16419 SCIP_INTERVAL* yinter;
16421 SCIP_INTERVAL ytb;
16422 SCIP_INTERVAL prod;
16423 SCIP_INTERVAL diff;
16425 SCIP_INTERVAL minprod;
16427 SCIP_ROW* row;
16428 SCIP_COL* col;
16429 SCIP_Real y;
16430 SCIP_Real c;
16431 int i;
16432 int j;
16433
16434 assert(lp != NULL);
16435 assert(lp->solved);
16436 assert(set != NULL);
16437 assert(bound != NULL);
16438
16439 /* allocate buffer for storing y in interval arithmetic */
16440 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16441
16442 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16443 SCIPintervalSet(&ytb, 0.0);
16444 for( j = 0; j < lp->nrows; ++j )
16445 {
16446 row = lp->rows[j];
16447 assert(row != NULL);
16448
16449 y = (usefarkas ? row->dualfarkas : row->dualsol);
16450
16452 {
16453 SCIPintervalSet(&yinter[j], y);
16454 SCIPintervalSet(&b, row->lhs - row->constant);
16455 }
16456 else if( SCIPsetIsFeasNegative(set, y) )
16457 {
16458 SCIPintervalSet(&yinter[j], y);
16459 SCIPintervalSet(&b, row->rhs - row->constant);
16460 }
16461 else
16462 {
16463 SCIPintervalSet(&yinter[j], 0.0);
16464 SCIPintervalSet(&b, 0.0);
16465 }
16466
16467 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16468 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16469 }
16470
16471 /* calculate min{(c^T - y^TA)x} */
16472 SCIPintervalSet(&minprod, 0.0);
16473 for( j = 0; j < lp->ncols; ++j )
16474 {
16475 col = lp->cols[j];
16476 assert(col != NULL);
16477 assert(col->nunlinked == 0);
16478
16480
16481 c = usefarkas ? 0.0 : col->obj;
16482 SCIPintervalSet(&diff, c);
16483
16484 for( i = 0; i < col->nlprows; ++i )
16485 {
16486 assert(col->rows[i] != NULL);
16487 assert(col->rows[i]->lppos >= 0);
16488 assert(col->linkpos[i] >= 0);
16489 SCIPintervalSet(&a, col->vals[i]);
16490 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16491 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16492 }
16493
16494#ifndef NDEBUG
16495 for( i = col->nlprows; i < col->len; ++i )
16496 {
16497 assert(col->rows[i] != NULL);
16498 assert(col->rows[i]->lppos == -1);
16499 assert(col->rows[i]->dualsol == 0.0);
16500 assert(col->rows[i]->dualfarkas == 0.0);
16501 assert(col->linkpos[i] >= 0);
16502 }
16503#endif
16504
16505 SCIPintervalSetBounds(&x, col->lb, col->ub);
16506 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16507 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16508 }
16509
16510 /* add y^Tb */
16511 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16512
16513 /* free buffer for storing y in interval arithmetic */
16514 SCIPsetFreeBufferArray(set, &yinter);
16515
16516 *bound = SCIPintervalGetInf(minprod);
16517
16518 return SCIP_OKAY;
16519}
16520
16521/** gets proven lower (dual) bound of last LP solution */
16523 SCIP_LP* lp, /**< current LP data */
16524 SCIP_SET* set, /**< global SCIP settings */
16525 SCIP_Real* bound /**< pointer to store proven dual bound */
16526 )
16527{
16529
16530 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16531
16532 return SCIP_OKAY;
16533}
16534
16535/** gets proven dual bound of last LP solution */
16537 SCIP_LP* lp, /**< current LP data */
16538 SCIP_SET* set, /**< global SCIP settings */
16539 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
16540 )
16541{
16543
16544 assert(proved != NULL);
16545
16546 SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16547
16548 *proved = (bound > 0.0);
16549
16550 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16551
16552 return SCIP_OKAY;
16553}
16554
16555
16556
16557/** writes LP to a file */
16559 SCIP_LP* lp, /**< current LP data */
16560 const char* fname /**< file name */
16561 )
16562{
16563 assert(lp != NULL);
16564 assert(fname != NULL);
16565
16566 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16567
16568 return SCIP_OKAY;
16569}
16570
16571/** writes MIP relaxation of the current B&B node to a file */
16573 SCIP_LP* lp, /**< current LP data */
16574 SCIP_SET* set, /**< global SCIP settings */
16575 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16576 const char* fname, /**< file name */
16577 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
16578 * troubles with reserved symbols? */
16579 SCIP_Bool origobj, /**< should the original objective function be used? */
16580 SCIP_OBJSENSE objsense, /**< objective sense */
16581 SCIP_Real objscale, /**< objective scaling factor */
16582 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
16583 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
16584 )
16585{
16586 FILE* file;
16587 int i;
16588 int j;
16589 char rowname[SCIP_MAXSTRLEN];
16590 SCIP_Real coeff;
16591
16592 assert(lp != NULL);
16593 assert(fname != NULL);
16594
16595 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16596 file = fopen(fname, "w");
16597 if( file == NULL )
16598 {
16599 SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16600 SCIPprintSysError(fname);
16601 return SCIP_FILECREATEERROR;
16602 }
16603
16604 /* print comments */
16605 if( genericnames )
16606 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16607 else
16608 {
16609 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16610 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16611 }
16612
16613 if( origobj && objoffset != 0.0 )
16614 {
16615 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16616 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16617 }
16618
16619 /* print objective function */
16620 /**@note the transformed problem in SCIP is always a minimization problem */
16621 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16622 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16623 else
16624 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16625
16626 /* print objective */
16627 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16628 j = 0;
16629 for( i = 0; i < lp->ncols; ++i )
16630 {
16631 if( lp->cols[i]->obj != 0.0 )
16632 {
16633 coeff = lp->cols[i]->obj;
16634 if( origobj )
16635 {
16636 coeff *= (SCIP_Real) objsense;
16637 coeff *= objscale;
16638 }
16639
16640 if( genericnames )
16641 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16642 else
16643 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16644
16645 ++j;
16646 if( j % 10 == 0 )
16647 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16648 }
16649 }
16650 /* add artificial variable 'objoffset' to transfer objective offset */
16651 if( origobj && objoffset != 0.0 )
16652 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16653
16654 /* print constraint section */
16655 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16656 for( i = 0; i < lp->nrows; i++ )
16657 {
16658 char type = 'i';
16659
16660 /* skip removable rows if we want to write them as lazy constraints */
16661 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16662 continue;
16663
16664 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16665 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16666 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16667 * type 'i' means: lhs and rhs are both infinite */
16669 type = 'r';
16670 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16671 type = 'l';
16672 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16673 type = 'e';
16674 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16675 type = 'b';
16676
16677 /* print name of row */
16678 if( genericnames )
16679 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16680 else
16681 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16682
16683 WRITEROW:
16684 switch( type )
16685 {
16686 case 'r':
16687 case 'l':
16688 case 'e':
16689 if( strlen(rowname) > 0 )
16690 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16691 break;
16692 case 'i':
16693 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16694 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16695 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16696 type = 'b';
16697 /*lint -fallthrough*/
16698 case 'b':
16699 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16700 break;
16701 default:
16702 assert(type == 'B');
16703 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16704 break;
16705 }
16706
16707 /* print coefficients and variables */
16708 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16709 {
16710 if( genericnames )
16711 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16712 else
16713 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16714
16715 if( (j+1) % 10 == 0 )
16716 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16717 }
16718
16719 /* print right hand side */
16720 switch( type )
16721 {
16722 case 'b':
16723 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16724 type = 'B';
16725 goto WRITEROW;
16726 case 'l':
16727 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16728 break;
16729 case 'B':
16730 case 'r':
16731 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16732 break;
16733 case 'e':
16734 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16735 break;
16736 default:
16737 SCIPerrorMessage("Undefined row type!\n");
16738 fclose(file);
16739 return SCIP_ERROR;
16740 }
16741 }
16742
16743 if ( lazyconss )
16744 {
16745 /* print lazy constraint section */
16746 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16747 for( i = 0; i < lp->nrows; i++ )
16748 {
16749 char type = 'i';
16750
16751 /* skip non-removable rows if we want to write lazy constraints */
16752 if ( ! SCIProwIsRemovable(lp->rows[i]) )
16753 continue;
16754
16755 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16756 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16757 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16758 * type 'i' means: lhs and rhs are both infinite */
16760 type = 'r';
16761 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16762 type = 'l';
16763 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16764 type = 'e';
16765 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16766 type = 'b';
16767
16768 /* print name of row */
16769 if( genericnames )
16770 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16771 else
16772 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16773
16774 WRITELAZYROW:
16775 switch( type )
16776 {
16777 case 'r':
16778 case 'l':
16779 case 'e':
16780 if( strlen(rowname) > 0 )
16781 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16782 break;
16783 case 'i':
16784 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16785 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16786 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16787 type = 'b';
16788 /*lint -fallthrough*/
16789 case 'b':
16790 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16791 break;
16792 default:
16793 assert(type == 'B');
16794 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16795 break;
16796 }
16797
16798 /* print coefficients and variables */
16799 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16800 {
16801 if( genericnames )
16802 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16803 else
16804 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16805
16806 if( (j+1) % 10 == 0 )
16807 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16808 }
16809
16810 /* print right hand side */
16811 switch( type )
16812 {
16813 case 'b':
16814 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16815 type = 'B';
16816 goto WRITELAZYROW;
16817 case 'l':
16818 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16819 break;
16820 case 'B':
16821 case 'r':
16822 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16823 break;
16824 case 'e':
16825 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16826 break;
16827 default:
16828 SCIPerrorMessage("Undefined row type!\n");
16829 fclose(file);
16830 return SCIP_ERROR;
16831 }
16832 }
16833 }
16834
16835 /* print variable bounds */
16836 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16837 for( i = 0; i < lp->ncols; ++i )
16838 {
16839 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16840 {
16841 /* print lower bound as far this one is not infinity */
16842 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16843 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16844
16845 /* print variable name */
16846 if( genericnames )
16847 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16848 else
16849 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16850
16851 /* print upper bound as far this one is not infinity */
16852 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16853 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16854 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16855 }
16856 }
16857 if( origobj && objoffset != 0.0 )
16858 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16859
16860 /* print integer variables */
16861 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16862 j = 0;
16863 for( i = 0; i < lp->ncols; ++i )
16864 {
16865 if( SCIPvarIsIntegral(lp->cols[i]->var) )
16866 {
16867 /* print variable name */
16868 if( genericnames )
16869 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16870 else
16871 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16872
16873 j++;
16874 if( j % 10 == 0 )
16875 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16876 }
16877 }
16878
16879 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16880 fclose(file);
16881
16882 return SCIP_OKAY;
16883}
16884
16885/*
16886 * simple functions implemented as defines
16887 */
16888
16889/* In debug mode, the following methods are implemented as function calls to ensure
16890 * type validity.
16891 * In optimized mode, the methods are implemented as defines to improve performance.
16892 * However, we want to have them in the library anyways, so we have to undef the defines.
16893 */
16894
16895#undef SCIPcolGetObj
16896#undef SCIPcolGetLb
16897#undef SCIPcolGetUb
16898#undef SCIPcolGetBestBound
16899#undef SCIPcolGetPrimsol
16900#undef SCIPcolGetMinPrimsol
16901#undef SCIPcolGetMaxPrimsol
16902#undef SCIPcolGetBasisStatus
16903#undef SCIPcolGetVar
16904#undef SCIPcolGetIndex
16905#undef SCIPcolGetVarProbindex
16906#undef SCIPcolIsIntegral
16907#undef SCIPcolIsRemovable
16908#undef SCIPcolGetLPPos
16909#undef SCIPcolGetLPDepth
16910#undef SCIPcolIsInLP
16911#undef SCIPcolGetNNonz
16912#undef SCIPcolGetNLPNonz
16913#undef SCIPcolGetRows
16914#undef SCIPcolGetVals
16915#undef SCIPcolGetStrongbranchNode
16916#undef SCIPcolGetNStrongbranchs
16917#undef SCIPcolGetAge
16918#undef SCIPboundtypeOpposite
16919#undef SCIProwGetNNonz
16920#undef SCIProwGetNLPNonz
16921#undef SCIProwGetCols
16922#undef SCIProwGetVals
16923#undef SCIProwGetConstant
16924#undef SCIProwGetNorm
16925#undef SCIProwGetSumNorm
16926#undef SCIProwGetLhs
16927#undef SCIProwGetRhs
16928#undef SCIProwGetDualsol
16929#undef SCIProwGetDualfarkas
16930#undef SCIProwGetBasisStatus
16931#undef SCIProwGetName
16932#undef SCIProwGetIndex
16933#undef SCIProwGetAge
16934#undef SCIProwGetRank
16935#undef SCIProwIsIntegral
16936#undef SCIProwIsLocal
16937#undef SCIProwIsModifiable
16938#undef SCIProwIsRemovable
16939#undef SCIProwGetOrigintype
16940#undef SCIProwGetOriginCons
16941#undef SCIProwGetOriginConshdlr
16942#undef SCIProwGetOriginSepa
16943#undef SCIProwIsInGlobalCutpool
16944#undef SCIProwGetLPPos
16945#undef SCIProwGetLPDepth
16946#undef SCIProwIsInLP
16947#undef SCIProwGetActiveLPCount
16948#undef SCIProwGetNLPsAfterCreation
16949#undef SCIProwChgRank
16950#undef SCIPlpGetCols
16951#undef SCIPlpGetNCols
16952#undef SCIPlpGetRows
16953#undef SCIPlpGetNRows
16954#undef SCIPlpGetNewcols
16955#undef SCIPlpGetNNewcols
16956#undef SCIPlpGetNewrows
16957#undef SCIPlpGetNNewrows
16958#undef SCIPlpGetObjNorm
16959#undef SCIPlpGetRootObjval
16960#undef SCIPlpGetRootColumnObjval
16961#undef SCIPlpGetRootLooseObjval
16962#undef SCIPlpGetLPI
16963#undef SCIPlpSetIsRelax
16964#undef SCIPlpIsRelax
16965#undef SCIPlpIsSolved
16966#undef SCIPlpIsSolBasic
16967#undef SCIPlpDiving
16968#undef SCIPlpDivingObjChanged
16969#undef SCIPlpMarkDivingObjChanged
16970#undef SCIPlpUnmarkDivingObjChanged
16971#undef SCIPlpDivingRowsChanged
16972#undef SCIPlpIsFeasEQ
16973#undef SCIPlpIsFeasLT
16974#undef SCIPlpIsFeasLE
16975#undef SCIPlpIsFeasGT
16976#undef SCIPlpIsFeasGE
16977#undef SCIPlpIsFeasZero
16978#undef SCIPlpIsFeasPositive
16979#undef SCIPlpIsFeasNegative
16980
16981/** gets objective value of column */
16983 SCIP_COL* col /**< LP column */
16984 )
16985{
16986 assert(col != NULL);
16987
16988 return col->obj;
16989}
16990
16991/** gets lower bound of column */
16993 SCIP_COL* col /**< LP column */
16994 )
16995{
16996 assert(col != NULL);
16997
16998 return col->lb;
16999}
17000
17001/** gets upper bound of column */
17003 SCIP_COL* col /**< LP column */
17004 )
17005{
17006 assert(col != NULL);
17007
17008 return col->ub;
17009}
17010
17011/** gets best bound of column with respect to the objective function */
17013 SCIP_COL* col /**< LP column */
17014 )
17015{
17016 assert(col != NULL);
17017
17018 if( col->obj >= 0.0 )
17019 return col->lb;
17020 else
17021 return col->ub;
17022}
17023
17024/** gets the primal LP solution of a column */
17026 SCIP_COL* col /**< LP column */
17027 )
17028{
17029 assert(col != NULL);
17030
17031 if( col->lppos >= 0 )
17032 return col->primsol;
17033 else
17034 return 0.0;
17035}
17036
17037/** gets the minimal LP solution value, this column ever assumed */
17039 SCIP_COL* col /**< LP column */
17040 )
17041{
17042 assert(col != NULL);
17043
17044 return col->minprimsol;
17045}
17046
17047/** gets the maximal LP solution value, this column ever assumed */
17049 SCIP_COL* col /**< LP column */
17050 )
17051{
17052 assert(col != NULL);
17053
17054 return col->maxprimsol;
17055}
17056
17057/** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17058 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17059 */
17061 SCIP_COL* col /**< LP column */
17062 )
17063{
17064 assert(col != NULL);
17066
17067 return (SCIP_BASESTAT)col->basisstatus;
17068}
17069
17070/** gets variable this column represents */
17072 SCIP_COL* col /**< LP column */
17073 )
17074{
17075 assert(col != NULL);
17076
17077 return col->var;
17078}
17079
17080/** gets unique index of col */
17082 SCIP_COL* col /**< LP col */
17083 )
17084{
17085 assert(col != NULL);
17086
17087 return col->index;
17088}
17089
17090/** gets probindex of corresponding variable */
17092 SCIP_COL* col /**< LP col */
17093 )
17094{
17095 assert(col != NULL);
17096
17097 return col->var_probindex;
17098}
17099
17100/** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17102 SCIP_COL* col /**< LP column */
17103 )
17104{
17105 assert(col != NULL);
17106 assert(SCIPvarIsIntegral(col->var) == col->integral);
17107
17108 return col->integral;
17109}
17110
17111/** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17113 SCIP_COL* col /**< LP column */
17114 )
17115{
17116 assert(col != NULL);
17117
17118 return col->removable;
17119}
17120
17121/** gets position of column in current LP, or -1 if it is not in LP */
17123 SCIP_COL* col /**< LP column */
17124 )
17125{
17126 assert(col != NULL);
17127 assert((col->lppos == -1) == (col->lpdepth == -1));
17128
17129 return col->lppos;
17130}
17131
17132/** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17134 SCIP_COL* col /**< LP column */
17135 )
17136{
17137 assert(col != NULL);
17138 assert((col->lppos == -1) == (col->lpdepth == -1));
17139
17140 return col->lpdepth;
17141}
17142
17143/** returns TRUE iff column is member of current LP */
17145 SCIP_COL* col /**< LP column */
17146 )
17147{
17148 assert(col != NULL);
17149 assert((col->lppos == -1) == (col->lpdepth == -1));
17150
17151 return (col->lppos >= 0);
17152}
17153
17154/** get number of nonzero entries in column vector */
17156 SCIP_COL* col /**< LP column */
17157 )
17158{
17159 assert(col != NULL);
17160
17161 return col->len;
17162}
17163
17164/** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17165 *
17166 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17167 * 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
17168 */
17170 SCIP_COL* col /**< LP column */
17171 )
17172{
17173 assert(col != NULL);
17174 assert(col->nunlinked == 0);
17175
17176 return col->nlprows;
17177}
17178
17179/** gets array with rows of nonzero entries */
17181 SCIP_COL* col /**< LP column */
17182 )
17183{
17184 assert(col != NULL);
17185
17186 return col->rows;
17187}
17188
17189/** gets array with coefficients of nonzero entries */
17191 SCIP_COL* col /**< LP column */
17192 )
17193{
17194 assert(col != NULL);
17195
17196 return col->vals;
17197}
17198
17199/** gets node number of the last node in current branch and bound run, where strong branching was used on the
17200 * given column, or -1 if strong branching was never applied to the column in current run
17201 */
17203 SCIP_COL* col /**< LP column */
17204 )
17205{
17206 assert(col != NULL);
17207
17208 return col->sbnode;
17209}
17210
17211/** gets number of times, strong branching was applied in current run on the given column */
17213 SCIP_COL* col /**< LP column */
17214 )
17215{
17216 assert(col != NULL);
17217
17218 return col->nsbcalls;
17219}
17220
17221/** 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 */
17223 SCIP_COL* col /**< LP column */
17224 )
17225{
17226 assert(col != NULL);
17227
17228 return col->age;
17229}
17230
17231/** gets opposite bound type of given bound type */
17233 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
17234 )
17235{
17236 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17237
17239}
17240
17241/** get number of nonzero entries in row vector */
17243 SCIP_ROW* row /**< LP row */
17244 )
17245{
17246 assert(row != NULL);
17247
17248 return row->len;
17249}
17250
17251/** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17252 *
17253 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17254 * 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
17255 */
17257 SCIP_ROW* row /**< LP row */
17258 )
17259{
17260 assert(row != NULL);
17261 assert(row->nunlinked == 0);
17262
17263 return row->nlpcols;
17264}
17265
17266/** gets array with columns of nonzero entries */
17268 SCIP_ROW* row /**< LP row */
17269 )
17270{
17271 assert(row != NULL);
17272
17273 return row->cols;
17274}
17275
17276/** gets array with coefficients of nonzero entries */
17278 SCIP_ROW* row /**< LP row */
17279 )
17280{
17281 assert(row != NULL);
17282
17283 return row->vals;
17284}
17285
17286/** gets constant shift of row */
17288 SCIP_ROW* row /**< LP row */
17289 )
17290{
17291 assert(row != NULL);
17292
17293 return row->constant;
17294}
17295
17296/** gets Euclidean norm of row vector */
17298 SCIP_ROW* row /**< LP row */
17299 )
17300{
17301 assert(row != NULL);
17302
17303 checkRowSqrnorm(row);
17304
17305 return sqrt(row->sqrnorm);
17306}
17307
17308/** gets sum norm of row vector (sum of absolute values of coefficients) */
17310 SCIP_ROW* row /**< LP row */
17311 )
17312{
17313 assert(row != NULL);
17314
17315 checkRowSumnorm(row);
17316
17317 return row->sumnorm;
17318}
17319
17320/** returns the left hand side of the row */
17322 SCIP_ROW* row /**< LP row */
17323 )
17324{
17325 assert(row != NULL);
17326
17327 return row->lhs;
17328}
17329
17330/** returns the right hand side of the row */
17332 SCIP_ROW* row /**< LP row */
17333 )
17334{
17335 assert(row != NULL);
17336
17337 return row->rhs;
17338}
17339
17340/** gets the dual LP solution of a row */
17342 SCIP_ROW* row /**< LP row */
17343 )
17344{
17345 assert(row != NULL);
17346
17347 if( row->lppos >= 0 )
17348 return row->dualsol;
17349 else
17350 return 0.0;
17351}
17352
17353/** gets the dual Farkas coefficient of a row in an infeasible LP */
17355 SCIP_ROW* row /**< LP row */
17356 )
17357{
17358 assert(row != NULL);
17359
17360 if( row->lppos >= 0 )
17361 return row->dualfarkas;
17362 else
17363 return 0.0;
17364}
17365
17366/** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17367 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17368 */
17370 SCIP_ROW* row /**< LP row */
17371 )
17372{
17373 assert(row != NULL);
17375
17376 return (SCIP_BASESTAT)row->basisstatus;
17377}
17378
17379/** returns the name of the row */
17380const char* SCIProwGetName(
17381 SCIP_ROW* row /**< LP row */
17382 )
17383{
17384 assert(row != NULL);
17385
17386 return row->name;
17387}
17388
17389/** gets unique index of row */
17391 SCIP_ROW* row /**< LP row */
17392 )
17393{
17394 assert(row != NULL);
17395
17396 return row->index;
17397}
17398
17399/** gets age of row */
17401 SCIP_ROW* row /**< LP row */
17402 )
17403{
17404 assert(row != NULL);
17405
17406 return row->age;
17407}
17408
17409/** gets rank of row */
17411 SCIP_ROW* row /**< LP row */
17412 )
17413{
17414 assert(row != NULL);
17415
17416 return row->rank;
17417}
17418
17419/** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17421 SCIP_ROW* row /**< LP row */
17422 )
17423{
17424 assert(row != NULL);
17425
17426 return row->integral;
17427}
17428
17429/** returns TRUE iff row is only valid locally */
17431 SCIP_ROW* row /**< LP row */
17432 )
17433{
17434 assert(row != NULL);
17435
17436 return row->local;
17437}
17438
17439/** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17441 SCIP_ROW* row /**< LP row */
17442 )
17443{
17444 assert(row != NULL);
17445
17446 return row->modifiable;
17447}
17448
17449/** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17451 SCIP_ROW* row /**< LP row */
17452 )
17453{
17454 assert(row != NULL);
17455
17456 return row->removable;
17457}
17458
17459/** returns type of origin that created the row */
17461 SCIP_ROW* row /**< LP row */
17462 )
17463{
17464 assert( row != NULL );
17465
17466 return (SCIP_ROWORIGINTYPE) row->origintype;
17467}
17468
17469/** returns origin constraint that created the row (NULL if not available) */
17471 SCIP_ROW* row /**< LP row */
17472 )
17473{
17474 assert( row != NULL );
17475
17477 {
17478 assert( row->origin != NULL );
17479 return (SCIP_CONS*) row->origin;
17480 }
17481 return NULL;
17482}
17483
17484/** returns origin constraint handler that created the row (NULL if not available) */
17486 SCIP_ROW* row /**< LP row */
17487 )
17488{
17489 assert( row != NULL );
17490
17492 {
17493 assert( row->origin != NULL );
17494 return (SCIP_CONSHDLR*) row->origin;
17495 }
17497 {
17498 assert(row->origin != NULL);
17499 return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17500 }
17501 return NULL;
17502}
17503
17504/** returns origin separator that created the row (NULL if not available) */
17506 SCIP_ROW* row /**< LP row */
17507 )
17508{
17509 assert( row != NULL );
17510
17512 {
17513 assert( row->origin != NULL );
17514 return (SCIP_SEPA*) row->origin;
17515 }
17516 return NULL;
17517}
17518
17519/** returns TRUE iff row is member of the global cut pool */
17521 SCIP_ROW* row /**< LP row */
17522 )
17523{
17524 assert(row != NULL);
17525
17526 return row->inglobalcutpool;
17527}
17528
17529/** gets position of row in current LP, or -1 if it is not in LP */
17531 SCIP_ROW* row /**< LP row */
17532 )
17533{
17534 assert(row != NULL);
17535 assert((row->lppos == -1) == (row->lpdepth == -1));
17536
17537 return row->lppos;
17538}
17539
17540/** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17542 SCIP_ROW* row /**< LP row */
17543 )
17544{
17545 assert(row != NULL);
17546 assert((row->lppos == -1) == (row->lpdepth == -1));
17547
17548 return row->lpdepth;
17549}
17550
17551/** returns TRUE iff row is member of current LP */
17553 SCIP_ROW* row /**< LP row */
17554 )
17555{
17556 assert(row != NULL);
17557 assert((row->lppos == -1) == (row->lpdepth == -1));
17558
17559 return (row->lppos >= 0);
17560}
17561
17562/** changes the rank of LP row */
17564 SCIP_ROW* row, /**< LP row */
17565 int rank /**< new value for rank */
17566 )
17567{
17568 assert(row != NULL);
17569
17570 row->rank = rank;
17571}
17572
17573/** returns the number of times that this row has been sharp in an optimal LP solution */
17575 SCIP_ROW* row /**< row */
17576 )
17577{
17578 assert(row != NULL);
17579
17580 return row->activeinlpcounter;
17581}
17582
17583/** returns the number of LPs since this row has been created */
17585 SCIP_ROW* row /**< row */
17586 )
17587{
17588 assert(row != NULL);
17589
17590 return row->nlpsaftercreation;
17591}
17592
17593/** gets array with columns of the LP */
17595 SCIP_LP* lp /**< current LP data */
17596 )
17597{
17598 assert(lp != NULL);
17599
17600 return lp->cols;
17601}
17602
17603/** gets current number of columns in LP */
17605 SCIP_LP* lp /**< current LP data */
17606 )
17607{
17608 assert(lp != NULL);
17609
17610 return lp->ncols;
17611}
17612
17613/** gets current number of unfixed columns in LP */
17615 SCIP_LP* lp, /**< current LP data */
17616 SCIP_Real eps /**< numerical tolerance */
17617 )
17618{
17619 SCIP_COL** lpcols;
17620 int nlpcols;
17621 int nunfixedcols;
17622 int c;
17623
17624 assert(lp != NULL);
17625 assert(eps > 0.0);
17626
17627 lpcols = lp->cols;
17628 nlpcols = lp->ncols;
17629
17630 nunfixedcols = 0;
17631 for( c = 0; c < nlpcols; ++c )
17632 {
17633 if( lpcols[c]->ub - lpcols[c]->lb > eps )
17634 ++nunfixedcols;
17635 }
17636
17637 return nunfixedcols;
17638}
17639
17640/** gets array with rows of the LP */
17642 SCIP_LP* lp /**< current LP data */
17643 )
17644{
17645 assert(lp != NULL);
17646
17647 return lp->rows;
17648}
17649
17650/** gets current number of rows in LP */
17652 SCIP_LP* lp /**< current LP data */
17653 )
17654{
17655 assert(lp != NULL);
17656
17657 return lp->nrows;
17658}
17659
17660/** gets array with newly added columns after the last mark */
17662 SCIP_LP* lp /**< current LP data */
17663 )
17664{
17665 assert(lp != NULL);
17666 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17667
17668 return &(lp->cols[lp->firstnewcol]);
17669}
17670
17671/** gets number of newly added columns after the last mark */
17673 SCIP_LP* lp /**< current LP data */
17674 )
17675{
17676 assert(lp != NULL);
17677 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17678
17679 return lp->ncols - lp->firstnewcol;
17680}
17681
17682/** gets array with newly added rows after the last mark */
17684 SCIP_LP* lp /**< current LP data */
17685 )
17686{
17687 assert(lp != NULL);
17688 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17689
17690 return &(lp->rows[lp->firstnewrow]);
17691}
17692
17693/** gets number of newly added rows after the last mark */
17695 SCIP_LP* lp /**< current LP data */
17696 )
17697{
17698 assert(lp != NULL);
17699 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17700
17701 return lp->nrows - lp->firstnewrow;
17702}
17703
17704/** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17706 SCIP_SET* set, /**< global SCIP settings */
17707 SCIP_LP* lp /**< LP data */
17708 )
17709{
17710 if( lp->objsqrnormunreliable )
17711 {
17712 SCIP_COL** cols;
17713 int c;
17714
17715 cols = lp->cols;
17716 assert(cols != NULL || lp->ncols == 0);
17717
17718 lp->objsqrnorm = 0.0;
17719
17720 for( c = lp->ncols - 1; c >= 0; --c )
17721 {
17722 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
17723 }
17724 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17725
17726 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17727 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17728
17730 }
17731 return;
17732}
17733
17734/** gets Euclidean norm of objective function vector of column variables, only use this method if
17735 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17737 SCIP_LP* lp /**< LP data */
17738 )
17739{
17740 assert(lp != NULL);
17742 assert(lp->objsqrnorm >= 0.0);
17743
17744 return sqrt(lp->objsqrnorm);
17745}
17746
17747/** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17749 SCIP_LP* lp, /**< LP data */
17750 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
17751 )
17752{
17753 assert(lp != NULL);
17754
17755 lp->rootlpisrelax = isrelax;
17756}
17757
17758/** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17760 SCIP_LP* lp /**< LP data */
17761 )
17762{
17763 assert(lp != NULL);
17764
17765 return lp->rootlpisrelax;
17766}
17767
17768/** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17770 SCIP_LP* lp /**< LP data */
17771 )
17772{
17773 assert(lp != NULL);
17774
17775 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17776}
17777
17778/** gets part of the objective value of the root node LP that results from COLUMN variables only;
17779 * returns SCIP_INVALID if the root node LP was not (yet) solved
17780 */
17782 SCIP_LP* lp /**< LP data */
17783 )
17784{
17785 assert(lp != NULL);
17786
17787 return lp->rootlpobjval;
17788}
17789
17790/** gets part of the objective value of the root node LP that results from LOOSE variables only;
17791 * returns SCIP_INVALID if the root node LP was not (yet) solved
17792 */
17794 SCIP_LP* lp /**< LP data */
17795 )
17796{
17797 assert(lp != NULL);
17798
17799 return lp->rootlooseobjval;
17800}
17801
17802/** gets the LP solver interface */
17804 SCIP_LP* lp /**< current LP data */
17805 )
17806{
17807 assert(lp != NULL);
17808
17809 return lp->lpi;
17810}
17811
17812/** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17814 SCIP_LP* lp, /**< LP data */
17815 SCIP_Bool relax /**< is the current lp a relaxation? */
17816 )
17817{
17818 assert(lp != NULL);
17819
17820 lp->isrelax = relax;
17821}
17822
17823/** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17824 * solution value a valid local lower bound?
17825 */
17827 SCIP_LP* lp /**< LP data */
17828 )
17829{
17830 assert(lp != NULL);
17831
17832 return lp->isrelax;
17833}
17834
17835/** returns whether the current LP is flushed and solved */
17837 SCIP_LP* lp /**< current LP data */
17838 )
17839{
17840 assert(lp != NULL);
17841
17842 return lp->flushed && lp->solved;
17843}
17844
17845/** return whether the current LP solution passed the primal feasibility check */
17847 SCIP_LP* lp /**< current LP data */
17848 )
17849{
17850 assert(lp != NULL);
17851
17852 return (lp->primalchecked && lp->primalfeasible);
17853}
17854
17855/** return whether the current LP solution passed the dual feasibility check */
17857 SCIP_LP* lp /**< current LP data */
17858 )
17859{
17860 assert(lp != NULL);
17861
17862 return (lp->dualchecked && lp->dualfeasible);
17863}
17864
17865/** returns whether the current LP solution is a basic solution */
17867 SCIP_LP* lp /**< current LP data */
17868 )
17869{
17870 assert(lp != NULL);
17871
17872 return lp->solisbasic;
17873}
17874
17875/** returns whether the LP is in diving mode */
17877 SCIP_LP* lp /**< current LP data */
17878 )
17879{
17880 assert(lp != NULL);
17881
17882 return lp->diving;
17883}
17884
17885/** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17887 SCIP_LP* lp /**< current LP data */
17888 )
17889{
17890 assert(lp != NULL);
17891
17892 return lp->divingobjchg;
17893}
17894
17895/** marks the diving LP to have a changed objective function */
17897 SCIP_LP* lp /**< current LP data */
17898 )
17899{
17900 assert(lp != NULL);
17901 assert(lp->diving || lp->probing);
17902
17903 lp->divingobjchg = TRUE;
17904}
17905
17906/** marks the diving LP to not have a changed objective function anymore */
17908 SCIP_LP* lp /**< current LP data */
17909 )
17910{
17911 assert(lp != NULL);
17912 assert(lp->diving || lp->probing);
17913
17914 lp->divingobjchg = FALSE;
17915}
17916
17917/* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17919 SCIP_LP* lp /**< current LP data */
17920 )
17921{
17922 assert(lp != NULL);
17923 assert(lp->diving || lp->ndivechgsides == 0);
17924
17925 return (lp->ndivechgsides > 0);
17926}
17927
17928/** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17929static
17931 SCIP_LPI* lpi, /**< auxiliary LP interface */
17932 SCIP_SET* set, /**< global SCIP settings */
17933 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17934 SCIP_LP* lp, /**< LP data */
17935 SCIP_PROB* prob, /**< problem data */
17936 SCIP_Bool relaxrows, /**< should the rows be relaxed */
17937 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
17938 SCIP_Real timelimit, /**< time limit for LP solver */
17939 int iterlimit, /**< iteration limit for LP solver */
17940 SCIP_Real* point, /**< array to store relative interior point on exit */
17941 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
17942 )
17943{
17944 SCIP_RETCODE retcode;
17945 SCIP_Real* primal;
17946 SCIP_Real* obj;
17947 SCIP_Real* lb;
17948 SCIP_Real* ub;
17949 SCIP_Real* matvals;
17950 SCIP_Real* matlhs;
17951 SCIP_Real* matrhs;
17954 int* matinds;
17955 int* matbeg;
17956#ifndef NDEBUG
17957 int nslacks;
17958#endif
17959 int nnewcols;
17960 int ntotnonz = 0;
17961 int ntotrows = 0;
17962 int matrowidx;
17963 int matidx;
17964 int cnt;
17965 int j;
17966 int i;
17967
17968 assert(lpi != NULL);
17969
17970 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17971 if( retcode != SCIP_OKAY )
17972 {
17973 /* stop execution on error, since result is likely to be unsuable */
17974 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17975 return SCIP_LPERROR;
17976 }
17977
17979 if( retcode != SCIP_OKAY )
17980 {
17981 /* stop execution on error, since result is likely to be unsuable */
17982 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17983 return SCIP_LPERROR;
17984 }
17985
17986 /* get storage */
17987 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17988 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17989 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17990 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17991
17992 /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17993 for( j = 0; j < lp->ncols; ++j )
17994 {
17995 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
17996 obj[j] = 0.0;
17997 lb[j] = -SCIPlpiInfinity(lpi);
17998 ub[j] = SCIPlpiInfinity(lpi);
17999 /* note: we could also use the original bounds - free variables seem to be faster. */
18000 }
18001
18002 /* add artificial alpha variable */
18003 nnewcols = lp->ncols;
18004 obj[nnewcols] = 0.0;
18005 lb[nnewcols] = 1.0;
18006 ub[nnewcols] = SCIPlpiInfinity(lpi);
18007 ++nnewcols;
18008
18009 /* create slacks for rows */
18010 for( i = 0; i < lp->nrows; ++i )
18011 {
18012 SCIP_ROW* row;
18013
18014 row = lp->rows[i];
18015 assert( row != NULL );
18016
18017 if( SCIProwIsModifiable(row) )
18018 continue;
18019
18020 /* make sure row is sorted */
18021 rowSortLP(row);
18022 assert( row->lpcolssorted );
18023
18024 /* check whether we have an equation */
18025 if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
18026 {
18029 ntotnonz += row->nlpcols + 1;
18030 ++ntotrows;
18031 }
18032 else
18033 {
18034 /* otherwise add slacks for each side if necessary */
18035 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18036 {
18037 if ( relaxrows )
18038 {
18039 lb[nnewcols] = 0.0;
18040 ub[nnewcols] = 1.0;
18041 obj[nnewcols++] = 1.0;
18042 ntotnonz += row->nlpcols + 2;
18043 }
18044 else
18045 ntotnonz += row->nlpcols + 1;
18046 ++ntotrows;
18047 }
18048 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18049 {
18050 if ( relaxrows )
18051 {
18052 lb[nnewcols] = 0.0;
18053 ub[nnewcols] = 1.0;
18054 obj[nnewcols++] = 1.0;
18055 ntotnonz += row->nlpcols + 2;
18056 }
18057 else
18058 ntotnonz += row->nlpcols + 1;
18059 ++ntotrows;
18060 }
18061 }
18062 }
18063
18064 /* create slacks for objective cutoff row */
18065 if( inclobjcutoff && relaxrows )
18066 {
18067 /* add slacks for right hand side */
18068 lb[nnewcols] = 0.0;
18069 ub[nnewcols] = 1.0;
18070 obj[nnewcols++] = 1.0;
18071 ntotnonz += lp->ncols + 2;
18072 ++ntotrows;
18073 }
18074
18075 /* create slacks for bounds */
18076 for( j = 0; j < lp->ncols; ++j )
18077 {
18078 SCIP_COL* col;
18079
18080 col = lp->cols[j];
18081 assert( col != NULL );
18082
18083 /* no slacks for fixed variables */
18084 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18085 {
18086 ++ntotrows;
18087 ntotnonz += 2;
18088 }
18089 else
18090 {
18091 /* add slacks for each bound if necessary */
18092 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18093 {
18094 lb[nnewcols] = 0.0;
18095 ub[nnewcols] = 1.0;
18096 obj[nnewcols++] = 1.0;
18097 ntotnonz += 3;
18098 ++ntotrows;
18099 }
18100 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18101 {
18102 lb[nnewcols] = 0.0;
18103 ub[nnewcols] = 1.0;
18104 obj[nnewcols++] = 1.0;
18105 ntotnonz += 3;
18106 ++ntotrows;
18107 }
18108 }
18109 }
18110#ifndef NDEBUG
18111 nslacks = nnewcols - lp->ncols - 1;
18112 assert( nslacks >= 0 );
18113 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18114#endif
18115
18116 /* add columns */
18117 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18118
18119 /* free storage */
18123
18124 /* prepare storage for rows */
18125 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18126 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18127 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18128 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18129 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18130
18131 /* create rows arising from original rows */
18132 cnt = 0;
18133 matrowidx = 0;
18134 matidx = 0;
18135 for( i = 0; i < lp->nrows; ++i )
18136 {
18137 SCIP_ROW* row;
18138 SCIP_COL** rowcols;
18139 SCIP_Real* rowvals;
18140 SCIP_Real lhs;
18141 SCIP_Real rhs;
18142 int nnonz;
18143
18144 row = lp->rows[i];
18145 assert( row != NULL );
18146
18147 if( SCIProwIsModifiable(row) )
18148 continue;
18149 assert( row->lpcolssorted );
18150
18151 /* get row data */
18152 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18153 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18154 nnonz = row->nlpcols;
18155 assert( nnonz <= lp->ncols );
18156 rowcols = row->cols;
18157 rowvals = row->vals;
18158
18159 /* if we have an equation */
18160 if( SCIPsetIsEQ(set, lhs, rhs) )
18161 {
18162 /* set up indices */
18163 matbeg[matrowidx] = matidx;
18164 for( j = 0; j < nnonz; ++j )
18165 {
18166 assert( rowcols[j] != NULL );
18167 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18168 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18169 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18170 matinds[matidx] = rowcols[j]->lppos;
18171 matvals[matidx++] = rowvals[j];
18172 assert( matidx <= ntotnonz );
18173 }
18174
18175 /* add artificial variable */
18176 if ( ! SCIPsetIsZero(set, rhs) )
18177 {
18178 matinds[matidx] = lp->ncols;
18179 matvals[matidx++] = -rhs;
18180 assert( matidx <= ntotnonz );
18181 }
18182
18183 matlhs[matrowidx] = 0.0;
18184 matrhs[matrowidx++] = 0.0;
18185 assert( matrowidx <= ntotrows );
18186 }
18187 else
18188 {
18189 SCIP_Real abslhs = REALABS(lhs);
18190 SCIP_Real absrhs = REALABS(rhs);
18191
18192 assert(!SCIPsetIsEQ(set, lhs, rhs));
18193
18194 /* treat lhs */
18195 if( !SCIPsetIsInfinity(set, abslhs) )
18196 {
18197 /* set up indices */
18198 matbeg[matrowidx] = matidx;
18199 for( j = 0; j < nnonz; ++j )
18200 {
18201 assert( rowcols[j] != NULL );
18202 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18203 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18204 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18205 matinds[matidx] = rowcols[j]->lppos;
18206 matvals[matidx++] = rowvals[j];
18207 assert( matidx <= ntotnonz );
18208 }
18209
18210 /* add artificial variable */
18211 if ( ! SCIPsetIsZero(set, lhs) )
18212 {
18213 matinds[matidx] = lp->ncols;
18214 matvals[matidx++] = -lhs;
18215 assert( matidx <= ntotnonz );
18216 }
18217
18218 if( relaxrows )
18219 {
18220 /* add slack variable */
18221 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/
18222 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18223 assert( matidx <= ntotnonz );
18224 ++cnt;
18225 }
18226
18227 matlhs[matrowidx] = 0.0;
18228 matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18229 assert( matrowidx <= ntotrows );
18230 }
18231
18232 /* treat rhs */
18233 if( !SCIPsetIsInfinity(set, absrhs) )
18234 {
18235 /* set up indices */
18236 matbeg[matrowidx] = matidx;
18237 for( j = 0; j < nnonz; ++j )
18238 {
18239 assert( rowcols[j] != NULL );
18240 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18241 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18242 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18243 matinds[matidx] = rowcols[j]->lppos;
18244 matvals[matidx++] = rowvals[j];
18245 assert( matidx <= ntotnonz );
18246 }
18247
18248 /* add artificial variable */
18249 if ( ! SCIPsetIsZero(set, rhs) )
18250 {
18251 matinds[matidx] = lp->ncols;
18252 matvals[matidx++] = -rhs;
18253 assert( matidx <= ntotnonz );
18254 }
18255
18256 if( relaxrows )
18257 {
18258 /* add slack variable */
18259 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/
18260 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18261 ++cnt;
18262 }
18263
18264 matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18265 matrhs[matrowidx++] = 0.0;
18266 assert( matrowidx <= ntotrows );
18267 }
18268 }
18269 }
18270
18271 /* create row arising from objective cutoff */
18272 if( inclobjcutoff )
18273 {
18274 SCIP_Real rhs;
18275
18276 /* get row data */
18277 assert(lp->looseobjvalinf == 0);
18278 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18279
18280 /* set up indices and coefficients */
18281 matbeg[matrowidx] = matidx;
18282 for( j = 0; j < lp->ncols; ++j )
18283 {
18284 assert( lp->cols[j] != NULL );
18285 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18286 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18287
18288 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18289 {
18290 matinds[matidx] = lp->cols[j]->lppos;
18291 matvals[matidx++] = lp->cols[j]->obj;
18292 assert( matidx <= ntotnonz );
18293 }
18294 }
18295
18296 /* treat rhs */
18297
18298 /* add artificial variable */
18299 if ( ! SCIPsetIsZero(set, rhs) )
18300 {
18301 matinds[matidx] = lp->ncols;
18302 matvals[matidx++] = -rhs;
18303 assert( matidx <= ntotnonz );
18304 }
18305
18306 if( relaxrows )
18307 {
18308 SCIP_Real absrhs = REALABS(rhs);
18309
18310 /* add slack variable */
18311 matvals[matidx] = MAX(1.0, absrhs);
18312 matinds[matidx++] = lp->ncols + 1 + cnt;
18313 assert( matidx <= ntotnonz );
18314 ++cnt;
18315 }
18316 matlhs[matrowidx] = -SCIPsetInfinity(set);
18317 matrhs[matrowidx++] = 0.0;
18318 assert( matrowidx <= ntotrows );
18319 }
18320
18321 /* create rows arising from bounds */
18322 for( j = 0; j < lp->ncols; ++j )
18323 {
18324 SCIP_COL* col;
18325 SCIP_Real abscollb;
18326 SCIP_Real abscolub;
18327
18328 col = lp->cols[j];
18329 assert( col != NULL );
18330 assert( col->lppos == j );
18331
18332 /* fixed variable */
18333 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18334 {
18335 /* set up index of column */
18336 matbeg[matrowidx] = matidx;
18337
18338 matinds[matidx] = j;
18339 matvals[matidx++] = 1.0;
18340 assert( matidx <= ntotnonz );
18341
18342 /* add artificial variable */
18343 if ( ! SCIPsetIsZero(set, col->ub) )
18344 {
18345 matinds[matidx] = lp->ncols;
18346 matvals[matidx++] = -col->ub;
18347 assert( matidx <= ntotnonz );
18348 }
18349
18350 matlhs[matrowidx] = 0.0;
18351 matrhs[matrowidx++] = 0.0;
18352 assert( matrowidx <= ntotrows );
18353
18354 continue;
18355 }
18356
18357 abscollb = REALABS(col->lb);
18358 abscolub = REALABS(col->ub);
18359
18360 /* lower bound */
18361 if ( ! SCIPsetIsInfinity(set, abscollb) )
18362 {
18363 /* set up index of column */
18364 matbeg[matrowidx] = matidx;
18365
18366 matinds[matidx] = j;
18367 matvals[matidx++] = 1.0;
18368 assert( matidx <= ntotnonz );
18369
18370 /* add artificial variable */
18371 if ( ! SCIPsetIsZero(set, col->lb) )
18372 {
18373 matinds[matidx] = lp->ncols;
18374 matvals[matidx++] = -col->lb;
18375 assert( matidx <= ntotnonz );
18376 }
18377
18378 /* add slack variable */
18379 matvals[matidx] = -MAX(1.0, abscollb);
18380 matinds[matidx++] = lp->ncols + 1 + cnt;
18381 assert( matidx <= ntotnonz );
18382 ++cnt;
18383
18384 matlhs[matrowidx] = 0.0;
18385 matrhs[matrowidx++] = SCIPsetInfinity(set);
18386 assert( matrowidx <= ntotrows );
18387 }
18388
18389 /* upper bound */
18390 if ( ! SCIPsetIsInfinity(set, abscolub) )
18391 {
18392 /* set up index of column */
18393 matbeg[matrowidx] = matidx;
18394
18395 matinds[matidx] = j;
18396 matvals[matidx++] = 1.0;
18397 assert( matidx <= ntotnonz );
18398
18399 /* add artificial variable */
18400 if ( ! SCIPsetIsZero(set, col->ub) )
18401 {
18402 matinds[matidx] = lp->ncols;
18403 matvals[matidx++] = -col->ub;
18404 assert( matidx <= ntotnonz );
18405 }
18406
18407 /* add slack variable */
18408 matvals[matidx] = MAX(1.0, abscolub);
18409 matinds[matidx++] = lp->ncols + 1 + cnt;
18410 assert( matidx <= ntotnonz );
18411 ++cnt;
18412
18413 matlhs[matrowidx] = -SCIPsetInfinity(set);
18414 matrhs[matrowidx++] = 0.0;
18415 assert( matrowidx <= ntotrows );
18416 }
18417 }
18418 assert( cnt == nslacks );
18419 assert( matrowidx == ntotrows );
18420
18421 /* add rows */
18422 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18423
18424 SCIPsetFreeBufferArray(set, &matrhs);
18425 SCIPsetFreeBufferArray(set, &matlhs);
18426 SCIPsetFreeBufferArray(set, &matbeg);
18427 SCIPsetFreeBufferArray(set, &matvals);
18428 SCIPsetFreeBufferArray(set, &matinds);
18429
18430#ifdef SCIP_OUTPUT
18431 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18432#endif
18433
18434#ifndef NDEBUG
18435 {
18436 int ncols;
18437 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18438 assert( ncols == nnewcols );
18439 }
18440#endif
18441
18442 /* set time limit */
18443 if( SCIPsetIsInfinity(set, timelimit) )
18444 timelimit = SCIPlpiInfinity(lpi);
18445 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18446
18447 /* check, if parameter is unknown */
18448 if( retcode == SCIP_PARAMETERUNKNOWN )
18449 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18450 else if ( retcode != SCIP_OKAY )
18451 return retcode;
18452
18453 /* set iteration limit */
18454 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18455
18456 /* check, if parameter is unknown */
18457 if( retcode == SCIP_PARAMETERUNKNOWN )
18458 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18459 else if ( retcode != SCIP_OKAY )
18460 return retcode;
18461
18462 /* solve and store point */
18463 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18464 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */
18465
18466#ifndef NDEBUG
18467 if ( SCIPlpiIsIterlimExc(lpi) )
18468 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18469 if ( SCIPlpiIsTimelimExc(lpi) )
18470 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18471#endif
18472
18473 if( SCIPlpiIsOptimal(lpi) )
18474 {
18475 /* get primal solution */
18476 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18477 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18478 alpha = primal[lp->ncols];
18479 assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18480
18481 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18482
18483 /* construct relative interior point */
18484 for( j = 0; j < lp->ncols; ++j )
18485 point[j] = primal[j]/alpha;
18486
18487#ifdef SCIP_DEBUG
18488 /* check whether the point is a relative interior point */
18489 cnt = 0;
18490 if( relaxrows )
18491 {
18492 for( i = 0; i < lp->nrows; ++i )
18493 {
18494 SCIP_ROW* row;
18495 SCIP_COL** rowcols;
18496 SCIP_Real* rowvals;
18497 SCIP_Real lhs;
18498 SCIP_Real rhs;
18499 SCIP_Real sum;
18500 int nnonz;
18501
18502 row = lp->rows[i];
18503 assert( row != NULL );
18504
18505 /* get row data */
18506 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18507 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18508 nnonz = row->nlpcols;
18509 assert( nnonz <= lp->ncols );
18510 rowcols = row->cols;
18511 rowvals = row->vals;
18512
18513 sum = 0.0;
18514 for( j = 0; j < nnonz; ++j )
18515 sum += rowvals[j] * primal[rowcols[j]->lppos];
18516 sum /= alpha;
18517
18518 /* if we have an equation */
18519 if( SCIPsetIsEQ(set, lhs, rhs) )
18520 {
18521 assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18522 }
18523 else
18524 {
18525 /* treat lhs */
18526 if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18527 {
18528 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18529 ++cnt;
18530 }
18531 /* treat rhs */
18532 if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18533 {
18534 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18535 ++cnt;
18536 }
18537 }
18538 }
18539 if( inclobjcutoff )
18540 {
18541 SCIP_Real sum;
18542#ifndef NDEBUG
18543 SCIP_Real rhs;
18544
18545 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18546#endif
18547 sum = 0.0;
18548 for( j = 0; j < lp->ncols; ++j )
18549 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18550 sum /= alpha;
18551
18552 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18553 ++cnt;
18554 }
18555 }
18556 /* check bounds */
18557 for( j = 0; j < lp->ncols; ++j )
18558 {
18559 SCIP_COL* col;
18560#ifndef NDEBUG
18561 SCIP_Real val;
18562#endif
18563
18564 col = lp->cols[j];
18565 assert( col != NULL );
18566#ifndef NDEBUG
18567 val = primal[col->lppos] / alpha;
18568#endif
18569 /* if the variable is not fixed */
18570 if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18571 {
18572 /* treat lb */
18573 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18574 {
18575 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18576 ++cnt;
18577 }
18578 /* treat rhs */
18579 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18580 {
18581 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18582 ++cnt;
18583 }
18584 }
18585 }
18586#endif
18587
18588 /* free */
18589 SCIPsetFreeBufferArray(set, &primal);
18590
18591 *success = TRUE;
18592 }
18593
18594 return SCIP_OKAY;
18595}
18596
18597/** compute relative interior point
18598 *
18599 * We use the approach of@par
18600 * R. Freund, R. Roundy, M. J. Todd@par
18601 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18602 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18603 *
18604 * to compute a relative interior point for the current LP.
18605 *
18606 * Assume the original LP looks as follows:
18607 * \f[
18608 * \begin{array}{rrl}
18609 * \min & c^T x &\\
18610 * & A x & \geq a\\
18611 * & B x & \leq b\\
18612 * & D x & = d.
18613 * \end{array}
18614 * \f]
18615 * Note that bounds should be included in the system.
18616 *
18617 * To find an interior point the following LP does the job:
18618 * \f[
18619 * \begin{array}{rrl}
18620 * \max & 1^T y &\\
18621 * & A x - y - \alpha a & \geq 0\\
18622 * & B x + y - \alpha b & \leq 0\\
18623 * & D x - \alpha d & = 0\\
18624 * & 0 \leq y & \leq 1\\
18625 * & \alpha & \geq 1.
18626 * \end{array}
18627 * \f]
18628 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18629 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18630 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18631 */
18633 SCIP_SET* set, /**< global SCIP settings */
18634 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18635 SCIP_LP* lp, /**< LP data */
18636 SCIP_PROB* prob, /**< problem data */
18637 SCIP_Bool relaxrows, /**< should the rows be relaxed */
18638 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
18639 SCIP_Real timelimit, /**< time limit for LP solver */
18640 int iterlimit, /**< iteration limit for LP solver */
18641 SCIP_Real* point, /**< array to store relative interior point on exit */
18642 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
18643 )
18644{
18645 SCIP_LPI* lpi;
18646 SCIP_RETCODE retcode;
18647
18648 assert(set != NULL);
18649 assert(lp != NULL);
18650 assert(point != NULL);
18651 assert(success != NULL);
18652
18653 *success = FALSE;
18654
18655 /* check time and iteration limits */
18656 if ( timelimit <= 0.0 || iterlimit <= 0 )
18657 return SCIP_OKAY;
18658
18659 /* exit if there are no columns */
18660 assert(lp->nrows >= 0);
18661 assert(lp->ncols >= 0);
18662 if( lp->ncols == 0 )
18663 return SCIP_OKAY;
18664
18665 /* disable objective cutoff if we have none */
18666 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18667 inclobjcutoff = FALSE;
18668
18669 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18670
18671 /* if there are no rows, we return the zero point */
18672 if( lp->nrows == 0 && !inclobjcutoff )
18673 {
18674 /* create zero point */
18675 BMSclearMemoryArray(point, lp->ncols);
18676 *success = TRUE;
18677
18678 return SCIP_OKAY;
18679 }
18680
18681 /* create auxiliary LP */
18682 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18683
18684 /* catch return code and ensure that lpi is freed, anyway */
18685 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18686
18687 SCIP_CALL( SCIPlpiFree(&lpi) );
18688
18689 /* return error, unless we obtained an LP error */
18690 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18691 {
18692 SCIP_CALL( retcode );
18693 }
18694
18695 return SCIP_OKAY;
18696}
18697
18698/** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18699 * based on the changes applied when reducing the problem to the optimal face
18700 *
18701 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18702 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18703 */
18705 SCIP_LP* lp, /**< LP data */
18706 SCIP_SET* set, /**< global SCIP settings */
18707 SCIP_STAT* stat, /**< problem statistics */
18708 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */
18709 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */
18710 )
18711{
18712 assert(lp != NULL);
18713 assert(lp->solved);
18714 assert(lp->flushed);
18715
18716 if( lp->validdegeneracylp != stat->nlps )
18717 {
18718 lp->validdegeneracylp = stat->nlps;
18719
18720 /* if the LP was solved to optimality, we determine the dual degeneracy */
18722 {
18723 SCIP_COL** cols;
18724 SCIP_ROW** rows;
18725 SCIP_COL* col;
18726 int ncols;
18727 int nrows;
18728 int nfixedcols = 0;
18729 int nalreadyfixedcols = 0;
18730 int nfixedrows = 0;
18731#ifndef NDEBUG
18732 int nimplicitfixedrows = 0;
18733#endif
18734 int nineq = 0;
18735 int c;
18736 int r;
18737 int nbasicequalities = 0;
18738
18739 cols = lp->cols;
18740 rows = lp->rows;
18741 ncols = lp->ncols;
18742 nrows = lp->nrows;
18743
18744 /* count number of columns that will be fixed when reducing the LP to the optimal face */
18745 for( c = ncols - 1 ; c >= 0; --c )
18746 {
18747 col = cols[c];
18748 assert(SCIPcolIsInLP(col));
18749
18750 /* column is not basic and not fixed already */
18752 {
18753 /* variable with nonzero reduced costs are fixed */
18754 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18755 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18756 ++nfixedcols;
18757 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18758 ++nalreadyfixedcols;
18759 }
18760 }
18761
18762 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18763 for( r = nrows - 1; r >= 0; --r )
18764 {
18765 SCIP_ROW* row = rows[r];
18766
18767 assert(SCIProwIsInLP(row));
18768
18769 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18770 {
18771 SCIP_Real dualsol = SCIProwGetDualsol(row);
18772
18773 ++nineq;
18774
18776 {
18777 /* rows with nonzero dual solution are turned into equations */
18778 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18779 if( !SCIPsetIsZero(set, dualsol) )
18780 {
18781 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18782 {
18784 ++nfixedrows;
18785 }
18786 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18787 {
18789 ++nfixedrows;
18790 }
18791 }
18792#ifndef NDEBUG
18793 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18794 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18795 {
18796 ++nimplicitfixedrows;
18797 }
18798#endif
18799 }
18800 }
18802 ++nbasicequalities;
18803 }
18804 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18805
18806 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18807 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18808 else
18809 lp->degeneracy = 0.0;
18810
18811 if( nrows > 0 )
18812 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18813 else
18814 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18815 assert(lp->degeneracy >= 0);
18816 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18817 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18818 }
18819 else
18820 {
18821 lp->degeneracy = 0.0;
18822 lp->varconsratio = 0.0;
18823 }
18824 }
18825
18826 *degeneracy = lp->degeneracy;
18827 *varconsratio = lp->varconsratio;
18828
18829 return SCIP_OKAY;
18830}
18831
18832/** checks, if absolute difference of values is in range of LP primal feastol */
18834 SCIP_SET* set, /**< global SCIP settings */
18835 SCIP_LP* lp, /**< current LP data */
18836 SCIP_Real val1, /**< first value to be compared */
18837 SCIP_Real val2 /**< second value to be compared */
18838 )
18839{
18840 assert(set != NULL);
18841 assert(lp != NULL);
18842
18843 /* avoid to compare two different infinities; the reason for that is
18844 * that such a comparison can lead to unexpected results */
18845 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18846 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18847 || val1 == val2 ); /*lint !e777*/
18848
18849 return EPSEQ(val1, val2, lp->feastol);
18850}
18851
18852/** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18854 SCIP_SET* set, /**< global SCIP settings */
18855 SCIP_LP* lp, /**< current LP data */
18856 SCIP_Real val1, /**< first value to be compared */
18857 SCIP_Real val2 /**< second value to be compared */
18858 )
18859{
18860 assert(set != NULL);
18861 assert(lp != NULL);
18862
18863 /* avoid to compare two different infinities; the reason for that is
18864 * that such a comparison can lead to unexpected results */
18865 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18866 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18867 || val1 == val2 ); /*lint !e777*/
18868
18869 return EPSLT(val1, val2, lp->feastol);
18870}
18871
18872/** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18874 SCIP_SET* set, /**< global SCIP settings */
18875 SCIP_LP* lp, /**< current LP data */
18876 SCIP_Real val1, /**< first value to be compared */
18877 SCIP_Real val2 /**< second value to be compared */
18878 )
18879{
18880 assert(set != NULL);
18881 assert(lp != NULL);
18882
18883 /* avoid to compare two different infinities; the reason for that is
18884 * that such a comparison can lead to unexpected results */
18885 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18886 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18887 || val1 == val2 ); /*lint !e777*/
18888
18889 return EPSLE(val1, val2, lp->feastol);
18890}
18891
18892/** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18894 SCIP_SET* set, /**< global SCIP settings */
18895 SCIP_LP* lp, /**< current LP data */
18896 SCIP_Real val1, /**< first value to be compared */
18897 SCIP_Real val2 /**< second value to be compared */
18898 )
18899{
18900 assert(set != NULL);
18901 assert(lp != NULL);
18902
18903 /* avoid to compare two different infinities; the reason for that is
18904 * that such a comparison can lead to unexpected results */
18905 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18906 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18907 || val1 == val2 ); /*lint !e777*/
18908
18909 return EPSGT(val1, val2, lp->feastol);
18910}
18911
18912/** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18914 SCIP_SET* set, /**< global SCIP settings */
18915 SCIP_LP* lp, /**< current LP data */
18916 SCIP_Real val1, /**< first value to be compared */
18917 SCIP_Real val2 /**< second value to be compared */
18918 )
18919{
18920 assert(set != NULL);
18921 assert(lp != NULL);
18922
18923 /* avoid to compare two different infinities; the reason for that is
18924 * that such a comparison can lead to unexpected results */
18925 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18926 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18927 || val1 == val2 ); /*lint !e777*/
18928
18929 return EPSGE(val1, val2, lp->feastol);
18930}
18931
18932/** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18934 SCIP_LP* lp, /**< current LP data */
18935 SCIP_Real val /**< value to process */
18936 )
18937{
18938 assert(lp != NULL);
18939
18940 return EPSZ(val, lp->feastol);
18941}
18942
18943/** checks, if value is greater than LP primal feasibility tolerance */
18945 SCIP_LP* lp, /**< current LP data */
18946 SCIP_Real val /**< value to process */
18947 )
18948{
18949 assert(lp != NULL);
18950
18951 return EPSP(val, lp->feastol);
18952}
18953
18954/** checks, if value is lower than -LP primal feasibility tolerance */
18956 SCIP_LP* lp, /**< current LP data */
18957 SCIP_Real val /**< value to process */
18958 )
18959{
18960 assert(lp != NULL);
18961
18962 return EPSN(val, lp->feastol);
18963}
static long bound
SCIP_VAR * a
SCIP_VAR ** b
SCIP_VAR ** y
SCIP_VAR ** x
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:6273
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition cons.c:6285
internal methods for constraints and constraint handlers
#define NULL
Definition def.h:262
#define SCIP_MAXSTRLEN
Definition def.h:283
#define EPSGE(x, y, eps)
Definition def.h:201
#define SCIP_Longint
Definition def.h:157
#define SCIP_UNUSED(x)
Definition def.h:423
#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:238
#define SCIP_ALLOC(x)
Definition def.h:380
#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:230
#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:234
#define SCIP_CALL_ABORT(x)
Definition def.h:348
#define EPSN(x, eps)
Definition def.h:204
#define SCIP_LONGINT_FORMAT
Definition def.h:164
#define SCIPABORT()
Definition def.h:341
#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:369
SCIP_RETCODE SCIPeventCreateRowDeletedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition event.c:913
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition event.c:2240
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition event.c:1846
SCIP_RETCODE SCIPeventCreateRowSideChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition event.c:980
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition event.c:1979
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition event.c:1821
SCIP_RETCODE SCIPeventCreateRowConstChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_Real oldval, SCIP_Real newval)
Definition event.c:957
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition event.c:1886
SCIP_RETCODE SCIPeventCreateRowCoefChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition event.c:932
SCIP_RETCODE SCIPeventCreateRowAddedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition event.c:894
internal methods for managing events
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition lpi_clp.cpp:1179
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition lpi_clp.cpp:3457
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition lpi_clp.cpp:3377
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition lpi_clp.cpp:3824
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition lpi_clp.cpp:3947
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2718
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2478
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition lpi_clp.cpp:2995
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition lpi_clp.cpp:920
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition lpi_clp.cpp:2860
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition lpi_clp.cpp:3676
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition lpi_clp.cpp:4029
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition lpi_clp.cpp:480
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition lpi_clp.cpp:3861
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition lpi_clp.cpp:2311
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition lpi_clp.cpp:3638
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition lpi_clp.cpp:2357
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition lpi_clp.cpp:1733
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition lpi_clp.cpp:2885
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition lpi_clp.cpp:2794
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2780
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2034
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition lpi_clp.cpp:2433
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition lpi_clp.cpp:3651
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2748
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition lpi_clp.cpp:1096
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2516
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition lpi_clp.cpp:1669
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition lpi_clp.cpp:643
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition lpi_clp.cpp:2332
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2549
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2637
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition lpi_clp.cpp:3620
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2764
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition lpi_clp.cpp:3550
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition lpi_clp.cpp:3720
const char * SCIPlpiGetSolverName(void)
Definition lpi_clp.cpp:454
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2496
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition lpi_clp.cpp:3269
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition lpi_clp.cpp:992
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition lpi_clp.cpp:3304
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition lpi_clp.cpp:3342
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition lpi_clp.cpp:1985
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2651
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2046
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition lpi_clp.cpp:1766
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition lpi_clp.cpp:2378
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition lpi_clp.cpp:2816
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2584
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition lpi_clp.cpp:874
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition lpi_clp.cpp:1708
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition lpi_clp.cpp:3531
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2530
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition lpi_clp.cpp:1908
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition lpi_clp.cpp:758
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition lpi_clp.cpp:1833
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition lpi_clp.cpp:2949
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition lpi_clp.cpp:3217
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition lpi_clp.cpp:531
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition lpi_clp.cpp:1252
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition lpi_clp.cpp:2675
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition lpi_clp.cpp:1447
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition lpi_clp.cpp:3923
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition lpi_clp.cpp:837
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition lpi_clp.cpp:1030
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition lpi_clp.cpp:1429
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition lpi_clp.cpp:3417
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9122
#define SCIPisFinite(x)
Definition pub_misc.h:1933
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9395
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11213
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition misc.c:10397
SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
Definition lp.c:17038
int SCIPcolGetLPPos(SCIP_COL *col)
Definition lp.c:17122
int SCIPcolGetVarProbindex(SCIP_COL *col)
Definition lp.c:17091
SCIP_Bool SCIPcolIsRemovable(SCIP_COL *col)
Definition lp.c:17112
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition lp.c:17071
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition lp.c:17101
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition lp.c:16982
int SCIPcolGetNNonz(SCIP_COL *col)
Definition lp.c:17155
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition lp.c:17190
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition lp.c:17180
void SCIPcolSort(SCIP_COL *col)
Definition lp.c:3433
int SCIPcolGetIndex(SCIP_COL *col)
Definition lp.c:17081
SCIP_Real SCIPcolGetBestBound(SCIP_COL *col)
Definition lp.c:17012
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition lp.c:16992
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:17025
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition lp.c:17002
SCIP_Longint SCIPcolGetStrongbranchNode(SCIP_COL *col)
Definition lp.c:17202
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition lp.c:17169
int SCIPcolGetNStrongbranchs(SCIP_COL *col)
Definition lp.c:17212
int SCIPcolGetAge(SCIP_COL *col)
Definition lp.c:17222
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17144
int SCIPcolGetLPDepth(SCIP_COL *col)
Definition lp.c:17133
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition lp.c:17060
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition lp.c:17232
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition lp.c:17048
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8253
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)
struct SCIP_Interval SCIP_INTERVAL
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:17420
void SCIProwSort(SCIP_ROW *row)
Definition lp.c:6012
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17321
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition lp.c:17440
SCIP_Longint SCIProwGetActiveLPCount(SCIP_ROW *row)
Definition lp.c:17574
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition lp.c:7784
SCIP_Real SCIProwGetScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition lp.c:7004
int SCIProwGetLPDepth(SCIP_ROW *row)
Definition lp.c:17541
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition lp.c:7720
SCIP_CONS * SCIProwGetOriginCons(SCIP_ROW *row)
Definition lp.c:17470
int SCIProwGetNNonz(SCIP_ROW *row)
Definition lp.c:17242
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition lp.c:17267
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition lp.c:17520
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17331
int SCIProwGetAge(SCIP_ROW *row)
Definition lp.c:17400
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition lp.c:17256
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition lp.c:17297
int SCIProwGetLPPos(SCIP_ROW *row)
Definition lp.c:17530
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition lp.c:17430
SCIP_CONSHDLR * SCIProwGetOriginConshdlr(SCIP_ROW *row)
Definition lp.c:17485
SCIP_Longint SCIProwGetNLPsAfterCreation(SCIP_ROW *row)
Definition lp.c:17584
void SCIProwLock(SCIP_ROW *row)
Definition lp.c:5374
SCIP_Bool SCIProwIsRemovable(SCIP_ROW *row)
Definition lp.c:17450
const char * SCIProwGetName(SCIP_ROW *row)
Definition lp.c:17380
SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
Definition lp.c:17505
void SCIProwUnlock(SCIP_ROW *row)
Definition lp.c:5389
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition lp.c:17309
int SCIProwGetRank(SCIP_ROW *row)
Definition lp.c:17410
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17354
int SCIProwGetIndex(SCIP_ROW *row)
Definition lp.c:17390
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition lp.c:17563
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition lp.c:17287
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17552
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17341
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition lp.c:17277
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition lp.c:17460
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition lp.c:17369
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:17807
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:18208
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:17617
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:17556
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:18162
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition var.c:3416
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:17944
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:18106
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:17786
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:17437
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:17628
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition var.c:18244
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:18152
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:18096
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition var.c:3429
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:18483
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition var.c:17954
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition var.c:18234
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:10878
void SCIPprintSysError(const char *message)
Definition misc.c:10770
return SCIP_OKAY
SCIP_Bool lperror
int c
heurdata nlpiterations
int depth
SCIP_Real objval
int nlprows
static SCIP_SOL * sol
SCIP_Longint nlps
int r
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real primsol
SCIP_Real objscale
SCIP_Real newobj
SCIP_Real oldobj
static SCIP_VAR ** vars
SCIP_Real alpha
interval arithmetics for provable bounds
static SCIP_RETCODE lpFlushDelRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition lp.c:8175
static void rowCalcIdxsAndVals(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:4826
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:15882
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition lp.c:17866
#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:13441
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:6667
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6920
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:6250
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:9847
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:6332
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:11587
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition lp.c:13383
void SCIProwCapture(SCIP_ROW *row)
Definition lp.c:5335
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition lp.c:10097
SCIP_Real SCIProwGetPseudoFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6446
SCIP_RETCODE SCIPlpUpdateAges(SCIP_LP *lp, SCIP_STAT *stat)
Definition lp.c:15273
SCIP_RETCODE SCIPlpGetBInvCol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition lp.c:9869
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition lp.c:3755
#define DIVESTACKGROWFACT
Definition lp.c:16319
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:10114
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:10667
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:5472
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:10130
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:8619
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:9787
int SCIProwGetNumIntCols(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:6731
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:10030
void SCIPlpRecalculateObjSqrNorm(SCIP_SET *set, SCIP_LP *lp)
Definition lp.c:17705
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:15606
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition lp.c:17672
SCIP_Real SCIProwGetSolFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition lp.c:6504
void SCIProwRecalcPseudoActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition lp.c:6391
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:18944
SCIP_Bool SCIPlpIsFeasGT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition lp.c:18893
SCIP_RETCODE SCIPlpIsInfeasibilityProved(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool *proved)
Definition lp.c:16536
SCIP_Real SCIProwGetRelaxFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6270
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition lp.c:9447
#define MAXNUMTROUBLELPMSGS
Definition lp.c:11496
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition lp.c:13169
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:10054
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:6522
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:13730
SCIP_Real SCIPlpGetObjNorm(SCIP_LP *lp)
Definition lp.c:17736
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6615
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:5977
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:15682
SCIP_Bool SCIProwIsLPEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool root)
Definition lp.c:6845
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition lp.c:6861
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:17886
#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:8667
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:13924
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition lp.c:14335
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:5636
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:10253
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:16558
int SCIProwGetMaxidx(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:6699
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:12003
static SCIP_RETCODE lpFlushAddRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition lp.c:8224
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:13343
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:6220
void SCIProwMarkNotRemovableLocal(SCIP_ROW *row, SCIP_STAT *stat)
Definition lp.c:7874
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:13897
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:13114
SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
Definition lp.c:9630
void SCIPlpStoreRootObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition lp.c:13189
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:5106
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:17683
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:13213
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:8899
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:13158
SCIP_RETCODE SCIPlpUpdateAddVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14033
SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition lp.c:9768
SCIP_Bool SCIPlpIsPrimalReliable(SCIP_LP *lp)
Definition lp.c:17846
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:17813
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:5426
SCIP_RETCODE SCIPlpGetBase(SCIP_LP *lp, int *cstat, int *rstat)
Definition lp.c:9830
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition lp.c:17826
#define FEASTOLTIGHTFAC
Definition lp.c:11584
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:12034
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition lp.c:12402
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:12422
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:6045
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:4896
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition lp.c:13130
static void computeLPBounds(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, SCIP_Real lpiinf, SCIP_Real *lb, SCIP_Real *ub)
Definition lp.c:7966
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:15921
void SCIProwRecalcLPActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition lp.c:6168
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:16412
SCIP_Real SCIProwGetMinval(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:6683
SCIP_RETCODE SCIPlpEndStrongbranch(SCIP_LP *lp)
Definition lp.c:4193
SCIP_Longint SCIPcolGetStrongbranchLPAge(SCIP_COL *col, SCIP_STAT *stat)
Definition lp.c:4735
static SCIP_RETCODE lpDelColset(SCIP_LP *lp, SCIP_SET *set, int *coldstat)
Definition lp.c:15333
static SCIP_RETCODE lpRemoveObsoleteCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition lp.c:15530
SCIP_Real SCIPlpGetRootObjval(SCIP_LP *lp)
Definition lp.c:17769
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:4936
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:18913
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:11558
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition lp.c:16522
static void checkLazyColArray(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:9577
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:8859
SCIP_Real SCIProwGetLPSolCutoffDistance(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_LP *lp)
Definition lp.c:6747
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:6462
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:9367
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:17896
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition lp.c:17661
SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition lp.c:10174
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:11276
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:5405
static void freeDiveChgSideArrays(SCIP_LP *lp)
Definition lp.c:9055
SCIP_RETCODE SCIPlpGetBInvARow(SCIP_LP *lp, int r, SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition lp.c:9895
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition lp.c:17803
SCIP_Bool SCIPlpIsFeasLT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition lp.c:18853
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:5524
static SCIP_RETCODE lpUpdateVarColumnProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14125
#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:15960
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition lp.c:17876
static void rowUpdateDelLP(SCIP_ROW *row)
Definition lp.c:8973
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition lp.c:17907
SCIP_RETCODE SCIPlpGetBasisInd(SCIP_LP *lp, int *basisind)
Definition lp.c:9813
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6960
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition lp.c:10154
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition lp.c:5726
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:18632
#define DIVESTACKINITSIZE
Definition lp.c:9072
SCIP_RETCODE SCIPlpGetDualDegeneracy(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *degeneracy, SCIP_Real *varconsratio)
Definition lp.c:18704
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:4767
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition lp.c:6804
SCIP_RETCODE SCIPlpGetSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition lp.c:14353
static void markRowDeleted(SCIP_ROW *row)
Definition lp.c:8159
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:13648
static const int nscalars
Definition lp.c:5740
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:4703
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:17930
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:17793
SCIP_RETCODE SCIPlpGetDualfarkas(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool forcedlpsolve, SCIP_Bool *valid)
Definition lp.c:15057
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition lp.c:5295
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition lp.c:10198
SCIP_RETCODE SCIPlpRecordOldRowSideDive(SCIP_LP *lp, SCIP_ROW *row, SCIP_SIDETYPE sidetype)
Definition lp.c:16322
static SCIP_RETCODE lpCleanupCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition lp.c:15744
SCIP_RETCODE SCIPlpMarkFlushed(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:8731
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:11413
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:9702
SCIP_Bool SCIProwIsRedundant(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6636
void SCIPlpStartStrongbranchProbing(SCIP_LP *lp)
Definition lp.c:16376
static SCIP_RETCODE lpFlushDelCols(SCIP_LP *lp)
Definition lp.c:7915
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:15258
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:8934
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:5581
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition lp.c:16346
SCIP_Real SCIPlpGetFeastol(SCIP_LP *lp)
Definition lp.c:10243
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:6904
static SCIP_RETCODE lpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14078
SCIP_RETCODE SCIPlpUpdateDelVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14054
void SCIPlpEndStrongbranchProbing(SCIP_LP *lp)
Definition lp.c:16389
SCIP_RETCODE SCIPlpGetBInvACol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition lp.c:9920
SCIP_Bool SCIPlpIsFeasZero(SCIP_LP *lp, SCIP_Real val)
Definition lp.c:18933
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:15713
static SCIP_RETCODE lpFlushChgCols(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:8372
static SCIP_RETCODE lpUpdateVarLooseProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14257
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:7829
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:5255
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:10476
static const char * lpalgoName(SCIP_LPALGO lpalgo)
Definition lp.c:10295
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:14212
static void getObjvalDeltaUb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldub, SCIP_Real newub, SCIP_Real *deltaval, int *deltainf)
Definition lp.c:13610
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:9075
SCIP_Bool SCIPlpDivingRowsChanged(SCIP_LP *lp)
Definition lp.c:17918
SCIP_RETCODE SCIPlpUpdateVarUbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition lp.c:13965
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:12223
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:9412
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:16361
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:7853
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:17759
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition lp.c:17836
SCIP_RETCODE SCIPlpUpdateVarUb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition lp.c:13992
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:13843
static void lpNumericalTroubleMessage(SCIP_MESSAGEHDLR *messagehdlr, SCIP_SET *set, SCIP_STAT *stat, SCIP_VERBLEVEL verblevel, const char *formatstr,...)
Definition lp.c:11505
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:14314
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition lp.c:13281
static SCIP_RETCODE reallocDiveChgSideArrays(SCIP_LP *lp, int minsize, SCIP_Real growfact)
Definition lp.c:9029
SCIP_Bool SCIPlpIsDualReliable(SCIP_LP *lp)
Definition lp.c:17856
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:9506
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:16572
static void getObjvalDeltaLb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real *deltaval, int *deltainf)
Definition lp.c:13572
int SCIProwGetMinidx(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:6715
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:16034
SCIP_Bool SCIPlpIsFeasNegative(SCIP_LP *lp, SCIP_Real val)
Definition lp.c:18955
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:16140
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition lp.c:17594
int SCIPlpGetNCols(SCIP_LP *lp)
Definition lp.c:17604
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:5694
SCIP_Real SCIPlpGetRootColumnObjval(SCIP_LP *lp)
Definition lp.c:17781
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:14670
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:5743
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition lp.c:10188
SCIP_Bool SCIPlpIsFeasEQ(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition lp.c:18833
static void markColDeleted(SCIP_COL *col)
Definition lp.c:7893
SCIP_Real SCIProwGetPseudoActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6418
static void checkLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:12313
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:9007
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition lp.c:17641
void SCIPlpSetRootLPIsRelax(SCIP_LP *lp, SCIP_Bool isrelax)
Definition lp.c:17748
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:5662
void SCIProwForceSort(SCIP_ROW *row, SCIP_SET *set)
Definition lp.c:6155
void SCIPcolMarkNotRemovableLocal(SCIP_COL *col, SCIP_STAT *stat)
Definition lp.c:4747
static SCIP_RETCODE updateLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:12340
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:17614
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition lp.c:6594
#define checkRowObjprod(row)
Definition lp.c:771
static const SCIP_Real scalars[]
Definition lp.c:5739
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:18873
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition lp.c:17694
void SCIPlpResetFeastol(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:10278
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition lp.c:14996
#define checkRow(row)
Definition lp.c:696
void SCIProwDelaySort(SCIP_ROW *row)
Definition lp.c:6144
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:13202
int SCIPlpGetNRows(SCIP_LP *lp)
Definition lp.c:17651
static SCIP_RETCODE lpFlushChgRows(SCIP_LP *lp, SCIP_SET *set)
Definition lp.c:8520
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:10318
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition lp.c:7796
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:9944
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:4480
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:15811
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition lp.c:13313
static SCIP_RETCODE lpDelRowset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int *rowdstat)
Definition lp.c:15432
void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
Definition lp.c:9799
static int SCIProwGetDiscreteScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition lp.c:7361
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14190
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition lp.c:5348
#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:8001
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:4090
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition misc.c:4366
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition misc.c:4245
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
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
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 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
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
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
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
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
SCIP_STATUS status
SCIP_Longint ndualresolvelpiterations
Definition struct_stat.h:70
SCIP_Longint nprimalresolvelpiterations
Definition struct_stat.h:69
SCIP_Longint nprimallps
SCIP_Longint nnodes
Definition struct_stat.h:82
SCIP_CLOCK * strongbranchtime
SCIP_CLOCK * barrierlptime
SCIP_Longint nduallps
SCIP_Longint nduallpiterations
Definition struct_stat.h:66
int nclockskipsleft
SCIP_Longint nlps
SCIP_Longint ndualresolvelps
SCIP_Longint domchgcount
SCIP_CLOCK * divinglptime
SCIP_Longint lpcount
SCIP_Longint nlpiterations
Definition struct_stat.h:62
SCIP_Longint nprimalresolvelps
SCIP_Longint nrootlpiterations
Definition struct_stat.h:63
SCIP_Longint nnumtroublelpmsgs
SCIP_CLOCK * resolveinstablelptime
SCIP_CLOCK * duallptime
SCIP_Longint ndivinglps
SCIP_Longint nrootlps
SCIP_CLOCK * primallptime
SCIP_Longint nprimallpiterations
Definition struct_stat.h:65
SCIP_CLOCK * solvingtime
SCIP_Longint nbarrierlps
SCIP_Bool userinterrupt
SCIP_CLOCK * lexduallptime
char * name
Definition struct_var.h:235
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
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
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:154
#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
struct SCIP_EventFilter SCIP_EVENTFILTER
Definition type_event.h:174
#define SCIP_EVENTTYPE_ROWCHANGED
Definition type_event.h:148
struct SCIP_EventQueue SCIP_EVENTQUEUE
Definition type_event.h:175
#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
struct SCIP_Event SCIP_EVENT
Definition type_event.h:156
#define SCIP_EVENTTYPE_ROWCONSTCHANGED
Definition type_event.h:113
struct SCIP_Row SCIP_ROW
Definition type_lp.h:104
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
struct SCIP_Lp SCIP_LP
Definition type_lp.h:110
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
struct SCIP_Col SCIP_COL
Definition type_lp.h:98
struct SCIP_LpSolVals SCIP_LPSOLVALS
Definition type_lp.h:92
struct SCIP_ColSolVals SCIP_COLSOLVALS
Definition type_lp.h:90
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
struct SCIP_RowSolVals SCIP_ROWSOLVALS
Definition type_lp.h:91
@ 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
struct SCIP_LPiState SCIP_LPISTATE
Definition type_lpi.h:107
struct SCIP_LPi SCIP_LPI
Definition type_lpi.h:106
struct SCIP_LPiNorms SCIP_LPINORMS
Definition type_lpi.h:108
@ 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
struct SCIP_Messagehdlr SCIP_MESSAGEHDLR
@ SCIP_VERBLEVEL_NONE
@ SCIP_VERBLEVEL_HIGH
@ SCIP_VERBLEVEL_FULL
struct SCIP_RealArray SCIP_REALARRAY
Definition type_misc.h:114
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:188
struct SCIP_Prob SCIP_PROB
Definition type_prob.h:52
@ SCIP_OBJSENSE_MINIMIZE
Definition type_prob.h:48
enum SCIP_Objsense SCIP_OBJSENSE
Definition type_prob.h:50
@ SCIP_FILECREATEERROR
@ SCIP_LPERROR
@ SCIP_INVALIDDATA
@ SCIP_PARAMETERUNKNOWN
@ SCIP_PARAMETERWRONGVAL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct SCIP_Sepa SCIP_SEPA
Definition type_sepa.h:51
struct SCIP_Set SCIP_SET
Definition type_set.h:71
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
@ SCIP_STATUS_TIMELIMIT
Definition type_stat.h:51
struct SCIP_Stat SCIP_STAT
Definition type_stat.h:69
struct SCIP_Var SCIP_VAR
Definition type_var.h:119
@ 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:13941
internal methods for problem variables