1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB) */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25 /**@file lp.c
26 * @ingroup OTHER_CFILES
27 * @brief LP management methods and data structures
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Kati Wolter
32 * @author Gerald Gamrath
33 *
34 * In LP management, we have to differ between the current LP and the SCIP_LP
35 * stored in the LP solver. All LP methods affect the current LP only.
36 * Before solving the current LP with the LP solver or setting an LP state,
37 * the LP solvers data has to be updated to the current LP with a call to
38 * lpFlush().
39 */
40
41 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42
43
44 #include "lpi/lpi.h"
45 #include "scip/clock.h"
46 #include "scip/cons.h"
47 #include "scip/event.h"
48 #include "scip/intervalarith.h"
49 #include "scip/lp.h"
50 #include "scip/misc.h"
51 #include "scip/prob.h"
52 #include "scip/pub_lp.h"
53 #include "scip/pub_message.h"
54 #include "scip/pub_misc.h"
55 #include "scip/pub_misc_sort.h"
56 #include "scip/pub_var.h"
57 #include "scip/set.h"
58 #include "scip/sol.h"
59 #include "scip/solve.h"
60 #include "scip/stat.h"
61 #include "scip/struct_event.h"
62 #include "scip/struct_lp.h"
63 #include "scip/struct_prob.h"
64 #include "scip/struct_set.h"
65 #include "scip/struct_stat.h"
66 #include "scip/struct_var.h"
67 #include "scip/var.h"
68 #include <string.h>
69
70
71 /* activate this to use the row activities as given by the LPI instead of recalculating
72 * using the LP solver activity is potentially faster, but may not be consistent with the SCIP_ROW calculations
73 * see also #2594 for more details on possible trouble
74 */
75 /* #define SCIP_USE_LPSOLVER_ACTIVITY */
76
77 /*
78 * debug messages
79 */
80
81 #ifdef SCIP_DEBUG
82 /** method is to print in row in case SCIP_DEBUG is defined */
83 static
84 void debugRowPrint(
85 SCIP_SET* set, /**< global SCIP settings */
86 SCIP_ROW* row /**< LP row */
87 )
88 {
89 int i;
90
91 assert(row != NULL);
92
93 /* print row name */
94 if( row->name != NULL && row->name[0] != '\0' )
95 {
96 SCIPsetDebugMsgPrint(set, "%s: ", row->name);
97 }
98
99 /* print left hand side */
100 SCIPsetDebugMsgPrint(set, "%.15g <= ", row->lhs);
101
102 /* print coefficients */
103 if( row->len == 0 )
104 {
105 SCIPsetDebugMsgPrint(set, "0 ");
106 }
107 for( i = 0; i < row->len; ++i )
108 {
109 assert(row->cols[i] != NULL);
110 assert(row->cols[i]->var != NULL);
111 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
112 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
113 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
114 }
115
116 /* print constant */
117 if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
118 {
119 SCIPsetDebugMsgPrint(set, "%+.15g ", row->constant);
120 }
121
122 /* print right hand side */
123 SCIPsetDebugMsgPrint(set, "<= %.15g\n", row->rhs);
124 }
125 #else
126 #define debugRowPrint(x,y) /**/
127 #endif
128
129 #ifdef SCIP_DEBUG
130 /** method to output column if SCIP_DEBUG is define */
131 static
132 void debugColPrint(
133 SCIP_SET* set, /**< global SCIP settings */
134 SCIP_COL* col /**< LP column */
135 )
136 {
137 int r;
138
139 assert(col != NULL);
140 assert(col->var != NULL);
141
142 /* print bounds */
143 SCIPsetDebugMsgPrint(set, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
144
145 /* print coefficients */
146 if( col->len == 0 )
147 {
148 SCIPsetDebugMsgPrint(set, "<empty>");
149 }
150 for( r = 0; r < col->len; ++r )
151 {
152 assert(col->rows[r] != NULL);
153 assert(col->rows[r]->name != NULL);
154 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
155 }
156 SCIPsetDebugMsgPrint(set, "\n");
157 }
158 #else
159 #define debugColPrint(x,y) /**/
160 #endif
161
162 /*
163 * memory growing methods for dynamically allocated arrays
164 */
165
166 /** ensures, that chgcols array can store at least num entries */
167 static
168 SCIP_RETCODE ensureChgcolsSize(
169 SCIP_LP* lp, /**< current LP data */
170 SCIP_SET* set, /**< global SCIP settings */
171 int num /**< minimum number of entries to store */
172 )
173 {
174 assert(lp->nchgcols <= lp->chgcolssize);
175
176 if( num > lp->chgcolssize )
177 {
178 int newsize;
179
180 newsize = SCIPsetCalcMemGrowSize(set, num);
181 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
182 lp->chgcolssize = newsize;
183 }
184 assert(num <= lp->chgcolssize);
185
186 return SCIP_OKAY;
187 }
188
189 /** ensures, that chgrows array can store at least num entries */
190 static
191 SCIP_RETCODE ensureChgrowsSize(
192 SCIP_LP* lp, /**< current LP data */
193 SCIP_SET* set, /**< global SCIP settings */
194 int num /**< minimum number of entries to store */
195 )
196 {
197 assert(lp->nchgrows <= lp->chgrowssize);
198
199 if( num > lp->chgrowssize )
200 {
201 int newsize;
202
203 newsize = SCIPsetCalcMemGrowSize(set, num);
204 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
205 lp->chgrowssize = newsize;
206 }
207 assert(num <= lp->chgrowssize);
208
209 return SCIP_OKAY;
210 }
211
212 /** ensures, that lpicols array can store at least num entries */
213 static
214 SCIP_RETCODE ensureLpicolsSize(
215 SCIP_LP* lp, /**< current LP data */
216 SCIP_SET* set, /**< global SCIP settings */
217 int num /**< minimum number of entries to store */
218 )
219 {
220 assert(lp->nlpicols <= lp->lpicolssize);
221
222 if( num > lp->lpicolssize )
223 {
224 int newsize;
225
226 newsize = SCIPsetCalcMemGrowSize(set, num);
227 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
228 lp->lpicolssize = newsize;
229 }
230 assert(num <= lp->lpicolssize);
231
232 return SCIP_OKAY;
233 }
234
235 /** ensures, that lpirows array can store at least num entries */
236 static
237 SCIP_RETCODE ensureLpirowsSize(
238 SCIP_LP* lp, /**< current LP data */
239 SCIP_SET* set, /**< global SCIP settings */
240 int num /**< minimum number of entries to store */
241 )
242 {
243 assert(lp->nlpirows <= lp->lpirowssize);
244
245 if( num > lp->lpirowssize )
246 {
247 int newsize;
248
249 newsize = SCIPsetCalcMemGrowSize(set, num);
250 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
251 lp->lpirowssize = newsize;
252 }
253 assert(num <= lp->lpirowssize);
254
255 return SCIP_OKAY;
256 }
257
258 /** ensures, that cols array can store at least num entries */
259 static
260 SCIP_RETCODE ensureColsSize(
261 SCIP_LP* lp, /**< current LP data */
262 SCIP_SET* set, /**< global SCIP settings */
263 int num /**< minimum number of entries to store */
264 )
265 {
266 assert(lp->ncols <= lp->colssize);
267
268 if( num > lp->colssize )
269 {
270 int newsize;
271
272 newsize = SCIPsetCalcMemGrowSize(set, num);
273 SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
274 lp->colssize = newsize;
275 }
276 assert(num <= lp->colssize);
277
278 return SCIP_OKAY;
279 }
280
281 /** ensures, that soldirection array can store at least num entries */
282 static
283 SCIP_RETCODE ensureSoldirectionSize(
284 SCIP_LP* lp, /**< current LP data */
285 int num /**< minimum number of entries to store */
286 )
287 {
288 if( num > lp->soldirectionsize )
289 {
290 BMSfreeMemoryArrayNull(&lp->soldirection);
291 SCIP_ALLOC( BMSallocMemoryArray(&lp->soldirection, num) );
292
293 lp->soldirectionsize = num;
294 }
295
296 assert(num <= lp->soldirectionsize);
297
298 return SCIP_OKAY;
299 }
300
301 /** ensures, that lazy cols array can store at least num entries */
302 static
303 SCIP_RETCODE ensureLazycolsSize(
304 SCIP_LP* lp, /**< current LP data */
305 SCIP_SET* set, /**< global SCIP settings */
306 int num /**< minimum number of entries to store */
307 )
308 {
309 assert(lp->nlazycols <= lp->lazycolssize);
310
311 if( num > lp->lazycolssize )
312 {
313 int newsize;
314
315 newsize = SCIPsetCalcMemGrowSize(set, num);
316 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
317 lp->lazycolssize = newsize;
318 }
319 assert(num <= lp->lazycolssize);
320
321 return SCIP_OKAY;
322 }
323
324 /** ensures, that rows array can store at least num entries */
325 static
326 SCIP_RETCODE ensureRowsSize(
327 SCIP_LP* lp, /**< current LP data */
328 SCIP_SET* set, /**< global SCIP settings */
329 int num /**< minimum number of entries to store */
330 )
331 {
332 assert(lp->nrows <= lp->rowssize);
333
334 if( num > lp->rowssize )
335 {
336 int newsize;
337
338 newsize = SCIPsetCalcMemGrowSize(set, num);
339 SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
340 lp->rowssize = newsize;
341 }
342 assert(num <= lp->rowssize);
343
344 return SCIP_OKAY;
345 }
346
347 /** ensures, that row array of column can store at least num entries */
348 static
349 SCIP_RETCODE colEnsureSize(
350 SCIP_COL* col, /**< LP column */
351 BMS_BLKMEM* blkmem, /**< block memory */
352 SCIP_SET* set, /**< global SCIP settings */
353 int num /**< minimum number of entries to store */
354 )
355 {
356 assert(col != NULL);
357 assert(col->len <= col->size);
358
359 if( num > col->size )
360 {
361 int newsize;
362
363 newsize = SCIPsetCalcMemGrowSize(set, num);
364 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
365 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
366 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
367 col->size = newsize;
368 }
369 assert(num <= col->size);
370
371 return SCIP_OKAY;
372 }
373
374 /** save current LP values dependent on the solution */
375 static
376 SCIP_RETCODE lpStoreSolVals(
377 SCIP_LP* lp, /**< LP data */
378 SCIP_STAT* stat, /**< problem statistics */
379 BMS_BLKMEM* blkmem /**< block memory */
380 )
381 {
382 SCIP_LPSOLVALS* storedsolvals;
383
384 assert(lp != NULL);
385 assert(stat != NULL);
386 assert(blkmem != NULL);
387
388 /* allocate memory for storage */
389 if( lp->storedsolvals == NULL )
390 {
391 SCIP_ALLOC( BMSallocMemory(&lp->storedsolvals) );
392 }
393 storedsolvals = lp->storedsolvals;
394
395 /* store values */
396 storedsolvals->lpsolstat = lp->lpsolstat;
397 storedsolvals->lpobjval = lp->lpobjval;
398 storedsolvals->primalfeasible = lp->primalfeasible;
399 storedsolvals->primalchecked = lp->primalchecked;
400 storedsolvals->dualfeasible = lp->dualfeasible;
401 storedsolvals->dualchecked = lp->dualchecked;
402 storedsolvals->solisbasic = lp->solisbasic;
403 storedsolvals->lpissolved = lp->solved;
404
405 return SCIP_OKAY;
406 }
407
408 /** restore LP solution values in column */
409 static
410 SCIP_RETCODE lpRestoreSolVals(
411 SCIP_LP* lp, /**< LP data */
412 BMS_BLKMEM* blkmem, /**< block memory */
413 SCIP_Longint validlp /**< number of lp for which restored values are valid */
414 )
415 {
416 SCIP_LPSOLVALS* storedsolvals;
417
418 assert(lp != NULL);
419 assert(blkmem != NULL);
420
421 /* if stored values are available, restore them */
422 storedsolvals = lp->storedsolvals;
423 if( storedsolvals != NULL )
424 {
425 lp->solved = storedsolvals->lpissolved;
426 lp->validsollp = validlp;
427
428 lp->lpsolstat = storedsolvals->lpsolstat;
429 lp->lpobjval = storedsolvals->lpobjval;
430 lp->primalfeasible = storedsolvals->primalfeasible;
431 lp->primalchecked = storedsolvals->primalchecked;
432 lp->dualfeasible = storedsolvals->dualfeasible;
433 lp->dualchecked = storedsolvals->dualchecked;
434 lp->solisbasic = storedsolvals->solisbasic;
435
436 /* solution values are stored only for LPs solved to optimality or unboundedness */
437 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
438 lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY ||
439 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
440 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT ||
441 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT ||
442 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE ||
443 lp->validsollp == -1);
444 }
445 /* no values available, mark LP as unsolved */
446 else
447 {
448 lp->solved = FALSE;
449 lp->validsollp = -1;
450
451 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
452 lp->lpobjval = SCIP_INVALID;
453 lp->primalfeasible = FALSE;
454 lp->primalchecked = FALSE;
455 lp->dualfeasible = FALSE;
456 lp->dualchecked = FALSE;
457 lp->solisbasic = FALSE;
458 lp->validfarkaslp = -1;
459 }
460
461 lp->validdegeneracylp = -1;
462
463 /* intentionally keep storage space allocated */
464
465 return SCIP_OKAY;
466 }
467
468 /** save current LP solution values stored in each column */
469 static
470 SCIP_RETCODE colStoreSolVals(
471 SCIP_COL* col, /**< LP column */
472 BMS_BLKMEM* blkmem /**< block memory */
473 )
474 {
475 SCIP_COLSOLVALS* storedsolvals;
476
477 assert(col != NULL);
478 assert(blkmem != NULL);
479
480 /* allocate memory for storage */
481 if( col->storedsolvals == NULL )
482 {
483 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &col->storedsolvals) );
484 }
485 storedsolvals = col->storedsolvals;
486
487 /* store values */
488 storedsolvals->primsol = col->primsol;
489 storedsolvals->redcost = col->redcost;
490 storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
491
492 return SCIP_OKAY;
493 }
494
495 /** restore LP solution values in column */
496 static
497 SCIP_RETCODE colRestoreSolVals(
498 SCIP_COL* col, /**< LP column */
499 BMS_BLKMEM* blkmem, /**< block memory */
500 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
501 SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */
502 )
503 {
504 SCIP_COLSOLVALS* storedsolvals;
505
506 assert(col != NULL);
507 assert(blkmem != NULL);
508
509 /* if stored values are available, restore them */
510 storedsolvals = col->storedsolvals;
511 if( storedsolvals != NULL )
512 {
513 col->primsol = storedsolvals->primsol;
514 col->redcost = storedsolvals->redcost;
515 col->validredcostlp = validlp;
516 col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
517
518 /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
519 col->validfarkaslp = -1;
520 }
521 /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
522 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
523 */
524 else
525 {
526 col->primsol = 0.0;
527 col->validredcostlp = -1;
528 col->validfarkaslp = -1;
529 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
530 }
531
532 /* free memory */
533 if( freebuffer )
534 {
535 BMSfreeBlockMemoryNull(blkmem, &col->storedsolvals);
536 assert(col->storedsolvals == NULL);
537 }
538
539 return SCIP_OKAY;
540 }
541
542 /** save current LP solution values stored in each column */
543 static
544 SCIP_RETCODE rowStoreSolVals(
545 SCIP_ROW* row, /**< LP row */
546 BMS_BLKMEM* blkmem, /**< block memory */
547 SCIP_Bool infeasible /**< is the solution infeasible? */
548 )
549 {
550 SCIP_ROWSOLVALS* storedsolvals;
551
552 assert(row != NULL);
553 assert(blkmem != NULL);
554
555 /* allocate memory for storage */
556 if( row->storedsolvals == NULL )
557 {
558 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &row->storedsolvals) );
559 }
560 storedsolvals = row->storedsolvals;
561
562 /* store values */
563 if ( infeasible )
564 {
565 storedsolvals->dualsol = row->dualfarkas;
566 storedsolvals->activity = SCIP_INVALID;
567 storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
568 }
569 else
570 {
571 storedsolvals->dualsol = row->dualsol;
572 storedsolvals->activity = row->activity;
573 storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
574 }
575
576 return SCIP_OKAY;
577 }
578
579 /** restore LP solution values in row */
580 static
581 SCIP_RETCODE rowRestoreSolVals(
582 SCIP_ROW* row, /**< LP column */
583 BMS_BLKMEM* blkmem, /**< block memory */
584 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
585 SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */
586 SCIP_Bool infeasible /**< is the solution infeasible? */
587 )
588 {
589 SCIP_ROWSOLVALS* storedsolvals;
590
591 assert(row != NULL);
592 assert(blkmem != NULL);
593
594 /* if stored values are available, restore them */
595 storedsolvals = row->storedsolvals;
596 if( storedsolvals != NULL )
597 {
598 if ( infeasible )
599 row->dualfarkas = storedsolvals->dualsol;
600 else
601 row->dualsol = storedsolvals->dualsol;
602 row->activity = storedsolvals->activity;
603 row->validactivitylp = validlp;
604 row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
605 }
606 /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
607 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
608 */
609 else
610 {
611 row->dualsol = 0.0;
612 row->dualfarkas = 0.0;
613 row->activity = SCIP_INVALID;
614 row->validactivitylp = -1;
615 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
616 }
617
618 /* free memory */
619 if( freebuffer )
620 {
621 BMSfreeBlockMemoryNull(blkmem, &row->storedsolvals);
622 assert(row->storedsolvals == NULL);
623 }
624
625 return SCIP_OKAY;
626 }
627
628 /** ensures, that column array of row can store at least num entries */
629 SCIP_RETCODE SCIProwEnsureSize(
630 SCIP_ROW* row, /**< LP row */
631 BMS_BLKMEM* blkmem, /**< block memory */
632 SCIP_SET* set, /**< global SCIP settings */
633 int num /**< minimum number of entries to store */
634 )
635 {
636 assert(row != NULL);
637 assert(row->len <= row->size);
638
639 if( num > row->size )
640 {
641 int newsize;
642
643 newsize = SCIPsetCalcMemGrowSize(set, num);
644 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
645 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
646 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
647 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
648 row->size = newsize;
649 }
650 assert(num <= row->size);
651
652 return SCIP_OKAY;
653 }
654
655
656 #ifdef SCIP_MORE_DEBUG /* enable this to check the sortings within rows (for debugging, very slow!) */
657 static SCIP_Bool msgdisp_checkrow = FALSE;
658
659 static
660 void checkRow(
661 SCIP_ROW* row
662 )
663 {
664 int i;
665
666 if( !msgdisp_checkrow )
667 {
668 printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
669 msgdisp_checkrow = TRUE;
670 }
671
672 /* validate sorting of LP part of row */
673 if( row->lpcolssorted && row->nlpcols > 0)
674 {
675 assert(row->cols_index[0] == row->cols[0]->index);
676 for( i = 1; i < row->nlpcols; ++i )
677 {
678 assert(row->cols_index[i] == row->cols[i]->index);
679 assert(row->cols_index[i] >= row->cols_index[i-1]);
680 }
681 }
682
683 /* validate sorting of non-LP part of row */
684 if( row->nonlpcolssorted && row->len > row->nlpcols )
685 {
686 assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
687 for( i = row->nlpcols + 1; i < row->len; ++i )
688 {
689 assert(row->cols_index[i] == row->cols[i]->index);
690 assert(row->cols_index[i] >= row->cols_index[i-1]);
691 }
692 }
693 }
694 #else
695 #define checkRow(row) /**/
696 #endif
697
698 #ifdef SCIP_MORE_DEBUG /* enable this to check norms of rows (for debugging, very slow!) */
699 static
700 void checkRowSqrnorm(
701 SCIP_ROW* row
702 )
703 {
704 SCIP_COL** cols;
705 SCIP_Real sqrnorm;
706 int c;
707
708 cols = row->cols;
709 assert(cols != NULL || row->len == 0);
710
711 sqrnorm = 0.0;
712
713 for( c = row->len - 1; c >= 0; --c )
714 {
715 if( cols[c]->lppos >= 0 )
716 sqrnorm += SQR(row->vals[c]);
717 }
718
719 assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
720 }
721
722 static
723 void checkRowSumnorm(
724 SCIP_ROW* row
725 )
726 {
727 SCIP_COL** cols;
728 SCIP_Real sumnorm;
729 int c;
730
731 cols = row->cols;
732 assert(cols != NULL || row->len == 0);
733
734 sumnorm = 0.0;
735
736 for( c = row->len - 1; c >= 0; --c )
737 {
738 if( cols[c]->lppos >= 0 )
739 sumnorm += REALABS(row->vals[c]);
740 }
741
742 assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
743 }
744
745 static
746 void checkRowObjprod(
747 SCIP_ROW* row
748 )
749 {
750 SCIP_COL** cols;
751 SCIP_Real objprod;
752 int c;
753
754 cols = row->cols;
755 assert(cols != NULL || row->len == 0);
756
757 objprod = 0.0;
758
759 for( c = row->len - 1; c >= 0; --c )
760 {
761 if( cols[c]->lppos >= 0 )
762 objprod += row->vals[c] * cols[c]->unchangedobj;
763 }
764
765 assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
766 }
767 #else
768 #define checkRowSqrnorm(row) /**/
769 #define checkRowSumnorm(row) /**/
770 #define checkRowObjprod(row) /**/
771 #endif
772
773 /*
774 * Local methods for pseudo and loose objective values
775 */
776
777 /* recompute the loose objective value from scratch, if it was marked to be unreliable before */
778 static
779 void recomputeLooseObjectiveValue(
780 SCIP_LP* lp, /**< current LP data */
781 SCIP_SET* set, /**< global SCIP settings */
782 SCIP_PROB* prob /**< problem data */
783 )
784 {
785 SCIP_VAR** vars;
786 SCIP_Real obj;
787 int nvars;
788 int v;
789
790 assert(lp != NULL);
791 assert(set != NULL);
792 assert(prob != NULL);
793 assert(!lp->looseobjvalid);
794
795 vars = prob->vars;
796 nvars = prob->nvars;
797 lp->looseobjval = 0.0;
798
799 /* iterate over all variables in the problem */
800 for( v = 0; v < nvars; ++v )
801 {
802 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
803 {
804 obj = SCIPvarGetObj(vars[v]);
805
806 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
807 if( SCIPsetIsPositive(set, obj) && !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
808 lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
809 else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
810 lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
811 }
812 }
813
814 /* the recomputed value is reliable */
815 lp->rellooseobjval = lp->looseobjval;
816 lp->looseobjvalid = TRUE;
817 }
818
819 /* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
820 static
821 void recomputePseudoObjectiveValue(
822 SCIP_LP* lp, /**< current LP data */
823 SCIP_SET* set, /**< global SCIP settings */
824 SCIP_PROB* prob /**< problem data */
825 )
826 {
827 SCIP_VAR** vars;
828 int nvars;
829 int v;
830
831 assert(lp != NULL);
832 assert(set != NULL);
833 assert(prob != NULL);
834 assert(!lp->pseudoobjvalid);
835
836 vars = prob->vars;
837 nvars = prob->nvars;
838 lp->pseudoobjval = 0.0;
839
840 /* iterate over all variables in the problem */
841 for( v = 0; v < nvars; ++v )
842 {
843 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
844 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
845 !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
846 {
847 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
848 }
849 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
850 !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
851 {
852 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
853 }
854 }
855
856 /* the recomputed value is reliable */
857 lp->relpseudoobjval = lp->pseudoobjval;
858 lp->pseudoobjvalid = TRUE;
859 }
860
861 /* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
862 static
863 void recomputeGlbPseudoObjectiveValue(
864 SCIP_LP* lp, /**< current LP data */
865 SCIP_SET* set, /**< global SCIP settings */
866 SCIP_PROB* prob /**< problem data */
867 )
868 {
869 SCIP_VAR** vars;
870 int nvars;
871 int v;
872
873 assert(lp != NULL);
874 assert(set != NULL);
875 assert(prob != NULL);
876 assert(!lp->glbpseudoobjvalid);
877
878 vars = prob->vars;
879 nvars = prob->nvars;
880 lp->glbpseudoobjval = 0.0;
881
882 /* iterate over all variables in the problem */
883 for( v = 0; v < nvars; ++v )
884 {
885 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
886 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
887 !SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
888 {
889 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
890 }
891 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
892 !SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
893 {
894 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
895 }
896 }
897
898 /* the recomputed value is reliable */
899 lp->relglbpseudoobjval = lp->glbpseudoobjval;
900 lp->glbpseudoobjvalid = TRUE;
901 }
902
903 /** gets finite part of objective value of current LP that results from LOOSE variables only */
904 static
905 SCIP_Real getFiniteLooseObjval(
906 SCIP_LP* lp, /**< current LP data */
907 SCIP_SET* set, /**< global SCIP settings */
908 SCIP_PROB* prob /**< problem data */
909 )
910 {
911 assert(lp != NULL);
912 assert(set != NULL);
913 assert(prob != NULL);
914 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
915 assert(lp->flushed);
916 assert(lp->looseobjvalinf == 0);
917
918 /* recalculate the loose objective value, if needed */
919 if( !lp->looseobjvalid )
920 recomputeLooseObjectiveValue(lp, set, prob);
921
922 return lp->looseobjval;
923 }
924
925 /** gets finite part of pseudo objective value of current LP */
926 static
927 SCIP_Real getFinitePseudoObjval(
928 SCIP_LP* lp, /**< current LP data */
929 SCIP_SET* set, /**< global SCIP settings */
930 SCIP_PROB* prob /**< problem data */
931 )
932 {
933 assert(lp != NULL);
934 assert(set != NULL);
935 assert(prob != NULL);
936
937 /* recalculate the pseudo objective value, if needed */
938 if( !lp->pseudoobjvalid )
939 recomputePseudoObjectiveValue(lp, set, prob);
940
941 return lp->pseudoobjval;
942 }
943
944 /*
945 * Sorting and searching rows and columns
946 */
947
948
949 /** comparison method for sorting rows by non-decreasing index */
950 SCIP_DECL_SORTPTRCOMP(SCIProwComp)
951 {
952 assert(elem1 != NULL);
953 assert(elem2 != NULL);
954
955 if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
956 return -1;
957 else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
958 return +1;
959 else
960 {
961 assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
962 return 0;
963 }
964 }
965
966
967 /** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
968 static
969 void colSortLP(
970 SCIP_COL* col /**< column to be sorted */
971 )
972 {
973 int i;
974
975 assert(col != NULL);
976
977 /* check, if column is already sorted in the LP part */
978 if( col->lprowssorted )
979 return;
980
981 /* sort coefficients */
982 SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
983
984 /* update links */
985 for( i = 0; i < col->nlprows; ++i )
986 {
987 if( col->linkpos[i] >= 0 )
988 {
989 assert(col->rows[i]->cols[col->linkpos[i]] == col);
990 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
991 col->rows[i]->linkpos[col->linkpos[i]] = i;
992 }
993 }
994
995 col->lprowssorted = TRUE;
996 }
997
998 /** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
999 * ones
1000 */
1001 static
1002 void colSortNonLP(
1003 SCIP_COL* col /**< column to be sorted */
1004 )
1005 {
1006 int i;
1007
1008 assert(col != NULL);
1009
1010 /* check, if column is already sorted in the non-LP part */
1011 if( col->nonlprowssorted )
1012 return;
1013
1014 /* sort coefficients */
1015 SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
1016
1017 /* update links */
1018 for( i = col->nlprows; i < col->len; ++i )
1019 {
1020 if( col->linkpos[i] >= 0 )
1021 {
1022 assert(col->rows[i]->cols[col->linkpos[i]] == col);
1023 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
1024 col->rows[i]->linkpos[col->linkpos[i]] = i;
1025 }
1026 }
1027
1028 col->nonlprowssorted = TRUE;
1029 }
1030
1031 /** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
1032 static
1033 void rowSortLP(
1034 SCIP_ROW* row /**< row to be sorted */
1035 )
1036 {
1037 int i;
1038
1039 assert(row != NULL);
1040
1041 /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
1042 if( row->lpcolssorted || row->delaysort )
1043 return;
1044
1045 /* sort coefficients */
1046 SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
1047
1048 /* update links */
1049 for( i = 0; i < row->nlpcols; ++i )
1050 {
1051 if( row->linkpos[i] >= 0 )
1052 {
1053 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1054 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1055 row->cols[i]->linkpos[row->linkpos[i]] = i;
1056 }
1057 }
1058
1059 row->lpcolssorted = TRUE;
1060 }
1061
1062 /** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1063 * higher ones
1064 */
1065 static
1066 void rowSortNonLP(
1067 SCIP_ROW* row /**< row to be sorted */
1068 )
1069 {
1070 int i;
1071
1072 assert(row != NULL);
1073
1074 checkRow(row);
1075
1076 /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1077 if( row->nonlpcolssorted || row->delaysort )
1078 return;
1079
1080 /* sort coefficients */
1081 SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1082
1083 /* update links */
1084 for( i = row->nlpcols; i < row->len; ++i )
1085 {
1086 if( row->linkpos[i] >= 0 )
1087 {
1088 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1089 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1090 row->cols[i]->linkpos[row->linkpos[i]] = i;
1091 }
1092 }
1093
1094 checkRow(row);
1095
1096 row->nonlpcolssorted = TRUE;
1097 }
1098
1099 /** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1100 static
1101 int colSearchCoefPart(
1102 SCIP_COL* col, /**< column to be searched in */
1103 const SCIP_ROW* row, /**< coefficient to be searched for */
1104 int minpos, /**< first position of search range */
1105 int maxpos /**< last position of search range */
1106 )
1107 {
1108 int pos;
1109 int idx;
1110 int searchidx;
1111
1112 assert(col != NULL);
1113 assert(row != NULL);
1114
1115 /* binary search */
1116 searchidx = row->index;
1117 while(minpos <= maxpos)
1118 {
1119 pos = (minpos + maxpos)/2;
1120 assert(0 <= pos && pos < col->len);
1121 assert(col->rows[pos] != NULL);
1122 assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1123 idx = col->rows[pos]->index;
1124 if( searchidx == idx )
1125 return pos;
1126 else if( searchidx < idx )
1127 maxpos = pos-1;
1128 else
1129 minpos = pos+1;
1130 }
1131
1132 return -1;
1133 }
1134
1135 /** searches coefficient in column, returns position in col vector or -1 if not found */
1136 static
1137 int colSearchCoef(
1138 SCIP_COL* col, /**< column to be searched in */
1139 const SCIP_ROW* row /**< coefficient to be searched for */
1140 )
1141 {
1142 int pos;
1143
1144 assert(col != NULL);
1145 assert(row != NULL);
1146
1147 pos = -1;
1148
1149 /* search in the linked LP rows */
1150 if( row->lppos >= 0 )
1151 {
1152 /* column has to be sorted, such that binary search works */
1153 colSortLP(col);
1154 assert(col->lprowssorted);
1155
1156 pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1157 if( pos >= 0 )
1158 return pos;
1159 }
1160
1161 /* search in the non-LP/unlinked rows */
1162 if( row->lppos == -1 || col->nunlinked > 0 )
1163 {
1164 /* column has to be sorted, such that binary search works */
1165 colSortNonLP(col);
1166 assert(col->nonlprowssorted);
1167
1168 pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1169 }
1170
1171 return pos;
1172 }
1173
1174 /** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1175 static
1176 int rowSearchCoefPart(
1177 SCIP_ROW* row, /**< row to be searched in */
1178 const SCIP_COL* col, /**< coefficient to be searched for */
1179 int minpos, /**< first position of search range */
1180 int maxpos /**< last position of search range */
1181 )
1182 {
1183 int pos;
1184 int idx;
1185 int searchidx;
1186
1187 assert(row != NULL);
1188 assert(col != NULL);
1189
1190 /* binary search */
1191 searchidx = col->index;
1192 while(minpos <= maxpos)
1193 {
1194 pos = (minpos + maxpos)/2;
1195 assert(0 <= pos && pos < row->len);
1196 assert(row->cols[pos] != NULL);
1197 assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1198 assert(row->cols_index[pos] == row->cols[pos]->index);
1199 idx = row->cols_index[pos];
1200 if( searchidx == idx )
1201 return pos;
1202 else if( searchidx < idx )
1203 maxpos = pos-1;
1204 else
1205 minpos = pos+1;
1206 }
1207
1208 return -1;
1209 }
1210
1211 /** searches coefficient in row, returns position in row vector or -1 if not found;
1212 * if the sorting of the row is delayed, returns -1
1213 */
1214 static
1215 int rowSearchCoef(
1216 SCIP_ROW* row, /**< row to be searched in */
1217 const SCIP_COL* col /**< coefficient to be searched for */
1218 )
1219 {
1220 int pos;
1221
1222 assert(row != NULL);
1223 assert(col != NULL);
1224
1225 if( row->delaysort )
1226 return -1;
1227
1228 pos = -1;
1229
1230 /* search in the linked LP columns */
1231 if( col->lppos >= 0 )
1232 {
1233 /* row has to be sorted, such that binary search works */
1234 rowSortLP(row);
1235 assert(row->lpcolssorted);
1236
1237 pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1238 }
1239
1240 /* search in the non-LP/unlinked columns */
1241 if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1242 {
1243 /* row has to be sorted, such that binary search works */
1244 rowSortNonLP(row);
1245 assert(row->nonlpcolssorted);
1246
1247 pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1248 }
1249
1250 #ifndef NDEBUG
1251 /* validate result */
1252 assert(-1 <= pos && pos < row->len);
1253 if( pos >= 0 )
1254 assert(row->cols[pos] == col);
1255 else
1256 {
1257 int i;
1258 for( i = 0; i < row->len; ++i )
1259 assert(row->cols[i] != col);
1260 }
1261 #endif
1262
1263 return pos;
1264 }
1265
1266 /** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1267 static
1268 void colMoveCoef(
1269 SCIP_COL* col, /**< LP column */
1270 int oldpos, /**< old position of coefficient */
1271 int newpos /**< new position of coefficient */
1272 )
1273 {
1274 assert(col != NULL);
1275 assert(0 <= oldpos && oldpos < col->len);
1276 assert(0 <= newpos && newpos < col->len);
1277 assert(col->rows[oldpos] != NULL);
1278
1279 if( oldpos == newpos )
1280 return;
1281
1282 col->rows[newpos] = col->rows[oldpos];
1283 col->vals[newpos] = col->vals[oldpos];
1284 col->linkpos[newpos] = col->linkpos[oldpos];
1285
1286 /* update link position in row */
1287 if( col->linkpos[newpos] >= 0 )
1288 {
1289 assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1290 assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1291
1292 col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1293 }
1294
1295 /* update sorted flags */
1296 if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1297 col->lprowssorted = FALSE;
1298 else
1299 col->nonlprowssorted = FALSE;
1300 }
1301
1302 /** swaps two coefficients in a column, and updates all corresponding data structures */
1303 static
1304 void colSwapCoefs(
1305 SCIP_COL* col, /**< LP column */
1306 int pos1, /**< position of first coefficient */
1307 int pos2 /**< position of second coefficient */
1308 )
1309 {
1310 SCIP_ROW* tmprow;
1311 SCIP_Real tmpval;
1312 int tmplinkpos;
1313
1314 assert(col != NULL);
1315 assert(0 <= pos1 && pos1 < col->len);
1316 assert(0 <= pos2 && pos2 < col->len);
1317 assert(col->rows[pos1] != NULL);
1318
1319 if( pos1 == pos2 )
1320 return;
1321
1322 /* swap coefficients */
1323 tmprow = col->rows[pos2];
1324 tmpval = col->vals[pos2];
1325 tmplinkpos = col->linkpos[pos2];
1326
1327 col->rows[pos2] = col->rows[pos1];
1328 col->vals[pos2] = col->vals[pos1];
1329 col->linkpos[pos2] = col->linkpos[pos1];
1330
1331 col->rows[pos1] = tmprow;
1332 col->vals[pos1] = tmpval;
1333 col->linkpos[pos1] = tmplinkpos;
1334
1335 /* update link position in rows */
1336 if( col->linkpos[pos1] >= 0 )
1337 {
1338 assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1339 assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1340
1341 col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1342 }
1343 if( col->linkpos[pos2] >= 0 )
1344 {
1345 assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1346 assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1347
1348 col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1349 }
1350
1351 /* update sorted flags */
1352 if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1353 col->lprowssorted = FALSE;
1354 else
1355 col->nonlprowssorted = FALSE;
1356 if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1357 col->lprowssorted = FALSE;
1358 else
1359 col->nonlprowssorted = FALSE;
1360 }
1361
1362 /** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1363 static
1364 void rowMoveCoef(
1365 SCIP_ROW* row, /**< LP row */
1366 int oldpos, /**< old position of coefficient */
1367 int newpos /**< new position of coefficient */
1368 )
1369 {
1370 assert(row != NULL);
1371 assert(0 <= oldpos && oldpos < row->len);
1372 assert(0 <= newpos && newpos < row->len);
1373 assert(row->cols[oldpos] != NULL);
1374
1375 if( oldpos == newpos )
1376 return;
1377
1378 row->cols[newpos] = row->cols[oldpos];
1379 row->cols_index[newpos] = row->cols_index[oldpos];
1380 row->vals[newpos] = row->vals[oldpos];
1381 row->linkpos[newpos] = row->linkpos[oldpos];
1382
1383 /* update link position in column */
1384 if( row->linkpos[newpos] >= 0 )
1385 {
1386 assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1387 assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1388
1389 row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1390 }
1391
1392 /* update sorted flags */
1393 if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1394 row->lpcolssorted = FALSE;
1395 else
1396 row->nonlpcolssorted = FALSE;
1397 }
1398
1399 /** swaps two coefficients in a row, and updates all corresponding data structures */
1400 static
1401 void rowSwapCoefs(
1402 SCIP_ROW* row, /**< LP row */
1403 int pos1, /**< position of first coefficient */
1404 int pos2 /**< position of second coefficient */
1405 )
1406 {
1407 SCIP_COL* tmpcol;
1408 SCIP_Real tmpval;
1409 int tmpindex;
1410 int tmplinkpos;
1411
1412 assert(row != NULL);
1413 assert(0 <= pos1 && pos1 < row->len);
1414 assert(0 <= pos2 && pos2 < row->len);
1415 assert(row->cols[pos1] != NULL);
1416 assert(row->cols[pos1]->index == row->cols_index[pos1]);
1417
1418 if( pos1 == pos2 )
1419 return;
1420
1421 /* swap coefficients */
1422 tmpcol = row->cols[pos2];
1423 tmpindex = row->cols_index[pos2];
1424 tmpval = row->vals[pos2];
1425 tmplinkpos = row->linkpos[pos2];
1426
1427 row->cols[pos2] = row->cols[pos1];
1428 row->cols_index[pos2] = row->cols_index[pos1];
1429 row->vals[pos2] = row->vals[pos1];
1430 row->linkpos[pos2] = row->linkpos[pos1];
1431
1432 row->cols[pos1] = tmpcol;
1433 row->cols_index[pos1] = tmpindex;
1434 row->vals[pos1] = tmpval;
1435 row->linkpos[pos1] = tmplinkpos;
1436
1437 /* update link position in columns */
1438 if( row->linkpos[pos1] >= 0 )
1439 {
1440 assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1441 assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1442
1443 row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1444 }
1445 if( row->linkpos[pos2] >= 0 )
1446 {
1447 assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1448 assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1449
1450 row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1451 }
1452
1453 /* update sorted flags */
1454 if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1455 row->lpcolssorted = FALSE;
1456 else
1457 row->nonlpcolssorted = FALSE;
1458 if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1459 row->lpcolssorted = FALSE;
1460 else
1461 row->nonlpcolssorted = FALSE;
1462 }
1463
1464 /** issues a ROWCOEFCHANGED event on the given row */
1465 static
1466 SCIP_RETCODE rowEventCoefChanged(
1467 SCIP_ROW* row, /**< row which coefficient has changed */
1468 BMS_BLKMEM* blkmem, /**< block memory */
1469 SCIP_SET* set, /**< global SCIP settings */
1470 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1471 SCIP_COL* col, /**< the column which coefficient has changed */
1472 SCIP_Real oldval, /**< old value of the coefficient */
1473 SCIP_Real newval /**< new value of the coefficient */
1474 )
1475 {
1476 assert(row != NULL);
1477 assert(row->eventfilter != NULL);
1478 assert(col != NULL);
1479
1480 /* check, if the row is being tracked for coefficient changes
1481 * if so, issue ROWCOEFCHANGED event
1482 */
1483 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1484 {
1485 SCIP_EVENT* event;
1486
1487 SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1488 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1489 }
1490
1491 return SCIP_OKAY;
1492 }
1493
1494 /** issues a ROWCONSTCHANGED event on the given row */
1495 static
1496 SCIP_RETCODE rowEventConstantChanged(
1497 SCIP_ROW* row, /**< row which coefficient has changed */
1498 BMS_BLKMEM* blkmem, /**< block memory */
1499 SCIP_SET* set, /**< global SCIP settings */
1500 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1501 SCIP_Real oldval, /**< old value of the constant */
1502 SCIP_Real newval /**< new value of the constant */
1503 )
1504 {
1505 assert(row != NULL);
1506 assert(row->eventfilter != NULL);
1507
1508 /* check, if the row is being tracked for coefficient changes
1509 * if so, issue ROWCONSTCHANGED event
1510 */
1511 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCONSTCHANGED)) )
1512 {
1513 SCIP_EVENT* event;
1514
1515 SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1516 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1517 }
1518
1519 return SCIP_OKAY;
1520 }
1521
1522 /** issues a ROWSIDECHANGED event on the given row */
1523 static
1524 SCIP_RETCODE rowEventSideChanged(
1525 SCIP_ROW* row, /**< row which coefficient has changed */
1526 BMS_BLKMEM* blkmem, /**< block memory */
1527 SCIP_SET* set, /**< global SCIP settings */
1528 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1529 SCIP_SIDETYPE side, /**< the side that has changed */
1530 SCIP_Real oldval, /**< old value of side */
1531 SCIP_Real newval /**< new value of side */
1532 )
1533 {
1534 assert(row != NULL);
1535 assert(row->eventfilter != NULL);
1536
1537 /* check, if the row is being tracked for coefficient changes
1538 * if so, issue ROWSIDECHANGED event
1539 */
1540 if( (row->eventfilter->len > 0 && !(row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED)) )
1541 {
1542 SCIP_EVENT* event;
1543
1544 SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1545 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1546 }
1547
1548 return SCIP_OKAY;
1549 }
1550
1551 #ifdef SCIP_MORE_DEBUG /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */
1552
1553 #ifdef NDEBUG
1554 #define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1555 #else
1556 #define ASSERT(x) assert(x)
1557 #endif
1558
1559 static SCIP_Bool msgdisp_checklinks = FALSE;
1560
1561
1562 static
1563 void checkLinks(
1564 SCIP_LP* lp /**< current LP data */
1565 )
1566 {
1567 SCIP_COL* col;
1568 SCIP_ROW* row;
1569 int i;
1570 int j;
1571
1572 ASSERT(lp != NULL);
1573
1574 if( !msgdisp_checklinks )
1575 {
1576 printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1577 msgdisp_checklinks = TRUE;
1578 }
1579
1580 for( i = 0; i < lp->ncols; ++i )
1581 {
1582 col = lp->cols[i];
1583 ASSERT(col != NULL);
1584 ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1585 ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1586 ASSERT(col->nlprows <= col->len);
1587 ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1588
1589 for( j = 0; j < col->len; ++j )
1590 {
1591 row = col->rows[j];
1592 ASSERT(row != NULL);
1593 ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1594 ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1595 ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1596 ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1597 }
1598 }
1599
1600 for( i = 0; i < lp->nrows; ++i )
1601 {
1602 row = lp->rows[i];
1603 ASSERT(row != NULL);
1604 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1605 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1606 ASSERT(row->nlpcols <= row->len);
1607 ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1608
1609 for( j = 0; j < row->len; ++j )
1610 {
1611 col = row->cols[j];
1612 ASSERT(col != NULL);
1613 ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1614 ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1615 ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1616 ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1617 }
1618 }
1619 }
1620
1621 #undef ASSERT
1622
1623 #else
1624 #define checkLinks(lp) /**/
1625 #endif
1626
1627 /*
1628 * Changing announcements
1629 */
1630
1631 /** announces, that the given coefficient in the constraint matrix changed */
1632 static
1633 void coefChanged(
1634 SCIP_ROW* row, /**< LP row */
1635 SCIP_COL* col, /**< LP col */
1636 SCIP_LP* lp /**< current LP data */
1637 )
1638 {
1639 assert(row != NULL);
1640 assert(col != NULL);
1641 assert(lp != NULL);
1642
1643 if( row->lpipos >= 0 && col->lpipos >= 0 )
1644 {
1645 assert(row->lpipos < lp->nlpirows);
1646 assert(col->lpipos < lp->nlpicols);
1647
1648 /* we have to remember the change only in the row or in the column,
1649 * because the readdition of one vector would change the other automatically.
1650 */
1651 if( row->lpipos >= lp->lpifirstchgrow )
1652 row->coefchanged = TRUE;
1653 else if( col->lpipos >= lp->lpifirstchgcol )
1654 col->coefchanged = TRUE;
1655 else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1656 {
1657 row->coefchanged = TRUE;
1658 lp->lpifirstchgrow = row->lpipos;
1659 }
1660 else
1661 {
1662 col->coefchanged = TRUE;
1663 lp->lpifirstchgcol = col->lpipos;
1664 }
1665
1666 /* mark the current LP unflushed */
1667 lp->flushed = FALSE;
1668 }
1669
1670 row->pseudoactivity = SCIP_INVALID;
1671 row->minactivity = SCIP_INVALID;
1672 row->maxactivity = SCIP_INVALID;
1673 row->validpsactivitydomchg = -1;
1674 row->validactivitybdsdomchg = -1;
1675 }
1676
1677
1678
1679 /*
1680 * local column changing methods
1681 */
1682
1683 /* forward declaration for colAddCoef() */
1684 static
1685 SCIP_RETCODE rowAddCoef(
1686 SCIP_ROW* row, /**< LP row */
1687 BMS_BLKMEM* blkmem, /**< block memory */
1688 SCIP_SET* set, /**< global SCIP settings */
1689 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1690 SCIP_LP* lp, /**< current LP data */
1691 SCIP_COL* col, /**< LP column */
1692 SCIP_Real val, /**< value of coefficient */
1693 int linkpos /**< position of row in the column's row array, or -1 */
1694 );
1695
1696 /** adds a previously non existing coefficient to an LP column */
1697 static
1698 SCIP_RETCODE colAddCoef(
1699 SCIP_COL* col, /**< LP column */
1700 BMS_BLKMEM* blkmem, /**< block memory */
1701 SCIP_SET* set, /**< global SCIP settings */
1702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1703 SCIP_LP* lp, /**< current LP data */
1704 SCIP_ROW* row, /**< LP row */
1705 SCIP_Real val, /**< value of coefficient */
1706 int linkpos /**< position of column in the row's col array, or -1 */
1707 )
1708 {
1709 int pos;
1710
1711 assert(blkmem != NULL);
1712 assert(col != NULL);
1713 assert(col->nlprows <= col->len);
1714 assert(col->var != NULL);
1715 assert(row != NULL);
1716 assert(!SCIPsetIsZero(set, val));
1717 /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1718
1719 SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1720 assert(col->rows != NULL);
1721 assert(col->vals != NULL);
1722 assert(col->linkpos != NULL);
1723
1724 pos = col->len;
1725 col->len++;
1726
1727 /* if the row is in current LP and is linked to the column, we have to insert it at the end of the linked LP rows
1728 * part of the column's arrays
1729 */
1730 if( row->lppos >= 0 && linkpos >= 0 )
1731 {
1732 /* move the first non-LP/not linked row to the end */
1733 if( col->nlprows < pos )
1734 {
1735 colMoveCoef(col, col->nlprows, pos);
1736 pos = col->nlprows;
1737 }
1738 col->nlprows++;
1739 }
1740
1741 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1742 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1743
1744 /* insert the row at the correct position and update the links */
1745 col->rows[pos] = row;
1746 col->vals[pos] = val;
1747 col->linkpos[pos] = linkpos;
1748 if( linkpos == -1 )
1749 {
1750 col->nunlinked++;
1751
1752 /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1753 * of the row is not complete
1754 */
1755 if( col->lppos >= 0 )
1756 {
1757 /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1758 * has to be updated
1759 */
1760 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1761 if( row->lppos >= 0 )
1762 pos = col->nlprows-1;
1763 linkpos = col->linkpos[pos];
1764
1765 assert(0 <= linkpos && linkpos < row->len);
1766 assert(row->cols[linkpos] == col);
1767 assert(col->rows[pos] == row);
1768 assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1769 assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1770 }
1771 }
1772 else
1773 {
1774 assert(row->linkpos[linkpos] == -1);
1775 assert(row->nunlinked > 0);
1776 row->linkpos[linkpos] = pos;
1777 row->nunlinked--;
1778
1779 /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1780 * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1781 */
1782 if( col->lppos >= 0 )
1783 {
1784 row->nlpcols++;
1785 rowSwapCoefs(row, linkpos, row->nlpcols-1);
1786
1787 /* if no swap was necessary, mark nonlpcols to be unsorted */
1788 if( linkpos == row->nlpcols-1 )
1789 row->lpcolssorted = FALSE;
1790 }
1791 }
1792
1793 /* update the sorted flags */
1794 if( row->lppos >= 0 && linkpos >= 0 )
1795 {
1796 assert(col->nlprows >= 1);
1797 assert(col->rows[col->nlprows-1] == row);
1798 if( col->nlprows > 1 )
1799 col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1800 }
1801 else
1802 {
1803 assert(col->len - col->nlprows >= 1);
1804 assert(col->rows[col->len-1] == row);
1805 if( col->len - col->nlprows > 1 )
1806 col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1807 }
1808
1809 coefChanged(row, col, lp);
1810
1811 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1812 val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1813
1814 return SCIP_OKAY;
1815 }
1816
1817 /** deletes coefficient at given position from column */
1818 static
1819 SCIP_RETCODE colDelCoefPos(
1820 SCIP_COL* col, /**< column to be changed */
1821 SCIP_SET* set, /**< global SCIP settings */
1822 SCIP_LP* lp, /**< current LP data */
1823 int pos /**< position in column vector to delete */
1824 )
1825 {
1826 SCIP_ROW* row;
1827
1828 assert(col != NULL);
1829 assert(col->var != NULL);
1830 assert(set != NULL);
1831 assert(0 <= pos && pos < col->len);
1832 assert(col->rows[pos] != NULL);
1833 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1834 assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1835
1836 row = col->rows[pos];
1837 assert((row->lppos >= 0) == (pos < col->nlprows));
1838
1839 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from column <%s>\n",
1840 col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1841
1842 if( col->linkpos[pos] == -1 )
1843 col->nunlinked--;
1844
1845 /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1846 if( pos < col->nlprows )
1847 {
1848 colMoveCoef(col, col->nlprows-1, pos);
1849 col->nlprows--;
1850 pos = col->nlprows;
1851 }
1852
1853 /* move last coefficient to position of empty slot */
1854 colMoveCoef(col, col->len-1, pos);
1855 col->len--;
1856
1857 coefChanged(row, col, lp);
1858
1859 return SCIP_OKAY;
1860 }
1861
1862 /** changes a coefficient at given position of an LP column */
1863 static
1864 SCIP_RETCODE colChgCoefPos(
1865 SCIP_COL* col, /**< LP column */
1866 SCIP_SET* set, /**< global SCIP settings */
1867 SCIP_LP* lp, /**< current LP data */
1868 int pos, /**< position in column vector to change */
1869 SCIP_Real val /**< value of coefficient */
1870 )
1871 {
1872 assert(col != NULL);
1873 assert(col->var != NULL);
1874 assert(0 <= pos && pos < col->len);
1875 assert(col->rows[pos] != NULL);
1876 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1877
1878 /*debugMsg(scip, "changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1879 col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1880
1881 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1882 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1883
1884 if( SCIPsetIsZero(set, val) )
1885 {
1886 /* delete existing coefficient */
1887 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1888 }
1889 else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1890 {
1891 /* change existing coefficient */
1892 col->vals[pos] = val;
1893 coefChanged(col->rows[pos], col, lp);
1894 }
1895
1896 return SCIP_OKAY;
1897 }
1898
1899
1900
1901
1902 /*
1903 * local row changing methods
1904 */
1905
1906 /** update row norms after addition of coefficient */
1907 static
1908 void rowAddNorms(
1909 SCIP_ROW* row, /**< LP row */
1910 SCIP_SET* set, /**< global SCIP settings */
1911 SCIP_COL* col, /**< column of added coefficient */
1912 SCIP_Real val, /**< value of added coefficient */
1913 SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */
1914 )
1915 {
1916 SCIP_Real absval;
1917
1918 assert(row != NULL);
1919 assert(row->nummaxval >= 0);
1920 assert(row->numminval >= 0);
1921 assert(set != NULL);
1922 assert(col != NULL);
1923
1924 absval = REALABS(val);
1925 assert(!SCIPsetIsZero(set, absval));
1926
1927 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
1928 if( col->lppos >= 0 )
1929 {
1930 /* update squared Euclidean norm and sum norm */
1931 row->sqrnorm += SQR(absval);
1932 row->sumnorm += absval;
1933
1934 /* update objective function scalar product */
1935 row->objprod += val * col->unchangedobj;
1936 }
1937
1938 if( updateidxvals )
1939 {
1940 /* update min/maxidx */
1941 row->minidx = MIN(row->minidx, col->index);
1942 row->maxidx = MAX(row->maxidx, col->index);
1943
1944 /* update maximal and minimal non-zero value */
1945 if( row->nummaxval > 0 )
1946 {
1947 if( SCIPsetIsGT(set, absval, row->maxval) )
1948 {
1949 row->maxval = absval;
1950 row->nummaxval = 1;
1951 }
1952 else if( SCIPsetIsGE(set, absval, row->maxval) )
1953 {
1954 /* make sure the maxval is always exactly the same */
1955 row->maxval = MAX(absval, row->maxval);
1956 row->nummaxval++;
1957 }
1958 }
1959 if( row->numminval > 0 )
1960 {
1961 if( SCIPsetIsLT(set, absval, row->minval) )
1962 {
1963 row->minval = absval;
1964 row->numminval = 1;
1965 }
1966 else if( SCIPsetIsLE(set, absval, row->minval) )
1967 {
1968 /* make sure the minval is always exactly the same */
1969 row->minval = MIN(absval, row->minval);
1970 row->numminval++;
1971 }
1972 }
1973 }
1974 else
1975 {
1976 assert(row->minidx <= col->index);
1977 assert(row->maxidx >= col->index);
1978 assert(row->numminval <= 0 || absval >= row->minval);
1979 assert(row->nummaxval <= 0 || absval <= row->maxval);
1980 }
1981 }
1982
1983 /** update row norms after deletion of coefficient */
1984 static
1985 void rowDelNorms(
1986 SCIP_ROW* row, /**< LP row */
1987 SCIP_SET* set, /**< global SCIP settings */
1988 SCIP_COL* col, /**< column of deleted coefficient */
1989 SCIP_Real val, /**< value of deleted coefficient */
1990 SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */
1991 SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */
1992 SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */
1993 )
1994 {
1995 SCIP_Real absval;
1996
1997 assert(row != NULL);
1998 assert(row->nummaxval >= 0);
1999 assert(row->numminval >= 0);
2000 assert(set != NULL);
2001 assert(col != NULL);
2002
2003 absval = REALABS(val);
2004 assert(!SCIPsetIsZero(set, absval));
2005 assert(row->nummaxval == 0 || row->maxval >= absval);
2006 assert(row->numminval == 0 || row->minval <= absval);
2007
2008 /* update min/maxidx validity */
2009 if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
2010 row->validminmaxidx = FALSE;
2011
2012 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
2013 if( forcenormupdate || col->lppos >= 0 )
2014 {
2015 /* update squared Euclidean norm and sum norm */
2016 row->sqrnorm -= SQR(absval);
2017 row->sqrnorm = MAX(row->sqrnorm, 0.0);
2018 row->sumnorm -= absval;
2019 row->sumnorm = MAX(row->sumnorm, 0.0);
2020
2021 /* update objective function scalar product */
2022 row->objprod -= val * col->unchangedobj;
2023 }
2024
2025 if( updateval )
2026 {
2027 /* update maximal and minimal non-zero value */
2028 if( row->nummaxval > 0 )
2029 {
2030 if( SCIPsetIsGE(set, absval, row->maxval) )
2031 row->nummaxval--;
2032 }
2033 if( row->numminval > 0 )
2034 {
2035 if( SCIPsetIsLE(set, absval, row->minval) )
2036 row->numminval--;
2037 }
2038 }
2039 }
2040
2041 /** adds a previously non existing coefficient to an LP row */
2042 static
2043 SCIP_RETCODE rowAddCoef(
2044 SCIP_ROW* row, /**< LP row */
2045 BMS_BLKMEM* blkmem, /**< block memory */
2046 SCIP_SET* set, /**< global SCIP settings */
2047 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2048 SCIP_LP* lp, /**< current LP data */
2049 SCIP_COL* col, /**< LP column */
2050 SCIP_Real val, /**< value of coefficient */
2051 int linkpos /**< position of row in the column's row array, or -1 */
2052 )
2053 {
2054 int pos;
2055
2056 assert(row != NULL);
2057 assert(row->nlpcols <= row->len);
2058 assert(blkmem != NULL);
2059 assert(col != NULL);
2060 assert(col->var != NULL);
2061 assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2062 assert(!SCIPsetIsZero(set, val));
2063 /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2064
2065 if( row->nlocks > 0 )
2066 {
2067 SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2068 return SCIP_INVALIDDATA;
2069 }
2070
2071 SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2072 assert(row->cols != NULL);
2073 assert(row->vals != NULL);
2074
2075 pos = row->len;
2076 row->len++;
2077
2078 /* if the column is in current LP and is linked to the row, we have to insert it at the end of the linked LP columns
2079 * part of the row's arrays
2080 */
2081 if( col->lppos >= 0 && linkpos >= 0 )
2082 {
2083 /* move the first non-LP/not linked column to the end */
2084 if( row->nlpcols < pos )
2085 {
2086 rowMoveCoef(row, row->nlpcols, pos);
2087 pos = row->nlpcols;
2088 }
2089 row->nlpcols++;
2090 }
2091
2092 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2093 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2094
2095 /* insert the column at the correct position and update the links */
2096 row->cols[pos] = col;
2097 row->cols_index[pos] = col->index;
2098 row->vals[pos] = val;
2099 row->linkpos[pos] = linkpos;
2100 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2101 if( linkpos == -1 )
2102 {
2103 row->nunlinked++;
2104
2105 /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2106 * of the column is not complete
2107 */
2108 if( row->lppos >= 0 )
2109 {
2110 /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2111 * has to be updated
2112 */
2113 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2114 if( col->lppos >= 0 )
2115 pos = row->nlpcols-1;
2116 linkpos = row->linkpos[pos];
2117
2118 assert(0 <= linkpos && linkpos < col->len);
2119 assert(col->rows[linkpos] == row);
2120 assert(row->cols[pos] == col);
2121 assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2122 assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2123 }
2124 }
2125 else
2126 {
2127 assert(col->linkpos[linkpos] == -1);
2128 assert(col->nunlinked > 0);
2129 col->linkpos[linkpos] = pos;
2130 col->nunlinked--;
2131
2132 /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2133 * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2134 */
2135 if( row->lppos >= 0 )
2136 {
2137 col->nlprows++;
2138 colSwapCoefs(col, linkpos, col->nlprows-1);
2139
2140 /* if no swap was necessary, mark lprows to be unsorted */
2141 if( linkpos == col->nlprows-1 )
2142 col->lprowssorted = FALSE;
2143 }
2144 }
2145
2146 /* update the sorted flags */
2147 if( col->lppos >= 0 && linkpos >= 0 )
2148 {
2149 assert(row->nlpcols >= 1);
2150 assert(row->cols[row->nlpcols-1] == col);
2151 if( row->nlpcols > 1 )
2152 {
2153 assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2154 row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2155 }
2156 }
2157 else
2158 {
2159 assert(row->len - row->nlpcols >= 1);
2160 assert(row->cols[row->len-1] == col);
2161 if( row->len - row->nlpcols > 1 )
2162 {
2163 assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2164 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2165 }
2166 }
2167
2168 /* update row norm */
2169 rowAddNorms(row, set, col, val, TRUE);
2170
2171 coefChanged(row, col, lp);
2172
2173 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2174 val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2175
2176 /* issue row coefficient changed event */
2177 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2178
2179 return SCIP_OKAY;
2180 }
2181
2182 /** deletes coefficient at given position from row */
2183 static
2184 SCIP_RETCODE rowDelCoefPos(
2185 SCIP_ROW* row, /**< row to be changed */
2186 BMS_BLKMEM* blkmem, /**< block memory */
2187 SCIP_SET* set, /**< global SCIP settings */
2188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2189 SCIP_LP* lp, /**< current LP data */
2190 int pos /**< position in row vector to delete */
2191 )
2192 {
2193 SCIP_COL* col;
2194 SCIP_Real val;
2195
2196 assert(row != NULL);
2197 assert(set != NULL);
2198 assert(0 <= pos && pos < row->len);
2199 assert(row->cols[pos] != NULL);
2200 assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2201
2202 col = row->cols[pos];
2203 val = row->vals[pos];
2204 assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2205
2206 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from row <%s>\n",
2207 val, SCIPvarGetName(col->var), pos, row->name);*/
2208
2209 if( row->nlocks > 0 )
2210 {
2211 SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2212 return SCIP_INVALIDDATA;
2213 }
2214
2215 if( row->linkpos[pos] == -1 )
2216 row->nunlinked--;
2217
2218 /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2219 if( pos < row->nlpcols )
2220 {
2221 rowMoveCoef(row, row->nlpcols-1, pos);
2222 assert(!row->lpcolssorted);
2223 row->nlpcols--;
2224 pos = row->nlpcols;
2225 }
2226
2227 /* move last coefficient to position of empty slot */
2228 rowMoveCoef(row, row->len-1, pos);
2229 row->len--;
2230
2231 /* update norms */
2232 rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2233
2234 coefChanged(row, col, lp);
2235
2236 /* issue row coefficient changed event */
2237 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2238
2239 return SCIP_OKAY;
2240 }
2241
2242 /** changes a coefficient at given position of an LP row */
2243 static
2244 SCIP_RETCODE rowChgCoefPos(
2245 SCIP_ROW* row, /**< LP row */
2246 BMS_BLKMEM* blkmem, /**< block memory */
2247 SCIP_SET* set, /**< global SCIP settings */
2248 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2249 SCIP_LP* lp, /**< current LP data */
2250 int pos, /**< position in row vector to change */
2251 SCIP_Real val /**< value of coefficient */
2252 )
2253 {
2254 SCIP_COL* col;
2255
2256 assert(row != NULL);
2257 assert(0 <= pos && pos < row->len);
2258
2259 /*SCIPsetDebugMsg(set, "changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2260 row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2261
2262 if( row->nlocks > 0 )
2263 {
2264 SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2265 return SCIP_INVALIDDATA;
2266 }
2267
2268 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2269 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2270 col = row->cols[pos];
2271 assert(row->cols[pos] != NULL);
2272
2273 if( SCIPsetIsZero(set, val) )
2274 {
2275 /* delete existing coefficient */
2276 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2277 }
2278 else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2279 {
2280 SCIP_Real oldval;
2281
2282 oldval = row->vals[pos];
2283
2284 /* change existing coefficient */
2285 rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2286 row->vals[pos] = val;
2287 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2288 rowAddNorms(row, set, col, row->vals[pos], TRUE);
2289 coefChanged(row, col, lp);
2290
2291 /* issue row coefficient changed event */
2292 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2293 }
2294
2295 return SCIP_OKAY;
2296 }
2297
2298 /** notifies LP row, that its sides were changed */
2299 static
2300 SCIP_RETCODE rowSideChanged(
2301 SCIP_ROW* row, /**< LP row */
2302 SCIP_SET* set, /**< global SCIP settings */
2303 SCIP_LP* lp, /**< current LP data */
2304 SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */
2305 )
2306 {
2307 assert(row != NULL);
2308 assert(lp != NULL);
2309
2310 if( row->lpipos >= 0 )
2311 {
2312 /* insert row in the chgrows list (if not already there) */
2313 if( !row->lhschanged && !row->rhschanged )
2314 {
2315 SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2316 lp->chgrows[lp->nchgrows] = row;
2317 lp->nchgrows++;
2318 }
2319
2320 /* mark side change in the row */
2321 switch( sidetype )
2322 {
2323 case SCIP_SIDETYPE_LEFT:
2324 row->lhschanged = TRUE;
2325 break;
2326 case SCIP_SIDETYPE_RIGHT:
2327 row->rhschanged = TRUE;
2328 break;
2329 default:
2330 SCIPerrorMessage("unknown row side type\n");
2331 SCIPABORT();
2332 return SCIP_INVALIDDATA; /*lint !e527*/
2333 }
2334
2335 /* mark the current LP unflushed */
2336 lp->flushed = FALSE;
2337
2338 assert(lp->nchgrows > 0);
2339 }
2340
2341 return SCIP_OKAY;
2342 }
2343
2344
2345
2346
2347 /*
2348 * double linked coefficient matrix methods
2349 */
2350
2351 /** insert column coefficients in corresponding rows */
2352 SCIP_RETCODE colLink(
2353 SCIP_COL* col, /**< column data */
2354 BMS_BLKMEM* blkmem, /**< block memory */
2355 SCIP_SET* set, /**< global SCIP settings */
2356 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2357 SCIP_LP* lp /**< current LP data */
2358 )
2359 {
2360 int i;
2361
2362 assert(col != NULL);
2363 assert(col->var != NULL);
2364 assert(blkmem != NULL);
2365 assert(set != NULL);
2366 assert(lp != NULL);
2367
2368 if( col->nunlinked > 0 )
2369 {
2370 SCIPsetDebugMsg(set, "linking column <%s>\n", SCIPvarGetName(col->var));
2371
2372 /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2373 for( i = col->nlprows; i < col->len; ++i )
2374 {
2375 assert(!SCIPsetIsZero(set, col->vals[i]));
2376 if( col->linkpos[i] == -1 )
2377 {
2378 /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2379 SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2380 }
2381 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2382 assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2383 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2384 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2385 }
2386 }
2387 assert(col->nunlinked == 0);
2388
2389 checkLinks(lp);
2390
2391 return SCIP_OKAY;
2392 }
2393
2394 /** removes column coefficients from corresponding rows */
2395 SCIP_RETCODE colUnlink(
2396 SCIP_COL* col, /**< column data */
2397 BMS_BLKMEM* blkmem, /**< block memory */
2398 SCIP_SET* set, /**< global SCIP settings */
2399 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2400 SCIP_LP* lp /**< current LP data */
2401 )
2402 {
2403 int i;
2404
2405 assert(col != NULL);
2406 assert(col->var != NULL);
2407 assert(blkmem != NULL);
2408 assert(set != NULL);
2409 assert(lp != NULL);
2410
2411 if( col->nunlinked < col->len )
2412 {
2413 SCIPsetDebugMsg(set, "unlinking column <%s>\n", SCIPvarGetName(col->var));
2414 for( i = 0; i < col->len; ++i )
2415 {
2416 if( col->linkpos[i] >= 0 )
2417 {
2418 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2419 SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2420 col->linkpos[i] = -1;
2421 col->nunlinked++;
2422 }
2423 }
2424 }
2425 assert(col->nunlinked == col->len);
2426
2427 checkLinks(lp);
2428
2429 return SCIP_OKAY;
2430 }
2431
2432 /** insert row coefficients in corresponding columns */
2433 SCIP_RETCODE rowLink(
2434 SCIP_ROW* row, /**< row data */
2435 BMS_BLKMEM* blkmem, /**< block memory */
2436 SCIP_SET* set, /**< global SCIP settings */
2437 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2438 SCIP_LP* lp /**< current LP data */
2439 )
2440 {
2441 int i;
2442
2443 assert(row != NULL);
2444 assert(blkmem != NULL);
2445 assert(set != NULL);
2446 assert(lp != NULL);
2447
2448 if( row->nunlinked > 0 )
2449 {
2450 SCIPsetDebugMsg(set, "linking row <%s>\n", row->name);
2451
2452 /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2453 for( i = row->nlpcols; i < row->len; ++i )
2454 {
2455 assert(!SCIPsetIsZero(set, row->vals[i]));
2456 if( row->linkpos[i] == -1 )
2457 {
2458 /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2459 SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2460 }
2461 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2462 assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2463 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2464 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2465 }
2466 }
2467 assert(row->nunlinked == 0);
2468
2469 checkLinks(lp);
2470
2471 return SCIP_OKAY;
2472 }
2473
2474 /** removes row coefficients from corresponding columns */
2475 SCIP_RETCODE rowUnlink(
2476 SCIP_ROW* row, /**< row data */
2477 SCIP_SET* set, /**< global SCIP settings */
2478 SCIP_LP* lp /**< current LP data */
2479 )
2480 {
2481 int i;
2482
2483 assert(row != NULL);
2484 assert(set != NULL);
2485 assert(lp != NULL);
2486
2487 if( row->nunlinked < row->len )
2488 {
2489 SCIPsetDebugMsg(set, "unlinking row <%s>\n", row->name);
2490 for( i = 0; i < row->len; ++i )
2491 {
2492 if( row->linkpos[i] >= 0 )
2493 {
2494 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2495 SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2496 row->nunlinked++;
2497 }
2498 }
2499 }
2500 assert(row->nunlinked == row->len);
2501
2502 return SCIP_OKAY;
2503 }
2504
2505
2506
2507
2508 /*
2509 * local LP parameter methods
2510 */
2511
2512 /** sets parameter of type int in LP solver, ignoring unknown parameters */
2513 static
2514 SCIP_RETCODE lpSetIntpar(
2515 SCIP_LP* lp, /**< current LP data */
2516 SCIP_LPPARAM lpparam, /**< LP parameter */
2517 int value, /**< value to set parameter to */
2518 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2519 )
2520 {
2521 SCIP_RETCODE retcode;
2522
2523 assert(lp != NULL);
2524 assert(success != NULL);
2525
2526 retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2527
2528 /* check, if parameter is unknown */
2529 if( retcode == SCIP_PARAMETERUNKNOWN )
2530 {
2531 *success = FALSE;
2532 return SCIP_OKAY;
2533 }
2534 *success = TRUE;
2535
2536 return retcode;
2537 }
2538
2539 /** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2540 static
2541 SCIP_RETCODE lpSetBoolpar(
2542 SCIP_LP* lp, /**< current LP data */
2543 SCIP_LPPARAM lpparam, /**< LP parameter */
2544 SCIP_Bool value, /**< value to set parameter to */
2545 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2546 )
2547 {
2548 return lpSetIntpar(lp, lpparam, (int)value, success);
2549 }
2550
2551 /** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2552 static
2553 SCIP_RETCODE lpSetRealpar(
2554 SCIP_LP* lp, /**< current LP data */
2555 SCIP_LPPARAM lpparam, /**< LP parameter */
2556 SCIP_Real value, /**< value to set parameter to */
2557 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2558 )
2559 {
2560 SCIP_RETCODE retcode;
2561
2562 assert(lp != NULL);
2563 assert(success != NULL);
2564
2565 retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2566
2567 /* check, if parameter is unknown */
2568 if( retcode == SCIP_PARAMETERUNKNOWN )
2569 {
2570 *success = FALSE;
2571 return SCIP_OKAY;
2572 }
2573 *success = TRUE;
2574
2575 return retcode;
2576 }
2577
2578 #ifndef NDEBUG
2579 /** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2580 static
2581 SCIP_RETCODE lpCheckIntpar(
2582 SCIP_LP* lp, /**< current LP data */
2583 SCIP_LPPARAM lpparam, /**< LP parameter */
2584 int value /**< value parameter should have */
2585 )
2586 {
2587 SCIP_RETCODE retcode;
2588 int lpivalue;
2589
2590 assert(lp != NULL);
2591
2592 retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2593
2594 /* ignore unknown parameter error */
2595 if( retcode == SCIP_PARAMETERUNKNOWN )
2596 return SCIP_OKAY;
2597
2598 /* check value */
2599 assert(lpivalue == value);
2600
2601 return retcode;
2602 }
2603
2604 /** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2605 static
2606 SCIP_RETCODE lpCheckBoolpar(
2607 SCIP_LP* lp, /**< current LP data */
2608 SCIP_LPPARAM lpparam, /**< LP parameter */
2609 SCIP_Bool value /**< value parameter should have */
2610 )
2611 {
2612 return lpCheckIntpar(lp, lpparam, (int)value);
2613 }
2614
2615 /** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2616 static
2617 SCIP_RETCODE lpCheckRealpar(
2618 SCIP_LP* lp, /**< current LP data */
2619 SCIP_LPPARAM lpparam, /**< LP parameter */
2620 SCIP_Real value /**< value parameter should have */
2621 )
2622 {
2623 SCIP_RETCODE retcode;
2624 SCIP_Real lpivalue;
2625
2626 assert(lp != NULL);
2627
2628 retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2629
2630 /* ignore unknown parameter error */
2631 if( retcode == SCIP_PARAMETERUNKNOWN )
2632 return SCIP_OKAY;
2633
2634 /* check value */
2635 assert(lpivalue == value); /*lint !e777*/
2636
2637 return retcode;
2638 }
2639 #else
2640 #define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2641 #define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2642 #define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2643 #endif
2644
2645 /** should the objective limit of the LP solver be disabled */
2646 #define lpCutoffDisabled(set,prob) (set->lp_disablecutoff == 1 || ((set->nactivepricers > 0 || !SCIPprobAllColsInLP(prob, set, lp)) && set->lp_disablecutoff == 2))
2647
2648 /** sets the objective limit of the LP solver
2649 *
2650 * Note that we are always minimizing.
2651 */
2652 static
2653 SCIP_RETCODE lpSetObjlim(
2654 SCIP_LP* lp, /**< current LP data */
2655 SCIP_SET* set, /**< global SCIP settings */
2656 SCIP_PROB* prob, /**< problem data */
2657 SCIP_Real objlim, /**< new objective limit */
2658 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2659 )
2660 {
2661 assert(lp != NULL);
2662 assert(set != NULL);
2663 assert(success != NULL);
2664
2665 *success = FALSE;
2666
2667 /* We disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP
2668 * solver's objective limit handling, so we make sure that the objective limit is inactive (infinity). */
2669 if( lpCutoffDisabled(set, prob) || set->misc_exactsolve )
2670 objlim = SCIPlpiInfinity(lp->lpi);
2671
2672 /* convert SCIP infinity value to lp-solver infinity value if necessary */
2673 if( SCIPsetIsInfinity(set, objlim) )
2674 objlim = SCIPlpiInfinity(lp->lpi);
2675
2676 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_OBJLIM, lp->lpiobjlim) );
2677
2678 if( objlim != lp->lpiobjlim ) /*lint !e777*/
2679 {
2680 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) );
2681 if( *success )
2682 {
2683 SCIP_Real actualobjlim;
2684
2685 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2686 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) );
2687 if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/
2688 {
2689 /* mark the current solution invalid */
2690 lp->solved = FALSE;
2691 lp->primalfeasible = FALSE;
2692 lp->primalchecked = FALSE;
2693 lp->lpobjval = SCIP_INVALID;
2694 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2695 }
2696 lp->lpiobjlim = actualobjlim;
2697 }
2698 }
2699
2700 return SCIP_OKAY;
2701 }
2702
2703 /** sets the feasibility tolerance of the LP solver */
2704 static
2705 SCIP_RETCODE lpSetFeastol(
2706 SCIP_LP* lp, /**< current LP data */
2707 SCIP_Real feastol, /**< new feasibility tolerance */
2708 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2709 )
2710 {
2711 assert(lp != NULL);
2712 assert(feastol >= 0.0);
2713 assert(success != NULL);
2714
2715 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_FEASTOL, lp->lpifeastol) );
2716
2717 if( feastol != lp->lpifeastol ) /*lint !e777*/
2718 {
2719 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2720 if( *success )
2721 {
2722 SCIP_Real actualfeastol;
2723
2724 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2725 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) );
2726 if( lp->nrows > 0 && actualfeastol < lp->lpifeastol )
2727 {
2728 /* mark the current solution invalid */
2729 lp->solved = FALSE;
2730 lp->primalfeasible = FALSE;
2731 lp->primalchecked = FALSE;
2732 lp->lpobjval = SCIP_INVALID;
2733 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2734 }
2735 else
2736 *success = FALSE;
2737 lp->lpifeastol = actualfeastol;
2738 }
2739 }
2740 else
2741 *success = FALSE;
2742
2743 return SCIP_OKAY;
2744 }
2745
2746 /** sets the reduced costs feasibility tolerance of the LP solver */
2747 static
2748 SCIP_RETCODE lpSetDualfeastol(
2749 SCIP_LP* lp, /**< current LP data */
2750 SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2751 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2752 )
2753 {
2754 assert(lp != NULL);
2755 assert(dualfeastol >= 0.0);
2756 assert(success != NULL);
2757
2758 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_DUALFEASTOL, lp->lpidualfeastol) );
2759
2760 if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2761 {
2762 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2763 if( *success )
2764 {
2765 SCIP_Real actualdualfeastol;
2766
2767 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2768 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) );
2769 if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol )
2770 {
2771 /* mark the current solution invalid */
2772 lp->solved = FALSE;
2773 lp->dualfeasible = FALSE;
2774 lp->dualchecked = FALSE;
2775 lp->lpobjval = SCIP_INVALID;
2776 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2777 }
2778 else
2779 *success = FALSE;
2780 lp->lpidualfeastol = actualdualfeastol;
2781 }
2782 }
2783 else
2784 *success = FALSE;
2785
2786 return SCIP_OKAY;
2787 }
2788
2789 /** sets the convergence tolerance used in barrier algorithm of the LP solver */
2790 static
2791 SCIP_RETCODE lpSetBarrierconvtol(
2792 SCIP_LP* lp, /**< current LP data */
2793 SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2794 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2795 )
2796 {
2797 assert(lp != NULL);
2798 assert(barrierconvtol >= 0.0);
2799 assert(success != NULL);
2800
2801 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, lp->lpibarrierconvtol) );
2802
2803 if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2804 {
2805 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2806 if( *success )
2807 {
2808 SCIP_Real actualbarrierconvtol;
2809
2810 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2811 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) );
2812 if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol
2813 && (lp->lastlpalgo == SCIP_LPALGO_BARRIER || lp->lastlpalgo == SCIP_LPALGO_BARRIERCROSSOVER) )
2814 {
2815 /* mark the current solution invalid */
2816 lp->solved = FALSE;
2817 lp->dualfeasible = FALSE;
2818 lp->dualchecked = FALSE;
2819 lp->lpobjval = SCIP_INVALID;
2820 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2821 }
2822 else
2823 *success = FALSE;
2824 lp->lpibarrierconvtol = actualbarrierconvtol;
2825 }
2826 }
2827 else
2828 *success = FALSE;
2829
2830 return SCIP_OKAY;
2831 }
2832
2833 /** sets the FROMSCRATCH setting of the LP solver */
2834 static
2835 SCIP_RETCODE lpSetFromscratch(
2836 SCIP_LP* lp, /**< current LP data */
2837 SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2838 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2839 )
2840 {
2841 assert(lp != NULL);
2842 assert(success != NULL);
2843
2844 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, lp->lpifromscratch) );
2845
2846 if( fromscratch != lp->lpifromscratch )
2847 {
2848 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2849 if( *success )
2850 lp->lpifromscratch = fromscratch;
2851 }
2852 else
2853 *success = FALSE;
2854
2855 return SCIP_OKAY;
2856 }
2857
2858 /** sets the FASTMIP setting of the LP solver */
2859 static
2860 SCIP_RETCODE lpSetFastmip(
2861 SCIP_LP* lp, /**< current LP data */
2862 int fastmip, /**< new FASTMIP setting */
2863 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2864 )
2865 {
2866 assert(lp != NULL);
2867 assert(success != NULL);
2868 assert(0 <= fastmip && fastmip <= 1);
2869
2870 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_FASTMIP, lp->lpifastmip) );
2871
2872 if( fastmip != lp->lpifastmip )
2873 {
2874 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2875 if( *success )
2876 {
2877 lp->lpifastmip = fastmip;
2878 lp->solved = FALSE;
2879 /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more
2880 * demanding setting; however, in the current code, this should have not effect. */
2881 }
2882 }
2883 else
2884 *success = FALSE;
2885
2886 return SCIP_OKAY;
2887 }
2888
2889 /** sets the SCALING setting of the LP solver */
2890 static
2891 SCIP_RETCODE lpSetScaling(
2892 SCIP_LP* lp, /**< current LP data */
2893 int scaling, /**< new SCALING setting */
2894 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2895 )
2896 {
2897 assert(lp != NULL);
2898 assert(success != NULL);
2899
2900 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_SCALING, lp->lpiscaling) );
2901
2902 if( scaling != lp->lpiscaling )
2903 {
2904 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2905 if( *success )
2906 lp->lpiscaling = scaling;
2907 }
2908 else
2909 *success = FALSE;
2910
2911 return SCIP_OKAY;
2912 }
2913
2914 /** sets the number of THREADS of the LP solver */
2915 static
2916 SCIP_RETCODE lpSetThreads(
2917 SCIP_LP* lp, /**< current LP data */
2918 int threads, /**< new number of threads used to solve the LP */
2919 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2920 )
2921 {
2922 assert(lp != NULL);
2923 assert(success != NULL);
2924
2925 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_THREADS, lp->lpithreads) );
2926
2927 if( threads != lp->lpithreads )
2928 {
2929 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2930 if( *success )
2931 lp->lpithreads = threads;
2932 }
2933 else
2934 *success = FALSE;
2935
2936 return SCIP_OKAY;
2937 }
2938
2939 /** sets the PRESOLVING setting of the LP solver */
2940 static
2941 SCIP_RETCODE lpSetPresolving(
2942 SCIP_LP* lp, /**< current LP data */
2943 SCIP_Bool presolving, /**< new PRESOLVING setting */
2944 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2945 )
2946 {
2947 assert(lp != NULL);
2948 assert(success != NULL);
2949
2950 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_PRESOLVING, lp->lpipresolving) );
2951
2952 if( presolving != lp->lpipresolving )
2953 {
2954 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2955 if( *success )
2956 lp->lpipresolving = presolving;
2957 }
2958 else
2959 *success = FALSE;
2960
2961 return SCIP_OKAY;
2962 }
2963
2964 /** sets the ROWREPSWITCH setting of the LP solver */
2965 static
2966 SCIP_RETCODE lpSetRowrepswitch(
2967 SCIP_LP* lp, /**< current LP data */
2968 SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2969 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2970 )
2971 {
2972 assert(lp != NULL);
2973 assert(success != NULL);
2974
2975 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, lp->lpirowrepswitch) );
2976
2977 if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2978 {
2979 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2980 if( *success )
2981 lp->lpirowrepswitch = rowrepswitch;
2982 }
2983 else
2984 *success = FALSE;
2985
2986 return SCIP_OKAY;
2987 }
2988
2989 /** sets the iteration limit of the LP solver */
2990 static
2991 SCIP_RETCODE lpSetIterationLimit(
2992 SCIP_LP* lp, /**< current LP data */
2993 int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2994 )
2995 {
2996 SCIP_Bool success;
2997
2998 assert(lp != NULL);
2999 assert(itlim >= -1);
3000
3001 if( itlim == -1 )
3002 itlim = INT_MAX;
3003
3004 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_LPITLIM, lp->lpiitlim) );
3005
3006 if( itlim != lp->lpiitlim )
3007 {
3008 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
3009 if( success )
3010 {
3011 if( itlim > lp->lpiitlim )
3012 {
3013 /* mark the current solution invalid */
3014 lp->solved = FALSE;
3015 lp->lpobjval = SCIP_INVALID;
3016 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
3017 }
3018 lp->lpiitlim = itlim;
3019 }
3020 }
3021
3022 return SCIP_OKAY;
3023 }
3024
3025 /** sets the pricing strategy of the LP solver */
3026 static
3027 SCIP_RETCODE lpSetPricing(
3028 SCIP_LP* lp, /**< current LP data */
3029 SCIP_PRICING pricing /**< pricing strategy */
3030 )
3031 {
3032 SCIP_Bool success;
3033
3034 assert(lp != NULL);
3035
3036 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_PRICING, (int)lp->lpipricing) );
3037
3038 if( pricing != lp->lpipricing )
3039 {
3040 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
3041 if( success )
3042 lp->lpipricing = pricing;
3043 }
3044
3045 return SCIP_OKAY;
3046 }
3047
3048 /** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
3049 static
3050 SCIP_RETCODE lpSetPricingChar(
3051 SCIP_LP* lp, /**< current LP data */
3052 char pricingchar /**< character representing the pricing strategy */
3053 )
3054 {
3055 SCIP_PRICING pricing;
3056
3057 switch( pricingchar )
3058 {
3059 case 'l':
3060 pricing = SCIP_PRICING_LPIDEFAULT;
3061 break;
3062 case 'a':
3063 pricing = SCIP_PRICING_AUTO;
3064 break;
3065 case 'f':
3066 pricing = SCIP_PRICING_FULL;
3067 break;
3068 case 'p':
3069 pricing = SCIP_PRICING_PARTIAL;
3070 break;
3071 case 's':
3072 pricing = SCIP_PRICING_STEEP;
3073 break;
3074 case 'q':
3075 pricing = SCIP_PRICING_STEEPQSTART;
3076 break;
3077 case 'd':
3078 pricing = SCIP_PRICING_DEVEX;
3079 break;
3080 default:
3081 SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
3082 return SCIP_INVALIDDATA;
3083 }
3084
3085 SCIP_CALL( lpSetPricing(lp, pricing) );
3086
3087 return SCIP_OKAY;
3088 }
3089
3090 /** sets the verbosity of the LP solver */
3091 static
3092 SCIP_RETCODE lpSetLPInfo(
3093 SCIP_LP* lp, /**< current LP data */
3094 SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3095 )
3096 {
3097 SCIP_Bool success;
3098
3099 assert(lp != NULL);
3100
3101 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_LPINFO, lp->lpilpinfo) );
3102
3103 if( lpinfo != lp->lpilpinfo )
3104 {
3105 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3106 if( success )
3107 lp->lpilpinfo = lpinfo;
3108 }
3109
3110 return SCIP_OKAY;
3111 }
3112
3113 /** sets the CONDITIONLIMIT setting of the LP solver */
3114 static
3115 SCIP_RETCODE lpSetConditionLimit(
3116 SCIP_LP* lp, /**< current LP data */
3117 SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3118 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3119 )
3120 {
3121 assert(lp != NULL);
3122 assert(success != NULL);
3123
3124 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, lp->lpiconditionlimit) );
3125
3126 if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3127 {
3128 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3129 if( *success )
3130 lp->lpiconditionlimit = condlimit;
3131 }
3132 else
3133 *success = FALSE;
3134
3135 return SCIP_OKAY;
3136 }
3137
3138 /** sets the MARKOWITZ setting of the LP solver */
3139 static
3140 SCIP_RETCODE lpSetMarkowitz(
3141 SCIP_LP* lp, /**< current LP data */
3142 SCIP_Real threshhold, /**< new MARKOWITZ value */
3143 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3144 )
3145 {
3146 assert(lp != NULL);
3147 assert(success != NULL);
3148
3149 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_MARKOWITZ, lp->lpimarkowitz) );
3150
3151 if( threshhold != lp->lpimarkowitz ) /*lint !e777*/
3152 {
3153 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) );
3154 if( *success )
3155 lp->lpimarkowitz = threshhold;
3156 }
3157 else
3158 *success = FALSE;
3159
3160 return SCIP_OKAY;
3161 }
3162
3163 /** sets the type of timer of the LP solver */
3164 static
3165 SCIP_RETCODE lpSetTiming(
3166 SCIP_LP* lp, /**< current LP data */
3167 SCIP_CLOCKTYPE timing, /**< new timing value */
3168 SCIP_Bool enabled, /**< is timing enabled? */
3169 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3170 )
3171 {
3172 int lptiming;
3173
3174 assert(lp != NULL);
3175 assert(success != NULL);
3176 assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/
3177
3178 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_TIMING, lp->lpitiming) );
3179
3180 if( !enabled )
3181 lptiming = 0;
3182 else
3183 lptiming = (int) timing;
3184
3185 if( lptiming != lp->lpitiming ) /*lint !e777*/
3186 {
3187 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3188 if( *success )
3189 lp->lpitiming = lptiming;
3190 }
3191 else
3192 *success = FALSE;
3193
3194 return SCIP_OKAY;
3195 }
3196
3197 /** sets the initial random seed of the LP solver */
3198 static
3199 SCIP_RETCODE lpSetRandomseed(
3200 SCIP_LP* lp, /**< current LP data */
3201 int randomseed, /**< new initial random seed */
3202 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3203 )
3204 {
3205 assert(lp != NULL);
3206 assert(success != NULL);
3207
3208 /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */
3209
3210 if( randomseed == 0 )
3211 {
3212 lp->lpirandomseed = randomseed;
3213 *success = TRUE;
3214 }
3215 else if( randomseed != lp->lpirandomseed ) /*lint !e777*/
3216 {
3217 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) );
3218 if( *success )
3219 lp->lpirandomseed = randomseed;
3220 }
3221 else
3222 *success = FALSE;
3223
3224 return SCIP_OKAY;
3225 }
3226
3227 /** sets the LP solution polishing method */
3228 static
3229 SCIP_RETCODE lpSetSolutionPolishing(
3230 SCIP_LP* lp, /**< current LP data */
3231 SCIP_Bool polishing, /**< LP solution polishing activated (0: disabled, 1: enabled) */
3232 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3233 )
3234 {
3235 assert(lp != NULL);
3236 assert(success != NULL);
3237
3238 if( polishing != lp->lpisolutionpolishing )
3239 {
3240 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) );
3241 if( *success )
3242 lp->lpisolutionpolishing = polishing;
3243 }
3244 else
3245 *success = FALSE;
3246
3247 return SCIP_OKAY;
3248 }
3249
3250 /** sets the LP refactorization interval */
3251 static
3252 SCIP_RETCODE lpSetRefactorInterval(
3253 SCIP_LP* lp, /**< current LP data */
3254 int refactor, /**< LP refactorization interval (0: automatic) */
3255 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3256 )
3257 {
3258 assert(lp != NULL);
3259 assert(success != NULL);
3260
3261 if( refactor != lp->lpirefactorinterval )
3262 {
3263 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) );
3264 if( *success )
3265 lp->lpirefactorinterval = refactor;
3266 }
3267 else
3268 *success = FALSE;
3269
3270 return SCIP_OKAY;
3271 }
3272
3273
3274 /*
3275 * Column methods
3276 */
3277
3278 /** creates an LP column */
3279 SCIP_RETCODE SCIPcolCreate(
3280 SCIP_COL** col, /**< pointer to column data */
3281 BMS_BLKMEM* blkmem, /**< block memory */
3282 SCIP_SET* set, /**< global SCIP settings */
3283 SCIP_STAT* stat, /**< problem statistics */
3284 SCIP_VAR* var, /**< variable, this column represents */
3285 int len, /**< number of nonzeros in the column */
3286 SCIP_ROW** rows, /**< array with rows of column entries */
3287 SCIP_Real* vals, /**< array with coefficients of column entries */
3288 SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3289 )
3290 {
3291 int i;
3292
3293 assert(col != NULL);
3294 assert(blkmem != NULL);
3295 assert(set != NULL);
3296 assert(stat != NULL);
3297 assert(var != NULL);
3298 assert(len >= 0);
3299 assert(len == 0 || (rows != NULL && vals != NULL));
3300
3301 SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3302
3303 if( len > 0 )
3304 {
3305 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3306 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3307 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3308
3309 for( i = 0; i < len; ++i )
3310 {
3311 assert(rows[i] != NULL);
3312 assert(!SCIPsetIsZero(set, vals[i]));
3313 (*col)->linkpos[i] = -1;
3314 }
3315 }
3316 else
3317 {
3318 (*col)->rows = NULL;
3319 (*col)->vals = NULL;
3320 (*col)->linkpos = NULL;
3321 }
3322
3323 (*col)->var = var;
3324 (*col)->obj = SCIPvarGetObj(var);
3325 (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3326 (*col)->lb = SCIPvarGetLbLocal(var);
3327 (*col)->ub = SCIPvarGetUbLocal(var);
3328 (*col)->flushedobj = 0.0;
3329 (*col)->flushedlb = 0.0;
3330 (*col)->flushedub = 0.0;
3331 (*col)->index = stat->ncolidx;
3332 SCIPstatIncrement(stat, set, ncolidx);
3333 (*col)->size = len;
3334 (*col)->len = len;
3335 (*col)->nlprows = 0;
3336 (*col)->nunlinked = len;
3337 (*col)->lppos = -1;
3338 (*col)->lpipos = -1;
3339 (*col)->lpdepth = -1;
3340 (*col)->primsol = 0.0;
3341 (*col)->redcost = SCIP_INVALID;
3342 (*col)->farkascoef = SCIP_INVALID;
3343 (*col)->minprimsol = (*col)->ub;
3344 (*col)->maxprimsol = (*col)->lb;
3345 (*col)->sbdown = SCIP_INVALID;
3346 (*col)->sbup = SCIP_INVALID;
3347 (*col)->sbsolval = SCIP_INVALID;
3348 (*col)->sblpobjval = SCIP_INVALID;
3349 (*col)->sbnode = -1;
3350 (*col)->validredcostlp = -1;
3351 (*col)->validfarkaslp = -1;
3352 (*col)->validsblp = -1;
3353 (*col)->sbitlim = -1;
3354 (*col)->nsbcalls = 0;
3355 (*col)->age = 0;
3356 (*col)->obsoletenode = -1;
3357 (*col)->var_probindex = SCIPvarGetProbindex(var);
3358 (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3359 (*col)->lprowssorted = TRUE;
3360 (*col)->nonlprowssorted = (len <= 1);
3361 (*col)->objchanged = FALSE;
3362 (*col)->lbchanged = FALSE;
3363 (*col)->ubchanged = FALSE;
3364 (*col)->coefchanged = FALSE;
3365 (*col)->integral = SCIPvarIsIntegral(var);
3366 (*col)->removable = removable;
3367 (*col)->sbdownvalid = FALSE;
3368 (*col)->sbupvalid = FALSE;
3369 (*col)->lazylb = SCIPvarGetLbLazy(var);
3370 (*col)->lazyub = SCIPvarGetUbLazy(var);
3371 (*col)->storedsolvals = NULL;
3372
3373 return SCIP_OKAY;
3374 }
3375
3376 /** frees an LP column */
3377 SCIP_RETCODE SCIPcolFree(
3378 SCIP_COL** col, /**< pointer to LP column */
3379 BMS_BLKMEM* blkmem, /**< block memory */
3380 SCIP_SET* set, /**< global SCIP settings */
3381 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3382 SCIP_LP* lp /**< current LP data */
3383 )
3384 {
3385 assert(blkmem != NULL);
3386 assert(col != NULL);
3387 assert(*col != NULL);
3388 assert((*col)->var != NULL);
3389 assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3390 assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3391 assert((*col)->lppos == -1);
3392 assert((*col)->lpipos == -1);
3393
3394 /* remove column indices from corresponding rows */
3395 SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3396
3397 BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3398 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3399 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3400 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3401 BMSfreeBlockMemory(blkmem, col);
3402
3403 return SCIP_OKAY;
3404 }
3405
3406 /** output column to file stream */
3407 void SCIPcolPrint(
3408 SCIP_COL* col, /**< LP column */
3409 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3410 FILE* file /**< output file (or NULL for standard output) */
3411 )
3412 {
3413 int r;
3414
3415 assert(col != NULL);
3416 assert(col->var != NULL);
3417
3418 /* print bounds */
3419 SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3420
3421 /* print coefficients */
3422 if( col->len == 0 )
3423 SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3424 for( r = 0; r < col->len; ++r )
3425 {
3426 assert(col->rows[r] != NULL);
3427 assert(col->rows[r]->name != NULL);
3428 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3429 }
3430 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3431 }
3432
3433 /** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3434 */
3435 void SCIPcolSort(
3436 SCIP_COL* col /**< column to be sorted */
3437 )
3438 {
3439 /* sort LP rows */
3440 colSortLP(col);
3441
3442 /* sort non-LP rows */
3443 colSortNonLP(col);
3444 }
3445
3446 /** adds a previously non existing coefficient to an LP column */
3447 SCIP_RETCODE SCIPcolAddCoef(
3448 SCIP_COL* col, /**< LP column */
3449 BMS_BLKMEM* blkmem, /**< block memory */
3450 SCIP_SET* set, /**< global SCIP settings */
3451 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3452 SCIP_LP* lp, /**< current LP data */
3453 SCIP_ROW* row, /**< LP row */
3454 SCIP_Real val /**< value of coefficient */
3455 )
3456 {
3457 assert(lp != NULL);
3458 assert(!lp->diving);
3459
3460 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3461
3462 checkLinks(lp);
3463
3464 return SCIP_OKAY;
3465 }
3466
3467 /** deletes existing coefficient from column */
3468 SCIP_RETCODE SCIPcolDelCoef(
3469 SCIP_COL* col, /**< column to be changed */
3470 BMS_BLKMEM* blkmem, /**< block memory */
3471 SCIP_SET* set, /**< global SCIP settings */
3472 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3473 SCIP_LP* lp, /**< current LP data */
3474 SCIP_ROW* row /**< coefficient to be deleted */
3475 )
3476 {
3477 int pos;
3478
3479 assert(col != NULL);
3480 assert(col->var != NULL);
3481 assert(lp != NULL);
3482 assert(!lp->diving);
3483 assert(row != NULL);
3484
3485 /* search the position of the row in the column's row vector */
3486 pos = colSearchCoef(col, row);
3487 if( pos == -1 )
3488 {
3489 SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3490 return SCIP_INVALIDDATA;
3491 }
3492 assert(0 <= pos && pos < col->len);
3493 assert(col->rows[pos] == row);
3494
3495 /* if row knows of the column, remove the column from the row's col vector */
3496 if( col->linkpos[pos] >= 0 )
3497 {
3498 assert(row->cols[col->linkpos[pos]] == col);
3499 assert(row->cols_index[col->linkpos[pos]] == col->index);
3500 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3501 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3502 }
3503
3504 /* delete the row from the column's row vector */
3505 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3506
3507 checkLinks(lp);
3508
3509 return SCIP_OKAY;
3510 }
3511
3512 /** changes or adds a coefficient to an LP column */
3513 SCIP_RETCODE SCIPcolChgCoef(
3514 SCIP_COL* col, /**< LP column */
3515 BMS_BLKMEM* blkmem, /**< block memory */
3516 SCIP_SET* set, /**< global SCIP settings */
3517 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3518 SCIP_LP* lp, /**< current LP data */
3519 SCIP_ROW* row, /**< LP row */
3520 SCIP_Real val /**< value of coefficient */
3521 )
3522 {
3523 int pos;
3524
3525 assert(col != NULL);
3526 assert(lp != NULL);
3527 assert(!lp->diving);
3528 assert(row != NULL);
3529
3530 /* search the position of the row in the column's row vector */
3531 pos = colSearchCoef(col, row);
3532
3533 /* check, if row already exists in the column's row vector */
3534 if( pos == -1 )
3535 {
3536 /* add previously not existing coefficient */
3537 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3538 }
3539 else
3540 {
3541 /* modify already existing coefficient */
3542 assert(0 <= pos && pos < col->len);
3543 assert(col->rows[pos] == row);
3544
3545 /* if row knows of the column, change the corresponding coefficient in the row */
3546 if( col->linkpos[pos] >= 0 )
3547 {
3548 assert(row->cols[col->linkpos[pos]] == col);
3549 assert(row->cols_index[col->linkpos[pos]] == col->index);
3550 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3551 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3552 }
3553
3554 /* change the coefficient in the column */
3555 SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3556 }
3557
3558 checkLinks(lp);
3559
3560 return SCIP_OKAY;
3561 }
3562
3563 /** increases value of an existing or non-existing coefficient in an LP column */
3564 SCIP_RETCODE SCIPcolIncCoef(
3565 SCIP_COL* col, /**< LP column */
3566 BMS_BLKMEM* blkmem, /**< block memory */
3567 SCIP_SET* set, /**< global SCIP settings */
3568 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3569 SCIP_LP* lp, /**< current LP data */
3570 SCIP_ROW* row, /**< LP row */
3571 SCIP_Real incval /**< value to add to the coefficient */
3572 )
3573 {
3574 int pos;
3575
3576 assert(col != NULL);
3577 assert(lp != NULL);
3578 assert(!lp->diving);
3579 assert(row != NULL);
3580
3581 if( SCIPsetIsZero(set, incval) )
3582 return SCIP_OKAY;
3583
3584 /* search the position of the row in the column's row vector */
3585 pos = colSearchCoef(col, row);
3586
3587 /* check, if row already exists in the column's row vector */
3588 if( pos == -1 )
3589 {
3590 /* add previously not existing coefficient */
3591 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3592 }
3593 else
3594 {
3595 /* modify already existing coefficient */
3596 assert(0 <= pos && pos < col->len);
3597 assert(col->rows[pos] == row);
3598
3599 /* if row knows of the column, change the corresponding coefficient in the row */
3600 if( col->linkpos[pos] >= 0 )
3601 {
3602 assert(row->cols[col->linkpos[pos]] == col);
3603 assert(row->cols_index[col->linkpos[pos]] == col->index);
3604 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3605 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3606 }
3607
3608 /* change the coefficient in the column */
3609 SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3610 }
3611
3612 checkLinks(lp);
3613
3614 return SCIP_OKAY;
3615 }
3616
3617 /** insert column in the chgcols list (if not already there) */
3618 static
3619 SCIP_RETCODE insertColChgcols(
3620 SCIP_COL* col, /**< LP column to change */
3621 SCIP_SET* set, /**< global SCIP settings */
3622 SCIP_LP* lp /**< current LP data */
3623 )
3624 {
3625 if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3626 {
3627 SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3628 lp->chgcols[lp->nchgcols] = col;
3629 lp->nchgcols++;
3630 }
3631
3632 /* mark the current LP unflushed */
3633 lp->flushed = FALSE;
3634
3635 return SCIP_OKAY;
3636 }
3637
3638 /** Is the new value reliable or may we have cancellation?
3639 *
3640 * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3641 * cancellations which can occur during increasing the oldvalue to the newvalue
3642 */
3643 static
3644 SCIP_Bool isNewValueUnreliable(
3645 SCIP_SET* set, /**< global SCIP settings */
3646 SCIP_Real newvalue, /**< new value */
3647 SCIP_Real oldvalue /**< old reliable value */
3648 )
3649 {
3650 SCIP_Real quotient;
3651
3652 assert(set != NULL);
3653 assert(oldvalue != SCIP_INVALID); /*lint !e777*/
3654
3655 quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3656
3657 return SCIPsetIsZero(set, quotient);
3658 }
3659
3660 /** update norms of objective function vector */
3661 static
3662 void lpUpdateObjNorms(
3663 SCIP_LP* lp, /**< current LP data */
3664 SCIP_SET* set, /**< global SCIP settings */
3665 SCIP_Real oldobj, /**< old objective value of variable */
3666 SCIP_Real newobj /**< new objective value of variable */
3667 )
3668 {
3669 if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
3670 {
3671 if( !lp->objsqrnormunreliable )
3672 {
3673 SCIP_Real oldvalue;
3674
3675 oldvalue = lp->objsqrnorm;
3676 lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3677
3678 /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3679 if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3680 lp->objsqrnormunreliable = TRUE;
3681 else
3682 {
3683 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3684
3685 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3686 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3687
3688 assert(lp->objsqrnorm >= 0.0);
3689 }
3690 }
3691
3692 lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3693 lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3694 }
3695 }
3696
3697 /** changes objective value of column */
3698 SCIP_RETCODE SCIPcolChgObj(
3699 SCIP_COL* col, /**< LP column to change */
3700 SCIP_SET* set, /**< global SCIP settings */
3701 SCIP_LP* lp, /**< current LP data */
3702 SCIP_Real newobj /**< new objective value */
3703 )
3704 {
3705 assert(col != NULL);
3706 assert(col->var != NULL);
3707 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3708 assert(SCIPvarGetCol(col->var) == col);
3709 assert(lp != NULL);
3710
3711 SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3712
3713 /* only add actual changes */
3714 if( !SCIPsetIsEQ(set, col->obj, newobj) )
3715 {
3716 /* only variables with a real position in the LPI can be inserted */
3717 if( col->lpipos >= 0 )
3718 {
3719 /* insert column in the chgcols list (if not already there) */
3720 SCIP_CALL( insertColChgcols(col, set, lp) );
3721
3722 /* mark objective value change in the column */
3723 col->objchanged = TRUE;
3724
3725 assert(lp->nchgcols > 0);
3726 }
3727 /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3728 * LP and the LP has to be flushed
3729 */
3730 else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3731 || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3732 {
3733 /* mark the LP unflushed */
3734 lp->flushed = FALSE;
3735 }
3736 }
3737
3738 /* store new objective function value */
3739 col->obj = newobj;
3740
3741 /* update original objective value, as long as we are not in diving or probing and changed objective values */
3742 if( !lp->divingobjchg )
3743 {
3744 SCIP_Real oldobj = col->unchangedobj;
3745
3746 assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3747 col->unchangedobj = newobj;
3748
3749 /* update the objective function vector norms */
3750 lpUpdateObjNorms(lp, set, oldobj, newobj);
3751 }
3752
3753 return SCIP_OKAY;
3754 }
3755
3756 /** changes lower bound of column */
3757 SCIP_RETCODE SCIPcolChgLb(
3758 SCIP_COL* col, /**< LP column to change */
3759 SCIP_SET* set, /**< global SCIP settings */
3760 SCIP_LP* lp, /**< current LP data */
3761 SCIP_Real newlb /**< new lower bound value */
3762 )
3763 {
3764 assert(col != NULL);
3765 assert(col->var != NULL);
3766 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3767 assert(SCIPvarGetCol(col->var) == col);
3768 assert(lp != NULL);
3769
3770 SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3771
3772 /* only add actual changes */
3773 if( !SCIPsetIsEQ(set, col->lb, newlb) )
3774 {
3775 /* only variables with a real position in the LPI can be inserted */
3776 if( col->lpipos >= 0 )
3777 {
3778 /* insert column in the chgcols list (if not already there) */
3779 SCIP_CALL( insertColChgcols(col, set, lp) );
3780
3781 /* mark bound change in the column */
3782 col->lbchanged = TRUE;
3783
3784 assert(lp->nchgcols > 0);
3785 }
3786 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3787 * flushed
3788 */
3789 else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3790 {
3791 /* mark the LP unflushed */
3792 lp->flushed = FALSE;
3793 }
3794 }
3795
3796 col->lb = newlb;
3797
3798 return SCIP_OKAY;
3799 }
3800
3801 /** changes upper bound of column */
3802 SCIP_RETCODE SCIPcolChgUb(
3803 SCIP_COL* col, /**< LP column to change */
3804 SCIP_SET* set, /**< global SCIP settings */
3805 SCIP_LP* lp, /**< current LP data */
3806 SCIP_Real newub /**< new upper bound value */
3807 )
3808 {
3809 assert(col != NULL);
3810 assert(col->var != NULL);
3811 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3812 assert(SCIPvarGetCol(col->var) == col);
3813 assert(lp != NULL);
3814
3815 SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3816
3817 /* only add actual changes */
3818 if( !SCIPsetIsEQ(set, col->ub, newub) )
3819 {
3820 /* only variables with a real position in the LPI can be inserted */
3821 if( col->lpipos >= 0 )
3822 {
3823 /* insert column in the chgcols list (if not already there) */
3824 SCIP_CALL( insertColChgcols(col, set, lp) );
3825
3826 /* mark bound change in the column */
3827 col->ubchanged = TRUE;
3828
3829 assert(lp->nchgcols > 0);
3830 }
3831 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3832 * flushed
3833 */
3834 else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3835 {
3836 /* mark the LP unflushed */
3837 lp->flushed = FALSE;
3838 }
3839 }
3840
3841 col->ub = newub;
3842
3843 return SCIP_OKAY;
3844 }
3845
3846 /** calculates the reduced costs of a column using the given dual solution vector */
3847 SCIP_Real SCIPcolCalcRedcost(
3848 SCIP_COL* col, /**< LP column */
3849 SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3850 )
3851 {
3852 SCIP_ROW* row;
3853 SCIP_Real redcost;
3854 int i;
3855
3856 assert(col != NULL);
3857 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3858 assert(SCIPvarGetCol(col->var) == col);
3859 assert(dualsol != NULL);
3860
3861 redcost = col->obj;
3862 for( i = 0; i < col->nlprows; ++i )
3863 {
3864 row = col->rows[i];
3865 assert(row != NULL);
3866 assert(row->lppos >= 0);
3867 redcost -= col->vals[i] * dualsol[row->lppos];
3868 }
3869
3870 if( col->nunlinked > 0 )
3871 {
3872 for( i = col->nlprows; i < col->len; ++i )
3873 {
3874 row = col->rows[i];
3875 assert(row != NULL);
3876 assert(row->lppos == -1 || col->linkpos[i] == -1);
3877 if( row->lppos >= 0 )
3878 redcost -= col->vals[i] * dualsol[row->lppos];
3879 }
3880 }
3881 #ifndef NDEBUG
3882 else
3883 {
3884 for( i = col->nlprows; i < col->len; ++i )
3885 {
3886 row = col->rows[i];
3887 assert(row != NULL);
3888 assert(row->lppos == -1);
3889 assert(col->linkpos[i] >= 0);
3890 }
3891 }
3892 #endif
3893
3894 return redcost;
3895 }
3896
3897 /** calculates the reduced costs of a column using the dual solution stored in the rows */
3898 static
3899 SCIP_Real colCalcInternalRedcost(
3900 SCIP_COL* col /**< LP column */
3901 )
3902 {
3903 SCIP_ROW* row;
3904 SCIP_Real redcost;
3905 int i;
3906
3907 assert(col != NULL);
3908 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3909 assert(SCIPvarGetCol(col->var) == col);
3910
3911 redcost = col->obj;
3912 for( i = 0; i < col->nlprows; ++i )
3913 {
3914 row = col->rows[i];
3915 assert(row != NULL);
3916 assert(row->dualsol != SCIP_INVALID); /*lint !e777*/
3917 assert(row->lppos >= 0);
3918 assert(col->linkpos[i] >= 0);
3919 redcost -= col->vals[i] * row->dualsol;
3920 }
3921
3922 if( col->nunlinked > 0 )
3923 {
3924 for( i = col->nlprows; i < col->len; ++i )
3925 {
3926 row = col->rows[i];
3927 assert(row != NULL);
3928 assert(row->lppos >= 0 || row->dualsol == 0.0);
3929 assert(row->lppos == -1 || col->linkpos[i] == -1);
3930 if( row->lppos >= 0 )
3931 redcost -= col->vals[i] * row->dualsol;
3932 }
3933 }
3934 #ifndef NDEBUG
3935 else
3936 {
3937 for( i = col->nlprows; i < col->len; ++i )
3938 {
3939 row = col->rows[i];
3940 assert(row != NULL);
3941 assert(row->dualsol == 0.0);
3942 assert(row->lppos == -1);
3943 assert(col->linkpos[i] >= 0);
3944 }
3945 }
3946 #endif
3947
3948 return redcost;
3949 }
3950
3951 /** gets the reduced costs of a column in last LP or after recalculation */
3952 SCIP_Real SCIPcolGetRedcost(
3953 SCIP_COL* col, /**< LP column */
3954 SCIP_STAT* stat, /**< problem statistics */
3955 SCIP_LP* lp /**< current LP data */
3956 )
3957 {
3958 assert(col != NULL);
3959 assert(stat != NULL);
3960 assert(lp != NULL);
3961 assert(col->validredcostlp <= stat->lpcount);
3962 assert(lp->validsollp == stat->lpcount);
3963
3964 if( col->validredcostlp < stat->lpcount )
3965 {
3966 col->redcost = colCalcInternalRedcost(col);
3967 col->validredcostlp = stat->lpcount;
3968 }
3969 assert(col->validredcostlp == stat->lpcount);
3970 assert(col->redcost != SCIP_INVALID); /*lint !e777*/
3971
3972 return col->redcost;
3973 }
3974
3975 /** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3976 SCIP_Real SCIPcolGetFeasibility(
3977 SCIP_COL* col, /**< LP column */
3978 SCIP_SET* set, /**< global SCIP settings */
3979 SCIP_STAT* stat, /**< problem statistics */
3980 SCIP_LP* lp /**< current LP data */
3981 )
3982 {
3983 assert(col != NULL);
3984 assert(set != NULL);
3985 assert(stat != NULL);
3986 assert(lp != NULL);
3987 assert(lp->validsollp == stat->lpcount);
3988
3989 /* A column's reduced cost is defined as
3990 * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3991 * The activity is equal to the activity of the corresponding row in the dual LP.
3992 * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3993 * The sides of the dual row depend on the bounds of the column:
3994 * - lb == ub : dual row is a free row with infinite sides
3995 * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3996 * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3997 * - lb < ub <= 0: obj <= activity => redcost <= 0
3998 */
3999 if( SCIPsetIsEQ(set, col->lb, col->ub) )
4000 {
4001 /* dual row is free */
4002 return SCIPsetInfinity(set);
4003 }
4004 else
4005 {
4006 SCIP_Real redcost;
4007
4008 /* calculate reduced costs */
4009 redcost = SCIPcolGetRedcost(col, stat, lp);
4010
4011 if( !SCIPsetIsNegative(set, col->lb) )
4012 {
4013 /* dual row is activity <= obj <=> redcost >= 0 */
4014 return redcost;
4015 }
4016 else if( SCIPsetIsPositive(set, col->ub) )
4017 {
4018 /* dual row is activity == obj <=> redcost == 0 */
4019 return -REALABS(redcost);
4020 }
4021 else
4022 {
4023 /* dual row is activity >= obj <=> redcost <= 0 */
4024 return -redcost;
4025 }
4026 }
4027 }
4028
4029 /** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
4030 SCIP_Real SCIPcolCalcFarkasCoef(
4031 SCIP_COL* col, /**< LP column */
4032 SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
4033 )
4034 {
4035 SCIP_ROW* row;
4036 SCIP_Real farkas;
4037 int i;
4038
4039 assert(col != NULL);
4040 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4041 assert(SCIPvarGetCol(col->var) == col);
4042 assert(dualfarkas != NULL);
4043
4044 farkas = 0.0;
4045 for( i = 0; i < col->nlprows; ++i )
4046 {
4047 row = col->rows[i];
4048 assert(row != NULL);
4049 assert(row->lppos >= 0);
4050 farkas += col->vals[i] * dualfarkas[row->lppos];
4051 }
4052
4053 if( col->nunlinked > 0 )
4054 {
4055 for( i = col->nlprows; i < col->len; ++i )
4056 {
4057 row = col->rows[i];
4058 assert(row != NULL);
4059 assert(row->lppos == -1 || col->linkpos[i] == -1);
4060 if( row->lppos >= 0 )
4061 farkas += col->vals[i] * dualfarkas[row->lppos];
4062 }
4063 }
4064 #ifndef NDEBUG
4065 else
4066 {
4067 for( i = col->nlprows; i < col->len; ++i )
4068 {
4069 row = col->rows[i];
4070 assert(row != NULL);
4071 assert(row->lppos == -1);
4072 assert(col->linkpos[i] >= 0);
4073 }
4074 }
4075 #endif
4076
4077 return farkas;
4078 }
4079
4080 /** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
4081 static
4082 SCIP_Real colCalcInternalFarkasCoef(
4083 SCIP_COL* col /**< LP column */
4084 )
4085 {
4086 SCIP_ROW* row;
4087 SCIP_Real farkas;
4088 int i;
4089
4090 assert(col != NULL);
4091 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4092 assert(SCIPvarGetCol(col->var) == col);
4093
4094 farkas = 0.0;
4095 for( i = 0; i < col->nlprows; ++i )
4096 {
4097 row = col->rows[i];
4098 assert(row != NULL);
4099 assert(row->dualfarkas != SCIP_INVALID); /*lint !e777*/
4100 assert(row->lppos >= 0);
4101 assert(col->linkpos[i] >= 0);
4102 farkas += col->vals[i] * row->dualfarkas;
4103 }
4104
4105 if( col->nunlinked > 0 )
4106 {
4107 for( i = col->nlprows; i < col->len; ++i )
4108 {
4109 row = col->rows[i];
4110 assert(row != NULL);
4111 assert(row->lppos >= 0 || row->dualfarkas == 0.0);
4112 assert(row->lppos == -1 || col->linkpos[i] == -1);
4113 if( row->lppos >= 0 )
4114 farkas += col->vals[i] * row->dualfarkas;
4115 }
4116 }
4117 #ifndef NDEBUG
4118 else
4119 {
4120 for( i = col->nlprows; i < col->len; ++i )
4121 {
4122 row = col->rows[i];
4123 assert(row != NULL);
4124 assert(row->dualfarkas == 0.0);
4125 assert(row->lppos == -1);
4126 assert(col->linkpos[i] >= 0);
4127 }
4128 }
4129 #endif
4130
4131 return farkas;
4132 }
4133
4134 /** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
4135 SCIP_Real SCIPcolGetFarkasCoef(
4136 SCIP_COL* col, /**< LP column */
4137 SCIP_STAT* stat, /**< problem statistics */
4138 SCIP_LP* lp /**< current LP data */
4139 )
4140 {
4141 assert(col != NULL);
4142 assert(stat != NULL);
4143 assert(lp != NULL);
4144 assert(col->validfarkaslp <= stat->lpcount);
4145 assert(lp->validfarkaslp == stat->lpcount);
4146
4147 if( col->validfarkaslp < stat->lpcount )
4148 {
4149 col->farkascoef = colCalcInternalFarkasCoef(col);
4150 col->validfarkaslp = stat->lpcount;
4151 }
4152 assert(col->validfarkaslp == stat->lpcount);
4153 assert(col->farkascoef != SCIP_INVALID); /*lint !e777*/
4154
4155 return col->farkascoef;
4156 }
4157
4158 /** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
4159 * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
4160 */
4161 SCIP_Real SCIPcolGetFarkasValue(
4162 SCIP_COL* col, /**< LP column */
4163 SCIP_STAT* stat, /**< problem statistics */
4164 SCIP_LP* lp /**< current LP data */
4165 )
4166 {
4167 SCIP_Real farkascoef;
4168
4169 assert(col != NULL);
4170
4171 farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
4172
4173 if( farkascoef > 0.0 )
4174 return col->ub * farkascoef;
4175 else
4176 return col->lb * farkascoef;
4177 }
4178
4179 /** start strong branching - call before any strong branching */
4180 SCIP_RETCODE SCIPlpStartStrongbranch(
4181 SCIP_LP* lp /**< LP data */
4182 )
4183 {
4184 assert(lp != NULL);
4185 assert(!lp->strongbranching);
4186
4187 lp->strongbranching = TRUE;
4188 SCIPdebugMessage("starting strong branching ...\n");
4189 SCIP_CALL( SCIPlpiStartStrongbranch(lp->lpi) );
4190
4191 return SCIP_OKAY;
4192 }
4193
4194 /** end strong branching - call after any strong branching */
4195 SCIP_RETCODE SCIPlpEndStrongbranch(
4196 SCIP_LP* lp /**< LP data */
4197 )
4198 {
4199 assert(lp != NULL);
4200 assert(lp->strongbranching);
4201
4202 lp->strongbranching = FALSE;
4203 SCIPdebugMessage("ending strong branching ...\n");
4204 SCIP_CALL( SCIPlpiEndStrongbranch(lp->lpi) );
4205
4206 return SCIP_OKAY;
4207 }
4208
4209 /** sets strong branching information for a column variable */
4210 void SCIPcolSetStrongbranchData(
4211 SCIP_COL* col, /**< LP column */
4212 SCIP_SET* set, /**< global SCIP settings */
4213 SCIP_STAT* stat, /**< dynamic problem statistics */
4214 SCIP_LP* lp, /**< LP data */
4215 SCIP_Real lpobjval, /**< objective value of the current LP */
4216 SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4217 SCIP_Real sbdown, /**< dual bound after branching column down */
4218 SCIP_Real sbup, /**< dual bound after branching column up */
4219 SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
4220 SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
4221 SCIP_Longint iter, /**< total number of strong branching iterations */
4222 int itlim /**< iteration limit applied to the strong branching call */
4223 )
4224 {
4225 assert(col != NULL);
4226 assert(col->var != NULL);
4227 assert(SCIPcolIsIntegral(col));
4228 assert(SCIPvarIsIntegral(col->var));
4229 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4230 assert(SCIPvarGetCol(col->var) == col);
4231 assert(col->lpipos >= 0);
4232 assert(col->lppos >= 0);
4233 assert(set != NULL);
4234 assert(stat != NULL);
4235 assert(lp != NULL);
4236 assert(lp->strongbranchprobing);
4237 assert(col->lppos < lp->ncols);
4238 assert(lp->cols[col->lppos] == col);
4239 assert(itlim >= 1);
4240
4241 col->sblpobjval = lpobjval;
4242 col->sbsolval = primsol;
4243 col->validsblp = stat->nlps;
4244 col->sbnode = stat->nnodes;
4245
4246 col->sbitlim = itlim;
4247 col->nsbcalls++;
4248
4249 col->sbdown = MIN(sbdown, lp->cutoffbound);
4250 col->sbup = MIN(sbup, lp->cutoffbound);
4251 col->sbdownvalid = sbdownvalid;
4252 col->sbupvalid = sbupvalid;
4253
4254 SCIPstatIncrement(stat, set, nstrongbranchs);
4255 SCIPstatAdd(stat, set, nsblpiterations, iter);
4256 if( stat->nnodes == 1 )
4257 {
4258 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4259 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4260 }
4261 }
4262
4263 /** invalidates strong branching information for a column variable */
4264 void SCIPcolInvalidateStrongbranchData(
4265 SCIP_COL* col, /**< LP column */
4266 SCIP_SET* set, /**< global SCIP settings */
4267 SCIP_STAT* stat, /**< dynamic problem statistics */
4268 SCIP_LP* lp /**< LP data */
4269 )
4270 {
4271 assert(col != NULL);
4272 assert(col->var != NULL);
4273 assert(SCIPcolIsIntegral(col));
4274 assert(SCIPvarIsIntegral(col->var));
4275 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4276 assert(SCIPvarGetCol(col->var) == col);
4277 assert(col->lpipos >= 0);
4278 assert(col->lppos >= 0);
4279 assert(set != NULL);
4280 assert(stat != NULL);
4281 assert(lp != NULL);
4282 assert(lp->strongbranchprobing);
4283 assert(col->lppos < lp->ncols);
4284 assert(lp->cols[col->lppos] == col);
4285
4286 col->sbdown = SCIP_INVALID;
4287 col->sbup = SCIP_INVALID;
4288 col->sbdownvalid = FALSE;
4289 col->sbupvalid = FALSE;
4290 col->validsblp = -1;
4291 col->sbsolval = SCIP_INVALID;
4292 col->sblpobjval = SCIP_INVALID;
4293 col->sbnode = -1;
4294 col->sbitlim = -1;
4295 }
4296
4297
4298 /** gets strong branching information on a column variable */
4299 SCIP_RETCODE SCIPcolGetStrongbranch(
4300 SCIP_COL* col, /**< LP column */
4301 SCIP_Bool integral, /**< should integral strong branching be performed? */
4302 SCIP_SET* set, /**< global SCIP settings */
4303 SCIP_STAT* stat, /**< dynamic problem statistics */
4304 SCIP_PROB* prob, /**< problem data */
4305 SCIP_LP* lp, /**< LP data */
4306 int itlim, /**< iteration limit for strong branchings */
4307 SCIP_Bool updatecol, /**< should col be updated, or should it stay in its current state ? */
4308 SCIP_Bool updatestat, /**< should stat be updated, or should it stay in its current state ? */
4309 SCIP_Real* down, /**< stores dual bound after branching column down */
4310 SCIP_Real* up, /**< stores dual bound after branching column up */
4311 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4312 * otherwise, it can only be used as an estimate value */
4313 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4314 * otherwise, it can only be used as an estimate value */
4315 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4316 )
4317 {
4318 SCIP_Real sbdown;
4319 SCIP_Real sbup;
4320 SCIP_Bool sbdownvalid;
4321 SCIP_Bool sbupvalid;
4322 SCIP_Longint validsblp;
4323 SCIP_Real sbsolval;
4324 SCIP_Real sblpobjval;
4325 SCIP_Longint sbnode;
4326 int sbitlim;
4327 int nsbcalls;
4328
4329 assert(col != NULL);
4330 assert(col->var != NULL);
4331 assert(SCIPcolIsIntegral(col));
4332 assert(SCIPvarIsIntegral(col->var));
4333 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4334 assert(SCIPvarGetCol(col->var) == col);
4335 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4336 assert(col->lpipos >= 0);
4337 assert(col->lppos >= 0);
4338 assert(set != NULL);
4339 assert(stat != NULL);
4340 assert(lp != NULL);
4341 assert(lp->flushed);
4342 assert(lp->solved);
4343 assert(lp->strongbranching);
4344 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4345 assert(lp->validsollp == stat->lpcount);
4346 assert(col->lppos < lp->ncols);
4347 assert(lp->cols[col->lppos] == col);
4348 assert(itlim >= 1);
4349 /* assert(down != NULL);
4350 * assert(up != NULL); temporary hack for cloud branching
4351 */
4352 assert(lperror != NULL);
4353
4354 *lperror = FALSE;
4355
4356 sbdown = col->sbdown;
4357 sbup = col->sbup;
4358 sbdownvalid = col->sbdownvalid;
4359 sbupvalid = col->sbupvalid;
4360 sbitlim = col->sbitlim;
4361 nsbcalls = col->nsbcalls;
4362
4363 validsblp = stat->nlps;
4364 sbsolval = col->primsol;
4365 sblpobjval = SCIPlpGetObjval(lp, set, prob);
4366 sbnode = stat->nnodes;
4367 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4368
4369 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4370 if( lp->looseobjvalinf > 0 )
4371 {
4372 sbdown = -SCIPsetInfinity(set);
4373 sbup = -SCIPsetInfinity(set);
4374 sbdownvalid = FALSE;
4375 sbupvalid = FALSE;
4376 }
4377 else
4378 {
4379 SCIP_RETCODE retcode;
4380 int iter;
4381
4382 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4383 SCIPvarGetName(col->var), col->primsol, itlim);
4384
4385 /* start timing */
4386 SCIPclockStart(stat->strongbranchtime, set);
4387
4388 /* call LPI strong branching */
4389 sbitlim = itlim;
4390 nsbcalls++;
4391
4392 sbdown = lp->lpobjval;
4393 sbup = lp->lpobjval;
4394
4395 if( integral )
4396 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4397 else
4398 {
4399 assert( ! SCIPsetIsIntegral(set, col->primsol) );
4400 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4401 }
4402
4403 /* check return code for errors */
4404 if( retcode == SCIP_LPERROR )
4405 {
4406 *lperror = TRUE;
4407 sbdown = SCIP_INVALID;
4408 sbup = SCIP_INVALID;
4409 sbdownvalid = FALSE;
4410 sbupvalid = FALSE;
4411 validsblp = -1;
4412 sbsolval = SCIP_INVALID;
4413 sblpobjval = SCIP_INVALID;
4414 sbnode = -1;
4415 }
4416 else
4417 {
4418 SCIP_Real looseobjval;
4419
4420 *lperror = FALSE;
4421 SCIP_CALL( retcode );
4422
4423 looseobjval = getFiniteLooseObjval(lp, set, prob);
4424 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4425 sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4426
4427 /* update strong branching statistics */
4428 if( updatestat )
4429 {
4430 if( iter == -1 )
4431 {
4432 /* calculate average iteration number */
4433 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4434 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4435 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4436 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4437 : 0;
4438 if( iter/2 >= itlim )
4439 iter = 2*itlim;
4440 }
4441 SCIPstatIncrement(stat, set, nstrongbranchs);
4442 SCIPstatAdd(stat, set, nsblpiterations, iter);
4443 if( stat->nnodes == 1 )
4444 {
4445 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4446 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4447 }
4448 }
4449 }
4450
4451 /* stop timing */
4452 SCIPclockStop(stat->strongbranchtime, set);
4453 }
4454 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/
4455 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/
4456
4457 if( down != NULL)
4458 *down = sbdown;
4459 if( up != NULL )
4460 *up = sbup;
4461 if( downvalid != NULL )
4462 *downvalid = sbdownvalid;
4463 if( upvalid != NULL )
4464 *upvalid = sbupvalid;
4465
4466 if( updatecol )
4467 {
4468 col->sbdown = sbdown;
4469 col->sbup = sbup;
4470 col->sbdownvalid = sbdownvalid;
4471 col->sbupvalid = sbupvalid;
4472 col->validsblp = validsblp;
4473 col->sbsolval = sbsolval;
4474 col->sblpobjval = sblpobjval;
4475 col->sbnode = sbnode;
4476 col->sbitlim = sbitlim;
4477 col->nsbcalls = nsbcalls;
4478 }
4479
4480 return SCIP_OKAY;
4481 }
4482
4483 /** gets strong branching information on column variables */
4484 SCIP_RETCODE SCIPcolGetStrongbranches(
4485 SCIP_COL** cols, /**< LP columns */
4486 int ncols, /**< number of columns */
4487 SCIP_Bool integral, /**< should integral strong branching be performed? */
4488 SCIP_SET* set, /**< global SCIP settings */
4489 SCIP_STAT* stat, /**< dynamic problem statistics */
4490 SCIP_PROB* prob, /**< problem data */
4491 SCIP_LP* lp, /**< LP data */
4492 int itlim, /**< iteration limit for strong branchings */
4493 SCIP_Real* down, /**< stores dual bounds after branching columns down */
4494 SCIP_Real* up, /**< stores dual bounds after branching columns up */
4495 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4496 * otherwise, they can only be used as an estimate value */
4497 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4498 * otherwise, they can only be used as an estimate value */
4499 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4500 )
4501 {
4502 SCIP_RETCODE retcode;
4503 SCIP_Real* sbdown;
4504 SCIP_Real* sbup;
4505 SCIP_Bool* sbdownvalid;
4506 SCIP_Bool* sbupvalid;
4507 SCIP_Real* primsols;
4508 SCIP_COL** subcols;
4509 int* lpipos;
4510 int* subidx;
4511 int nsubcols;
4512 int iter;
4513 int j;
4514
4515 assert(cols != NULL);
4516 assert(set != NULL);
4517 assert(stat != NULL);
4518 assert(lp != NULL);
4519 assert(lp->flushed);
4520 assert(lp->solved);
4521 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4522 assert(lp->validsollp == stat->lpcount);
4523 assert(itlim >= 1);
4524 assert(down != NULL);
4525 assert(up != NULL);
4526 assert(lperror != NULL);
4527
4528 *lperror = FALSE;
4529
4530 if ( ncols <= 0 )
4531 return SCIP_OKAY;
4532
4533 /* start timing */
4534 SCIPclockStart(stat->strongbranchtime, set);
4535
4536 /* initialize storage */
4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4541 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4542 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4543 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4544 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4545
4546 nsubcols = 0;
4547 for( j = 0; j < ncols; ++j )
4548 {
4549 SCIP_COL* col;
4550 col = cols[j];
4551
4552 assert(col->lppos < lp->ncols);
4553 assert(lp->cols[col->lppos] == col);
4554 assert(SCIPcolIsIntegral(col));
4555 assert(SCIPvarIsIntegral(col->var));
4556 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4557 assert(SCIPvarGetCol(col->var) == col);
4558 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4559 assert(col->lpipos >= 0);
4560 assert(col->lppos >= 0);
4561
4562 col->validsblp = stat->nlps;
4563 col->sbsolval = col->primsol;
4564 col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4565 col->sbnode = stat->nnodes;
4566 assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4567
4568 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4569 if( lp->looseobjvalinf > 0 )
4570 {
4571 /* directly set up column and result vectors*/
4572 col->sbdown = -SCIPsetInfinity(set);
4573 col->sbup = -SCIPsetInfinity(set);
4574 col->sbdownvalid = FALSE;
4575 col->sbupvalid = FALSE;
4576 down[j] = col->sbdown;
4577 up[j] = col->sbup;
4578 if( downvalid != NULL )
4579 downvalid[j] = col->sbdownvalid;
4580 if( upvalid != NULL )
4581 upvalid[j] = col->sbupvalid;
4582 }
4583 else
4584 {
4585 col->sbitlim = itlim;
4586 col->nsbcalls++;
4587
4588 lpipos[nsubcols] = col->lpipos;
4589 primsols[nsubcols] = col->primsol;
4590 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4591 subidx[nsubcols] = j;
4592 subcols[nsubcols++] = col;
4593 }
4594 }
4595
4596 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4597
4598 /* call LPI strong branching */
4599 if ( integral )
4600 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4601 else
4602 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4603
4604 /* check return code for errors */
4605 if( retcode == SCIP_LPERROR )
4606 {
4607 *lperror = TRUE;
4608
4609 for( j = 0; j < nsubcols; ++j )
4610 {
4611 SCIP_COL* col;
4612 int idx;
4613
4614 col = subcols[j];
4615 idx = subidx[j];
4616
4617 col->sbdown = SCIP_INVALID;
4618 col->sbup = SCIP_INVALID;
4619 col->sbdownvalid = FALSE;
4620 col->sbupvalid = FALSE;
4621 col->validsblp = -1;
4622 col->sbsolval = SCIP_INVALID;
4623 col->sblpobjval = SCIP_INVALID;
4624 col->sbnode = -1;
4625
4626 down[idx] = col->sbdown;
4627 up[idx] = col->sbup;
4628 if( downvalid != NULL )
4629 downvalid[idx] = col->sbdownvalid;
4630 if( upvalid != NULL )
4631 upvalid[idx] = col->sbupvalid;
4632 }
4633 }
4634 else
4635 {
4636 SCIP_Real looseobjval;
4637
4638 *lperror = FALSE;
4639 SCIP_CALL( retcode );
4640
4641 looseobjval = getFiniteLooseObjval(lp, set, prob);
4642
4643 for( j = 0; j < nsubcols; ++j )
4644 {
4645 SCIP_COL* col;
4646 int idx;
4647
4648 col = subcols[j];
4649 idx = subidx[j];
4650
4651 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/
4652 assert( col->sbup != SCIP_INVALID); /*lint !e777*/
4653
4654 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4655 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4656 col->sbdownvalid = sbdownvalid[j];
4657 col->sbupvalid = sbupvalid[j];
4658
4659 down[idx] = col->sbdown;
4660 up[idx] = col->sbup;
4661 if( downvalid != NULL )
4662 downvalid[idx] = col->sbdownvalid;
4663 if( upvalid != NULL )
4664 upvalid[idx] = col->sbupvalid;
4665 }
4666
4667 /* update strong branching statistics */
4668 if( iter == -1 )
4669 {
4670 /* calculate average iteration number */
4671 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4672 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4673 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4674 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4675 : 0;
4676 if( iter/2 >= itlim )
4677 iter = 2*itlim;
4678 }
4679 SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4680 SCIPstatAdd(stat, set, nsblpiterations, iter);
4681 if( stat->nnodes == 1 )
4682 {
4683 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4684 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4685 }
4686 }
4687
4688 SCIPsetFreeBufferArray(set, &sbupvalid);
4689 SCIPsetFreeBufferArray(set, &sbdownvalid);
4690 SCIPsetFreeBufferArray(set, &sbup);
4691 SCIPsetFreeBufferArray(set, &sbdown);
4692 SCIPsetFreeBufferArray(set, &primsols);
4693 SCIPsetFreeBufferArray(set, &lpipos);
4694 SCIPsetFreeBufferArray(set, &subidx);
4695 SCIPsetFreeBufferArray(set, &subcols);
4696
4697 /* stop timing */
4698 SCIPclockStop(stat->strongbranchtime, set);
4699
4700 return SCIP_OKAY;
4701 }
4702
4703 /** gets last strong branching information available for a column variable;
4704 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4705 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4706 */
4707 void SCIPcolGetStrongbranchLast(
4708 SCIP_COL* col, /**< LP column */
4709 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4710 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4711 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4712 * otherwise, it can only be used as an estimate value */
4713 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4714 * otherwise, it can only be used as an estimate value */
4715 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4716 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4717 )
4718 {
4719 assert(col != NULL);
4720
4721 if( down != NULL )
4722 *down = col->sbdown;
4723 if( up != NULL )
4724 *up = col->sbup;
4725 if( downvalid != NULL )
4726 *downvalid = col->sbdownvalid;
4727 if( upvalid != NULL )
4728 *upvalid = col->sbupvalid;
4729 if( solval != NULL )
4730 *solval = col->sbsolval;
4731 if( lpobjval != NULL )
4732 *lpobjval = col->sblpobjval;
4733 }
4734
4735 /** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4736 * the LP where the strong branching on this column was applied;
4737 * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4738 */
4739 SCIP_Longint SCIPcolGetStrongbranchLPAge(
4740 SCIP_COL* col, /**< LP column */
4741 SCIP_STAT* stat /**< dynamic problem statistics */
4742 )
4743 {
4744 assert(col != NULL);
4745 assert(stat != NULL);
4746
4747 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4748 }
4749
4750 /** marks a column to be not removable from the LP in the current node because it became obsolete */
4751 void SCIPcolMarkNotRemovableLocal(
4752 SCIP_COL* col, /**< LP column */
4753 SCIP_STAT* stat /**< problem statistics */
4754 )
4755 {
4756 assert(col != NULL);
4757 assert(stat != NULL);
4758 assert(stat->nnodes > 0);
4759
4760 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4761 col->obsoletenode = stat->nnodes;
4762 }
4763
4764
4765 /*
4766 * Row methods
4767 */
4768
4769 /** calculates row norms and min/maxidx from scratch, and checks for sorting */
4770 static
4771 void rowCalcNorms(
4772 SCIP_ROW* row, /**< LP row */
4773 SCIP_SET* set /**< global SCIP settings */
4774 )
4775 {
4776 int i;
4777
4778 assert(row != NULL);
4779 assert(set != NULL);
4780
4781 row->sqrnorm = 0.0;
4782 row->sumnorm = 0.0;
4783 row->objprod = 0.0;
4784 row->maxval = 0.0;
4785 row->nummaxval = 1;
4786 row->minval = SCIPsetInfinity(set);
4787 row->numminval = 1;
4788 row->minidx = INT_MAX;
4789 row->maxidx = INT_MIN;
4790 row->validminmaxidx = TRUE;
4791 row->lpcolssorted = TRUE;
4792 row->nonlpcolssorted = TRUE;
4793
4794 /* check, if row is sorted
4795 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4796 */
4797 for( i = 0; i < row->nlpcols; ++i )
4798 {
4799 assert(row->cols[i] != NULL);
4800 assert(!SCIPsetIsZero(set, row->vals[i]));
4801 assert(row->cols[i]->lppos >= 0);
4802 assert(row->linkpos[i] >= 0);
4803 assert(row->cols[i]->index == row->cols_index[i]);
4804
4805 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4806 if( i > 0 )
4807 {
4808 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4809 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4810 }
4811 }
4812 for( i = row->nlpcols; i < row->len; ++i )
4813 {
4814 assert(row->cols[i] != NULL);
4815 assert(!SCIPsetIsZero(set, row->vals[i]));
4816 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4817 assert(row->cols[i]->index == row->cols_index[i]);
4818
4819 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4820 if( i > row->nlpcols )
4821 {
4822 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4823 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4824 }
4825 }
4826 }
4827
4828 /** calculates min/maxval and min/maxidx from scratch */
4829 static
4830 void rowCalcIdxsAndVals(
4831 SCIP_ROW* row, /**< LP row */
4832 SCIP_SET* set /**< global SCIP settings */
4833 )
4834 {
4835 SCIP_COL* col;
4836 SCIP_Real absval;
4837 int i;
4838
4839 assert(row != NULL);
4840 assert(set != NULL);
4841
4842 row->maxval = 0.0;
4843 row->nummaxval = 1;
4844 row->numintcols = 0;
4845 row->minval = SCIPsetInfinity(set);
4846 row->numminval = 1;
4847 row->minidx = INT_MAX;
4848 row->maxidx = INT_MIN;
4849 row->validminmaxidx = TRUE;
4850
4851 /* calculate maxval, minval, minidx, and maxidx */
4852 for( i = 0; i < row->len; ++i )
4853 {
4854 col = row->cols[i];
4855 assert(col != NULL);
4856 assert(!SCIPsetIsZero(set, row->vals[i]));
4857
4858 absval = REALABS(row->vals[i]);
4859 assert(!SCIPsetIsZero(set, absval));
4860
4861 /* update min/maxidx */
4862 row->minidx = MIN(row->minidx, col->index);
4863 row->maxidx = MAX(row->maxidx, col->index);
4864 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4865
4866 /* update maximal and minimal non-zero value */
4867 if( row->nummaxval > 0 )
4868 {
4869 if( SCIPsetIsGT(set, absval, row->maxval) )
4870 {
4871 row->maxval = absval;
4872 row->nummaxval = 1;
4873 }
4874 else if( SCIPsetIsGE(set, absval, row->maxval) )
4875 {
4876 /* make sure the maxval is always exactly the same */
4877 row->maxval = MAX(absval, row->maxval);
4878 row->nummaxval++;
4879 }
4880 }
4881 if( row->numminval > 0 )
4882 {
4883 if( SCIPsetIsLT(set, absval, row->minval) )
4884 {
4885 row->minval = absval;
4886 row->numminval = 1;
4887 }
4888 else if( SCIPsetIsLE(set, absval, row->minval) )
4889 {
4890 /* make sure the minval is always exactly the same */
4891 row->minval = MIN(absval, row->minval);
4892 row->numminval++;
4893 }
4894 }
4895 }
4896 }
4897
4898 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4899 static
4900 SCIP_Bool isIntegralScalar(
4901 SCIP_Real val, /**< value that should be scaled to an integral value */
4902 SCIP_Real scalar, /**< scalar that should be tried */
4903 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4904 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4905 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4906 )
4907 {
4908 SCIP_Real sval;
4909 SCIP_Real downval;
4910 SCIP_Real upval;
4911
4912 assert(mindelta <= 0.0);
4913 assert(maxdelta >= 0.0);
4914
4915 sval = val * scalar;
4916 downval = floor(sval);
4917 upval = ceil(sval);
4918
4919 if( SCIPrelDiff(sval, downval) <= maxdelta )
4920 {
4921 if( intval != NULL )
4922 *intval = downval;
4923 return TRUE;
4924 }
4925 else if( SCIPrelDiff(sval, upval) >= mindelta )
4926 {
4927 if( intval != NULL )
4928 *intval = upval;
4929 return TRUE;
4930 }
4931
4932 return FALSE;
4933 }
4934
4935 /** scales row with given factor, and rounds coefficients to integers if close enough;
4936 * the constant is automatically moved to the sides;
4937 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4938 */
4939 static
4940 SCIP_RETCODE rowScale(
4941 SCIP_ROW* row, /**< LP row */
4942 BMS_BLKMEM* blkmem, /**< block memory */
4943 SCIP_SET* set, /**< global SCIP settings */
4944 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4945 SCIP_STAT* stat, /**< problem statistics */
4946 SCIP_LP* lp, /**< current LP data */
4947 SCIP_Real scaleval, /**< value to scale row with */
4948 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4949 * if they are close to integral values? */
4950 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4951 * upto which the integral is used instead of the scaled real coefficient */
4952 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4953 * upto which the integral is used instead of the scaled real coefficient */
4954 )
4955 {
4956 SCIP_COL* col;
4957 SCIP_Real val;
4958 SCIP_Real newval;
4959 SCIP_Real intval;
4960 SCIP_Real mindelta;
4961 SCIP_Real maxdelta;
4962 SCIP_Real lb;
4963 SCIP_Real ub;
4964 SCIP_Bool mindeltainf;
4965 SCIP_Bool maxdeltainf;
4966 int oldlen;
4967 int c;
4968
4969 assert(row != NULL);
4970 assert(row->len == 0 || row->cols != NULL);
4971 assert(row->len == 0 || row->vals != NULL);
4972 assert(SCIPsetIsPositive(set, scaleval));
4973 assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4974 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4975
4976 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4977
4978 mindelta = 0.0;
4979 maxdelta = 0.0;
4980 mindeltainf = FALSE;
4981 maxdeltainf = FALSE;
4982 oldlen = row->len;
4983
4984 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4985 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4986 * this rounding can lead to
4987 */
4988 row->integral = TRUE;
4989
4990 c = 0;
4991 while( c < row->len )
4992 {
4993 col = row->cols[c];
4994 val = row->vals[c];
4995 assert(!SCIPsetIsZero(set, val));
4996
4997 /* get local or global bounds for column, depending on the local or global feasibility of the row */
4998 if( row->local )
4999 {
5000 lb = col->lb;
5001 ub = col->ub;
5002 }
5003 else
5004 {
5005 lb = SCIPvarGetLbGlobal(col->var);
5006 ub = SCIPvarGetUbGlobal(col->var);
5007 }
5008
5009 /* calculate scaled coefficient */
5010 newval = val * scaleval;
5011 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5012 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5013 {
5014 if( !SCIPsetIsEQ(set, intval, newval) )
5015 {
5016 if( intval < newval )
5017 {
5018 mindelta += (intval - newval)*ub;
5019 maxdelta += (intval - newval)*lb;
5020 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5021 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5022 }
5023 else
5024 {
5025 mindelta += (intval - newval)*lb;
5026 maxdelta += (intval - newval)*ub;
5027 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5028 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5029 }
5030 }
5031 newval = intval;
5032 }
5033
5034 if( !SCIPsetIsEQ(set, val, newval) )
5035 {
5036 /* if column knows of the row, change the corresponding coefficient in the column */
5037 if( row->linkpos[c] >= 0 )
5038 {
5039 assert(col->rows[row->linkpos[c]] == row);
5040 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5041 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5042 }
5043
5044 /* change the coefficient in the row, and update the norms and integrality status */
5045 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5046
5047 /* current coefficient has been deleted from the row because it was almost zero */
5048 if( oldlen != row->len )
5049 {
5050 assert(row->len == oldlen - 1);
5051 c--;
5052 oldlen = row->len;
5053 }
5054 }
5055 else
5056 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5057
5058 ++c;
5059 }
5060
5061 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5062 * to not destroy feasibility due to rounding
5063 */
5064 /**@todo ensure that returned cut does not have infinite lhs and rhs */
5065 if( !SCIPsetIsInfinity(set, -row->lhs) )
5066 {
5067 if( mindeltainf )
5068 newval = -SCIPsetInfinity(set);
5069 else
5070 {
5071 newval = (row->lhs - row->constant) * scaleval + mindelta;
5072 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5073 newval = SCIPsetSumCeil(set, newval);
5074 }
5075 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5076 }
5077 if( !SCIPsetIsInfinity(set, row->rhs) )
5078 {
5079 if( maxdeltainf )
5080 newval = SCIPsetInfinity(set);
5081 else
5082 {
5083 newval = (row->rhs - row->constant) * scaleval + maxdelta;
5084 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5085 newval = SCIPsetSumFloor(set, newval);
5086 }
5087 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5088 }
5089
5090 /* clear the row constant */
5091 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5092
5093 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5094 debugRowPrint(set, row);
5095
5096 #ifdef SCIP_DEBUG
5097 /* check integrality status of row */
5098 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5099 {}
5100 assert(row->integral == (c == row->len));
5101 #endif
5102
5103 /* invalid the activity */
5104 row->validactivitylp = -1;
5105
5106 return SCIP_OKAY;
5107 }
5108
5109 /** creates and captures an LP row */
5110 SCIP_RETCODE SCIProwCreate(
5111 SCIP_ROW** row, /**< pointer to LP row data */
5112 BMS_BLKMEM* blkmem, /**< block memory */
5113 SCIP_SET* set, /**< global SCIP settings */
5114 SCIP_STAT* stat, /**< problem statistics */
5115 const char* name, /**< name of row */
5116 int len, /**< number of nonzeros in the row */
5117 SCIP_COL** cols, /**< array with columns of row entries */
5118 SCIP_Real* vals, /**< array with coefficients of row entries */
5119 SCIP_Real lhs, /**< left hand side of row */
5120 SCIP_Real rhs, /**< right hand side of row */
5121 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
5122 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5123 SCIP_Bool local, /**< is row only valid locally? */
5124 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
5125 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
5126 )
5127 {
5128 assert(row != NULL);
5129 assert(blkmem != NULL);
5130 assert(stat != NULL);
5131 assert(len >= 0);
5132 assert(len == 0 || (cols != NULL && vals != NULL));
5133 /* note, that the assert tries to avoid numerical troubles in the LP solver.
5134 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5135 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5136 */
5137 assert(lhs <= rhs);
5138
5139 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5140
5141 (*row)->integral = TRUE;
5142 if( len > 0 )
5143 {
5144 SCIP_VAR* var;
5145 int i;
5146
5147 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5148 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5149 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5150 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5151
5152 for( i = 0; i < len; ++i )
5153 {
5154 assert(cols[i] != NULL);
5155 assert(!SCIPsetIsZero(set, vals[i]));
5156
5157 var = cols[i]->var;
5158 (*row)->cols_index[i] = cols[i]->index;
5159 (*row)->linkpos[i] = -1;
5160 if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5161 {
5162 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5163 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5164 }
5165 else
5166 {
5167 (*row)->integral = FALSE;
5168 }
5169 }
5170 }
5171 else
5172 {
5173 (*row)->cols = NULL;
5174 (*row)->cols_index = NULL;
5175 (*row)->vals = NULL;
5176 (*row)->linkpos = NULL;
5177 }
5178
5179 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5180 (*row)->constant = 0.0;
5181 (*row)->lhs = lhs;
5182 (*row)->rhs = rhs;
5183 (*row)->flushedlhs = -SCIPsetInfinity(set);
5184 (*row)->flushedrhs = SCIPsetInfinity(set);
5185 (*row)->sqrnorm = 0.0;
5186 (*row)->sumnorm = 0.0;
5187 (*row)->objprod = 0.0;
5188 (*row)->maxval = 0.0;
5189 (*row)->minval = SCIPsetInfinity(set);
5190 (*row)->dualsol = 0.0;
5191 (*row)->activity = SCIP_INVALID;
5192 (*row)->dualfarkas = 0.0;
5193 (*row)->pseudoactivity = SCIP_INVALID;
5194 (*row)->minactivity = SCIP_INVALID;
5195 (*row)->maxactivity = SCIP_INVALID;
5196 (*row)->origin = origin;
5197 (*row)->eventfilter = NULL;
5198 (*row)->index = stat->nrowidx;
5199 SCIPstatIncrement(stat, set, nrowidx);
5200 (*row)->size = len;
5201 (*row)->len = len;
5202 (*row)->nlpcols = 0;
5203 (*row)->nunlinked = len;
5204 (*row)->nuses = 0;
5205 (*row)->lppos = -1;
5206 (*row)->lpipos = -1;
5207 (*row)->lpdepth = -1;
5208 (*row)->minidx = INT_MAX;
5209 (*row)->maxidx = INT_MIN;
5210 (*row)->nummaxval = 0;
5211 (*row)->numminval = 0;
5212 (*row)->numintcols = -1;
5213 (*row)->validactivitylp = -1;
5214 (*row)->validpsactivitydomchg = -1;
5215 (*row)->validactivitybdsdomchg = -1;
5216 (*row)->nlpsaftercreation = 0L;
5217 (*row)->activeinlpcounter = 0L;
5218 (*row)->age = 0;
5219 (*row)->rank = 0;
5220 (*row)->obsoletenode = -1;
5221 (*row)->fromcutpool = FALSE;
5222 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5223 (*row)->lpcolssorted = TRUE;
5224 (*row)->nonlpcolssorted = (len <= 1);
5225 (*row)->delaysort = FALSE;
5226 (*row)->validminmaxidx = FALSE;
5227 (*row)->lhschanged = FALSE;
5228 (*row)->rhschanged = FALSE;
5229 (*row)->coefchanged = FALSE;
5230 (*row)->local = local;
5231 (*row)->modifiable = modifiable;
5232 (*row)->nlocks = 0;
5233 (*row)->origintype = origintype; /*lint !e641*/
5234 (*row)->removable = removable;
5235 (*row)->inglobalcutpool = FALSE;
5236 (*row)->storedsolvals = NULL;
5237
5238 /* calculate row norms and min/maxidx, and check if row is sorted */
5239 rowCalcNorms(*row, set);
5240
5241 /* capture the row */
5242 SCIProwCapture(*row);
5243
5244 /* create event filter */
5245 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5246
5247 /* capture origin constraint if available */
5248 if( origintype == SCIP_ROWORIGINTYPE_CONS )
5249 {
5250 SCIP_CONS* cons = (SCIP_CONS*) origin;
5251 assert(cons != NULL);
5252 SCIPconsCapture(cons);
5253 }
5254
5255 return SCIP_OKAY;
5256 } /*lint !e715*/
5257
5258 /** frees an LP row */
5259 SCIP_RETCODE SCIProwFree(
5260 SCIP_ROW** row, /**< pointer to LP row */
5261 BMS_BLKMEM* blkmem, /**< block memory */
5262 SCIP_SET* set, /**< global SCIP settings */
5263 SCIP_LP* lp /**< current LP data */
5264 )
5265 {
5266 assert(blkmem != NULL);
5267 assert(row != NULL);
5268 assert(*row != NULL);
5269 assert((*row)->nuses == 0);
5270 assert((*row)->lppos == -1);
5271 assert((*row)->eventfilter != NULL);
5272
5273 /* release constraint that has been used for creating the row */
5274 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5275 {
5276 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5277 assert(cons != NULL);
5278 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5279 }
5280
5281 /* remove column indices from corresponding rows */
5282 SCIP_CALL( rowUnlink(*row, set, lp) );
5283
5284 /* free event filter */
5285 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5286
5287 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5288 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5289 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5290 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5291 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5292 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5293 BMSfreeBlockMemory(blkmem, row);
5294
5295 return SCIP_OKAY;
5296 }
5297
5298 /** output row to file stream */
5299 void SCIProwPrint(
5300 SCIP_ROW* row, /**< LP row */
5301 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5302 FILE* file /**< output file (or NULL for standard output) */
5303 )
5304 {
5305 int i;
5306
5307 assert(row != NULL);
5308
5309 /* print row name */
5310 if( row->name != NULL && row->name[0] != '\0' )
5311 {
5312 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5313 }
5314
5315 /* print left hand side */
5316 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5317
5318 /* print coefficients */
5319 if( row->len == 0 )
5320 SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5321 for( i = 0; i < row->len; ++i )
5322 {
5323 assert(row->cols[i] != NULL);
5324 assert(row->cols[i]->var != NULL);
5325 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5326 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5327 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5328 }
5329
5330 /* print constant */
5331 if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
5332 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5333
5334 /* print right hand side */
5335 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5336 }
5337
5338 /** increases usage counter of LP row */
5339 void SCIProwCapture(
5340 SCIP_ROW* row /**< LP row */
5341 )
5342 {
5343 assert(row != NULL);
5344 assert(row->nuses >= 0);
5345 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5346
5347 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5348 row->nuses++;
5349 }
5350
5351 /** decreases usage counter of LP row, and frees memory if necessary */
5352 SCIP_RETCODE SCIProwRelease(
5353 SCIP_ROW** row, /**< pointer to LP row */
5354 BMS_BLKMEM* blkmem, /**< block memory */
5355 SCIP_SET* set, /**< global SCIP settings */
5356 SCIP_LP* lp /**< current LP data */
5357 )
5358 {
5359 assert(blkmem != NULL);
5360 assert(row != NULL);
5361 assert(*row != NULL);
5362 assert((*row)->nuses >= 1);
5363 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5364
5365 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5366 (*row)->nuses--;
5367 if( (*row)->nuses == 0 )
5368 {
5369 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5370 }
5371
5372 *row = NULL;
5373
5374 return SCIP_OKAY;
5375 }
5376
5377 /** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5378 void SCIProwLock(
5379 SCIP_ROW* row /**< LP row */
5380 )
5381 {
5382 assert(row != NULL);
5383
5384 /* check, if row is modifiable */
5385 if( !row->modifiable )
5386 {
5387 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5388 row->nlocks++;
5389 }
5390 }
5391
5392 /** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5393 void SCIProwUnlock(
5394 SCIP_ROW* row /**< LP row */
5395 )
5396 {
5397 assert(row != NULL);
5398
5399 /* check, if row is modifiable */
5400 if( !row->modifiable )
5401 {
5402 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5403 assert(row->nlocks > 0);
5404 row->nlocks--;
5405 }
5406 }
5407
5408 /** adds a previously non existing coefficient to an LP row */
5409 SCIP_RETCODE SCIProwAddCoef(
5410 SCIP_ROW* row, /**< LP row */
5411 BMS_BLKMEM* blkmem, /**< block memory */
5412 SCIP_SET* set, /**< global SCIP settings */
5413 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5414 SCIP_LP* lp, /**< current LP data */
5415 SCIP_COL* col, /**< LP column */
5416 SCIP_Real val /**< value of coefficient */
5417 )
5418 {
5419 assert(lp != NULL);
5420 assert(!lp->diving || row->lppos == -1);
5421
5422 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5423
5424 checkLinks(lp);
5425
5426 return SCIP_OKAY;
5427 }
5428
5429 /** deletes coefficient from row */
5430 SCIP_RETCODE SCIProwDelCoef(
5431 SCIP_ROW* row, /**< row to be changed */
5432 BMS_BLKMEM* blkmem, /**< block memory */
5433 SCIP_SET* set, /**< global SCIP settings */
5434 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5435 SCIP_LP* lp, /**< current LP data */
5436 SCIP_COL* col /**< coefficient to be deleted */
5437 )
5438 {
5439 int pos;
5440
5441 assert(row != NULL);
5442 assert(!row->delaysort);
5443 assert(lp != NULL);
5444 assert(!lp->diving || row->lppos == -1);
5445 assert(col != NULL);
5446 assert(col->var != NULL);
5447
5448 /* search the position of the column in the row's col vector */
5449 pos = rowSearchCoef(row, col);
5450 if( pos == -1 )
5451 {
5452 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5453 return SCIP_INVALIDDATA;
5454 }
5455 assert(0 <= pos && pos < row->len);
5456 assert(row->cols[pos] == col);
5457 assert(row->cols_index[pos] == col->index);
5458
5459 /* if column knows of the row, remove the row from the column's row vector */
5460 if( row->linkpos[pos] >= 0 )
5461 {
5462 assert(col->rows[row->linkpos[pos]] == row);
5463 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5464 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5465 }
5466
5467 /* delete the column from the row's col vector */
5468 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5469
5470 checkLinks(lp);
5471
5472 return SCIP_OKAY;
5473 }
5474
5475 /** changes or adds a coefficient to an LP row */
5476 SCIP_RETCODE SCIProwChgCoef(
5477 SCIP_ROW* row, /**< LP row */
5478 BMS_BLKMEM* blkmem, /**< block memory */
5479 SCIP_SET* set, /**< global SCIP settings */
5480 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5481 SCIP_LP* lp, /**< current LP data */
5482 SCIP_COL* col, /**< LP column */
5483 SCIP_Real val /**< value of coefficient */
5484 )
5485 {
5486 int pos;
5487
5488 assert(row != NULL);
5489 assert(!row->delaysort);
5490 assert(lp != NULL);
5491 assert(!lp->diving || row->lppos == -1);
5492 assert(col != NULL);
5493
5494 /* search the position of the column in the row's col vector */
5495 pos = rowSearchCoef(row, col);
5496
5497 /* check, if column already exists in the row's col vector */
5498 if( pos == -1 )
5499 {
5500 /* add previously not existing coefficient */
5501 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5502 }
5503 else
5504 {
5505 /* modify already existing coefficient */
5506 assert(0 <= pos && pos < row->len);
5507 assert(row->cols[pos] == col);
5508 assert(row->cols_index[pos] == col->index);
5509
5510 /* if column knows of the row, change the corresponding coefficient in the column */
5511 if( row->linkpos[pos] >= 0 )
5512 {
5513 assert(col->rows[row->linkpos[pos]] == row);
5514 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5515 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5516 }
5517
5518 /* change the coefficient in the row */
5519 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5520 }
5521
5522 checkLinks(lp);
5523
5524 return SCIP_OKAY;
5525 }
5526
5527 /** increases value of an existing or non-existing coefficient in an LP row */
5528 SCIP_RETCODE SCIProwIncCoef(
5529 SCIP_ROW* row, /**< LP row */
5530 BMS_BLKMEM* blkmem, /**< block memory */
5531 SCIP_SET* set, /**< global SCIP settings */
5532 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5533 SCIP_LP* lp, /**< current LP data */
5534 SCIP_COL* col, /**< LP column */
5535 SCIP_Real incval /**< value to add to the coefficient */
5536 )
5537 {
5538 int pos;
5539
5540 assert(row != NULL);
5541 assert(lp != NULL);
5542 assert(!lp->diving || row->lppos == -1);
5543 assert(col != NULL);
5544
5545 if( SCIPsetIsZero(set, incval) )
5546 return SCIP_OKAY;
5547
5548 /* search the position of the column in the row's col vector */
5549 pos = rowSearchCoef(row, col);
5550
5551 /* check, if column already exists in the row's col vector */
5552 if( pos == -1 )
5553 {
5554 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5555 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5556 }
5557 else
5558 {
5559 /* modify already existing coefficient */
5560 assert(0 <= pos && pos < row->len);
5561 assert(row->cols[pos] == col);
5562 assert(row->cols_index[pos] == col->index);
5563
5564 /* if column knows of the row, change the corresponding coefficient in the column */
5565 if( row->linkpos[pos] >= 0 )
5566 {
5567 assert(col->rows[row->linkpos[pos]] == row);
5568 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5569 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5570 }
5571
5572 /* change the coefficient in the row */
5573 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5574 }
5575
5576 checkLinks(lp);
5577
5578 /* invalid the activity */
5579 row->validactivitylp = -1;
5580
5581 return SCIP_OKAY;
5582 }
5583
5584 /** changes constant value of a row */
5585 SCIP_RETCODE SCIProwChgConstant(
5586 SCIP_ROW* row, /**< LP row */
5587 BMS_BLKMEM* blkmem, /**< block memory */
5588 SCIP_SET* set, /**< global SCIP settings */
5589 SCIP_STAT* stat, /**< problem statistics */
5590 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5591 SCIP_LP* lp, /**< current LP data */
5592 SCIP_Real constant /**< new constant value */
5593 )
5594 {
5595 assert(row != NULL);
5596 assert(row->lhs <= row->rhs);
5597 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5598 assert(stat != NULL);
5599 assert(lp != NULL);
5600 assert(!lp->diving || row->lppos == -1);
5601
5602 if( !SCIPsetIsEQ(set, constant, row->constant) )
5603 {
5604 SCIP_Real oldconstant;
5605
5606 if( row->validpsactivitydomchg == stat->domchgcount )
5607 {
5608 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
5609 row->pseudoactivity += constant - row->constant;
5610 }
5611 if( row->validactivitybdsdomchg == stat->domchgcount )
5612 {
5613 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
5614 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
5615 row->minactivity += constant - row->constant;
5616 row->maxactivity += constant - row->constant;
5617 }
5618
5619 if( !SCIPsetIsInfinity(set, -row->lhs) )
5620 {
5621 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5622 }
5623 if( !SCIPsetIsInfinity(set, row->rhs) )
5624 {
5625 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5626 }
5627
5628 oldconstant = row->constant;
5629
5630 row->constant = constant;
5631
5632 /* issue row constant changed event */
5633 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5634 }
5635
5636 return SCIP_OKAY;
5637 }
5638
5639 /** add constant value to a row */
5640 SCIP_RETCODE SCIProwAddConstant(
5641 SCIP_ROW* row, /**< LP row */
5642 BMS_BLKMEM* blkmem, /**< block memory */
5643 SCIP_SET* set, /**< global SCIP settings */
5644 SCIP_STAT* stat, /**< problem statistics */
5645 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5646 SCIP_LP* lp, /**< current LP data */
5647 SCIP_Real addval /**< constant value to add to the row */
5648 )
5649 {
5650 assert(row != NULL);
5651 assert(row->lhs <= row->rhs);
5652 assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5653 assert(stat != NULL);
5654 assert(lp != NULL);
5655 assert(!lp->diving || row->lppos == -1);
5656
5657 if( !SCIPsetIsZero(set, addval) )
5658 {
5659 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5660 }
5661
5662 return SCIP_OKAY;
5663 }
5664
5665 /** changes left hand side of LP row */
5666 SCIP_RETCODE SCIProwChgLhs(
5667 SCIP_ROW* row, /**< LP row */
5668 BMS_BLKMEM* blkmem, /**< block memory */
5669 SCIP_SET* set, /**< global SCIP settings */
5670 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5671 SCIP_LP* lp, /**< current LP data */
5672 SCIP_Real lhs /**< new left hand side */
5673 )
5674 {
5675 assert(row != NULL);
5676 assert(lp != NULL);
5677
5678 if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5679 {
5680 SCIP_Real oldlhs;
5681
5682 oldlhs = row->lhs;
5683
5684 row->lhs = lhs;
5685 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5686
5687 if( !lp->diving )
5688 {
5689 /* issue row side changed event */
5690 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5691 }
5692 }
5693
5694 return SCIP_OKAY;
5695 }
5696
5697 /** changes right hand side of LP row */
5698 SCIP_RETCODE SCIProwChgRhs(
5699 SCIP_ROW* row, /**< LP row */
5700 BMS_BLKMEM* blkmem, /**< block memory */
5701 SCIP_SET* set, /**< global SCIP settings */
5702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5703 SCIP_LP* lp, /**< current LP data */
5704 SCIP_Real rhs /**< new right hand side */
5705 )
5706 {
5707 assert(row != NULL);
5708 assert(lp != NULL);
5709
5710 if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5711 {
5712 SCIP_Real oldrhs;
5713
5714 oldrhs = row->rhs;
5715
5716 row->rhs = rhs;
5717 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5718
5719 if( !lp->diving )
5720 {
5721 /* issue row side changed event */
5722 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5723 }
5724 }
5725
5726 return SCIP_OKAY;
5727 }
5728
5729 /** changes the local flag of LP row */
5730 SCIP_RETCODE SCIProwChgLocal(
5731 SCIP_ROW* row, /**< LP row */
5732 SCIP_Bool local /**< new value for local flag */
5733 )
5734 {
5735 assert(row != NULL);
5736
5737 row->local = local;
5738
5739 return SCIP_OKAY;
5740 }
5741
5742 /** additional scalars that are tried in integrality scaling */
5743 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5744 static const int nscalars = 9;
5745
5746 /** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5747 SCIP_RETCODE SCIProwCalcIntegralScalar(
5748 SCIP_ROW* row, /**< LP row */
5749 SCIP_SET* set, /**< global SCIP settings */
5750 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5751 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5752 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5753 SCIP_Real maxscale, /**< maximal allowed scalar */
5754 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5755 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5756 SCIP_Bool* success /**< stores whether returned value is valid */
5757 )
5758 {
5759 #ifndef NDEBUG
5760 SCIP_COL* col;
5761 #endif
5762 SCIP_Longint gcd;
5763 SCIP_Longint scm;
5764 SCIP_Longint nominator;
5765 SCIP_Longint denominator;
5766 SCIP_Real val;
5767 SCIP_Real absval;
5768 SCIP_Real minval;
5769 SCIP_Real scaleval;
5770 SCIP_Real twomultval;
5771 SCIP_Bool scalable;
5772 SCIP_Bool twomult;
5773 SCIP_Bool rational;
5774 int c;
5775 int s;
5776
5777 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5778 assert(row != NULL);
5779 assert(row->len == 0 || row->cols != NULL);
5780 assert(row->len == 0 || row->cols_index != NULL);
5781 assert(row->len == 0 || row->vals != NULL);
5782 assert(maxdnom >= 1);
5783 assert(mindelta < 0.0);
5784 assert(maxdelta > 0.0);
5785 assert(success != NULL);
5786
5787 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5788 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5789
5790 if( intscalar != NULL )
5791 *intscalar = SCIP_INVALID;
5792 *success = FALSE;
5793
5794 /* get minimal absolute non-zero value */
5795 minval = SCIP_REAL_MAX;
5796 for( c = 0; c < row->len; ++c )
5797 {
5798 #ifndef NDEBUG
5799 col = row->cols[c];
5800 assert(col != NULL);
5801 assert(col->var != NULL);
5802 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
5803 assert(SCIPvarGetCol(col->var) == col);
5804 #endif
5805 val = row->vals[c];
5806 assert(!SCIPsetIsZero(set, val));
5807
5808 if( val < mindelta || val > maxdelta )
5809 {
5810 absval = REALABS(val);
5811 minval = MIN(minval, absval);
5812 }
5813 }
5814 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5815 {
5816 /* all coefficients are zero (inside tolerances) */
5817 if( intscalar != NULL )
5818 *intscalar = 1.0;
5819 *success = TRUE;
5820 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5821
5822 return SCIP_OKAY;
5823 }
5824 assert(minval > MIN(-mindelta, maxdelta));
5825 assert(SCIPsetIsPositive(set, minval));
5826 assert(!SCIPsetIsInfinity(set, minval));
5827
5828 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5829 * and a power of 2
5830 */
5831 scaleval = 1.0/minval;
5832 scalable = (scaleval <= maxscale);
5833 for( c = 0; c < row->len && scalable; ++c )
5834 {
5835 /* don't look at continuous variables, if we don't have to */
5836 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5837 continue;
5838
5839 /* check, if the coefficient can be scaled with a simple scalar */
5840 val = row->vals[c];
5841 absval = REALABS(val);
5842 while( scaleval <= maxscale
5843 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5844 {
5845 for( s = 0; s < nscalars; ++s )
5846 {
5847 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5848 {
5849 scaleval *= scalars[s];
5850 break;
5851 }
5852 }
5853 if( s >= nscalars )
5854 scaleval *= 2.0;
5855 }
5856 scalable = (scaleval <= maxscale);
5857 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5858 }
5859 if( scalable )
5860 {
5861 /* make row coefficients integral by dividing them by the smallest coefficient
5862 * (and multiplying them with a power of 2)
5863 */
5864 assert(scaleval <= maxscale);
5865 if( intscalar != NULL )
5866 *intscalar = scaleval;
5867 *success = TRUE;
5868 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5869
5870 return SCIP_OKAY;
5871 }
5872
5873 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5874 twomultval = 1.0;
5875 twomult = (twomultval <= maxscale);
5876 for( c = 0; c < row->len && twomult; ++c )
5877 {
5878 /* don't look at continuous variables, if we don't have to */
5879 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5880 continue;
5881
5882 /* check, if the coefficient can be scaled with a simple scalar */
5883 val = row->vals[c];
5884 absval = REALABS(val);
5885 while( twomultval <= maxscale
5886 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5887 {
5888 for( s = 0; s < nscalars; ++s )
5889 {
5890 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5891 {
5892 twomultval *= scalars[s];
5893 break;
5894 }
5895 }
5896 if( s >= nscalars )
5897 twomultval *= 2.0;
5898 }
5899 twomult = (twomultval <= maxscale);
5900 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5901 val, twomultval, val*twomultval, twomult);
5902 }
5903 if( twomult )
5904 {
5905 /* make row coefficients integral by multiplying them with a power of 2 */
5906 assert(twomultval <= maxscale);
5907 if( intscalar != NULL )
5908 *intscalar = twomultval;
5909 *success = TRUE;
5910 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5911
5912 return SCIP_OKAY;
5913 }
5914
5915 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5916 * and the smallest common multiple of the denominators
5917 */
5918 gcd = 1;
5919 scm = 1;
5920 rational = (maxdnom > 1);
5921
5922 /* first coefficient (to initialize gcd) */
5923 for( c = 0; c < row->len && rational; ++c )
5924 {
5925 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5926 {
5927 val = row->vals[c];
5928 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5929 if( rational && nominator != 0 )
5930 {
5931 assert(denominator > 0);
5932 gcd = ABS(nominator);
5933 scm = denominator;
5934 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5935 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5936 val, nominator, denominator, gcd, scm, rational);
5937 break;
5938 }
5939 }
5940 }
5941
5942 /* remaining coefficients */
5943 for( ++c; c < row->len && rational; ++c )
5944 {
5945 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5946 {
5947 val = row->vals[c];
5948 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5949 if( rational && nominator != 0 )
5950 {
5951 assert(denominator > 0);
5952 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5953 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5954 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5955 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5956 val, nominator, denominator, gcd, scm, rational);
5957 }
5958 }
5959 }
5960
5961 if( rational )
5962 {
5963 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5964 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5965 if( intscalar != NULL )
5966 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5967 *success = TRUE;
5968 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5969 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5970 }
5971 else
5972 {
5973 assert(!(*success));
5974 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5975 }
5976
5977 return SCIP_OKAY;
5978 }
5979
5980 /** tries to scale row, s.t. all coefficients become integral */
5981 SCIP_RETCODE SCIProwMakeIntegral(
5982 SCIP_ROW* row, /**< LP row */
5983 BMS_BLKMEM* blkmem, /**< block memory */
5984 SCIP_SET* set, /**< global SCIP settings */
5985 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5986 SCIP_STAT* stat, /**< problem statistics */
5987 SCIP_LP* lp, /**< current LP data */
5988 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5989 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5990 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5991 SCIP_Real maxscale, /**< maximal value to scale row with */
5992 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5993 SCIP_Bool* success /**< stores whether row could be made rational */
5994 )
5995 {
5996 SCIP_Real intscalar;
5997
5998 assert(success != NULL);
5999
6000 /* calculate scalar to make coefficients integral */
6001 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
6002 &intscalar, success) );
6003
6004 if( *success )
6005 {
6006 /* scale the row */
6007 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6008 }
6009
6010 return SCIP_OKAY;
6011 }
6012
6013 /** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6014 * higher ones
6015 */
6016 void SCIProwSort(
6017 SCIP_ROW* row /**< row to be sorted */
6018 )
6019 {
6020 assert(row != NULL);
6021
6022 /* sort LP columns */
6023 rowSortLP(row);
6024
6025 /* sort non-LP columns */
6026 rowSortNonLP(row);
6027
6028 #ifdef SCIP_MORE_DEBUG
6029 /* check the sorting */
6030 {
6031 int c;
6032 if( !row->delaysort )
6033 {
6034 for( c = 1; c < row->nlpcols; ++c )
6035 assert(row->cols[c]->index >= row->cols[c-1]->index);
6036 for( c = row->nlpcols + 1; c < row->len; ++c )
6037 assert(row->cols[c]->index >= row->cols[c-1]->index);
6038 }
6039 }
6040 #endif
6041 }
6042
6043 /** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6044 * zero entries from row
6045 * the row must not be linked to the columns; otherwise, we would need to update the columns as
6046 * well, which is too expensive
6047 */
6048 static
6049 void rowMerge(
6050 SCIP_ROW* row, /**< row to be sorted */
6051 SCIP_SET* set /**< global SCIP settings */
6052 )
6053 {
6054 assert(row != NULL);
6055 assert(!row->delaysort);
6056 assert(row->nunlinked == row->len);
6057 assert(row->nlpcols == 0);
6058
6059 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6060
6061 /* do nothing on empty rows; if row is sorted, nothing has to be done */
6062 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6063 {
6064 SCIP_COL** cols;
6065 int* cols_index;
6066 SCIP_Real* vals;
6067 int s;
6068 int t;
6069
6070 /* make sure, the row is sorted */
6071 SCIProwSort(row);
6072 assert(row->lpcolssorted);
6073 assert(row->nonlpcolssorted);
6074
6075 /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6076 cols = row->cols;
6077 cols_index = row->cols_index;
6078 vals = row->vals;
6079 assert(cols != NULL);
6080 assert(cols_index != NULL);
6081 assert(vals != NULL);
6082
6083 t = 0;
6084 row->integral = TRUE;
6085 assert(!SCIPsetIsZero(set, vals[0]));
6086 assert(row->linkpos[0] == -1);
6087
6088 for( s = 1; s < row->len; ++s )
6089 {
6090 assert(!SCIPsetIsZero(set, vals[s]));
6091 assert(row->linkpos[s] == -1);
6092
6093 if( cols[s] == cols[t] )
6094 {
6095 /* merge entries with equal column */
6096 vals[t] += vals[s];
6097 }
6098 else
6099 {
6100 /* go to the next entry, overwriting current entry if coefficient is zero */
6101 if( !SCIPsetIsZero(set, vals[t]) )
6102 {
6103 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6104 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6105
6106 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6107 t++;
6108 }
6109 cols[t] = cols[s];
6110 cols_index[t] = cols_index[s];
6111 vals[t] = vals[s];
6112 }
6113 }
6114 if( !SCIPsetIsZero(set, vals[t]) )
6115 {
6116 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6117 t++;
6118 }
6119 assert(s == row->len);
6120 assert(t <= row->len);
6121
6122 row->len = t;
6123 row->nunlinked = t;
6124
6125 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6126 if( t < s )
6127 rowCalcNorms(row, set);
6128 }
6129
6130 #ifndef NDEBUG
6131 /* check for double entries */
6132 {
6133 int i;
6134 int j;
6135
6136 for( i = 0; i < row->len; ++i )
6137 {
6138 assert(row->cols[i] != NULL);
6139 assert(row->cols[i]->index == row->cols_index[i]);
6140 for( j = i+1; j < row->len; ++j )
6141 assert(row->cols[i] != row->cols[j]);
6142 }
6143 }
6144 #endif
6145 }
6146
6147 /** enables delaying of row sorting */
6148 void SCIProwDelaySort(
6149 SCIP_ROW* row /**< LP row */
6150 )
6151 {
6152 assert(row != NULL);
6153 assert(!row->delaysort);
6154
6155 row->delaysort = TRUE;
6156 }
6157
6158 /** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6159 void SCIProwForceSort(
6160 SCIP_ROW* row, /**< LP row */
6161 SCIP_SET* set /**< global SCIP settings */
6162 )
6163 {
6164 assert(row != NULL);
6165 assert(row->delaysort);
6166
6167 row->delaysort = FALSE;
6168 rowMerge(row, set);
6169 }
6170
6171 /** recalculates the current activity of a row */
6172 void SCIProwRecalcLPActivity(
6173 SCIP_ROW* row, /**< LP row */
6174 SCIP_STAT* stat /**< problem statistics */
6175 )
6176 {
6177 SCIP_COL* col;
6178 int c;
6179
6180 assert(row != NULL);
6181 assert(stat != NULL);
6182
6183 row->activity = row->constant;
6184 for( c = 0; c < row->nlpcols; ++c )
6185 {
6186 col = row->cols[c];
6187 assert(col != NULL);
6188 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
6189 assert(col->lppos >= 0);
6190 assert(row->linkpos[c] >= 0);
6191 row->activity += row->vals[c] * col->primsol;
6192 }
6193
6194 if( row->nunlinked > 0 )
6195 {
6196 for( c = row->nlpcols; c < row->len; ++c )
6197 {
6198 col = row->cols[c];
6199 assert(col != NULL);
6200 assert(col->lppos >= 0 || col->primsol == 0.0);
6201 assert(col->lppos == -1 || row->linkpos[c] == -1);
6202 if( col->lppos >= 0 )
6203 row->activity += row->vals[c] * col->primsol;
6204 }
6205 }
6206 #ifndef NDEBUG
6207 else
6208 {
6209 for( c = row->nlpcols; c < row->len; ++c )
6210 {
6211 col = row->cols[c];
6212 assert(col != NULL);
6213 assert(col->primsol == 0.0);
6214 assert(col->lppos == -1);
6215 assert(row->linkpos[c] >= 0);
6216 }
6217 }
6218 #endif
6219
6220 row->validactivitylp = stat->lpcount;
6221 }
6222
6223 /** returns the activity of a row in the current LP solution */
6224 SCIP_Real SCIProwGetLPActivity(
6225 SCIP_ROW* row, /**< LP row */
6226 SCIP_SET* set, /**< global SCIP settings */
6227 SCIP_STAT* stat, /**< problem statistics */
6228 SCIP_LP* lp /**< current LP data */
6229 )
6230 {
6231 SCIP_Real inf;
6232 SCIP_Real activity;
6233
6234 assert(row != NULL);
6235 assert(stat != NULL);
6236 assert(lp != NULL);
6237 assert(row->validactivitylp <= stat->lpcount);
6238 assert(lp->validsollp == stat->lpcount);
6239
6240 if( row->validactivitylp != stat->lpcount )
6241 SCIProwRecalcLPActivity(row, stat);
6242 assert(row->validactivitylp == stat->lpcount);
6243 assert(row->activity != SCIP_INVALID); /*lint !e777*/
6244
6245 activity = row->activity;
6246 inf = SCIPsetInfinity(set);
6247 activity = MAX(activity, -inf);
6248 activity = MIN(activity, +inf);
6249
6250 return activity;
6251 }
6252
6253 /** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6254 SCIP_Real SCIProwGetLPFeasibility(
6255 SCIP_ROW* row, /**< LP row */
6256 SCIP_SET* set, /**< global SCIP settings */
6257 SCIP_STAT* stat, /**< problem statistics */
6258 SCIP_LP* lp /**< current LP data */
6259 )
6260 {
6261 SCIP_Real activity;
6262
6263 assert(row != NULL);
6264
6265 activity = SCIProwGetLPActivity(row, set, stat, lp);
6266
6267 return MIN(row->rhs - activity, activity - row->lhs);
6268 }
6269
6270 /** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6271 *
6272 * @todo Implement calculation of activities similar to LPs.
6273 */
6274 SCIP_Real SCIProwGetRelaxFeasibility(
6275 SCIP_ROW* row, /**< LP row */
6276 SCIP_SET* set, /**< global SCIP settings */
6277 SCIP_STAT* stat /**< problem statistics */
6278 )
6279 {
6280 SCIP_Real inf;
6281 SCIP_Real activity;
6282 SCIP_COL* col;
6283 int c;
6284
6285 assert( row != NULL );
6286 assert( stat != NULL );
6287
6288 activity = row->constant;
6289 for (c = 0; c < row->nlpcols; ++c)
6290 {
6291 col = row->cols[c];
6292 assert( col != NULL );
6293 assert( col->lppos >= 0 );
6294 assert( col->var != NULL );
6295 assert( row->linkpos[c] >= 0 );
6296 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6297 }
6298
6299 if ( row->nunlinked > 0 )
6300 {
6301 for (c = row->nlpcols; c < row->len; ++c)
6302 {
6303 col = row->cols[c];
6304 assert( col != NULL );
6305 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6306 if ( col->lppos >= 0 )
6307 {
6308 assert( col->var != NULL );
6309 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6310 }
6311 }
6312 }
6313 #ifndef NDEBUG
6314 else
6315 {
6316 for (c = row->nlpcols; c < row->len; ++c)
6317 {
6318 col = row->cols[c];
6319 assert( col != NULL );
6320 assert( col->lppos == -1 );
6321 assert( row->linkpos[c] >= 0 );
6322 }
6323 }
6324 #endif
6325 inf = SCIPsetInfinity(set);
6326 activity = MAX(activity, -inf);
6327 activity = MIN(activity, +inf);
6328
6329 return MIN(row->rhs - activity, activity - row->lhs);
6330 }
6331
6332 /** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6333 *
6334 * @todo Implement calculation of activities similar to LPs.
6335 */
6336 SCIP_Real SCIProwGetNLPFeasibility(
6337 SCIP_ROW* row, /**< LP row */
6338 SCIP_SET* set, /**< global SCIP settings */
6339 SCIP_STAT* stat /**< problem statistics */
6340 )
6341 {
6342 SCIP_Real inf;
6343 SCIP_Real activity;
6344 SCIP_COL* col;
6345 int c;
6346
6347 assert( row != NULL );
6348 assert( stat != NULL );
6349
6350 activity = row->constant;
6351 for (c = 0; c < row->nlpcols; ++c)
6352 {
6353 col = row->cols[c];
6354 assert( col != NULL );
6355 assert( col->lppos >= 0 );
6356 assert( col->var != NULL );
6357 assert( row->linkpos[c] >= 0 );
6358 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6359 }
6360
6361 if ( row->nunlinked > 0 )
6362 {
6363 for (c = row->nlpcols; c < row->len; ++c)
6364 {
6365 col = row->cols[c];
6366 assert( col != NULL );
6367 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6368 if ( col->lppos >= 0 )
6369 {
6370 assert( col->var != NULL );
6371 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6372 }
6373 }
6374 }
6375 #ifndef NDEBUG
6376 else
6377 {
6378 for (c = row->nlpcols; c < row->len; ++c)
6379 {
6380 col = row->cols[c];
6381 assert( col != NULL );
6382 assert( col->lppos == -1 );
6383 assert( row->linkpos[c] >= 0 );
6384 }
6385 }
6386 #endif
6387 inf = SCIPsetInfinity(set);
6388 activity = MAX(activity, -inf);
6389 activity = MIN(activity, +inf);
6390
6391 return MIN(row->rhs - activity, activity - row->lhs);
6392 }
6393
6394 /** calculates the current pseudo activity of a row */
6395 void SCIProwRecalcPseudoActivity(
6396 SCIP_ROW* row, /**< row data */
6397 SCIP_STAT* stat /**< problem statistics */
6398 )
6399 {
6400 SCIP_COL* col;
6401 int i;
6402
6403 assert(row != NULL);
6404 assert(stat != NULL);
6405
6406 row->pseudoactivity = row->constant;
6407 for( i = 0; i < row->len; ++i )
6408 {
6409 col = row->cols[i];
6410 assert(col != NULL);
6411 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6412 assert(col->var != NULL);
6413 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
6414
6415 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6416 }
6417 row->validpsactivitydomchg = stat->domchgcount;
6418 assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6419 }
6420
6421 /** returns the pseudo activity of a row in the current pseudo solution */
6422 SCIP_Real SCIProwGetPseudoActivity(
6423 SCIP_ROW* row, /**< LP row */
6424 SCIP_SET* set, /**< global SCIP settings */
6425 SCIP_STAT* stat /**< problem statistics */
6426 )
6427 {
6428 SCIP_Real inf;
6429 SCIP_Real activity;
6430
6431 assert(row != NULL);
6432 assert(stat != NULL);
6433 assert(row->validpsactivitydomchg <= stat->domchgcount);
6434
6435 /* check, if pseudo activity has to be calculated */
6436 if( row->validpsactivitydomchg != stat->domchgcount )
6437 SCIProwRecalcPseudoActivity(row, stat);
6438 assert(row->validpsactivitydomchg == stat->domchgcount);
6439 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
6440
6441 activity = row->pseudoactivity;
6442 inf = SCIPsetInfinity(set);
6443 activity = MAX(activity, -inf);
6444 activity = MIN(activity, +inf);
6445
6446 return activity;
6447 }
6448
6449 /** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6450 SCIP_Real SCIProwGetPseudoFeasibility(
6451 SCIP_ROW* row, /**< LP row */
6452 SCIP_SET* set, /**< global SCIP settings */
6453 SCIP_STAT* stat /**< problem statistics */
6454 )
6455 {
6456 SCIP_Real pseudoactivity;
6457
6458 assert(row != NULL);
6459
6460 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6461
6462 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6463 }
6464
6465 /** returns the activity of a row for a given solution */
6466 SCIP_Real SCIProwGetSolActivity(
6467 SCIP_ROW* row, /**< LP row */
6468 SCIP_SET* set, /**< global SCIP settings */
6469 SCIP_STAT* stat, /**< problem statistics data */
6470 SCIP_SOL* sol /**< primal CIP solution */
6471 )
6472 {
6473 SCIP_COL* col;
6474 SCIP_Real inf;
6475 SCIP_Real activity;
6476 SCIP_Real solval;
6477 int i;
6478
6479 assert(row != NULL);
6480
6481 activity = row->constant;
6482 for( i = 0; i < row->len; ++i )
6483 {
6484 col = row->cols[i];
6485 assert(col != NULL);
6486 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6487 solval = SCIPsolGetVal(sol, set, stat, col->var);
6488 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6489 {
6490 if( SCIPsetIsInfinity(set, -row->lhs) )
6491 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6492 else if( SCIPsetIsInfinity(set, row->rhs) )
6493 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6494 else
6495 solval = (col->lb + col->ub)/2.0;
6496 }
6497 activity += row->vals[i] * solval;
6498 }
6499
6500 inf = SCIPsetInfinity(set);
6501 activity = MAX(activity, -inf);
6502 activity = MIN(activity, +inf);
6503
6504 return activity;
6505 }
6506
6507 /** returns the feasibility of a row for the given solution */
6508 SCIP_Real SCIProwGetSolFeasibility(
6509 SCIP_ROW* row, /**< LP row */
6510 SCIP_SET* set, /**< global SCIP settings */
6511 SCIP_STAT* stat, /**< problem statistics data */
6512 SCIP_SOL* sol /**< primal CIP solution */
6513 )
6514 {
6515 SCIP_Real activity;
6516
6517 assert(row != NULL);
6518
6519 activity = SCIProwGetSolActivity(row, set, stat, sol);
6520
6521 return MIN(row->rhs - activity, activity - row->lhs);
6522 }
6523
6524 /** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6525 static
6526 void rowCalcActivityBounds(
6527 SCIP_ROW* row, /**< row data */
6528 SCIP_SET* set, /**< global SCIP settings */
6529 SCIP_STAT* stat /**< problem statistics data */
6530 )
6531 {
6532 SCIP_COL* col;
6533 SCIP_Real val;
6534 SCIP_Bool mininfinite;
6535 SCIP_Bool maxinfinite;
6536 int i;
6537
6538 assert(row != NULL);
6539 assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6540 assert(stat != NULL);
6541
6542 /* calculate activity bounds */
6543 mininfinite = FALSE;
6544 maxinfinite = FALSE;
6545 row->minactivity = row->constant;
6546 row->maxactivity = row->constant;
6547 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6548 {
6549 col = row->cols[i];
6550 assert(col != NULL);
6551 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6552 val = row->vals[i];
6553 if( val >= 0.0 )
6554 {
6555 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6556 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6557 if( !mininfinite )
6558 row->minactivity += val * col->lb;
6559 if( !maxinfinite )
6560 row->maxactivity += val * col->ub;
6561 }
6562 else
6563 {
6564 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6565 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6566 if( !mininfinite )
6567 row->minactivity += val * col->ub;
6568 if( !maxinfinite )
6569 row->maxactivity += val * col->lb;
6570 }
6571 }
6572
6573 if( mininfinite )
6574 row->minactivity = -SCIPsetInfinity(set);
6575 if( maxinfinite )
6576 row->maxactivity = SCIPsetInfinity(set);
6577 row->validactivitybdsdomchg = stat->domchgcount;
6578
6579 #ifndef NDEBUG
6580 {
6581 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6582
6583 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6584 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6585 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6586 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6587 * tolerance as a proxy to account for the accumulation effect
6588 */
6589 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6590 || EPSISINT(row->minactivity - row->constant, inttol));
6591 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6592 || EPSISINT(row->maxactivity - row->constant, inttol));
6593 }
6594 #endif
6595 }
6596
6597 /** returns the minimal activity of a row w.r.t. the columns' bounds */
6598 SCIP_Real SCIProwGetMinActivity(
6599 SCIP_ROW* row, /**< LP row */
6600 SCIP_SET* set, /**< global SCIP settings */
6601 SCIP_STAT* stat /**< problem statistics data */
6602 )
6603 {
6604 assert(row != NULL);
6605 assert(stat != NULL);
6606 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6607
6608 /* check, if activity bounds has to be calculated */
6609 if( row->validactivitybdsdomchg != stat->domchgcount )
6610 rowCalcActivityBounds(row, set, stat);
6611 assert(row->validactivitybdsdomchg == stat->domchgcount);
6612 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6613 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6614
6615 return row->minactivity;
6616 }
6617
6618 /** returns the maximal activity of a row w.r.t. the columns' bounds */
6619 SCIP_Real SCIProwGetMaxActivity(
6620 SCIP_ROW* row, /**< LP row */
6621 SCIP_SET* set, /**< global SCIP settings */
6622 SCIP_STAT* stat /**< problem statistics data */
6623 )
6624 {
6625 assert(row != NULL);
6626 assert(stat != NULL);
6627 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6628
6629 /* check, if activity bounds has to be calculated */
6630 if( row->validactivitybdsdomchg != stat->domchgcount )
6631 rowCalcActivityBounds(row, set, stat);
6632 assert(row->validactivitybdsdomchg == stat->domchgcount);
6633 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6634 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6635
6636 return row->maxactivity;
6637 }
6638
6639 /** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6640 SCIP_Bool SCIProwIsRedundant(
6641 SCIP_ROW* row, /**< LP row */
6642 SCIP_SET* set, /**< global SCIP settings */
6643 SCIP_STAT* stat /**< problem statistics data */
6644 )
6645 {
6646 assert(row != NULL);
6647
6648 if( row->modifiable )
6649 return FALSE;
6650 if( !SCIPsetIsInfinity(set, -row->lhs) )
6651 {
6652 SCIP_Real minactivity;
6653
6654 minactivity = SCIProwGetMinActivity(row, set, stat);
6655 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6656 return FALSE;
6657 }
6658 if( !SCIPsetIsInfinity(set, row->rhs) )
6659 {
6660 SCIP_Real maxactivity;
6661
6662 maxactivity = SCIProwGetMaxActivity(row, set, stat);
6663 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6664 return FALSE;
6665 }
6666
6667 return TRUE;
6668 }
6669
6670 /** gets maximal absolute value of row vector coefficients */
6671 SCIP_Real SCIProwGetMaxval(
6672 SCIP_ROW* row, /**< LP row */
6673 SCIP_SET* set /**< global SCIP settings */
6674 )
6675 {
6676 assert(row != NULL);
6677
6678 if( row->nummaxval == 0 )
6679 rowCalcIdxsAndVals(row, set);
6680 assert(row->nummaxval > 0);
6681 assert(row->maxval >= 0.0 || row->len == 0);
6682
6683 return row->maxval;
6684 }
6685
6686 /** gets minimal absolute value of row vector's non-zero coefficients */
6687 SCIP_Real SCIProwGetMinval(
6688 SCIP_ROW* row, /**< LP row */
6689 SCIP_SET* set /**< global SCIP settings */
6690 )
6691 {
6692 assert(row != NULL);
6693
6694 if( row->numminval == 0 )
6695 rowCalcIdxsAndVals(row, set);
6696 assert(row->numminval > 0);
6697 assert(row->minval >= 0.0 || row->len == 0);
6698
6699 return row->minval;
6700 }
6701
6702 /** gets maximal column index of row entries */
6703 int SCIProwGetMaxidx(
6704 SCIP_ROW* row, /**< LP row */
6705 SCIP_SET* set /**< global SCIP settings */
6706 )
6707 {
6708 assert(row != NULL);
6709
6710 if( row->validminmaxidx == 0 )
6711 rowCalcIdxsAndVals(row, set);
6712 assert(row->maxidx >= 0 || row->len == 0);
6713 assert(row->validminmaxidx);
6714
6715 return row->maxidx;
6716 }
6717
6718 /** gets minimal column index of row entries */
6719 int SCIProwGetMinidx(
6720 SCIP_ROW* row, /**< LP row */
6721 SCIP_SET* set /**< global SCIP settings */
6722 )
6723 {
6724 assert(row != NULL);
6725
6726 if( row->validminmaxidx == 0 )
6727 rowCalcIdxsAndVals(row, set);
6728 assert(row->minidx >= 0 || row->len == 0);
6729 assert(row->validminmaxidx);
6730
6731 return row->minidx;
6732 }
6733
6734 /** gets number of integral columns in row */
6735 int SCIProwGetNumIntCols(
6736 SCIP_ROW* row, /**< LP row */
6737 SCIP_SET* set /**< global SCIP settings */
6738 )
6739 {
6740 assert(row != NULL);
6741
6742 if( row->numintcols == -1 )
6743 rowCalcIdxsAndVals(row, set);
6744
6745 assert(row->numintcols <= row->len && row->numintcols >= 0);
6746
6747 return row->numintcols;
6748 }
6749
6750 /** returns row's cutoff distance in the direction of the given primal solution */
6751 SCIP_Real SCIProwGetLPSolCutoffDistance(
6752 SCIP_ROW* row, /**< LP row */
6753 SCIP_SET* set, /**< global SCIP settings */
6754 SCIP_STAT* stat, /**< problem statistics data */
6755 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
6756 SCIP_LP* lp /**< current LP data */
6757 )
6758 {
6759 SCIP_Real solcutoffdist;
6760 int k;
6761
6762 assert(sol != NULL);
6763
6764 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6765 {
6766 SCIP_Real scale = 0.0;
6767
6768 lp->validsoldirlp = stat->lpcount;
6769 lp->validsoldirsol = sol;
6770
6771 SCIP_CALL_ABORT( ensureSoldirectionSize(lp, lp->ncols) );
6772
6773 for( k = 0; k < lp->ncols; ++k )
6774 {
6775 assert(lp->cols[k]->lppos == k);
6776 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6777 scale += SQR(lp->soldirection[k]);
6778 }
6779
6780 if( scale > 0.0 )
6781 {
6782 scale = 1.0 / SQRT(scale);
6783
6784 for( k = 0; k < lp->ncols; ++k )
6785 lp->soldirection[k] *= scale;
6786 }
6787 }
6788
6789 solcutoffdist = 0.0;
6790 for( k = 0; k < row->nlpcols; ++k )
6791 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6792
6793 for( k = row->nlpcols; k < row->len; ++k )
6794 {
6795 if( row->cols[k]->lppos >= 0 )
6796 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6797 }
6798
6799 if( SCIPsetIsSumZero(set, solcutoffdist) )
6800 solcutoffdist = set->num_sumepsilon;
6801
6802 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6803
6804 return solcutoffdist;
6805 }
6806
6807 /** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6808 SCIP_Real SCIProwGetLPEfficacy(
6809 SCIP_ROW* row, /**< LP row */
6810 SCIP_SET* set, /**< global SCIP settings */
6811 SCIP_STAT* stat, /**< problem statistics data */
6812 SCIP_LP* lp /**< current LP data */
6813 )
6814 {
6815 SCIP_Real norm;
6816 SCIP_Real feasibility;
6817 SCIP_Real eps;
6818
6819 assert(set != NULL);
6820
6821 switch( set->sepa_efficacynorm )
6822 {
6823 case 'e':
6824 norm = SCIProwGetNorm(row);
6825 break;
6826 case 'm':
6827 norm = SCIProwGetMaxval(row, set);
6828 break;
6829 case 's':
6830 norm = SCIProwGetSumNorm(row);
6831 break;
6832 case 'd':
6833 norm = (row->len == 0 ? 0.0 : 1.0);
6834 break;
6835 default:
6836 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6837 SCIPABORT();
6838 norm = 0.0; /*lint !e527*/
6839 }
6840
6841 eps = SCIPsetSumepsilon(set);
6842 norm = MAX(norm, eps);
6843 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6844
6845 return -feasibility / norm;
6846 }
6847
6848 /** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6849 SCIP_Bool SCIProwIsLPEfficacious(
6850 SCIP_ROW* row, /**< LP row */
6851 SCIP_SET* set, /**< global SCIP settings */
6852 SCIP_STAT* stat, /**< problem statistics data */
6853 SCIP_LP* lp, /**< current LP data */
6854 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6855 )
6856 {
6857 SCIP_Real efficacy;
6858
6859 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6860
6861 return SCIPsetIsEfficacious(set, root, efficacy);
6862 }
6863
6864 /** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6865 SCIP_Real SCIProwGetSolEfficacy(
6866 SCIP_ROW* row, /**< LP row */
6867 SCIP_SET* set, /**< global SCIP settings */
6868 SCIP_STAT* stat, /**< problem statistics data */
6869 SCIP_SOL* sol /**< primal CIP solution */
6870 )
6871 {
6872 SCIP_Real norm;
6873 SCIP_Real feasibility;
6874 SCIP_Real eps;
6875
6876 assert(set != NULL);
6877
6878 switch( set->sepa_efficacynorm )
6879 {
6880 case 'e':
6881 norm = SCIProwGetNorm(row);
6882 break;
6883 case 'm':
6884 norm = SCIProwGetMaxval(row, set);
6885 break;
6886 case 's':
6887 norm = SCIProwGetSumNorm(row);
6888 break;
6889 case 'd':
6890 norm = (row->len == 0 ? 0.0 : 1.0);
6891 break;
6892 default:
6893 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6894 SCIPABORT();
6895 norm = 0.0; /*lint !e527*/
6896 }
6897
6898 eps = SCIPsetSumepsilon(set);
6899 norm = MAX(norm, eps);
6900 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6901
6902 return -feasibility / norm;
6903 }
6904
6905 /** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6906 * efficacy
6907 */
6908 SCIP_Bool SCIProwIsSolEfficacious(
6909 SCIP_ROW* row, /**< LP row */
6910 SCIP_SET* set, /**< global SCIP settings */
6911 SCIP_STAT* stat, /**< problem statistics data */
6912 SCIP_SOL* sol, /**< primal CIP solution */
6913 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6914 )
6915 {
6916 SCIP_Real efficacy;
6917
6918 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6919
6920 return SCIPsetIsEfficacious(set, root, efficacy);
6921 }
6922
6923 /** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6924 SCIP_Real SCIProwGetRelaxEfficacy(
6925 SCIP_ROW* row, /**< LP row */
6926 SCIP_SET* set, /**< global SCIP settings */
6927 SCIP_STAT* stat /**< problem statistics data */
6928 )
6929 {
6930 SCIP_Real norm;
6931 SCIP_Real feasibility;
6932 SCIP_Real eps;
6933
6934 assert(set != NULL);
6935
6936 switch( set->sepa_efficacynorm )
6937 {
6938 case 'e':
6939 norm = SCIProwGetNorm(row);
6940 break;
6941 case 'm':
6942 norm = SCIProwGetMaxval(row, set);
6943 break;
6944 case 's':
6945 norm = SCIProwGetSumNorm(row);
6946 break;
6947 case 'd':
6948 norm = (row->len == 0 ? 0.0 : 1.0);
6949 break;
6950 default:
6951 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6952 SCIPABORT();
6953 norm = 0.0; /*lint !e527*/
6954 }
6955
6956 eps = SCIPsetSumepsilon(set);
6957 norm = MAX(norm, eps);
6958 feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6959
6960 return -feasibility / norm;
6961 }
6962
6963 /** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6964 SCIP_Real SCIProwGetNLPEfficacy(
6965 SCIP_ROW* row, /**< LP row */
6966 SCIP_SET* set, /**< global SCIP settings */
6967 SCIP_STAT* stat /**< problem statistics data */
6968 )
6969 {
6970 SCIP_Real norm;
6971 SCIP_Real feasibility;
6972 SCIP_Real eps;
6973
6974 assert(set != NULL);
6975
6976 switch( set->sepa_efficacynorm )
6977 {
6978 case 'e':
6979 norm = SCIProwGetNorm(row);
6980 break;
6981 case 'm':
6982 norm = SCIProwGetMaxval(row, set);
6983 break;
6984 case 's':
6985 norm = SCIProwGetSumNorm(row);
6986 break;
6987 case 'd':
6988 norm = (row->len == 0 ? 0.0 : 1.0);
6989 break;
6990 default:
6991 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6992 SCIPABORT();
6993 norm = 0.0; /*lint !e527*/
6994 }
6995
6996 eps = SCIPsetSumepsilon(set);
6997 norm = MAX(norm, eps);
6998 feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6999
7000 return -feasibility / norm;
7001 }
7002
7003 /** returns the scalar product of the coefficient vectors of the two given rows
7004 *
7005 * @note the scalar product is computed w.r.t. the current LP columns only
7006 * @todo also consider non-LP columns for the computation?
7007 */
7008 SCIP_Real SCIProwGetScalarProduct(
7009 SCIP_ROW* row1, /**< first LP row */
7010 SCIP_ROW* row2 /**< second LP row */
7011 )
7012 {
7013 SCIP_Real scalarprod;
7014 int* row1colsidx;
7015 int* row2colsidx;
7016 int i1;
7017 int i2;
7018
7019 assert(row1 != NULL);
7020 assert(row2 != NULL);
7021
7022 /* Sort the column indices of both rows.
7023 *
7024 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7025 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7026 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7027 * for both or one of the non-LP columns for both.
7028 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7029 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7030 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7031 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7032 *
7033 * We distinguish the following cases:
7034 *
7035 * 1) both rows have no unlinked columns
7036 * -> we just check the LP partitions
7037 *
7038 * 2) exactly one row is completely unlinked, the other one is completely linked
7039 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7040 * (thus all common LP columns are regarded)
7041 *
7042 * 3) we have unlinked and LP columns in both rows
7043 * -> we need to compare four partitions at once
7044 *
7045 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7046 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7047 * other row
7048 *
7049 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7050 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7051 *
7052 * 5) both rows are completely unlinked
7053 * -> we need to compare two partitions: both complete rows
7054 */
7055 SCIProwSort(row1);
7056 assert(row1->lpcolssorted);
7057 assert(row1->nonlpcolssorted);
7058 SCIProwSort(row2);
7059 assert(row2->lpcolssorted);
7060 assert(row2->nonlpcolssorted);
7061
7062 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7063 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7064
7065 row1colsidx = row1->cols_index;
7066 row2colsidx = row2->cols_index;
7067
7068 #ifndef NDEBUG
7069 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7070 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7071 {
7072 i1 = 0;
7073 i2 = row2->nlpcols;
7074 while( i1 < row1->nlpcols && i2 < row2->len )
7075 {
7076 assert(row1->cols[i1] != row2->cols[i2]);
7077 if( row1->cols[i1]->index < row2->cols[i2]->index )
7078 ++i1;
7079 else
7080 {
7081 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7082 ++i2;
7083 }
7084 }
7085 assert(i1 == row1->nlpcols || i2 == row2->len);
7086
7087 i1 = row1->nlpcols;
7088 i2 = 0;
7089 while( i1 < row1->len && i2 < row2->nlpcols )
7090 {
7091 assert(row1->cols[i1] != row2->cols[i2]);
7092 if( row1->cols[i1]->index < row2->cols[i2]->index )
7093 ++i1;
7094 else
7095 {
7096 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7097 ++i2;
7098 }
7099 }
7100 assert(i1 == row1->len || i2 == row2->nlpcols);
7101 }
7102 #endif
7103
7104 /* The "easy" cases 1) and 2) */
7105 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7106 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7107 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7108 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7109 {
7110 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7111 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7112
7113 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7114 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7115 */
7116 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7117 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7118 scalarprod = 0.0;
7119
7120 /* calculate the scalar product */
7121 while( i1 >= 0 && i2 >= 0 )
7122 {
7123 assert(row1->cols[i1]->index == row1colsidx[i1]);
7124 assert(row2->cols[i2]->index == row2colsidx[i2]);
7125 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7126 if( row1colsidx[i1] < row2colsidx[i2] )
7127 --i2;
7128 else if( row1colsidx[i1] > row2colsidx[i2] )
7129 --i1;
7130 else
7131 {
7132 scalarprod += row1->vals[i1] * row2->vals[i2];
7133 --i1;
7134 --i2;
7135 }
7136 }
7137 }
7138 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7139 else
7140 {
7141 SCIP_Bool lpcols;
7142 int ilp1;
7143 int inlp1;
7144 int ilp2;
7145 int inlp2;
7146 int end1;
7147 int end2;
7148
7149 scalarprod = 0;
7150 ilp1 = 0;
7151 ilp2 = 0;
7152
7153 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7154 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7155 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7156
7157 /* handle the case of four partitions (case 3) until one partition is finished;
7158 * cases 4a), 4b), and 5) will fail the while-condition
7159 */
7160 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7161 {
7162 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7163 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7164 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7165 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7166 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7167 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7168 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7169 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7170
7171 /* rows have the same linked LP columns */
7172 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7173 {
7174 scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7175 ++ilp1;
7176 ++ilp2;
7177 }
7178 /* LP column of row1 is the same as unlinked column of row2 */
7179 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7180 {
7181 scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7182 ++ilp1;
7183 ++inlp2;
7184 }
7185 /* unlinked column of row1 is the same as LP column of row2 */
7186 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7187 {
7188 scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7189 ++inlp1;
7190 ++ilp2;
7191 }
7192 /* two unlinked LP columns are the same */
7193 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7194 {
7195 scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7196 ++inlp1;
7197 ++inlp2;
7198 }
7199 /* increase smallest counter */
7200 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7201 {
7202 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7203 {
7204 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7205 ++ilp1;
7206 else
7207 ++ilp2;
7208 }
7209 else
7210 {
7211 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7212 ++ilp1;
7213 else
7214 ++inlp2;
7215 }
7216 }
7217 else
7218 {
7219 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7220 {
7221 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7222 ++inlp1;
7223 else
7224 ++ilp2;
7225 }
7226 else
7227 {
7228 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7229 ++inlp1;
7230 else
7231 ++inlp2;
7232 }
7233 }
7234 }
7235
7236 /* One partition was completely handled, we just have to handle the three remaining partitions:
7237 * the remaining partition of this row and the two partitions of the other row.
7238 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7239 */
7240 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7241 {
7242 int tmpilp;
7243 int tmpinlp;
7244
7245 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7246
7247 SCIPswapPointers((void**) &row1, (void**) &row2);
7248 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7249 tmpilp = ilp1;
7250 tmpinlp = inlp1;
7251 ilp1 = ilp2;
7252 inlp1 = inlp2;
7253 ilp2 = tmpilp;
7254 inlp2 = tmpinlp;
7255 }
7256
7257 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7258 * -> this merges cases 4a) and 4b)
7259 */
7260 if( ilp1 == row1->nlpcols )
7261 {
7262 i1 = inlp1;
7263 end1 = row1->len;
7264 lpcols = FALSE;
7265 }
7266 else
7267 {
7268 assert(inlp1 == row1->len);
7269
7270 i1 = ilp1;
7271 end1 = row1->nlpcols;
7272 lpcols = TRUE;
7273 }
7274
7275 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7276 * case 5) will fail the while-condition
7277 */
7278 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7279 {
7280 assert(row1->cols[i1]->index == row1colsidx[i1]);
7281 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7282 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7283 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7284 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7285
7286 /* current column in row 1 is the same as the current LP column in row 2 */
7287 if( row1colsidx[i1] == row2colsidx[ilp2] )
7288 {
7289 scalarprod += row1->vals[i1] * row2->vals[ilp2];
7290 ++i1;
7291 ++ilp2;
7292 }
7293 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7294 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7295 {
7296 scalarprod += row1->vals[i1] * row2->vals[inlp2];
7297 ++i1;
7298 ++inlp2;
7299 }
7300 /* increase smallest counter */
7301 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7302 {
7303 if( row1colsidx[i1] < row2colsidx[ilp2] )
7304 ++i1;
7305 else
7306 ++ilp2;
7307 }
7308 else
7309 {
7310 if( row1colsidx[i1] < row2colsidx[inlp2] )
7311 ++i1;
7312 else
7313 ++inlp2;
7314 }
7315 }
7316
7317 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7318 * the two rows
7319 */
7320 if( i1 < end1 )
7321 {
7322 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7323 if( ilp2 == row2->nlpcols )
7324 {
7325 i2 = inlp2;
7326 end2 = row2->len;
7327 lpcols = FALSE;
7328 }
7329 else
7330 {
7331 assert(inlp2 == row2->len);
7332
7333 i2 = ilp2;
7334 end2 = row2->nlpcols;
7335 }
7336
7337 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7338 while( i1 < end1 && i2 < end2 )
7339 {
7340 assert(row1->cols[i1]->index == row1colsidx[i1]);
7341 assert(row2->cols[i2]->index == row2colsidx[i2]);
7342 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7343
7344 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7345 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7346 {
7347 scalarprod += row1->vals[i1] * row2->vals[i2];
7348 ++i1;
7349 ++i2;
7350 }
7351 /* increase smallest counter */
7352 else if( row1colsidx[i1] < row2colsidx[i2] )
7353 ++i1;
7354 else
7355 ++i2;
7356 }
7357 }
7358 }
7359
7360 return scalarprod;
7361 }
7362
7363 /** returns the discrete scalar product of the coefficient vectors of the two given rows */
7364 static
7365 int SCIProwGetDiscreteScalarProduct(
7366 SCIP_ROW* row1, /**< first LP row */
7367 SCIP_ROW* row2 /**< second LP row */
7368 )
7369 {
7370 int prod;
7371 int* row1colsidx;
7372 int* row2colsidx;
7373 int i1;
7374 int i2;
7375
7376 assert(row1 != NULL);
7377 assert(row2 != NULL);
7378
7379 /* Sort the column indices of both rows.
7380 *
7381 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7382 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7383 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7384 * for both or one of the non-LP columns for both.
7385 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7386 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7387 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7388 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7389 *
7390 * We distinguish the following cases:
7391 *
7392 * 1) both rows have no unlinked columns
7393 * -> we just check the LP partitions
7394 *
7395 * 2) exactly one row is completely unlinked, the other one is completely linked
7396 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7397 * (thus all common LP columns are regarded)
7398 *
7399 * 3) we have unlinked and LP columns in both rows
7400 * -> we need to compare four partitions at once
7401 *
7402 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7403 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7404 * other row
7405 *
7406 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7407 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7408 *
7409 * 5) both rows are completely unlinked
7410 * -> we need to compare two partitions: both complete rows
7411 */
7412 SCIProwSort(row1);
7413 assert(row1->lpcolssorted);
7414 assert(row1->nonlpcolssorted);
7415 SCIProwSort(row2);
7416 assert(row2->lpcolssorted);
7417 assert(row2->nonlpcolssorted);
7418
7419 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7420 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7421
7422 row1colsidx = row1->cols_index;
7423 row2colsidx = row2->cols_index;
7424
7425 #ifndef NDEBUG
7426 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7427 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7428 {
7429 i1 = 0;
7430 i2 = row2->nlpcols;
7431 while( i1 < row1->nlpcols && i2 < row2->len )
7432 {
7433 assert(row1->cols[i1] != row2->cols[i2]);
7434 if( row1->cols[i1]->index < row2->cols[i2]->index )
7435 ++i1;
7436 else
7437 {
7438 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7439 ++i2;
7440 }
7441 }
7442 assert(i1 == row1->nlpcols || i2 == row2->len);
7443
7444 i1 = row1->nlpcols;
7445 i2 = 0;
7446 while( i1 < row1->len && i2 < row2->nlpcols )
7447 {
7448 assert(row1->cols[i1] != row2->cols[i2]);
7449 if( row1->cols[i1]->index < row2->cols[i2]->index )
7450 ++i1;
7451 else
7452 {
7453 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7454 ++i2;
7455 }
7456 }
7457 assert(i1 == row1->len || i2 == row2->nlpcols);
7458 }
7459 #endif
7460
7461 /* The "easy" cases 1) and 2) */
7462 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7463 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7464 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7465 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7466 {
7467 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7468 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7469
7470 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7471 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7472 */
7473 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7474 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7475 prod = 0;
7476
7477 /* calculate the scalar product */
7478 while( i1 >= 0 && i2 >= 0 )
7479 {
7480 assert(row1->cols[i1]->index == row1colsidx[i1]);
7481 assert(row2->cols[i2]->index == row2colsidx[i2]);
7482 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7483 if( row1colsidx[i1] < row2colsidx[i2] )
7484 --i2;
7485 else if( row1colsidx[i1] > row2colsidx[i2] )
7486 --i1;
7487 else
7488 {
7489 ++prod;
7490 --i1;
7491 --i2;
7492 }
7493 }
7494 }
7495 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7496 else
7497 {
7498 SCIP_Bool lpcols;
7499 int ilp1;
7500 int inlp1;
7501 int ilp2;
7502 int inlp2;
7503 int end1;
7504 int end2;
7505
7506 prod = 0;
7507 ilp1 = 0;
7508 ilp2 = 0;
7509
7510 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7511 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7512 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7513
7514 /* handle the case of four partitions (case 3) until one partition is finished;
7515 * cases 4a), 4b), and 5) will fail the while-condition
7516 */
7517 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7518 {
7519 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7520 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7521 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7522 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7523 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7524 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7525 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7526 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7527
7528 /* rows have the same linked LP columns */
7529 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7530 {
7531 ++prod;
7532 ++ilp1;
7533 ++ilp2;
7534 }
7535 /* LP column of row1 is the same as unlinked column of row2 */
7536 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7537 {
7538 ++prod;
7539 ++ilp1;
7540 ++inlp2;
7541 }
7542 /* unlinked column of row1 is the same as LP column of row2 */
7543 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7544 {
7545 ++prod;
7546 ++inlp1;
7547 ++ilp2;
7548 }
7549 /* two unlinked LP columns are the same */
7550 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7551 {
7552 ++prod;
7553 ++inlp1;
7554 ++inlp2;
7555 }
7556 /* increase smallest counter */
7557 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7558 {
7559 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7560 {
7561 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7562 ++ilp1;
7563 else
7564 ++ilp2;
7565 }
7566 else
7567 {
7568 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7569 ++ilp1;
7570 else
7571 ++inlp2;
7572 }
7573 }
7574 else
7575 {
7576 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7577 {
7578 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7579 ++inlp1;
7580 else
7581 ++ilp2;
7582 }
7583 else
7584 {
7585 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7586 ++inlp1;
7587 else
7588 ++inlp2;
7589 }
7590 }
7591 }
7592
7593 /* One partition was completely handled, we just have to handle the three remaining partitions:
7594 * the remaining partition of this row and the two partitions of the other row.
7595 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7596 */
7597 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7598 {
7599 int tmpilp;
7600 int tmpinlp;
7601
7602 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7603
7604 SCIPswapPointers((void**) &row1, (void**) &row2);
7605 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7606 tmpilp = ilp1;
7607 tmpinlp = inlp1;
7608 ilp1 = ilp2;
7609 inlp1 = inlp2;
7610 ilp2 = tmpilp;
7611 inlp2 = tmpinlp;
7612 }
7613
7614 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7615 * -> this merges cases 4a) and 4b)
7616 */
7617 if( ilp1 == row1->nlpcols )
7618 {
7619 i1 = inlp1;
7620 end1 = row1->len;
7621 lpcols = FALSE;
7622 }
7623 else
7624 {
7625 assert(inlp1 == row1->len);
7626
7627 i1 = ilp1;
7628 end1 = row1->nlpcols;
7629 lpcols = TRUE;
7630 }
7631
7632 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7633 * case 5) will fail the while-condition
7634 */
7635 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7636 {
7637 assert(row1->cols[i1]->index == row1colsidx[i1]);
7638 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7639 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7640 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7641 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7642
7643 /* current column in row 1 is the same as the current LP column in row 2 */
7644 if( row1colsidx[i1] == row2colsidx[ilp2] )
7645 {
7646 ++prod;
7647 ++i1;
7648 ++ilp2;
7649 }
7650 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7651 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7652 {
7653 ++prod;
7654 ++i1;
7655 ++inlp2;
7656 }
7657 /* increase smallest counter */
7658 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7659 {
7660 if( row1colsidx[i1] < row2colsidx[ilp2] )
7661 ++i1;
7662 else
7663 ++ilp2;
7664 }
7665 else
7666 {
7667 if( row1colsidx[i1] < row2colsidx[inlp2] )
7668 ++i1;
7669 else
7670 ++inlp2;
7671 }
7672 }
7673
7674 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7675 * the two rows
7676 */
7677 if( i1 < end1 )
7678 {
7679 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7680 if( ilp2 == row2->nlpcols )
7681 {
7682 i2 = inlp2;
7683 end2 = row2->len;
7684 lpcols = FALSE;
7685 }
7686 else
7687 {
7688 assert(inlp2 == row2->len);
7689
7690 i2 = ilp2;
7691 end2 = row2->nlpcols;
7692 }
7693
7694 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7695 while( i1 < end1 && i2 < end2 )
7696 {
7697 assert(row1->cols[i1]->index == row1colsidx[i1]);
7698 assert(row2->cols[i2]->index == row2colsidx[i2]);
7699 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7700
7701 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7702 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7703 {
7704 ++prod;
7705 ++i1;
7706 ++i2;
7707 }
7708 /* increase smallest counter */
7709 else if( row1colsidx[i1] < row2colsidx[i2] )
7710 ++i1;
7711 else
7712 ++i2;
7713 }
7714 }
7715 }
7716
7717 return prod;
7718 }
7719
7720 /** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7721 * p = |v*w|/(|v|*|w|);
7722 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7723 */
7724 SCIP_Real SCIProwGetParallelism(
7725 SCIP_ROW* row1, /**< first LP row */
7726 SCIP_ROW* row2, /**< second LP row */
7727 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7728 )
7729 {
7730 SCIP_Real parallelism;
7731 SCIP_Real scalarprod;
7732
7733 switch( orthofunc )
7734 {
7735 case 'e':
7736 scalarprod = SCIProwGetScalarProduct(row1, row2);
7737 if( scalarprod == 0.0 )
7738 {
7739 parallelism = 0.0;
7740 break;
7741 }
7742
7743 if( SCIProwGetNorm(row1) == 0.0 )
7744 {
7745 /* In theory, this should not happen if the scalarproduct is not zero
7746 * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7747 * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7748 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7749 */
7750 int i;
7751 for( i = 0; i < row1->len; ++i )
7752 if( row1->cols[i]->lppos >= 0 )
7753 row1->sqrnorm += SQR(row1->vals[i]);
7754 assert(SCIProwGetNorm(row1) != 0.0);
7755 }
7756
7757 if( SCIProwGetNorm(row2) == 0.0 )
7758 {
7759 /* same as for row1 above: reeval norms if it is 0, which is wrong */
7760 int i;
7761 for( i = 0; i < row2->len; ++i )
7762 if( row2->cols[i]->lppos >= 0 )
7763 row2->sqrnorm += SQR(row2->vals[i]);
7764 assert(SCIProwGetNorm(row2) != 0.0);
7765 }
7766
7767 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7768 break;
7769
7770 case 'd':
7771 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7772 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7773 break;
7774
7775 default:
7776 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7777 SCIPABORT();
7778 parallelism = 0.0; /*lint !e527*/
7779 }
7780
7781 return parallelism;
7782 }
7783
7784 /** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7785 * o = 1 - |v*w|/(|v|*|w|);
7786 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7787 */
7788 SCIP_Real SCIProwGetOrthogonality(
7789 SCIP_ROW* row1, /**< first LP row */
7790 SCIP_ROW* row2, /**< second LP row */
7791 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7792 )
7793 {
7794 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7795 }
7796
7797 /** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7798 * function, if the value is 0, it is orthogonal to the objective function
7799 */
7800 SCIP_Real SCIProwGetObjParallelism(
7801 SCIP_ROW* row, /**< LP row */
7802 SCIP_SET* set, /**< global SCIP settings */
7803 SCIP_LP* lp /**< current LP data */
7804 )
7805 {
7806 SCIP_Real prod;
7807 SCIP_Real parallelism;
7808
7809 assert(row != NULL);
7810 assert(lp != NULL);
7811
7812 if( lp->objsqrnormunreliable )
7813 SCIPlpRecalculateObjSqrNorm(set, lp);
7814
7815 assert(!lp->objsqrnormunreliable);
7816 assert(lp->objsqrnorm >= 0.0);
7817
7818 checkRowSqrnorm(row);
7819 checkRowObjprod(row);
7820
7821 prod = row->sqrnorm * lp->objsqrnorm;
7822
7823 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / SQRT(prod) : 0.0;
7824 assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7825 assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7826 parallelism = MIN(parallelism, 1.0);
7827 parallelism = MAX(parallelism, 0.0);
7828
7829 return parallelism;
7830 }
7831
7832 /** includes event handler with given data in row's event filter */
7833 SCIP_RETCODE SCIProwCatchEvent(
7834 SCIP_ROW* row, /**< row */
7835 BMS_BLKMEM* blkmem, /**< block memory */
7836 SCIP_SET* set, /**< global SCIP settings */
7837 SCIP_EVENTTYPE eventtype, /**< event type to catch */
7838 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7839 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7840 int* filterpos /**< pointer to store position of event filter entry, or NULL */
7841 )
7842 {
7843 assert(row != NULL);
7844 assert(row->eventfilter != NULL);
7845 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7846 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7847
7848 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7849 eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7850
7851 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7852
7853 return SCIP_OKAY;
7854 }
7855
7856 /** deletes event handler with given data from row's event filter */
7857 SCIP_RETCODE SCIProwDropEvent(
7858 SCIP_ROW* row, /**< row */
7859 BMS_BLKMEM* blkmem, /**< block memory */
7860 SCIP_SET* set, /**< global SCIP settings */
7861 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7862 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7863 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7864 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7865 )
7866 {
7867 assert(row != NULL);
7868 assert(row->eventfilter != NULL);
7869
7870 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7871
7872 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7873
7874 return SCIP_OKAY;
7875 }
7876
7877 /** marks a row to be not removable from the LP in the current node because it became obsolete */
7878 void SCIProwMarkNotRemovableLocal(
7879 SCIP_ROW* row, /**< LP row */
7880 SCIP_STAT* stat /**< problem statistics */
7881 )
7882 {
7883 assert(row != NULL);
7884 assert(stat != NULL);
7885 assert(stat->nnodes > 0);
7886
7887 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7888 row->obsoletenode = stat->nnodes;
7889 }
7890
7891 /*
7892 * LP solver data update
7893 */
7894
7895 /** resets column data to represent a column not in the LP solver */
7896 static
7897 void markColDeleted(
7898 SCIP_COL* col /**< column to be marked deleted */
7899 )
7900 {
7901 assert(col != NULL);
7902
7903 col->lpipos = -1;
7904 col->primsol = 0.0;
7905 col->redcost = SCIP_INVALID;
7906 col->farkascoef = SCIP_INVALID;
7907 col->sbdown = SCIP_INVALID;
7908 col->sbup = SCIP_INVALID;
7909 col->sbdownvalid = FALSE;
7910 col->sbupvalid = FALSE;
7911 col->validredcostlp = -1;
7912 col->validfarkaslp = -1;
7913 col->sbitlim = -1;
7914 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7915 }
7916
7917 /** applies all cached column removals to the LP solver */
7918 static
7919 SCIP_RETCODE lpFlushDelCols(
7920 SCIP_LP* lp /**< current LP data */
7921 )
7922 {
7923 assert(lp != NULL);
7924 assert(lp->lpifirstchgcol <= lp->nlpicols);
7925 assert(lp->lpifirstchgcol <= lp->ncols);
7926
7927 /* find the first column to change */
7928 while( lp->lpifirstchgcol < lp->nlpicols
7929 && lp->lpifirstchgcol < lp->ncols
7930 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7931 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7932 {
7933 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7934 lp->lpifirstchgcol++;
7935 }
7936
7937 /* shrink LP to the part which didn't change */
7938 if( lp->lpifirstchgcol < lp->nlpicols )
7939 {
7940 int i;
7941
7942 assert(!lp->diving);
7943 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7944 SCIP_CALL( SCIPlpiDelCols(lp->lpi, lp->lpifirstchgcol, lp->nlpicols-1) );
7945 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7946 {
7947 markColDeleted(lp->lpicols[i]);
7948 }
7949 lp->nlpicols = lp->lpifirstchgcol;
7950 lp->flushdeletedcols = TRUE;
7951 lp->updateintegrality = TRUE;
7952
7953 /* mark the LP unsolved */
7954 lp->solved = FALSE;
7955 lp->primalfeasible = FALSE;
7956 lp->primalchecked = FALSE;
7957 lp->lpobjval = SCIP_INVALID;
7958 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
7959 }
7960 assert(lp->nlpicols == lp->lpifirstchgcol);
7961
7962 return SCIP_OKAY;
7963 }
7964
7965 /** computes for the given column the lower and upper bound that should be flushed into the LP
7966 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7967 * the bounds are explicitly added to the LP in any case
7968 */
7969 static
7970 void computeLPBounds(
7971 SCIP_LP* lp, /**< current LP data */
7972 SCIP_SET* set, /**< global SCIP settings */
7973 SCIP_COL* col, /**< column to compute bounds for */
7974 SCIP_Real lpiinf, /**< infinity value if the LP solver */
7975 SCIP_Real* lb, /**< pointer to store the new lower bound */
7976 SCIP_Real* ub /**< pointer to store the new upper bound */
7977 )
7978 {
7979 assert(lp != NULL);
7980 assert(set != NULL);
7981 assert(col != NULL);
7982 assert(lb != NULL);
7983 assert(ub != NULL);
7984
7985 /* get the correct new lower bound:
7986 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7987 * if we are in diving mode, ignore lazy bounds and always take the lower bound
7988 */
7989 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7990 (*lb) = -lpiinf;
7991 else
7992 (*lb) = col->lb;
7993 /* get the correct new upper bound:
7994 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7995 * if we are in diving mode, ignore lazy bounds and always take the upper bound
7996 */
7997 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7998 (*ub) = lpiinf;
7999 else
8000 (*ub) = col->ub;
8001 }
8002
8003 /** applies all cached column additions to the LP solver */
8004 static
8005 SCIP_RETCODE lpFlushAddCols(
8006 SCIP_LP* lp, /**< current LP data */
8007 BMS_BLKMEM* blkmem, /**< block memory */
8008 SCIP_SET* set, /**< global SCIP settings */
8009 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8010 )
8011 {
8012 SCIP_Real* obj;
8013 SCIP_Real* lb;
8014 SCIP_Real* ub;
8015 int* beg;
8016 int* ind;
8017 SCIP_Real* val;
8018 char** name;
8019 SCIP_COL* col;
8020 SCIP_Real lpiinf;
8021 int c;
8022 int pos;
8023 int nnonz;
8024 int naddcols;
8025 int naddcoefs;
8026 int i;
8027 int lpipos;
8028
8029 assert(lp != NULL);
8030 assert(lp->lpifirstchgcol == lp->nlpicols);
8031 assert(blkmem != NULL);
8032 assert(set != NULL);
8033
8034 /* if there are no columns to add, we are ready */
8035 if( lp->ncols == lp->nlpicols )
8036 return SCIP_OKAY;
8037
8038 /* add the additional columns */
8039 assert(!lp->diving);
8040 assert(lp->ncols > lp->nlpicols);
8041 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8042
8043 /* get the solver's infinity value */
8044 lpiinf = SCIPlpiInfinity(lp->lpi);
8045
8046 /* count the (maximal) number of added coefficients, calculate the number of added columns */
8047 naddcols = lp->ncols - lp->nlpicols;
8048 naddcoefs = 0;
8049 for( c = lp->nlpicols; c < lp->ncols; ++c )
8050 naddcoefs += lp->cols[c]->len;
8051 assert(naddcols > 0);
8052
8053 /* get temporary memory for changes */
8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8057 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8058 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8059 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8060 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8061
8062 /* fill temporary memory with column data */
8063 nnonz = 0;
8064 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8065 {
8066 col = lp->cols[c];
8067 assert(col != NULL);
8068 assert(col->var != NULL);
8069 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8070 assert(SCIPvarGetCol(col->var) == col);
8071 assert(col->lppos == c);
8072 assert(nnonz + col->nlprows <= naddcoefs);
8073
8074 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8075 debugColPrint(set, col);
8076
8077 /* Because the column becomes a member of the LP solver, it now can take values
8078 * different from zero. That means, we have to include the column in the corresponding
8079 * row vectors.
8080 */
8081 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8082
8083 lp->lpicols[c] = col;
8084 col->lpipos = c;
8085 col->primsol = SCIP_INVALID;
8086 col->redcost = SCIP_INVALID;
8087 col->farkascoef = SCIP_INVALID;
8088 col->sbdown = SCIP_INVALID;
8089 col->sbup = SCIP_INVALID;
8090 col->sbdownvalid = FALSE;
8091 col->sbupvalid = FALSE;
8092 col->validredcostlp = -1;
8093 col->validfarkaslp = -1;
8094 col->sbitlim = -1;
8095 col->objchanged = FALSE;
8096 col->lbchanged = FALSE;
8097 col->ubchanged = FALSE;
8098 col->coefchanged = FALSE;
8099 obj[pos] = col->obj;
8100
8101 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8102 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8103
8104 beg[pos] = nnonz;
8105 name[pos] = (char*)SCIPvarGetName(col->var);
8106
8107 col->flushedobj = obj[pos];
8108 col->flushedlb = lb[pos];
8109 col->flushedub = ub[pos];
8110
8111 for( i = 0; i < col->nlprows; ++i )
8112 {
8113 assert(col->rows[i] != NULL);
8114 lpipos = col->rows[i]->lpipos;
8115 if( lpipos >= 0 )
8116 {
8117 assert(lpipos < lp->nrows);
8118 assert(nnonz < naddcoefs);
8119 ind[nnonz] = lpipos;
8120 val[nnonz] = col->vals[i];
8121 nnonz++;
8122 }
8123 }
8124 #ifndef NDEBUG
8125 for( i = col->nlprows; i < col->len; ++i )
8126 {
8127 assert(col->rows[i] != NULL);
8128 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8129 }
8130 #endif
8131 }
8132
8133 /* call LP interface */
8134 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8135 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8136 lp->nlpicols = lp->ncols;
8137 lp->lpifirstchgcol = lp->nlpicols;
8138
8139 /* free temporary memory */
8140 SCIPsetFreeBufferArray(set, &name);
8141 SCIPsetFreeBufferArray(set, &val);
8142 SCIPsetFreeBufferArray(set, &ind);
8143 SCIPsetFreeBufferArray(set, &beg);
8144 SCIPsetFreeBufferArray(set, &ub);
8145 SCIPsetFreeBufferArray(set, &lb);
8146 SCIPsetFreeBufferArray(set, &obj);
8147
8148 lp->flushaddedcols = TRUE;
8149 lp->updateintegrality = TRUE;
8150
8151 /* mark the LP unsolved */
8152 lp->solved = FALSE;
8153 lp->dualfeasible = FALSE;
8154 lp->dualchecked = FALSE;
8155 lp->lpobjval = SCIP_INVALID;
8156 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8157
8158 return SCIP_OKAY;
8159 }
8160
8161 /** resets row data to represent a row not in the LP solver */
8162 static
8163 void markRowDeleted(
8164 SCIP_ROW* row /**< row to be marked deleted */
8165 )
8166 {
8167 assert(row != NULL);
8168
8169 row->lpipos = -1;
8170 row->dualsol = 0.0;
8171 row->activity = SCIP_INVALID;
8172 row->dualfarkas = 0.0;
8173 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8174 row->validactivitylp = -1;
8175 }
8176
8177 /** applies all cached row removals to the LP solver */
8178 static
8179 SCIP_RETCODE lpFlushDelRows(
8180 SCIP_LP* lp, /**< current LP data */
8181 BMS_BLKMEM* blkmem, /**< block memory */
8182 SCIP_SET* set /**< global SCIP settings */
8183 )
8184 {
8185 assert(lp != NULL);
8186 assert(lp->lpifirstchgrow <= lp->nlpirows);
8187 assert(lp->lpifirstchgrow <= lp->nrows);
8188
8189 /* find the first row to change */
8190 while( lp->lpifirstchgrow < lp->nlpirows
8191 && lp->lpifirstchgrow < lp->nrows
8192 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8193 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8194 {
8195 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8196 lp->lpifirstchgrow++;
8197 }
8198
8199 /* shrink LP to the part which didn't change */
8200 if( lp->lpifirstchgrow < lp->nlpirows )
8201 {
8202 int i;
8203
8204 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8205 SCIP_CALL( SCIPlpiDelRows(lp->lpi, lp->lpifirstchgrow, lp->nlpirows-1) );
8206 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8207 {
8208 markRowDeleted(lp->lpirows[i]);
8209 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8210 }
8211 lp->nlpirows = lp->lpifirstchgrow;
8212 lp->flushdeletedrows = TRUE;
8213
8214 /* mark the LP unsolved */
8215 lp->solved = FALSE;
8216 lp->dualfeasible = FALSE;
8217 lp->dualchecked = FALSE;
8218 lp->lpobjval = SCIP_INVALID;
8219 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8220 }
8221 assert(lp->nlpirows == lp->lpifirstchgrow);
8222
8223 return SCIP_OKAY;
8224 }
8225
8226 /** applies all cached row additions and removals to the LP solver */
8227 static
8228 SCIP_RETCODE lpFlushAddRows(
8229 SCIP_LP* lp, /**< current LP data */
8230 BMS_BLKMEM* blkmem, /**< block memory */
8231 SCIP_SET* set, /**< global SCIP settings */
8232 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8233 )
8234 {
8235 SCIP_Real* lhs;
8236 SCIP_Real* rhs;
8237 int* beg;
8238 int* ind;
8239 SCIP_Real* val;
8240 char** name;
8241 SCIP_ROW* row;
8242 SCIP_Real lpiinf;
8243 int r;
8244 int pos;
8245 int nnonz;
8246 int naddrows;
8247 int naddcoefs;
8248 int i;
8249 int lpipos;
8250
8251 assert(lp != NULL);
8252 assert(lp->lpifirstchgrow == lp->nlpirows);
8253 assert(blkmem != NULL);
8254
8255 /* if there are no rows to add, we are ready */
8256 if( lp->nrows == lp->nlpirows )
8257 return SCIP_OKAY;
8258
8259 /* add the additional rows */
8260 assert(lp->nrows > lp->nlpirows);
8261 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8262
8263 /* get the solver's infinity value */
8264 lpiinf = SCIPlpiInfinity(lp->lpi);
8265
8266 /* count the (maximal) number of added coefficients, calculate the number of added rows */
8267 naddrows = lp->nrows - lp->nlpirows;
8268 naddcoefs = 0;
8269 for( r = lp->nlpirows; r < lp->nrows; ++r )
8270 naddcoefs += lp->rows[r]->len;
8271 assert(naddrows > 0);
8272
8273 /* get temporary memory for changes */
8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8276 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8277 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8278 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8279 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8280
8281 /* fill temporary memory with row data */
8282 nnonz = 0;
8283 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8284 {
8285 row = lp->rows[r];
8286 assert(row != NULL);
8287 assert(row->lppos == r);
8288 assert(nnonz + row->nlpcols <= naddcoefs);
8289
8290 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8291 debugRowPrint(set, row);
8292
8293 /* Because the row becomes a member of the LP solver, its dual variable now can take values
8294 * different from zero. That means, we have to include the row in the corresponding
8295 * column vectors.
8296 */
8297 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8298
8299 SCIProwCapture(row);
8300 lp->lpirows[r] = row;
8301 row->lpipos = r;
8302 row->dualsol = SCIP_INVALID;
8303 row->activity = SCIP_INVALID;
8304 row->dualfarkas = SCIP_INVALID;
8305 row->validactivitylp = -1;
8306 row->lhschanged = FALSE;
8307 row->rhschanged = FALSE;
8308 row->coefchanged = FALSE;
8309 if( SCIPsetIsInfinity(set, -row->lhs) )
8310 lhs[pos] = -lpiinf;
8311 else
8312 lhs[pos] = row->lhs - row->constant;
8313 if( SCIPsetIsInfinity(set, row->rhs) )
8314 rhs[pos] = lpiinf;
8315 else
8316 rhs[pos] = row->rhs - row->constant;
8317 beg[pos] = nnonz;
8318 name[pos] = row->name;
8319
8320 row->flushedlhs = lhs[pos];
8321 row->flushedrhs = rhs[pos];
8322
8323 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8324 for( i = 0; i < row->nlpcols; ++i )
8325 {
8326 assert(row->cols[i] != NULL);
8327 lpipos = row->cols[i]->lpipos;
8328 if( lpipos >= 0 )
8329 {
8330 assert(lpipos < lp->ncols);
8331 assert(nnonz < naddcoefs);
8332 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8333 ind[nnonz] = lpipos;
8334 val[nnonz] = row->vals[i];
8335 nnonz++;
8336 }
8337 }
8338 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8339 #ifndef NDEBUG
8340 for( i = row->nlpcols; i < row->len; ++i )
8341 {
8342 assert(row->cols[i] != NULL);
8343 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8344 }
8345 #endif
8346 }
8347
8348 /* call LP interface */
8349 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8350 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8351 lp->nlpirows = lp->nrows;
8352 lp->lpifirstchgrow = lp->nlpirows;
8353
8354 /* free temporary memory */
8355 SCIPsetFreeBufferArray(set, &name);
8356 SCIPsetFreeBufferArray(set, &val);
8357 SCIPsetFreeBufferArray(set, &ind);
8358 SCIPsetFreeBufferArray(set, &beg);
8359 SCIPsetFreeBufferArray(set, &rhs);
8360 SCIPsetFreeBufferArray(set, &lhs);
8361
8362 lp->flushaddedrows = TRUE;
8363
8364 /* mark the LP unsolved */
8365 lp->solved = FALSE;
8366 lp->primalfeasible = FALSE;
8367 lp->primalchecked = FALSE;
8368 lp->lpobjval = SCIP_INVALID;
8369 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8370
8371 return SCIP_OKAY;
8372 }
8373
8374 /** applies all cached column bound and objective changes to the LP */
8375 static
8376 SCIP_RETCODE lpFlushChgCols(
8377 SCIP_LP* lp, /**< current LP data */
8378 SCIP_SET* set /**< global SCIP settings */
8379 )
8380 {
8381 #ifndef NDEBUG
8382 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8383 #endif
8384 SCIP_COL* col;
8385 int* objind;
8386 int* bdind;
8387 SCIP_Real* obj;
8388 SCIP_Real* lb;
8389 SCIP_Real* ub;
8390 SCIP_Real lpiinf;
8391 int nobjchg;
8392 int nbdchg;
8393 int i;
8394
8395 assert(lp != NULL);
8396
8397 if( lp->nchgcols == 0 )
8398 return SCIP_OKAY;
8399
8400 /* get the solver's infinity value */
8401 lpiinf = SCIPlpiInfinity(lp->lpi);
8402
8403 /* get temporary memory for changes */
8404 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8405 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, lp->ncols) );
8406 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8407 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, lp->ncols) );
8408 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, lp->ncols) );
8409
8410 /* collect all cached bound and objective changes */
8411 nobjchg = 0;
8412 nbdchg = 0;
8413 for( i = 0; i < lp->nchgcols; ++i )
8414 {
8415 col = lp->chgcols[i];
8416 assert(col != NULL);
8417 assert(col->var != NULL);
8418 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8419 assert(SCIPvarGetCol(col->var) == col);
8420
8421 if( col->lpipos >= 0 )
8422 {
8423 #ifndef NDEBUG
8424 /* do not check consistency of data with LPI in case of LPI=none */
8425 if( !lpinone )
8426 {
8427 SCIP_Real lpiobj;
8428 SCIP_Real lpilb;
8429 SCIP_Real lpiub;
8430
8431 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8432 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8433 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8434 assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb))
8435 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8436 assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub))
8437 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8438 }
8439 #endif
8440
8441 if( col->objchanged )
8442 {
8443 SCIP_Real newobj;
8444
8445 newobj = col->obj;
8446 if( col->flushedobj != newobj ) /*lint !e777*/
8447 {
8448 assert(nobjchg < lp->ncols);
8449 objind[nobjchg] = col->lpipos;
8450 obj[nobjchg] = newobj;
8451 nobjchg++;
8452 col->flushedobj = newobj;
8453 }
8454 col->objchanged = FALSE;
8455 }
8456
8457 if( col->lbchanged || col->ubchanged )
8458 {
8459 SCIP_Real newlb;
8460 SCIP_Real newub;
8461
8462 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8463 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8464
8465 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8466 {
8467 assert(nbdchg < lp->ncols);
8468 bdind[nbdchg] = col->lpipos;
8469 lb[nbdchg] = newlb;
8470 ub[nbdchg] = newub;
8471 nbdchg++;
8472 col->flushedlb = newlb;
8473 col->flushedub = newub;
8474 }
8475 col->lbchanged = FALSE;
8476 col->ubchanged = FALSE;
8477 }
8478 }
8479 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8480 }
8481
8482 /* change objective values in LP */
8483 if( nobjchg > 0 )
8484 {
8485 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8486 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8487
8488 /* mark the LP unsolved */
8489 lp->solved = FALSE;
8490 lp->dualfeasible = FALSE;
8491 lp->dualchecked = FALSE;
8492 lp->lpobjval = SCIP_INVALID;
8493 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8494 }
8495
8496 /* change bounds in LP */
8497 if( nbdchg > 0 )
8498 {
8499 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8500 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8501
8502 /* mark the LP unsolved */
8503 lp->solved = FALSE;
8504 lp->primalfeasible = FALSE;
8505 lp->primalchecked = FALSE;
8506 lp->lpobjval = SCIP_INVALID;
8507 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8508 }
8509
8510 lp->nchgcols = 0;
8511
8512 /* free temporary memory */
8513 SCIPsetFreeBufferArray(set, &ub);
8514 SCIPsetFreeBufferArray(set, &lb);
8515 SCIPsetFreeBufferArray(set, &bdind);
8516 SCIPsetFreeBufferArray(set, &obj);
8517 SCIPsetFreeBufferArray(set, &objind);
8518
8519 return SCIP_OKAY;
8520 }
8521
8522 /** applies all cached row side changes to the LP */
8523 static
8524 SCIP_RETCODE lpFlushChgRows(
8525 SCIP_LP* lp, /**< current LP data */
8526 SCIP_SET* set /**< global SCIP settings */
8527 )
8528 {
8529 #ifndef NDEBUG
8530 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8531 #endif
8532 SCIP_ROW* row;
8533 int* ind;
8534 SCIP_Real* lhs;
8535 SCIP_Real* rhs;
8536 SCIP_Real lpiinf;
8537 int i;
8538 int nchg;
8539
8540 assert(lp != NULL);
8541
8542 if( lp->nchgrows == 0 )
8543 return SCIP_OKAY;
8544
8545 /* get the solver's infinity value */
8546 lpiinf = SCIPlpiInfinity(lp->lpi);
8547
8548 /* get temporary memory for changes */
8549 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, lp->nrows) );
8550 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, lp->nrows) );
8551 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, lp->nrows) );
8552
8553 /* collect all cached left and right hand side changes */
8554 nchg = 0;
8555 for( i = 0; i < lp->nchgrows; ++i )
8556 {
8557 row = lp->chgrows[i];
8558 assert(row != NULL);
8559
8560 if( row->lpipos >= 0 )
8561 {
8562 #ifndef NDEBUG
8563 /* do not check consistency of data with LPI in case of LPI=none */
8564 if( !lpinone )
8565 {
8566 SCIP_Real lpilhs;
8567 SCIP_Real lpirhs;
8568
8569 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8570 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8571 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8572 }
8573 #endif
8574 if( row->lhschanged || row->rhschanged )
8575 {
8576 SCIP_Real newlhs;
8577 SCIP_Real newrhs;
8578
8579 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8580 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8581 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8582 {
8583 assert(nchg < lp->nrows);
8584 ind[nchg] = row->lpipos;
8585 lhs[nchg] = newlhs;
8586 rhs[nchg] = newrhs;
8587 nchg++;
8588 row->flushedlhs = newlhs;
8589 row->flushedrhs = newrhs;
8590 }
8591 row->lhschanged = FALSE;
8592 row->rhschanged = FALSE;
8593 }
8594 }
8595 }
8596
8597 /* change left and right hand sides in LP */
8598 if( nchg > 0 )
8599 {
8600 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8601 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8602
8603 /* mark the LP unsolved */
8604 lp->solved = FALSE;
8605 lp->primalfeasible = FALSE;
8606 lp->primalchecked = FALSE;
8607 lp->lpobjval = SCIP_INVALID;
8608 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8609 }
8610
8611 lp->nchgrows = 0;
8612
8613 /* free temporary memory */
8614 SCIPsetFreeBufferArray(set, &rhs);
8615 SCIPsetFreeBufferArray(set, &lhs);
8616 SCIPsetFreeBufferArray(set, &ind);
8617
8618 return SCIP_OKAY;
8619 }
8620
8621 /** copy integrality information to the LP */
8622 static
8623 SCIP_RETCODE lpCopyIntegrality(
8624 SCIP_LP* lp, /**< current LP data */
8625 SCIP_SET* set /**< global SCIP settings */
8626 )
8627 {
8628 int i;
8629 int nintegers;
8630 int* integerInfo;
8631 SCIP_VAR* var;
8632
8633 assert(lp != NULL);
8634
8635 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8636
8637 /* count total number of integralities */
8638 nintegers = 0;
8639
8640 for( i = 0; i < lp->ncols; ++i )
8641 {
8642 var = SCIPcolGetVar(lp->cols[i]);
8643 if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) )
8644 {
8645 integerInfo[i] = 1;
8646 ++nintegers;
8647 }
8648 else
8649 integerInfo[i] = 0;
8650 }
8651
8652 /* only pass integrality information if integer variables are present */
8653 if( nintegers > 0 )
8654 {
8655 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8656 }
8657 else
8658 {
8659 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, 0, NULL) );
8660 }
8661
8662 SCIPsetFreeBufferArray(set, &integerInfo);
8663
8664 /* mark integralities to be updated */
8665 lp->updateintegrality = FALSE;
8666
8667 return SCIP_OKAY;
8668 }
8669
8670 /** applies all cached changes to the LP solver */
8671 SCIP_RETCODE SCIPlpFlush(
8672 SCIP_LP* lp, /**< current LP data */
8673 BMS_BLKMEM* blkmem, /**< block memory */
8674 SCIP_SET* set, /**< global SCIP settings */
8675 SCIP_PROB* prob, /**< problem data */
8676 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8677 )
8678 {
8679 assert(lp != NULL);
8680 assert(blkmem != NULL);
8681
8682 SCIPsetDebugMsg(set, "flushing LP changes: old (%d cols, %d rows), nchgcols=%d, nchgrows=%d, firstchgcol=%d, firstchgrow=%d, new (%d cols, %d rows), flushed=%u\n",
8683 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8684
8685 if( !lp->flushed )
8686 {
8687 lp->flushdeletedcols = FALSE;
8688 lp->flushaddedcols = FALSE;
8689 lp->flushdeletedrows = FALSE;
8690 lp->flushaddedrows = FALSE;
8691
8692 SCIP_CALL( lpFlushDelCols(lp) );
8693 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8694 SCIP_CALL( lpFlushChgCols(lp, set) );
8695 SCIP_CALL( lpFlushChgRows(lp, set) );
8696 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8697 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8698
8699 lp->flushed = TRUE;
8700
8701 checkLinks(lp);
8702 }
8703
8704 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8705 * we want to re-optimize the LP even if nothing else has changed */
8706 if( lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 && ! lpCutoffDisabled(set, prob) ) /*lint !e777*/
8707 {
8708 lp->solved = FALSE;
8709 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8710 }
8711
8712 assert(lp->nlpicols == lp->ncols);
8713 assert(lp->lpifirstchgcol == lp->nlpicols);
8714 assert(lp->nlpirows == lp->nrows);
8715 assert(lp->lpifirstchgrow == lp->nlpirows);
8716 assert(lp->nchgcols == 0);
8717 assert(lp->nchgrows == 0);
8718 #ifndef NDEBUG
8719 {
8720 int ncols;
8721 int nrows;
8722
8723 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8724 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8725 assert(ncols == lp->ncols);
8726 assert(nrows == lp->nrows);
8727 }
8728 #endif
8729
8730 return SCIP_OKAY;
8731 }
8732
8733 /** marks the LP to be flushed, even if the LP thinks it is not flushed */
8734 SCIP_RETCODE SCIPlpMarkFlushed(
8735 SCIP_LP* lp, /**< current LP data */
8736 SCIP_SET* set /**< global SCIP settings */
8737 )
8738 {
8739 #ifndef NDEBUG
8740 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8741 #endif
8742 int i;
8743
8744 assert(lp != NULL);
8745
8746 #ifndef NDEBUG
8747 /* check, if there are really no column or row deletions or coefficient changes left */
8748 while( lp->lpifirstchgcol < lp->nlpicols
8749 && lp->lpifirstchgcol < lp->ncols
8750 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8751 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8752 {
8753 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8754 lp->lpifirstchgcol++;
8755 }
8756 assert(lp->nlpicols == lp->lpifirstchgcol);
8757
8758 while( lp->lpifirstchgrow < lp->nlpirows
8759 && lp->lpifirstchgrow < lp->nrows
8760 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8761 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8762 {
8763 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8764 lp->lpifirstchgrow++;
8765 }
8766 assert(lp->nlpirows == lp->lpifirstchgrow);
8767 #endif
8768
8769 lp->lpifirstchgcol = lp->nlpicols;
8770 lp->lpifirstchgrow = lp->nlpirows;
8771
8772 /* check, if there are really no column or row additions left */
8773 assert(lp->ncols == lp->nlpicols);
8774 assert(lp->nrows == lp->nlpirows);
8775
8776 /* mark the changed columns to be unchanged, and check, if this is really correct */
8777 for( i = 0; i < lp->nchgcols; ++i )
8778 {
8779 SCIP_COL* col;
8780
8781 col = lp->chgcols[i];
8782 assert(col != NULL);
8783 assert(col->var != NULL);
8784 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8785 assert(SCIPvarGetCol(col->var) == col);
8786
8787 if( col->lpipos >= 0 )
8788 {
8789 #ifndef NDEBUG
8790 /* do not check consistency of data with LPI in case of LPI=none */
8791 if( !lpinone )
8792 {
8793 SCIP_Real lpiobj;
8794 SCIP_Real lpilb;
8795 SCIP_Real lpiub;
8796
8797 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8798 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8799 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8800 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8801 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8802 assert(col->flushedobj == col->obj); /*lint !e777*/
8803 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8804 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8805 }
8806 #endif
8807 col->objchanged = FALSE;
8808 col->lbchanged = FALSE;
8809 col->ubchanged = FALSE;
8810 }
8811 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8812 }
8813 lp->nchgcols = 0;
8814
8815 /* mark the changed rows to be unchanged, and check, if this is really correct */
8816 for( i = 0; i < lp->nchgrows; ++i )
8817 {
8818 SCIP_ROW* row;
8819
8820 row = lp->chgrows[i];
8821 assert(row != NULL);
8822
8823 if( row->lpipos >= 0 )
8824 {
8825 #ifndef NDEBUG
8826 /* do not check consistency of data with LPI in case of LPI=none */
8827 if( !lpinone )
8828 {
8829 SCIP_Real lpilhs;
8830 SCIP_Real lpirhs;
8831
8832 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8833 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8834 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8835 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8836 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8837 }
8838 #endif
8839 row->lhschanged = FALSE;
8840 row->rhschanged = FALSE;
8841 }
8842 }
8843 lp->nchgrows = 0;
8844
8845 /* mark the LP to be flushed */
8846 lp->flushed = TRUE;
8847
8848 checkLinks(lp);
8849
8850 return SCIP_OKAY;
8851 }
8852
8853
8854
8855
8856 /*
8857 * LP methods
8858 */
8859
8860 /** updates link data after addition of column */
8861 static
8862 void colUpdateAddLP(
8863 SCIP_COL* col, /**< LP column */
8864 SCIP_SET* set /**< global SCIP settings */
8865 )
8866 {
8867 SCIP_ROW* row;
8868 int i;
8869 int pos;
8870
8871 assert(col != NULL);
8872 assert(col->lppos >= 0);
8873
8874 /* update column arrays of all linked rows */
8875 for( i = 0; i < col->len; ++i )
8876 {
8877 pos = col->linkpos[i];
8878 if( pos >= 0 )
8879 {
8880 row = col->rows[i];
8881 assert(row != NULL);
8882 assert(row->linkpos[pos] == i);
8883 assert(row->cols[pos] == col);
8884 assert(row->nlpcols <= pos && pos < row->len);
8885
8886 row->nlpcols++;
8887 rowSwapCoefs(row, pos, row->nlpcols-1);
8888 assert(row->cols[row->nlpcols-1] == col);
8889
8890 /* if no swap was necessary, mark lpcols to be unsorted */
8891 if( pos == row->nlpcols-1 )
8892 row->lpcolssorted = FALSE;
8893
8894 /* update norms */
8895 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8896 }
8897 }
8898 }
8899
8900 /** updates link data after addition of row */
8901 static
8902 void rowUpdateAddLP(
8903 SCIP_ROW* row /**< LP row */
8904 )
8905 {
8906 SCIP_COL* col;
8907 int i;
8908 int pos;
8909
8910 assert(row != NULL);
8911 assert(row->lppos >= 0);
8912
8913 /* update row arrays of all linked columns */
8914 for( i = 0; i < row->len; ++i )
8915 {
8916 pos = row->linkpos[i];
8917 if( pos >= 0 )
8918 {
8919 col = row->cols[i];
8920 assert(col != NULL);
8921 assert(col->linkpos[pos] == i);
8922 assert(col->rows[pos] == row);
8923 assert(col->nlprows <= pos && pos < col->len);
8924
8925 col->nlprows++;
8926 colSwapCoefs(col, pos, col->nlprows-1);
8927
8928 /* if no swap was necessary, mark lprows to be unsorted */
8929 if( pos == col->nlprows-1 )
8930 col->lprowssorted = FALSE;
8931 }
8932 }
8933 }
8934
8935 /** updates link data after removal of column */
8936 static
8937 void colUpdateDelLP(
8938 SCIP_COL* col, /**< LP column */
8939 SCIP_SET* set /**< global SCIP settings */
8940 )
8941 {
8942 SCIP_ROW* row;
8943 int i;
8944 int pos;
8945
8946 assert(col != NULL);
8947 assert(col->lppos == -1);
8948
8949 /* update column arrays of all linked rows */
8950 for( i = 0; i < col->len; ++i )
8951 {
8952 pos = col->linkpos[i];
8953 if( pos >= 0 )
8954 {
8955 row = col->rows[i];
8956 assert(row != NULL);
8957 assert(row->linkpos[pos] == i);
8958 assert(row->cols[pos] == col);
8959 assert(0 <= pos && pos < row->nlpcols);
8960
8961 /* update norms */
8962 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8963
8964 row->nlpcols--;
8965 rowSwapCoefs(row, pos, row->nlpcols);
8966
8967 /* if no swap was necessary, mark nonlpcols to be unsorted */
8968 if( pos == row->nlpcols )
8969 row->nonlpcolssorted = FALSE;
8970 }
8971 }
8972 }
8973
8974 /** updates link data after removal of row */
8975 static
8976 void rowUpdateDelLP(
8977 SCIP_ROW* row /**< LP row */
8978 )
8979 {
8980 SCIP_COL* col;
8981 int i;
8982 int pos;
8983
8984 assert(row != NULL);
8985 assert(row->lppos == -1);
8986
8987 /* update row arrays of all linked columns */
8988 for( i = 0; i < row->len; ++i )
8989 {
8990 pos = row->linkpos[i];
8991 if( pos >= 0 )
8992 {
8993 col = row->cols[i];
8994 assert(col != NULL);
8995 assert(0 <= pos && pos < col->nlprows);
8996 assert(col->linkpos[pos] == i);
8997 assert(col->rows[pos] == row);
8998
8999 col->nlprows--;
9000 colSwapCoefs(col, pos, col->nlprows);
9001
9002 /* if no swap was necessary, mark lprows to be unsorted */
9003 if( pos == col->nlprows )
9004 col->nonlprowssorted = FALSE;
9005 }
9006 }
9007 }
9008
9009 static
9010 SCIP_RETCODE allocDiveChgSideArrays(
9011 SCIP_LP* lp, /**< LP data object */
9012 int initsize /**< initial size of the arrays */
9013 )
9014 {
9015 assert(lp != NULL);
9016 assert(lp->divechgsides == NULL);
9017 assert(lp->divechgsidetypes == NULL);
9018 assert(lp->divechgrows == NULL);
9019 assert(lp->ndivechgsides == 0);
9020 assert(lp->divechgsidessize == 0);
9021 assert(initsize > 0);
9022
9023 lp->divechgsidessize = initsize;
9024 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) );
9025 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) );
9026 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) );
9027
9028 return SCIP_OKAY;
9029 }
9030
9031 static
9032 SCIP_RETCODE reallocDiveChgSideArrays(
9033 SCIP_LP* lp, /**< LP data object */
9034 int minsize, /**< minimal number of elements */
9035 SCIP_Real growfact /**< growing factor */
9036 )
9037 {
9038 assert(lp != NULL);
9039 assert(lp->divechgsides != NULL);
9040 assert(lp->divechgsidetypes != NULL);
9041 assert(lp->divechgrows != NULL);
9042 assert(lp->ndivechgsides > 0);
9043 assert(lp->divechgsidessize > 0);
9044 assert(minsize > 0);
9045
9046 if( minsize <= lp->divechgsidessize )
9047 return SCIP_OKAY;
9048
9049 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9050 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) );
9051 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) );
9052 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) );
9053
9054 return SCIP_OKAY;
9055 }
9056
9057 static
9058 void freeDiveChgSideArrays(
9059 SCIP_LP* lp /**< LP data object */
9060 )
9061 {
9062 assert(lp != NULL);
9063 assert(lp->divechgsides != NULL);
9064 assert(lp->divechgsidetypes != NULL);
9065 assert(lp->divechgrows != NULL);
9066 assert(lp->ndivechgsides == 0);
9067 assert(lp->divechgsidessize > 0);
9068
9069 BMSfreeMemoryArrayNull(&lp->divechgsides);
9070 BMSfreeMemoryArrayNull(&lp->divechgsidetypes);
9071 BMSfreeMemoryArrayNull(&lp->divechgrows);
9072 lp->divechgsidessize = 0;
9073 }
9074
9075 #define DIVESTACKINITSIZE 100
9076
9077 /** creates empty LP data object */
9078 SCIP_RETCODE SCIPlpCreate(
9079 SCIP_LP** lp, /**< pointer to LP data object */
9080 SCIP_SET* set, /**< global SCIP settings */
9081 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
9082 SCIP_STAT* stat, /**< problem statistics */
9083 const char* name /**< problem name */
9084 )
9085 {
9086 SCIP_Bool success;
9087
9088 assert(lp != NULL);
9089 assert(set != NULL);
9090 assert(stat != NULL);
9091 assert(name != NULL);
9092
9093 SCIP_ALLOC( BMSallocMemory(lp) );
9094
9095 /* open LP Solver interface */
9096 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9097
9098 (*lp)->lpicols = NULL;
9099 (*lp)->lpirows = NULL;
9100 (*lp)->chgcols = NULL;
9101 (*lp)->chgrows = NULL;
9102 (*lp)->cols = NULL;
9103 (*lp)->soldirection = NULL;
9104 (*lp)->lazycols = NULL;
9105 (*lp)->rows = NULL;
9106 (*lp)->lpobjval = 0.0;
9107 (*lp)->glbpseudoobjval = 0.0;
9108 (*lp)->relglbpseudoobjval = 0.0;
9109 (*lp)->glbpseudoobjvalid = TRUE;
9110 (*lp)->glbpseudoobjvalinf = 0;
9111 (*lp)->pseudoobjval = 0.0;
9112 (*lp)->relpseudoobjval = 0.0;
9113 (*lp)->pseudoobjvalid = TRUE;
9114 (*lp)->pseudoobjvalinf = 0;
9115 (*lp)->looseobjval = 0.0;
9116 (*lp)->rellooseobjval = 0.0;
9117 (*lp)->looseobjvalid = TRUE;
9118 (*lp)->looseobjvalinf = 0;
9119 (*lp)->nloosevars = 0;
9120 (*lp)->rootlpobjval = SCIP_INVALID;
9121 (*lp)->rootlooseobjval = SCIP_INVALID;
9122 (*lp)->cutoffbound = SCIPsetInfinity(set);
9123 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9124 SCIPlpResetFeastol(*lp, set);
9125 (*lp)->validdegeneracylp = -1;
9126 (*lp)->objsqrnorm = 0.0;
9127 (*lp)->objsumnorm = 0.0;
9128 (*lp)->lpicolssize = 0;
9129 (*lp)->nlpicols = 0;
9130 (*lp)->lpirowssize = 0;
9131 (*lp)->nlpirows = 0;
9132 (*lp)->lpifirstchgcol = 0;
9133 (*lp)->lpifirstchgrow = 0;
9134 (*lp)->colssize = 0;
9135 (*lp)->soldirectionsize = 0;
9136 (*lp)->ncols = 0;
9137 (*lp)->lazycolssize = 0;
9138 (*lp)->nlazycols = 0;
9139 (*lp)->rowssize = 0;
9140 (*lp)->nrows = 0;
9141 (*lp)->chgcolssize = 0;
9142 (*lp)->nchgcols = 0;
9143 (*lp)->chgrowssize = 0;
9144 (*lp)->nchgrows = 0;
9145 (*lp)->firstnewcol = 0;
9146 (*lp)->firstnewrow = 0;
9147 (*lp)->nremovablecols = 0;
9148 (*lp)->nremovablerows = 0;
9149 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9150 (*lp)->validfarkaslp = -1;
9151 (*lp)->validsoldirlp = -1;
9152 (*lp)->validsoldirsol = NULL;
9153 (*lp)->objsqrnormunreliable = FALSE;
9154 (*lp)->flushdeletedcols = FALSE;
9155 (*lp)->flushaddedcols = FALSE;
9156 (*lp)->flushdeletedrows = FALSE;
9157 (*lp)->flushaddedrows = FALSE;
9158 (*lp)->updateintegrality = TRUE;
9159 (*lp)->flushed = TRUE;
9160 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9161 (*lp)->solved = TRUE;
9162 (*lp)->primalfeasible = TRUE;
9163 (*lp)->primalchecked = TRUE;
9164 (*lp)->dualfeasible = TRUE;
9165 (*lp)->dualchecked = TRUE;
9166 (*lp)->solisbasic = FALSE;
9167 (*lp)->rootlpisrelax = TRUE;
9168 (*lp)->isrelax = TRUE;
9169 (*lp)->installing = FALSE;
9170 (*lp)->strongbranching = FALSE;
9171 (*lp)->strongbranchprobing = FALSE;
9172 (*lp)->probing = FALSE;
9173 (*lp)->diving = FALSE;
9174 (*lp)->divingobjchg = FALSE;
9175 (*lp)->divinglazyapplied = FALSE;
9176 (*lp)->divelpistate = NULL;
9177 (*lp)->divelpwasprimfeas = TRUE;
9178 (*lp)->divelpwasprimchecked = TRUE;
9179 (*lp)->divelpwasdualfeas = TRUE;
9180 (*lp)->divelpwasdualchecked = TRUE;
9181 (*lp)->divechgsides = NULL;
9182 (*lp)->divechgsidetypes = NULL;
9183 (*lp)->divechgrows = NULL;
9184 (*lp)->ndivechgsides = 0;
9185 (*lp)->divechgsidessize = 0;
9186 (*lp)->ndivingrows = 0;
9187 (*lp)->divinglpiitlim = INT_MAX;
9188 (*lp)->resolvelperror = FALSE;
9189 (*lp)->divenolddomchgs = 0;
9190 (*lp)->adjustlpval = FALSE;
9191 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9192 (*lp)->lpifeastol = (*lp)->feastol;
9193 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9194 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9195 (*lp)->lpifromscratch = FALSE;
9196 (*lp)->lpifastmip = set->lp_fastmip;
9197 (*lp)->lpiscaling = set->lp_scaling;
9198 (*lp)->lpipresolving = set->lp_presolving;
9199 (*lp)->lpilpinfo = set->disp_lpinfo;
9200 (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9201 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9202 (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9203 (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9204 (*lp)->lpimarkowitz = set->lp_markowitz;
9205 (*lp)->lpiitlim = INT_MAX;
9206 (*lp)->lpipricing = SCIP_PRICING_AUTO;
9207 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9208 (*lp)->lpithreads = set->lp_threads;
9209 (*lp)->lpitiming = (int) set->time_clocktype;
9210 (*lp)->lpirandomseed = set->random_randomseed;
9211 (*lp)->storedsolvals = NULL;
9212
9213 /* allocate arrays for diving */
9214 SCIP_CALL( allocDiveChgSideArrays(*lp, DIVESTACKINITSIZE) );
9215
9216 /* set default parameters in LP solver */
9217 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9218 if( !success )
9219 {
9220 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9221 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9222 SCIPlpiGetSolverName());
9223 }
9224 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9225 (*lp)->lpihasfeastol = success;
9226 if( !success )
9227 {
9228 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9229 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9230 SCIPlpiGetSolverName());
9231 }
9232 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9233 (*lp)->lpihasdualfeastol = success;
9234 if( !success )
9235 {
9236 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9237 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9238 SCIPlpiGetSolverName());
9239 }
9240 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9241 (*lp)->lpihasbarrierconvtol = success;
9242 if( !success )
9243 {
9244 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9245 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9246 SCIPlpiGetSolverName());
9247 }
9248 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9249 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9250 (*lp)->lpihasfastmip = success;
9251 if( !success )
9252 {
9253 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9254 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9255 SCIPlpiGetSolverName());
9256 }
9257 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9258 (*lp)->lpihasscaling = success;
9259 if( !success )
9260 {
9261 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9262 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9263 SCIPlpiGetSolverName());
9264 }
9265 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9266 (*lp)->lpihaspresolving = success;
9267 if( !success )
9268 {
9269 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9270 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9271 SCIPlpiGetSolverName());
9272 }
9273 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9274 if( !success )
9275 {
9276 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9277 "LP Solver <%s>: clock type cannot be set\n",
9278 SCIPlpiGetSolverName());
9279 }
9280 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9281 if( !success )
9282 {
9283 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9284 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9285 SCIPlpiGetSolverName());
9286 }
9287 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9288 if( !success )
9289 {
9290 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9291 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9292 SCIPlpiGetSolverName());
9293 }
9294 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9295 if( !success )
9296 {
9297 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9298 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9299 SCIPlpiGetSolverName());
9300 }
9301 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9302 (*lp)->lpihasrowrep = success;
9303 if( !success )
9304 {
9305 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9306 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9307 SCIPlpiGetSolverName());
9308 }
9309 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9310 (*lp)->lpihaspolishing = success;
9311 if( !success )
9312 {
9313 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9314 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9315 SCIPlpiGetSolverName());
9316 }
9317 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9318 (*lp)->lpihasrefactor = success;
9319 if( !success )
9320 {
9321 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9322 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9323 SCIPlpiGetSolverName());
9324 }
9325 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9326 if( !success )
9327 {
9328 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9329 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9330 SCIPlpiGetSolverName());
9331 }
9332 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9333 if( !success )
9334 {
9335 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9336 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9337 SCIPlpiGetSolverName());
9338 }
9339 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9340 if( !success )
9341 {
9342 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9343 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9344 SCIPlpiGetSolverName());
9345 }
9346 /* keep the default LP random seed if this parameter is set to 0 (current default) */
9347 if( (*lp)->lpirandomseed != 0 )
9348 {
9349 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9350 if( !success )
9351 {
9352 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9353 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9354 SCIPlpiGetSolverName());
9355 }
9356 }
9357
9358 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9359 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9360 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9361 {
9362 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9363 return SCIP_PARAMETERWRONGVAL;
9364 }
9365
9366 return SCIP_OKAY;
9367 }
9368
9369 /** frees LP data object */
9370 SCIP_RETCODE SCIPlpFree(
9371 SCIP_LP** lp, /**< pointer to LP data object */
9372 BMS_BLKMEM* blkmem, /**< block memory */
9373 SCIP_SET* set, /**< global SCIP settings */
9374 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9375 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9376 )
9377 {
9378 int i;
9379
9380 assert(lp != NULL);
9381 assert(*lp != NULL);
9382
9383 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9384
9385 freeDiveChgSideArrays(*lp);
9386
9387 /* release LPI rows */
9388 for( i = 0; i < (*lp)->nlpirows; ++i )
9389 {
9390 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9391 }
9392
9393 if( (*lp)->lpi != NULL )
9394 {
9395 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9396 }
9397
9398 BMSfreeMemoryNull(&(*lp)->storedsolvals);
9399 BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9400 BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9401 BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9402 BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9403 BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9404 BMSfreeMemoryArrayNull(&(*lp)->cols);
9405 BMSfreeMemoryArrayNull(&(*lp)->rows);
9406 BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9407 BMSfreeMemory(lp);
9408
9409 return SCIP_OKAY;
9410 }
9411
9412 /** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9413 * changes to the LP solver
9414 */
9415 SCIP_RETCODE SCIPlpReset(
9416 SCIP_LP* lp, /**< LP data */
9417 BMS_BLKMEM* blkmem, /**< block memory */
9418 SCIP_SET* set, /**< global SCIP settings */
9419 SCIP_PROB* prob, /**< problem data */
9420 SCIP_STAT* stat, /**< problem statistics */
9421 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9422 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9423 )
9424 {
9425 assert(stat != NULL);
9426
9427 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9428 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9429
9430 /* mark the empty LP to be solved */
9431 lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9432 lp->lpobjval = 0.0;
9433 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9434 lp->validfarkaslp = -1;
9435 lp->validdegeneracylp = -1;
9436 lp->validsoldirlp = -1;
9437 lp->validsoldirsol = NULL;
9438 lp->solved = TRUE;
9439 lp->primalfeasible = TRUE;
9440 lp->primalchecked = TRUE;
9441 lp->dualfeasible = TRUE;
9442 lp->dualchecked = TRUE;
9443 lp->solisbasic = FALSE;
9444 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9445
9446 return SCIP_OKAY;
9447 }
9448
9449 /** adds a column to the LP */
9450 SCIP_RETCODE SCIPlpAddCol(
9451 SCIP_LP* lp, /**< LP data */
9452 SCIP_SET* set, /**< global SCIP settings */
9453 SCIP_COL* col, /**< LP column */
9454 int depth /**< depth in the tree where the column addition is performed */
9455 )
9456 {
9457 assert(lp != NULL);
9458 assert(!lp->diving);
9459 assert(col != NULL);
9460 assert(col->len == 0 || col->rows != NULL);
9461 assert(col->lppos == -1);
9462 assert(col->var != NULL);
9463 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9464 assert(SCIPvarGetCol(col->var) == col);
9465 assert(SCIPvarIsIntegral(col->var) == col->integral);
9466
9467 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9468 #ifdef SCIP_DEBUG
9469 {
9470 int i;
9471 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9472 for( i = 0; i < col->len; ++i )
9473 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9474 SCIPsetDebugMsgPrint(set, "\n");
9475 }
9476 #endif
9477
9478 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9479 lp->cols[lp->ncols] = col;
9480 col->lppos = lp->ncols;
9481 col->lpdepth = depth;
9482 col->age = 0;
9483 lp->ncols++;
9484 if( col->removable )
9485 lp->nremovablecols++;
9486
9487 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9488 {
9489 SCIP_CALL( ensureLazycolsSize(lp, set, lp->nlazycols+1) );
9490 lp->lazycols[lp->nlazycols] = col;
9491 lp->nlazycols++;
9492 }
9493
9494 /* mark the current LP unflushed */
9495 lp->flushed = FALSE;
9496
9497 /* update column arrays of all linked rows */
9498 colUpdateAddLP(col, set);
9499
9500 /* update the objective function vector norms */
9501 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9502
9503 checkLinks(lp);
9504
9505 return SCIP_OKAY;
9506 }
9507
9508 /** adds a row to the LP and captures it */
9509 SCIP_RETCODE SCIPlpAddRow(
9510 SCIP_LP* lp, /**< LP data */
9511 BMS_BLKMEM* blkmem, /**< block memory buffers */
9512 SCIP_SET* set, /**< global SCIP settings */
9513 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9514 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9515 SCIP_ROW* row, /**< LP row */
9516 int depth /**< depth in the tree where the row addition is performed */
9517 )
9518 {
9519 assert(lp != NULL);
9520 assert(row != NULL);
9521 assert(row->len == 0 || row->cols != NULL);
9522 assert(row->lppos == -1);
9523
9524 SCIProwCapture(row);
9525 SCIProwLock(row);
9526
9527 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9528 #ifdef SCIP_DEBUG
9529 {
9530 int i;
9531 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs);
9532 for( i = 0; i < row->len; ++i )
9533 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9534 if( !SCIPsetIsZero(set, row->constant) )
9535 SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9536 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9537 }
9538 #endif
9539
9540 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9541 lp->rows[lp->nrows] = row;
9542 row->lppos = lp->nrows;
9543 row->lpdepth = depth;
9544 row->age = 0;
9545 lp->nrows++;
9546 if( row->removable )
9547 lp->nremovablerows++;
9548
9549 /* mark the current LP unflushed */
9550 lp->flushed = FALSE;
9551
9552 /* update row arrays of all linked columns */
9553 rowUpdateAddLP(row);
9554
9555 checkLinks(lp);
9556
9557 rowCalcNorms(row, set);
9558
9559 /* check, if row addition to LP events are tracked
9560 * if so, issue ROWADDEDLP event
9561 */
9562 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9563 {
9564 SCIP_EVENT* event;
9565
9566 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9567 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9568 }
9569
9570 return SCIP_OKAY;
9571 }
9572
9573
9574 #ifndef NDEBUG
9575 /** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9576 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9577 * the lazycols array
9578 */
9579 static
9580 void checkLazyColArray(
9581 SCIP_LP* lp, /**< LP data */
9582 SCIP_SET* set /**< global SCIP settings */
9583 )
9584 {
9585 SCIP_Bool contained;
9586 int c;
9587 int i;
9588
9589 assert(lp != NULL);
9590
9591 /* check if each column in the lazy column array has a counter part in the column array */
9592 for( i = 0; i < lp->nlazycols; ++i )
9593 {
9594 /* check if each lazy column has at least on lazy bound */
9595 assert(lp->lazycols[i] != NULL);
9596 assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9597
9598 contained = FALSE;
9599 for( c = 0; c < lp->ncols; ++c )
9600 {
9601 if( lp->lazycols[i] == lp->cols[c] )
9602 {
9603 assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9604 contained = TRUE;
9605 }
9606 }
9607 assert(contained);
9608 }
9609
9610 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9611 * array */
9612 for( c = 0; c < lp->ncols; ++c )
9613 {
9614 contained = FALSE;
9615 assert(lp->cols[c] != NULL);
9616
9617 for( i = 0; i < lp->nlazycols; ++i )
9618 {
9619 if( lp->lazycols[i] == lp->cols[c] )
9620 {
9621 contained = TRUE;
9622 }
9623 }
9624
9625 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9626 }
9627 }
9628 #else
9629 #define checkLazyColArray(lp, set) /**/
9630 #endif
9631
9632 /** removes all columns after the given number of cols from the LP */
9633 SCIP_RETCODE SCIPlpShrinkCols(
9634 SCIP_LP* lp, /**< LP data */
9635 SCIP_SET* set, /**< global SCIP settings */
9636 int newncols /**< new number of columns in the LP */
9637 )
9638 {
9639 SCIP_COL* col;
9640 int c;
9641
9642 assert(lp != NULL);
9643
9644 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9645 assert(0 <= newncols);
9646 assert(newncols <= lp->ncols);
9647
9648 if( newncols < lp->ncols )
9649 {
9650 assert(!lp->diving);
9651
9652 for( c = lp->ncols-1; c >= newncols; --c )
9653 {
9654 col = lp->cols[c];
9655 assert(col != NULL);
9656 assert(col->len == 0 || col->rows != NULL);
9657 assert(col->var != NULL);
9658 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9659 assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9660 assert(col->lppos == c);
9661
9662 /* mark column to be removed from the LP */
9663 col->lppos = -1;
9664 col->lpdepth = -1;
9665 lp->ncols--;
9666
9667 /* count removable columns */
9668 if( col->removable )
9669 lp->nremovablecols--;
9670
9671 /* update column arrays of all linked rows */
9672 colUpdateDelLP(col, set);
9673
9674 /* update the objective function vector norms */
9675 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9676 }
9677 assert(lp->ncols == newncols);
9678 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9679
9680 /* remove columns which are deleted from the lazy column array */
9681 c = 0;
9682 while( c < lp->nlazycols )
9683 {
9684 if( lp->lazycols[c]->lppos < 0 )
9685 {
9686 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9687 lp->nlazycols--;
9688 }
9689 else
9690 c++;
9691 }
9692
9693 /* mark the current LP unflushed */
9694 lp->flushed = FALSE;
9695
9696 checkLazyColArray(lp, set);
9697 checkLinks(lp);
9698 }
9699 assert(lp->nremovablecols <= lp->ncols);
9700
9701 return SCIP_OKAY;
9702 }
9703
9704 /** removes and releases all rows after the given number of rows from the LP */
9705 SCIP_RETCODE SCIPlpShrinkRows(
9706 SCIP_LP* lp, /**< LP data */
9707 BMS_BLKMEM* blkmem, /**< block memory */
9708 SCIP_SET* set, /**< global SCIP settings */
9709 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9710 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9711 int newnrows /**< new number of rows in the LP */
9712 )
9713 {
9714 SCIP_ROW* row;
9715 int r;
9716
9717 assert(lp != NULL);
9718 assert(0 <= newnrows && newnrows <= lp->nrows);
9719
9720 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9721 if( newnrows < lp->nrows )
9722 {
9723 for( r = lp->nrows-1; r >= newnrows; --r )
9724 {
9725 row = lp->rows[r];
9726 assert(row != NULL);
9727 assert(row->len == 0 || row->cols != NULL);
9728 assert(row->lppos == r);
9729
9730 /* mark row to be removed from the LP */
9731 row->lppos = -1;
9732 row->lpdepth = -1;
9733 lp->nrows--;
9734
9735 /* count removable rows */
9736 if( row->removable )
9737 lp->nremovablerows--;
9738
9739 /* update row arrays of all linked columns */
9740 rowUpdateDelLP(row);
9741
9742 SCIProwUnlock(lp->rows[r]);
9743
9744 /* check, if row deletion events are tracked
9745 * if so, issue ROWDELETEDLP event
9746 */
9747 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9748 {
9749 SCIP_EVENT* event;
9750
9751 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9752 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9753 }
9754
9755 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9756 }
9757 assert(lp->nrows == newnrows);
9758 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9759
9760 /* mark the current LP unflushed */
9761 lp->flushed = FALSE;
9762
9763 checkLinks(lp);
9764 }
9765 assert(lp->nremovablerows <= lp->nrows);
9766
9767 return SCIP_OKAY;
9768 }
9769
9770 /** removes all columns and rows from LP, releases all rows */
9771 SCIP_RETCODE SCIPlpClear(
9772 SCIP_LP* lp, /**< LP data */
9773 BMS_BLKMEM* blkmem, /**< block memory */
9774 SCIP_SET* set, /**< global SCIP settings */
9775 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9776 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9777 )
9778 {
9779 assert(lp != NULL);
9780 assert(!lp->diving);
9781
9782 SCIPsetDebugMsg(set, "clearing LP\n");
9783 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9784 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9785
9786 return SCIP_OKAY;
9787 }
9788
9789 /** remembers number of columns and rows to track the newly added ones */
9790 void SCIPlpMarkSize(
9791 SCIP_LP* lp /**< current LP data */
9792 )
9793 {
9794 assert(lp != NULL);
9795 assert(!lp->diving);
9796
9797 lp->firstnewrow = lp->nrows;
9798 lp->firstnewcol = lp->ncols;
9799 }
9800
9801 /** sets the remembered number of columns and rows to the given values */
9802 void SCIPlpSetSizeMark(
9803 SCIP_LP* lp, /**< current LP data */
9804 int nrows, /**< number of rows to set the size marker to */
9805 int ncols /**< number of columns to set the size marker to */
9806 )
9807 {
9808 assert(lp != NULL);
9809 assert(!lp->diving);
9810
9811 lp->firstnewrow = nrows;
9812 lp->firstnewcol = ncols;
9813 }
9814
9815 /** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9816 SCIP_RETCODE SCIPlpGetBasisInd(
9817 SCIP_LP* lp, /**< LP data */
9818 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9819 )
9820 {
9821 assert(lp != NULL);
9822 assert(lp->flushed);
9823 assert(lp->solved);
9824 assert(lp->solisbasic);
9825 assert(basisind != NULL);
9826
9827 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9828
9829 return SCIP_OKAY;
9830 }
9831
9832 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9833 SCIP_RETCODE SCIPlpGetBase(
9834 SCIP_LP* lp, /**< LP data */
9835 int* cstat, /**< array to store column basis status, or NULL */
9836 int* rstat /**< array to store row basis status, or NULL */
9837 )
9838 {
9839 assert(lp != NULL);
9840 assert(lp->flushed);
9841 assert(lp->solved);
9842 assert(lp->solisbasic);
9843
9844 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9845
9846 return SCIP_OKAY;
9847 }
9848
9849 /** gets a row from the inverse basis matrix B^-1 */
9850 SCIP_RETCODE SCIPlpGetBInvRow(
9851 SCIP_LP* lp, /**< LP data */
9852 int r, /**< row number */
9853 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9854 int* inds, /**< array to store the non-zero indices, or NULL */
9855 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9856 * (-1: if we do not store sparsity informations) */
9857 )
9858 {
9859 assert(lp != NULL);
9860 assert(lp->flushed);
9861 assert(lp->solved);
9862 assert(lp->solisbasic);
9863 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9864 assert(coef != NULL);
9865
9866 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9867
9868 return SCIP_OKAY;
9869 }
9870
9871 /** gets a column from the inverse basis matrix B^-1 */
9872 SCIP_RETCODE SCIPlpGetBInvCol(
9873 SCIP_LP* lp, /**< LP data */
9874 int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9875 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9876 * to get the array which links the B^-1 column numbers to the row and
9877 * column numbers of the LP! c must be between 0 and nrows-1, since the
9878 * basis has the size nrows * nrows */
9879 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9880 int* inds, /**< array to store the non-zero indices, or NULL */
9881 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9882 * (-1: if we do not store sparsity informations) */
9883 )
9884 {
9885 assert(lp != NULL);
9886 assert(lp->flushed);
9887 assert(lp->solved);
9888 assert(lp->solisbasic);
9889 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9890 assert(coef != NULL);
9891
9892 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9893
9894 return SCIP_OKAY;
9895 }
9896
9897 /** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9898 SCIP_RETCODE SCIPlpGetBInvARow(
9899 SCIP_LP* lp, /**< LP data */
9900 int r, /**< row number */
9901 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9902 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9903 int* inds, /**< array to store the non-zero indices, or NULL */
9904 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9905 * (-1: if we do not store sparsity informations) */
9906 )
9907 {
9908 assert(lp != NULL);
9909 assert(lp->flushed);
9910 assert(lp->solved);
9911 assert(lp->solisbasic);
9912 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9913 assert(coef != NULL);
9914
9915 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9916
9917 return SCIP_OKAY;
9918 }
9919
9920 /** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9921 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9922 */
9923 SCIP_RETCODE SCIPlpGetBInvACol(
9924 SCIP_LP* lp, /**< LP data */
9925 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9926 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9927 int* inds, /**< array to store the non-zero indices, or NULL */
9928 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9929 * (-1: if we do not store sparsity informations) */
9930 )
9931 {
9932 assert(lp != NULL);
9933 assert(lp->flushed);
9934 assert(lp->solved);
9935 assert(lp->solisbasic);
9936 assert(0 <= c && c < lp->ncols);
9937 assert(coef != NULL);
9938
9939 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9940
9941 return SCIP_OKAY;
9942 }
9943
9944 /** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9945 * LP row are swapped in the summation
9946 */
9947 SCIP_RETCODE SCIPlpSumRows(
9948 SCIP_LP* lp, /**< LP data */
9949 SCIP_SET* set, /**< global SCIP settings */
9950 SCIP_PROB* prob, /**< problem data */
9951 SCIP_Real* weights, /**< row weights in row summation */
9952 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9953 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9954 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9955 )
9956 {
9957 SCIP_ROW* row;
9958 int r;
9959 int i;
9960 int idx;
9961 SCIP_Bool lhsinfinite;
9962 SCIP_Bool rhsinfinite;
9963
9964 assert(lp != NULL);
9965 assert(prob != NULL);
9966 assert(weights != NULL);
9967 assert(sumcoef != NULL);
9968 assert(sumlhs != NULL);
9969 assert(sumrhs != NULL);
9970
9971 /**@todo test, if a column based summation is faster */
9972
9973 SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9974 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9975 *sumlhs = 0.0;
9976 *sumrhs = 0.0;
9977 lhsinfinite = FALSE;
9978 rhsinfinite = FALSE;
9979 for( r = 0; r < lp->nrows; ++r )
9980 {
9981 if( !SCIPsetIsZero(set, weights[r]) )
9982 {
9983 row = lp->rows[r];
9984 assert(row != NULL);
9985 assert(row->len == 0 || row->cols != NULL);
9986 assert(row->len == 0 || row->cols_index != NULL);
9987 assert(row->len == 0 || row->vals != NULL);
9988
9989 /* add the row coefficients to the sum */
9990 for( i = 0; i < row->len; ++i )
9991 {
9992 assert(row->cols[i] != NULL);
9993 assert(row->cols[i]->var != NULL);
9994 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9995 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9996 assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9997 idx = row->cols[i]->var_probindex;
9998 assert(0 <= idx && idx < prob->nvars);
9999 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
10000 }
10001
10002 /* add the row sides to the sum, depending on the sign of the weight */
10003 if( weights[r] > 0.0 )
10004 {
10005 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10006 if( !lhsinfinite )
10007 (*sumlhs) += weights[r] * (row->lhs - row->constant);
10008 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10009 if( !rhsinfinite )
10010 (*sumrhs) += weights[r] * (row->rhs - row->constant);
10011 }
10012 else
10013 {
10014 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10015 if( !lhsinfinite )
10016 (*sumlhs) += weights[r] * (row->rhs - row->constant);
10017 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10018 if( !rhsinfinite )
10019 (*sumrhs) += weights[r] * (row->lhs - row->constant);
10020 }
10021 }
10022 }
10023
10024 if( lhsinfinite )
10025 *sumlhs = -SCIPsetInfinity(set);
10026 if( rhsinfinite )
10027 *sumrhs = SCIPsetInfinity(set);
10028
10029 return SCIP_OKAY;
10030 }
10031
10032 /** stores LP state (like basis information) into LP state object */
10033 SCIP_RETCODE SCIPlpGetState(
10034 SCIP_LP* lp, /**< LP data */
10035 BMS_BLKMEM* blkmem, /**< block memory */
10036 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10037 )
10038 {
10039 assert(lp != NULL);
10040 assert(lp->flushed);
10041 assert(lp->solved);
10042 assert(blkmem != NULL);
10043 assert(lpistate != NULL);
10044
10045 /* check whether there is no lp */
10046 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10047 *lpistate = NULL;
10048 else
10049 {
10050 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10051 }
10052
10053 return SCIP_OKAY;
10054 }
10055
10056 /** loads LP state (like basis information) into solver */
10057 SCIP_RETCODE SCIPlpSetState(
10058 SCIP_LP* lp, /**< LP data */
10059 BMS_BLKMEM* blkmem, /**< block memory */
10060 SCIP_SET* set, /**< global SCIP settings */
10061 SCIP_PROB* prob, /**< problem data */
10062 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10063 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
10064 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
10065 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */
10066 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */
10067 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */
10068 )
10069 {
10070 assert(lp != NULL);
10071 assert(blkmem != NULL);
10072
10073 /* flush changes to the LP solver */
10074 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10075 assert(lp->flushed);
10076
10077 if( lp->solved && lp->solisbasic )
10078 return SCIP_OKAY;
10079
10080 /* set LPI state in the LP solver */
10081 if( lpistate == NULL )
10082 lp->solisbasic = FALSE;
10083 else
10084 {
10085 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10086 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10087 }
10088 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10089 * flushed and solved, also, e.g., when we hit the iteration limit
10090 */
10091 lp->primalfeasible = wasprimfeas;
10092 lp->primalchecked = wasprimchecked;
10093 lp->dualfeasible = wasdualfeas;
10094 lp->dualchecked = wasdualchecked;
10095
10096 return SCIP_OKAY;
10097 }
10098
10099 /** frees LP state information */
10100 SCIP_RETCODE SCIPlpFreeState(
10101 SCIP_LP* lp, /**< LP data */
10102 BMS_BLKMEM* blkmem, /**< block memory */
10103 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10104 )
10105 {
10106 assert(lp != NULL);
10107
10108 if( *lpistate != NULL )
10109 {
10110 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10111 }
10112
10113 return SCIP_OKAY;
10114 }
10115
10116 /** interrupts the currently ongoing lp solve, or disables the interrupt */
10117 SCIP_RETCODE SCIPlpInterrupt(
10118 SCIP_LP* lp, /**< LP data */
10119 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10120 )
10121 {
10122 assert(lp != NULL);
10123
10124 if( lp->lpi == NULL )
10125 return SCIP_OKAY;
10126
10127 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10128
10129 return SCIP_OKAY;
10130 }
10131
10132 /** stores pricing norms into LP norms object */
10133 SCIP_RETCODE SCIPlpGetNorms(
10134 SCIP_LP* lp, /**< LP data */
10135 BMS_BLKMEM* blkmem, /**< block memory */
10136 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10137 )
10138 {
10139 assert(lp != NULL);
10140 assert(lp->flushed);
10141 assert(lp->solved);
10142 assert(blkmem != NULL);
10143 assert(lpinorms != NULL);
10144
10145 /* check whether there is no lp */
10146 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10147 *lpinorms = NULL;
10148 else
10149 {
10150 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10151 }
10152
10153 return SCIP_OKAY;
10154 }
10155
10156 /** loads pricing norms from LP norms object into solver */
10157 SCIP_RETCODE SCIPlpSetNorms(
10158 SCIP_LP* lp, /**< LP data */
10159 BMS_BLKMEM* blkmem, /**< block memory */
10160 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
10161 )
10162 {
10163 assert(lp != NULL);
10164 assert(blkmem != NULL);
10165 assert(lp->flushed);
10166
10167 /* set LPI norms in the LP solver */
10168 if( lpinorms != NULL )
10169 {
10170 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10171 }
10172
10173 return SCIP_OKAY;
10174 }
10175
10176 /** frees pricing norms information */
10177 SCIP_RETCODE SCIPlpFreeNorms(
10178 SCIP_LP* lp, /**< LP data */
10179 BMS_BLKMEM* blkmem, /**< block memory */
10180 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10181 )
10182 {
10183 assert(lp != NULL);
10184
10185 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10186
10187 return SCIP_OKAY;
10188 }
10189
10190 /** return the current cutoff bound of the lp */
10191 SCIP_Real SCIPlpGetCutoffbound(
10192 SCIP_LP* lp /**< current LP data */
10193 )
10194 {
10195 assert(lp != NULL);
10196
10197 return lp->cutoffbound;
10198 }
10199
10200 /** sets the upper objective limit of the LP solver */
10201 SCIP_RETCODE SCIPlpSetCutoffbound(
10202 SCIP_LP* lp, /**< current LP data */
10203 SCIP_SET* set, /**< global SCIP settings */
10204 SCIP_PROB* prob, /**< problem data */
10205 SCIP_Real cutoffbound /**< new upper objective limit */
10206 )
10207 {
10208 assert(lp != NULL);
10209
10210 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10211
10212 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10213 * in SCIPendDive())
10214 */
10215 if( SCIPlpDivingObjChanged(lp) )
10216 {
10217 assert(SCIPsetIsInfinity(set, lp->cutoffbound));
10218 return SCIP_OKAY;
10219 }
10220
10221 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10222 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10223 {
10224 /* mark the current solution invalid */
10225 lp->solved = FALSE;
10226 lp->lpobjval = SCIP_INVALID;
10227 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
10228 }
10229 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10230 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10231 */
10232 else if( !lpCutoffDisabled(set, prob) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
10233 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10234 {
10235 assert(lp->flushed);
10236 assert(lp->solved);
10237 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
10238 }
10239
10240 lp->cutoffbound = cutoffbound;
10241
10242 return SCIP_OKAY;
10243 }
10244
10245 /** gets current primal feasibility tolerance of LP solver */
10246 SCIP_Real SCIPlpGetFeastol(
10247 SCIP_LP* lp /**< current LP data */
10248 )
10249 {
10250 assert(lp != NULL);
10251
10252 return lp->feastol;
10253 }
10254
10255 /** sets primal feasibility tolerance of LP solver */
10256 void SCIPlpSetFeastol(
10257 SCIP_LP* lp, /**< current LP data */
10258 SCIP_SET* set, /**< global SCIP settings */
10259 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */
10260 )
10261 {
10262 assert(lp != NULL);
10263 assert(newfeastol > 0.0);
10264
10265 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10266
10267 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10268 if( newfeastol < lp->feastol )
10269 {
10270 lp->solved = FALSE;
10271 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
10272 }
10273
10274 lp->feastol = newfeastol;
10275 }
10276
10277 /** resets primal feasibility tolerance of LP solver
10278 *
10279 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10280 */
10281 void SCIPlpResetFeastol(
10282 SCIP_LP* lp, /**< current LP data */
10283 SCIP_SET* set /**< global SCIP settings */
10284 )
10285 {
10286 assert(lp != NULL);
10287
10288 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10289
10290 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10291 SCIPlpSetFeastol(lp, set, MIN(SCIPsetRelaxfeastol(set), SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set))); /*lint !e666*/
10292 else
10293 SCIPlpSetFeastol(lp, set, SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set));
10294 }
10295
10296 /** returns the name of the given LP algorithm */
10297 static
10298 const char* lpalgoName(
10299 SCIP_LPALGO lpalgo /**< LP algorithm */
10300 )
10301 {
10302 switch( lpalgo )
10303 {
10304 case SCIP_LPALGO_PRIMALSIMPLEX:
10305 return "primal simplex";
10306 case SCIP_LPALGO_DUALSIMPLEX:
10307 return "dual simplex";
10308 case SCIP_LPALGO_BARRIER:
10309 return "barrier";
10310 case SCIP_LPALGO_BARRIERCROSSOVER:
10311 return "barrier/crossover";
10312 default:
10313 SCIPerrorMessage("invalid LP algorithm\n");
10314 SCIPABORT();
10315 return "invalid"; /*lint !e527*/
10316 }
10317 }
10318
10319 /** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10320 static
10321 SCIP_RETCODE lpPrimalSimplex(
10322 SCIP_LP* lp, /**< current LP data */
10323 SCIP_SET* set, /**< global SCIP settings */
10324 SCIP_STAT* stat, /**< problem statistics */
10325 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10326 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10327 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10328 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10329 )
10330 {
10331 SCIP_Real timedelta;
10332 SCIP_RETCODE retcode;
10333 int iterations;
10334
10335 assert(lp != NULL);
10336 assert(lp->flushed);
10337 assert(set != NULL);
10338 assert(stat != NULL);
10339 assert(lperror != NULL);
10340
10341 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10342 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10343
10344 *lperror = FALSE;
10345
10346 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10347 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10348 {
10349 char fname[SCIP_MAXSTRLEN];
10350 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10351 SCIP_CALL( SCIPlpWrite(lp, fname) );
10352 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10353 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10354 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
10355 }
10356 #endif
10357
10358 /* start timing */
10359 if( lp->diving || lp->probing )
10360 {
10361 if( lp->strongbranchprobing )
10362 SCIPclockStart(stat->strongbranchtime, set);
10363 else
10364 SCIPclockStart(stat->divinglptime, set);
10365
10366 timedelta = 0.0; /* unused for diving or probing */
10367 }
10368 else
10369 {
10370 SCIPclockStart(stat->primallptime, set);
10371 timedelta = -SCIPclockGetTime(stat->primallptime);
10372 }
10373
10374 /* if this is a call to resolve an instable LP, collect time */
10375 if( instable )
10376 {
10377 SCIPclockStart(stat->resolveinstablelptime, set);
10378 }
10379
10380 /* call primal simplex */
10381 retcode = SCIPlpiSolvePrimal(lp->lpi);
10382 if( retcode == SCIP_LPERROR )
10383 {
10384 *lperror = TRUE;
10385 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10386 }
10387 else
10388 {
10389 SCIP_CALL( retcode );
10390 }
10391 lp->lastlpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
10392 lp->solisbasic = TRUE;
10393
10394 /* stop timing */
10395 if( lp->diving || lp->probing )
10396 {
10397 if( lp->strongbranchprobing )
10398 SCIPclockStop(stat->strongbranchtime, set);
10399 else
10400 SCIPclockStop(stat->divinglptime, set);
10401 }
10402 else
10403 {
10404 timedelta += SCIPclockGetTime(stat->primallptime);
10405 SCIPclockStop(stat->primallptime, set);
10406 }
10407
10408 if ( instable )
10409 {
10410 SCIPclockStop(stat->resolveinstablelptime, set);
10411 }
10412
10413 /* count number of iterations */
10414 SCIPstatIncrement(stat, set, lpcount);
10415 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10416 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10417 {
10418 if( !lp->strongbranchprobing )
10419 {
10420 SCIPstatIncrement(stat, set, nlps);
10421 SCIPstatAdd( stat, set, nlpiterations, iterations );
10422 }
10423 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10424 {
10425 SCIPstatIncrement(stat, set, nprimalresolvelps );
10426 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10427 }
10428 if ( instable )
10429 {
10430 SCIPstatIncrement(stat, set, nresolveinstablelps);
10431 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10432 }
10433 if( lp->diving || lp->probing )
10434 {
10435 if( lp->strongbranchprobing )
10436 {
10437 SCIPstatIncrement(stat, set, nsbdivinglps);
10438 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10439 }
10440 else
10441 {
10442 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10443 SCIPstatIncrement(stat, set, ndivinglps);
10444 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10445 }
10446 }
10447 else
10448 {
10449 SCIPstatIncrement(stat, set, nprimallps);
10450 SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10451 }
10452 }
10453 else
10454 {
10455 if ( ! lp->diving && ! lp->probing )
10456 {
10457 SCIPstatIncrement(stat, set, nprimalzeroitlps);
10458 SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10459 }
10460
10461 if ( keepsol && !(*lperror) )
10462 {
10463 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10464 if( lp->validsollp == stat->lpcount-1 )
10465 lp->validsollp = stat->lpcount;
10466 if( lp->validfarkaslp == stat->lpcount-1 )
10467 lp->validfarkaslp = stat->lpcount;
10468 }
10469 }
10470
10471 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10472 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10473
10474 return SCIP_OKAY;
10475 }
10476
10477 /** calls LPI to perform dual simplex, measures time and counts iterations */
10478 static
10479 SCIP_RETCODE lpDualSimplex(
10480 SCIP_LP* lp, /**< current LP data */
10481 SCIP_SET* set, /**< global SCIP settings */
10482 SCIP_STAT* stat, /**< problem statistics */
10483 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10484 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10485 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10486 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10487 )
10488 {
10489 SCIP_Real timedelta;
10490 SCIP_RETCODE retcode;
10491 int iterations;
10492
10493 assert(lp != NULL);
10494 assert(lp->flushed);
10495 assert(set != NULL);
10496 assert(stat != NULL);
10497 assert(lperror != NULL);
10498
10499 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10500 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10501
10502 *lperror = FALSE;
10503
10504 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10505 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10506 {
10507 char fname[SCIP_MAXSTRLEN];
10508 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10509 SCIP_CALL( SCIPlpWrite(lp, fname) );
10510 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10511 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10512 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
10513 }
10514 #endif
10515
10516 /* start timing */
10517 if( lp->diving || lp->probing )
10518 {
10519 if( lp->strongbranchprobing )
10520 SCIPclockStart(stat->strongbranchtime, set);
10521 else
10522 SCIPclockStart(stat->divinglptime, set);
10523
10524 timedelta = 0.0; /* unused for diving or probing */
10525 }
10526 else
10527 {
10528 SCIPclockStart(stat->duallptime, set);
10529 timedelta = -SCIPclockGetTime(stat->duallptime);
10530 }
10531
10532 /* if this is a call to resolve an instable LP, collect time */
10533 if ( instable )
10534 {
10535 SCIPclockStart(stat->resolveinstablelptime, set);
10536 }
10537
10538 /* call dual simplex */
10539 retcode = SCIPlpiSolveDual(lp->lpi);
10540 if( retcode == SCIP_LPERROR )
10541 {
10542 *lperror = TRUE;
10543 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10544 }
10545 else
10546 {
10547 SCIP_CALL( retcode );
10548 }
10549 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
10550 lp->solisbasic = TRUE;
10551
10552 /* stop timing */
10553 if( lp->diving || lp->probing )
10554 {
10555 if( lp->strongbranchprobing )
10556 SCIPclockStop(stat->strongbranchtime, set);
10557 else
10558 SCIPclockStop(stat->divinglptime, set);
10559 }
10560 else
10561 {
10562 timedelta += SCIPclockGetTime(stat->duallptime);
10563 SCIPclockStop(stat->duallptime, set);
10564 }
10565
10566 if ( instable )
10567 {
10568 SCIPclockStop(stat->resolveinstablelptime, set);
10569 }
10570
10571 /* count number of iterations */
10572 SCIPstatIncrement(stat, set, lpcount);
10573 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10574 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10575 {
10576 if( !lp->strongbranchprobing )
10577 {
10578 SCIPstatIncrement(stat, set, nlps);
10579 SCIPstatAdd(stat, set, nlpiterations, iterations);
10580 }
10581 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10582 {
10583 SCIPstatIncrement(stat, set, ndualresolvelps);
10584 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10585 }
10586 if ( instable )
10587 {
10588 SCIPstatIncrement(stat, set, nresolveinstablelps);
10589 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10590 }
10591 if( lp->diving || lp->probing )
10592 {
10593 if( lp->strongbranchprobing )
10594 {
10595 SCIPstatIncrement(stat, set, nsbdivinglps);
10596 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10597 }
10598 else
10599 {
10600 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10601 SCIPstatIncrement(stat, set, ndivinglps);
10602 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10603 }
10604 }
10605 else
10606 {
10607 SCIPstatIncrement(stat, set, nduallps);
10608 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10609 }
10610 }
10611 else
10612 {
10613 if ( ! lp->diving && ! lp->probing )
10614 {
10615 SCIPstatIncrement(stat, set, ndualzeroitlps);
10616 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10617 }
10618
10619 if( keepsol && !(*lperror) )
10620 {
10621 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10622 if( lp->validsollp == stat->lpcount-1 )
10623 lp->validsollp = stat->lpcount;
10624 if( lp->validfarkaslp == stat->lpcount-1 )
10625 lp->validfarkaslp = stat->lpcount;
10626 }
10627 }
10628
10629 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10630 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10631
10632 return SCIP_OKAY;
10633 }
10634
10635 /** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10636 *
10637 * We follow the approach of the following paper to find a lexicographically minimal optimal
10638 * solution:
10639 *
10640 * Zanette, Fischetti, Balas@n
10641 * Can pure cutting plane algorithms work?@n
10642 * IPCO 2008, Bertinoro, Italy.
10643 *
10644 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10645 * heuristic, i.e., we limit the number of components which are minimized.
10646 *
10647 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10648 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10649 * variables) that have nonzero reduced cost. This fixes the objective function value, because only
10650 * pivots that will not change the objective are allowed afterwards.
10651 *
10652 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10653 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10654 * candidate is found, we set the objective to minimize this variable. We run the primal simplex
10655 * algorithm (since the objective is changed the solution is not dual feasible anymore; if
10656 * variables out of the basis have been fixed to their lower bound, the basis is also not primal
10657 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10658 * reduced cost. We then choose the next variable and iterate.
10659 *
10660 * We stop the process once we do not find candidates or have performed a maximum number of
10661 * iterations.
10662 *
10663 * @todo Does this really produce a lexicographically minimal solution?
10664 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10665 * guarantee that these variables will not be changed in later stages? We can fix these variables
10666 * to their lower bound, but this destroys the basis.
10667 * @todo Should we use lexicographical minimization in diving/probing or not?
10668 */
10669 static
10670 SCIP_RETCODE lpLexDualSimplex(
10671 SCIP_LP* lp, /**< current LP data */
10672 SCIP_SET* set, /**< global SCIP settings */
10673 SCIP_STAT* stat, /**< problem statistics */
10674 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10675 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10676 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10677 )
10678 {
10679 SCIP_Real timedelta;
10680 SCIP_RETCODE retcode;
10681 int totalIterations;
10682 int lexIterations;
10683 int iterations;
10684 int rounds;
10685
10686 assert(lp != NULL);
10687 assert(lp->flushed);
10688 assert(set != NULL);
10689 assert(stat != NULL);
10690 assert(lperror != NULL);
10691
10692 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10693 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10694
10695 *lperror = FALSE;
10696
10697 /* start timing */
10698 if( lp->diving || lp->probing )
10699 {
10700 if( lp->strongbranchprobing )
10701 SCIPclockStart(stat->strongbranchtime, set);
10702 else
10703 SCIPclockStart(stat->divinglptime, set);
10704
10705 timedelta = 0.0; /* unused for diving or probing */
10706 }
10707 else
10708 {
10709 SCIPclockStart(stat->duallptime, set);
10710 timedelta = -SCIPclockGetTime(stat->duallptime);
10711 }
10712
10713 /* call dual simplex for first lp */
10714 retcode = SCIPlpiSolveDual(lp->lpi);
10715 if( retcode == SCIP_LPERROR )
10716 {
10717 *lperror = TRUE;
10718 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10719 }
10720 else
10721 {
10722 SCIP_CALL( retcode );
10723 }
10724 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10725 totalIterations = iterations;
10726
10727 /* stop timing */
10728 if( lp->diving || lp->probing )
10729 {
10730 if( lp->strongbranchprobing )
10731 SCIPclockStop(stat->strongbranchtime, set);
10732 else
10733 SCIPclockStop(stat->divinglptime, set);
10734 }
10735 else
10736 {
10737 timedelta += SCIPclockGetTime(stat->duallptime);
10738 SCIPclockStop(stat->duallptime, set);
10739 }
10740
10741 /* count number of iterations */
10742 SCIPstatIncrement(stat, set, lpcount);
10743 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10744 {
10745 if( lp->strongbranchprobing )
10746 {
10747 SCIPstatAdd(stat, set, nlpiterations, iterations);
10748 }
10749 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10750 {
10751 SCIPstatIncrement(stat, set, ndualresolvelps);
10752 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10753 }
10754 if( lp->diving || lp->probing )
10755 {
10756 if( lp->strongbranchprobing )
10757 {
10758 SCIPstatIncrement(stat, set, nsbdivinglps);
10759 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10760 }
10761 else
10762 {
10763 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10764 SCIPstatIncrement(stat, set, ndivinglps);
10765 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10766 }
10767 }
10768 else
10769 {
10770 SCIPstatIncrement(stat, set, nduallps);
10771 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10772 }
10773 }
10774 else
10775 {
10776 if ( ! lp->diving && ! lp->probing )
10777 {
10778 SCIPstatIncrement(stat, set, ndualzeroitlps);
10779 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10780 }
10781 }
10782 lexIterations = 0;
10783
10784 /* search for lexicographically minimal optimal solution */
10785 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10786 {
10787 SCIP_Bool chooseBasic;
10788 SCIP_Real* primsol;
10789 SCIP_Real* dualsol;
10790 SCIP_Real* redcost;
10791 int* cstat;
10792 int* rstat;
10793 SCIP_Real* newobj;
10794 SCIP_Real* newlb;
10795 SCIP_Real* newub;
10796 SCIP_Real* newlhs;
10797 SCIP_Real* newrhs;
10798 SCIP_Real* oldlb;
10799 SCIP_Real* oldub;
10800 SCIP_Real* oldlhs;
10801 SCIP_Real* oldrhs;
10802 SCIP_Real* oldobj;
10803 SCIP_Bool* fixedc;
10804 SCIP_Bool* fixedr;
10805 int* indcol;
10806 int* indrow;
10807 int* indallcol;
10808 int* indallrow;
10809 int nDualDeg;
10810 int r, c;
10811 int cntcol;
10812 int cntrow;
10813 int nruns;
10814 int pos;
10815
10816 chooseBasic = set->lp_lexdualbasic;
10817
10818 /* start timing */
10819 SCIPclockStart(stat->lexduallptime, set);
10820
10821 /* get all solution information */
10822 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10823 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10824 if( chooseBasic )
10825 {
10826 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10827 }
10828 else
10829 primsol = NULL;
10830
10831 /* get basic and nonbasic information */
10832 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
10833 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
10834
10835 /* save bounds, lhs/rhs, and objective */
10836 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldobj, lp->nlpicols) );
10837 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlb, lp->nlpicols) );
10838 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldub, lp->nlpicols) );
10839 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlhs, lp->nlpirows) );
10840 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldrhs, lp->nlpirows) );
10841 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10842 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10843 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10844
10845 /* get storage for several arrays */
10846 SCIP_CALL( SCIPsetAllocBufferArray(set, &newlb, lp->nlpicols) );
10847 SCIP_CALL( SCIPsetAllocBufferArray(set, &newub, lp->nlpicols) );
10848 SCIP_CALL( SCIPsetAllocBufferArray(set, &indcol, lp->nlpicols) );
10849
10850 SCIP_CALL( SCIPsetAllocBufferArray(set, &newlhs, lp->nlpirows) );
10851 SCIP_CALL( SCIPsetAllocBufferArray(set, &newrhs, lp->nlpirows) );
10852 SCIP_CALL( SCIPsetAllocBufferArray(set, &indrow, lp->nlpirows) );
10853
10854 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10855 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10856
10857 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedc, lp->nlpicols) );
10858 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedr, lp->nlpirows) );
10859
10860 /* initialize: set objective to 0, get fixed variables */
10861 SCIP_CALL( SCIPsetAllocBufferArray(set, &newobj, lp->nlpicols) );
10862 for( c = 0; c < lp->nlpicols; ++c )
10863 {
10864 newobj[c] = 0.0;
10865 indallcol[c] = c;
10866 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10867 fixedc[c] = TRUE;
10868 else
10869 fixedc[c] = FALSE;
10870 }
10871
10872 /* initialize: get fixed slack variables */
10873 for( r = 0; r < lp->nlpirows; ++r )
10874 {
10875 indallrow[r] = r;
10876 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10877 fixedr[r] = TRUE;
10878 else
10879 fixedr[r] = FALSE;
10880 }
10881
10882 #ifdef DEBUG_LEXDUAL
10883 {
10884 int j;
10885
10886 if( !chooseBasic )
10887 {
10888 assert(primsol == NULL);
10889 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10890 }
10891 assert(primsol != NULL);
10892 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10893 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10894
10895 for( j = 0; j < lp->nlpicols; ++j )
10896 {
10897 if( fixedc[j] )
10898 {
10899 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10900 }
10901 else
10902 {
10903 char type;
10904 switch( (SCIP_BASESTAT) cstat[j] )
10905 {
10906 case SCIP_BASESTAT_LOWER:
10907 type = 'l';
10908 break;
10909 case SCIP_BASESTAT_UPPER:
10910 type = 'u';
10911 break;
10912 case SCIP_BASESTAT_ZERO:
10913 type = 'z';
10914 break;
10915 case SCIP_BASESTAT_BASIC:
10916 type = 'b';
10917 break;
10918 default:
10919 type = '?';
10920 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10921 SCIPABORT();
10922 }
10923 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10924 }
10925 }
10926 SCIPsetDebugMsg(set, "\n\n");
10927
10928 if( !chooseBasic )
10929 {
10930 SCIPsetFreeBufferArray(set, &primsol);
10931 assert(primsol == NULL);
10932 }
10933 }
10934 #endif
10935
10936 /* perform lexicographic rounds */
10937 pos = -1;
10938 nruns = 0;
10939 rounds = 0;
10940 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10941 do
10942 {
10943 int oldpos;
10944
10945 /* get current solution */
10946 if( chooseBasic )
10947 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10948 else
10949 {
10950 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10951 assert(primsol == NULL);
10952 }
10953
10954 /* get current basis */
10955 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10956
10957 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10958 nDualDeg = 0;
10959 cntcol = 0;
10960 oldpos = pos;
10961 pos = -1;
10962 for( c = 0; c < lp->nlpicols; ++c )
10963 {
10964 if( !fixedc[c] )
10965 {
10966 /* check whether variable is in basis */
10967 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10968 {
10969 /* store first candidate */
10970 if( pos == -1 && c > oldpos )
10971 {
10972 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10973 pos = c;
10974 }
10975 }
10976 else
10977 {
10978 /* reduced cost == 0 -> possible candidate */
10979 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10980 {
10981 ++nDualDeg;
10982 /* only if we have not yet found a candidate */
10983 if( pos == -1 && c > oldpos )
10984 {
10985 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10986 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10987 {
10988 newlb[cntcol] = oldlb[c];
10989 newub[cntcol] = oldlb[c];
10990 indcol[cntcol++] = c;
10991 fixedc[c] = TRUE;
10992 }
10993 else /* found a non-fixed candidate */
10994 {
10995 if( !chooseBasic )
10996 pos = c;
10997 }
10998 }
10999 }
11000 else
11001 {
11002 /* nonzero reduced cost -> variable can be fixed */
11003 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11004 {
11005 newlb[cntcol] = oldlb[c];
11006 newub[cntcol] = oldlb[c];
11007 }
11008 else
11009 {
11010 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11011 {
11012 newlb[cntcol] = oldub[c];
11013 newub[cntcol] = oldub[c];
11014 }
11015 else
11016 {
11017 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11018 newlb[cntcol] = 0.0;
11019 newub[cntcol] = 0.0;
11020 }
11021 }
11022 indcol[cntcol++] = c;
11023 fixedc[c] = TRUE;
11024 }
11025 }
11026 }
11027 }
11028
11029 /* check rows */
11030 cntrow = 0;
11031 for( r = 0; r < lp->nlpirows; ++r )
11032 {
11033 if( !fixedr[r] )
11034 {
11035 /* consider only nonbasic rows */
11036 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11037 {
11038 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11039 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11040 ++nDualDeg;
11041 else
11042 {
11043 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11044 {
11045 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11046 newlhs[cntrow] = oldlhs[r];
11047 newrhs[cntrow] = oldlhs[r];
11048 }
11049 else
11050 {
11051 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11052 newlhs[cntrow] = oldrhs[r];
11053 newrhs[cntrow] = oldrhs[r];
11054 }
11055 indrow[cntrow++] = r;
11056 fixedr[r] = TRUE;
11057 }
11058 }
11059 }
11060 }
11061
11062 if( nDualDeg > 0 && pos >= 0 )
11063 {
11064 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11065
11066 /* change objective */
11067 if( nruns == 0 )
11068 {
11069 /* set objective to appropriate unit vector for first run */
11070 newobj[pos] = 1.0;
11071 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11072 }
11073 else
11074 {
11075 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11076 SCIP_Real obj = 1.0;
11077 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11078 }
11079
11080 /* fix variables */
11081 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11082 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11083
11084 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11085 retcode = SCIPlpiSolvePrimal(lp->lpi);
11086 if( retcode == SCIP_LPERROR )
11087 {
11088 *lperror = TRUE;
11089 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11090 }
11091 else
11092 {
11093 SCIP_CALL( retcode );
11094 }
11095 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11096 lexIterations += iterations;
11097
11098 #ifdef DEBUG_LEXDUAL
11099 if( iterations > 0 )
11100 {
11101 int j;
11102
11103 if( !chooseBasic )
11104 {
11105 assert(primsol == NULL);
11106 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11107 }
11108 assert(primsol != NULL);
11109 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11110
11111 for( j = 0; j < lp->nlpicols; ++j )
11112 {
11113 if( fixedc[j] )
11114 {
11115 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11116 }
11117 else
11118 {
11119 char cstart = '[';
11120 char cend = ']';
11121 char type;
11122
11123 if(j == pos)
11124 {
11125 cstart = '*';
11126 cend = '*';
11127 }
11128
11129 switch( (SCIP_BASESTAT) cstat[j] )
11130 {
11131 case SCIP_BASESTAT_LOWER:
11132 type = 'l';
11133 break;
11134 case SCIP_BASESTAT_UPPER:
11135 type = 'u';
11136 break;
11137 case SCIP_BASESTAT_ZERO:
11138 type = 'z';
11139 break;
11140 case SCIP_BASESTAT_BASIC:
11141 type = 'b';
11142 break;
11143 default:
11144 type = '?';
11145 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11146 SCIPABORT();
11147 }
11148 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11149 }
11150 }
11151 SCIPsetDebugMsg(set, "\n\n");
11152
11153 if( !chooseBasic )
11154 {
11155 SCIPsetFreeBufferArray(set, &primsol);
11156 assert(primsol == NULL);
11157 }
11158 }
11159 #endif
11160
11161 /* count only as round if iterations have been performed */
11162 if( iterations > 0 )
11163 ++rounds;
11164 ++nruns;
11165 }
11166 }
11167 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11168
11169 /* reset bounds, lhs/rhs, and obj */
11170 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11171 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11172 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11173
11174 /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
11175 retcode = SCIPlpiSolveDual(lp->lpi);
11176 if( retcode == SCIP_LPERROR )
11177 {
11178 *lperror = TRUE;
11179 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11180 }
11181 else
11182 {
11183 SCIP_CALL( retcode );
11184 }
11185 assert(SCIPlpiIsOptimal(lp->lpi));
11186 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11187 lexIterations += iterations;
11188
11189 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11190
11191 /* count number of iterations */
11192 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11193 SCIPstatIncrement(stat, set, nlps);
11194
11195 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11196 {
11197 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11198 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11199 {
11200 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11201 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11202 }
11203 SCIPstatIncrement(stat, set, nlexduallps);
11204 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11205
11206 totalIterations += lexIterations;
11207 }
11208
11209 /* free space */
11210 SCIPsetFreeBufferArray(set, &newobj);
11211
11212 SCIPsetFreeBufferArray(set, &fixedr);
11213 SCIPsetFreeBufferArray(set, &fixedc);
11214
11215 SCIPsetFreeBufferArray(set, &indallrow);
11216 SCIPsetFreeBufferArray(set, &indallcol);
11217
11218 SCIPsetFreeBufferArray(set, &indrow);
11219 SCIPsetFreeBufferArray(set, &newrhs);
11220 SCIPsetFreeBufferArray(set, &newlhs);
11221
11222 SCIPsetFreeBufferArray(set, &indcol);
11223 SCIPsetFreeBufferArray(set, &newub);
11224 SCIPsetFreeBufferArray(set, &newlb);
11225
11226 SCIPsetFreeBufferArray(set, &oldobj);
11227 SCIPsetFreeBufferArray(set, &oldrhs);
11228 SCIPsetFreeBufferArray(set, &oldlhs);
11229 SCIPsetFreeBufferArray(set, &oldub);
11230 SCIPsetFreeBufferArray(set, &oldlb);
11231
11232 SCIPsetFreeBufferArray(set, &rstat);
11233 SCIPsetFreeBufferArray(set, &cstat);
11234
11235 SCIPsetFreeBufferArray(set, &redcost);
11236 SCIPsetFreeBufferArray(set, &dualsol);
11237 if( chooseBasic )
11238 SCIPsetFreeBufferArray(set, &primsol);
11239
11240 /* stop timing */
11241 SCIPclockStop(stat->lexduallptime, set);
11242
11243 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11244 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11245 }
11246 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
11247 lp->solisbasic = TRUE;
11248
11249 if( totalIterations > 0 && !lp->strongbranchprobing )
11250 SCIPstatIncrement(stat, set, nlps);
11251 else
11252 {
11253 if( keepsol && !(*lperror) )
11254 {
11255 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11256 if( lp->validsollp == stat->lpcount-1 )
11257 lp->validsollp = stat->lpcount;
11258 if( lp->validfarkaslp == stat->lpcount-1 )
11259 lp->validfarkaslp = stat->lpcount;
11260 }
11261 }
11262
11263 return SCIP_OKAY;
11264 }
11265
11266 /** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11267 static
11268 SCIP_RETCODE lpBarrier(
11269 SCIP_LP* lp, /**< current LP data */
11270 SCIP_SET* set, /**< global SCIP settings */
11271 SCIP_STAT* stat, /**< problem statistics */
11272 SCIP_Bool crossover, /**< should crossover be performed? */
11273 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11274 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11275 )
11276 {
11277 SCIP_Real timedelta;
11278 SCIP_RETCODE retcode;
11279 int iterations;
11280
11281 assert(lp != NULL);
11282 assert(lp->flushed);
11283 assert(set != NULL);
11284 assert(stat != NULL);
11285 assert(lperror != NULL);
11286
11287 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11288 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11289 stat->nbarrierlps, stat->ndivinglps);
11290
11291 *lperror = FALSE;
11292
11293 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11294 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11295 {
11296 char fname[SCIP_MAXSTRLEN];
11297 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11298 SCIP_CALL( SCIPlpWrite(lp, fname) );
11299 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11300 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11301 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
11302 }
11303 #endif
11304
11305 /* start timing */
11306 if( lp->diving || lp->probing )
11307 {
11308 if( lp->strongbranchprobing )
11309 SCIPclockStart(stat->strongbranchtime, set);
11310 else
11311 SCIPclockStart(stat->divinglptime, set);
11312
11313 timedelta = 0.0; /* unused for diving or probing */
11314 }
11315 else
11316 {
11317 SCIPclockStart(stat->barrierlptime, set);
11318 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11319 }
11320
11321 /* call barrier algorithm */
11322 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11323 if( retcode == SCIP_LPERROR )
11324 {
11325 *lperror = TRUE;
11326 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11327 }
11328 else
11329 {
11330 SCIP_CALL( retcode );
11331 }
11332 lp->lastlpalgo = (crossover ? SCIP_LPALGO_BARRIERCROSSOVER : SCIP_LPALGO_BARRIER);
11333 lp->solisbasic = crossover;
11334
11335 /* stop timing */
11336 if( lp->diving || lp->probing )
11337 {
11338 if( lp->strongbranchprobing )
11339 SCIPclockStop(stat->strongbranchtime, set);
11340 else
11341 SCIPclockStop(stat->divinglptime, set);
11342 }
11343 else
11344 {
11345 SCIPclockStop(stat->barrierlptime, set);
11346 timedelta += SCIPclockGetTime(stat->barrierlptime);
11347 }
11348
11349 /* count number of iterations */
11350 SCIPstatIncrement(stat, set, lpcount);
11351 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11352 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11353 {
11354 if( !lp->strongbranchprobing )
11355 {
11356 SCIPstatIncrement(stat, set, nlps);
11357 SCIPstatAdd(stat, set, nlpiterations, iterations);
11358 }
11359 if( lp->diving || lp->probing )
11360 {
11361 if( lp->strongbranchprobing )
11362 {
11363 SCIPstatIncrement(stat, set, nsbdivinglps);
11364 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11365 }
11366 else
11367 {
11368 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11369 SCIPstatIncrement(stat, set, ndivinglps);
11370 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11371 }
11372 }
11373 else
11374 {
11375 SCIPstatIncrement(stat, set, nbarrierlps);
11376 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11377 }
11378 }
11379 else
11380 {
11381 if ( ! lp->diving && ! lp->probing )
11382 {
11383 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11384 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11385 }
11386
11387 if( keepsol && !(*lperror) )
11388 {
11389 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11390 if( lp->validsollp == stat->lpcount-1 )
11391 lp->validsollp = stat->lpcount;
11392 if( lp->validfarkaslp == stat->lpcount-1 )
11393 lp->validfarkaslp = stat->lpcount;
11394 }
11395 }
11396
11397 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11398 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11399
11400 return SCIP_OKAY;
11401 }
11402
11403 /** solves the LP with the given algorithm */
11404 static
11405 SCIP_RETCODE lpAlgorithm(
11406 SCIP_LP* lp, /**< current LP data */
11407 SCIP_SET* set, /**< global SCIP settings */
11408 SCIP_STAT* stat, /**< problem statistics */
11409 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11410 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11411 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11412 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11413 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11414 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11415 )
11416 {
11417 SCIP_Real lptimelimit;
11418 SCIP_Bool success;
11419
11420 assert(lp != NULL);
11421 assert(lp->flushed);
11422 assert(lperror != NULL);
11423
11424 /* check if a time limit is set, and set time limit for LP solver accordingly */
11425 lptimelimit = SCIPlpiInfinity(lp->lpi);
11426 if( set->istimelimitfinite )
11427 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11428
11429 success = FALSE;
11430 if( lptimelimit > 0.0 )
11431 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11432
11433 if( lptimelimit <= 0.0 || !success )
11434 {
11435 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11436 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11437 *timelimit = TRUE;
11438 return SCIP_OKAY;
11439 }
11440 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11441
11442 /* call appropriate LP algorithm */
11443 switch( lpalgo )
11444 {
11445 case SCIP_LPALGO_PRIMALSIMPLEX:
11446 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11447 break;
11448
11449 case SCIP_LPALGO_DUALSIMPLEX:
11450 /* run dual lexicographic simplex if required */
11451 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11452 {
11453 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11454 }
11455 else
11456 {
11457 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11458 }
11459 break;
11460
11461 case SCIP_LPALGO_BARRIER:
11462 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11463 break;
11464
11465 case SCIP_LPALGO_BARRIERCROSSOVER:
11466 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11467 break;
11468
11469 default:
11470 SCIPerrorMessage("invalid LP algorithm\n");
11471 return SCIP_INVALIDDATA;
11472 }
11473
11474 if( !(*lperror) )
11475 {
11476 /* check for primal and dual feasibility */
11477 SCIP_CALL( SCIPlpiGetSolFeasibility(lp->lpi, &lp->primalfeasible, &lp->dualfeasible) );
11478
11479 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11480 }
11481
11482 return SCIP_OKAY;
11483 }
11484
11485 /** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11486 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11487 */
11488 #define MAXNUMTROUBLELPMSGS 10
11489
11490 /** prints message about numerical trouble
11491 *
11492 * If message has verblevel at most high and display/verblevel is not full,
11493 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11494 * were printed before in the current run.
11495 */
11496 static
11497 void lpNumericalTroubleMessage(
11498 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11499 SCIP_SET* set, /**< global SCIP settings */
11500 SCIP_STAT* stat, /**< problem statistics */
11501 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11502 const char* formatstr, /**< message format string */
11503 ... /**< arguments to format string */
11504 )
11505 {
11506 va_list ap;
11507
11508 assert(verblevel > SCIP_VERBLEVEL_NONE);
11509 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11510 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11511
11512 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11513 {
11514 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11515 {
11516 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11517 if( stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11518 return;
11519
11520 /* increase count on messages with verblevel high */
11521 ++stat->nnumtroublelpmsgs ;
11522 }
11523
11524 /* if messages wouldn't be printed, then return already */
11525 if( verblevel > set->disp_verblevel )
11526 return;
11527 }
11528
11529 /* print common begin of message */
11530 SCIPmessagePrintInfo(messagehdlr,
11531 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11532 stat->nnodes, stat->nlps);
11533
11534 /* print individual part of message */
11535 va_start(ap, formatstr); /*lint !e838*/
11536 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11537 va_end(ap);
11538
11539 /* warn that further messages will be suppressed */
11540 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11541 {
11542 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11543 }
11544
11545 /* print closing new-line */
11546 SCIPmessagePrintInfo(messagehdlr, "\n");
11547 }
11548
11549 static
11550 SCIP_RETCODE ignoreInstability(
11551 SCIP_LP* lp, /**< current LP data */
11552 SCIP_SET* set, /**< global SCIP settings */
11553 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11554 SCIP_STAT* stat, /**< problem statistics */
11555 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11556 SCIP_Bool* success /**< was instability successfully ignored */
11557 )
11558 {
11559 assert(lp != NULL);
11560 assert(set != NULL);
11561
11562 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11563
11564 if( *success )
11565 {
11566 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11567 if( !set->lp_checkdualfeas )
11568 lp->dualfeasible = TRUE;
11569 if( !set->lp_checkprimfeas )
11570 lp->primalchecked = TRUE;
11571 }
11572
11573 return SCIP_OKAY;
11574 }
11575
11576 #define FEASTOLTIGHTFAC 0.001
11577 /** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11578 static
11579 SCIP_RETCODE lpSolveStable(
11580 SCIP_LP* lp, /**< current LP data */
11581 SCIP_SET* set, /**< global SCIP settings */
11582 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11583 SCIP_STAT* stat, /**< problem statistics */
11584 SCIP_PROB* prob, /**< problem data */
11585 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11586 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11587 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11588 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11589 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11590 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11591 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11592 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11593 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11594 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11595 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11596 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11597 )
11598 {
11599 SCIP_Bool success;
11600 SCIP_Bool success2;
11601 SCIP_Bool success3;
11602 SCIP_Bool simplex;
11603 SCIP_Bool itlimishard;
11604 SCIP_Bool usepolishing;
11605
11606 assert(lp != NULL);
11607 assert(lp->flushed);
11608 assert(set != NULL);
11609 assert(stat != NULL);
11610 assert(lperror != NULL);
11611 assert(timelimit != NULL);
11612
11613 *lperror = FALSE;
11614
11615 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11616 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11617 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11618 * SCIP_LP such that we can return a primal ray
11619 */
11620 if( lp->looseobjvalinf > 0 )
11621 {
11622 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11623 return SCIP_ERROR;
11624 }
11625
11626 /* check, whether we solve with a simplex algorithm */
11627 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11628
11629 /* check whether the iteration limit is a hard one */
11630 itlimishard = (itlim == harditlim);
11631
11632 /* check whether solution polishing should be used */
11633 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11634 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11635 {
11636 usepolishing = TRUE;
11637 if( lp->updateintegrality )
11638 {
11639 SCIP_CALL( lpCopyIntegrality(lp, set) );
11640 }
11641 }
11642 else
11643 usepolishing = FALSE;
11644
11645 /* solve with given settings (usually fast but imprecise) */
11646 if( SCIPsetIsInfinity(set, lp->cutoffbound) )
11647 {
11648 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11649 }
11650 else
11651 {
11652 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11653 }
11654 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11655 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11656 SCIP_CALL( lpSetDualfeastol(lp, tightdualfeastol ? FEASTOLTIGHTFAC * SCIPsetDualfeastol(set) : SCIPsetDualfeastol(set),
11657 &success) );
11658 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11659 : SCIPsetBarrierconvtol(set), &success) );
11660 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11661 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11662 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11663 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11664 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11665 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11666 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11667 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11668 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11669 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11670 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11671 SCIP_CALL( lpSetRandomseed(lp, (int) SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed), &success) );
11672 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11673 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11674
11675 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11676
11677 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11678 * optimal without preforming scaling/change tolerances/presolving */
11679 resolve = FALSE;
11680
11681 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11682 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11683 return SCIP_OKAY;
11684
11685 if( !set->lp_checkstability )
11686 {
11687 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11688
11689 if( success )
11690 return SCIP_OKAY;
11691 }
11692
11693 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11694 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11695 */
11696
11697 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11698 * do this only if the iteration limit was not exceeded in the last LP solving call
11699 */
11700 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11701 {
11702 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11703 if( success )
11704 {
11705 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11706 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11707
11708 /* check for stability */
11709 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11710 return SCIP_OKAY;
11711
11712 if( !set->lp_checkstability )
11713 {
11714 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11715
11716 if( success )
11717 return SCIP_OKAY;
11718 }
11719 }
11720 }
11721
11722 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11723 * and go directly to solving the LP from scratch
11724 */
11725 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11726 {
11727 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11728 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11729 if( success )
11730 {
11731 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11732 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11733 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11734
11735 /* check for stability */
11736 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11737 return SCIP_OKAY;
11738
11739 if( !set->lp_checkstability )
11740 {
11741 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11742
11743 if( success )
11744 return SCIP_OKAY;
11745 }
11746
11747 /* reset scaling */
11748 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11749 assert(success);
11750 }
11751 }
11752
11753 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11754 * and go directly to solving the LP from scratch */
11755 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11756 {
11757 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11758 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11759 if( success )
11760 {
11761 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11762 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11763 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11764
11765 /* check for stability */
11766 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11767 return SCIP_OKAY;
11768
11769 if( !set->lp_checkstability )
11770 {
11771 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11772
11773 if( success )
11774 return SCIP_OKAY;
11775 }
11776
11777 /* reset presolving */
11778 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11779 assert(success);
11780 }
11781 }
11782
11783 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11784 * do this only if the iteration limit was not exceeded in the last LP solving call
11785 */
11786 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11787 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11788 {
11789 success = FALSE;
11790 if( !tightprimfeastol )
11791 {
11792 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11793 }
11794
11795 success2 = FALSE;
11796 if( !tightdualfeastol )
11797 {
11798 SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) );
11799 }
11800
11801 success3 = FALSE;
11802 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11803 {
11804 SCIP_CALL( lpSetBarrierconvtol(lp, FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set), &success3) );
11805 }
11806
11807 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11808 if( success || success2 || success3 )
11809 {
11810 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11811 lpalgoName(lpalgo));
11812 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11813
11814 /* check for stability */
11815 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11816 return SCIP_OKAY;
11817
11818 if( !set->lp_checkstability )
11819 {
11820 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11821
11822 if( success )
11823 return SCIP_OKAY;
11824 }
11825
11826 /* reset feasibility tolerance */
11827 if( !tightprimfeastol )
11828 {
11829 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11830 }
11831 if( !tightdualfeastol )
11832 {
11833 SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
11834 }
11835 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11836 {
11837 SCIP_CALL( lpSetBarrierconvtol(lp, SCIPsetBarrierconvtol(set), &success) );
11838 }
11839 }
11840 }
11841
11842 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11843 * the given iteration limit might be a soft one to restrict resolving calls only */
11844 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11845
11846 /* if not already done, solve again from scratch */
11847 if( !fromscratch && simplex )
11848 {
11849 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11850 if( success )
11851 {
11852 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11853 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11854
11855 /* check for stability */
11856 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11857 return SCIP_OKAY;
11858
11859 if( !set->lp_checkstability )
11860 {
11861 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11862
11863 if( success )
11864 return SCIP_OKAY;
11865 }
11866 }
11867 }
11868
11869 /* solve again, use other simplex this time */
11870 if( simplex )
11871 {
11872 lpalgo = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX ? SCIP_LPALGO_DUALSIMPLEX : SCIP_LPALGO_PRIMALSIMPLEX);
11873 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11874 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11875
11876 /* check for stability */
11877 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11878 return SCIP_OKAY;
11879
11880 if( !set->lp_checkstability )
11881 {
11882 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11883
11884 if( success )
11885 return SCIP_OKAY;
11886 }
11887
11888 /* solve again with opposite scaling and other simplex */
11889 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11890 if( success )
11891 {
11892 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11893 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11894 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11895
11896 /* check for stability */
11897 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11898 return SCIP_OKAY;
11899
11900 if( !set->lp_checkstability )
11901 {
11902 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11903
11904 if( success )
11905 return SCIP_OKAY;
11906 }
11907
11908 /* reset scaling */
11909 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11910 assert(success);
11911 }
11912
11913 /* solve again with opposite presolving and other simplex */
11914 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11915 if( success )
11916 {
11917 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11918 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11919 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11920
11921 /* check for stability */
11922 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11923 return SCIP_OKAY;
11924
11925 if( !set->lp_checkstability )
11926 {
11927 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11928
11929 if( success )
11930 return SCIP_OKAY;
11931 }
11932
11933 /* reset presolving */
11934 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11935 assert(success);
11936 }
11937
11938 /* solve again with tighter feasibility tolerance, use other simplex this time */
11939 if( !tightprimfeastol || !tightdualfeastol )
11940 {
11941 success = FALSE;
11942 if( !tightprimfeastol )
11943 {
11944 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11945 }
11946
11947 success2 = FALSE;
11948 if( !tightdualfeastol )
11949 {
11950 SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) );
11951 }
11952
11953 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11954 if( success || success2 )
11955 {
11956 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11957 lpalgoName(lpalgo));
11958 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11959
11960 /* check for stability */
11961 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11962 return SCIP_OKAY;
11963
11964 if( !set->lp_checkstability )
11965 {
11966 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11967
11968 if( success )
11969 return SCIP_OKAY;
11970 }
11971
11972 /* reset feasibility tolerance */
11973 if( !tightprimfeastol )
11974 {
11975 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11976 }
11977 if( !tightdualfeastol )
11978 {
11979 SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
11980 }
11981 SCIP_UNUSED(success);
11982 }
11983 }
11984 }
11985
11986 /* nothing worked -- exit with an LPERROR */
11987 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11988 *lperror = TRUE;
11989
11990 return SCIP_OKAY;
11991 }
11992
11993 /** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
11994 static
11995 void adjustLPobjval(
11996 SCIP_LP* lp, /**< current LP data */
11997 SCIP_SET* set, /**< global SCIP settings */
11998 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
11999 )
12000 {
12001 assert(lp != NULL);
12002 assert(set != NULL);
12003
12004 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12005 {
12006 if( !lp->adjustlpval && messagehdlr != NULL )
12007 {
12008 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12009 lp->adjustlpval = TRUE;
12010 }
12011 lp->lpobjval = SCIPsetInfinity(set);
12012 }
12013 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12014 {
12015 if( !lp->adjustlpval && messagehdlr != NULL )
12016 {
12017 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12018 lp->adjustlpval = TRUE;
12019 }
12020 lp->lpobjval = -SCIPsetInfinity(set);
12021 }
12022 }
12023
12024 /** solves the LP with the given algorithm and evaluates return status */
12025 static
12026 SCIP_RETCODE lpSolve(
12027 SCIP_LP* lp, /**< current LP data */
12028 SCIP_SET* set, /**< global SCIP settings */
12029 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12030 SCIP_STAT* stat, /**< problem statistics */
12031 SCIP_PROB* prob, /**< problem data */
12032 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12033 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12034 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12035 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12036 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12037 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12038 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12039 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12040 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12041 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12042 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12043 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12044 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12045 )
12046 {
12047 SCIP_Bool solvedprimal;
12048 SCIP_Bool solveddual;
12049 SCIP_Bool timelimit;
12050 int itlim;
12051
12052 assert(lp != NULL);
12053 assert(lp->flushed);
12054 assert(set != NULL);
12055 assert(stat != NULL);
12056 assert(lperror != NULL);
12057
12058 checkLinks(lp);
12059
12060 solvedprimal = FALSE;
12061 solveddual = FALSE;
12062 timelimit = FALSE;
12063
12064 /* select the basic iteration limit depending on whether this is a resolving call or not */
12065 itlim = ( resolve ? resolveitlim : harditlim );
12066
12067 SOLVEAGAIN:
12068 /* call simplex */
12069 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12070 scaling, keepsol, &timelimit, lperror) );
12071 resolve = FALSE; /* only the first solve should be counted as resolving call */
12072 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12073 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12074
12075 /* check, if an error occurred */
12076 if( *lperror )
12077 {
12078 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12079 lp->solved = FALSE;
12080 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12081 return SCIP_OKAY;
12082 }
12083
12084 /* check, if a time limit was exceeded */
12085 if( timelimit )
12086 {
12087 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12088 lp->solved = TRUE;
12089 lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT;
12090 lp->lpobjval = -SCIPsetInfinity(set);
12091 return SCIP_OKAY;
12092 }
12093
12094 /* only one should return true */
12095 assert(!(SCIPlpiIsOptimal(lp->lpi) && SCIPlpiIsObjlimExc(lp->lpi) && SCIPlpiIsPrimalInfeasible(lp->lpi) &&
12096 SCIPlpiExistsPrimalRay(lp->lpi) && SCIPlpiIsIterlimExc(lp->lpi) && SCIPlpiIsTimelimExc(lp->lpi)));
12097
12098 /* evaluate solution status */
12099 if( SCIPlpiIsOptimal(lp->lpi) )
12100 {
12101 assert(lp->primalfeasible);
12102 assert(lp->dualfeasible);
12103 lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
12104 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12105 adjustLPobjval(lp, set, messagehdlr);
12106
12107 if( !SCIPsetIsInfinity(set, lp->lpiobjlim) && SCIPsetIsGE(set, lp->lpobjval, lp->lpiobjlim) )
12108 {
12109 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12110 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12111 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12112 lp->lpobjval = SCIPsetInfinity(set);
12113 }
12114 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12115 * reached if the LP objective value is greater than the cutoff bound
12116 */
12117 assert(lpCutoffDisabled(set, prob) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || SCIPsetIsInfinity(set, lp->cutoffbound)
12118 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12119 }
12120 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12121 {
12122 assert(!lpCutoffDisabled(set, prob));
12123
12124 #ifndef NDEBUG
12125 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12126 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12127 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12128 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12129 #endif
12130
12131 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12132 lp->lpobjval = SCIPsetInfinity(set);
12133 }
12134 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12135 {
12136 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12137 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12138 {
12139 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12140 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12141 goto SOLVEAGAIN;
12142 }
12143 lp->lpsolstat = SCIP_LPSOLSTAT_INFEASIBLE;
12144 lp->lpobjval = SCIPsetInfinity(set);
12145 }
12146 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12147 {
12148 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12149 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12150 {
12151 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12152 assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
12153 lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
12154 goto SOLVEAGAIN;
12155 }
12156 lp->lpsolstat = SCIP_LPSOLSTAT_UNBOUNDEDRAY;
12157 lp->lpobjval = -SCIPsetInfinity(set);
12158 }
12159 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12160 {
12161 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12162
12163 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12164 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12165 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12166 adjustLPobjval(lp, set, NULL);
12167 else
12168 adjustLPobjval(lp, set, messagehdlr);
12169
12170 lp->lpsolstat = SCIP_LPSOLSTAT_ITERLIMIT;
12171 }
12172 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12173 {
12174 lp->lpobjval = -SCIPsetInfinity(set);
12175 lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT;
12176 }
12177 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12178 {
12179 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12180 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12181 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12182 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12183 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12184 goto SOLVEAGAIN;
12185 }
12186 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12187 {
12188 assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
12189 lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
12190 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12191 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12192 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12193 goto SOLVEAGAIN;
12194 }
12195 else
12196 {
12197 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12198 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12199 lp->lpsolstat = SCIP_LPSOLSTAT_ERROR;
12200 return SCIP_LPERROR;
12201 }
12202
12203 lp->solved = TRUE;
12204
12205 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12206 lpalgoName(lp->lastlpalgo), lp->lpsolstat, SCIPlpiGetInternalStatus(lp->lpi),
12207 SCIPlpiIsPrimalFeasible(lp->lpi), SCIPlpiIsDualFeasible(lp->lpi));
12208
12209 return SCIP_OKAY;
12210 }
12211
12212 /** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12213 static
12214 SCIP_RETCODE lpFlushAndSolve(
12215 SCIP_LP* lp, /**< current LP data */
12216 BMS_BLKMEM* blkmem, /**< block memory */
12217 SCIP_SET* set, /**< global SCIP settings */
12218 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12219 SCIP_STAT* stat, /**< problem statistics */
12220 SCIP_PROB* prob, /**< problem data */
12221 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12222 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12223 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12224 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12225 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12226 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12227 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12228 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12229 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12230 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12231 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12232 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12233 )
12234 {
12235 SCIP_Bool resolve;
12236 char algo;
12237
12238 assert(lp != NULL);
12239 assert(set != NULL);
12240 assert(lperror != NULL);
12241
12242 /* flush changes to the LP solver */
12243 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12244 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12245
12246 /* select LP algorithm to apply */
12247 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12248 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12249
12250 switch( algo )
12251 {
12252 case 's':
12253 /* select simplex method */
12254 if( lp->dualfeasible || !lp->primalfeasible )
12255 {
12256 SCIPsetDebugMsg(set, "solving dual LP\n");
12257 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12258 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12259 }
12260 else
12261 {
12262 SCIPsetDebugMsg(set, "solving primal LP\n");
12263 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12264 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12265 }
12266 break;
12267
12268 case 'p':
12269 SCIPsetDebugMsg(set, "solving primal LP\n");
12270 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12271 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12272 break;
12273
12274 case 'd':
12275 SCIPsetDebugMsg(set, "solving dual LP\n");
12276 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12277 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12278 break;
12279
12280 case 'b':
12281 SCIPsetDebugMsg(set, "solving barrier LP\n");
12282 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12283 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12284 break;
12285
12286 case 'c':
12287 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12288 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12289 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12290 break;
12291
12292 default:
12293 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12294 return SCIP_PARAMETERWRONGVAL;
12295 }
12296 assert(!(*lperror) || !lp->solved);
12297
12298 return SCIP_OKAY;
12299 }
12300
12301 #ifndef NDEBUG
12302 /** checks if the lazy bounds are valid */
12303 static
12304 void checkLazyBounds(
12305 SCIP_LP* lp, /**< LP data */
12306 SCIP_SET* set /**< global SCIP settings */
12307 )
12308 {
12309 SCIP_COL* col;
12310 int c;
12311
12312 assert(lp->flushed);
12313
12314 for( c = 0; c < lp->nlazycols; ++c )
12315 {
12316 col = lp->lazycols[c];
12317
12318 /* in case lazy bounds are given, check that the primal solution satisfies them */
12319 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12320 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12321 }
12322 }
12323 #else
12324 #define checkLazyBounds(lp, set) /**/
12325 #endif
12326
12327 /** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12328 * diving
12329 */
12330 static
12331 SCIP_RETCODE updateLazyBounds(
12332 SCIP_LP* lp, /**< LP data */
12333 SCIP_SET* set /**< global SCIP settings */
12334 )
12335 {
12336 SCIP_COL* col;
12337 int c;
12338
12339 assert(lp->nlazycols > 0);
12340
12341 /* return, if we are in diving, and bounds were already applied
12342 * or if we are not in diving and bounds were not applied
12343 */
12344 if( lp->diving == lp->divinglazyapplied )
12345 return SCIP_OKAY;
12346
12347 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12348 lp->diving, lp->divinglazyapplied);
12349
12350 for( c = 0; c < lp->nlazycols; ++c )
12351 {
12352 col = lp->lazycols[c];
12353
12354 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12355 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12356 {
12357 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12358 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12359 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12360
12361 /* insert column in the chgcols list (if not already there) */
12362 SCIP_CALL( insertColChgcols(col, set, lp) );
12363
12364 /* mark bound change in the column */
12365 col->lbchanged = TRUE;
12366 }
12367
12368 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12369 if( !SCIPsetIsInfinity(set, col->lazyub) )
12370 {
12371 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12372 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12373 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12374
12375 /* insert column in the chgcols list (if not already there) */
12376 SCIP_CALL( insertColChgcols(col, set, lp) );
12377
12378 /* mark bound change in the column */
12379 col->ubchanged = TRUE;
12380 }
12381 }
12382
12383 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12384 * if not, we just removed them
12385 */
12386 lp->divinglazyapplied = lp->diving;
12387
12388 return SCIP_OKAY;
12389 }
12390
12391 /** returns the iteration limit for an LP resolving call */
12392 static
12393 int lpGetResolveItlim(
12394 SCIP_SET* set, /**< global SCIP settings */
12395 SCIP_STAT* stat, /**< dynamic problem statistics */
12396 int itlim /**< hard iteration limit */
12397 )
12398 {
12399 /* no limit set or average not yet reliable */
12400 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12401 return itlim;
12402 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12403 if( itlim == -1 )
12404 itlim = INT_MAX;
12405 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12406 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12407 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12408 }
12409
12410
12411
12412 /** solves the LP with simplex algorithm, and copy the solution into the column's data */
12413 SCIP_RETCODE SCIPlpSolveAndEval(
12414 SCIP_LP* lp, /**< LP data */
12415 SCIP_SET* set, /**< global SCIP settings */
12416 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12417 BMS_BLKMEM* blkmem, /**< block memory buffers */
12418 SCIP_STAT* stat, /**< problem statistics */
12419 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12420 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12421 SCIP_PROB* prob, /**< problem data */
12422 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12423 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12424 * (limit is computed within the method w.r.t. the average LP iterations) */
12425 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12426 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12427 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12428 )
12429 {
12430 SCIP_RETCODE retcode;
12431 SCIP_Bool needprimalray;
12432 SCIP_Bool needdualray;
12433 int harditlim;
12434 int resolveitlim;
12435
12436 assert(lp != NULL);
12437 assert(prob != NULL);
12438 assert(prob->nvars >= lp->ncols);
12439 assert(lperror != NULL);
12440
12441 retcode = SCIP_OKAY;
12442 *lperror = FALSE;
12443
12444 if( lp->flushed && lp->solved )
12445 {
12446 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12447 return SCIP_OKAY;
12448 }
12449
12450 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12451 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12452
12453 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12454 needprimalray = TRUE;
12455 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12456 || (set->conf_enable && set->conf_useinflp != 'o'));
12457
12458 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12459 harditlim = (int) MIN(itlim, INT_MAX);
12460 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12461 assert(harditlim == -1 || (resolveitlim <= harditlim));
12462
12463 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12464 * or removed from the LP (diving was ended)
12465 */
12466 if( lp->nlazycols > 0 )
12467 {
12468 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12469 * first resolve LP?
12470 */
12471 SCIP_CALL( updateLazyBounds(lp, set) );
12472 assert(lp->diving == lp->divinglazyapplied);
12473 }
12474
12475 /* flush changes to the LP solver */
12476 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12477 assert(lp->flushed);
12478
12479 /* if the time limit was reached in the last call and the LP did not change, lp->solved is set to TRUE, but we want
12480 * to run again anyway, since there seems to be some time left / the time limit was increased
12481 */
12482 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12483 {
12484 SCIP_Bool* primalfeaspointer;
12485 SCIP_Bool* dualfeaspointer;
12486 SCIP_Bool primalfeasible;
12487 SCIP_Bool dualfeasible;
12488 SCIP_Bool farkasvalid;
12489 SCIP_Bool rayfeasible;
12490 SCIP_Bool tightprimfeastol;
12491 SCIP_Bool tightdualfeastol;
12492 SCIP_Bool fromscratch;
12493 SCIP_Bool wasfromscratch;
12494 int scaling;
12495 SCIP_Longint oldnlps;
12496 int fastmip;
12497
12498 /* set initial LP solver settings */
12499 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12500 tightprimfeastol = FALSE;
12501 tightdualfeastol = FALSE;
12502 fromscratch = FALSE;
12503 primalfeasible = FALSE;
12504 dualfeasible = FALSE;
12505 wasfromscratch = (stat->nlps == 0);
12506 scaling = set->lp_scaling;
12507
12508 SOLVEAGAIN:
12509 /* solve the LP */
12510 oldnlps = stat->nlps;
12511 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12512 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12513 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12514 assert(!(*lperror) || !lp->solved);
12515
12516 /* check for error */
12517 if( *lperror )
12518 {
12519 retcode = SCIP_OKAY;
12520 goto TERMINATE;
12521 }
12522
12523 /* evaluate solution status */
12524 switch( SCIPlpGetSolstat(lp) )
12525 {
12526 case SCIP_LPSOLSTAT_OPTIMAL:
12527 /* get LP solution and possibly check the solution's feasibility again */
12528 if( set->lp_checkprimfeas )
12529 {
12530 primalfeaspointer = &primalfeasible;
12531 lp->primalchecked = TRUE;
12532 }
12533 else
12534 {
12535 /* believe in the primal feasibility of the LP solution */
12536 primalfeasible = TRUE;
12537 primalfeaspointer = NULL;
12538 lp->primalchecked = FALSE;
12539 }
12540 if( set->lp_checkdualfeas )
12541 {
12542 dualfeaspointer = &dualfeasible;
12543 lp->dualchecked = TRUE;
12544 }
12545 else
12546 {
12547 /* believe in the dual feasibility of the LP solution */
12548 dualfeasible = TRUE;
12549 dualfeaspointer = NULL;
12550 lp->dualchecked = FALSE;
12551 }
12552
12553 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12554
12555 /* in debug mode, check that lazy bounds (if present) are not violated */
12556 checkLazyBounds(lp, set);
12557
12558 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12559 {
12560 /* update ages and remove obsolete columns and rows from LP */
12561 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12562 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12563 {
12564 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12565 }
12566
12567 if( !lp->solved )
12568 {
12569 /* resolve LP after removing obsolete columns and rows */
12570 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12571 aging = FALSE; /* to prevent infinite loops */
12572 goto SOLVEAGAIN;
12573 }
12574 }
12575 if( !primalfeasible || !dualfeasible )
12576 {
12577 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12578
12579 if( (fastmip > 0) && simplex )
12580 {
12581 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12582 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12583 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12584 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12585 fastmip = 0;
12586 goto SOLVEAGAIN;
12587 }
12588 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12589 {
12590 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12591 * tolerance
12592 */
12593 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12594 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12595 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12596 tightprimfeastol = tightprimfeastol || !primalfeasible;
12597 tightdualfeastol = tightdualfeastol || !dualfeasible;
12598 goto SOLVEAGAIN;
12599 }
12600 else if( !fromscratch && !wasfromscratch && simplex )
12601 {
12602 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12603 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12604 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12605 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12606 fromscratch = TRUE;
12607 goto SOLVEAGAIN;
12608 }
12609 else
12610 {
12611 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12612 lp->solved = FALSE;
12613 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12614 *lperror = TRUE;
12615 }
12616 }
12617 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12618 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12619 lp->lpsolstat, lp->cutoffbound);
12620 break;
12621
12622 case SCIP_LPSOLSTAT_INFEASIBLE:
12623 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12624 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve || set->lp_alwaysgetduals )
12625 {
12626 if( SCIPlpiHasDualRay(lp->lpi) )
12627 {
12628 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12629 }
12630 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12631 * with the primal simplex due to numerical problems) - treat this case like an LP error
12632 */
12633 else
12634 {
12635 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12636 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12637 lp->solved = FALSE;
12638 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12639 farkasvalid = FALSE;
12640 *lperror = TRUE;
12641 }
12642 }
12643 else
12644 farkasvalid = TRUE;
12645
12646 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12647 if( !farkasvalid && !(*lperror) )
12648 {
12649 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12650
12651 if( (fastmip > 0) && simplex )
12652 {
12653 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12654 * without FASTMIP
12655 */
12656 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12657 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12658 stat->nnodes, stat->nlps);
12659 fastmip = 0;
12660 goto SOLVEAGAIN;
12661 }
12662 else if( !tightdualfeastol )
12663 {
12664 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12665 * solve again with tighter feasibility tolerance
12666 */
12667 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12668 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12669 stat->nnodes, stat->nlps);
12670 tightdualfeastol = TRUE;
12671 goto SOLVEAGAIN;
12672 }
12673 else if( !fromscratch && simplex )
12674 {
12675 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12676 * from scratch
12677 */
12678 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12679 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12680 stat->nnodes, stat->nlps);
12681 fromscratch = TRUE;
12682 goto SOLVEAGAIN;
12683 }
12684 else
12685 {
12686 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12687 * helped forget about the LP at this node and mark it to be unsolved
12688 */
12689 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12690 lp->solved = FALSE;
12691 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12692 *lperror = TRUE;
12693 }
12694 }
12695
12696 break;
12697
12698 case SCIP_LPSOLSTAT_UNBOUNDEDRAY:
12699 if( set->lp_checkprimfeas )
12700 {
12701 /* get unbounded LP solution and check the solution's feasibility again */
12702 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12703
12704 lp->primalchecked = TRUE;
12705 }
12706 else
12707 {
12708 /* get unbounded LP solution believing in the feasibility of the LP solution */
12709 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
12710
12711 primalfeasible = TRUE;
12712 rayfeasible = TRUE;
12713 lp->primalchecked = FALSE;
12714 }
12715
12716 /* in debug mode, check that lazy bounds (if present) are not violated */
12717 checkLazyBounds(lp, set);
12718
12719 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12720 primalfeasible, rayfeasible);
12721
12722 if( !primalfeasible || !rayfeasible )
12723 {
12724 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12725
12726 if( (fastmip > 0) && simplex )
12727 {
12728 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12729 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12730 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12731 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12732 fastmip = 0;
12733 goto SOLVEAGAIN;
12734 }
12735 else if( !tightprimfeastol )
12736 {
12737 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12738 * tolerance
12739 */
12740 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12741 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again with tighter primal feasibility tolerance\n",
12742 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12743 tightprimfeastol = TRUE;
12744 goto SOLVEAGAIN;
12745 }
12746 else if( !fromscratch && simplex )
12747 {
12748 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12749 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12750 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12751 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12752 fromscratch = TRUE;
12753 goto SOLVEAGAIN;
12754 }
12755 else if( scaling > 0 )
12756 {
12757 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12758 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12759 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12760 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12761 scaling = 0;
12762 goto SOLVEAGAIN;
12763 }
12764 else
12765 {
12766 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12767 * forget about the LP at this node and mark it to be unsolved
12768 */
12769 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12770 lp->solved = FALSE;
12771 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12772 *lperror = TRUE;
12773 }
12774 }
12775
12776 break;
12777
12778 case SCIP_LPSOLSTAT_OBJLIMIT:
12779 assert(!lpCutoffDisabled(set, prob));
12780 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12781 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12782 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12783 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12784 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12785 * FASTMIP and solve again. */
12786 if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
12787 {
12788 SCIP_LPI* lpi;
12789 SCIP_Real objval;
12790
12791 lpi = SCIPlpGetLPI(lp);
12792
12793 assert(lpi != NULL);
12794 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12795 * the assert by using !SCIPsetIsFeasNegative()
12796 */
12797 assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim));
12798
12799 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12800
12801 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12802 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12803 {
12804 SCIP_Real tmpcutoff;
12805 char tmppricingchar;
12806 SCIP_LPSOLSTAT solstat;
12807
12808 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12809
12810 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12811 fromscratch = FALSE;
12812
12813 /* temporarily disable cutoffbound, which also disables the objective limit */
12814 tmpcutoff = lp->cutoffbound;
12815 lp->cutoffbound = SCIPlpiInfinity(lpi);
12816
12817 /* set lp pricing strategy to steepest edge */
12818 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12819 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12820
12821 /* resolve LP with an iteration limit of 1 */
12822 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12823 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12824
12825 /* reinstall old cutoff bound and lp pricing strategy */
12826 lp->cutoffbound = tmpcutoff;
12827 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12828
12829 /* get objective value */
12830 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12831
12832 /* get solution status for the lp */
12833 solstat = SCIPlpGetSolstat(lp);
12834 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12835
12836 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12837
12838 /* the solution is still not exceeding the objective limit and the solving process
12839 * was stopped due to time or iteration limit, solve again with fastmip turned off
12840 */
12841 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12842 SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12843 {
12844 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12845 if( !(lperror) && (fastmip > 0) && simplex )
12846 {
12847 fastmip = 0;
12848 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12849 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12850
12851 /* get objective value */
12852 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12853
12854 /* get solution status for the lp */
12855 solstat = SCIPlpGetSolstat(lp);
12856
12857 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12858 }
12859 }/*lint !e438*/
12860
12861 /* check for lp errors */
12862 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12863 {
12864 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12865 lp->solved = FALSE;
12866 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12867
12868 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12869 goto TERMINATE;
12870 }
12871
12872 lp->solved = TRUE;
12873
12874 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12875 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12876 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12877 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12878 {
12879 /* get LP solution and possibly check the solution's feasibility again */
12880 if( set->lp_checkprimfeas )
12881 {
12882 primalfeaspointer = &primalfeasible;
12883 lp->primalchecked = TRUE;
12884 }
12885 else
12886 {
12887 /* believe in the primal feasibility of the LP solution */
12888 primalfeasible = TRUE;
12889 primalfeaspointer = NULL;
12890 lp->primalchecked = FALSE;
12891 }
12892 if( set->lp_checkdualfeas )
12893 {
12894 dualfeaspointer = &dualfeasible;
12895 lp->dualchecked = TRUE;
12896 }
12897 else
12898 {
12899 /* believe in the dual feasibility of the LP solution */
12900 dualfeasible = TRUE;
12901 dualfeaspointer = NULL;
12902 lp->dualchecked = FALSE;
12903 }
12904
12905 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12906
12907 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12908 if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12909 {
12910 checkLazyBounds(lp, set);
12911 }
12912
12913 /* if objective value is larger than the cutoff bound, set solution status to objective
12914 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12915 * this was already done in the lpSolve() method
12916 */
12917 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12918 {
12919 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12920 lp->lpobjval = SCIPsetInfinity(set);
12921 }
12922
12923 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12924 * the cutoffbound; mark the LP to be unsolved
12925 */
12926 if( !primalfeasible || !dualfeasible
12927 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12928 !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
12929 {
12930 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12931 lp->solved = FALSE;
12932 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12933 *lperror = TRUE;
12934 }
12935
12936 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12937 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12938 lp->lpsolstat, lp->cutoffbound);
12939 }
12940 /* infeasible solution */
12941 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12942 {
12943 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12944
12945 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve )
12946 {
12947 if( SCIPlpiHasDualRay(lp->lpi) )
12948 {
12949 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12950 }
12951 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12952 * with the primal simplex due to numerical problems) - treat this case like an LP error
12953 */
12954 else
12955 {
12956 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12957 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12958 lp->solved = FALSE;
12959 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12960 farkasvalid = FALSE;
12961 *lperror = TRUE;
12962 }
12963 }
12964 else
12965 farkasvalid = TRUE;
12966
12967 if( !farkasvalid )
12968 {
12969 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12970
12971 if( !tightprimfeastol )
12972 {
12973 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12974 * solve again with tighter feasibility tolerance
12975 */
12976 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12977 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12978 stat->nnodes, stat->nlps);
12979 tightprimfeastol = TRUE;
12980 goto SOLVEAGAIN;
12981 }
12982 else if( simplex )
12983 {
12984 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12985 * from scratch
12986 */
12987 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12988 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12989 stat->nnodes, stat->nlps);
12990 fromscratch = TRUE;
12991 goto SOLVEAGAIN;
12992 }
12993 else
12994 {
12995 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12996 * helped forget about the LP at this node and mark it to be unsolved
12997 */
12998 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12999 lp->solved = FALSE;
13000 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
13001 *lperror = TRUE;
13002 }
13003 }
13004 }
13005 /* unbounded solution */
13006 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13007 {
13008 if( set->lp_checkprimfeas )
13009 {
13010 /* get unbounded LP solution and check the solution's feasibility again */
13011 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13012
13013 lp->primalchecked = TRUE;
13014 }
13015 else
13016 {
13017 /* get unbounded LP solution believing in its feasibility */
13018 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
13019
13020 primalfeasible = TRUE;
13021 rayfeasible = TRUE;
13022 lp->primalchecked = FALSE;
13023 }
13024
13025 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13026
13027 /* in debug mode, check that lazy bounds (if present) are not violated */
13028 checkLazyBounds(lp, set);
13029
13030 if( !primalfeasible || !rayfeasible )
13031 {
13032 /* unbounded solution is infeasible (this can happen due to numerical problems):
13033 * forget about the LP at this node and mark it to be unsolved
13034 *
13035 * @todo: like in the default LP solving evaluation, solve without fastmip,
13036 * with tighter feasibility tolerance and from scratch
13037 */
13038 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13039 lp->solved = FALSE;
13040 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
13041 *lperror = TRUE;
13042 }
13043 }
13044
13045 assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
13046 assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
13047 || lp->lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT);
13048 }
13049 else
13050 {
13051 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13052 }
13053 }
13054 SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13055 break;
13056
13057 case SCIP_LPSOLSTAT_ITERLIMIT:
13058 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13059 break;
13060
13061 case SCIP_LPSOLSTAT_TIMELIMIT:
13062 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13063
13064 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13065 stat->nclockskipsleft = 0;
13066 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13067 {
13068 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13069 "you might consider switching the clock type of SCIP\n");
13070 stat->status = SCIP_STATUS_TIMELIMIT;
13071 }
13072 break;
13073
13074 case SCIP_LPSOLSTAT_ERROR:
13075 case SCIP_LPSOLSTAT_NOTSOLVED:
13076 SCIPerrorMessage("error in LP solver\n");
13077 retcode = SCIP_LPERROR;
13078 goto TERMINATE;
13079
13080 default:
13081 SCIPerrorMessage("unknown LP solution status\n");
13082 retcode = SCIP_ERROR;
13083 goto TERMINATE;
13084 }
13085 }
13086 assert(!(*lperror) || !lp->solved);
13087
13088 TERMINATE:
13089 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13090 * may happen that we continue to solve from scratch during strong branching */
13091 if( lp->lpifromscratch )
13092 {
13093 SCIP_Bool success;
13094 (void) lpSetFromscratch(lp, FALSE, &success);
13095 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13096 SCIP_UNUSED(success);
13097 }
13098
13099 return retcode;
13100 }
13101
13102 /** gets solution status of current LP */
13103 SCIP_LPSOLSTAT SCIPlpGetSolstat(
13104 SCIP_LP* lp /**< current LP data */
13105 )
13106 {
13107 assert(lp != NULL);
13108 assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
13109
13110 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13111 }
13112
13113 /** gets objective value of current LP
13114 *
13115 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13116 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13117 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13118 */
13119 SCIP_Real SCIPlpGetObjval(
13120 SCIP_LP* lp, /**< current LP data */
13121 SCIP_SET* set, /**< global SCIP settings */
13122 SCIP_PROB* prob /**< problem data */
13123 )
13124 {
13125 assert(lp != NULL);
13126 assert(lp->solved);
13127 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13128 assert(set != NULL);
13129
13130 if( !lp->flushed )
13131 return SCIP_INVALID;
13132 else if( SCIPsetIsInfinity(set, lp->lpobjval) || SCIPsetIsInfinity(set, -lp->lpobjval))
13133 return lp->lpobjval;
13134 else if( lp->looseobjvalinf > 0 )
13135 return -SCIPsetInfinity(set);
13136 else
13137 {
13138 /* recalculate the loose objective value, if needed */
13139 if( !lp->looseobjvalid )
13140 recomputeLooseObjectiveValue(lp, set, prob);
13141
13142 return lp->lpobjval + lp->looseobjval;
13143 }
13144 }
13145
13146 /** gets part of objective value of current LP that results from COLUMN variables only */
13147 SCIP_Real SCIPlpGetColumnObjval(
13148 SCIP_LP* lp /**< current LP data */
13149 )
13150 {
13151 assert(lp != NULL);
13152 assert(lp->solved);
13153
13154 return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13155 }
13156
13157 /** gets part of objective value of current LP that results from LOOSE variables only */
13158 SCIP_Real SCIPlpGetLooseObjval(
13159 SCIP_LP* lp, /**< current LP data */
13160 SCIP_SET* set, /**< global SCIP settings */
13161 SCIP_PROB* prob /**< problem data */
13162 )
13163 {
13164 assert(lp != NULL);
13165 assert(lp->solved);
13166 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13167 assert(set != NULL);
13168
13169 if( !lp->flushed )
13170 return SCIP_INVALID;
13171 else if( lp->looseobjvalinf > 0 )
13172 return -SCIPsetInfinity(set);
13173 else
13174 return getFiniteLooseObjval(lp, set, prob);
13175 }
13176
13177 /** remembers the current LP objective value as root solution value */
13178 void SCIPlpStoreRootObjval(
13179 SCIP_LP* lp, /**< current LP data */
13180 SCIP_SET* set, /**< global SCIP settings */
13181 SCIP_PROB* prob /**< problem data */
13182 )
13183 {
13184 assert(lp != NULL);
13185
13186 lp->rootlpobjval = SCIPlpGetColumnObjval(lp);
13187 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13188 }
13189
13190 /** invalidates the root LP solution value */
13191 void SCIPlpInvalidateRootObjval(
13192 SCIP_LP* lp /**< current LP data */
13193 )
13194 {
13195 assert(lp != NULL);
13196
13197 lp->rootlpobjval = SCIP_INVALID;
13198 lp->rootlooseobjval = SCIP_INVALID;
13199 }
13200
13201 /** recomputes local and global pseudo objective values */
13202 void SCIPlpRecomputeLocalAndGlobalPseudoObjval(
13203 SCIP_LP* lp, /**< current LP data */
13204 SCIP_SET* set, /**< global SCIP settings */
13205 SCIP_PROB* prob /**< problem data */
13206 )
13207 {
13208 SCIP_VAR** vars;
13209 int nvars;
13210 int v;
13211
13212 assert(lp != NULL);
13213 assert(set != NULL);
13214 assert(prob != NULL);
13215
13216 vars = prob->vars;
13217 nvars = prob->nvars;
13218
13219 lp->glbpseudoobjvalinf = 0;
13220 lp->glbpseudoobjval = 0.0;
13221
13222 lp->pseudoobjvalinf = 0;
13223 lp->pseudoobjval = 0.0;
13224
13225 for( v = 0; v < nvars; ++v )
13226 {
13227 SCIP_Real obj = SCIPvarGetObj(vars[v]);
13228
13229 if( SCIPsetIsPositive(set, obj) )
13230 {
13231 /* update the global pseudo objective value */
13232 if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
13233 ++(lp->glbpseudoobjvalinf);
13234 else
13235 lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
13236
13237 /* update the local pseudo objective value */
13238 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
13239 ++(lp->pseudoobjvalinf);
13240 else
13241 lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
13242 }
13243
13244 if( SCIPsetIsNegative(set, obj) )
13245 {
13246 /* update the global pseudo objective value */
13247 if( SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
13248 ++(lp->glbpseudoobjvalinf);
13249 else
13250 lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
13251
13252 /* update the local pseudo objective value */
13253 if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
13254 ++(lp->pseudoobjvalinf);
13255 else
13256 lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
13257 }
13258 }
13259
13260 /* the recomputed values are reliable */
13261 lp->relglbpseudoobjval = lp->glbpseudoobjval;
13262 lp->glbpseudoobjvalid = TRUE;
13263 lp->relpseudoobjval = lp->pseudoobjval;
13264 lp->pseudoobjvalid = TRUE;
13265 }
13266
13267 /** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13268 * global bound
13269 */
13270 SCIP_Real SCIPlpGetGlobalPseudoObjval(
13271 SCIP_LP* lp, /**< current LP data */
13272 SCIP_SET* set, /**< global SCIP settings */
13273 SCIP_PROB* prob /**< problem data */
13274 )
13275 {
13276 assert(lp != NULL);
13277 assert(lp->glbpseudoobjvalinf >= 0);
13278 assert(set != NULL);
13279
13280 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13281 return -SCIPsetInfinity(set);
13282 else
13283 {
13284 /* recalculate the global pseudo solution value, if needed */
13285 if( !lp->glbpseudoobjvalid )
13286 recomputeGlbPseudoObjectiveValue(lp, set, prob);
13287
13288 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13289 if( SCIPsetIsInfinity(set, -lp->glbpseudoobjval) )
13290 return -SCIPsetInfinity(set);
13291
13292 if( SCIPsetIsInfinity(set, lp->glbpseudoobjval) )
13293 return SCIPsetInfinity(set);
13294
13295 return lp->glbpseudoobjval;
13296 }
13297 }
13298
13299 /** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13300 * objective function) local bound
13301 */
13302 SCIP_Real SCIPlpGetPseudoObjval(
13303 SCIP_LP* lp, /**< current LP data */
13304 SCIP_SET* set, /**< global SCIP settings */
13305 SCIP_PROB* prob /**< problem data */
13306 )
13307 {
13308 assert(lp != NULL);
13309 assert(lp->pseudoobjvalinf >= 0);
13310 assert(set != NULL);
13311
13312 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13313 return -SCIPsetInfinity(set);
13314 else
13315 {
13316 /* recalculate the pseudo solution value, if needed */
13317 if( !lp->pseudoobjvalid )
13318 recomputePseudoObjectiveValue(lp, set, prob);
13319
13320 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13321 if( SCIPsetIsInfinity(set, -lp->pseudoobjval) )
13322 return -SCIPsetInfinity(set);
13323
13324 if( SCIPsetIsInfinity(set, lp->pseudoobjval) )
13325 return SCIPsetInfinity(set);
13326
13327 return lp->pseudoobjval;
13328 }
13329 }
13330
13331 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13332 SCIP_Real SCIPlpGetModifiedPseudoObjval(
13333 SCIP_LP* lp, /**< current LP data */
13334 SCIP_SET* set, /**< global SCIP settings */
13335 SCIP_PROB* prob, /**< problem data */
13336 SCIP_VAR* var, /**< problem variable */
13337 SCIP_Real oldbound, /**< old value for bound */
13338 SCIP_Real newbound, /**< new value for bound */
13339 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13340 )
13341 {
13342 SCIP_Real pseudoobjval;
13343 int pseudoobjvalinf;
13344 SCIP_Real obj;
13345
13346 pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13347 pseudoobjvalinf = lp->pseudoobjvalinf;
13348 obj = SCIPvarGetObj(var);
13349 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13350 {
13351 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13352 pseudoobjvalinf--;
13353 else
13354 pseudoobjval -= oldbound * obj;
13355 assert(pseudoobjvalinf >= 0);
13356 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13357 pseudoobjvalinf++;
13358 else
13359 pseudoobjval += newbound * obj;
13360 }
13361 assert(pseudoobjvalinf >= 0);
13362
13363 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13364 return -SCIPsetInfinity(set);
13365 else
13366 return pseudoobjval;
13367 }
13368
13369 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13370 * perform calculations with interval arithmetic to get an exact lower bound
13371 */
13372 SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(
13373 SCIP_LP* lp, /**< current LP data */
13374 SCIP_SET* set, /**< global SCIP settings */
13375 SCIP_VAR* var, /**< problem variable */
13376 SCIP_Real oldbound, /**< old value for bound */
13377 SCIP_Real newbound, /**< new value for bound */
13378 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13379 )
13380 {
13381 SCIP_Real pseudoobjval;
13382 int pseudoobjvalinf;
13383 SCIP_Real obj;
13384
13385 assert(lp->pseudoobjvalid);
13386
13387 pseudoobjval = lp->pseudoobjval;
13388 pseudoobjvalinf = lp->pseudoobjvalinf;
13389 obj = SCIPvarGetObj(var);
13390 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13391 {
13392 SCIP_INTERVAL objint;
13393 SCIP_INTERVAL bd;
13394 SCIP_INTERVAL prod;
13395 SCIP_INTERVAL psval;
13396
13397 SCIPintervalSet(&psval, pseudoobjval);
13398 SCIPintervalSet(&objint, SCIPvarGetObj(var));
13399
13400 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13401 pseudoobjvalinf--;
13402 else
13403 {
13404 SCIPintervalSet(&bd, oldbound);
13405 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13406 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13407 }
13408 assert(pseudoobjvalinf >= 0);
13409 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13410 pseudoobjvalinf++;
13411 else
13412 {
13413 SCIPintervalSet(&bd, newbound);
13414 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13415 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13416 }
13417
13418 pseudoobjval = SCIPintervalGetInf(psval);
13419 }
13420 assert(pseudoobjvalinf >= 0);
13421
13422 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13423 return -SCIPsetInfinity(set);
13424 else
13425 return pseudoobjval;
13426 }
13427
13428 /** compute the objective delta due the new objective coefficient */
13429 static
13430 void getObjvalDeltaObj(
13431 SCIP_SET* set, /**< global SCIP settings */
13432 SCIP_Real oldobj, /**< old objective value of variable */
13433 SCIP_Real newobj, /**< new objective value of variable */
13434 SCIP_Real lb, /**< lower bound of variable */
13435 SCIP_Real ub, /**< upper bound of variable */
13436 SCIP_Real* deltaval, /**< pointer to store the delta value */
13437 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13438 )
13439 {
13440 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13441 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13442 assert(!SCIPsetIsInfinity(set, lb));
13443 assert(!SCIPsetIsInfinity(set, -ub));
13444 assert(!SCIPsetIsEQ(set, oldobj, newobj));
13445
13446 (*deltaval) = 0.0;
13447 (*deltainf) = 0;
13448
13449 if( SCIPsetIsPositive(set, oldobj) )
13450 {
13451 /* sign of objective did not change */
13452 if( SCIPsetIsPositive(set, newobj) )
13453 {
13454 /* if the bound is finite, calculate the deltaval */
13455 if( !SCIPsetIsInfinity(set, -lb) )
13456 (*deltaval) = lb * (newobj - oldobj);
13457 }
13458 /* sign of objective did change, so the best bound does change */
13459 else if( SCIPsetIsNegative(set, newobj) )
13460 {
13461 if( SCIPsetIsInfinity(set, -lb) )
13462 {
13463 /* old best bound was infinite while new one is not */
13464 if( !SCIPsetIsInfinity(set, ub) )
13465 {
13466 (*deltainf) = -1;
13467 (*deltaval) = ub * newobj;
13468 }
13469 }
13470 else
13471 {
13472 /* new best bound is infinite while old one was not */
13473 if( SCIPsetIsInfinity(set, ub) )
13474 {
13475 (*deltainf) = 1;
13476 (*deltaval) = -lb * oldobj;
13477 }
13478 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13479 else
13480 {
13481 (*deltaval) = (ub * newobj) - (lb * oldobj);
13482 }
13483 }
13484 }
13485 /* new objective is 0.0 */
13486 else
13487 {
13488 if( SCIPsetIsInfinity(set, -lb) )
13489 (*deltainf) = -1;
13490 else
13491 (*deltaval) = -lb * oldobj;
13492 }
13493 }
13494 else if( SCIPsetIsNegative(set, oldobj) )
13495 {
13496 /* sign of objective did not change */
13497 if( SCIPsetIsNegative(set, newobj) )
13498 {
13499 /* if the bound is finite, calculate the deltaval */
13500 if( !SCIPsetIsInfinity(set, ub) )
13501 (*deltaval) = ub * (newobj - oldobj);
13502 }
13503 /* sign of objective did change, so the best bound does change */
13504 else if( SCIPsetIsPositive(set, newobj) )
13505 {
13506 if( SCIPsetIsInfinity(set, ub) )
13507 {
13508 /* old best bound was infinite while new one is not */
13509 if( !SCIPsetIsInfinity(set, -lb) )
13510 {
13511 (*deltainf) = -1;
13512 (*deltaval) = lb * newobj;
13513 }
13514 }
13515 else
13516 {
13517 /* new best bound is infinite while old one was not */
13518 if( SCIPsetIsInfinity(set, -lb) )
13519 {
13520 (*deltainf) = 1;
13521 (*deltaval) = -ub * oldobj;
13522 }
13523 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13524 else
13525 {
13526 (*deltaval) = (lb * newobj) - (ub * oldobj);
13527 }
13528 }
13529 }
13530 /* new objective is 0.0 */
13531 else
13532 {
13533 if( SCIPsetIsInfinity(set, ub) )
13534 (*deltainf) = -1;
13535 else
13536 (*deltaval) = -ub * oldobj;
13537 }
13538 }
13539 /* old objective was 0.0 */
13540 else
13541 {
13542 if( SCIPsetIsNegative(set, newobj) )
13543 {
13544 if( SCIPsetIsInfinity(set, ub) )
13545 (*deltainf) = 1;
13546 else
13547 (*deltaval) = ub * newobj;
13548 }
13549 else if( SCIPsetIsPositive(set, newobj) )
13550 {
13551 if( SCIPsetIsInfinity(set, -lb) )
13552 (*deltainf) = 1;
13553 else
13554 (*deltaval) = lb * newobj;
13555 }
13556 }
13557 }
13558
13559 /** compute the objective delta due the new lower bound */
13560 static
13561 void getObjvalDeltaLb(
13562 SCIP_SET* set, /**< global SCIP settings */
13563 SCIP_Real obj, /**< objective value of variable */
13564 SCIP_Real oldlb, /**< old lower bound of variable */
13565 SCIP_Real newlb, /**< new lower bound of variable */
13566 SCIP_Real* deltaval, /**< pointer to store the delta value */
13567 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13568 )
13569 {
13570 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13571 assert(!SCIPsetIsInfinity(set, oldlb));
13572 assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
13573 assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
13574
13575 if( SCIPsetIsInfinity(set, -oldlb) )
13576 {
13577 if( !SCIPsetIsInfinity(set, newlb) )
13578 {
13579 (*deltainf) = -1;
13580 (*deltaval) = newlb * obj;
13581 }
13582 else
13583 {
13584 (*deltainf) = 0;
13585 (*deltaval) = 0.0;
13586 }
13587 }
13588 else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
13589 {
13590 (*deltainf) = 1;
13591 (*deltaval) = -oldlb * obj;
13592 }
13593 else
13594 {
13595 (*deltainf) = 0;
13596 (*deltaval) = obj * (newlb - oldlb);
13597 }
13598 }
13599
13600 /** compute the objective delta due the new upper bound */
13601 static
13602 void getObjvalDeltaUb(
13603 SCIP_SET* set, /**< global SCIP settings */
13604 SCIP_Real obj, /**< objective value of variable */
13605 SCIP_Real oldub, /**< old upper bound of variable */
13606 SCIP_Real newub, /**< new upper bound of variable */
13607 SCIP_Real* deltaval, /**< pointer to store the delta value */
13608 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13609 )
13610 {
13611 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13612 assert(!SCIPsetIsInfinity(set, -oldub));
13613 assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
13614 assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
13615
13616 if( SCIPsetIsInfinity(set, oldub) )
13617 {
13618 if( !SCIPsetIsInfinity(set, -newub) )
13619 {
13620 (*deltainf) = -1;
13621 (*deltaval) = newub * obj;
13622 }
13623 else
13624 {
13625 (*deltainf) = 0;
13626 (*deltaval) = 0.0;
13627 }
13628 }
13629 else if( SCIPsetIsInfinity(set, REALABS(newub)) )
13630 {
13631 (*deltainf) = 1;
13632 (*deltaval) = -oldub * obj;
13633 }
13634 else
13635 {
13636 (*deltainf) = 0;
13637 (*deltaval) = obj * (newub - oldub);
13638 }
13639 }
13640
13641 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13642 static
13643 void lpUpdateObjval(
13644 SCIP_LP* lp, /**< current LP data */
13645 SCIP_SET* set, /**< global SCIP settings */
13646 SCIP_VAR* var, /**< problem variable that changed */
13647 SCIP_Real deltaval, /**< delta value in the objective function */
13648 int deltainf, /**< delta value for the number of variables with infinite best bound */
13649 SCIP_Bool local, /**< should the local pseudo objective value be updated? */
13650 SCIP_Bool loose, /**< should the loose objective value be updated? */
13651 SCIP_Bool global /**< should the global pseudo objective value be updated? */
13652 )
13653 {
13654 assert(lp != NULL);
13655 assert(lp->looseobjvalinf >= 0);
13656 assert(lp->pseudoobjvalinf >= 0);
13657 assert(lp->glbpseudoobjvalinf >= 0);
13658
13659 /* update the pseudo objective value */
13660 if( local )
13661 {
13662 lp->pseudoobjvalinf += deltainf;
13663 if( lp->pseudoobjvalid )
13664 {
13665 lp->pseudoobjval += deltaval;
13666
13667 /* if the absolute value was increased, this is regarded as reliable,
13668 * otherwise, we check whether we can still trust the updated value
13669 */
13670 if( REALABS(lp->relpseudoobjval) < REALABS(lp->pseudoobjval) )
13671 lp->relpseudoobjval = lp->pseudoobjval;
13672 else if( SCIPsetIsUpdateUnreliable(set, lp->pseudoobjval, lp->relpseudoobjval) )
13673 lp->pseudoobjvalid = FALSE;
13674 }
13675
13676 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13677 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
13678 loose = TRUE;
13679 }
13680 /* update the loose objective value */
13681 if( loose )
13682 {
13683 lp->looseobjvalinf += deltainf;
13684
13685 if( deltaval != 0.0 && lp->looseobjvalid )
13686 {
13687 lp->looseobjval += deltaval;
13688
13689 /* if the absolute value was increased, this is regarded as reliable,
13690 * otherwise, we check whether we can still trust the updated value
13691 */
13692 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13693 lp->rellooseobjval = lp->looseobjval;
13694 else if( SCIPsetIsUpdateUnreliable(set, lp->looseobjval, lp->rellooseobjval) )
13695 lp->looseobjvalid = FALSE;
13696 }
13697 }
13698 /* update the root pseudo objective values */
13699 if( global )
13700 {
13701 lp->glbpseudoobjvalinf += deltainf;
13702 if( lp->glbpseudoobjvalid )
13703 {
13704 lp->glbpseudoobjval += deltaval;
13705
13706 /* if the absolute value was increased, this is regarded as reliable,
13707 * otherwise, we check whether we can still trust the updated value
13708 */
13709 if( REALABS(lp->relglbpseudoobjval) < REALABS(lp->glbpseudoobjval) )
13710 lp->relglbpseudoobjval = lp->glbpseudoobjval;
13711 else if( SCIPsetIsUpdateUnreliable(set, lp->glbpseudoobjval, lp->relglbpseudoobjval) )
13712 lp->glbpseudoobjvalid = FALSE;
13713 }
13714 }
13715
13716 assert(lp->looseobjvalinf >= 0);
13717 assert(lp->pseudoobjvalinf >= 0);
13718 assert(lp->glbpseudoobjvalinf >= 0);
13719 }
13720
13721 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13722 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13723 */
13724 static
13725 SCIP_RETCODE lpUpdateVarProved(
13726 SCIP_LP* lp, /**< current LP data */
13727 SCIP_SET* set, /**< global SCIP settings */
13728 SCIP_VAR* var, /**< problem variable that changed */
13729 SCIP_Real oldobj, /**< old objective value of variable */
13730 SCIP_Real oldlb, /**< old objective value of variable */
13731 SCIP_Real oldub, /**< old objective value of variable */
13732 SCIP_Real newobj, /**< new objective value of variable */
13733 SCIP_Real newlb, /**< new objective value of variable */
13734 SCIP_Real newub /**< new objective value of variable */
13735 )
13736 {
13737 SCIP_INTERVAL deltaval;
13738 SCIP_INTERVAL bd;
13739 SCIP_INTERVAL obj;
13740 SCIP_INTERVAL prod;
13741 SCIP_INTERVAL psval;
13742 int deltainf;
13743
13744 assert(lp != NULL);
13745 assert(lp->pseudoobjvalinf >= 0);
13746 assert(lp->looseobjvalinf >= 0);
13747 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13748 assert(!SCIPsetIsInfinity(set, oldlb));
13749 assert(!SCIPsetIsInfinity(set, -oldub));
13750 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13751 assert(!SCIPsetIsInfinity(set, newlb));
13752 assert(!SCIPsetIsInfinity(set, -newub));
13753 assert(var != NULL);
13754
13755 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
13756 {
13757 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13758 return SCIP_INVALIDDATA;
13759 }
13760
13761 assert(SCIPvarGetProbindex(var) >= 0);
13762
13763 SCIPintervalSet(&deltaval, 0.0);
13764 deltainf = 0;
13765
13766 /* subtract old pseudo objective value */
13767 if( oldobj > 0.0 )
13768 {
13769 if( SCIPsetIsInfinity(set, -oldlb) )
13770 deltainf--;
13771 else
13772 {
13773 SCIPintervalSet(&bd, oldlb);
13774 SCIPintervalSet(&obj, oldobj);
13775 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13776 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
13777 }
13778 }
13779 else if( oldobj < 0.0 )
13780 {
13781 if( SCIPsetIsInfinity(set, oldub) )
13782 deltainf--;
13783 else
13784 {
13785 SCIPintervalSet(&bd, oldub);
13786 SCIPintervalSet(&obj, oldobj);
13787 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13788 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
13789 }
13790 }
13791
13792 /* add new pseudo objective value */
13793 if( newobj > 0.0 )
13794 {
13795 if( SCIPsetIsInfinity(set, -newlb) )
13796 deltainf++;
13797 else
13798 {
13799 SCIPintervalSet(&bd, newlb);
13800 SCIPintervalSet(&obj, newobj);
13801 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13802 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
13803 }
13804 }
13805 else if( newobj < 0.0 )
13806 {
13807 if( SCIPsetIsInfinity(set, newub) )
13808 deltainf++;
13809 else
13810 {
13811 SCIPintervalSet(&bd, newub);
13812 SCIPintervalSet(&obj, newobj);
13813 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13814 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
13815 }
13816 }
13817
13818 /* update the pseudo and loose objective values */
13819 SCIPintervalSet(&psval, lp->pseudoobjval);
13820 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13821 lp->pseudoobjval = SCIPintervalGetInf(psval);
13822 lp->pseudoobjvalinf += deltainf;
13823 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
13824 {
13825 SCIPintervalSet(&psval, lp->looseobjval);
13826 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13827 lp->looseobjval = SCIPintervalGetInf(psval);
13828 lp->looseobjvalinf += deltainf;
13829 }
13830
13831 assert(lp->pseudoobjvalinf >= 0);
13832 assert(lp->looseobjvalinf >= 0);
13833
13834 return SCIP_OKAY;
13835 }
13836
13837 /** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13838 SCIP_RETCODE SCIPlpUpdateVarObj(
13839 SCIP_LP* lp, /**< current LP data */
13840 SCIP_SET* set, /**< global SCIP settings */
13841 SCIP_VAR* var, /**< problem variable that changed */
13842 SCIP_Real oldobj, /**< old objective coefficient of variable */
13843 SCIP_Real newobj /**< new objective coefficient of variable */
13844 )
13845 {
13846 assert(set != NULL);
13847 assert(var != NULL);
13848
13849 if( set->misc_exactsolve )
13850 {
13851 if( oldobj != newobj ) /*lint !e777*/
13852 {
13853 SCIP_CALL( lpUpdateVarProved(lp, set, var, oldobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
13854 newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
13855 }
13856 }
13857 else
13858 {
13859 if( !SCIPsetIsEQ(set, oldobj, newobj) )
13860 {
13861 SCIP_Real deltaval;
13862 int deltainf;
13863
13864 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13865 assert(SCIPvarGetProbindex(var) >= 0);
13866
13867 /* the objective coefficient can only be changed during presolving, that implies that the global and local
13868 * domain of the variable are the same
13869 */
13870 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
13871 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
13872
13873 /* compute the pseudo objective delta due the new objective coefficient */
13874 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
13875
13876 /* update the local pseudo objective value */
13877 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13878
13879 /* compute the pseudo objective delta due the new objective coefficient */
13880 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
13881
13882 /* update the global pseudo objective value */
13883 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13884 }
13885 }
13886
13887 return SCIP_OKAY;
13888 }
13889
13890
13891 /** updates current root pseudo objective value for a global change in a variable's lower bound */
13892 SCIP_RETCODE SCIPlpUpdateVarLbGlobal(
13893 SCIP_LP* lp, /**< current LP data */
13894 SCIP_SET* set, /**< global SCIP settings */
13895 SCIP_VAR* var, /**< problem variable that changed */
13896 SCIP_Real oldlb, /**< old lower bound of variable */
13897 SCIP_Real newlb /**< new lower bound of variable */
13898 )
13899 {
13900 assert(set != NULL);
13901 assert(var != NULL);
13902
13903 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13904 {
13905 SCIP_Real deltaval;
13906 int deltainf;
13907
13908 /* compute the pseudo objective delta due the new lower bound */
13909 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13910
13911 /* update the root pseudo objective values */
13912 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13913 }
13914
13915 return SCIP_OKAY;
13916 }
13917
13918 /** updates current pseudo and loose objective value for a change in a variable's lower bound */
13919 SCIP_RETCODE SCIPlpUpdateVarLb(
13920 SCIP_LP* lp, /**< current LP data */
13921 SCIP_SET* set, /**< global SCIP settings */
13922 SCIP_VAR* var, /**< problem variable that changed */
13923 SCIP_Real oldlb, /**< old lower bound of variable */
13924 SCIP_Real newlb /**< new lower bound of variable */
13925 )
13926 {
13927 assert(set != NULL);
13928 assert(var != NULL);
13929
13930 if( set->misc_exactsolve )
13931 {
13932 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13933 {
13934 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
13935 SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
13936 }
13937 }
13938 else
13939 {
13940 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13941 {
13942 SCIP_Real deltaval;
13943 int deltainf;
13944
13945 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13946 assert(SCIPvarGetProbindex(var) >= 0);
13947
13948 /* compute the pseudo objective delta due the new lower bound */
13949 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13950
13951 /* update the pseudo and loose objective values */
13952 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13953 }
13954 }
13955
13956 return SCIP_OKAY;
13957 }
13958
13959 /** updates current root pseudo objective value for a global change in a variable's upper bound */
13960 SCIP_RETCODE SCIPlpUpdateVarUbGlobal(
13961 SCIP_LP* lp, /**< current LP data */
13962 SCIP_SET* set, /**< global SCIP settings */
13963 SCIP_VAR* var, /**< problem variable that changed */
13964 SCIP_Real oldub, /**< old upper bound of variable */
13965 SCIP_Real newub /**< new upper bound of variable */
13966 )
13967 {
13968 assert(set != NULL);
13969 assert(var != NULL);
13970
13971 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13972 {
13973 SCIP_Real deltaval;
13974 int deltainf;
13975
13976 /* compute the pseudo objective delta due the new upper bound */
13977 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13978
13979 /* update the root pseudo objective values */
13980 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13981 }
13982
13983 return SCIP_OKAY;
13984 }
13985
13986 /** updates current pseudo objective value for a change in a variable's upper bound */
13987 SCIP_RETCODE SCIPlpUpdateVarUb(
13988 SCIP_LP* lp, /**< current LP data */
13989 SCIP_SET* set, /**< global SCIP settings */
13990 SCIP_VAR* var, /**< problem variable that changed */
13991 SCIP_Real oldub, /**< old upper bound of variable */
13992 SCIP_Real newub /**< new upper bound of variable */
13993 )
13994 {
13995 assert(set != NULL);
13996 assert(var != NULL);
13997
13998 if( set->misc_exactsolve )
13999 {
14000 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14001 {
14002 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
14003 SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
14004 }
14005 }
14006 else
14007 {
14008 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14009 {
14010 SCIP_Real deltaval;
14011 int deltainf;
14012
14013 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14014 assert(SCIPvarGetProbindex(var) >= 0);
14015
14016 /* compute the pseudo objective delta due the new upper bound */
14017 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14018
14019 /* update the pseudo and loose objective values */
14020 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14021 }
14022 }
14023
14024 return SCIP_OKAY;
14025 }
14026
14027 /** informs LP, that given variable was added to the problem */
14028 SCIP_RETCODE SCIPlpUpdateAddVar(
14029 SCIP_LP* lp, /**< current LP data */
14030 SCIP_SET* set, /**< global SCIP settings */
14031 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
14032 )
14033 {
14034 assert(lp != NULL);
14035 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14036 assert(SCIPvarGetProbindex(var) >= 0);
14037
14038 /* add the variable to the loose objective value sum */
14039 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
14040
14041 /* update the loose variables counter */
14042 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
14043 lp->nloosevars++;
14044
14045 return SCIP_OKAY;
14046 }
14047
14048 /** informs LP, that given variable is to be deleted from the problem */
14049 SCIP_RETCODE SCIPlpUpdateDelVar(
14050 SCIP_LP* lp, /**< current LP data */
14051 SCIP_SET* set, /**< global SCIP settings */
14052 SCIP_VAR* var /**< variable that will be deleted from the problem */
14053 )
14054 {
14055 assert(lp != NULL);
14056 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14057 assert(SCIPvarGetProbindex(var) >= 0);
14058
14059 /* subtract the variable from the loose objective value sum */
14060 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
14061
14062 /* update the loose variables counter */
14063 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
14064 {
14065 SCIPlpDecNLoosevars(lp);
14066 }
14067
14068 return SCIP_OKAY;
14069 }
14070
14071 /** informs LP, that given formerly loose problem variable is now a column variable */
14072 static
14073 SCIP_RETCODE lpUpdateVarColumn(
14074 SCIP_LP* lp, /**< current LP data */
14075 SCIP_SET* set, /**< global SCIP settings */
14076 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14077 )
14078 {
14079 SCIP_Real obj;
14080 SCIP_Real lb;
14081 SCIP_Real ub;
14082
14083 assert(lp != NULL);
14084 assert(lp->nloosevars > 0);
14085 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14086 assert(SCIPvarGetProbindex(var) >= 0);
14087 assert(lp->looseobjvalinf >= 0);
14088
14089 obj = SCIPvarGetObj(var);
14090
14091 /* update loose objective value */
14092 if( SCIPsetIsPositive(set, obj) )
14093 {
14094 lb = SCIPvarGetLbLocal(var);
14095 if( SCIPsetIsInfinity(set, -lb) )
14096 lp->looseobjvalinf--;
14097 else
14098 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14099 }
14100 else if( SCIPsetIsNegative(set, obj) )
14101 {
14102 ub = SCIPvarGetUbLocal(var);
14103 if( SCIPsetIsInfinity(set, ub) )
14104 lp->looseobjvalinf--;
14105 else
14106 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14107 }
14108
14109 SCIPlpDecNLoosevars(lp);
14110
14111 assert(lp->looseobjvalinf >= 0);
14112
14113 return SCIP_OKAY;
14114 }
14115
14116 /** informs LP, that given formerly loose problem variable is now a column variable
14117 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14118 */
14119 static
14120 SCIP_RETCODE lpUpdateVarColumnProved(
14121 SCIP_LP* lp, /**< current LP data */
14122 SCIP_SET* set, /**< global SCIP settings */
14123 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14124 )
14125 {
14126 SCIP_INTERVAL bd;
14127 SCIP_INTERVAL ob;
14128 SCIP_INTERVAL prod;
14129 SCIP_INTERVAL loose;
14130 SCIP_Real obj;
14131 SCIP_Real lb;
14132 SCIP_Real ub;
14133
14134 assert(lp != NULL);
14135 assert(lp->nloosevars > 0);
14136 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14137 assert(SCIPvarGetProbindex(var) >= 0);
14138
14139 obj = SCIPvarGetObj(var);
14140
14141 SCIPintervalSet(&loose, lp->looseobjval);
14142
14143 /* update loose objective value corresponding to the deletion of variable */
14144 if( obj > 0.0 )
14145 {
14146 lb = SCIPvarGetLbLocal(var);
14147 if( SCIPsetIsInfinity(set, -lb) )
14148 lp->looseobjvalinf--;
14149 else
14150 {
14151 SCIPintervalSet(&bd, lb);
14152 SCIPintervalSet(&ob, obj);
14153 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14154 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
14155 }
14156 }
14157 else if( SCIPsetIsNegative(set, obj) )
14158 {
14159 ub = SCIPvarGetUbLocal(var);
14160 if( SCIPsetIsInfinity(set, ub) )
14161 lp->looseobjvalinf--;
14162 else
14163 {
14164 SCIPintervalSet(&bd, ub);
14165 SCIPintervalSet(&ob, obj);
14166 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14167 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
14168 }
14169 }
14170 lp->nloosevars--;
14171
14172 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14173 if( lp->nloosevars == 0 )
14174 {
14175 assert(lp->looseobjvalinf == 0);
14176 lp->looseobjval = 0.0;
14177 }
14178 else
14179 lp->looseobjval = SCIPintervalGetInf(loose);
14180
14181 return SCIP_OKAY;
14182 }
14183
14184 /** informs LP, that given formerly loose problem variable is now a column variable */
14185 SCIP_RETCODE SCIPlpUpdateVarColumn(
14186 SCIP_LP* lp, /**< current LP data */
14187 SCIP_SET* set, /**< global SCIP settings */
14188 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14189 )
14190 {
14191 assert(set != NULL);
14192
14193 if( set->misc_exactsolve )
14194 {
14195 SCIP_CALL( lpUpdateVarColumnProved(lp, set, var) );
14196 }
14197 else
14198 {
14199 SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
14200 }
14201
14202 return SCIP_OKAY;
14203 }
14204
14205 /** informs LP, that given formerly column problem variable is now again a loose variable */
14206 static
14207 SCIP_RETCODE lpUpdateVarLoose(
14208 SCIP_LP* lp, /**< current LP data */
14209 SCIP_SET* set, /**< global SCIP settings */
14210 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14211 )
14212 {
14213 SCIP_Real obj;
14214 SCIP_Real lb;
14215 SCIP_Real ub;
14216
14217 assert(lp != NULL);
14218 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14219 assert(SCIPvarGetProbindex(var) >= 0);
14220 assert(lp->looseobjvalinf >= 0);
14221
14222 obj = SCIPvarGetObj(var);
14223
14224 /* update loose objective value corresponding to the addition of variable */
14225 if( SCIPsetIsPositive(set, obj) )
14226 {
14227 lb = SCIPvarGetLbLocal(var);
14228 if( SCIPsetIsInfinity(set, -lb) )
14229 lp->looseobjvalinf++;
14230 else
14231 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14232 }
14233 else if( SCIPsetIsNegative(set, obj) )
14234 {
14235 ub = SCIPvarGetUbLocal(var);
14236 if( SCIPsetIsInfinity(set, ub) )
14237 lp->looseobjvalinf++;
14238 else
14239 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14240 }
14241 lp->nloosevars++;
14242
14243 assert(lp->looseobjvalinf >= 0);
14244
14245 return SCIP_OKAY;
14246 }
14247
14248 /** informs LP, that given formerly column problem variable is now again a loose variable
14249 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14250 */
14251 static
14252 SCIP_RETCODE lpUpdateVarLooseProved(
14253 SCIP_LP* lp, /**< current LP data */
14254 SCIP_SET* set, /**< global SCIP settings */
14255 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14256 )
14257 {
14258 SCIP_INTERVAL bd;
14259 SCIP_INTERVAL ob;
14260 SCIP_INTERVAL prod;
14261 SCIP_INTERVAL loose;
14262 SCIP_Real obj;
14263 SCIP_Real lb;
14264 SCIP_Real ub;
14265
14266 assert(lp != NULL);
14267 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14268 assert(SCIPvarGetProbindex(var) >= 0);
14269
14270 obj = SCIPvarGetObj(var);
14271
14272 SCIPintervalSet(&loose, lp->looseobjval);
14273
14274 /* update loose objective value corresponding to the deletion of variable */
14275 if( obj > 0.0 )
14276 {
14277 lb = SCIPvarGetLbLocal(var);
14278 if( SCIPsetIsInfinity(set, -lb) )
14279 lp->looseobjvalinf++;
14280 else
14281 {
14282 SCIPintervalSet(&bd, lb);
14283 SCIPintervalSet(&ob, obj);
14284 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14285 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
14286 }
14287 }
14288 else if( SCIPsetIsNegative(set, obj) )
14289 {
14290 ub = SCIPvarGetUbLocal(var);
14291 if( SCIPsetIsInfinity(set, ub) )
14292 lp->looseobjvalinf++;
14293 else
14294 {
14295 SCIPintervalSet(&bd, ub);
14296 SCIPintervalSet(&ob, obj);
14297 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14298 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
14299 }
14300 }
14301 lp->nloosevars++;
14302
14303 lp->looseobjval = SCIPintervalGetInf(loose);
14304
14305 return SCIP_OKAY;
14306 }
14307
14308 /** informs LP, that given formerly column problem variable is now again a loose variable */
14309 SCIP_RETCODE SCIPlpUpdateVarLoose(
14310 SCIP_LP* lp, /**< current LP data */
14311 SCIP_SET* set, /**< global SCIP settings */
14312 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14313 )
14314 {
14315 assert(set != NULL);
14316
14317 if( set->misc_exactsolve )
14318 {
14319 SCIP_CALL( lpUpdateVarLooseProved(lp, set, var) );
14320 }
14321 else
14322 {
14323 SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
14324 }
14325
14326 return SCIP_OKAY;
14327 }
14328
14329 /** decrease the number of loose variables by one */
14330 void SCIPlpDecNLoosevars(
14331 SCIP_LP* lp /**< current LP data */
14332 )
14333 {
14334 assert(lp != NULL);
14335 assert(lp->nloosevars > 0);
14336
14337 lp->nloosevars--;
14338
14339 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14340 if( lp->nloosevars == 0 )
14341 {
14342 assert(lp->looseobjvalinf == 0);
14343 lp->looseobjval = 0.0;
14344 }
14345 }
14346
14347 /** stores the LP solution in the columns and rows */
14348 SCIP_RETCODE SCIPlpGetSol(
14349 SCIP_LP* lp, /**< current LP data */
14350 SCIP_SET* set, /**< global SCIP settings */
14351 SCIP_STAT* stat, /**< problem statistics */
14352 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14353 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
14354 )
14355 {
14356 SCIP_COL** lpicols;
14357 SCIP_ROW** lpirows;
14358 SCIP_Real* primsol;
14359 SCIP_Real* dualsol;
14360 SCIP_Real* activity = NULL;
14361 SCIP_Real* redcost;
14362 SCIP_Real primalbound;
14363 SCIP_Real dualbound;
14364 SCIP_Bool stillprimalfeasible;
14365 SCIP_Bool stilldualfeasible;
14366 int* cstat;
14367 int* rstat;
14368 SCIP_Longint lpcount;
14369 int nlpicols;
14370 int nlpirows;
14371 int c;
14372 int r;
14373
14374 assert(lp != NULL);
14375 assert(lp->flushed);
14376 assert(lp->solved);
14377 assert(set != NULL);
14378 assert(stat != NULL);
14379 assert(lp->validsollp <= stat->lpcount);
14380
14381 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
14382
14383 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14384 * corresponding flag immediately to FALSE to skip all checks
14385 */
14386 if( primalfeasible == NULL )
14387 stillprimalfeasible = FALSE;
14388 else
14389 {
14390 *primalfeasible = TRUE;
14391 stillprimalfeasible = TRUE;
14392 }
14393 if( dualfeasible == NULL )
14394 stilldualfeasible = FALSE;
14395 else
14396 {
14397 *dualfeasible = TRUE;
14398 stilldualfeasible = TRUE;
14399 }
14400
14401 /* check if the values are already calculated */
14402 if( lp->validsollp == stat->lpcount )
14403 return SCIP_OKAY;
14404 lp->validsollp = stat->lpcount;
14405
14406 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14407 stat->lpcount, SCIPlpGetSolstat(lp));
14408
14409 lpicols = lp->lpicols;
14410 lpirows = lp->lpirows;
14411 nlpicols = lp->nlpicols;
14412 nlpirows = lp->nlpirows;
14413 lpcount = stat->lpcount;
14414
14415 /* get temporary memory */
14416 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
14417 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14418 #ifdef SCIP_USE_LPSOLVER_ACTIVITY
14419 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14420 #endif
14421 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14422 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14423 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14424
14425 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14426 if( lp->solisbasic )
14427 {
14428 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14429 }
14430 else
14431 {
14432 BMSclearMemoryArray(cstat, nlpicols);
14433 BMSclearMemoryArray(rstat, nlpirows);
14434 }
14435
14436 primalbound = 0.0;
14437 dualbound = 0.0;
14438
14439 /* copy primal solution and reduced costs into columns */
14440 for( c = 0; c < nlpicols; ++c )
14441 {
14442 assert( 0 <= cstat[c] && cstat[c] < 4 );
14443 lpicols[c]->primsol = primsol[c];
14444 if( !SCIPisFinite(lpicols[c]->primsol) )
14445 {
14446 /* calculating with nan or +/-inf can have many unexpected effects
14447 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14448 * this should trigger a resolve of the LP, or a stop with an LP error
14449 */
14450 stillprimalfeasible = FALSE;
14451 stilldualfeasible = FALSE;
14452 lpicols[c]->primsol = 0.0;
14453 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14454 }
14455 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14456 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14457 lpicols[c]->redcost = redcost[c];
14458 lpicols[c]->basisstatus = (unsigned int) cstat[c];
14459 lpicols[c]->validredcostlp = lpcount;
14460 if( stillprimalfeasible )
14461 {
14462 stillprimalfeasible =
14463 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14464 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14465 primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14466 }
14467 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14468 {
14469 double compslack;
14470
14471 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14472 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14473 * variables, which would magnify even the tiniest violation in the dual multiplier
14474 */
14475 if( stilldualfeasible )
14476 {
14477 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14478 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14479 }
14480 if( stilldualfeasible )
14481 {
14482 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14483 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14484 }
14485
14486 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14487 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14488 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14489 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14490 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14491 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14492 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14493 dualfeasible != NULL ? stilldualfeasible : TRUE);
14494 }
14495 else
14496 {
14497 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14498 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14499 {
14500 lpicols[c]->redcost = 0.0;
14501 }
14502
14503 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14504 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14505 * bounds, its reduced cost must be zero
14506 */
14507 if( stilldualfeasible
14508 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14509 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14510 if( stilldualfeasible
14511 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14512 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14513
14514 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14515 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14516 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14517 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14518 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14519 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14520 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14521 dualfeasible != NULL ? stilldualfeasible : TRUE);
14522 }
14523
14524 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14525 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14526 * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14527 */
14528 if( stilldualfeasible )
14529 {
14530 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14531 dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14532 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14533 dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14534 }
14535 }
14536
14537 /* copy dual solution and activities into rows */
14538 for( r = 0; r < nlpirows; ++r )
14539 {
14540 assert( 0 <= rstat[r] && rstat[r] < 4 );
14541 lpirows[r]->dualsol = dualsol[r];
14542 #ifdef SCIP_USE_LPSOLVER_ACTIVITY
14543 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14544 #else
14545 /* calculate row activity if invalid */
14546 if( lpirows[r]->validactivitylp != stat->lpcount )
14547 SCIProwRecalcLPActivity(lpirows[r], stat);
14548 #endif
14549 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14550 lpirows[r]->validactivitylp = lpcount;
14551 if( stillprimalfeasible )
14552 {
14553 stillprimalfeasible =
14554 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14555 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14556 }
14557 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14558 {
14559 double compslack;
14560
14561 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14562 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14563 * variables, which would magnify even the tiniest violation in the dual multiplier
14564 */
14565 if( stilldualfeasible )
14566 {
14567 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14568 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14569 }
14570 if( stilldualfeasible )
14571 {
14572 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14573 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14574 }
14575
14576 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14577 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14578 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14579 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14580 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14581 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14582 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14583 dualfeasible != NULL ? stilldualfeasible : TRUE);
14584 }
14585 else
14586 {
14587 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14588 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14589 * strictly within left-hand and right-hand side, its dual multiplier must be zero
14590 */
14591 if( stilldualfeasible &&
14592 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14593 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14594 if( stilldualfeasible &&
14595 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14596 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14597
14598 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14599 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14600 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14601 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14602 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14603 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14604 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14605 dualfeasible != NULL ? stilldualfeasible : TRUE);
14606 }
14607
14608 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14609 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14610 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14611 */
14612 if( stilldualfeasible )
14613 {
14614 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14615 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14616 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14617 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14618 }
14619 }
14620
14621 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14622 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14623 * infinity
14624 */
14625 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14626 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14627 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14628 {
14629 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14630 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14631 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14632 }
14633
14634 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14635 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14636 */
14637 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14638 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14639 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14640 {
14641 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14642 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14643 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14644 }
14645
14646 if( primalfeasible != NULL )
14647 *primalfeasible = stillprimalfeasible;
14648 if( dualfeasible != NULL )
14649 *dualfeasible = stilldualfeasible;
14650
14651 /* free temporary memory */
14652 SCIPsetFreeBufferArray(set, &rstat);
14653 SCIPsetFreeBufferArray(set, &cstat);
14654 SCIPsetFreeBufferArray(set, &redcost);
14655 #ifdef SCIP_USE_LPSOLVER_ACTIVITY
14656 SCIPsetFreeBufferArray(set, &activity);
14657 #endif
14658 SCIPsetFreeBufferArray(set, &dualsol);
14659 SCIPsetFreeBufferArray(set, &primsol);
14660
14661 return SCIP_OKAY;
14662 }
14663
14664 /** stores LP solution with infinite objective value in the columns and rows */
14665 SCIP_RETCODE SCIPlpGetUnboundedSol(
14666 SCIP_LP* lp, /**< current LP data */
14667 SCIP_SET* set, /**< global SCIP settings */
14668 SCIP_STAT* stat, /**< problem statistics */
14669 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14670 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14671 )
14672 {
14673 SCIP_COL** lpicols;
14674 SCIP_ROW** lpirows;
14675 SCIP_Real* primsol;
14676 SCIP_Real* activity;
14677 SCIP_Real* ray;
14678 SCIP_Real rayobjval;
14679 SCIP_Real rayscale;
14680 SCIP_Longint lpcount;
14681 SCIP_COL* col;
14682 int nlpicols;
14683 int nlpirows;
14684 int c;
14685 int r;
14686
14687 assert(lp != NULL);
14688 assert(lp->flushed);
14689 assert(lp->solved);
14690 assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
14691 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
14692 assert(set != NULL);
14693 assert(stat != NULL);
14694 assert(lp->validsollp <= stat->lpcount);
14695
14696 if( primalfeasible != NULL )
14697 *primalfeasible = TRUE;
14698 if( rayfeasible != NULL )
14699 *rayfeasible = TRUE;
14700
14701 /* check if the values are already calculated */
14702 if( lp->validsollp == stat->lpcount )
14703 return SCIP_OKAY;
14704 lp->validsollp = stat->lpcount;
14705
14706 /* check if the LP solver is able to provide a primal unbounded ray */
14707 if( !SCIPlpiHasPrimalRay(lp->lpi) )
14708 {
14709 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14710 return SCIP_LPERROR;
14711 }
14712
14713 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14714
14715 /* get temporary memory */
14716 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
14717 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14718 SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, lp->nlpicols) );
14719
14720 /* get primal unbounded ray */
14721 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14722
14723 lpicols = lp->lpicols;
14724 lpirows = lp->lpirows;
14725 nlpicols = lp->nlpicols;
14726 nlpirows = lp->nlpirows;
14727 lpcount = stat->lpcount;
14728
14729 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14730 rayobjval = 0.0;
14731 for( c = 0; c < nlpicols; ++c )
14732 {
14733 assert(lpicols[c] != NULL);
14734 assert(lpicols[c]->var != NULL);
14735
14736 col = lpicols[c];
14737
14738 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14739 if( rayfeasible != NULL )
14740 {
14741 *rayfeasible = *rayfeasible
14742 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14743 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub));
14744 }
14745
14746 if( ! SCIPsetIsZero(set, ray[c]) )
14747 rayobjval += ray[c] * col->obj;
14748
14749 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14750 * heuristically try to construct a primal solution.
14751 */
14752 primsol[c] = 0.0;
14753 if( SCIPsetIsFeasZero(set, ray[c]) )
14754 {
14755 /* if the ray component is 0, we try to satisfy as many rows as possible */
14756 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14757 primsol[c] = col->lb;
14758 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14759 primsol[c] = col->ub;
14760 }
14761
14762 /* make sure we respect the bounds */
14763 primsol[c] = MAX(primsol[c], col->lb);
14764 primsol[c] = MIN(primsol[c], col->ub);
14765
14766 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14767 }
14768
14769 /* check feasibility of heuristic primal solution */
14770 for( r = 0; r < nlpirows; ++r )
14771 {
14772 SCIP_Real act;
14773 SCIP_ROW* row;
14774
14775 row = lpirows[r];
14776 assert( row != NULL );
14777 act = row->constant;
14778
14779 for( c = 0; c < row->nlpcols; ++c )
14780 {
14781 col = row->cols[c];
14782
14783 assert( col != NULL );
14784 assert( col->lppos >= 0 );
14785 assert( row->linkpos[c] >= 0 );
14786 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14787
14788 act += row->vals[c] * primsol[col->lppos];
14789 }
14790
14791 if( row->nunlinked > 0 )
14792 {
14793 for( c = row->nlpcols; c < row->len; ++c )
14794 {
14795 col = row->cols[c];
14796 assert( col != NULL );
14797
14798 if( col->lppos >= 0 )
14799 act += row->vals[c] * primsol[col->lppos];
14800 }
14801 }
14802
14803 /* check feasibility */
14804 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14805 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14806 break;
14807 }
14808
14809 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14810 if( r < nlpirows )
14811 {
14812 /* get primal feasible point */
14813 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
14814
14815 /* check bounds of primal solution */
14816 if( primalfeasible != NULL )
14817 {
14818 assert( *primalfeasible );
14819 for( c = 0; c < nlpicols; ++c )
14820 {
14821 assert( lpicols[c] != NULL );
14822 assert( lpicols[c]->var != NULL );
14823
14824 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14825 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14826 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14827 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14828 {
14829 *primalfeasible = FALSE;
14830 break;
14831 }
14832 }
14833 }
14834 }
14835
14836 /* compute activity and check feasibility of primal solution and ray */
14837 for( r = 0; r < nlpirows; ++r )
14838 {
14839 SCIP_Real primact;
14840 SCIP_Real rayact = 0.0;
14841 SCIP_ROW* row;
14842
14843 row = lpirows[r];
14844 assert( row != NULL );
14845
14846 primact = row->constant;
14847
14848 for( c = 0; c < row->nlpcols; ++c )
14849 {
14850 col = row->cols[c];
14851
14852 assert( col != NULL );
14853 assert( col->lppos >= 0 );
14854 assert( row->linkpos[c] >= 0 );
14855 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14856
14857 primact += row->vals[c] * primsol[col->lppos];
14858 rayact += row->vals[c] * ray[col->lppos];
14859 }
14860
14861 if( row->nunlinked > 0 )
14862 {
14863 for( c = row->nlpcols; c < row->len; ++c )
14864 {
14865 col = row->cols[c];
14866 assert( col != NULL );
14867
14868 if( col->lppos >= 0 )
14869 {
14870 primact += row->vals[c] * primsol[col->lppos];
14871 rayact += row->vals[c] * ray[col->lppos];
14872 }
14873 }
14874 }
14875
14876 /* check feasibility of primal solution */
14877 if( primalfeasible != NULL && *primalfeasible )
14878 {
14879 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14880 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14881 *primalfeasible = FALSE;
14882 }
14883
14884 /* check feasibility of ray */
14885 if( rayfeasible != NULL && *rayfeasible )
14886 {
14887 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14888 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14889 *rayfeasible = FALSE;
14890 }
14891
14892 /* store activity of primal solution */
14893 activity[r] = primact;
14894 }
14895
14896 if( primalfeasible != NULL && !(*primalfeasible) )
14897 {
14898 /* if the finite point is already infeasible, we do not have to add the ray */
14899 rayscale = 0.0;
14900 }
14901 else if( rayfeasible != NULL && !(*rayfeasible) )
14902 {
14903 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14904 rayscale = 0.0;
14905 }
14906 else if( !SCIPsetIsNegative(set, rayobjval) )
14907 {
14908 /* due to numerical problems, the objective of the ray might be nonnegative
14909 *
14910 * @todo How to check for negative objective value here?
14911 */
14912 if( rayfeasible != NULL )
14913 *rayfeasible = FALSE;
14914
14915 rayscale = 0.0;
14916 }
14917 else
14918 {
14919 assert(rayobjval != 0.0);
14920
14921 /* scale the ray, such that the resulting point has infinite objective value */
14922 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14923 assert(SCIPsetIsFeasPositive(set, rayscale));
14924
14925 /* ensure that unbounded point does not violate the bounds of the variables */
14926 for( c = 0; c < nlpicols; ++c )
14927 {
14928 if( SCIPsetIsPositive(set, ray[c]) )
14929 {
14930 if( !SCIPsetIsInfinity(set, primsol[c]) )
14931 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14932 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14933 else
14934 {
14935 assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14936 rayscale = MIN(rayscale, 1.0 / ray[c]);
14937 }
14938 }
14939 else if( SCIPsetIsNegative(set, ray[c]) )
14940 {
14941 if( !SCIPsetIsInfinity(set, -primsol[c]) )
14942 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14943 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14944 else
14945 {
14946 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14947 rayscale = MIN(rayscale, -1.0 / ray[c]);
14948 }
14949 }
14950
14951 assert(SCIPsetIsFeasPositive(set, rayscale));
14952 }
14953 }
14954
14955 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14956
14957 /* calculate the unbounded point: x' = x + rayscale * ray */
14958 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14959 * typically large values in scaling. */
14960 for( c = 0; c < nlpicols; ++c )
14961 {
14962 if( SCIPsetIsZero(set, ray[c]) )
14963 lpicols[c]->primsol = primsol[c];
14964 else
14965 {
14966 SCIP_Real primsolval;
14967 primsolval = primsol[c] + rayscale * ray[c];
14968 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14969 }
14970 lpicols[c]->redcost = SCIP_INVALID;
14971 lpicols[c]->validredcostlp = -1;
14972 }
14973
14974 /* transfer solution */
14975 for( r = 0; r < nlpirows; ++r )
14976 {
14977 lpirows[r]->dualsol = SCIP_INVALID;
14978 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14979 lpirows[r]->validactivitylp = lpcount;
14980 }
14981
14982 /* free temporary memory */
14983 SCIPsetFreeBufferArray(set, &ray);
14984 SCIPsetFreeBufferArray(set, &activity);
14985 SCIPsetFreeBufferArray(set, &primsol);
14986
14987 return SCIP_OKAY;
14988 }
14989
14990 /** returns primal ray proving the unboundedness of the current LP */
14991 SCIP_RETCODE SCIPlpGetPrimalRay(
14992 SCIP_LP* lp, /**< current LP data */
14993 SCIP_SET* set, /**< global SCIP settings */
14994 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
14995 * so the size of this array should be at least number of active variables
14996 * (all entries have to be initialized to 0 before) */
14997 )
14998 {
14999 SCIP_COL** lpicols;
15000 SCIP_Real* lpiray;
15001 SCIP_VAR* var;
15002 int nlpicols;
15003 int c;
15004
15005 assert(lp != NULL);
15006 assert(set != NULL);
15007 assert(ray != NULL);
15008 assert(lp->flushed);
15009 assert(lp->solved);
15010 assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
15011 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
15012
15013 /* check if the LP solver is able to provide a primal unbounded ray */
15014 if( !SCIPlpiHasPrimalRay(lp->lpi) )
15015 {
15016 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15017 return SCIP_LPERROR;
15018 }
15019
15020 /* get temporary memory */
15021 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpiray, lp->nlpicols) );
15022
15023 SCIPsetDebugMsg(set, "getting primal ray values\n");
15024
15025 /* get primal unbounded ray */
15026 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15027
15028 lpicols = lp->lpicols;
15029 nlpicols = lp->nlpicols;
15030
15031 /* store the ray values of active problem variables */
15032 for( c = 0; c < nlpicols; c++ )
15033 {
15034 assert(lpicols[c] != NULL);
15035
15036 var = lpicols[c]->var;
15037 assert(var != NULL);
15038 assert(SCIPvarGetProbindex(var) != -1);
15039 ray[SCIPvarGetProbindex(var)] = lpiray[c];
15040 }
15041
15042 SCIPsetFreeBufferArray(set, &lpiray);
15043
15044 return SCIP_OKAY;
15045 }
15046
15047 /** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15048 * lp/checkfarkas = TRUE.
15049 *
15050 * @note the check will not be performed if @p valid is NULL.
15051 */
15052 SCIP_RETCODE SCIPlpGetDualfarkas(
15053 SCIP_LP* lp, /**< current LP data */
15054 SCIP_SET* set, /**< global SCIP settings */
15055 SCIP_STAT* stat, /**< problem statistics */
15056 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */
15057 )
15058 {
15059 SCIP_COL** lpicols;
15060 SCIP_ROW** lpirows;
15061 SCIP_Real* dualfarkas;
15062 SCIP_Real* farkascoefs;
15063 SCIP_Real farkaslhs;
15064 SCIP_Real maxactivity;
15065 SCIP_Bool checkfarkas;
15066 int nlpicols;
15067 int nlpirows;
15068 int c;
15069 int r;
15070
15071 assert(lp != NULL);
15072 assert(lp->flushed);
15073 assert(lp->solved);
15074 assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
15075 assert(set != NULL);
15076 assert(stat != NULL);
15077 assert(lp->validfarkaslp <= stat->lpcount);
15078
15079 if( valid != NULL )
15080 *valid = TRUE;
15081
15082 /* check if the values are already calculated */
15083 if( lp->validfarkaslp == stat->lpcount )
15084 return SCIP_OKAY;
15085 lp->validfarkaslp = stat->lpcount;
15086
15087 farkascoefs = NULL;
15088 maxactivity = 0.0;
15089 farkaslhs = 0.0;
15090
15091 checkfarkas = (set->lp_checkfarkas && valid != NULL);
15092
15093 /* get temporary memory */
15094 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15095
15096 if( checkfarkas )
15097 {
15098 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15099 BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15100 }
15101
15102 /* get dual Farkas infeasibility proof */
15103 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15104
15105 lpicols = lp->lpicols;
15106 lpirows = lp->lpirows;
15107 nlpicols = lp->nlpicols;
15108 nlpirows = lp->nlpirows;
15109
15110 /* store infeasibility proof in rows */
15111 SCIPsetDebugMsg(set, "LP is infeasible:\n");
15112 for( r = 0; r < nlpirows; ++r )
15113 {
15114 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15115 lpirows[r]->dualfarkas = dualfarkas[r];
15116 lpirows[r]->dualsol = SCIP_INVALID;
15117 lpirows[r]->activity = 0.0;
15118 lpirows[r]->validactivitylp = -1L;
15119 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15120
15121 if( checkfarkas )
15122 {
15123 assert(farkascoefs != NULL);
15124
15125 /* the infeasibility proof would be invalid if
15126 * (i) dualfarkas[r] > 0 and lhs = -inf
15127 * (ii) dualfarkas[r] < 0 and rhs = inf
15128 * however, due to numerics we accept slightly negative / positive values
15129 */
15130 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15131 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15132 {
15133 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15134 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15135
15136 if( valid != NULL )
15137 *valid = FALSE;
15138
15139 goto TERMINATE;
15140 }
15141
15142 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15143 * within tolerances (see above) but slighty positive / negative
15144 */
15145 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15146 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15147 continue;
15148
15149 /* iterate over all columns and scale with dual solution */
15150 for( c = 0; c < lpirows[r]->len; c++ )
15151 {
15152 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15153
15154 if( pos == -1 )
15155 continue;
15156
15157 assert(pos >= 0 && pos < nlpicols);
15158
15159 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15160 }
15161
15162 /* the row contributes with its left-hand side to the proof */
15163 if( dualfarkas[r] > 0.0 )
15164 {
15165 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15166
15167 farkaslhs += dualfarkas[r] * (lpirows[r]->lhs - lpirows[r]->constant);
15168 }
15169 /* the row contributes with its right-hand side to the proof */
15170 else if( dualfarkas[r] < 0.0 )
15171 {
15172 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15173
15174 farkaslhs += dualfarkas[r] * (lpirows[r]->rhs - lpirows[r]->constant);
15175 }
15176 }
15177 }
15178
15179 /* set columns as invalid */
15180 for( c = 0; c < nlpicols; ++c )
15181 {
15182 lpicols[c]->primsol = SCIP_INVALID;
15183 lpicols[c]->redcost = SCIP_INVALID;
15184 lpicols[c]->validredcostlp = -1L;
15185 lpicols[c]->validfarkaslp = -1L;
15186
15187 if( checkfarkas )
15188 {
15189 assert(farkascoefs != NULL);
15190 assert(SCIPcolGetLPPos(lpicols[c]) == c);
15191
15192 /* skip coefficients that are too close to zero */
15193 if( SCIPsetIsFeasZero(set, farkascoefs[c]) )
15194 continue;
15195
15196 /* calculate the maximal activity */
15197 if( farkascoefs[c] > 0.0 )
15198 maxactivity += farkascoefs[c] * SCIPcolGetUb(lpicols[c]);
15199 else
15200 maxactivity += farkascoefs[c] * SCIPcolGetLb(lpicols[c]);
15201 }
15202 }
15203
15204 /* check whether the farkasproof is valid
15205 * due to numerics, it might happen that the left-hand side of the aggregation is larger/smaller or equal than +/- infinity.
15206 * in that case, we declare the Farkas proof to be invalid.
15207 */
15208 if( checkfarkas && (SCIPsetIsInfinity(set, REALABS(farkaslhs)) || SCIPsetIsGE(set, maxactivity, farkaslhs)) )
15209 {
15210 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15211
15212 if( valid != NULL )
15213 *valid = FALSE;
15214 }
15215
15216 TERMINATE:
15217 /* free temporary memory */
15218 if( checkfarkas )
15219 SCIPsetFreeBufferArray(set, &farkascoefs);
15220
15221 SCIPsetFreeBufferArray(set, &dualfarkas);
15222
15223 return SCIP_OKAY;
15224 }
15225
15226 /** get number of iterations used in last LP solve */
15227 SCIP_RETCODE SCIPlpGetIterations(
15228 SCIP_LP* lp, /**< current LP data */
15229 int* iterations /**< pointer to store the iteration count */
15230 )
15231 {
15232 assert(lp != NULL);
15233
15234 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15235
15236 return SCIP_OKAY;
15237 }
15238
15239 /** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15240 * resets age of non-zero columns and sharp rows
15241 */
15242 SCIP_RETCODE SCIPlpUpdateAges(
15243 SCIP_LP* lp, /**< current LP data */
15244 SCIP_STAT* stat /**< problem statistics */
15245 )
15246 {
15247 SCIP_COL** lpicols;
15248 SCIP_ROW** lpirows;
15249 int nlpicols;
15250 int nlpirows;
15251 int c;
15252 int r;
15253
15254 assert(lp != NULL);
15255 assert(lp->flushed);
15256 assert(lp->solved);
15257 assert(lp->nlpicols == lp->ncols);
15258 assert(lp->nlpirows == lp->nrows);
15259 assert(stat != NULL);
15260 assert(lp->validsollp == stat->lpcount);
15261
15262 SCIPdebugMessage("updating LP ages\n");
15263
15264 lpicols = lp->lpicols;
15265 lpirows = lp->lpirows;
15266 nlpicols = lp->nlpicols;
15267 nlpirows = lp->nlpirows;
15268
15269 for( c = 0; c < nlpicols; ++c )
15270 {
15271 assert(lpicols[c] == lp->cols[c]);
15272 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
15273 lpicols[c]->age++;
15274 else
15275 lpicols[c]->age = 0;
15276 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15277 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15278 }
15279
15280 for( r = 0; r < nlpirows; ++r )
15281 {
15282 lpirows[r]->nlpsaftercreation++;
15283 assert(lpirows[r] == lp->rows[r]);
15284
15285 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15286 {
15287 lpirows[r]->age++;
15288 }
15289 else
15290 {
15291 lpirows[r]->activeinlpcounter++;
15292 lpirows[r]->age = 0;
15293 }
15294 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15295 }
15296
15297 return SCIP_OKAY;
15298 }
15299
15300 /* deletes the marked columns from the LP and the LP interface */
15301 static
15302 SCIP_RETCODE lpDelColset(
15303 SCIP_LP* lp, /**< current LP data */
15304 SCIP_SET* set, /**< global SCIP settings */
15305 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
15306 )
15307 {
15308 SCIP_COL* col;
15309 int ncols;
15310 int c;
15311
15312 assert(lp != NULL);
15313 assert(lp->flushed);
15314 assert(lp->ncols == lp->nlpicols);
15315 assert(!lp->diving);
15316 assert(coldstat != NULL);
15317 assert(lp->nlazycols <= lp->ncols);
15318
15319 ncols = lp->ncols;
15320
15321 /* delete columns in LP solver */
15322 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15323
15324 /* update LP data respectively */
15325 for( c = 0; c < ncols; ++c )
15326 {
15327 col = lp->cols[c];
15328 assert(col != NULL);
15329 assert(col == lp->lpicols[c]);
15330 assert(coldstat[c] <= c);
15331 col->lppos = coldstat[c];
15332 if( coldstat[c] == -1 )
15333 {
15334 assert(col->removable);
15335
15336 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15337 * function vector norms
15338 */
15339 markColDeleted(col);
15340 colUpdateDelLP(col, set);
15341 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15342 col->lpdepth = -1;
15343
15344 lp->cols[c] = NULL;
15345 lp->lpicols[c] = NULL;
15346 lp->ncols--;
15347 lp->nremovablecols--;
15348 lp->nlpicols--;
15349 }
15350 else if( coldstat[c] < c )
15351 {
15352 assert(lp->cols[coldstat[c]] == NULL);
15353 assert(lp->lpicols[coldstat[c]] == NULL);
15354 lp->cols[coldstat[c]] = col;
15355 lp->lpicols[coldstat[c]] = col;
15356 lp->cols[coldstat[c]]->lppos = coldstat[c];
15357 lp->cols[coldstat[c]]->lpipos = coldstat[c];
15358 lp->cols[c] = NULL;
15359 lp->lpicols[c] = NULL;
15360 }
15361 }
15362
15363 /* remove columns which are deleted from the lazy column array */
15364 c = 0;
15365 while( c < lp->nlazycols )
15366 {
15367 if( lp->lazycols[c]->lpipos < 0 )
15368 {
15369 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15370 lp->nlazycols--;
15371 }
15372 else
15373 c++;
15374 }
15375
15376 /* mark LP to be unsolved */
15377 if( lp->ncols < ncols )
15378 {
15379 assert(lp->ncols == lp->nlpicols);
15380 assert(lp->nchgcols == 0);
15381 assert(lp->flushed);
15382
15383 lp->lpifirstchgcol = lp->nlpicols;
15384
15385 /* mark the current solution invalid */
15386 lp->solved = FALSE;
15387 lp->primalfeasible = FALSE;
15388 lp->primalchecked = FALSE;
15389 lp->lpobjval = SCIP_INVALID;
15390 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
15391 }
15392
15393 checkLazyColArray(lp, set);
15394 checkLinks(lp);
15395
15396 return SCIP_OKAY;
15397 }
15398
15399 /* deletes the marked rows from the LP and the LP interface */
15400 static
15401 SCIP_RETCODE lpDelRowset(
15402 SCIP_LP* lp, /**< current LP data */
15403 BMS_BLKMEM* blkmem, /**< block memory buffers */
15404 SCIP_SET* set, /**< global SCIP settings */
15405 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15406 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15407 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
15408 )
15409 {
15410 SCIP_ROW* row;
15411 int nrows;
15412 int r;
15413
15414 assert(lp != NULL);
15415 assert(lp->flushed);
15416 assert(lp->nrows == lp->nlpirows);
15417 assert(!lp->diving);
15418 assert(rowdstat != NULL);
15419
15420 nrows = lp->nrows;
15421
15422 /* delete rows in LP solver */
15423 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15424
15425 /* update LP data respectively */
15426 for( r = 0; r < nrows; ++r )
15427 {
15428 row = lp->rows[r];
15429 assert(row == lp->lpirows[r]);
15430 assert(rowdstat[r] <= r);
15431 assert(row != NULL);
15432 row->lppos = rowdstat[r];
15433 if( rowdstat[r] == -1 )
15434 {
15435 if( row->removable )
15436 lp->nremovablerows--;
15437
15438 /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15439 markRowDeleted(row);
15440 rowUpdateDelLP(row);
15441 row->lpdepth = -1;
15442
15443 /* check, if row deletion events are tracked
15444 * if so, issue ROWDELETEDLP event
15445 */
15446 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15447 {
15448 SCIP_EVENT* event;
15449
15450 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15451 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15452 }
15453
15454 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15455 SCIProwUnlock(lp->rows[r]);
15456 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15457 assert(lp->lpirows[r] == NULL);
15458 assert(lp->rows[r] == NULL);
15459 lp->nrows--;
15460 lp->nlpirows--;
15461 }
15462 else if( rowdstat[r] < r )
15463 {
15464 assert(lp->rows[rowdstat[r]] == NULL);
15465 assert(lp->lpirows[rowdstat[r]] == NULL);
15466 lp->rows[rowdstat[r]] = row;
15467 lp->lpirows[rowdstat[r]] = row;
15468 lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15469 lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15470 lp->rows[r] = NULL;
15471 lp->lpirows[r] = NULL;
15472 }
15473 }
15474
15475 /* mark LP to be unsolved */
15476 if( lp->nrows < nrows )
15477 {
15478 assert(lp->nrows == lp->nlpirows);
15479 assert(lp->nchgrows == 0);
15480 assert(lp->flushed);
15481
15482 lp->lpifirstchgrow = lp->nlpirows;
15483
15484 /* mark the current solution invalid */
15485 lp->solved = FALSE;
15486 lp->dualfeasible = FALSE;
15487 lp->dualchecked = FALSE;
15488 lp->lpobjval = SCIP_INVALID;
15489 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
15490 }
15491
15492 checkLinks(lp);
15493
15494 return SCIP_OKAY;
15495 }
15496
15497 /** removes all non-basic columns, that are too old, beginning with the given firstcol */
15498 static
15499 SCIP_RETCODE lpRemoveObsoleteCols(
15500 SCIP_LP* lp, /**< current LP data */
15501 SCIP_SET* set, /**< global SCIP settings */
15502 SCIP_STAT* stat, /**< problem statistics */
15503 int firstcol /**< first column to check for clean up */
15504 )
15505 {
15506 SCIP_COL** cols;
15507 #ifndef NDEBUG
15508 SCIP_COL** lpicols;
15509 #endif
15510 int* coldstat;
15511 int ncols;
15512 int ndelcols;
15513 int c;
15514
15515 assert(lp != NULL);
15516 assert(lp->flushed);
15517 assert(lp->ncols == lp->nlpicols);
15518 assert(lp->nremovablecols <= lp->ncols);
15519 assert(!lp->diving);
15520 assert(set != NULL);
15521 assert(stat != NULL);
15522
15523 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15524 return SCIP_OKAY;
15525
15526 ncols = lp->ncols;
15527 cols = lp->cols;
15528 #ifndef NDEBUG
15529 lpicols = lp->lpicols;
15530 #endif
15531
15532 /* get temporary memory */
15533 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15534
15535 /* mark obsolete columns to be deleted */
15536 ndelcols = 0;
15537 BMSclearMemoryArray(coldstat, ncols);
15538 for( c = firstcol; c < ncols; ++c )
15539 {
15540 assert(cols[c] == lpicols[c]);
15541 assert(cols[c]->lppos == c);
15542 assert(cols[c]->lpipos == c);
15543 if( cols[c]->removable
15544 && cols[c]->obsoletenode != stat->nnodes /* don't remove column a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15545 && cols[c]->age > set->lp_colagelimit
15546 && (SCIP_BASESTAT)cols[c]->basisstatus != SCIP_BASESTAT_BASIC
15547 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15548 {
15549 assert(cols[c]->primsol == 0.0);
15550 coldstat[c] = 1;
15551 ndelcols++;
15552 cols[c]->obsoletenode = stat->nnodes;
15553 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15554 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15555 }
15556 }
15557
15558 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15559
15560 /* delete the marked columns in the LP solver interface, update the LP respectively */
15561 if( ndelcols > 0 )
15562 {
15563 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15564 }
15565 assert(lp->ncols == ncols - ndelcols);
15566
15567 /* release temporary memory */
15568 SCIPsetFreeBufferArray(set, &coldstat);
15569
15570 return SCIP_OKAY;
15571 }
15572
15573 /** removes all basic rows, that are too old, beginning with the given firstrow */
15574 static
15575 SCIP_RETCODE lpRemoveObsoleteRows(
15576 SCIP_LP* lp, /**< current LP data */
15577 BMS_BLKMEM* blkmem, /**< block memory buffers */
15578 SCIP_SET* set, /**< global SCIP settings */
15579 SCIP_STAT* stat, /**< problem statistics */
15580 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15581 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15582 int firstrow /**< first row to check for clean up */
15583 )
15584 {
15585 SCIP_ROW** rows;
15586 #ifndef NDEBUG
15587 SCIP_ROW** lpirows;
15588 #endif
15589 int* rowdstat;
15590 int nrows;
15591 int ndelrows;
15592 int r;
15593
15594 assert(lp != NULL);
15595 assert(lp->flushed);
15596 assert(lp->nrows == lp->nlpirows);
15597 assert(lp->nremovablerows <= lp->nrows);
15598 assert(!lp->diving);
15599 assert(set != NULL);
15600 assert(stat != NULL);
15601
15602 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15603 return SCIP_OKAY;
15604
15605 nrows = lp->nrows;
15606 rows = lp->rows;
15607 #ifndef NDEBUG
15608 lpirows = lp->lpirows;
15609 #endif
15610
15611 /* get temporary memory */
15612 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15613
15614 /* mark obsolete rows to be deleted */
15615 ndelrows = 0;
15616 BMSclearMemoryArray(rowdstat, nrows);
15617 for( r = firstrow; r < nrows; ++r )
15618 {
15619 assert(rows[r] == lpirows[r]);
15620 assert(rows[r]->lppos == r);
15621 assert(rows[r]->lpipos == r);
15622 if( rows[r]->removable
15623 && rows[r]->obsoletenode != stat->nnodes /* don't remove row a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15624 && rows[r]->age > set->lp_rowagelimit
15625 && (SCIP_BASESTAT)rows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15626 {
15627 rowdstat[r] = 1;
15628 ndelrows++;
15629 rows[r]->obsoletenode = stat->nnodes;
15630 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15631 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15632 }
15633 }
15634
15635 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15636
15637 /* delete the marked rows in the LP solver interface, update the LP respectively */
15638 if( ndelrows > 0 )
15639 {
15640 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15641 }
15642 assert(lp->nrows == nrows - ndelrows);
15643
15644 /* release temporary memory */
15645 SCIPsetFreeBufferArray(set, &rowdstat);
15646
15647 return SCIP_OKAY;
15648 }
15649
15650 /** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15651 SCIP_RETCODE SCIPlpRemoveNewObsoletes(
15652 SCIP_LP* lp, /**< current LP data */
15653 BMS_BLKMEM* blkmem, /**< block memory buffers */
15654 SCIP_SET* set, /**< global SCIP settings */
15655 SCIP_STAT* stat, /**< problem statistics */
15656 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15657 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15658 )
15659 {
15660 assert(lp != NULL);
15661 assert(lp->solved);
15662 assert(!lp->diving);
15663 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15664 assert(set != NULL);
15665
15666 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15667 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15668
15669 if( lp->firstnewcol < lp->ncols )
15670 {
15671 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15672 }
15673 if( lp->firstnewrow < lp->nrows )
15674 {
15675 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15676 }
15677
15678 return SCIP_OKAY;
15679 }
15680
15681 /** removes all non-basic columns and basic rows in whole LP, that are too old */
15682 SCIP_RETCODE SCIPlpRemoveAllObsoletes(
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);
15694 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15695 assert(set != NULL);
15696
15697 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15698
15699 if( 0 < lp->ncols )
15700 {
15701 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15702 }
15703 if( 0 < lp->nrows )
15704 {
15705 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15706 }
15707
15708 return SCIP_OKAY;
15709 }
15710
15711 /** removes all non-basic columns at 0.0 beginning with the given firstcol */
15712 static
15713 SCIP_RETCODE lpCleanupCols(
15714 SCIP_LP* lp, /**< current LP data */
15715 SCIP_SET* set, /**< global SCIP settings */
15716 SCIP_STAT* stat, /**< problem statistics */
15717 int firstcol /**< first column to check for clean up */
15718 )
15719 {
15720 SCIP_COL** cols;
15721 SCIP_COL** lpicols;
15722 int* coldstat;
15723 int ncols;
15724 int ndelcols;
15725 int c;
15726
15727 assert(lp != NULL);
15728 assert(lp->flushed);
15729 assert(lp->ncols == lp->nlpicols);
15730 assert(!lp->diving);
15731 assert(stat != NULL);
15732 assert(lp->validsollp == stat->lpcount);
15733 assert(0 <= firstcol && firstcol < lp->ncols);
15734
15735 if( lp->nremovablecols == 0 || !lp->solisbasic )
15736 return SCIP_OKAY;
15737
15738 ncols = lp->ncols;
15739 cols = lp->cols;
15740 lpicols = lp->lpicols;
15741
15742 /* get temporary memory */
15743 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15744
15745 /* mark unused columns to be deleted */
15746 ndelcols = 0;
15747 BMSclearMemoryArray(coldstat, ncols);
15748 for( c = firstcol; c < ncols; ++c )
15749 {
15750 assert(cols[c] == lpicols[c]);
15751 assert(cols[c]->lppos == c);
15752 assert(cols[c]->lpipos == c);
15753 if( lpicols[c]->removable
15754 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15755 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15756 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15757 {
15758 coldstat[c] = 1;
15759 ndelcols++;
15760 }
15761 }
15762
15763 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15764
15765 /* delete the marked columns in the LP solver interface, update the LP respectively */
15766 if( ndelcols > 0 )
15767 {
15768 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15769 }
15770 assert(lp->ncols == ncols - ndelcols);
15771
15772 /* release temporary memory */
15773 SCIPsetFreeBufferArray(set, &coldstat);
15774
15775 return SCIP_OKAY;
15776 }
15777
15778 /** removes all basic rows beginning with the given firstrow */
15779 static
15780 SCIP_RETCODE lpCleanupRows(
15781 SCIP_LP* lp, /**< current LP data */
15782 BMS_BLKMEM* blkmem, /**< block memory buffers */
15783 SCIP_SET* set, /**< global SCIP settings */
15784 SCIP_STAT* stat, /**< problem statistics */
15785 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15786 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15787 int firstrow /**< first row to check for clean up */
15788 )
15789 {
15790 #ifndef NDEBUG
15791 SCIP_ROW** rows;
15792 #endif
15793 SCIP_ROW** lpirows;
15794 int* rowdstat;
15795 int nrows;
15796 int ndelrows;
15797 int r;
15798
15799 assert(lp != NULL);
15800 assert(lp->flushed);
15801 assert(lp->ncols == lp->nlpicols);
15802 assert(lp->nrows == lp->nlpirows);
15803 assert(!lp->diving);
15804 assert(stat != NULL);
15805 assert(lp->validsollp == stat->lpcount);
15806 assert(0 <= firstrow && firstrow < lp->nrows);
15807
15808 if( lp->nremovablerows == 0 || !lp->solisbasic )
15809 return SCIP_OKAY;
15810
15811 #ifndef NDEBUG
15812 rows = lp->rows;
15813 #endif
15814 nrows = lp->nrows;
15815 lpirows = lp->lpirows;
15816
15817 /* get temporary memory */
15818 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15819
15820 /* mark unused rows to be deleted */
15821 ndelrows = 0;
15822 BMSclearMemoryArray(rowdstat, nrows);
15823 for( r = firstrow; r < nrows; ++r )
15824 {
15825 assert(rows[r] == lpirows[r]);
15826 assert(rows[r]->lppos == r);
15827 assert(rows[r]->lpipos == r);
15828 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15829 {
15830 rowdstat[r] = 1;
15831 ndelrows++;
15832 }
15833 }
15834
15835 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15836
15837 /* delete the marked rows in the LP solver interface, update the LP respectively */
15838 if( ndelrows > 0 )
15839 {
15840 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15841 }
15842 assert(lp->nrows == nrows - ndelrows);
15843
15844 /* release temporary memory */
15845 SCIPsetFreeBufferArray(set, &rowdstat);
15846
15847 return SCIP_OKAY;
15848 }
15849
15850 /** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15851 SCIP_RETCODE SCIPlpCleanupNew(
15852 SCIP_LP* lp, /**< current LP data */
15853 BMS_BLKMEM* blkmem, /**< block memory buffers */
15854 SCIP_SET* set, /**< global SCIP settings */
15855 SCIP_STAT* stat, /**< problem statistics */
15856 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15857 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15858 SCIP_Bool root /**< are we at the root node? */
15859 )
15860 {
15861 SCIP_Bool cleanupcols;
15862 SCIP_Bool cleanuprows;
15863
15864 assert(lp != NULL);
15865 assert(lp->solved);
15866 assert(!lp->diving);
15867 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15868 assert(set != NULL);
15869
15870 /* check, if we want to clean up the columns and rows */
15871 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15872 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15873
15874 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15875 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15876
15877 if( cleanupcols && lp->firstnewcol < lp->ncols )
15878 {
15879 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15880 }
15881 if( cleanuprows && lp->firstnewrow < lp->nrows )
15882 {
15883 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15884 }
15885
15886 return SCIP_OKAY;
15887 }
15888
15889 /** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15890 SCIP_RETCODE SCIPlpCleanupAll(
15891 SCIP_LP* lp, /**< current LP data */
15892 BMS_BLKMEM* blkmem, /**< block memory buffers */
15893 SCIP_SET* set, /**< global SCIP settings */
15894 SCIP_STAT* stat, /**< problem statistics */
15895 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15896 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15897 SCIP_Bool root /**< are we at the root node? */
15898 )
15899 {
15900 SCIP_Bool cleanupcols;
15901 SCIP_Bool cleanuprows;
15902
15903 assert(lp != NULL);
15904 assert(lp->solved);
15905 assert(!lp->diving);
15906 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15907 assert(set != NULL);
15908
15909 /* check, if we want to clean up the columns and rows */
15910 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15911 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15912
15913 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15914 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15915
15916 if( cleanupcols && 0 < lp->ncols )
15917 {
15918 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15919 }
15920 if( cleanuprows && 0 < lp->nrows )
15921 {
15922 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15923 }
15924
15925 return SCIP_OKAY;
15926 }
15927
15928 /** removes all redundant rows that were added at the current node */
15929 SCIP_RETCODE SCIPlpRemoveRedundantRows(
15930 SCIP_LP* lp, /**< current LP data */
15931 BMS_BLKMEM* blkmem, /**< block memory buffers */
15932 SCIP_SET* set, /**< global SCIP settings */
15933 SCIP_STAT* stat, /**< problem statistics */
15934 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15935 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15936 )
15937 {
15938 #ifndef NDEBUG
15939 SCIP_ROW** rows;
15940 #endif
15941 SCIP_ROW** lpirows;
15942 int* rowdstat;
15943 int nrows;
15944 int ndelrows;
15945 int r;
15946
15947 assert(lp != NULL);
15948 assert(lp->flushed);
15949 assert(lp->ncols == lp->nlpicols);
15950 assert(lp->nrows == lp->nlpirows);
15951 assert(!lp->diving);
15952 assert(stat != NULL);
15953 assert(lp->validsollp == stat->lpcount);
15954 assert(lp->firstnewrow <= lp->nrows);
15955
15956 if( lp->firstnewrow == lp->nrows )
15957 return SCIP_OKAY;
15958
15959 #ifndef NDEBUG
15960 rows = lp->rows;
15961 #endif
15962 nrows = lp->nrows;
15963 lpirows = lp->lpirows;
15964
15965 /* get temporary memory */
15966 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15967
15968 /* mark redundant rows to be deleted (only delete basic rows!) */
15969 ndelrows = 0;
15970 BMSclearMemoryArray(rowdstat, nrows);
15971 for( r = lp->firstnewrow; r < nrows; ++r )
15972 {
15973 assert(rows[r] == lpirows[r]);
15974 assert(rows[r]->lppos == r);
15975 assert(rows[r]->lpipos == r);
15976 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
15977 && SCIProwIsRedundant(lpirows[r], set, stat) )
15978 {
15979 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
15980 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
15981 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
15982 rowdstat[r] = 1;
15983 ndelrows++;
15984 }
15985 }
15986
15987 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
15988
15989 /* delete the marked rows in the LP solver interface, update the LP respectively */
15990 if( ndelrows > 0 )
15991 {
15992 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15993 }
15994 assert(lp->nrows == nrows - ndelrows);
15995
15996 /* release temporary memory */
15997 SCIPsetFreeBufferArray(set, &rowdstat);
15998
15999 return SCIP_OKAY;
16000 }
16001
16002 /** initiates LP diving */
16003 SCIP_RETCODE SCIPlpStartDive(
16004 SCIP_LP* lp, /**< current LP data */
16005 BMS_BLKMEM* blkmem, /**< block memory */
16006 SCIP_SET* set, /**< global SCIP settings */
16007 SCIP_STAT* stat /**< problem statistics */
16008 )
16009 {
16010 int c;
16011 int r;
16012
16013 assert(lp != NULL);
16014 assert(lp->flushed || !lp->solved);
16015 assert(!lp->diving);
16016 assert(!lp->probing);
16017 assert(lp->divelpistate == NULL);
16018 assert(lp->divelpwasprimfeas);
16019 assert(lp->divelpwasdualfeas);
16020 assert(lp->validsollp <= stat->lpcount);
16021 assert(blkmem != NULL);
16022 assert(set != NULL);
16023 assert(lp->ndivechgsides == 0);
16024
16025 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16026 lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16027
16028 #ifndef NDEBUG
16029 for( c = 0; c < lp->ncols; ++c )
16030 {
16031 assert(lp->cols[c] != NULL);
16032 assert(lp->cols[c]->var != NULL);
16033 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16034 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16035 assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16036 assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16037 assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16038 }
16039 #endif
16040
16041 /* save current LPI state (basis information) */
16042 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16043 lp->divelpwasprimfeas = lp->primalfeasible;
16044 lp->divelpwasdualfeas = lp->dualfeasible;
16045 lp->divelpwasprimchecked = lp->primalchecked;
16046 lp->divelpwasdualchecked = lp->dualchecked;
16047
16048 /* save current LP values dependent on the solution */
16049 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16050 assert(lp->storedsolvals != NULL);
16051 if( !set->lp_resolverestore && lp->solved )
16052 {
16053 SCIP_Bool store = TRUE;
16054
16055 switch ( lp->lpsolstat )
16056 {
16057 case SCIP_LPSOLSTAT_OPTIMAL:
16058 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16059 assert(lp->validsollp == stat->lpcount);
16060 break;
16061 case SCIP_LPSOLSTAT_UNBOUNDEDRAY:
16062 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
16063 assert(lp->validsollp == stat->lpcount);
16064 break;
16065 case SCIP_LPSOLSTAT_OBJLIMIT:
16066 case SCIP_LPSOLSTAT_ITERLIMIT:
16067 case SCIP_LPSOLSTAT_TIMELIMIT:
16068 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16069 assert(lp->validsollp == stat->lpcount);
16070 break;
16071 case SCIP_LPSOLSTAT_INFEASIBLE:
16072 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, NULL) );
16073 break;
16074 case SCIP_LPSOLSTAT_NOTSOLVED:
16075 case SCIP_LPSOLSTAT_ERROR:
16076 default:
16077 store = FALSE;
16078 }
16079
16080 if ( store )
16081 {
16082 for( c = 0; c < lp->ncols; ++c )
16083 {
16084 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16085 }
16086 for( r = 0; r < lp->nrows; ++r )
16087 {
16088 SCIP_CALL( rowStoreSolVals(lp->rows[r], blkmem, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16089 }
16090 }
16091 }
16092
16093 /* store LPI iteration limit */
16094 SCIP_CALL( SCIPlpiGetIntpar(lp->lpi, SCIP_LPPAR_LPITLIM, &lp->divinglpiitlim) );
16095
16096 /* remember the number of domain changes */
16097 lp->divenolddomchgs = stat->domchgcount;
16098
16099 /* store current number of rows */
16100 lp->ndivingrows = lp->nrows;
16101
16102 /* switch to diving mode */
16103 lp->diving = TRUE;
16104
16105 return SCIP_OKAY;
16106 }
16107
16108 /** quits LP diving and resets bounds and objective values of columns to the current node's values */
16109 SCIP_RETCODE SCIPlpEndDive(
16110 SCIP_LP* lp, /**< current LP data */
16111 BMS_BLKMEM* blkmem, /**< block memory */
16112 SCIP_SET* set, /**< global SCIP settings */
16113 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16114 SCIP_STAT* stat, /**< problem statistics */
16115 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16116 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16117 SCIP_PROB* prob, /**< problem data */
16118 SCIP_VAR** vars, /**< array with all active variables */
16119 int nvars /**< number of active variables */
16120 )
16121 {
16122 SCIP_VAR* var;
16123 int v;
16124
16125 assert(lp != NULL);
16126 assert(lp->diving);
16127 assert(blkmem != NULL);
16128 assert(nvars == 0 || vars != NULL);
16129
16130 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16131
16132 /* reset all columns' objective values and bounds to its original values */
16133 for( v = 0; v < nvars; ++v )
16134 {
16135 var = vars[v];
16136 assert(var != NULL);
16137 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
16138 {
16139 SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, SCIPvarGetObj(var)) );
16140 SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, SCIPvarGetLbLocal(var)) );
16141 SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, SCIPvarGetUbLocal(var)) );
16142 }
16143 }
16144
16145 /* remove rows which were added in diving mode */
16146 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16147
16148 /* undo changes to left hand sides and right hand sides */
16149 while( lp->ndivechgsides > 0 )
16150 {
16151 SCIP_Real oldside;
16152 SCIP_SIDETYPE sidetype;
16153 SCIP_ROW* row;
16154
16155 lp->ndivechgsides--;
16156 oldside = lp->divechgsides[lp->ndivechgsides];
16157 sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16158 row = lp->divechgrows[lp->ndivechgsides];
16159
16160 if( sidetype == SCIP_SIDETYPE_LEFT )
16161 {
16162 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16163 }
16164 else
16165 {
16166 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16167 }
16168 }
16169
16170 /* restore LPI iteration limit */
16171 SCIP_CALL( lpSetIterationLimit(lp, lp->divinglpiitlim) );
16172
16173 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16174 * happens
16175 */
16176 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16177 lp->divelpwasprimfeas, lp->divelpwasprimchecked, lp->divelpwasdualfeas, lp->divelpwasdualchecked) );
16178 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16179 lp->divelpwasprimfeas = TRUE;
16180 lp->divelpwasdualfeas = TRUE;
16181 lp->divelpwasprimchecked = TRUE;
16182 lp->divelpwasdualchecked = TRUE;
16183 assert(lp->divelpistate == NULL);
16184
16185 /* switch to standard (non-diving) mode */
16186 lp->diving = FALSE;
16187 lp->divingobjchg = FALSE;
16188
16189 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16190 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16191 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16192 * the parameter resolverestore to TRUE
16193 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16194 */
16195 assert(lp->storedsolvals != NULL);
16196 if( lp->storedsolvals->lpissolved
16197 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16198 {
16199 SCIP_Bool lperror;
16200
16201 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) );
16202 if( lperror )
16203 {
16204 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16205 lp->resolvelperror = TRUE;
16206 }
16207 else if( SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL
16208 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_INFEASIBLE
16209 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_UNBOUNDEDRAY
16210 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OBJLIMIT )
16211 {
16212 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16213 "LP was not resolved to a sufficient status after diving\n");
16214 lp->resolvelperror = TRUE;
16215 }
16216 }
16217 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16218 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16219 * re-solve as above can lead to a different LP status
16220 */
16221 else
16222 {
16223 int c;
16224 int r;
16225
16226 /* if there are lazy bounds, remove them from the LP */
16227 if( lp->nlazycols > 0 )
16228 {
16229 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16230 * first resolve LP?
16231 */
16232 SCIP_CALL( updateLazyBounds(lp, set) );
16233 assert(lp->diving == lp->divinglazyapplied);
16234
16235 /* flush changes to the LP solver */
16236 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16237 }
16238
16239 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16240 SCIPstatIncrement(stat, set, lpcount);
16241
16242 /* restore LP solution values in lp data, columns and rows */
16243 if( lp->storedsolvals->lpissolved &&
16244 (lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
16245 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY ||
16246 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
16247 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT ||
16248 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT ||
16249 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE)
16250 )
16251 {
16252 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16253
16254 for( c = 0; c < lp->ncols; ++c )
16255 {
16256 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16257 }
16258 for( r = 0; r < lp->nrows; ++r )
16259 {
16260 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16261 }
16262 }
16263 else
16264 {
16265 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16266 }
16267 }
16268
16269 #ifndef NDEBUG
16270 {
16271 int c;
16272 for( c = 0; c < lp->ncols; ++c )
16273 {
16274 assert(lp->cols[c] != NULL);
16275 assert(lp->cols[c]->var != NULL);
16276 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16277 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16278 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16279 assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16280 assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16281 }
16282 }
16283 #endif
16284
16285 return SCIP_OKAY;
16286 }
16287
16288 #define DIVESTACKGROWFACT 1.5
16289
16290 /** records a current row side such that any change will be undone after diving */
16291 SCIP_RETCODE SCIPlpRecordOldRowSideDive(
16292 SCIP_LP* lp, /**< LP data object */
16293 SCIP_ROW* row, /**< row affected by the change */
16294 SCIP_SIDETYPE sidetype /**< side type */
16295 )
16296 {
16297 assert(lp != NULL);
16298 assert(row != NULL);
16299
16300 if( lp->ndivechgsides == lp->divechgsidessize )
16301 {
16302 SCIP_CALL( reallocDiveChgSideArrays(lp, lp->divechgsidessize + 1, DIVESTACKGROWFACT) );
16303 }
16304 assert(lp->ndivechgsides < lp->divechgsidessize);
16305
16306 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16307 lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16308 lp->divechgrows[lp->ndivechgsides] = row;
16309 lp->ndivechgsides++;
16310
16311 return SCIP_OKAY;
16312 }
16313
16314 /** informs the LP that probing mode was initiated */
16315 SCIP_RETCODE SCIPlpStartProbing(
16316 SCIP_LP* lp /**< current LP data */
16317 )
16318 {
16319 assert(lp != NULL);
16320 assert(!lp->probing);
16321 assert(!lp->strongbranching);
16322 assert(!lp->strongbranchprobing);
16323
16324 lp->probing = TRUE;
16325
16326 return SCIP_OKAY;
16327 }
16328
16329 /** informs the LP that probing mode was finished */
16330 SCIP_RETCODE SCIPlpEndProbing(
16331 SCIP_LP* lp /**< current LP data */
16332 )
16333 {
16334 assert(lp != NULL);
16335 assert(lp->probing);
16336 assert(!lp->strongbranching);
16337 assert(!lp->strongbranchprobing);
16338
16339 lp->probing = FALSE;
16340
16341 return SCIP_OKAY;
16342 }
16343
16344 /** informs the LP that the probing mode is now used for strongbranching */
16345 void SCIPlpStartStrongbranchProbing(
16346 SCIP_LP* lp /**< current LP data */
16347 )
16348 {
16349 assert(lp != NULL);
16350 assert(lp->probing);
16351 assert(!lp->strongbranching);
16352 assert(!lp->strongbranchprobing);
16353
16354 lp->strongbranchprobing = TRUE;
16355 }
16356
16357 /** informs the LP that the probing mode is not used for strongbranching anymore */
16358 void SCIPlpEndStrongbranchProbing(
16359 SCIP_LP* lp /**< current LP data */
16360 )
16361 {
16362 assert(lp != NULL);
16363 assert(lp->probing);
16364 assert(!lp->strongbranching);
16365 assert(lp->strongbranchprobing);
16366
16367 lp->strongbranchprobing = FALSE;
16368 }
16369
16370 /** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16371 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16372 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16373 * we have only left hand sides):
16374 * min{cx | b <= Ax, lb <= x <= ub}
16375 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
16376 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
16377 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
16378 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
16379 */
16380 static
16381 SCIP_RETCODE provedBound(
16382 SCIP_LP* lp, /**< current LP data */
16383 SCIP_SET* set, /**< global SCIP settings */
16384 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16385 SCIP_Real* bound /**< result of interval arithmetic minimization */
16386 )
16387 {
16388 SCIP_INTERVAL* yinter;
16389 SCIP_INTERVAL b;
16390 SCIP_INTERVAL ytb;
16391 SCIP_INTERVAL prod;
16392 SCIP_INTERVAL diff;
16393 SCIP_INTERVAL x;
16394 SCIP_INTERVAL minprod;
16395 SCIP_INTERVAL a;
16396 SCIP_ROW* row;
16397 SCIP_COL* col;
16398 SCIP_Real y;
16399 SCIP_Real c;
16400 int i;
16401 int j;
16402
16403 assert(lp != NULL);
16404 assert(lp->solved);
16405 assert(set != NULL);
16406 assert(bound != NULL);
16407
16408 /* allocate buffer for storing y in interval arithmetic */
16409 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16410
16411 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16412 SCIPintervalSet(&ytb, 0.0);
16413 for( j = 0; j < lp->nrows; ++j )
16414 {
16415 row = lp->rows[j];
16416 assert(row != NULL);
16417
16418 y = (usefarkas ? row->dualfarkas : row->dualsol);
16419
16420 if( SCIPsetIsFeasPositive(set, y) )
16421 {
16422 SCIPintervalSet(&yinter[j], y);
16423 SCIPintervalSet(&b, row->lhs - row->constant);
16424 }
16425 else if( SCIPsetIsFeasNegative(set, y) )
16426 {
16427 SCIPintervalSet(&yinter[j], y);
16428 SCIPintervalSet(&b, row->rhs - row->constant);
16429 }
16430 else
16431 {
16432 SCIPintervalSet(&yinter[j], 0.0);
16433 SCIPintervalSet(&b, 0.0);
16434 }
16435
16436 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16437 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16438 }
16439
16440 /* calculate min{(c^T - y^TA)x} */
16441 SCIPintervalSet(&minprod, 0.0);
16442 for( j = 0; j < lp->ncols; ++j )
16443 {
16444 col = lp->cols[j];
16445 assert(col != NULL);
16446 assert(col->nunlinked == 0);
16447
16448 SCIPintervalSetBounds(&x, SCIPcolGetLb(col), SCIPcolGetUb(col));
16449
16450 c = usefarkas ? 0.0 : col->obj;
16451 SCIPintervalSet(&diff, c);
16452
16453 for( i = 0; i < col->nlprows; ++i )
16454 {
16455 assert(col->rows[i] != NULL);
16456 assert(col->rows[i]->lppos >= 0);
16457 assert(col->linkpos[i] >= 0);
16458 SCIPintervalSet(&a, col->vals[i]);
16459 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16460 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16461 }
16462
16463 #ifndef NDEBUG
16464 for( i = col->nlprows; i < col->len; ++i )
16465 {
16466 assert(col->rows[i] != NULL);
16467 assert(col->rows[i]->lppos == -1);
16468 assert(col->rows[i]->dualsol == 0.0);
16469 assert(col->rows[i]->dualfarkas == 0.0);
16470 assert(col->linkpos[i] >= 0);
16471 }
16472 #endif
16473
16474 SCIPintervalSetBounds(&x, col->lb, col->ub);
16475 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16476 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16477 }
16478
16479 /* add y^Tb */
16480 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16481
16482 /* free buffer for storing y in interval arithmetic */
16483 SCIPsetFreeBufferArray(set, &yinter);
16484
16485 *bound = SCIPintervalGetInf(minprod);
16486
16487 return SCIP_OKAY;
16488 }
16489
16490 /** gets proven lower (dual) bound of last LP solution */
16491 SCIP_RETCODE SCIPlpGetProvedLowerbound(
16492 SCIP_LP* lp, /**< current LP data */
16493 SCIP_SET* set, /**< global SCIP settings */
16494 SCIP_Real* bound /**< pointer to store proven dual bound */
16495 )
16496 {
16497 SCIP_CALL( provedBound(lp, set, FALSE, bound) );
16498
16499 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16500
16501 return SCIP_OKAY;
16502 }
16503
16504 /** gets proven dual bound of last LP solution */
16505 SCIP_RETCODE SCIPlpIsInfeasibilityProved(
16506 SCIP_LP* lp, /**< current LP data */
16507 SCIP_SET* set, /**< global SCIP settings */
16508 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
16509 )
16510 {
16511 SCIP_Real bound;
16512
16513 assert(proved != NULL);
16514
16515 SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16516
16517 *proved = (bound > 0.0);
16518
16519 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16520
16521 return SCIP_OKAY;
16522 }
16523
16524
16525
16526 /** writes LP to a file */
16527 SCIP_RETCODE SCIPlpWrite(
16528 SCIP_LP* lp, /**< current LP data */
16529 const char* fname /**< file name */
16530 )
16531 {
16532 assert(lp != NULL);
16533 assert(lp->flushed);
16534 assert(fname != NULL);
16535
16536 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16537
16538 return SCIP_OKAY;
16539 }
16540
16541 /** writes MIP relaxation of the current B&B node to a file */
16542 SCIP_RETCODE SCIPlpWriteMip(
16543 SCIP_LP* lp, /**< current LP data */
16544 SCIP_SET* set, /**< global SCIP settings */
16545 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16546 const char* fname, /**< file name */
16547 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
16548 * troubles with reserved symbols? */
16549 SCIP_Bool origobj, /**< should the original objective function be used? */
16550 SCIP_OBJSENSE objsense, /**< objective sense */
16551 SCIP_Real objscale, /**< objective scaling factor */
16552 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
16553 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
16554 )
16555 {
16556 FILE* file;
16557 int i;
16558 int j;
16559 char rowname[SCIP_MAXSTRLEN];
16560 SCIP_Real coeff;
16561
16562 assert(lp != NULL);
16563 assert(lp->flushed);
16564 assert(fname != NULL);
16565
16566 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16567 file = fopen(fname, "w");
16568 if( file == NULL )
16569 {
16570 SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16571 SCIPprintSysError(fname);
16572 return SCIP_FILECREATEERROR;
16573 }
16574
16575 /* print comments */
16576 if( genericnames )
16577 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16578 else
16579 {
16580 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16581 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16582 }
16583
16584 if( origobj && objoffset != 0.0 )
16585 {
16586 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16587 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16588 }
16589
16590 /* print objective function */
16591 /**@note the transformed problem in SCIP is always a minimization problem */
16592 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16593 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16594 else
16595 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16596
16597 /* print objective */
16598 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16599 j = 0;
16600 for( i = 0; i < lp->ncols; ++i )
16601 {
16602 if( lp->cols[i]->obj != 0.0 )
16603 {
16604 coeff = lp->cols[i]->obj;
16605 if( origobj )
16606 {
16607 coeff *= (SCIP_Real) objsense;
16608 coeff *= objscale;
16609 }
16610
16611 if( genericnames )
16612 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16613 else
16614 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16615
16616 ++j;
16617 if( j % 10 == 0 )
16618 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16619 }
16620 }
16621 /* add artificial variable 'objoffset' to transfer objective offset */
16622 if( origobj && objoffset != 0.0 )
16623 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16624
16625 /* print constraint section */
16626 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16627 for( i = 0; i < lp->nrows; i++ )
16628 {
16629 char type = 'i';
16630
16631 /* skip removable rows if we want to write them as lazy constraints */
16632 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16633 continue;
16634
16635 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16636 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16637 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16638 * type 'i' means: lhs and rhs are both infinite */
16639 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16640 type = 'r';
16641 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16642 type = 'l';
16643 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16644 type = 'e';
16645 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16646 type = 'b';
16647
16648 /* print name of row */
16649 if( genericnames )
16650 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16651 else
16652 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16653
16654 WRITEROW:
16655 switch( type )
16656 {
16657 case 'r':
16658 case 'l':
16659 case 'e':
16660 if( strlen(rowname) > 0 )
16661 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16662 break;
16663 case 'i':
16664 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16665 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16666 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16667 type = 'b';
16668 /*lint -fallthrough*/
16669 case 'b':
16670 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16671 break;
16672 default:
16673 assert(type == 'B');
16674 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16675 break;
16676 }
16677
16678 /* print coefficients and variables */
16679 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16680 {
16681 if( genericnames )
16682 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16683 else
16684 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16685
16686 if( (j+1) % 10 == 0 )
16687 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16688 }
16689
16690 /* print right hand side */
16691 switch( type )
16692 {
16693 case 'b':
16694 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16695 type = 'B';
16696 goto WRITEROW;
16697 case 'l':
16698 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16699 break;
16700 case 'B':
16701 case 'r':
16702 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16703 break;
16704 case 'e':
16705 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16706 break;
16707 default:
16708 SCIPerrorMessage("Undefined row type!\n");
16709 fclose(file);
16710 return SCIP_ERROR;
16711 }
16712 }
16713
16714 if ( lazyconss )
16715 {
16716 /* print lazy constraint section */
16717 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16718 for( i = 0; i < lp->nrows; i++ )
16719 {
16720 char type = 'i';
16721
16722 /* skip non-removable rows if we want to write lazy constraints */
16723 if ( ! SCIProwIsRemovable(lp->rows[i]) )
16724 continue;
16725
16726 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16727 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16728 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16729 * type 'i' means: lhs and rhs are both infinite */
16730 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16731 type = 'r';
16732 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16733 type = 'l';
16734 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16735 type = 'e';
16736 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16737 type = 'b';
16738
16739 /* print name of row */
16740 if( genericnames )
16741 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16742 else
16743 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16744
16745 WRITELAZYROW:
16746 switch( type )
16747 {
16748 case 'r':
16749 case 'l':
16750 case 'e':
16751 if( strlen(rowname) > 0 )
16752 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16753 break;
16754 case 'i':
16755 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16756 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16757 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16758 type = 'b';
16759 /*lint -fallthrough*/
16760 case 'b':
16761 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16762 break;
16763 default:
16764 assert(type == 'B');
16765 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16766 break;
16767 }
16768
16769 /* print coefficients and variables */
16770 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16771 {
16772 if( genericnames )
16773 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16774 else
16775 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16776
16777 if( (j+1) % 10 == 0 )
16778 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16779 }
16780
16781 /* print right hand side */
16782 switch( type )
16783 {
16784 case 'b':
16785 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16786 type = 'B';
16787 goto WRITELAZYROW;
16788 case 'l':
16789 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16790 break;
16791 case 'B':
16792 case 'r':
16793 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16794 break;
16795 case 'e':
16796 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16797 break;
16798 default:
16799 SCIPerrorMessage("Undefined row type!\n");
16800 fclose(file);
16801 return SCIP_ERROR;
16802 }
16803 }
16804 }
16805
16806 /* print variable bounds */
16807 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16808 for( i = 0; i < lp->ncols; ++i )
16809 {
16810 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16811 {
16812 /* print lower bound as far this one is not infinity */
16813 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16814 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16815
16816 /* print variable name */
16817 if( genericnames )
16818 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16819 else
16820 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16821
16822 /* print upper bound as far this one is not infinity */
16823 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16824 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16825 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16826 }
16827 }
16828 if( origobj && objoffset != 0.0 )
16829 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16830
16831 /* print integer variables */
16832 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16833 j = 0;
16834 for( i = 0; i < lp->ncols; ++i )
16835 {
16836 if( SCIPvarIsIntegral(lp->cols[i]->var) )
16837 {
16838 /* print variable name */
16839 if( genericnames )
16840 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16841 else
16842 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16843
16844 j++;
16845 if( j % 10 == 0 )
16846 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16847 }
16848 }
16849
16850 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16851 fclose(file);
16852
16853 return SCIP_OKAY;
16854 }
16855
16856 /*
16857 * simple functions implemented as defines
16858 */
16859
16860 /* In debug mode, the following methods are implemented as function calls to ensure
16861 * type validity.
16862 * In optimized mode, the methods are implemented as defines to improve performance.
16863 * However, we want to have them in the library anyways, so we have to undef the defines.
16864 */
16865
16866 #undef SCIPcolGetObj
16867 #undef SCIPcolGetLb
16868 #undef SCIPcolGetUb
16869 #undef SCIPcolGetBestBound
16870 #undef SCIPcolGetPrimsol
16871 #undef SCIPcolGetMinPrimsol
16872 #undef SCIPcolGetMaxPrimsol
16873 #undef SCIPcolGetBasisStatus
16874 #undef SCIPcolGetVar
16875 #undef SCIPcolGetIndex
16876 #undef SCIPcolGetVarProbindex
16877 #undef SCIPcolIsIntegral
16878 #undef SCIPcolIsRemovable
16879 #undef SCIPcolGetLPPos
16880 #undef SCIPcolGetLPDepth
16881 #undef SCIPcolIsInLP
16882 #undef SCIPcolGetNNonz
16883 #undef SCIPcolGetNLPNonz
16884 #undef SCIPcolGetRows
16885 #undef SCIPcolGetVals
16886 #undef SCIPcolGetStrongbranchNode
16887 #undef SCIPcolGetNStrongbranchs
16888 #undef SCIPcolGetAge
16889 #undef SCIPboundtypeOpposite
16890 #undef SCIProwGetNNonz
16891 #undef SCIProwGetNLPNonz
16892 #undef SCIProwGetCols
16893 #undef SCIProwGetVals
16894 #undef SCIProwGetConstant
16895 #undef SCIProwGetNorm
16896 #undef SCIProwGetSumNorm
16897 #undef SCIProwGetLhs
16898 #undef SCIProwGetRhs
16899 #undef SCIProwGetDualsol
16900 #undef SCIProwGetDualfarkas
16901 #undef SCIProwGetBasisStatus
16902 #undef SCIProwGetName
16903 #undef SCIProwGetIndex
16904 #undef SCIProwGetAge
16905 #undef SCIProwGetRank
16906 #undef SCIProwIsIntegral
16907 #undef SCIProwIsLocal
16908 #undef SCIProwIsModifiable
16909 #undef SCIProwIsRemovable
16910 #undef SCIProwGetOrigintype
16911 #undef SCIProwGetOriginCons
16912 #undef SCIProwGetOriginConshdlr
16913 #undef SCIProwGetOriginSepa
16914 #undef SCIProwIsInGlobalCutpool
16915 #undef SCIProwGetLPPos
16916 #undef SCIProwGetLPDepth
16917 #undef SCIProwIsInLP
16918 #undef SCIProwGetActiveLPCount
16919 #undef SCIProwGetNLPsAfterCreation
16920 #undef SCIProwChgRank
16921 #undef SCIPlpGetCols
16922 #undef SCIPlpGetNCols
16923 #undef SCIPlpGetRows
16924 #undef SCIPlpGetNRows
16925 #undef SCIPlpGetNewcols
16926 #undef SCIPlpGetNNewcols
16927 #undef SCIPlpGetNewrows
16928 #undef SCIPlpGetNNewrows
16929 #undef SCIPlpGetObjNorm
16930 #undef SCIPlpGetRootObjval
16931 #undef SCIPlpGetRootColumnObjval
16932 #undef SCIPlpGetRootLooseObjval
16933 #undef SCIPlpGetLPI
16934 #undef SCIPlpSetIsRelax
16935 #undef SCIPlpIsRelax
16936 #undef SCIPlpIsSolved
16937 #undef SCIPlpIsSolBasic
16938 #undef SCIPlpDiving
16939 #undef SCIPlpDivingObjChanged
16940 #undef SCIPlpMarkDivingObjChanged
16941 #undef SCIPlpUnmarkDivingObjChanged
16942 #undef SCIPlpDivingRowsChanged
16943 #undef SCIPlpIsFeasEQ
16944 #undef SCIPlpIsFeasLT
16945 #undef SCIPlpIsFeasLE
16946 #undef SCIPlpIsFeasGT
16947 #undef SCIPlpIsFeasGE
16948 #undef SCIPlpIsFeasZero
16949 #undef SCIPlpIsFeasPositive
16950 #undef SCIPlpIsFeasNegative
16951
16952 /** gets objective value of column */
16953 SCIP_Real SCIPcolGetObj(
16954 SCIP_COL* col /**< LP column */
16955 )
16956 {
16957 assert(col != NULL);
16958
16959 return col->obj;
16960 }
16961
16962 /** gets lower bound of column */
16963 SCIP_Real SCIPcolGetLb(
16964 SCIP_COL* col /**< LP column */
16965 )
16966 {
16967 assert(col != NULL);
16968
16969 return col->lb;
16970 }
16971
16972 /** gets upper bound of column */
16973 SCIP_Real SCIPcolGetUb(
16974 SCIP_COL* col /**< LP column */
16975 )
16976 {
16977 assert(col != NULL);
16978
16979 return col->ub;
16980 }
16981
16982 /** gets best bound of column with respect to the objective function */
16983 SCIP_Real SCIPcolGetBestBound(
16984 SCIP_COL* col /**< LP column */
16985 )
16986 {
16987 assert(col != NULL);
16988
16989 if( col->obj >= 0.0 )
16990 return col->lb;
16991 else
16992 return col->ub;
16993 }
16994
16995 /** gets the primal LP solution of a column */
16996 SCIP_Real SCIPcolGetPrimsol(
16997 SCIP_COL* col /**< LP column */
16998 )
16999 {
17000 assert(col != NULL);
17001
17002 if( col->lppos >= 0 )
17003 return col->primsol;
17004 else
17005 return 0.0;
17006 }
17007
17008 /** gets the minimal LP solution value, this column ever assumed */
17009 SCIP_Real SCIPcolGetMinPrimsol(
17010 SCIP_COL* col /**< LP column */
17011 )
17012 {
17013 assert(col != NULL);
17014
17015 return col->minprimsol;
17016 }
17017
17018 /** gets the maximal LP solution value, this column ever assumed */
17019 SCIP_Real SCIPcolGetMaxPrimsol(
17020 SCIP_COL* col /**< LP column */
17021 )
17022 {
17023 assert(col != NULL);
17024
17025 return col->maxprimsol;
17026 }
17027
17028 /** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17029 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17030 */
17031 SCIP_BASESTAT SCIPcolGetBasisStatus(
17032 SCIP_COL* col /**< LP column */
17033 )
17034 {
17035 assert(col != NULL);
17036 assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
17037
17038 return (SCIP_BASESTAT)col->basisstatus;
17039 }
17040
17041 /** gets variable this column represents */
17042 SCIP_VAR* SCIPcolGetVar(
17043 SCIP_COL* col /**< LP column */
17044 )
17045 {
17046 assert(col != NULL);
17047
17048 return col->var;
17049 }
17050
17051 /** gets unique index of col */
17052 int SCIPcolGetIndex(
17053 SCIP_COL* col /**< LP col */
17054 )
17055 {
17056 assert(col != NULL);
17057
17058 return col->index;
17059 }
17060
17061 /** gets probindex of corresponding variable */
17062 int SCIPcolGetVarProbindex(
17063 SCIP_COL* col /**< LP col */
17064 )
17065 {
17066 assert(col != NULL);
17067
17068 return col->var_probindex;
17069 }
17070
17071 /** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17072 SCIP_Bool SCIPcolIsIntegral(
17073 SCIP_COL* col /**< LP column */
17074 )
17075 {
17076 assert(col != NULL);
17077 assert(SCIPvarIsIntegral(col->var) == col->integral);
17078
17079 return col->integral;
17080 }
17081
17082 /** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17083 SCIP_Bool SCIPcolIsRemovable(
17084 SCIP_COL* col /**< LP column */
17085 )
17086 {
17087 assert(col != NULL);
17088
17089 return col->removable;
17090 }
17091
17092 /** gets position of column in current LP, or -1 if it is not in LP */
17093 int SCIPcolGetLPPos(
17094 SCIP_COL* col /**< LP column */
17095 )
17096 {
17097 assert(col != NULL);
17098 assert((col->lppos == -1) == (col->lpdepth == -1));
17099
17100 return col->lppos;
17101 }
17102
17103 /** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17104 int SCIPcolGetLPDepth(
17105 SCIP_COL* col /**< LP column */
17106 )
17107 {
17108 assert(col != NULL);
17109 assert((col->lppos == -1) == (col->lpdepth == -1));
17110
17111 return col->lpdepth;
17112 }
17113
17114 /** returns TRUE iff column is member of current LP */
17115 SCIP_Bool SCIPcolIsInLP(
17116 SCIP_COL* col /**< LP column */
17117 )
17118 {
17119 assert(col != NULL);
17120 assert((col->lppos == -1) == (col->lpdepth == -1));
17121
17122 return (col->lppos >= 0);
17123 }
17124
17125 /** get number of nonzero entries in column vector */
17126 int SCIPcolGetNNonz(
17127 SCIP_COL* col /**< LP column */
17128 )
17129 {
17130 assert(col != NULL);
17131
17132 return col->len;
17133 }
17134
17135 /** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17136 *
17137 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17138 * that is in the current LP and the LP was solved, or a column that was in a solved LP and didn't change afterwards
17139 */
17140 int SCIPcolGetNLPNonz(
17141 SCIP_COL* col /**< LP column */
17142 )
17143 {
17144 assert(col != NULL);
17145 assert(col->nunlinked == 0);
17146
17147 return col->nlprows;
17148 }
17149
17150 /** gets array with rows of nonzero entries */
17151 SCIP_ROW** SCIPcolGetRows(
17152 SCIP_COL* col /**< LP column */
17153 )
17154 {
17155 assert(col != NULL);
17156
17157 return col->rows;
17158 }
17159
17160 /** gets array with coefficients of nonzero entries */
17161 SCIP_Real* SCIPcolGetVals(
17162 SCIP_COL* col /**< LP column */
17163 )
17164 {
17165 assert(col != NULL);
17166
17167 return col->vals;
17168 }
17169
17170 /** gets node number of the last node in current branch and bound run, where strong branching was used on the
17171 * given column, or -1 if strong branching was never applied to the column in current run
17172 */
17173 SCIP_Longint SCIPcolGetStrongbranchNode(
17174 SCIP_COL* col /**< LP column */
17175 )
17176 {
17177 assert(col != NULL);
17178
17179 return col->sbnode;
17180 }
17181
17182 /** gets number of times, strong branching was applied in current run on the given column */
17183 int SCIPcolGetNStrongbranchs(
17184 SCIP_COL* col /**< LP column */
17185 )
17186 {
17187 assert(col != NULL);
17188
17189 return col->nsbcalls;
17190 }
17191
17192 /** gets the age of a column, i.e., the total number of successive times a column was in the LP and was 0.0 in the solution */
17193 int SCIPcolGetAge(
17194 SCIP_COL* col /**< LP column */
17195 )
17196 {
17197 assert(col != NULL);
17198
17199 return col->age;
17200 }
17201
17202 /** gets opposite bound type of given bound type */
17203 SCIP_BOUNDTYPE SCIPboundtypeOpposite(
17204 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
17205 )
17206 {
17207 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17208
17209 return (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
17210 }
17211
17212 /** get number of nonzero entries in row vector */
17213 int SCIProwGetNNonz(
17214 SCIP_ROW* row /**< LP row */
17215 )
17216 {
17217 assert(row != NULL);
17218
17219 return row->len;
17220 }
17221
17222 /** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17223 *
17224 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17225 * that is in the current LP and the LP was solved, or a row that was in a solved LP and didn't change afterwards
17226 */
17227 int SCIProwGetNLPNonz(
17228 SCIP_ROW* row /**< LP row */
17229 )
17230 {
17231 assert(row != NULL);
17232 assert(row->nunlinked == 0);
17233
17234 return row->nlpcols;
17235 }
17236
17237 /** gets array with columns of nonzero entries */
17238 SCIP_COL** SCIProwGetCols(
17239 SCIP_ROW* row /**< LP row */
17240 )
17241 {
17242 assert(row != NULL);
17243
17244 return row->cols;
17245 }
17246
17247 /** gets array with coefficients of nonzero entries */
17248 SCIP_Real* SCIProwGetVals(
17249 SCIP_ROW* row /**< LP row */
17250 )
17251 {
17252 assert(row != NULL);
17253
17254 return row->vals;
17255 }
17256
17257 /** gets constant shift of row */
17258 SCIP_Real SCIProwGetConstant(
17259 SCIP_ROW* row /**< LP row */
17260 )
17261 {
17262 assert(row != NULL);
17263
17264 return row->constant;
17265 }
17266
17267 /** gets Euclidean norm of row vector */
17268 SCIP_Real SCIProwGetNorm(
17269 SCIP_ROW* row /**< LP row */
17270 )
17271 {
17272 assert(row != NULL);
17273
17274 checkRowSqrnorm(row);
17275
17276 return sqrt(row->sqrnorm);
17277 }
17278
17279 /** gets sum norm of row vector (sum of absolute values of coefficients) */
17280 SCIP_Real SCIProwGetSumNorm(
17281 SCIP_ROW* row /**< LP row */
17282 )
17283 {
17284 assert(row != NULL);
17285
17286 checkRowSumnorm(row);
17287
17288 return row->sumnorm;
17289 }
17290
17291 /** returns the left hand side of the row */
17292 SCIP_Real SCIProwGetLhs(
17293 SCIP_ROW* row /**< LP row */
17294 )
17295 {
17296 assert(row != NULL);
17297
17298 return row->lhs;
17299 }
17300
17301 /** returns the right hand side of the row */
17302 SCIP_Real SCIProwGetRhs(
17303 SCIP_ROW* row /**< LP row */
17304 )
17305 {
17306 assert(row != NULL);
17307
17308 return row->rhs;
17309 }
17310
17311 /** gets the dual LP solution of a row */
17312 SCIP_Real SCIProwGetDualsol(
17313 SCIP_ROW* row /**< LP row */
17314 )
17315 {
17316 assert(row != NULL);
17317
17318 if( row->lppos >= 0 )
17319 return row->dualsol;
17320 else
17321 return 0.0;
17322 }
17323
17324 /** gets the dual Farkas coefficient of a row in an infeasible LP */
17325 SCIP_Real SCIProwGetDualfarkas(
17326 SCIP_ROW* row /**< LP row */
17327 )
17328 {
17329 assert(row != NULL);
17330
17331 if( row->lppos >= 0 )
17332 return row->dualfarkas;
17333 else
17334 return 0.0;
17335 }
17336
17337 /** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17338 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17339 */
17340 SCIP_BASESTAT SCIProwGetBasisStatus(
17341 SCIP_ROW* row /**< LP row */
17342 )
17343 {
17344 assert(row != NULL);
17345 assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
17346
17347 return (SCIP_BASESTAT)row->basisstatus;
17348 }
17349
17350 /** returns the name of the row */
17351 const char* SCIProwGetName(
17352 SCIP_ROW* row /**< LP row */
17353 )
17354 {
17355 assert(row != NULL);
17356
17357 return row->name;
17358 }
17359
17360 /** gets unique index of row */
17361 int SCIProwGetIndex(
17362 SCIP_ROW* row /**< LP row */
17363 )
17364 {
17365 assert(row != NULL);
17366
17367 return row->index;
17368 }
17369
17370 /** gets age of row */
17371 int SCIProwGetAge(
17372 SCIP_ROW* row /**< LP row */
17373 )
17374 {
17375 assert(row != NULL);
17376
17377 return row->age;
17378 }
17379
17380 /** gets rank of row */
17381 int SCIProwGetRank(
17382 SCIP_ROW* row /**< LP row */
17383 )
17384 {
17385 assert(row != NULL);
17386
17387 return row->rank;
17388 }
17389
17390 /** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17391 SCIP_Bool SCIProwIsIntegral(
17392 SCIP_ROW* row /**< LP row */
17393 )
17394 {
17395 assert(row != NULL);
17396
17397 return row->integral;
17398 }
17399
17400 /** returns TRUE iff row is only valid locally */
17401 SCIP_Bool SCIProwIsLocal(
17402 SCIP_ROW* row /**< LP row */
17403 )
17404 {
17405 assert(row != NULL);
17406
17407 return row->local;
17408 }
17409
17410 /** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17411 SCIP_Bool SCIProwIsModifiable(
17412 SCIP_ROW* row /**< LP row */
17413 )
17414 {
17415 assert(row != NULL);
17416
17417 return row->modifiable;
17418 }
17419
17420 /** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17421 SCIP_Bool SCIProwIsRemovable(
17422 SCIP_ROW* row /**< LP row */
17423 )
17424 {
17425 assert(row != NULL);
17426
17427 return row->removable;
17428 }
17429
17430 /** returns type of origin that created the row */
17431 SCIP_ROWORIGINTYPE SCIProwGetOrigintype(
17432 SCIP_ROW* row /**< LP row */
17433 )
17434 {
17435 assert( row != NULL );
17436
17437 return (SCIP_ROWORIGINTYPE) row->origintype;
17438 }
17439
17440 /** returns origin constraint that created the row (NULL if not available) */
17441 SCIP_CONS* SCIProwGetOriginCons(
17442 SCIP_ROW* row /**< LP row */
17443 )
17444 {
17445 assert( row != NULL );
17446
17447 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS )
17448 {
17449 assert( row->origin != NULL );
17450 return (SCIP_CONS*) row->origin;
17451 }
17452 return NULL;
17453 }
17454
17455 /** returns origin constraint handler that created the row (NULL if not available) */
17456 SCIP_CONSHDLR* SCIProwGetOriginConshdlr(
17457 SCIP_ROW* row /**< LP row */
17458 )
17459 {
17460 assert( row != NULL );
17461
17462 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONSHDLR )
17463 {
17464 assert( row->origin != NULL );
17465 return (SCIP_CONSHDLR*) row->origin;
17466 }
17467 else if( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS )
17468 {
17469 assert(row->origin != NULL);
17470 return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17471 }
17472 return NULL;
17473 }
17474
17475 /** returns origin separator that created the row (NULL if not available) */
17476 SCIP_SEPA* SCIProwGetOriginSepa(
17477 SCIP_ROW* row /**< LP row */
17478 )
17479 {
17480 assert( row != NULL );
17481
17482 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_SEPA )
17483 {
17484 assert( row->origin != NULL );
17485 return (SCIP_SEPA*) row->origin;
17486 }
17487 return NULL;
17488 }
17489
17490 /** returns TRUE iff row is member of the global cut pool */
17491 SCIP_Bool SCIProwIsInGlobalCutpool(
17492 SCIP_ROW* row /**< LP row */
17493 )
17494 {
17495 assert(row != NULL);
17496
17497 return row->inglobalcutpool;
17498 }
17499
17500 /** gets position of row in current LP, or -1 if it is not in LP */
17501 int SCIProwGetLPPos(
17502 SCIP_ROW* row /**< LP row */
17503 )
17504 {
17505 assert(row != NULL);
17506 assert((row->lppos == -1) == (row->lpdepth == -1));
17507
17508 return row->lppos;
17509 }
17510
17511 /** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17512 int SCIProwGetLPDepth(
17513 SCIP_ROW* row /**< LP row */
17514 )
17515 {
17516 assert(row != NULL);
17517 assert((row->lppos == -1) == (row->lpdepth == -1));
17518
17519 return row->lpdepth;
17520 }
17521
17522 /** returns TRUE iff row is member of current LP */
17523 SCIP_Bool SCIProwIsInLP(
17524 SCIP_ROW* row /**< LP row */
17525 )
17526 {
17527 assert(row != NULL);
17528 assert((row->lppos == -1) == (row->lpdepth == -1));
17529
17530 return (row->lppos >= 0);
17531 }
17532
17533 /** changes the rank of LP row */
17534 void SCIProwChgRank(
17535 SCIP_ROW* row, /**< LP row */
17536 int rank /**< new value for rank */
17537 )
17538 {
17539 assert(row != NULL);
17540
17541 row->rank = rank;
17542 }
17543
17544 /** returns the number of times that this row has been sharp in an optimal LP solution */
17545 SCIP_Longint SCIProwGetActiveLPCount(
17546 SCIP_ROW* row /**< row */
17547 )
17548 {
17549 assert(row != NULL);
17550
17551 return row->activeinlpcounter;
17552 }
17553
17554 /** returns the number of LPs since this row has been created */
17555 SCIP_Longint SCIProwGetNLPsAfterCreation(
17556 SCIP_ROW* row /**< row */
17557 )
17558 {
17559 assert(row != NULL);
17560
17561 return row->nlpsaftercreation;
17562 }
17563
17564 /** gets array with columns of the LP */
17565 SCIP_COL** SCIPlpGetCols(
17566 SCIP_LP* lp /**< current LP data */
17567 )
17568 {
17569 assert(lp != NULL);
17570
17571 return lp->cols;
17572 }
17573
17574 /** gets current number of columns in LP */
17575 int SCIPlpGetNCols(
17576 SCIP_LP* lp /**< current LP data */
17577 )
17578 {
17579 assert(lp != NULL);
17580
17581 return lp->ncols;
17582 }
17583
17584 /** gets current number of unfixed columns in LP */
17585 int SCIPlpGetNUnfixedCols(
17586 SCIP_LP* lp, /**< current LP data */
17587 SCIP_Real eps /**< numerical tolerance */
17588 )
17589 {
17590 SCIP_COL** lpcols;
17591 int nlpcols;
17592 int nunfixedcols;
17593 int c;
17594
17595 assert(lp != NULL);
17596 assert(eps > 0.0);
17597
17598 lpcols = lp->cols;
17599 nlpcols = lp->ncols;
17600
17601 nunfixedcols = 0;
17602 for( c = 0; c < nlpcols; ++c )
17603 {
17604 if( lpcols[c]->ub - lpcols[c]->lb > eps )
17605 ++nunfixedcols;
17606 }
17607
17608 return nunfixedcols;
17609 }
17610
17611 /** gets array with rows of the LP */
17612 SCIP_ROW** SCIPlpGetRows(
17613 SCIP_LP* lp /**< current LP data */
17614 )
17615 {
17616 assert(lp != NULL);
17617
17618 return lp->rows;
17619 }
17620
17621 /** gets current number of rows in LP */
17622 int SCIPlpGetNRows(
17623 SCIP_LP* lp /**< current LP data */
17624 )
17625 {
17626 assert(lp != NULL);
17627
17628 return lp->nrows;
17629 }
17630
17631 /** gets array with newly added columns after the last mark */
17632 SCIP_COL** SCIPlpGetNewcols(
17633 SCIP_LP* lp /**< current LP data */
17634 )
17635 {
17636 assert(lp != NULL);
17637 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17638
17639 return &(lp->cols[lp->firstnewcol]);
17640 }
17641
17642 /** gets number of newly added columns after the last mark */
17643 int SCIPlpGetNNewcols(
17644 SCIP_LP* lp /**< current LP data */
17645 )
17646 {
17647 assert(lp != NULL);
17648 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17649
17650 return lp->ncols - lp->firstnewcol;
17651 }
17652
17653 /** gets array with newly added rows after the last mark */
17654 SCIP_ROW** SCIPlpGetNewrows(
17655 SCIP_LP* lp /**< current LP data */
17656 )
17657 {
17658 assert(lp != NULL);
17659 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17660
17661 return &(lp->rows[lp->firstnewrow]);
17662 }
17663
17664 /** gets number of newly added rows after the last mark */
17665 int SCIPlpGetNNewrows(
17666 SCIP_LP* lp /**< current LP data */
17667 )
17668 {
17669 assert(lp != NULL);
17670 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17671
17672 return lp->nrows - lp->firstnewrow;
17673 }
17674
17675 /** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17676 void SCIPlpRecalculateObjSqrNorm(
17677 SCIP_SET* set, /**< global SCIP settings */
17678 SCIP_LP* lp /**< LP data */
17679 )
17680 {
17681 if( lp->objsqrnormunreliable )
17682 {
17683 SCIP_COL** cols;
17684 int c;
17685
17686 cols = lp->cols;
17687 assert(cols != NULL || lp->ncols == 0);
17688
17689 lp->objsqrnorm = 0.0;
17690
17691 for( c = lp->ncols - 1; c >= 0; --c )
17692 {
17693 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
17694 }
17695 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17696
17697 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17698 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17699
17700 lp->objsqrnormunreliable = FALSE;
17701 }
17702 return;
17703 }
17704
17705 /** gets Euclidean norm of objective function vector of column variables, only use this method if
17706 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17707 SCIP_Real SCIPlpGetObjNorm(
17708 SCIP_LP* lp /**< LP data */
17709 )
17710 {
17711 assert(lp != NULL);
17712 assert(!lp->objsqrnormunreliable);
17713 assert(lp->objsqrnorm >= 0.0);
17714
17715 return SQRT(lp->objsqrnorm);
17716 }
17717
17718 /** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17719 void SCIPlpSetRootLPIsRelax(
17720 SCIP_LP* lp, /**< LP data */
17721 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
17722 )
17723 {
17724 assert(lp != NULL);
17725
17726 lp->rootlpisrelax = isrelax;
17727 }
17728
17729 /** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17730 SCIP_Bool SCIPlpIsRootLPRelax(
17731 SCIP_LP* lp /**< LP data */
17732 )
17733 {
17734 assert(lp != NULL);
17735
17736 return lp->rootlpisrelax;
17737 }
17738
17739 /** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17740 SCIP_Real SCIPlpGetRootObjval(
17741 SCIP_LP* lp /**< LP data */
17742 )
17743 {
17744 assert(lp != NULL);
17745
17746 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17747 }
17748
17749 /** gets part of the objective value of the root node LP that results from COLUMN variables only;
17750 * returns SCIP_INVALID if the root node LP was not (yet) solved
17751 */
17752 SCIP_Real SCIPlpGetRootColumnObjval(
17753 SCIP_LP* lp /**< LP data */
17754 )
17755 {
17756 assert(lp != NULL);
17757
17758 return lp->rootlpobjval;
17759 }
17760
17761 /** gets part of the objective value of the root node LP that results from LOOSE variables only;
17762 * returns SCIP_INVALID if the root node LP was not (yet) solved
17763 */
17764 SCIP_Real SCIPlpGetRootLooseObjval(
17765 SCIP_LP* lp /**< LP data */
17766 )
17767 {
17768 assert(lp != NULL);
17769
17770 return lp->rootlooseobjval;
17771 }
17772
17773 /** gets the LP solver interface */
17774 SCIP_LPI* SCIPlpGetLPI(
17775 SCIP_LP* lp /**< current LP data */
17776 )
17777 {
17778 assert(lp != NULL);
17779
17780 return lp->lpi;
17781 }
17782
17783 /** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17784 void SCIPlpSetIsRelax(
17785 SCIP_LP* lp, /**< LP data */
17786 SCIP_Bool relax /**< is the current lp a relaxation? */
17787 )
17788 {
17789 assert(lp != NULL);
17790
17791 lp->isrelax = relax;
17792 }
17793
17794 /** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17795 * solution value a valid local lower bound?
17796 */
17797 SCIP_Bool SCIPlpIsRelax(
17798 SCIP_LP* lp /**< LP data */
17799 )
17800 {
17801 assert(lp != NULL);
17802
17803 return lp->isrelax;
17804 }
17805
17806 /** returns whether the current LP is flushed and solved */
17807 SCIP_Bool SCIPlpIsSolved(
17808 SCIP_LP* lp /**< current LP data */
17809 )
17810 {
17811 assert(lp != NULL);
17812
17813 return lp->flushed && lp->solved;
17814 }
17815
17816 /** return whether the current LP solution passed the primal feasibility check */
17817 SCIP_Bool SCIPlpIsPrimalReliable(
17818 SCIP_LP* lp /**< current LP data */
17819 )
17820 {
17821 assert(lp != NULL);
17822
17823 return (lp->primalchecked && lp->primalfeasible);
17824 }
17825
17826 /** return whether the current LP solution passed the dual feasibility check */
17827 SCIP_Bool SCIPlpIsDualReliable(
17828 SCIP_LP* lp /**< current LP data */
17829 )
17830 {
17831 assert(lp != NULL);
17832
17833 return (lp->dualchecked && lp->dualfeasible);
17834 }
17835
17836 /** returns whether the current LP solution is a basic solution */
17837 SCIP_Bool SCIPlpIsSolBasic(
17838 SCIP_LP* lp /**< current LP data */
17839 )
17840 {
17841 assert(lp != NULL);
17842
17843 return lp->solisbasic;
17844 }
17845
17846 /** returns whether the LP is in diving mode */
17847 SCIP_Bool SCIPlpDiving(
17848 SCIP_LP* lp /**< current LP data */
17849 )
17850 {
17851 assert(lp != NULL);
17852
17853 return lp->diving;
17854 }
17855
17856 /** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17857 SCIP_Bool SCIPlpDivingObjChanged(
17858 SCIP_LP* lp /**< current LP data */
17859 )
17860 {
17861 assert(lp != NULL);
17862
17863 return lp->divingobjchg;
17864 }
17865
17866 /** marks the diving LP to have a changed objective function */
17867 void SCIPlpMarkDivingObjChanged(
17868 SCIP_LP* lp /**< current LP data */
17869 )
17870 {
17871 assert(lp != NULL);
17872 assert(lp->diving || lp->probing);
17873
17874 lp->divingobjchg = TRUE;
17875 }
17876
17877 /** marks the diving LP to not have a changed objective function anymore */
17878 void SCIPlpUnmarkDivingObjChanged(
17879 SCIP_LP* lp /**< current LP data */
17880 )
17881 {
17882 assert(lp != NULL);
17883 assert(lp->diving || lp->probing);
17884
17885 lp->divingobjchg = FALSE;
17886 }
17887
17888 /* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17889 SCIP_Bool SCIPlpDivingRowsChanged(
17890 SCIP_LP* lp /**< current LP data */
17891 )
17892 {
17893 assert(lp != NULL);
17894 assert(lp->diving || lp->ndivechgsides == 0);
17895
17896 return (lp->ndivechgsides > 0);
17897 }
17898
17899 /** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17900 static
17901 SCIP_RETCODE computeRelIntPoint(
17902 SCIP_LPI* lpi, /**< auxiliary LP interface */
17903 SCIP_SET* set, /**< global SCIP settings */
17904 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17905 SCIP_LP* lp, /**< LP data */
17906 SCIP_PROB* prob, /**< problem data */
17907 SCIP_Bool relaxrows, /**< should the rows be relaxed */
17908 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
17909 SCIP_Real timelimit, /**< time limit for LP solver */
17910 int iterlimit, /**< iteration limit for LP solver */
17911 SCIP_Real* point, /**< array to store relative interior point on exit */
17912 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
17913 )
17914 {
17915 SCIP_RETCODE retcode;
17916 SCIP_Real* primal;
17917 SCIP_Real* obj;
17918 SCIP_Real* lb;
17919 SCIP_Real* ub;
17920 SCIP_Real* matvals;
17921 SCIP_Real* matlhs;
17922 SCIP_Real* matrhs;
17923 SCIP_Real objval;
17924 SCIP_Real alpha;
17925 int* matinds;
17926 int* matbeg;
17927 #ifndef NDEBUG
17928 int nslacks;
17929 #endif
17930 int nnewcols;
17931 int ntotnonz = 0;
17932 int ntotrows = 0;
17933 int matrowidx;
17934 int matidx;
17935 int cnt;
17936 int j;
17937 int i;
17938
17939 assert(lpi != NULL);
17940
17941 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17942 if( retcode != SCIP_OKAY )
17943 {
17944 /* stop execution on error, since result is likely to be unsuable */
17945 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17946 return SCIP_LPERROR;
17947 }
17948
17949 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_DUALFEASTOL, SCIPsetDualfeastol(set));
17950 if( retcode != SCIP_OKAY )
17951 {
17952 /* stop execution on error, since result is likely to be unsuable */
17953 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17954 return SCIP_LPERROR;
17955 }
17956
17957 /* get storage */
17958 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17959 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17960 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17961 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17962
17963 /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17964 for( j = 0; j < lp->ncols; ++j )
17965 {
17966 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
17967 obj[j] = 0.0;
17968 lb[j] = -SCIPlpiInfinity(lpi);
17969 ub[j] = SCIPlpiInfinity(lpi);
17970 /* note: we could also use the original bounds - free variables seem to be faster. */
17971 }
17972
17973 /* add artificial alpha variable */
17974 nnewcols = lp->ncols;
17975 obj[nnewcols] = 0.0;
17976 lb[nnewcols] = 1.0;
17977 ub[nnewcols] = SCIPlpiInfinity(lpi);
17978 ++nnewcols;
17979
17980 /* create slacks for rows */
17981 for( i = 0; i < lp->nrows; ++i )
17982 {
17983 SCIP_ROW* row;
17984
17985 row = lp->rows[i];
17986 assert( row != NULL );
17987
17988 if( SCIProwIsModifiable(row) )
17989 continue;
17990
17991 /* make sure row is sorted */
17992 rowSortLP(row);
17993 assert( row->lpcolssorted );
17994
17995 /* check whether we have an equation */
17996 if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
17997 {
17998 assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
17999 assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
18000 ntotnonz += row->nlpcols + 1;
18001 ++ntotrows;
18002 }
18003 else
18004 {
18005 /* otherwise add slacks for each side if necessary */
18006 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18007 {
18008 if ( relaxrows )
18009 {
18010 lb[nnewcols] = 0.0;
18011 ub[nnewcols] = 1.0;
18012 obj[nnewcols++] = 1.0;
18013 ntotnonz += row->nlpcols + 2;
18014 }
18015 else
18016 ntotnonz += row->nlpcols + 1;
18017 ++ntotrows;
18018 }
18019 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18020 {
18021 if ( relaxrows )
18022 {
18023 lb[nnewcols] = 0.0;
18024 ub[nnewcols] = 1.0;
18025 obj[nnewcols++] = 1.0;
18026 ntotnonz += row->nlpcols + 2;
18027 }
18028 else
18029 ntotnonz += row->nlpcols + 1;
18030 ++ntotrows;
18031 }
18032 }
18033 }
18034
18035 /* create slacks for objective cutoff row */
18036 if( inclobjcutoff && relaxrows )
18037 {
18038 /* add slacks for right hand side */
18039 lb[nnewcols] = 0.0;
18040 ub[nnewcols] = 1.0;
18041 obj[nnewcols++] = 1.0;
18042 ntotnonz += lp->ncols + 2;
18043 ++ntotrows;
18044 }
18045
18046 /* create slacks for bounds */
18047 for( j = 0; j < lp->ncols; ++j )
18048 {
18049 SCIP_COL* col;
18050
18051 col = lp->cols[j];
18052 assert( col != NULL );
18053
18054 /* no slacks for fixed variables */
18055 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18056 {
18057 ++ntotrows;
18058 ntotnonz += 2;
18059 }
18060 else
18061 {
18062 /* add slacks for each bound if necessary */
18063 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18064 {
18065 lb[nnewcols] = 0.0;
18066 ub[nnewcols] = 1.0;
18067 obj[nnewcols++] = 1.0;
18068 ntotnonz += 3;
18069 ++ntotrows;
18070 }
18071 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18072 {
18073 lb[nnewcols] = 0.0;
18074 ub[nnewcols] = 1.0;
18075 obj[nnewcols++] = 1.0;
18076 ntotnonz += 3;
18077 ++ntotrows;
18078 }
18079 }
18080 }
18081 #ifndef NDEBUG
18082 nslacks = nnewcols - lp->ncols - 1;
18083 assert( nslacks >= 0 );
18084 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18085 #endif
18086
18087 /* add columns */
18088 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18089
18090 /* free storage */
18091 SCIPsetFreeBufferArray(set, &obj);
18092 SCIPsetFreeBufferArray(set, &ub);
18093 SCIPsetFreeBufferArray(set, &lb);
18094
18095 /* prepare storage for rows */
18096 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18097 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18098 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18099 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18100 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18101
18102 /* create rows arising from original rows */
18103 cnt = 0;
18104 matrowidx = 0;
18105 matidx = 0;
18106 for( i = 0; i < lp->nrows; ++i )
18107 {
18108 SCIP_ROW* row;
18109 SCIP_COL** rowcols;
18110 SCIP_Real* rowvals;
18111 SCIP_Real lhs;
18112 SCIP_Real rhs;
18113 int nnonz;
18114
18115 row = lp->rows[i];
18116 assert( row != NULL );
18117
18118 if( SCIProwIsModifiable(row) )
18119 continue;
18120 assert( row->lpcolssorted );
18121
18122 /* get row data */
18123 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18124 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18125 nnonz = row->nlpcols;
18126 assert( nnonz <= lp->ncols );
18127 rowcols = row->cols;
18128 rowvals = row->vals;
18129
18130 /* if we have an equation */
18131 if( SCIPsetIsEQ(set, lhs, rhs) )
18132 {
18133 /* set up indices */
18134 matbeg[matrowidx] = matidx;
18135 for( j = 0; j < nnonz; ++j )
18136 {
18137 assert( rowcols[j] != NULL );
18138 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18139 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18140 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18141 matinds[matidx] = rowcols[j]->lppos;
18142 matvals[matidx++] = rowvals[j];
18143 assert( matidx <= ntotnonz );
18144 }
18145
18146 /* add artificial variable */
18147 if ( ! SCIPsetIsZero(set, rhs) )
18148 {
18149 matinds[matidx] = lp->ncols;
18150 matvals[matidx++] = -rhs;
18151 assert( matidx <= ntotnonz );
18152 }
18153
18154 matlhs[matrowidx] = 0.0;
18155 matrhs[matrowidx++] = 0.0;
18156 assert( matrowidx <= ntotrows );
18157 }
18158 else
18159 {
18160 SCIP_Real abslhs = REALABS(lhs);
18161 SCIP_Real absrhs = REALABS(rhs);
18162
18163 assert(!SCIPsetIsEQ(set, lhs, rhs));
18164
18165 /* treat lhs */
18166 if( !SCIPsetIsInfinity(set, abslhs) )
18167 {
18168 /* set up indices */
18169 matbeg[matrowidx] = matidx;
18170 for( j = 0; j < nnonz; ++j )
18171 {
18172 assert( rowcols[j] != NULL );
18173 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18174 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18175 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18176 matinds[matidx] = rowcols[j]->lppos;
18177 matvals[matidx++] = rowvals[j];
18178 assert( matidx <= ntotnonz );
18179 }
18180
18181 /* add artificial variable */
18182 if ( ! SCIPsetIsZero(set, lhs) )
18183 {
18184 matinds[matidx] = lp->ncols;
18185 matvals[matidx++] = -lhs;
18186 assert( matidx <= ntotnonz );
18187 }
18188
18189 if( relaxrows )
18190 {
18191 /* add slack variable */
18192 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/
18193 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18194 assert( matidx <= ntotnonz );
18195 ++cnt;
18196 }
18197
18198 matlhs[matrowidx] = 0.0;
18199 matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18200 assert( matrowidx <= ntotrows );
18201 }
18202
18203 /* treat rhs */
18204 if( !SCIPsetIsInfinity(set, absrhs) )
18205 {
18206 /* set up indices */
18207 matbeg[matrowidx] = matidx;
18208 for( j = 0; j < nnonz; ++j )
18209 {
18210 assert( rowcols[j] != NULL );
18211 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18212 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18213 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18214 matinds[matidx] = rowcols[j]->lppos;
18215 matvals[matidx++] = rowvals[j];
18216 assert( matidx <= ntotnonz );
18217 }
18218
18219 /* add artificial variable */
18220 if ( ! SCIPsetIsZero(set, rhs) )
18221 {
18222 matinds[matidx] = lp->ncols;
18223 matvals[matidx++] = -rhs;
18224 assert( matidx <= ntotnonz );
18225 }
18226
18227 if( relaxrows )
18228 {
18229 /* add slack variable */
18230 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/
18231 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18232 ++cnt;
18233 }
18234
18235 matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18236 matrhs[matrowidx++] = 0.0;
18237 assert( matrowidx <= ntotrows );
18238 }
18239 }
18240 }
18241
18242 /* create row arising from objective cutoff */
18243 if( inclobjcutoff )
18244 {
18245 SCIP_Real rhs;
18246
18247 /* get row data */
18248 assert(lp->looseobjvalinf == 0);
18249 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18250
18251 /* set up indices and coefficients */
18252 matbeg[matrowidx] = matidx;
18253 for( j = 0; j < lp->ncols; ++j )
18254 {
18255 assert( lp->cols[j] != NULL );
18256 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18257 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18258
18259 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18260 {
18261 matinds[matidx] = lp->cols[j]->lppos;
18262 matvals[matidx++] = lp->cols[j]->obj;
18263 assert( matidx <= ntotnonz );
18264 }
18265 }
18266
18267 /* treat rhs */
18268
18269 /* add artificial variable */
18270 if ( ! SCIPsetIsZero(set, rhs) )
18271 {
18272 matinds[matidx] = lp->ncols;
18273 matvals[matidx++] = -rhs;
18274 assert( matidx <= ntotnonz );
18275 }
18276
18277 if( relaxrows )
18278 {
18279 SCIP_Real absrhs = REALABS(rhs);
18280
18281 /* add slack variable */
18282 matvals[matidx] = MAX(1.0, absrhs);
18283 matinds[matidx++] = lp->ncols + 1 + cnt;
18284 assert( matidx <= ntotnonz );
18285 ++cnt;
18286 }
18287 matlhs[matrowidx] = -SCIPsetInfinity(set);
18288 matrhs[matrowidx++] = 0.0;
18289 assert( matrowidx <= ntotrows );
18290 }
18291
18292 /* create rows arising from bounds */
18293 for( j = 0; j < lp->ncols; ++j )
18294 {
18295 SCIP_COL* col;
18296 SCIP_Real abscollb;
18297 SCIP_Real abscolub;
18298
18299 col = lp->cols[j];
18300 assert( col != NULL );
18301 assert( col->lppos == j );
18302
18303 /* fixed variable */
18304 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18305 {
18306 /* set up index of column */
18307 matbeg[matrowidx] = matidx;
18308
18309 matinds[matidx] = j;
18310 matvals[matidx++] = 1.0;
18311 assert( matidx <= ntotnonz );
18312
18313 /* add artificial variable */
18314 if ( ! SCIPsetIsZero(set, col->ub) )
18315 {
18316 matinds[matidx] = lp->ncols;
18317 matvals[matidx++] = -col->ub;
18318 assert( matidx <= ntotnonz );
18319 }
18320
18321 matlhs[matrowidx] = 0.0;
18322 matrhs[matrowidx++] = 0.0;
18323 assert( matrowidx <= ntotrows );
18324
18325 continue;
18326 }
18327
18328 abscollb = REALABS(col->lb);
18329 abscolub = REALABS(col->ub);
18330
18331 /* lower bound */
18332 if ( ! SCIPsetIsInfinity(set, abscollb) )
18333 {
18334 /* set up index of column */
18335 matbeg[matrowidx] = matidx;
18336
18337 matinds[matidx] = j;
18338 matvals[matidx++] = 1.0;
18339 assert( matidx <= ntotnonz );
18340
18341 /* add artificial variable */
18342 if ( ! SCIPsetIsZero(set, col->lb) )
18343 {
18344 matinds[matidx] = lp->ncols;
18345 matvals[matidx++] = -col->lb;
18346 assert( matidx <= ntotnonz );
18347 }
18348
18349 /* add slack variable */
18350 matvals[matidx] = -MAX(1.0, abscollb);
18351 matinds[matidx++] = lp->ncols + 1 + cnt;
18352 assert( matidx <= ntotnonz );
18353 ++cnt;
18354
18355 matlhs[matrowidx] = 0.0;
18356 matrhs[matrowidx++] = SCIPsetInfinity(set);
18357 assert( matrowidx <= ntotrows );
18358 }
18359
18360 /* upper bound */
18361 if ( ! SCIPsetIsInfinity(set, abscolub) )
18362 {
18363 /* set up index of column */
18364 matbeg[matrowidx] = matidx;
18365
18366 matinds[matidx] = j;
18367 matvals[matidx++] = 1.0;
18368 assert( matidx <= ntotnonz );
18369
18370 /* add artificial variable */
18371 if ( ! SCIPsetIsZero(set, col->ub) )
18372 {
18373 matinds[matidx] = lp->ncols;
18374 matvals[matidx++] = -col->ub;
18375 assert( matidx <= ntotnonz );
18376 }
18377
18378 /* add slack variable */
18379 matvals[matidx] = MAX(1.0, abscolub);
18380 matinds[matidx++] = lp->ncols + 1 + cnt;
18381 assert( matidx <= ntotnonz );
18382 ++cnt;
18383
18384 matlhs[matrowidx] = -SCIPsetInfinity(set);
18385 matrhs[matrowidx++] = 0.0;
18386 assert( matrowidx <= ntotrows );
18387 }
18388 }
18389 assert( cnt == nslacks );
18390 assert( matrowidx == ntotrows );
18391
18392 /* add rows */
18393 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18394
18395 SCIPsetFreeBufferArray(set, &matrhs);
18396 SCIPsetFreeBufferArray(set, &matlhs);
18397 SCIPsetFreeBufferArray(set, &matbeg);
18398 SCIPsetFreeBufferArray(set, &matvals);
18399 SCIPsetFreeBufferArray(set, &matinds);
18400
18401 #ifdef SCIP_OUTPUT
18402 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18403 #endif
18404
18405 #ifndef NDEBUG
18406 {
18407 int ncols;
18408 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18409 assert( ncols == nnewcols );
18410 }
18411 #endif
18412
18413 /* set time limit */
18414 if( SCIPsetIsInfinity(set, timelimit) )
18415 timelimit = SCIPlpiInfinity(lpi);
18416 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18417
18418 /* check, if parameter is unknown */
18419 if( retcode == SCIP_PARAMETERUNKNOWN )
18420 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18421 else if ( retcode != SCIP_OKAY )
18422 return retcode;
18423
18424 /* set iteration limit */
18425 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18426
18427 /* check, if parameter is unknown */
18428 if( retcode == SCIP_PARAMETERUNKNOWN )
18429 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18430 else if ( retcode != SCIP_OKAY )
18431 return retcode;
18432
18433 /* solve and store point */
18434 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18435 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */
18436
18437 #ifndef NDEBUG
18438 if ( SCIPlpiIsIterlimExc(lpi) )
18439 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18440 if ( SCIPlpiIsTimelimExc(lpi) )
18441 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18442 #endif
18443
18444 if( SCIPlpiIsOptimal(lpi) )
18445 {
18446 /* get primal solution */
18447 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18448 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18449 alpha = primal[lp->ncols];
18450 assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18451
18452 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18453
18454 /* construct relative interior point */
18455 for( j = 0; j < lp->ncols; ++j )
18456 point[j] = primal[j]/alpha;
18457
18458 #ifdef SCIP_DEBUG
18459 /* check whether the point is a relative interior point */
18460 cnt = 0;
18461 if( relaxrows )
18462 {
18463 for( i = 0; i < lp->nrows; ++i )
18464 {
18465 SCIP_ROW* row;
18466 SCIP_COL** rowcols;
18467 SCIP_Real* rowvals;
18468 SCIP_Real lhs;
18469 SCIP_Real rhs;
18470 SCIP_Real sum;
18471 int nnonz;
18472
18473 row = lp->rows[i];
18474 assert( row != NULL );
18475
18476 /* get row data */
18477 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18478 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18479 nnonz = row->nlpcols;
18480 assert( nnonz <= lp->ncols );
18481 rowcols = row->cols;
18482 rowvals = row->vals;
18483
18484 sum = 0.0;
18485 for( j = 0; j < nnonz; ++j )
18486 sum += rowvals[j] * primal[rowcols[j]->lppos];
18487 sum /= alpha;
18488
18489 /* if we have an equation */
18490 if( SCIPsetIsEQ(set, lhs, rhs) )
18491 {
18492 assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18493 }
18494 else
18495 {
18496 /* treat lhs */
18497 if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18498 {
18499 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18500 ++cnt;
18501 }
18502 /* treat rhs */
18503 if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18504 {
18505 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18506 ++cnt;
18507 }
18508 }
18509 }
18510 if( inclobjcutoff )
18511 {
18512 SCIP_Real sum;
18513 #ifndef NDEBUG
18514 SCIP_Real rhs;
18515
18516 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18517 #endif
18518 sum = 0.0;
18519 for( j = 0; j < lp->ncols; ++j )
18520 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18521 sum /= alpha;
18522
18523 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18524 ++cnt;
18525 }
18526 }
18527 /* check bounds */
18528 for( j = 0; j < lp->ncols; ++j )
18529 {
18530 SCIP_COL* col;
18531 #ifndef NDEBUG
18532 SCIP_Real val;
18533 #endif
18534
18535 col = lp->cols[j];
18536 assert( col != NULL );
18537 #ifndef NDEBUG
18538 val = primal[col->lppos] / alpha;
18539 #endif
18540 /* if the variable is not fixed */
18541 if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18542 {
18543 /* treat lb */
18544 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18545 {
18546 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18547 ++cnt;
18548 }
18549 /* treat rhs */
18550 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18551 {
18552 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18553 ++cnt;
18554 }
18555 }
18556 }
18557 #endif
18558
18559 /* free */
18560 SCIPsetFreeBufferArray(set, &primal);
18561
18562 *success = TRUE;
18563 }
18564
18565 return SCIP_OKAY;
18566 }
18567
18568 /** compute relative interior point
18569 *
18570 * We use the approach of@par
18571 * R. Freund, R. Roundy, M. J. Todd@par
18572 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18573 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18574 *
18575 * to compute a relative interior point for the current LP.
18576 *
18577 * Assume the original LP looks as follows:
18578 * \f[
18579 * \begin{array}{rrl}
18580 * \min & c^T x &\\
18581 * & A x & \geq a\\
18582 * & B x & \leq b\\
18583 * & D x & = d.
18584 * \end{array}
18585 * \f]
18586 * Note that bounds should be included in the system.
18587 *
18588 * To find an interior point the following LP does the job:
18589 * \f[
18590 * \begin{array}{rrl}
18591 * \max & 1^T y &\\
18592 * & A x - y - \alpha a & \geq 0\\
18593 * & B x + y - \alpha b & \leq 0\\
18594 * & D x - \alpha d & = 0\\
18595 * & 0 \leq y & \leq 1\\
18596 * & \alpha & \geq 1.
18597 * \end{array}
18598 * \f]
18599 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18600 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18601 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18602 */
18603 SCIP_RETCODE SCIPlpComputeRelIntPoint(
18604 SCIP_SET* set, /**< global SCIP settings */
18605 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18606 SCIP_LP* lp, /**< LP data */
18607 SCIP_PROB* prob, /**< problem data */
18608 SCIP_Bool relaxrows, /**< should the rows be relaxed */
18609 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
18610 SCIP_Real timelimit, /**< time limit for LP solver */
18611 int iterlimit, /**< iteration limit for LP solver */
18612 SCIP_Real* point, /**< array to store relative interior point on exit */
18613 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
18614 )
18615 {
18616 SCIP_LPI* lpi;
18617 SCIP_RETCODE retcode;
18618
18619 assert(set != NULL);
18620 assert(lp != NULL);
18621 assert(point != NULL);
18622 assert(success != NULL);
18623
18624 *success = FALSE;
18625
18626 /* check time and iteration limits */
18627 if ( timelimit <= 0.0 || iterlimit <= 0 )
18628 return SCIP_OKAY;
18629
18630 /* exit if there are no columns */
18631 assert(lp->nrows >= 0);
18632 assert(lp->ncols >= 0);
18633 if( lp->ncols == 0 )
18634 return SCIP_OKAY;
18635
18636 /* disable objective cutoff if we have none */
18637 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18638 inclobjcutoff = FALSE;
18639
18640 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18641
18642 /* if there are no rows, we return the zero point */
18643 if( lp->nrows == 0 && !inclobjcutoff )
18644 {
18645 /* create zero point */
18646 BMSclearMemoryArray(point, lp->ncols);
18647 *success = TRUE;
18648
18649 return SCIP_OKAY;
18650 }
18651
18652 /* create auxiliary LP */
18653 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18654
18655 /* catch return code and ensure that lpi is freed, anyway */
18656 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18657
18658 SCIP_CALL( SCIPlpiFree(&lpi) );
18659
18660 /* return error, unless we obtained an LP error */
18661 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18662 {
18663 SCIP_CALL( retcode );
18664 }
18665
18666 return SCIP_OKAY;
18667 }
18668
18669 /** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18670 * based on the changes applied when reducing the problem to the optimal face
18671 *
18672 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18673 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18674 */
18675 SCIP_RETCODE SCIPlpGetDualDegeneracy(
18676 SCIP_LP* lp, /**< LP data */
18677 SCIP_SET* set, /**< global SCIP settings */
18678 SCIP_STAT* stat, /**< problem statistics */
18679 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */
18680 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */
18681 )
18682 {
18683 assert(lp != NULL);
18684 assert(lp->solved);
18685 assert(lp->flushed);
18686
18687 if( lp->validdegeneracylp != stat->nlps )
18688 {
18689 lp->validdegeneracylp = stat->nlps;
18690
18691 /* if the LP was solved to optimality, we determine the dual degeneracy */
18692 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
18693 {
18694 SCIP_COL** cols;
18695 SCIP_ROW** rows;
18696 SCIP_COL* col;
18697 int ncols;
18698 int nrows;
18699 int nfixedcols = 0;
18700 int nalreadyfixedcols = 0;
18701 int nfixedrows = 0;
18702 #ifndef NDEBUG
18703 int nimplicitfixedrows = 0;
18704 #endif
18705 int nineq = 0;
18706 int c;
18707 int r;
18708 int nbasicequalities = 0;
18709
18710 cols = lp->cols;
18711 rows = lp->rows;
18712 ncols = lp->ncols;
18713 nrows = lp->nrows;
18714
18715 /* count number of columns that will be fixed when reducing the LP to the optimal face */
18716 for( c = ncols - 1 ; c >= 0; --c )
18717 {
18718 col = cols[c];
18719 assert(SCIPcolIsInLP(col));
18720
18721 /* column is not basic and not fixed already */
18722 if( (SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_BASIC) )
18723 {
18724 /* variable with nonzero reduced costs are fixed */
18725 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18726 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18727 ++nfixedcols;
18728 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18729 ++nalreadyfixedcols;
18730 }
18731 }
18732
18733 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18734 for( r = nrows - 1; r >= 0; --r )
18735 {
18736 SCIP_ROW* row = rows[r];
18737
18738 assert(SCIProwIsInLP(row));
18739
18740 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18741 {
18742 SCIP_Real dualsol = SCIProwGetDualsol(row);
18743
18744 ++nineq;
18745
18746 if( (SCIProwGetBasisStatus(row) != SCIP_BASESTAT_BASIC) )
18747 {
18748 /* rows with nonzero dual solution are turned into equations */
18749 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18750 if( !SCIPsetIsZero(set, dualsol) )
18751 {
18752 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18753 {
18754 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol));
18755 ++nfixedrows;
18756 }
18757 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18758 {
18759 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol));
18760 ++nfixedrows;
18761 }
18762 }
18763 #ifndef NDEBUG
18764 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18765 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18766 {
18767 ++nimplicitfixedrows;
18768 }
18769 #endif
18770 }
18771 }
18772 else if( SCIProwGetBasisStatus(row) == SCIP_BASESTAT_BASIC )
18773 ++nbasicequalities;
18774 }
18775 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18776
18777 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18778 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18779 else
18780 lp->degeneracy = 0.0;
18781
18782 if( nrows > 0 )
18783 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18784 else
18785 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18786 assert(lp->degeneracy >= 0);
18787 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18788 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18789 }
18790 else
18791 {
18792 lp->degeneracy = 0.0;
18793 lp->varconsratio = 0.0;
18794 }
18795 }
18796
18797 *degeneracy = lp->degeneracy;
18798 *varconsratio = lp->varconsratio;
18799
18800 return SCIP_OKAY;
18801 }
18802
18803 /** checks, if absolute difference of values is in range of LP primal feastol */
18804 SCIP_Bool SCIPlpIsFeasEQ(
18805 SCIP_SET* set, /**< global SCIP settings */
18806 SCIP_LP* lp, /**< current LP data */
18807 SCIP_Real val1, /**< first value to be compared */
18808 SCIP_Real val2 /**< second value to be compared */
18809 )
18810 {
18811 assert(set != NULL);
18812 assert(lp != NULL);
18813
18814 /* avoid to compare two different infinities; the reason for that is
18815 * that such a comparison can lead to unexpected results */
18816 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18817 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18818 || val1 == val2 ); /*lint !e777*/
18819
18820 return EPSEQ(val1, val2, lp->feastol);
18821 }
18822
18823 /** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18824 SCIP_Bool SCIPlpIsFeasLT(
18825 SCIP_SET* set, /**< global SCIP settings */
18826 SCIP_LP* lp, /**< current LP data */
18827 SCIP_Real val1, /**< first value to be compared */
18828 SCIP_Real val2 /**< second value to be compared */
18829 )
18830 {
18831 assert(set != NULL);
18832 assert(lp != NULL);
18833
18834 /* avoid to compare two different infinities; the reason for that is
18835 * that such a comparison can lead to unexpected results */
18836 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18837 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18838 || val1 == val2 ); /*lint !e777*/
18839
18840 return EPSLT(val1, val2, lp->feastol);
18841 }
18842
18843 /** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18844 SCIP_Bool SCIPlpIsFeasLE(
18845 SCIP_SET* set, /**< global SCIP settings */
18846 SCIP_LP* lp, /**< current LP data */
18847 SCIP_Real val1, /**< first value to be compared */
18848 SCIP_Real val2 /**< second value to be compared */
18849 )
18850 {
18851 assert(set != NULL);
18852 assert(lp != NULL);
18853
18854 /* avoid to compare two different infinities; the reason for that is
18855 * that such a comparison can lead to unexpected results */
18856 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18857 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18858 || val1 == val2 ); /*lint !e777*/
18859
18860 return EPSLE(val1, val2, lp->feastol);
18861 }
18862
18863 /** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18864 SCIP_Bool SCIPlpIsFeasGT(
18865 SCIP_SET* set, /**< global SCIP settings */
18866 SCIP_LP* lp, /**< current LP data */
18867 SCIP_Real val1, /**< first value to be compared */
18868 SCIP_Real val2 /**< second value to be compared */
18869 )
18870 {
18871 assert(set != NULL);
18872 assert(lp != NULL);
18873
18874 /* avoid to compare two different infinities; the reason for that is
18875 * that such a comparison can lead to unexpected results */
18876 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18877 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18878 || val1 == val2 ); /*lint !e777*/
18879
18880 return EPSGT(val1, val2, lp->feastol);
18881 }
18882
18883 /** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18884 SCIP_Bool SCIPlpIsFeasGE(
18885 SCIP_SET* set, /**< global SCIP settings */
18886 SCIP_LP* lp, /**< current LP data */
18887 SCIP_Real val1, /**< first value to be compared */
18888 SCIP_Real val2 /**< second value to be compared */
18889 )
18890 {
18891 assert(set != NULL);
18892 assert(lp != NULL);
18893
18894 /* avoid to compare two different infinities; the reason for that is
18895 * that such a comparison can lead to unexpected results */
18896 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18897 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18898 || val1 == val2 ); /*lint !e777*/
18899
18900 return EPSGE(val1, val2, lp->feastol);
18901 }
18902
18903 /** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18904 SCIP_Bool SCIPlpIsFeasZero(
18905 SCIP_LP* lp, /**< current LP data */
18906 SCIP_Real val /**< value to process */
18907 )
18908 {
18909 assert(lp != NULL);
18910
18911 return EPSZ(val, lp->feastol);
18912 }
18913
18914 /** checks, if value is greater than LP primal feasibility tolerance */
18915 SCIP_Bool SCIPlpIsFeasPositive(
18916 SCIP_LP* lp, /**< current LP data */
18917 SCIP_Real val /**< value to process */
18918 )
18919 {
18920 assert(lp != NULL);
18921
18922 return EPSP(val, lp->feastol);
18923 }
18924
18925 /** checks, if value is lower than -LP primal feasibility tolerance */
18926 SCIP_Bool SCIPlpIsFeasNegative(
18927 SCIP_LP* lp, /**< current LP data */
18928 SCIP_Real val /**< value to process */
18929 )
18930 {
18931 assert(lp != NULL);
18932
18933 return EPSN(val, lp->feastol);
18934 }
18935