Scippy

SCIP

Solving Constraint Integer Programs

lp.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file lp.c
17  * @brief LP management methods and data structures
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Gerald Gamrath
23  *
24  * In LP management, we have to differ between the current LP and the SCIP_LP
25  * stored in the LP solver. All LP methods affect the current LP only.
26  * Before solving the current LP with the LP solver or setting an LP state,
27  * the LP solvers data has to be updated to the current LP with a call to
28  * lpFlush().
29  */
30 
31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32 
33 
34 #include <assert.h>
35 #include <math.h>
36 #include <limits.h>
37 #include <string.h>
38 
39 #include "scip/def.h"
40 #include "scip/set.h"
41 #include "scip/stat.h"
42 #include "scip/intervalarith.h"
43 #include "scip/clock.h"
44 #include "scip/misc.h"
45 #include "scip/lp.h"
46 #include "scip/var.h"
47 #include "scip/prob.h"
48 #include "scip/sol.h"
49 #include "scip/solve.h"
50 #include "scip/event.h"
51 #include "scip/pub_message.h"
52 #include "lpi/lpi.h"
53 
54 #define MAXCMIRSCALE 1e+6 /**< maximal scaling (scale/(1-f0)) allowed in c-MIR calculations */
55 
56 
57 
58 /*
59  * debug messages
60  */
61 
62 #ifdef SCIP_DEBUG
63 /** method is to print in row in case SCIP_DEBUG is defined */
64 static
65 void debugRowPrint(
66  SCIP_ROW* row /**< LP row */
67  )
68 {
69  int i;
70 
71  assert(row != NULL);
72 
73  /* print row name */
74  if( row->name != NULL && row->name[0] != '\0' )
75  {
76  SCIPdebugPrintf("%s: ", row->name);
77  }
78 
79  /* print left hand side */
80  SCIPdebugPrintf("%.15g <= ", row->lhs);
81 
82  /* print coefficients */
83  if( row->len == 0 )
84  {
85  SCIPdebugPrintf("0 ");
86  }
87  for( i = 0; i < row->len; ++i )
88  {
89  assert(row->cols[i] != NULL);
90  assert(row->cols[i]->var != NULL);
91  assert(SCIPvarGetName(row->cols[i]->var) != NULL);
92  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
93  SCIPdebugPrintf("%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
94  }
95 
96  /* print constant */
98  {
99  SCIPdebugPrintf("%+.15g ", row->constant);
100  }
101 
102  /* print right hand side */
103  SCIPdebugPrintf("<= %.15g\n", row->rhs);
104 }
105 #else
106 #define debugRowPrint(x) /**/
107 #endif
108 
109 #ifdef SCIP_DEBUG
110 /** method to output column if SCIP_DEBUG is define */
111 static
112 void debugColPrint(
113  SCIP_COL* col /**< LP column */
114  )
115 {
116  int r;
117 
118  assert(col != NULL);
119  assert(col->var != NULL);
120 
121  /* print bounds */
122  SCIPdebugPrintf("(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
123 
124  /* print coefficients */
125  if( col->len == 0 )
126  {
127  SCIPdebugPrintf("<empty>");
128  }
129  for( r = 0; r < col->len; ++r )
130  {
131  assert(col->rows[r] != NULL);
132  assert(col->rows[r]->name != NULL);
133  SCIPdebugPrintf("%+.15g<%s> ", col->vals[r], col->rows[r]->name);
134  }
135  SCIPdebugPrintf("\n");
136 }
137 #else
138 #define debugColPrint(x) /**/
139 #endif
140 
141 /*
142  * memory growing methods for dynamically allocated arrays
143  */
144 
145 /** ensures, that chgcols array can store at least num entries */
146 static
148  SCIP_LP* lp, /**< current LP data */
149  SCIP_SET* set, /**< global SCIP settings */
150  int num /**< minimum number of entries to store */
151  )
152 {
153  assert(lp->nchgcols <= lp->chgcolssize);
154 
155  if( num > lp->chgcolssize )
156  {
157  int newsize;
158 
159  newsize = SCIPsetCalcMemGrowSize(set, num);
160  SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
161  lp->chgcolssize = newsize;
162  }
163  assert(num <= lp->chgcolssize);
164 
165  return SCIP_OKAY;
166 }
167 
168 /** ensures, that chgrows array can store at least num entries */
169 static
171  SCIP_LP* lp, /**< current LP data */
172  SCIP_SET* set, /**< global SCIP settings */
173  int num /**< minimum number of entries to store */
174  )
175 {
176  assert(lp->nchgrows <= lp->chgrowssize);
177 
178  if( num > lp->chgrowssize )
179  {
180  int newsize;
181 
182  newsize = SCIPsetCalcMemGrowSize(set, num);
183  SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
184  lp->chgrowssize = newsize;
185  }
186  assert(num <= lp->chgrowssize);
187 
188  return SCIP_OKAY;
189 }
190 
191 /** ensures, that lpicols array can store at least num entries */
192 static
194  SCIP_LP* lp, /**< current LP data */
195  SCIP_SET* set, /**< global SCIP settings */
196  int num /**< minimum number of entries to store */
197  )
198 {
199  assert(lp->nlpicols <= lp->lpicolssize);
200 
201  if( num > lp->lpicolssize )
202  {
203  int newsize;
204 
205  newsize = SCIPsetCalcMemGrowSize(set, num);
206  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
207  lp->lpicolssize = newsize;
208  }
209  assert(num <= lp->lpicolssize);
210 
211  return SCIP_OKAY;
212 }
213 
214 /** ensures, that lpirows array can store at least num entries */
215 static
217  SCIP_LP* lp, /**< current LP data */
218  SCIP_SET* set, /**< global SCIP settings */
219  int num /**< minimum number of entries to store */
220  )
221 {
222  assert(lp->nlpirows <= lp->lpirowssize);
223 
224  if( num > lp->lpirowssize )
225  {
226  int newsize;
227 
228  newsize = SCIPsetCalcMemGrowSize(set, num);
229  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
230  lp->lpirowssize = newsize;
231  }
232  assert(num <= lp->lpirowssize);
233 
234  return SCIP_OKAY;
235 }
236 
237 /** ensures, that cols array can store at least num entries */
238 static
240  SCIP_LP* lp, /**< current LP data */
241  SCIP_SET* set, /**< global SCIP settings */
242  int num /**< minimum number of entries to store */
243  )
244 {
245  assert(lp->ncols <= lp->colssize);
246 
247  if( num > lp->colssize )
248  {
249  int newsize;
250 
251  newsize = SCIPsetCalcMemGrowSize(set, num);
252  SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
253  lp->colssize = newsize;
254  }
255  assert(num <= lp->colssize);
256 
257  return SCIP_OKAY;
258 }
259 
260 /** ensures, that lazy cols array can store at least num entries */
261 static
263  SCIP_LP* lp, /**< current LP data */
264  SCIP_SET* set, /**< global SCIP settings */
265  int num /**< minimum number of entries to store */
266  )
267 {
268  assert(lp->nlazycols <= lp->lazycolssize);
269 
270  if( num > lp->lazycolssize )
271  {
272  int newsize;
273 
274  newsize = SCIPsetCalcMemGrowSize(set, num);
275  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
276  lp->lazycolssize = newsize;
277  }
278  assert(num <= lp->lazycolssize);
279 
280  return SCIP_OKAY;
281 }
282 
283 /** ensures, that rows array can store at least num entries */
284 static
286  SCIP_LP* lp, /**< current LP data */
287  SCIP_SET* set, /**< global SCIP settings */
288  int num /**< minimum number of entries to store */
289  )
290 {
291  assert(lp->nrows <= lp->rowssize);
292 
293  if( num > lp->rowssize )
294  {
295  int newsize;
296 
297  newsize = SCIPsetCalcMemGrowSize(set, num);
298  SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
299  lp->rowssize = newsize;
300  }
301  assert(num <= lp->rowssize);
302 
303  return SCIP_OKAY;
304 }
305 
306 /** ensures, that row array of column can store at least num entries */
307 static
309  SCIP_COL* col, /**< LP column */
310  BMS_BLKMEM* blkmem, /**< block memory */
311  SCIP_SET* set, /**< global SCIP settings */
312  int num /**< minimum number of entries to store */
313  )
314 {
315  assert(col != NULL);
316  assert(col->len <= col->size);
317 
318  if( num > col->size )
319  {
320  int newsize;
321 
322  newsize = SCIPsetCalcMemGrowSize(set, num);
323  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
324  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
325  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
326  col->size = newsize;
327  }
328  assert(num <= col->size);
329 
330  return SCIP_OKAY;
331 }
332 
333 /** save current LP values dependent on the solution */
334 static
336  SCIP_LP* lp, /**< LP data */
337  SCIP_STAT* stat, /**< problem statistics */
338  BMS_BLKMEM* blkmem /**< block memory */
339  )
340 {
341  SCIP_LPSOLVALS* storedsolvals;
342 
343  assert(lp != NULL);
344  assert(stat != NULL);
345  assert(blkmem != NULL);
346 
347  /* allocate memory for storage */
348  if( lp->storedsolvals == NULL )
349  {
351  }
352  storedsolvals = lp->storedsolvals;
353 
354  /* store values */
355  storedsolvals->lpsolstat = lp->lpsolstat;
356  storedsolvals->lpobjval = lp->lpobjval;
357  storedsolvals->primalfeasible = lp->primalfeasible;
358  storedsolvals->dualfeasible = lp->dualfeasible;
359  storedsolvals->solisbasic = lp->solisbasic;
360  storedsolvals->lpissolved = lp->solved;
361 
362  return SCIP_OKAY;
363 }
364 
365 /** restore LP solution values in column */
366 static
368  SCIP_LP* lp, /**< LP data */
369  BMS_BLKMEM* blkmem, /**< block memory */
370  SCIP_Longint validlp /**< number of lp for which restored values are valid */
371  )
372 {
373  SCIP_LPSOLVALS* storedsolvals;
374 
375  assert(lp != NULL);
376  assert(blkmem != NULL);
377 
378  /* if stored values are available, restore them */
379  storedsolvals = lp->storedsolvals;
380  if( storedsolvals != NULL )
381  {
382  lp->solved = storedsolvals->lpissolved;
383  lp->validsollp = validlp;
384 
385  lp->lpsolstat = storedsolvals->lpsolstat;
386  lp->lpobjval = storedsolvals->lpobjval;
387  lp->primalfeasible = storedsolvals->primalfeasible;
388  lp->dualfeasible = storedsolvals->dualfeasible;
389  lp->solisbasic = storedsolvals->solisbasic;
390 
391  /* solution values are stored only for LPs solved to optimality or unboundedness */
392  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
398  lp->validsollp == -1);
399  }
400  /* no values available, mark LP as unsolved */
401  else
402  {
403  lp->solved = FALSE;
404  lp->validsollp = -1;
405 
407  lp->lpobjval = SCIP_INVALID;
408  lp->primalfeasible = FALSE;
409  lp->dualfeasible = FALSE;
410  lp->solisbasic = FALSE;
411  lp->validfarkaslp = -1;
412  }
413 
414  /* intentionally keep storage space allocated */
415 
416  return SCIP_OKAY;
417 }
418 
419 /** save current LP solution values stored in each column */
420 static
422  SCIP_COL* col, /**< LP column */
423  BMS_BLKMEM* blkmem /**< block memory */
424  )
425 {
426  SCIP_COLSOLVALS* storedsolvals;
427 
428  assert(col != NULL);
429  assert(blkmem != NULL);
430 
431  /* allocate memory for storage */
432  if( col->storedsolvals == NULL )
433  {
434  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &col->storedsolvals) );
435  }
436  storedsolvals = col->storedsolvals;
437 
438  /* store values */
439  storedsolvals->primsol = col->primsol;
440  storedsolvals->redcost = col->redcost;
441  storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
442 
443  return SCIP_OKAY;
444 }
445 
446 /** restore LP solution values in column */
447 static
449  SCIP_COL* col, /**< LP column */
450  BMS_BLKMEM* blkmem, /**< block memory */
451  SCIP_Longint validlp, /**< number of lp for which restored values are valid */
452  SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */
453  )
454 {
455  SCIP_COLSOLVALS* storedsolvals;
456 
457  assert(col != NULL);
458  assert(blkmem != NULL);
459 
460  /* if stored values are available, restore them */
461  storedsolvals = col->storedsolvals;
462  if( storedsolvals != NULL )
463  {
464  col->primsol = storedsolvals->primsol;
465  col->redcost = storedsolvals->redcost;
466  col->validredcostlp = validlp;
467  col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
468 
469  /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
470  col->validfarkaslp = -1;
471  }
472  /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
473  * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
474  */
475  else
476  {
477  col->primsol = 0.0;
478  col->validredcostlp = -1;
479  col->validfarkaslp = -1;
480  col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
481  }
482 
483  /* free memory */
484  if( freebuffer )
485  {
486  BMSfreeBlockMemoryNull(blkmem, &col->storedsolvals);
487  assert(col->storedsolvals == NULL);
488  }
489 
490  return SCIP_OKAY;
491 }
492 
493 /** save current LP solution values stored in each column */
494 static
496  SCIP_ROW* row, /**< LP row */
497  BMS_BLKMEM* blkmem, /**< block memory */
498  SCIP_Bool infeasible /**< is the solution infeasible? */
499  )
500 {
501  SCIP_ROWSOLVALS* storedsolvals;
502 
503  assert(row != NULL);
504  assert(blkmem != NULL);
505 
506  /* allocate memory for storage */
507  if( row->storedsolvals == NULL )
508  {
509  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &row->storedsolvals) );
510  }
511  storedsolvals = row->storedsolvals;
512 
513  /* store values */
514  if ( infeasible )
515  {
516  storedsolvals->dualsol = row->dualfarkas;
517  storedsolvals->activity = SCIP_INVALID;
518  storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
519  }
520  else
521  {
522  storedsolvals->dualsol = row->dualsol;
523  storedsolvals->activity = row->activity;
524  storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
525  }
526 
527  return SCIP_OKAY;
528 }
529 
530 /** restore LP solution values in row */
531 static
533  SCIP_ROW* row, /**< LP column */
534  BMS_BLKMEM* blkmem, /**< block memory */
535  SCIP_Longint validlp, /**< number of lp for which restored values are valid */
536  SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */
537  SCIP_Bool infeasible /**< is the solution infeasible? */
538  )
539 {
540  SCIP_ROWSOLVALS* storedsolvals;
541 
542  assert(row != NULL);
543  assert(blkmem != NULL);
544 
545  /* if stored values are available, restore them */
546  storedsolvals = row->storedsolvals;
547  if( storedsolvals != NULL )
548  {
549  if ( infeasible )
550  row->dualfarkas = storedsolvals->dualsol;
551  else
552  row->dualsol = storedsolvals->dualsol;
553  row->activity = storedsolvals->activity;
554  row->validactivitylp = validlp;
555  row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
556  }
557  /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
558  * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
559  */
560  else
561  {
562  row->dualsol = 0.0;
563  row->dualfarkas = 0.0;
564  row->activity = SCIP_INVALID;
565  row->validactivitylp = -1;
566  row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
567  }
568 
569  /* free memory */
570  if( freebuffer )
571  {
572  BMSfreeBlockMemoryNull(blkmem, &row->storedsolvals);
573  assert(row->storedsolvals == NULL);
574  }
575 
576  return SCIP_OKAY;
577 }
578 
579 /** ensures, that column array of row can store at least num entries */
581  SCIP_ROW* row, /**< LP row */
582  BMS_BLKMEM* blkmem, /**< block memory */
583  SCIP_SET* set, /**< global SCIP settings */
584  int num /**< minimum number of entries to store */
585  )
586 {
587  assert(row != NULL);
588  assert(row->len <= row->size);
589 
590  if( num > row->size )
591  {
592  int newsize;
593 
594  newsize = SCIPsetCalcMemGrowSize(set, num);
595  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
596  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
597  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
598  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
599  row->size = newsize;
600  }
601  assert(num <= row->size);
602 
603  return SCIP_OKAY;
604 }
605 
606 
607 #if 0 /* enable this to check the sortings within rows (for debugging, very slow!) */
608 static SCIP_Bool msgdisp_checkrow = FALSE;
609 
610 static
611 void checkRow(
612  SCIP_ROW* row
613  )
614 {
615  int i;
616 
617  if( !msgdisp_checkrow )
618  {
619  printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
620  msgdisp_checkrow = TRUE;
621  }
622 
623  /* validate sorting of LP part of row */
624  if( row->lpcolssorted && row->nlpcols > 0)
625  {
626  assert(row->cols_index[0] == row->cols[0]->index);
627  for( i = 1; i < row->nlpcols; ++i )
628  {
629  assert(row->cols_index[i] == row->cols[i]->index);
630  assert(row->cols_index[i] >= row->cols_index[i-1]);
631  }
632  }
633 
634  /* validate sorting of non-LP part of row */
635  if( row->nonlpcolssorted && row->len > row->nlpcols )
636  {
637  assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
638  for( i = row->nlpcols + 1; i < row->len; ++i )
639  {
640  assert(row->cols_index[i] == row->cols[i]->index);
641  assert(row->cols_index[i] >= row->cols_index[i-1]);
642  }
643  }
644 }
645 #else
646 #define checkRow(row) /**/
647 #endif
648 
649 #if 0 /* enable this to check norms of rows (for debugging, very slow!) */
650 static
651 void checkRowSqrnorm(
652  SCIP_ROW* row
653  )
654 {
655  SCIP_COL** cols;
656  SCIP_Real sqrnorm;
657  int c;
658 
659  cols = row->cols;
660  assert(cols != NULL || row->len == 0);
661 
662  sqrnorm = 0.0;
663 
664  for( c = row->len - 1; c >= 0; --c )
665  {
666  if( cols[c]->lppos >= 0 )
667  sqrnorm += SQR(row->vals[c]);
668  }
669 
670  assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
671 }
672 
673 static
674 void checkRowSumnorm(
675  SCIP_ROW* row
676  )
677 {
678  SCIP_COL** cols;
679  SCIP_Real sumnorm;
680  int c;
681 
682  cols = row->cols;
683  assert(cols != NULL || row->len == 0);
684 
685  sumnorm = 0.0;
686 
687  for( c = row->len - 1; c >= 0; --c )
688  {
689  if( cols[c]->lppos >= 0 )
690  sumnorm += REALABS(row->vals[c]);
691  }
692 
693  assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
694 }
695 
696 static
697 void checkRowObjprod(
698  SCIP_ROW* row
699  )
700 {
701  SCIP_COL** cols;
702  SCIP_Real objprod;
703  int c;
704 
705  cols = row->cols;
706  assert(cols != NULL || row->len == 0);
707 
708  objprod = 0.0;
709 
710  for( c = row->len - 1; c >= 0; --c )
711  {
712  if( cols[c]->lppos >= 0 )
713  objprod += row->vals[c] * cols[c]->unchangedobj;
714  }
715 
716  assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
717 }
718 #else
719 #define checkRowSqrnorm(row) /**/
720 #define checkRowSumnorm(row) /**/
721 #define checkRowObjprod(row) /**/
722 #endif
723 
724 /*
725  * Local methods for pseudo and loose objective values
726  */
727 
728 /* recompute the loose objective value from scratch, if it was marked to be unreliable before */
729 static
731  SCIP_LP* lp, /**< current LP data */
732  SCIP_SET* set, /**< global SCIP settings */
733  SCIP_PROB* prob /**< problem data */
734  )
735 {
736  SCIP_VAR** vars;
737  SCIP_Real obj;
738  int nvars;
739  int v;
740 
741  assert(lp != NULL);
742  assert(set != NULL);
743  assert(prob != NULL);
744  assert(!lp->looseobjvalid);
745 
746  vars = prob->vars;
747  nvars = prob->nvars;
748  lp->looseobjval = 0.0;
749 
750  /* iterate over all variables in the problem */
751  for( v = 0; v < nvars; ++v )
752  {
753  if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
754  {
755  obj = SCIPvarGetObj(vars[v]);
756 
757  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
758  if( SCIPsetIsPositive(set, obj) && !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
759  lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
760  else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
761  lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
762  }
763  }
764 
765  /* the recomputed value is reliable */
766  lp->rellooseobjval = lp->looseobjval;
767  lp->looseobjvalid = TRUE;
768 }
769 
770 /* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
771 static
773  SCIP_LP* lp, /**< current LP data */
774  SCIP_SET* set, /**< global SCIP settings */
775  SCIP_PROB* prob /**< problem data */
776  )
777 {
778  SCIP_VAR** vars;
779  int nvars;
780  int v;
781 
782  assert(lp != NULL);
783  assert(set != NULL);
784  assert(prob != NULL);
785  assert(!lp->pseudoobjvalid);
786 
787  vars = prob->vars;
788  nvars = prob->nvars;
789  lp->pseudoobjval = 0.0;
790 
791  /* iterate over all variables in the problem */
792  for( v = 0; v < nvars; ++v )
793  {
794  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
795  if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
796  !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
797  {
798  lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
799  }
800  else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
801  !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
802  {
803  lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
804  }
805  }
806 
807  /* the recomputed value is reliable */
808  lp->relpseudoobjval = lp->pseudoobjval;
809  lp->pseudoobjvalid = TRUE;
810 }
811 
812 /* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
813 static
815  SCIP_LP* lp, /**< current LP data */
816  SCIP_SET* set, /**< global SCIP settings */
817  SCIP_PROB* prob /**< problem data */
818  )
819 {
820  SCIP_VAR** vars;
821  int nvars;
822  int v;
823 
824  assert(lp != NULL);
825  assert(set != NULL);
826  assert(prob != NULL);
827  assert(!lp->glbpseudoobjvalid);
828 
829  vars = prob->vars;
830  nvars = prob->nvars;
831  lp->glbpseudoobjval = 0.0;
832 
833  /* iterate over all variables in the problem */
834  for( v = 0; v < nvars; ++v )
835  {
836  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
837  if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
838  !SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
839  {
840  lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
841  }
842  else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
843  !SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
844  {
845  lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
846  }
847  }
848 
849  /* the recomputed value is reliable */
851  lp->glbpseudoobjvalid = TRUE;
852 }
853 
854 /** gets finite part of objective value of current LP that results from LOOSE variables only */
855 static
857  SCIP_LP* lp, /**< current LP data */
858  SCIP_SET* set, /**< global SCIP settings */
859  SCIP_PROB* prob /**< problem data */
860  )
861 {
862  assert(lp != NULL);
863  assert(set != NULL);
864  assert(prob != NULL);
865  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
866  assert(lp->flushed);
867  assert(lp->looseobjvalinf == 0);
868 
869  /* recalculate the loose objective value, if needed */
870  if( !lp->looseobjvalid )
871  recomputeLooseObjectiveValue(lp, set, prob);
872 
873  return lp->looseobjval;
874 }
875 
876 /** gets finite part of pseudo objective value of current LP */
877 static
879  SCIP_LP* lp, /**< current LP data */
880  SCIP_SET* set, /**< global SCIP settings */
881  SCIP_PROB* prob /**< problem data */
882  )
883 {
884  assert(lp != NULL);
885  assert(set != NULL);
886  assert(prob != NULL);
887 
888  /* recalculate the pseudo objective value, if needed */
889  if( !lp->pseudoobjvalid )
890  recomputePseudoObjectiveValue(lp, set, prob);
891 
892  return lp->pseudoobjval;
893 }
894 
895 /*
896  * Sorting and searching rows and columns
897  */
898 
899 
900 /** comparison method for sorting rows by non-decreasing index */
902 {
903  assert(elem1 != NULL);
904  assert(elem2 != NULL);
905 
906  if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
907  return -1;
908  else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
909  return +1;
910  else
911  {
912  assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
913  return 0;
914  }
915 }
916 
917 
918 /** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
919 static
921  SCIP_COL* col /**< column to be sorted */
922  )
923 {
924  int i;
925 
926  assert(col != NULL);
927 
928  /* check, if column is already sorted in the LP part */
929  if( col->lprowssorted )
930  return;
931 
932  /* sort coefficients */
933  SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
934 
935  /* update links */
936  for( i = 0; i < col->nlprows; ++i )
937  {
938  if( col->linkpos[i] >= 0 )
939  {
940  assert(col->rows[i]->cols[col->linkpos[i]] == col);
941  assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
942  col->rows[i]->linkpos[col->linkpos[i]] = i;
943  }
944  }
945 
946  col->lprowssorted = TRUE;
947 }
948 
949 /** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
950  * ones
951  */
952 static
954  SCIP_COL* col /**< column to be sorted */
955  )
956 {
957  int i;
958 
959  assert(col != NULL);
960 
961  /* check, if column is already sorted in the non-LP part */
962  if( col->nonlprowssorted )
963  return;
964 
965  /* sort coefficients */
966  SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
967 
968  /* update links */
969  for( i = col->nlprows; i < col->len; ++i )
970  {
971  if( col->linkpos[i] >= 0 )
972  {
973  assert(col->rows[i]->cols[col->linkpos[i]] == col);
974  assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
975  col->rows[i]->linkpos[col->linkpos[i]] = i;
976  }
977  }
978 
979  col->nonlprowssorted = TRUE;
980 }
981 
982 /** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
983 static
985  SCIP_ROW* row /**< row to be sorted */
986  )
987 {
988  int i;
989 
990  assert(row != NULL);
991 
992  /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
993  if( row->lpcolssorted || row->delaysort )
994  return;
995 
996  /* sort coefficients */
997  SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
998 
999  /* update links */
1000  for( i = 0; i < row->nlpcols; ++i )
1001  {
1002  if( row->linkpos[i] >= 0 )
1003  {
1004  assert(row->cols[i]->rows[row->linkpos[i]] == row);
1005  assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1006  row->cols[i]->linkpos[row->linkpos[i]] = i;
1007  }
1008  }
1009 
1010  row->lpcolssorted = TRUE;
1011 }
1012 
1013 /** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1014  * higher ones
1015  */
1016 static
1018  SCIP_ROW* row /**< row to be sorted */
1019  )
1020 {
1021  int i;
1022 
1023  assert(row != NULL);
1024 
1025  checkRow(row);
1026 
1027  /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1028  if( row->nonlpcolssorted || row->delaysort )
1029  return;
1030 
1031  /* sort coefficients */
1032  SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1033 
1034  /* update links */
1035  for( i = row->nlpcols; i < row->len; ++i )
1036  {
1037  if( row->linkpos[i] >= 0 )
1038  {
1039  assert(row->cols[i]->rows[row->linkpos[i]] == row);
1040  assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1041  row->cols[i]->linkpos[row->linkpos[i]] = i;
1042  }
1043  }
1044 
1045  checkRow(row);
1046 
1047  row->nonlpcolssorted = TRUE;
1048 }
1049 
1050 /** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1051 static
1053  SCIP_COL* col, /**< column to be searched in */
1054  const SCIP_ROW* row, /**< coefficient to be searched for */
1055  int minpos, /**< first position of search range */
1056  int maxpos /**< last position of search range */
1057  )
1058 {
1059  int pos;
1060  int idx;
1061  int searchidx;
1062 
1063  assert(col != NULL);
1064  assert(row != NULL);
1065 
1066  /* binary search */
1067  searchidx = row->index;
1068  while(minpos <= maxpos)
1069  {
1070  pos = (minpos + maxpos)/2;
1071  assert(0 <= pos && pos < col->len);
1072  assert(col->rows[pos] != NULL);
1073  assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1074  idx = col->rows[pos]->index;
1075  if( searchidx == idx )
1076  return pos;
1077  else if( searchidx < idx )
1078  maxpos = pos-1;
1079  else
1080  minpos = pos+1;
1081  }
1082 
1083  return -1;
1084 }
1085 
1086 /** searches coefficient in column, returns position in col vector or -1 if not found */
1087 static
1089  SCIP_COL* col, /**< column to be searched in */
1090  const SCIP_ROW* row /**< coefficient to be searched for */
1091  )
1092 {
1093  int pos;
1094 
1095  assert(col != NULL);
1096  assert(row != NULL);
1097 
1098  pos = -1;
1099 
1100  /* search in the linked LP rows */
1101  if( row->lppos >= 0 )
1102  {
1103  /* column has to be sorted, such that binary search works */
1104  colSortLP(col);
1105  assert(col->lprowssorted);
1106 
1107  pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1108  if( pos >= 0 )
1109  return pos;
1110  }
1111 
1112  /* search in the non-LP/unlinked rows */
1113  if( row->lppos == -1 || col->nunlinked > 0 )
1114  {
1115  /* column has to be sorted, such that binary search works */
1116  colSortNonLP(col);
1117  assert(col->nonlprowssorted);
1118 
1119  pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1120  }
1121 
1122  return pos;
1123 }
1124 
1125 /** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1126 static
1128  SCIP_ROW* row, /**< row to be searched in */
1129  const SCIP_COL* col, /**< coefficient to be searched for */
1130  int minpos, /**< first position of search range */
1131  int maxpos /**< last position of search range */
1132  )
1133 {
1134  int pos;
1135  int idx;
1136  int searchidx;
1137 
1138  assert(row != NULL);
1139  assert(col != NULL);
1140 
1141  /* binary search */
1142  searchidx = col->index;
1143  while(minpos <= maxpos)
1144  {
1145  pos = (minpos + maxpos)/2;
1146  assert(0 <= pos && pos < row->len);
1147  assert(row->cols[pos] != NULL);
1148  assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1149  assert(row->cols_index[pos] == row->cols[pos]->index);
1150  idx = row->cols_index[pos];
1151  if( searchidx == idx )
1152  return pos;
1153  else if( searchidx < idx )
1154  maxpos = pos-1;
1155  else
1156  minpos = pos+1;
1157  }
1158 
1159  return -1;
1160 }
1161 
1162 /** searches coefficient in row, returns position in row vector or -1 if not found;
1163  * if the sorting of the row is delayed, returns -1
1164  */
1165 static
1167  SCIP_ROW* row, /**< row to be searched in */
1168  const SCIP_COL* col /**< coefficient to be searched for */
1169  )
1170 {
1171  int pos;
1172 
1173  assert(row != NULL);
1174  assert(col != NULL);
1175 
1176  if( row->delaysort )
1177  return -1;
1178 
1179  pos = -1;
1180 
1181  /* search in the linked LP columns */
1182  if( col->lppos >= 0 )
1183  {
1184  /* row has to be sorted, such that binary search works */
1185  rowSortLP(row);
1186  assert(row->lpcolssorted);
1187 
1188  pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1189  }
1190 
1191  /* search in the non-LP/unlinked columns */
1192  if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1193  {
1194  /* row has to be sorted, such that binary search works */
1195  rowSortNonLP(row);
1196  assert(row->nonlpcolssorted);
1197 
1198  pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1199  }
1200 
1201 #ifndef NDEBUG
1202  /* validate result */
1203  assert(-1 <= pos && pos < row->len);
1204  if( pos >= 0 )
1205  assert(row->cols[pos] == col);
1206  else
1207  {
1208  int i;
1209  for( i = 0; i < row->len; ++i )
1210  assert(row->cols[i] != col);
1211  }
1212 #endif
1213 
1214  return pos;
1215 }
1216 
1217 /** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1218 static
1220  SCIP_COL* col, /**< LP column */
1221  int oldpos, /**< old position of coefficient */
1222  int newpos /**< new position of coefficient */
1223  )
1224 {
1225  assert(col != NULL);
1226  assert(0 <= oldpos && oldpos < col->len);
1227  assert(0 <= newpos && newpos < col->len);
1228  assert(col->rows[oldpos] != NULL);
1229 
1230  if( oldpos == newpos )
1231  return;
1232 
1233  col->rows[newpos] = col->rows[oldpos];
1234  col->vals[newpos] = col->vals[oldpos];
1235  col->linkpos[newpos] = col->linkpos[oldpos];
1236 
1237  /* update link position in row */
1238  if( col->linkpos[newpos] >= 0 )
1239  {
1240  assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1241  assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1242 
1243  col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1244  }
1245 
1246  /* update sorted flags */
1247  if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1248  col->lprowssorted = FALSE;
1249  else
1250  col->nonlprowssorted = FALSE;
1251 }
1252 
1253 /** swaps two coefficients in a column, and updates all corresponding data structures */
1254 static
1256  SCIP_COL* col, /**< LP column */
1257  int pos1, /**< position of first coefficient */
1258  int pos2 /**< position of second coefficient */
1259  )
1260 {
1261  SCIP_ROW* tmprow;
1262  SCIP_Real tmpval;
1263  int tmplinkpos;
1264 
1265  assert(col != NULL);
1266  assert(0 <= pos1 && pos1 < col->len);
1267  assert(0 <= pos2 && pos2 < col->len);
1268  assert(col->rows[pos1] != NULL);
1269 
1270  if( pos1 == pos2 )
1271  return;
1272 
1273  /* swap coefficients */
1274  tmprow = col->rows[pos2];
1275  tmpval = col->vals[pos2];
1276  tmplinkpos = col->linkpos[pos2];
1277 
1278  col->rows[pos2] = col->rows[pos1];
1279  col->vals[pos2] = col->vals[pos1];
1280  col->linkpos[pos2] = col->linkpos[pos1];
1281 
1282  col->rows[pos1] = tmprow;
1283  col->vals[pos1] = tmpval;
1284  col->linkpos[pos1] = tmplinkpos;
1285 
1286  /* update link position in rows */
1287  if( col->linkpos[pos1] >= 0 )
1288  {
1289  assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1290  assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1291 
1292  col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1293  }
1294  if( col->linkpos[pos2] >= 0 )
1295  {
1296  assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1297  assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1298 
1299  col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1300  }
1301 
1302  /* update sorted flags */
1303  if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1304  col->lprowssorted = FALSE;
1305  else
1306  col->nonlprowssorted = FALSE;
1307  if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1308  col->lprowssorted = FALSE;
1309  else
1310  col->nonlprowssorted = FALSE;
1311 }
1312 
1313 /** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1314 static
1316  SCIP_ROW* row, /**< LP row */
1317  int oldpos, /**< old position of coefficient */
1318  int newpos /**< new position of coefficient */
1319  )
1320 {
1321  assert(row != NULL);
1322  assert(0 <= oldpos && oldpos < row->len);
1323  assert(0 <= newpos && newpos < row->len);
1324  assert(row->cols[oldpos] != NULL);
1325 
1326  if( oldpos == newpos )
1327  return;
1328 
1329  row->cols[newpos] = row->cols[oldpos];
1330  row->cols_index[newpos] = row->cols_index[oldpos];
1331  row->vals[newpos] = row->vals[oldpos];
1332  row->linkpos[newpos] = row->linkpos[oldpos];
1333 
1334  /* update link position in column */
1335  if( row->linkpos[newpos] >= 0 )
1336  {
1337  assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1338  assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1339 
1340  row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1341  }
1342 
1343  /* update sorted flags */
1344  if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1345  row->lpcolssorted = FALSE;
1346  else
1347  row->nonlpcolssorted = FALSE;
1348 }
1349 
1350 /** swaps two coefficients in a row, and updates all corresponding data structures */
1351 static
1353  SCIP_ROW* row, /**< LP row */
1354  int pos1, /**< position of first coefficient */
1355  int pos2 /**< position of second coefficient */
1356  )
1357 {
1358  SCIP_COL* tmpcol;
1359  SCIP_Real tmpval;
1360  int tmpindex;
1361  int tmplinkpos;
1362 
1363  assert(row != NULL);
1364  assert(0 <= pos1 && pos1 < row->len);
1365  assert(0 <= pos2 && pos2 < row->len);
1366  assert(row->cols[pos1] != NULL);
1367  assert(row->cols[pos1]->index == row->cols_index[pos1]);
1368 
1369  if( pos1 == pos2 )
1370  return;
1371 
1372  /* swap coefficients */
1373  tmpcol = row->cols[pos2];
1374  tmpindex = row->cols_index[pos2];
1375  tmpval = row->vals[pos2];
1376  tmplinkpos = row->linkpos[pos2];
1377 
1378  row->cols[pos2] = row->cols[pos1];
1379  row->cols_index[pos2] = row->cols_index[pos1];
1380  row->vals[pos2] = row->vals[pos1];
1381  row->linkpos[pos2] = row->linkpos[pos1];
1382 
1383  row->cols[pos1] = tmpcol;
1384  row->cols_index[pos1] = tmpindex;
1385  row->vals[pos1] = tmpval;
1386  row->linkpos[pos1] = tmplinkpos;
1387 
1388  /* update link position in columns */
1389  if( row->linkpos[pos1] >= 0 )
1390  {
1391  assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1392  assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1393 
1394  row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1395  }
1396  if( row->linkpos[pos2] >= 0 )
1397  {
1398  assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1399  assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1400 
1401  row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1402  }
1403 
1404  /* update sorted flags */
1405  if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1406  row->lpcolssorted = FALSE;
1407  else
1408  row->nonlpcolssorted = FALSE;
1409  if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1410  row->lpcolssorted = FALSE;
1411  else
1412  row->nonlpcolssorted = FALSE;
1413 }
1414 
1415 /** issues a ROWCOEFCHANGED event on the given row */
1416 static
1418  SCIP_ROW* row, /**< row which coefficient has changed */
1419  BMS_BLKMEM* blkmem, /**< block memory */
1420  SCIP_SET* set, /**< global SCIP settings */
1421  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1422  SCIP_COL* col, /**< the column which coefficient has changed */
1423  SCIP_Real oldval, /**< old value of the coefficient */
1424  SCIP_Real newval /**< new value of the coefficient */
1425  )
1426 {
1427  assert(row != NULL);
1428  assert(row->eventfilter != NULL);
1429  assert(col != NULL);
1430 
1431  /* check, if the row is being tracked for coefficient changes
1432  * if so, issue ROWCOEFCHANGED event
1433  */
1434  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1435  {
1436  SCIP_EVENT* event;
1437 
1438  SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1439  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1440  }
1441 
1442  return SCIP_OKAY;
1443 }
1444 
1445 /** issues a ROWCONSTCHANGED event on the given row */
1446 static
1448  SCIP_ROW* row, /**< row which coefficient has changed */
1449  BMS_BLKMEM* blkmem, /**< block memory */
1450  SCIP_SET* set, /**< global SCIP settings */
1451  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1452  SCIP_Real oldval, /**< old value of the constant */
1453  SCIP_Real newval /**< new value of the constant */
1454  )
1455 {
1456  assert(row != NULL);
1457  assert(row->eventfilter != NULL);
1458 
1459  /* check, if the row is being tracked for coefficient changes
1460  * if so, issue ROWCONSTCHANGED event
1461  */
1462  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCONSTCHANGED) != 0) )
1463  {
1464  SCIP_EVENT* event;
1465 
1466  SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1467  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1468  }
1469 
1470  return SCIP_OKAY;
1471 }
1472 
1473 /** issues a ROWSIDECHANGED event on the given row */
1474 static
1476  SCIP_ROW* row, /**< row which coefficient has changed */
1477  BMS_BLKMEM* blkmem, /**< block memory */
1478  SCIP_SET* set, /**< global SCIP settings */
1479  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1480  SCIP_SIDETYPE side, /**< the side that has changed */
1481  SCIP_Real oldval, /**< old value of side */
1482  SCIP_Real newval /**< new value of side */
1483  )
1484 {
1485  assert(row != NULL);
1486  assert(row->eventfilter != NULL);
1487 
1488  /* check, if the row is being tracked for coefficient changes
1489  * if so, issue ROWSIDECHANGED event
1490  */
1491  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED) != 0) )
1492  {
1493  SCIP_EVENT* event;
1494 
1495  SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1496  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1497  }
1498 
1499  return SCIP_OKAY;
1500 }
1501 
1502 #if 0 /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */
1503 
1504 #ifdef NDEBUG
1505 #define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1506 #else
1507 #define ASSERT(x) assert(x)
1508 #endif
1509 
1510 static SCIP_Bool msgdisp_checklinks = FALSE;
1511 
1512 
1513 static
1514 void checkLinks(
1515  SCIP_LP* lp /**< current LP data */
1516  )
1517 {
1518  SCIP_COL* col;
1519  SCIP_ROW* row;
1520  int i;
1521  int j;
1522 
1523  ASSERT(lp != NULL);
1524 
1525  if( !msgdisp_checklinks )
1526  {
1527  printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1528  msgdisp_checklinks = TRUE;
1529  }
1530 
1531  for( i = 0; i < lp->ncols; ++i )
1532  {
1533  col = lp->cols[i];
1534  ASSERT(col != NULL);
1535  ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1536  ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1537  ASSERT(col->nlprows <= col->len);
1538  ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1539 
1540  for( j = 0; j < col->len; ++j )
1541  {
1542  row = col->rows[j];
1543  ASSERT(row != NULL);
1544  ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1545  ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1546  ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1547  ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1548  }
1549  }
1550 
1551  for( i = 0; i < lp->nrows; ++i )
1552  {
1553  row = lp->rows[i];
1554  ASSERT(row != NULL);
1555  ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1556  ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1557  ASSERT(row->nlpcols <= row->len);
1558  ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1559 
1560  for( j = 0; j < row->len; ++j )
1561  {
1562  col = row->cols[j];
1563  ASSERT(col != NULL);
1564  ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1565  ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1566  ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1567  ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1568  }
1569  }
1570 }
1571 
1572 #undef ASSERT
1573 
1574 #else
1575 #define checkLinks(lp) /**/
1576 #endif
1577 
1578 /*
1579  * Changing announcements
1580  */
1581 
1582 /** announces, that the given coefficient in the constraint matrix changed */
1583 static
1585  SCIP_ROW* row, /**< LP row */
1586  SCIP_COL* col, /**< LP col */
1587  SCIP_LP* lp /**< current LP data */
1588  )
1589 {
1590  assert(row != NULL);
1591  assert(col != NULL);
1592  assert(lp != NULL);
1593 
1594  if( row->lpipos >= 0 && col->lpipos >= 0 )
1595  {
1596  assert(row->lpipos < lp->nlpirows);
1597  assert(col->lpipos < lp->nlpicols);
1598 
1599  /* we have to remember the change only in the row or in the column,
1600  * because the readdition of one vector would change the other automatically.
1601  */
1602  if( row->lpipos >= lp->lpifirstchgrow )
1603  row->coefchanged = TRUE;
1604  else if( col->lpipos >= lp->lpifirstchgcol )
1605  col->coefchanged = TRUE;
1606  else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1607  {
1608  row->coefchanged = TRUE;
1609  lp->lpifirstchgrow = row->lpipos;
1610  }
1611  else
1612  {
1613  col->coefchanged = TRUE;
1614  lp->lpifirstchgcol = col->lpipos;
1615  }
1616 
1617  /* mark the current LP unflushed */
1618  lp->flushed = FALSE;
1619  }
1620 
1622  row->minactivity = SCIP_INVALID;
1623  row->maxactivity = SCIP_INVALID;
1624  row->validpsactivitydomchg = -1;
1625  row->validactivitybdsdomchg = -1;
1626 }
1627 
1628 
1629 
1630 /*
1631  * local column changing methods
1632  */
1633 
1634 /* forward declaration for colAddCoef() */
1635 static
1637  SCIP_ROW* row, /**< LP row */
1638  BMS_BLKMEM* blkmem, /**< block memory */
1639  SCIP_SET* set, /**< global SCIP settings */
1640  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1641  SCIP_LP* lp, /**< current LP data */
1642  SCIP_COL* col, /**< LP column */
1643  SCIP_Real val, /**< value of coefficient */
1644  int linkpos /**< position of row in the column's row array, or -1 */
1645  );
1646 
1647 /** adds a previously non existing coefficient to an LP column */
1648 static
1650  SCIP_COL* col, /**< LP column */
1651  BMS_BLKMEM* blkmem, /**< block memory */
1652  SCIP_SET* set, /**< global SCIP settings */
1653  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1654  SCIP_LP* lp, /**< current LP data */
1655  SCIP_ROW* row, /**< LP row */
1656  SCIP_Real val, /**< value of coefficient */
1657  int linkpos /**< position of column in the row's col array, or -1 */
1658  )
1659 {
1660  int pos;
1661 
1662  assert(blkmem != NULL);
1663  assert(col != NULL);
1664  assert(col->nlprows <= col->len);
1665  assert(col->var != NULL);
1666  assert(row != NULL);
1667  assert(!SCIPsetIsZero(set, val));
1668  /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1669 
1670  SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1671  assert(col->rows != NULL);
1672  assert(col->vals != NULL);
1673  assert(col->linkpos != NULL);
1674 
1675  pos = col->len;
1676  col->len++;
1677 
1678  /* 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
1679  * part of the column's arrays
1680  */
1681  if( row->lppos >= 0 && linkpos >= 0 )
1682  {
1683  /* move the first non-LP/not linked row to the end */
1684  if( col->nlprows < pos )
1685  {
1686  colMoveCoef(col, col->nlprows, pos);
1687  pos = col->nlprows;
1688  }
1689  col->nlprows++;
1690  }
1691 
1692  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1693  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1694 
1695  /* insert the row at the correct position and update the links */
1696  col->rows[pos] = row;
1697  col->vals[pos] = val;
1698  col->linkpos[pos] = linkpos;
1699  if( linkpos == -1 )
1700  {
1701  col->nunlinked++;
1702 
1703  /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1704  * of the row is not complete
1705  */
1706  if( col->lppos >= 0 )
1707  {
1708  /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1709  * has to be updated
1710  */
1711  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1712  if( row->lppos >= 0 )
1713  pos = col->nlprows-1;
1714  linkpos = col->linkpos[pos];
1715 
1716  assert(0 <= linkpos && linkpos < row->len);
1717  assert(row->cols[linkpos] == col);
1718  assert(col->rows[pos] == row);
1719  assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1720  assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1721  }
1722  }
1723  else
1724  {
1725  assert(row->linkpos[linkpos] == -1);
1726  assert(row->nunlinked > 0);
1727  row->linkpos[linkpos] = pos;
1728  row->nunlinked--;
1729 
1730  /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1731  * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1732  */
1733  if( col->lppos >= 0 )
1734  {
1735  row->nlpcols++;
1736  rowSwapCoefs(row, linkpos, row->nlpcols-1);
1737 
1738  /* if no swap was necessary, mark nonlpcols to be unsorted */
1739  if( linkpos == row->nlpcols-1 )
1740  row->lpcolssorted = FALSE;
1741  }
1742  }
1743 
1744  /* update the sorted flags */
1745  if( row->lppos >= 0 && linkpos >= 0 )
1746  {
1747  assert(col->nlprows >= 1);
1748  assert(col->rows[col->nlprows-1] == row);
1749  if( col->nlprows > 1 )
1750  col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1751  }
1752  else
1753  {
1754  assert(col->len - col->nlprows >= 1);
1755  assert(col->rows[col->len-1] == row);
1756  if( col->len - col->nlprows > 1 )
1757  col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1758  }
1759 
1760  coefChanged(row, col, lp);
1761 
1762  SCIPdebugMessage("added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1763  val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1764 
1765  return SCIP_OKAY;
1766 }
1767 
1768 /** deletes coefficient at given position from column */
1769 static
1771  SCIP_COL* col, /**< column to be changed */
1772  SCIP_SET* set, /**< global SCIP settings */
1773  SCIP_LP* lp, /**< current LP data */
1774  int pos /**< position in column vector to delete */
1775  )
1776 {
1777  SCIP_ROW* row;
1778 
1779  assert(col != NULL);
1780  assert(col->var != NULL);
1781  assert(set != NULL);
1782  assert(0 <= pos && pos < col->len);
1783  assert(col->rows[pos] != NULL);
1784  assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1785  assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1786 
1787  row = col->rows[pos];
1788  assert((row->lppos >= 0) == (pos < col->nlprows));
1789 
1790  /*debugMessage("deleting coefficient %g * <%s> at position %d from column <%s>\n",
1791  col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1792 
1793  if( col->linkpos[pos] == -1 )
1794  col->nunlinked--;
1795 
1796  /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1797  if( pos < col->nlprows )
1798  {
1799  colMoveCoef(col, col->nlprows-1, pos);
1800  col->nlprows--;
1801  pos = col->nlprows;
1802  }
1803 
1804  /* move last coefficient to position of empty slot */
1805  colMoveCoef(col, col->len-1, pos);
1806  col->len--;
1807 
1808  coefChanged(row, col, lp);
1809 
1810  return SCIP_OKAY;
1811 }
1812 
1813 /** changes a coefficient at given position of an LP column */
1814 static
1816  SCIP_COL* col, /**< LP column */
1817  SCIP_SET* set, /**< global SCIP settings */
1818  SCIP_LP* lp, /**< current LP data */
1819  int pos, /**< position in column vector to change */
1820  SCIP_Real val /**< value of coefficient */
1821  )
1822 {
1823  assert(col != NULL);
1824  assert(col->var != NULL);
1825  assert(0 <= pos && pos < col->len);
1826  assert(col->rows[pos] != NULL);
1827  assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1828 
1829  /*debugMessage("changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1830  col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1831 
1832  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1833  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1834 
1835  if( SCIPsetIsZero(set, val) )
1836  {
1837  /* delete existing coefficient */
1838  SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1839  }
1840  else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1841  {
1842  /* change existing coefficient */
1843  col->vals[pos] = val;
1844  coefChanged(col->rows[pos], col, lp);
1845  }
1846 
1847  return SCIP_OKAY;
1848 }
1849 
1850 
1851 
1852 
1853 /*
1854  * local row changing methods
1855  */
1856 
1857 /** update row norms after addition of coefficient */
1858 static
1860  SCIP_ROW* row, /**< LP row */
1861  SCIP_SET* set, /**< global SCIP settings */
1862  SCIP_COL* col, /**< column of added coefficient */
1863  SCIP_Real val, /**< value of added coefficient */
1864  SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */
1865  )
1866 {
1867  SCIP_Real absval;
1868 
1869  assert(row != NULL);
1870  assert(row->nummaxval >= 0);
1871  assert(row->numminval >= 0);
1872  assert(set != NULL);
1873  assert(col != NULL);
1874 
1875  absval = REALABS(val);
1876  assert(!SCIPsetIsZero(set, absval));
1877 
1878  /* Euclidean norm, sum norm, and objective function scalar product only take into accout LP columns */
1879  if( col->lppos >= 0 )
1880  {
1881  /* update squared Euclidean norm and sum norm */
1882  row->sqrnorm += SQR(absval);
1883  row->sumnorm += absval;
1884 
1885  /* update objective function scalar product */
1886  row->objprod += val * col->unchangedobj;
1887  }
1888 
1889  if( updateidxvals )
1890  {
1891  /* update min/maxidx */
1892  row->minidx = MIN(row->minidx, col->index);
1893  row->maxidx = MAX(row->maxidx, col->index);
1894 
1895  /* update maximal and minimal non-zero value */
1896  if( row->nummaxval > 0 )
1897  {
1898  if( SCIPsetIsGT(set, absval, row->maxval) )
1899  {
1900  row->maxval = absval;
1901  row->nummaxval = 1;
1902  }
1903  else if( SCIPsetIsGE(set, absval, row->maxval) )
1904  row->nummaxval++;
1905  }
1906  if( row->numminval > 0 )
1907  {
1908  if( SCIPsetIsLT(set, absval, row->minval) )
1909  {
1910  row->minval = absval;
1911  row->numminval = 1;
1912  }
1913  else if( SCIPsetIsLE(set, absval, row->minval) )
1914  row->numminval++;
1915  }
1916  }
1917  else
1918  {
1919  assert(row->minidx <= col->index);
1920  assert(row->maxidx >= col->index);
1921  assert(row->numminval <= 0 || SCIPsetIsGE(set, absval, row->minval));
1922  assert(row->nummaxval <= 0 || SCIPsetIsLE(set, absval, row->maxval));
1923  }
1924 }
1925 
1926 /** update row norms after deletion of coefficient */
1927 static
1929  SCIP_ROW* row, /**< LP row */
1930  SCIP_SET* set, /**< global SCIP settings */
1931  SCIP_COL* col, /**< column of deleted coefficient */
1932  SCIP_Real val, /**< value of deleted coefficient */
1933  SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */
1934  SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */
1935  SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */
1936  )
1937 {
1938  SCIP_Real absval;
1939 
1940  assert(row != NULL);
1941  assert(row->nummaxval >= 0);
1942  assert(row->numminval >= 0);
1943  assert(set != NULL);
1944  assert(col != NULL);
1945 
1946  absval = REALABS(val);
1947  assert(!SCIPsetIsZero(set, absval));
1948  assert(row->nummaxval == 0 || SCIPsetIsGE(set, row->maxval, absval));
1949  assert(row->numminval == 0 || SCIPsetIsLE(set, row->minval, absval));
1950 
1951  /* update min/maxidx validity */
1952  if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
1953  row->validminmaxidx = FALSE;
1954 
1955  /* Euclidean norm, sum norm, and objective function scalar product only take into accout LP columns */
1956  if( forcenormupdate || col->lppos >= 0 )
1957  {
1958  /* update squared Euclidean norm and sum norm */
1959  row->sqrnorm -= SQR(absval);
1960  row->sqrnorm = MAX(row->sqrnorm, 0.0);
1961  row->sumnorm -= absval;
1962  row->sumnorm = MAX(row->sumnorm, 0.0);
1963 
1964  /* update objective function scalar product */
1965  row->objprod -= val * col->unchangedobj;
1966  }
1967 
1968  if( updateval )
1969  {
1970  /* update maximal and minimal non-zero value */
1971  if( row->nummaxval > 0 )
1972  {
1973  if( SCIPsetIsGE(set, absval, row->maxval) )
1974  row->nummaxval--;
1975  }
1976  if( row->numminval > 0 )
1977  {
1978  if( SCIPsetIsLE(set, absval, row->minval) )
1979  row->numminval--;
1980  }
1981  }
1982 }
1983 
1984 /** adds a previously non existing coefficient to an LP row */
1985 static
1987  SCIP_ROW* row, /**< LP row */
1988  BMS_BLKMEM* blkmem, /**< block memory */
1989  SCIP_SET* set, /**< global SCIP settings */
1990  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1991  SCIP_LP* lp, /**< current LP data */
1992  SCIP_COL* col, /**< LP column */
1993  SCIP_Real val, /**< value of coefficient */
1994  int linkpos /**< position of row in the column's row array, or -1 */
1995  )
1996 {
1997  int pos;
1998 
1999  assert(row != NULL);
2000  assert(row->nlpcols <= row->len);
2001  assert(blkmem != NULL);
2002  assert(col != NULL);
2003  assert(col->var != NULL);
2004  assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2005  assert(!SCIPsetIsZero(set, val));
2006  /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2007 
2008  if( row->nlocks > 0 )
2009  {
2010  SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2011  return SCIP_INVALIDDATA;
2012  }
2013 
2014  SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2015  assert(row->cols != NULL);
2016  assert(row->vals != NULL);
2017 
2018  pos = row->len;
2019  row->len++;
2020 
2021  /* 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
2022  * part of the row's arrays
2023  */
2024  if( col->lppos >= 0 && linkpos >= 0 )
2025  {
2026  /* move the first non-LP/not linked column to the end */
2027  if( row->nlpcols < pos )
2028  {
2029  rowMoveCoef(row, row->nlpcols, pos);
2030  pos = row->nlpcols;
2031  }
2032  row->nlpcols++;
2033  }
2034 
2035  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2036  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2037 
2038  /* insert the column at the correct position and update the links */
2039  row->cols[pos] = col;
2040  row->cols_index[pos] = col->index;
2041  row->vals[pos] = val;
2042  row->linkpos[pos] = linkpos;
2043  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2044  if( linkpos == -1 )
2045  {
2046  row->nunlinked++;
2047 
2048  /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2049  * of the column is not complete
2050  */
2051  if( row->lppos >= 0 )
2052  {
2053  /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2054  * has to be updated
2055  */
2056  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2057  if( col->lppos >= 0 )
2058  pos = row->nlpcols-1;
2059  linkpos = row->linkpos[pos];
2060 
2061  assert(0 <= linkpos && linkpos < col->len);
2062  assert(col->rows[linkpos] == row);
2063  assert(row->cols[pos] == col);
2064  assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2065  assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2066  }
2067  }
2068  else
2069  {
2070  assert(col->linkpos[linkpos] == -1);
2071  assert(col->nunlinked > 0);
2072  col->linkpos[linkpos] = pos;
2073  col->nunlinked--;
2074 
2075  /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2076  * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2077  */
2078  if( row->lppos >= 0 )
2079  {
2080  col->nlprows++;
2081  colSwapCoefs(col, linkpos, col->nlprows-1);
2082 
2083  /* if no swap was necessary, mark lprows to be unsorted */
2084  if( linkpos == col->nlprows-1 )
2085  col->lprowssorted = FALSE;
2086  }
2087  }
2088 
2089  /* update the sorted flags */
2090  if( col->lppos >= 0 && linkpos >= 0 )
2091  {
2092  assert(row->nlpcols >= 1);
2093  assert(row->cols[row->nlpcols-1] == col);
2094  if( row->nlpcols > 1 )
2095  {
2096  assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2097  row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2098  }
2099  }
2100  else
2101  {
2102  assert(row->len - row->nlpcols >= 1);
2103  assert(row->cols[row->len-1] == col);
2104  if( row->len - row->nlpcols > 1 )
2105  {
2106  assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2107  row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2108  }
2109  }
2110 
2111  /* update row norm */
2112  rowAddNorms(row, set, col, val, TRUE);
2113 
2114  coefChanged(row, col, lp);
2115 
2116  SCIPdebugMessage("added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2117  val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2118 
2119  /* issue row coefficient changed event */
2120  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2121 
2122  return SCIP_OKAY;
2123 }
2124 
2125 /** deletes coefficient at given position from row */
2126 static
2128  SCIP_ROW* row, /**< row to be changed */
2129  BMS_BLKMEM* blkmem, /**< block memory */
2130  SCIP_SET* set, /**< global SCIP settings */
2131  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2132  SCIP_LP* lp, /**< current LP data */
2133  int pos /**< position in row vector to delete */
2134  )
2135 {
2136  SCIP_COL* col;
2137  SCIP_Real val;
2138 
2139  assert(row != NULL);
2140  assert(set != NULL);
2141  assert(0 <= pos && pos < row->len);
2142  assert(row->cols[pos] != NULL);
2143  assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2144 
2145  col = row->cols[pos];
2146  val = row->vals[pos];
2147  assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2148 
2149  /*debugMessage("deleting coefficient %g * <%s> at position %d from row <%s>\n",
2150  val, SCIPvarGetName(col->var), pos, row->name);*/
2151 
2152  if( row->nlocks > 0 )
2153  {
2154  SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2155  return SCIP_INVALIDDATA;
2156  }
2157 
2158  if( row->linkpos[pos] == -1 )
2159  row->nunlinked--;
2160 
2161  /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2162  if( pos < row->nlpcols )
2163  {
2164  rowMoveCoef(row, row->nlpcols-1, pos);
2165  assert(!row->lpcolssorted);
2166  row->nlpcols--;
2167  pos = row->nlpcols;
2168  }
2169 
2170  /* move last coefficient to position of empty slot */
2171  rowMoveCoef(row, row->len-1, pos);
2172  row->len--;
2173 
2174  /* update norms */
2175  rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2176 
2177  coefChanged(row, col, lp);
2178 
2179  /* issue row coefficient changed event */
2180  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2181 
2182  return SCIP_OKAY;
2183 }
2184 
2185 /** changes a coefficient at given position of an LP row */
2186 static
2188  SCIP_ROW* row, /**< LP row */
2189  BMS_BLKMEM* blkmem, /**< block memory */
2190  SCIP_SET* set, /**< global SCIP settings */
2191  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2192  SCIP_LP* lp, /**< current LP data */
2193  int pos, /**< position in row vector to change */
2194  SCIP_Real val /**< value of coefficient */
2195  )
2196 {
2197  SCIP_COL* col;
2198 
2199  assert(row != NULL);
2200  assert(0 <= pos && pos < row->len);
2201 
2202  /*debugMessage("changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2203  row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2204 
2205  if( row->nlocks > 0 )
2206  {
2207  SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2208  return SCIP_INVALIDDATA;
2209  }
2210 
2211  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2212  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2213  col = row->cols[pos];
2214  assert(row->cols[pos] != NULL);
2215 
2216  if( SCIPsetIsZero(set, val) )
2217  {
2218  /* delete existing coefficient */
2219  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2220  }
2221  else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2222  {
2223  SCIP_Real oldval;
2224 
2225  oldval = row->vals[pos];
2226 
2227  /* change existing coefficient */
2228  rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2229  row->vals[pos] = val;
2230  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2231  rowAddNorms(row, set, col, row->vals[pos], TRUE);
2232  coefChanged(row, col, lp);
2233 
2234  /* issue row coefficient changed event */
2235  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2236  }
2237 
2238  return SCIP_OKAY;
2239 }
2240 
2241 /** notifies LP row, that its sides were changed */
2242 static
2244  SCIP_ROW* row, /**< LP row */
2245  SCIP_SET* set, /**< global SCIP settings */
2246  SCIP_LP* lp, /**< current LP data */
2247  SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */
2248  )
2249 {
2250  assert(row != NULL);
2251  assert(lp != NULL);
2252 
2253  if( row->lpipos >= 0 )
2254  {
2255  /* insert row in the chgrows list (if not already there) */
2256  if( !row->lhschanged && !row->rhschanged )
2257  {
2258  SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2259  lp->chgrows[lp->nchgrows] = row;
2260  lp->nchgrows++;
2261  }
2262 
2263  /* mark side change in the row */
2264  switch( sidetype )
2265  {
2266  case SCIP_SIDETYPE_LEFT:
2267  row->lhschanged = TRUE;
2268  break;
2269  case SCIP_SIDETYPE_RIGHT:
2270  row->rhschanged = TRUE;
2271  break;
2272  default:
2273  SCIPerrorMessage("unknown row side type\n");
2274  SCIPABORT();
2275  return SCIP_INVALIDDATA; /*lint !e527*/
2276  }
2277 
2278  /* mark the current LP unflushed */
2279  lp->flushed = FALSE;
2280 
2281  assert(lp->nchgrows > 0);
2282  }
2283 
2284  return SCIP_OKAY;
2285 }
2286 
2287 
2288 
2289 
2290 /*
2291  * double linked coefficient matrix methods
2292  */
2293 
2294 /** insert column coefficients in corresponding rows */
2295 static
2297  SCIP_COL* col, /**< column data */
2298  BMS_BLKMEM* blkmem, /**< block memory */
2299  SCIP_SET* set, /**< global SCIP settings */
2300  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2301  SCIP_LP* lp /**< current LP data */
2302  )
2303 {
2304  int i;
2305 
2306  assert(col != NULL);
2307  assert(col->var != NULL);
2308  assert(blkmem != NULL);
2309  assert(set != NULL);
2310  assert(lp != NULL);
2311 
2312  if( col->nunlinked > 0 )
2313  {
2314  SCIPdebugMessage("linking column <%s>\n", SCIPvarGetName(col->var));
2315 
2316  /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2317  for( i = col->nlprows; i < col->len; ++i )
2318  {
2319  assert(!SCIPsetIsZero(set, col->vals[i]));
2320  if( col->linkpos[i] == -1 )
2321  {
2322  /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2323  SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2324  }
2325  assert(col->rows[i]->cols[col->linkpos[i]] == col);
2326  assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2327  assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2328  assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2329  }
2330  }
2331  assert(col->nunlinked == 0);
2332 
2333  checkLinks(lp);
2334 
2335  return SCIP_OKAY;
2336 }
2337 
2338 /** removes column coefficients from corresponding rows */
2339 static
2341  SCIP_COL* col, /**< column data */
2342  BMS_BLKMEM* blkmem, /**< block memory */
2343  SCIP_SET* set, /**< global SCIP settings */
2344  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2345  SCIP_LP* lp /**< current LP data */
2346  )
2347 {
2348  int i;
2349 
2350  assert(col != NULL);
2351  assert(col->var != NULL);
2352  assert(blkmem != NULL);
2353  assert(set != NULL);
2354  assert(lp != NULL);
2355 
2356  if( col->nunlinked < col->len )
2357  {
2358  SCIPdebugMessage("unlinking column <%s>\n", SCIPvarGetName(col->var));
2359  for( i = 0; i < col->len; ++i )
2360  {
2361  if( col->linkpos[i] >= 0 )
2362  {
2363  assert(col->rows[i]->cols[col->linkpos[i]] == col);
2364  SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2365  col->linkpos[i] = -1;
2366  col->nunlinked++;
2367  }
2368  }
2369  }
2370  assert(col->nunlinked == col->len);
2371 
2372  checkLinks(lp);
2373 
2374  return SCIP_OKAY;
2375 }
2376 
2377 /** insert row coefficients in corresponding columns */
2378 static
2380  SCIP_ROW* row, /**< row data */
2381  BMS_BLKMEM* blkmem, /**< block memory */
2382  SCIP_SET* set, /**< global SCIP settings */
2383  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2384  SCIP_LP* lp /**< current LP data */
2385  )
2386 {
2387  int i;
2388 
2389  assert(row != NULL);
2390  assert(blkmem != NULL);
2391  assert(set != NULL);
2392  assert(lp != NULL);
2393 
2394  if( row->nunlinked > 0 )
2395  {
2396  SCIPdebugMessage("linking row <%s>\n", row->name);
2397 
2398  /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2399  for( i = row->nlpcols; i < row->len; ++i )
2400  {
2401  assert(!SCIPsetIsZero(set, row->vals[i]));
2402  if( row->linkpos[i] == -1 )
2403  {
2404  /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2405  SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2406  }
2407  assert(row->cols[i]->rows[row->linkpos[i]] == row);
2408  assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2409  assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2410  assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2411  }
2412  }
2413  assert(row->nunlinked == 0);
2414 
2415  checkLinks(lp);
2416 
2417  return SCIP_OKAY;
2418 }
2419 
2420 /** removes row coefficients from corresponding columns */
2421 static
2423  SCIP_ROW* row, /**< row data */
2424  SCIP_SET* set, /**< global SCIP settings */
2425  SCIP_LP* lp /**< current LP data */
2426  )
2427 {
2428  int i;
2429 
2430  assert(row != NULL);
2431  assert(set != NULL);
2432  assert(lp != NULL);
2433 
2434  if( row->nunlinked < row->len )
2435  {
2436  SCIPdebugMessage("unlinking row <%s>\n", row->name);
2437  for( i = 0; i < row->len; ++i )
2438  {
2439  if( row->linkpos[i] >= 0 )
2440  {
2441  assert(row->cols[i]->rows[row->linkpos[i]] == row);
2442  SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2443  row->nunlinked++;
2444  }
2445  }
2446  }
2447  assert(row->nunlinked == row->len);
2448 
2449  return SCIP_OKAY;
2450 }
2451 
2452 
2453 
2454 
2455 /*
2456  * local LP parameter methods
2457  */
2458 
2459 /** sets parameter of type int in LP solver, ignoring unknown parameters */
2460 static
2462  SCIP_LP* lp, /**< current LP data */
2463  SCIP_LPPARAM lpparam, /**< LP parameter */
2464  int value, /**< value to set parameter to */
2465  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2466  )
2467 {
2468  SCIP_RETCODE retcode;
2469 
2470  assert(lp != NULL);
2471  assert(success != NULL);
2472 
2473  retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2474 
2475  /* check, if parameter is unknown */
2476  if( retcode == SCIP_PARAMETERUNKNOWN )
2477  {
2478  *success = FALSE;
2479  return SCIP_OKAY;
2480  }
2481  *success = TRUE;
2482 
2483  return retcode;
2484 }
2485 
2486 /** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2487 static
2489  SCIP_LP* lp, /**< current LP data */
2490  SCIP_LPPARAM lpparam, /**< LP parameter */
2491  SCIP_Bool value, /**< value to set parameter to */
2492  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2493  )
2494 {
2495  return lpSetIntpar(lp, lpparam, (int)value, success);
2496 }
2497 
2498 /** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2499 static
2501  SCIP_LP* lp, /**< current LP data */
2502  SCIP_LPPARAM lpparam, /**< LP parameter */
2503  SCIP_Real value, /**< value to set parameter to */
2504  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2505  )
2506 {
2507  SCIP_RETCODE retcode;
2508 
2509  assert(lp != NULL);
2510  assert(success != NULL);
2511 
2512  retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2513 
2514  /* check, if parameter is unknown */
2515  if( retcode == SCIP_PARAMETERUNKNOWN )
2516  {
2517  *success = FALSE;
2518  return SCIP_OKAY;
2519  }
2520  *success = TRUE;
2521 
2522  return retcode;
2523 }
2524 
2525 #ifndef NDEBUG
2526 /** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2527 static
2529  SCIP_LP* lp, /**< current LP data */
2530  SCIP_LPPARAM lpparam, /**< LP parameter */
2531  int value /**< value parameter should have */
2532  )
2533 {
2534  SCIP_RETCODE retcode;
2535  int lpivalue;
2536 
2537  assert(lp != NULL);
2538 
2539  retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2540 
2541  /* ignore unknown parameter error */
2542  if( retcode == SCIP_PARAMETERUNKNOWN )
2543  return SCIP_OKAY;
2544 
2545  /* check value */
2546  assert(lpivalue == value);
2547 
2548  return retcode;
2549 }
2550 
2551 /** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2552 static
2554  SCIP_LP* lp, /**< current LP data */
2555  SCIP_LPPARAM lpparam, /**< LP parameter */
2556  SCIP_Bool value /**< value parameter should have */
2557  )
2558 {
2559  return lpCheckIntpar(lp, lpparam, (int)value);
2560 }
2561 
2562 /** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2563 static
2565  SCIP_LP* lp, /**< current LP data */
2566  SCIP_LPPARAM lpparam, /**< LP parameter */
2567  SCIP_Real value /**< value parameter should have */
2568  )
2569 {
2570  SCIP_RETCODE retcode;
2571  SCIP_Real lpivalue;
2572 
2573  assert(lp != NULL);
2574 
2575  retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2576 
2577  /* ignore unknown parameter error */
2578  if( retcode == SCIP_PARAMETERUNKNOWN )
2579  return SCIP_OKAY;
2580 
2581  /* check value */
2582  assert(lpivalue == value); /*lint !e777*/
2583 
2584  return retcode;
2585 }
2586 #else
2587 #define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2588 #define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2589 #define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2590 #endif
2591 
2592 /** should the objective limit of the LP solver be disabled */
2593 #define lpCutoffDisabled(set) (set->lp_disablecutoff == 1 || (set->nactivepricers > 0 && set->lp_disablecutoff == 2))
2594 
2595 /** sets the upper objective limit of the LP solver */
2596 static
2598  SCIP_LP* lp, /**< current LP data */
2599  SCIP_SET* set, /**< global SCIP settings */
2600  SCIP_Real uobjlim /**< new feasibility tolerance */
2601  )
2602 {
2603  assert(lp != NULL);
2604  assert(set != NULL);
2605 
2606  /* we disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP
2607  * solver's objective limit handling, so we return here and do not apply the objective limit
2608  */
2609  if( lpCutoffDisabled(set) || set->misc_exactsolve )
2610  return SCIP_OKAY;
2611 
2612  /* convert SCIP infinity value to lp-solver infinity value if necessary */
2613  if( SCIPsetIsInfinity(set, uobjlim) )
2614  uobjlim = SCIPlpiInfinity(lp->lpi);
2615 
2617 
2618  if( uobjlim != lp->lpiuobjlim ) /*lint !e777*/
2619  {
2620  SCIP_Bool success;
2621 
2622  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_UOBJLIM, uobjlim, &success) );
2623  if( success )
2624  {
2625  /* mark the current solution invalid */
2626  lp->solved = FALSE;
2627  lp->primalfeasible = FALSE;
2628  lp->lpobjval = SCIP_INVALID;
2630  lp->lpiuobjlim = uobjlim;
2631  }
2632  }
2633 
2634  return SCIP_OKAY;
2635 }
2636 
2637 /** sets the feasibility tolerance of the LP solver */
2638 static
2640  SCIP_LP* lp, /**< current LP data */
2641  SCIP_Real feastol, /**< new feasibility tolerance */
2642  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2643  )
2644 {
2645  assert(lp != NULL);
2646  assert(feastol >= 0.0);
2647  assert(success != NULL);
2648 
2650 
2651  if( feastol != lp->lpifeastol ) /*lint !e777*/
2652  {
2653  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2654  if( *success )
2655  {
2656  if( lp->nrows > 0 && feastol < lp->lpifeastol )
2657  {
2658  /* mark the current solution invalid */
2659  lp->solved = FALSE;
2660  lp->primalfeasible = FALSE;
2661  lp->lpobjval = SCIP_INVALID;
2663  }
2664  lp->lpifeastol = feastol;
2665  }
2666  }
2667  else
2668  *success = FALSE;
2669 
2670  return SCIP_OKAY;
2671 }
2672 
2673 /** sets the reduced costs feasibility tolerance of the LP solver */
2674 static
2676  SCIP_LP* lp, /**< current LP data */
2677  SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2678  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2679  )
2680 {
2681  assert(lp != NULL);
2682  assert(dualfeastol >= 0.0);
2683  assert(success != NULL);
2684 
2686 
2687  if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2688  {
2689  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2690  if( *success )
2691  {
2692  if( lp->nrows > 0 && dualfeastol < lp->lpidualfeastol )
2693  {
2694  /* mark the current solution invalid */
2695  lp->solved = FALSE;
2696  lp->dualfeasible = FALSE;
2697  lp->lpobjval = SCIP_INVALID;
2699  }
2700  lp->lpidualfeastol = dualfeastol;
2701  }
2702  }
2703  else
2704  *success = FALSE;
2705 
2706  return SCIP_OKAY;
2707 }
2708 
2709 /** sets the convergence tolerance used in barrier algorithm of the LP solver */
2710 static
2712  SCIP_LP* lp, /**< current LP data */
2713  SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2714  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2715  )
2716 {
2717  assert(lp != NULL);
2718  assert(barrierconvtol >= 0.0);
2719  assert(success != NULL);
2720 
2722 
2723  if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2724  {
2725  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2726  if( *success )
2727  {
2728  if( lp->nrows > 0 && barrierconvtol < lp->lpibarrierconvtol
2730  {
2731  /* mark the current solution invalid */
2732  lp->solved = FALSE;
2733  lp->dualfeasible = FALSE;
2734  lp->lpobjval = SCIP_INVALID;
2736  }
2737  lp->lpibarrierconvtol = barrierconvtol;
2738  }
2739  }
2740  else
2741  *success = FALSE;
2742 
2743  return SCIP_OKAY;
2744 }
2745 
2746 /** sets the FROMSCRATCH setting of the LP solver */
2747 static
2749  SCIP_LP* lp, /**< current LP data */
2750  SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2751  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2752  )
2753 {
2754  assert(lp != NULL);
2755  assert(success != NULL);
2756 
2758 
2759  if( fromscratch != lp->lpifromscratch )
2760  {
2761  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2762  if( *success )
2763  lp->lpifromscratch = fromscratch;
2764  }
2765  else
2766  *success = FALSE;
2767 
2768  return SCIP_OKAY;
2769 }
2770 
2771 /** sets the FASTMIP setting of the LP solver */
2772 static
2774  SCIP_LP* lp, /**< current LP data */
2775  int fastmip, /**< new FASTMIP setting */
2776  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2777  )
2778 {
2779  assert(lp != NULL);
2780  assert(success != NULL);
2781  assert(0 <= fastmip && fastmip <= 1);
2782 
2784 
2785  if( fastmip != lp->lpifastmip )
2786  {
2787  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2788  if( *success )
2789  lp->lpifastmip = fastmip;
2790  }
2791  else
2792  *success = FALSE;
2793 
2794  return SCIP_OKAY;
2795 }
2796 
2797 /** sets the SCALING setting of the LP solver */
2798 static
2800  SCIP_LP* lp, /**< current LP data */
2801  SCIP_Bool scaling, /**< new SCALING setting */
2802  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2803  )
2804 {
2805  assert(lp != NULL);
2806  assert(success != NULL);
2807 
2809 
2810  if( scaling != lp->lpiscaling )
2811  {
2812  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2813  if( *success )
2814  lp->lpiscaling = scaling;
2815  }
2816  else
2817  *success = FALSE;
2818 
2819  return SCIP_OKAY;
2820 }
2821 
2822 /** sets the number of THREADS of the LP solver */
2823 static
2825  SCIP_LP* lp, /**< current LP data */
2826  int threads, /**< new number of threads used to solve the LP */
2827  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2828  )
2829 {
2830  assert(lp != NULL);
2831  assert(success != NULL);
2832 
2834 
2835  if( threads != lp->lpithreads )
2836  {
2837  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2838  if( *success )
2839  lp->lpithreads = threads;
2840  }
2841  else
2842  *success = FALSE;
2843 
2844  return SCIP_OKAY;
2845 }
2846 
2847 /** sets the PRESOLVING setting of the LP solver */
2848 static
2850  SCIP_LP* lp, /**< current LP data */
2851  SCIP_Bool presolving, /**< new PRESOLVING setting */
2852  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2853  )
2854 {
2855  assert(lp != NULL);
2856  assert(success != NULL);
2857 
2859 
2860  if( presolving != lp->lpipresolving )
2861  {
2862  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2863  if( *success )
2864  lp->lpipresolving = presolving;
2865  }
2866  else
2867  *success = FALSE;
2868 
2869  return SCIP_OKAY;
2870 }
2871 
2872 /** sets the ROWREPSWITCH setting of the LP solver */
2873 static
2875  SCIP_LP* lp, /**< current LP data */
2876  SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2877  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2878  )
2879 {
2880  assert(lp != NULL);
2881  assert(success != NULL);
2882 
2884 
2885  if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2886  {
2887  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2888  if( *success )
2889  lp->lpirowrepswitch = rowrepswitch;
2890  }
2891  else
2892  *success = FALSE;
2893 
2894  return SCIP_OKAY;
2895 }
2896 
2897 /** sets the iteration limit of the LP solver */
2898 static
2900  SCIP_LP* lp, /**< current LP data */
2901  int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2902  )
2903 {
2904  SCIP_Bool success;
2905 
2906  assert(lp != NULL);
2907  assert(itlim >= -1);
2908 
2909  if( itlim == -1 )
2910  itlim = INT_MAX;
2911 
2913 
2914  if( itlim != lp->lpiitlim )
2915  {
2916  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
2917  if( success )
2918  {
2919  if( itlim > lp->lpiitlim )
2920  {
2921  /* mark the current solution invalid */
2922  lp->solved = FALSE;
2923  lp->lpobjval = SCIP_INVALID;
2925  }
2926  lp->lpiitlim = itlim;
2927  }
2928  }
2929 
2930  return SCIP_OKAY;
2931 }
2932 
2933 /** sets the pricing strategy of the LP solver */
2934 static
2936  SCIP_LP* lp, /**< current LP data */
2937  SCIP_PRICING pricing /**< pricing strategy */
2938  )
2939 {
2940  SCIP_Bool success;
2941 
2942  assert(lp != NULL);
2943 
2945 
2946  if( pricing != lp->lpipricing )
2947  {
2948  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
2949  if( success )
2950  lp->lpipricing = pricing;
2951  }
2952 
2953  return SCIP_OKAY;
2954 }
2955 
2956 /** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
2957 static
2959  SCIP_LP* lp, /**< current LP data */
2960  char pricingchar /**< character representing the pricing strategy */
2961  )
2962 {
2963  SCIP_PRICING pricing;
2964 
2965  switch( pricingchar )
2966  {
2967  case 'l':
2968  pricing = SCIP_PRICING_LPIDEFAULT;
2969  break;
2970  case 'a':
2971  pricing = SCIP_PRICING_AUTO;
2972  break;
2973  case 'f':
2974  pricing = SCIP_PRICING_FULL;
2975  break;
2976  case 'p':
2977  pricing = SCIP_PRICING_PARTIAL;
2978  break;
2979  case 's':
2980  pricing = SCIP_PRICING_STEEP;
2981  break;
2982  case 'q':
2983  pricing = SCIP_PRICING_STEEPQSTART;
2984  break;
2985  case 'd':
2986  pricing = SCIP_PRICING_DEVEX;
2987  break;
2988  default:
2989  SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
2990  return SCIP_INVALIDDATA;
2991  }
2992 
2993  SCIP_CALL( lpSetPricing(lp, pricing) );
2994 
2995  return SCIP_OKAY;
2996 }
2997 
2998 /** sets the verbosity of the LP solver */
2999 static
3001  SCIP_LP* lp, /**< current LP data */
3002  SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3003  )
3004 {
3005  SCIP_Bool success;
3006 
3007  assert(lp != NULL);
3008 
3010 
3011  if( lpinfo != lp->lpilpinfo )
3012  {
3013  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3014  if( success )
3015  lp->lpilpinfo = lpinfo;
3016  }
3017 
3018  return SCIP_OKAY;
3019 }
3020 
3021 /** sets the CONDITIONLIMIT setting of the LP solver */
3022 static
3024  SCIP_LP* lp, /**< current LP data */
3025  SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3026  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3027  )
3028 {
3029  assert(lp != NULL);
3030  assert(success != NULL);
3031 
3033 
3034  if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3035  {
3036  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3037  if( *success )
3038  lp->lpiconditionlimit = condlimit;
3039  }
3040  else
3041  *success = FALSE;
3042 
3043  return SCIP_OKAY;
3044 }
3045 
3046 /** sets the type of timer of the LP solver */
3047 static
3049  SCIP_LP* lp, /**< current LP data */
3050  SCIP_CLOCKTYPE timing, /**< new timing value */
3051  SCIP_Bool enabled, /**< is timing enabled? */
3052  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3053  )
3054 {
3055  int lptiming;
3056 
3057  assert(lp != NULL);
3058  assert(success != NULL);
3059  assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2);
3060 
3062 
3063  if( !enabled )
3064  lptiming = 0;
3065  else
3066  lptiming = (int) timing;
3067 
3068  if( lptiming != lp->lpitiming ) /*lint !e777*/
3069  {
3070  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3071  if( *success )
3072  lp->lpitiming = lptiming;
3073  }
3074  else
3075  *success = FALSE;
3076 
3077  return SCIP_OKAY;
3078 }
3079 
3080 
3081 /*
3082  * Column methods
3083  */
3084 
3085 /** creates an LP column */
3087  SCIP_COL** col, /**< pointer to column data */
3088  BMS_BLKMEM* blkmem, /**< block memory */
3089  SCIP_SET* set, /**< global SCIP settings */
3090  SCIP_STAT* stat, /**< problem statistics */
3091  SCIP_VAR* var, /**< variable, this column represents */
3092  int len, /**< number of nonzeros in the column */
3093  SCIP_ROW** rows, /**< array with rows of column entries */
3094  SCIP_Real* vals, /**< array with coefficients of column entries */
3095  SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3096  )
3097 {
3098  int i;
3099 
3100  assert(col != NULL);
3101  assert(blkmem != NULL);
3102  assert(set != NULL);
3103  assert(stat != NULL);
3104  assert(var != NULL);
3105  assert(len >= 0);
3106  assert(len == 0 || (rows != NULL && vals != NULL));
3107 
3108  SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3109 
3110  if( len > 0 )
3111  {
3112  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3113  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3114  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3115 
3116  for( i = 0; i < len; ++i )
3117  {
3118  assert(rows[i] != NULL);
3119  assert(!SCIPsetIsZero(set, vals[i]));
3120  (*col)->linkpos[i] = -1;
3121  }
3122  }
3123  else
3124  {
3125  (*col)->rows = NULL;
3126  (*col)->vals = NULL;
3127  (*col)->linkpos = NULL;
3128  }
3129 
3130  (*col)->var = var;
3131  (*col)->obj = SCIPvarGetObj(var);
3132  (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3133  (*col)->lb = SCIPvarGetLbLocal(var);
3134  (*col)->ub = SCIPvarGetUbLocal(var);
3135  (*col)->flushedobj = 0.0;
3136  (*col)->flushedlb = 0.0;
3137  (*col)->flushedub = 0.0;
3138  (*col)->index = stat->ncolidx++;
3139  (*col)->size = len;
3140  (*col)->len = len;
3141  (*col)->nlprows = 0;
3142  (*col)->nunlinked = len;
3143  (*col)->lppos = -1;
3144  (*col)->lpipos = -1;
3145  (*col)->lpdepth = -1;
3146  (*col)->primsol = 0.0;
3147  (*col)->redcost = SCIP_INVALID;
3148  (*col)->farkascoef = SCIP_INVALID;
3149  (*col)->minprimsol = (*col)->ub;
3150  (*col)->maxprimsol = (*col)->lb;
3151  (*col)->sbdown = SCIP_INVALID;
3152  (*col)->sbup = SCIP_INVALID;
3153  (*col)->sbsolval = SCIP_INVALID;
3154  (*col)->sblpobjval = SCIP_INVALID;
3155  (*col)->sbnode = -1;
3156  (*col)->validredcostlp = -1;
3157  (*col)->validfarkaslp = -1;
3158  (*col)->validsblp = -1;
3159  (*col)->sbitlim = -1;
3160  (*col)->nsbcalls = 0;
3161  (*col)->age = 0;
3162  (*col)->obsoletenode = -1;
3163  (*col)->var_probindex = SCIPvarGetProbindex(var);
3164  (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3165  (*col)->lprowssorted = TRUE;
3166  (*col)->nonlprowssorted = (len <= 1);
3167  (*col)->objchanged = FALSE;
3168  (*col)->lbchanged = FALSE;
3169  (*col)->ubchanged = FALSE;
3170  (*col)->coefchanged = FALSE;
3171  (*col)->integral = SCIPvarIsIntegral(var);
3172  (*col)->removable = removable;
3173  (*col)->sbdownvalid = FALSE;
3174  (*col)->sbupvalid = FALSE;
3175  (*col)->lazylb = SCIPvarGetLbLazy(var);
3176  (*col)->lazyub = SCIPvarGetUbLazy(var);
3177  (*col)->storedsolvals = NULL;
3178 
3179  return SCIP_OKAY;
3180 }
3181 
3182 /** frees an LP column */
3184  SCIP_COL** col, /**< pointer to LP column */
3185  BMS_BLKMEM* blkmem, /**< block memory */
3186  SCIP_SET* set, /**< global SCIP settings */
3187  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3188  SCIP_LP* lp /**< current LP data */
3189  )
3190 {
3191  assert(blkmem != NULL);
3192  assert(col != NULL);
3193  assert(*col != NULL);
3194  assert((*col)->var != NULL);
3195  assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3196  assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3197  assert((*col)->lppos == -1);
3198  assert((*col)->lpipos == -1);
3199 
3200  /* remove column indices from corresponding rows */
3201  SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3202 
3203  BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3204  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3205  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3206  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3207  BMSfreeBlockMemory(blkmem, col);
3208 
3209  return SCIP_OKAY;
3210 }
3211 
3212 /** output column to file stream */
3214  SCIP_COL* col, /**< LP column */
3215  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3216  FILE* file /**< output file (or NULL for standard output) */
3217  )
3218 {
3219  int r;
3220 
3221  assert(col != NULL);
3222  assert(col->var != NULL);
3223 
3224  /* print bounds */
3225  SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3226 
3227  /* print coefficients */
3228  if( col->len == 0 )
3229  SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3230  for( r = 0; r < col->len; ++r )
3231  {
3232  assert(col->rows[r] != NULL);
3233  assert(col->rows[r]->name != NULL);
3234  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3235  }
3236  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3237 }
3238 
3239 /** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3240  */
3242  SCIP_COL* col /**< column to be sorted */
3243  )
3244 {
3245  /* sort LP rows */
3246  colSortLP(col);
3247 
3248  /* sort non-LP rows */
3249  colSortNonLP(col);
3250 }
3251 
3252 /** adds a previously non existing coefficient to an LP column */
3254  SCIP_COL* col, /**< LP column */
3255  BMS_BLKMEM* blkmem, /**< block memory */
3256  SCIP_SET* set, /**< global SCIP settings */
3257  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3258  SCIP_LP* lp, /**< current LP data */
3259  SCIP_ROW* row, /**< LP row */
3260  SCIP_Real val /**< value of coefficient */
3261  )
3262 {
3263  assert(lp != NULL);
3264  assert(!lp->diving);
3265 
3266  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3267 
3268  checkLinks(lp);
3269 
3270  return SCIP_OKAY;
3271 }
3272 
3273 /** deletes existing coefficient from column */
3275  SCIP_COL* col, /**< column to be changed */
3276  BMS_BLKMEM* blkmem, /**< block memory */
3277  SCIP_SET* set, /**< global SCIP settings */
3278  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3279  SCIP_LP* lp, /**< current LP data */
3280  SCIP_ROW* row /**< coefficient to be deleted */
3281  )
3282 {
3283  int pos;
3284 
3285  assert(col != NULL);
3286  assert(col->var != NULL);
3287  assert(lp != NULL);
3288  assert(!lp->diving);
3289  assert(row != NULL);
3290 
3291  /* search the position of the row in the column's row vector */
3292  pos = colSearchCoef(col, row);
3293  if( pos == -1 )
3294  {
3295  SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3296  return SCIP_INVALIDDATA;
3297  }
3298  assert(0 <= pos && pos < col->len);
3299  assert(col->rows[pos] == row);
3300 
3301  /* if row knows of the column, remove the column from the row's col vector */
3302  if( col->linkpos[pos] >= 0 )
3303  {
3304  assert(row->cols[col->linkpos[pos]] == col);
3305  assert(row->cols_index[col->linkpos[pos]] == col->index);
3306  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3307  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3308  }
3309 
3310  /* delete the row from the column's row vector */
3311  SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3312 
3313  checkLinks(lp);
3314 
3315  return SCIP_OKAY;
3316 }
3317 
3318 /** changes or adds a coefficient to an LP column */
3320  SCIP_COL* col, /**< LP column */
3321  BMS_BLKMEM* blkmem, /**< block memory */
3322  SCIP_SET* set, /**< global SCIP settings */
3323  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3324  SCIP_LP* lp, /**< current LP data */
3325  SCIP_ROW* row, /**< LP row */
3326  SCIP_Real val /**< value of coefficient */
3327  )
3328 {
3329  int pos;
3330 
3331  assert(col != NULL);
3332  assert(lp != NULL);
3333  assert(!lp->diving);
3334  assert(row != NULL);
3335 
3336  /* search the position of the row in the column's row vector */
3337  pos = colSearchCoef(col, row);
3338 
3339  /* check, if row already exists in the column's row vector */
3340  if( pos == -1 )
3341  {
3342  /* add previously not existing coefficient */
3343  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3344  }
3345  else
3346  {
3347  /* modify already existing coefficient */
3348  assert(0 <= pos && pos < col->len);
3349  assert(col->rows[pos] == row);
3350 
3351  /* if row knows of the column, change the corresponding coefficient in the row */
3352  if( col->linkpos[pos] >= 0 )
3353  {
3354  assert(row->cols[col->linkpos[pos]] == col);
3355  assert(row->cols_index[col->linkpos[pos]] == col->index);
3356  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3357  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3358  }
3359 
3360  /* change the coefficient in the column */
3361  SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3362  }
3363 
3364  checkLinks(lp);
3365 
3366  return SCIP_OKAY;
3367 }
3368 
3369 /** increases value of an existing or non-existing coefficient in an LP column */
3371  SCIP_COL* col, /**< LP column */
3372  BMS_BLKMEM* blkmem, /**< block memory */
3373  SCIP_SET* set, /**< global SCIP settings */
3374  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3375  SCIP_LP* lp, /**< current LP data */
3376  SCIP_ROW* row, /**< LP row */
3377  SCIP_Real incval /**< value to add to the coefficient */
3378  )
3379 {
3380  int pos;
3381 
3382  assert(col != NULL);
3383  assert(lp != NULL);
3384  assert(!lp->diving);
3385  assert(row != NULL);
3386 
3387  if( SCIPsetIsZero(set, incval) )
3388  return SCIP_OKAY;
3389 
3390  /* search the position of the row in the column's row vector */
3391  pos = colSearchCoef(col, row);
3392 
3393  /* check, if row already exists in the column's row vector */
3394  if( pos == -1 )
3395  {
3396  /* add previously not existing coefficient */
3397  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3398  }
3399  else
3400  {
3401  /* modify already existing coefficient */
3402  assert(0 <= pos && pos < col->len);
3403  assert(col->rows[pos] == row);
3404 
3405  /* if row knows of the column, change the corresponding coefficient in the row */
3406  if( col->linkpos[pos] >= 0 )
3407  {
3408  assert(row->cols[col->linkpos[pos]] == col);
3409  assert(row->cols_index[col->linkpos[pos]] == col->index);
3410  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3411  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3412  }
3413 
3414  /* change the coefficient in the column */
3415  SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3416  }
3417 
3418  checkLinks(lp);
3419 
3420  return SCIP_OKAY;
3421 }
3422 
3423 /** insert column in the chgcols list (if not already there) */
3424 static
3426  SCIP_COL* col, /**< LP column to change */
3427  SCIP_SET* set, /**< global SCIP settings */
3428  SCIP_LP* lp /**< current LP data */
3429  )
3430 {
3431  if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3432  {
3433  SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3434  lp->chgcols[lp->nchgcols] = col;
3435  lp->nchgcols++;
3436  }
3437 
3438  /* mark the current LP unflushed */
3439  lp->flushed = FALSE;
3440 
3441  return SCIP_OKAY;
3442 }
3443 
3444 /** Is the new value reliable or may we have cancellation?
3445  *
3446  * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3447  * cancellations which can occur during increasing the oldvalue to the newvalue
3448  */
3449 static
3451  SCIP_SET* set, /**< global SCIP settings */
3452  SCIP_Real newvalue, /**< new value */
3453  SCIP_Real oldvalue /**< old reliable value */
3454  )
3455 {
3456  SCIP_Real quotient;
3457 
3458  assert(set != NULL);
3459  assert(oldvalue < SCIP_INVALID);
3460 
3461  quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3462 
3463  return SCIPsetIsZero(set, quotient);
3464 }
3465 
3466 /** update norms of objective function vector */
3467 static
3469  SCIP_LP* lp, /**< current LP data */
3470  SCIP_SET* set, /**< global SCIP settings */
3471  SCIP_Real oldobj, /**< old objective value of variable */
3472  SCIP_Real newobj /**< new objective value of variable */
3473  )
3474 {
3475  if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
3476  {
3477  if( !lp->objsqrnormunreliable )
3478  {
3479  SCIP_Real oldvalue;
3480 
3481  oldvalue = lp->objsqrnorm;
3482  lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3483 
3484  /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3485  if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3486  lp->objsqrnormunreliable = TRUE;
3487  else
3488  {
3489  assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3490 
3491  /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3492  lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3493 
3494  assert(lp->objsqrnorm >= 0.0);
3495  }
3496  }
3497 
3498  lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3499  lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3500  }
3501 }
3502 
3503 /** changes objective value of column */
3505  SCIP_COL* col, /**< LP column to change */
3506  SCIP_SET* set, /**< global SCIP settings */
3507  SCIP_LP* lp, /**< current LP data */
3508  SCIP_Real newobj /**< new objective value */
3509  )
3510 {
3511  assert(col != NULL);
3512  assert(col->var != NULL);
3513  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3514  assert(SCIPvarGetCol(col->var) == col);
3515  assert(lp != NULL);
3516 
3517  SCIPdebugMessage("changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3518 
3519  /* only add actual changes */
3520  if( !SCIPsetIsEQ(set, col->obj, newobj) )
3521  {
3522  /* only variables with a real position in the LPI can be inserted */
3523  if( col->lpipos >= 0 )
3524  {
3525  /* insert column in the chgcols list (if not already there) */
3526  SCIP_CALL( insertColChgcols(col, set, lp) );
3527 
3528  /* mark objective value change in the column */
3529  col->objchanged = TRUE;
3530 
3531  assert(lp->nchgcols > 0);
3532  }
3533  /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3534  * LP and the LP has to be flushed
3535  */
3536  else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3537  || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3538  {
3539  /* mark the LP unflushed */
3540  lp->flushed = FALSE;
3541  }
3542  }
3543 
3544  /* store new objective function value */
3545  col->obj = newobj;
3546 
3547  /* update original objective value, as long as we are not in diving or probing and changed objective values */
3548  if( !lp->divingobjchg )
3549  {
3550  SCIP_Real oldobj = col->unchangedobj;
3551 
3552  assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3553  col->unchangedobj = newobj;
3554 
3555  /* update the objective function vector norms */
3556  lpUpdateObjNorms(lp, set, oldobj, newobj);
3557  }
3558 
3559  return SCIP_OKAY;
3560 }
3561 
3562 /** changes lower bound of column */
3564  SCIP_COL* col, /**< LP column to change */
3565  SCIP_SET* set, /**< global SCIP settings */
3566  SCIP_LP* lp, /**< current LP data */
3567  SCIP_Real newlb /**< new lower bound value */
3568  )
3569 {
3570  assert(col != NULL);
3571  assert(col->var != NULL);
3572  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3573  assert(SCIPvarGetCol(col->var) == col);
3574  assert(lp != NULL);
3575 
3576  SCIPdebugMessage("changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3577 
3578  /* only add actual changes */
3579  if( !SCIPsetIsEQ(set, col->lb, newlb) )
3580  {
3581  /* only variables with a real position in the LPI can be inserted */
3582  if( col->lpipos >= 0 )
3583  {
3584  /* insert column in the chgcols list (if not already there) */
3585  SCIP_CALL( insertColChgcols(col, set, lp) );
3586 
3587  /* mark bound change in the column */
3588  col->lbchanged = TRUE;
3589 
3590  assert(lp->nchgcols > 0);
3591  }
3592  /* 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
3593  * flushed
3594  */
3595  else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3596  {
3597  /* mark the LP unflushed */
3598  lp->flushed = FALSE;
3599  }
3600  }
3601 
3602  col->lb = newlb;
3603 
3604  return SCIP_OKAY;
3605 }
3606 
3607 /** changes upper bound of column */
3609  SCIP_COL* col, /**< LP column to change */
3610  SCIP_SET* set, /**< global SCIP settings */
3611  SCIP_LP* lp, /**< current LP data */
3612  SCIP_Real newub /**< new upper bound value */
3613  )
3614 {
3615  assert(col != NULL);
3616  assert(col->var != NULL);
3617  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3618  assert(SCIPvarGetCol(col->var) == col);
3619  assert(lp != NULL);
3620 
3621  SCIPdebugMessage("changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3622 
3623  /* only add actual changes */
3624  if( !SCIPsetIsEQ(set, col->ub, newub) )
3625  {
3626  /* only variables with a real position in the LPI can be inserted */
3627  if( col->lpipos >= 0 )
3628  {
3629  /* insert column in the chgcols list (if not already there) */
3630  SCIP_CALL( insertColChgcols(col, set, lp) );
3631 
3632  /* mark bound change in the column */
3633  col->ubchanged = TRUE;
3634 
3635  assert(lp->nchgcols > 0);
3636  }
3637  /* 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
3638  * flushed
3639  */
3640  else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3641  {
3642  /* mark the LP unflushed */
3643  lp->flushed = FALSE;
3644  }
3645  }
3646 
3647  col->ub = newub;
3648 
3649  return SCIP_OKAY;
3650 }
3651 
3652 /** calculates the reduced costs of a column using the given dual solution vector */
3654  SCIP_COL* col, /**< LP column */
3655  SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3656  )
3657 {
3658  SCIP_ROW* row;
3659  SCIP_Real redcost;
3660  int i;
3661 
3662  assert(col != NULL);
3663  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3664  assert(SCIPvarGetCol(col->var) == col);
3665  assert(dualsol != NULL);
3666 
3667  redcost = col->obj;
3668  for( i = 0; i < col->nlprows; ++i )
3669  {
3670  row = col->rows[i];
3671  assert(row != NULL);
3672  assert(row->lppos >= 0);
3673  redcost -= col->vals[i] * dualsol[row->lppos];
3674  }
3675 
3676  if( col->nunlinked > 0 )
3677  {
3678  for( i = col->nlprows; i < col->len; ++i )
3679  {
3680  row = col->rows[i];
3681  assert(row != NULL);
3682  assert(row->lppos == -1 || col->linkpos[i] == -1);
3683  if( row->lppos >= 0 )
3684  redcost -= col->vals[i] * dualsol[row->lppos];
3685  }
3686  }
3687 #ifndef NDEBUG
3688  else
3689  {
3690  for( i = col->nlprows; i < col->len; ++i )
3691  {
3692  row = col->rows[i];
3693  assert(row != NULL);
3694  assert(row->lppos == -1);
3695  assert(col->linkpos[i] >= 0);
3696  }
3697  }
3698 #endif
3699 
3700  return redcost;
3701 }
3702 
3703 /** calculates the reduced costs of a column using the dual solution stored in the rows */
3704 static
3706  SCIP_COL* col /**< LP column */
3707  )
3708 {
3709  SCIP_ROW* row;
3710  SCIP_Real redcost;
3711  int i;
3712 
3713  assert(col != NULL);
3714  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3715  assert(SCIPvarGetCol(col->var) == col);
3716 
3717  redcost = col->obj;
3718  for( i = 0; i < col->nlprows; ++i )
3719  {
3720  row = col->rows[i];
3721  assert(row != NULL);
3722  assert(row->dualsol < SCIP_INVALID);
3723  assert(row->lppos >= 0);
3724  assert(col->linkpos[i] >= 0);
3725  redcost -= col->vals[i] * row->dualsol;
3726  }
3727 
3728  if( col->nunlinked > 0 )
3729  {
3730  for( i = col->nlprows; i < col->len; ++i )
3731  {
3732  row = col->rows[i];
3733  assert(row != NULL);
3734  assert(row->lppos >= 0 || row->dualsol == 0.0);
3735  assert(row->lppos == -1 || col->linkpos[i] == -1);
3736  if( row->lppos >= 0 )
3737  redcost -= col->vals[i] * row->dualsol;
3738  }
3739  }
3740 #ifndef NDEBUG
3741  else
3742  {
3743  for( i = col->nlprows; i < col->len; ++i )
3744  {
3745  row = col->rows[i];
3746  assert(row != NULL);
3747  assert(row->dualsol == 0.0);
3748  assert(row->lppos == -1);
3749  assert(col->linkpos[i] >= 0);
3750  }
3751  }
3752 #endif
3753 
3754  return redcost;
3755 }
3756 
3757 /** gets the reduced costs of a column in last LP or after recalculation */
3759  SCIP_COL* col, /**< LP column */
3760  SCIP_STAT* stat, /**< problem statistics */
3761  SCIP_LP* lp /**< current LP data */
3762  )
3763 {
3764  assert(col != NULL);
3765  assert(stat != NULL);
3766  assert(lp != NULL);
3767  assert(col->validredcostlp <= stat->lpcount);
3768  assert(lp->validsollp == stat->lpcount);
3769 
3770  if( col->validredcostlp < stat->lpcount )
3771  {
3772  col->redcost = colCalcInternalRedcost(col);
3773  col->validredcostlp = stat->lpcount;
3774  }
3775  assert(col->validredcostlp == stat->lpcount);
3776  assert(col->redcost < SCIP_INVALID);
3777 
3778  return col->redcost;
3779 }
3780 
3781 /** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3783  SCIP_COL* col, /**< LP column */
3784  SCIP_SET* set, /**< global SCIP settings */
3785  SCIP_STAT* stat, /**< problem statistics */
3786  SCIP_LP* lp /**< current LP data */
3787  )
3788 {
3789  assert(col != NULL);
3790  assert(set != NULL);
3791  assert(stat != NULL);
3792  assert(lp != NULL);
3793  assert(lp->validsollp == stat->lpcount);
3794 
3795  /* A column's reduced cost is defined as
3796  * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3797  * The activity is equal to the activity of the corresponding row in the dual LP.
3798  * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3799  * The sides of the dual row depend on the bounds of the column:
3800  * - lb == ub : dual row is a free row with infinite sides
3801  * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3802  * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3803  * - lb < ub <= 0: obj <= activity => redcost <= 0
3804  */
3805  if( SCIPsetIsEQ(set, col->lb, col->ub) )
3806  {
3807  /* dual row is free */
3808  return SCIPsetInfinity(set);
3809  }
3810  else
3811  {
3812  SCIP_Real redcost;
3813 
3814  /* calculate reduced costs */
3815  redcost = SCIPcolGetRedcost(col, stat, lp);
3816 
3817  if( !SCIPsetIsNegative(set, col->lb) )
3818  {
3819  /* dual row is activity <= obj <=> redcost >= 0 */
3820  return redcost;
3821  }
3822  else if( SCIPsetIsPositive(set, col->ub) )
3823  {
3824  /* dual row is activity == obj <=> redcost == 0 */
3825  return -REALABS(redcost);
3826  }
3827  else
3828  {
3829  /* dual row is activity >= obj <=> redcost <= 0 */
3830  return -redcost;
3831  }
3832  }
3833 }
3834 
3835 /** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
3837  SCIP_COL* col, /**< LP column */
3838  SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
3839  )
3840 {
3841  SCIP_ROW* row;
3842  SCIP_Real farkas;
3843  int i;
3844 
3845  assert(col != NULL);
3846  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3847  assert(SCIPvarGetCol(col->var) == col);
3848  assert(dualfarkas != NULL);
3849 
3850  farkas = 0.0;
3851  for( i = 0; i < col->nlprows; ++i )
3852  {
3853  row = col->rows[i];
3854  assert(row != NULL);
3855  assert(row->lppos >= 0);
3856  farkas += col->vals[i] * dualfarkas[row->lppos];
3857  }
3858 
3859  if( col->nunlinked > 0 )
3860  {
3861  for( i = col->nlprows; i < col->len; ++i )
3862  {
3863  row = col->rows[i];
3864  assert(row != NULL);
3865  assert(row->lppos == -1 || col->linkpos[i] == -1);
3866  if( row->lppos >= 0 )
3867  farkas += col->vals[i] * dualfarkas[row->lppos];
3868  }
3869  }
3870 #ifndef NDEBUG
3871  else
3872  {
3873  for( i = col->nlprows; i < col->len; ++i )
3874  {
3875  row = col->rows[i];
3876  assert(row != NULL);
3877  assert(row->lppos == -1);
3878  assert(col->linkpos[i] >= 0);
3879  }
3880  }
3881 #endif
3882 
3883  return farkas;
3884 }
3885 
3886 /** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
3887 static
3889  SCIP_COL* col /**< LP column */
3890  )
3891 {
3892  SCIP_ROW* row;
3893  SCIP_Real farkas;
3894  int i;
3895 
3896  assert(col != NULL);
3897  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3898  assert(SCIPvarGetCol(col->var) == col);
3899 
3900  farkas = 0.0;
3901  for( i = 0; i < col->nlprows; ++i )
3902  {
3903  row = col->rows[i];
3904  assert(row != NULL);
3905  assert(row->dualfarkas < SCIP_INVALID);
3906  assert(row->lppos >= 0);
3907  assert(col->linkpos[i] >= 0);
3908  farkas += col->vals[i] * row->dualfarkas;
3909  }
3910 
3911  if( col->nunlinked > 0 )
3912  {
3913  for( i = col->nlprows; i < col->len; ++i )
3914  {
3915  row = col->rows[i];
3916  assert(row != NULL);
3917  assert(row->lppos >= 0 || row->dualfarkas == 0.0);
3918  assert(row->lppos == -1 || col->linkpos[i] == -1);
3919  if( row->lppos >= 0 )
3920  farkas += col->vals[i] * row->dualfarkas;
3921  }
3922  }
3923 #ifndef NDEBUG
3924  else
3925  {
3926  for( i = col->nlprows; i < col->len; ++i )
3927  {
3928  row = col->rows[i];
3929  assert(row != NULL);
3930  assert(row->dualfarkas == 0.0);
3931  assert(row->lppos == -1);
3932  assert(col->linkpos[i] >= 0);
3933  }
3934  }
3935 #endif
3936 
3937  return farkas;
3938 }
3939 
3940 /** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
3942  SCIP_COL* col, /**< LP column */
3943  SCIP_STAT* stat, /**< problem statistics */
3944  SCIP_LP* lp /**< current LP data */
3945  )
3946 {
3947  assert(col != NULL);
3948  assert(stat != NULL);
3949  assert(lp != NULL);
3950  assert(col->validfarkaslp <= stat->lpcount);
3951  assert(lp->validfarkaslp == stat->lpcount);
3952 
3953  if( col->validfarkaslp < stat->lpcount )
3954  {
3956  col->validfarkaslp = stat->lpcount;
3957  }
3958  assert(col->validfarkaslp == stat->lpcount);
3959  assert(col->farkascoef < SCIP_INVALID);
3960 
3961  return col->farkascoef;
3962 }
3963 
3964 /** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
3965  * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
3966  */
3968  SCIP_COL* col, /**< LP column */
3969  SCIP_STAT* stat, /**< problem statistics */
3970  SCIP_LP* lp /**< current LP data */
3971  )
3972 {
3973  SCIP_Real farkascoef;
3974 
3975  assert(col != NULL);
3976 
3977  farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
3978 
3979  if( farkascoef > 0.0 )
3980  return col->ub * farkascoef;
3981  else
3982  return col->lb * farkascoef;
3983 }
3984 
3985 /** start strong branching - call before any strong branching */
3987  SCIP_LP* lp /**< LP data */
3988  )
3989 {
3990  assert(lp != NULL);
3991  assert(!lp->strongbranching);
3992 
3993  lp->strongbranching = TRUE;
3994  SCIPdebugMessage("starting strong branching ...\n");
3996 
3997  return SCIP_OKAY;
3998 }
3999 
4000 /** end strong branching - call after any strong branching */
4002  SCIP_LP* lp /**< LP data */
4003  )
4004 {
4005  assert(lp != NULL);
4006  assert(lp->strongbranching);
4007 
4008  lp->strongbranching = FALSE;
4009  SCIPdebugMessage("ending strong branching ...\n");
4011 
4012  return SCIP_OKAY;
4013 }
4014 
4015 /** sets strong branching information for a column variable */
4017  SCIP_COL* col, /**< LP column */
4018  SCIP_SET* set, /**< global SCIP settings */
4019  SCIP_STAT* stat, /**< dynamic problem statistics */
4020  SCIP_LP* lp, /**< LP data */
4021  SCIP_Real lpobjval, /**< objective value of the current LP */
4022  SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4023  SCIP_Real sbdown, /**< dual bound after branching column down */
4024  SCIP_Real sbup, /**< dual bound after branching column up */
4025  SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
4026  SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
4027  SCIP_Longint iter, /**< total number of strong branching iterations */
4028  int itlim /**< iteration limit applied to the strong branching call */
4029  )
4030 {
4031  assert(col != NULL);
4032  assert(col->var != NULL);
4033  assert(SCIPcolIsIntegral(col));
4034  assert(SCIPvarIsIntegral(col->var));
4035  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4036  assert(SCIPvarGetCol(col->var) == col);
4037  assert(col->lpipos >= 0);
4038  assert(col->lppos >= 0);
4039  assert(set != NULL);
4040  assert(stat != NULL);
4041  assert(lp != NULL);
4042  assert(lp->strongbranchprobing);
4043  assert(col->lppos < lp->ncols);
4044  assert(lp->cols[col->lppos] == col);
4045  assert(itlim >= 1);
4046 
4047  col->sblpobjval = lpobjval;
4048  col->sbsolval = primsol;
4049  col->validsblp = stat->lpcount - stat->nsbdivinglps;
4050  col->sbnode = stat->nnodes;
4051 
4052  col->sbitlim = itlim;
4053  col->nsbcalls++;
4054 
4055  col->sbdown = MIN(sbdown, lp->cutoffbound);
4056  col->sbup = MIN(sbup, lp->cutoffbound);
4057  col->sbdownvalid = sbdownvalid;
4058  col->sbupvalid = sbupvalid;
4059 
4060  stat->nstrongbranchs++;
4061  stat->nsblpiterations += iter;
4062  if( stat->nnodes == 1 )
4063  {
4064  stat->nrootstrongbranchs++;
4065  stat->nrootsblpiterations += iter;
4066  }
4067 }
4068 
4069 /** invalidates strong branching information for a column variable */
4071  SCIP_COL* col, /**< LP column */
4072  SCIP_SET* set, /**< global SCIP settings */
4073  SCIP_STAT* stat, /**< dynamic problem statistics */
4074  SCIP_LP* lp /**< LP data */
4075  )
4076 {
4077  assert(col != NULL);
4078  assert(col->var != NULL);
4079  assert(SCIPcolIsIntegral(col));
4080  assert(SCIPvarIsIntegral(col->var));
4081  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4082  assert(SCIPvarGetCol(col->var) == col);
4083  assert(col->lpipos >= 0);
4084  assert(col->lppos >= 0);
4085  assert(set != NULL);
4086  assert(stat != NULL);
4087  assert(lp != NULL);
4088  assert(lp->strongbranchprobing);
4089  assert(col->lppos < lp->ncols);
4090  assert(lp->cols[col->lppos] == col);
4091 
4092  col->sbdown = SCIP_INVALID;
4093  col->sbup = SCIP_INVALID;
4094  col->sbdownvalid = FALSE;
4095  col->sbupvalid = FALSE;
4096  col->validsblp = -1;
4097  col->sbsolval = SCIP_INVALID;
4098  col->sblpobjval = SCIP_INVALID;
4099  col->sbnode = -1;
4100  col->sbitlim = -1;
4101 }
4102 
4103 
4104 /** gets strong branching information on a column variable */
4106  SCIP_COL* col, /**< LP column */
4107  SCIP_Bool integral, /**< should integral strong branching be performed? */
4108  SCIP_SET* set, /**< global SCIP settings */
4109  SCIP_STAT* stat, /**< dynamic problem statistics */
4110  SCIP_PROB* prob, /**< problem data */
4111  SCIP_LP* lp, /**< LP data */
4112  int itlim, /**< iteration limit for strong branchings */
4113  SCIP_Real* down, /**< stores dual bound after branching column down */
4114  SCIP_Real* up, /**< stores dual bound after branching column up */
4115  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4116  * otherwise, it can only be used as an estimate value */
4117  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4118  * otherwise, it can only be used as an estimate value */
4119  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4120  )
4121 {
4122  assert(col != NULL);
4123  assert(col->var != NULL);
4124  assert(SCIPcolIsIntegral(col));
4125  assert(SCIPvarIsIntegral(col->var));
4126  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4127  assert(SCIPvarGetCol(col->var) == col);
4128  assert(col->primsol < SCIP_INVALID);
4129  assert(col->lpipos >= 0);
4130  assert(col->lppos >= 0);
4131  assert(set != NULL);
4132  assert(stat != NULL);
4133  assert(lp != NULL);
4134  assert(lp->flushed);
4135  assert(lp->solved);
4136  assert(lp->strongbranching);
4137  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4138  assert(lp->validsollp == stat->lpcount);
4139  assert(col->lppos < lp->ncols);
4140  assert(lp->cols[col->lppos] == col);
4141  assert(itlim >= 1);
4142  /* assert(down != NULL);
4143  * assert(up != NULL); temporary hack for cloud branching
4144  */
4145  assert(lperror != NULL);
4146 
4147  *lperror = FALSE;
4148 
4149  if( col->validsblp != stat->lpcount - stat->nsbdivinglps || itlim > col->sbitlim )
4150  {
4151  col->validsblp = stat->lpcount - stat->nsbdivinglps;
4152  col->sbsolval = col->primsol;
4153  col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4154  col->sbnode = stat->nnodes;
4155  assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4156 
4157  /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4158  if( lp->looseobjvalinf > 0 )
4159  {
4160  col->sbdown = -SCIPsetInfinity(set);
4161  col->sbup = -SCIPsetInfinity(set);
4162  col->sbdownvalid = FALSE;
4163  col->sbupvalid = FALSE;
4164  }
4165  else
4166  {
4167  SCIP_RETCODE retcode;
4168  SCIP_Real sbdown;
4169  SCIP_Real sbup;
4170  SCIP_Bool sbdownvalid;
4171  SCIP_Bool sbupvalid;
4172  int iter;
4173 
4174  SCIPdebugMessage("performing strong branching on variable <%s>(%g) with %d iterations\n",
4175  SCIPvarGetName(col->var), col->primsol, itlim);
4176 
4177  /* start timing */
4178  SCIPclockStart(stat->strongbranchtime, set);
4179 
4180  /* call LPI strong branching */
4181  col->sbitlim = itlim;
4182  col->nsbcalls++;
4183 
4184  sbdown = lp->lpobjval;
4185  sbup = lp->lpobjval;
4186 
4187  if( integral )
4188  retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4189  else
4190  {
4191  assert( ! SCIPsetIsIntegral(set, col->primsol) );
4192  retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4193  }
4194 
4195 
4196  /* check return code for errors */
4197  if( retcode == SCIP_LPERROR )
4198  {
4199  *lperror = TRUE;
4200  col->sbdown = SCIP_INVALID;
4201  col->sbup = SCIP_INVALID;
4202  col->sbdownvalid = FALSE;
4203  col->sbupvalid = FALSE;
4204  col->validsblp = -1;
4205  col->sbsolval = SCIP_INVALID;
4206  col->sblpobjval = SCIP_INVALID;
4207  col->sbnode = -1;
4208  }
4209  else
4210  {
4211  SCIP_Real looseobjval;
4212 
4213  *lperror = FALSE;
4214  SCIP_CALL( retcode );
4215 
4216  looseobjval = getFiniteLooseObjval(lp, set, prob);
4217  col->sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4218  col->sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4219 
4220  col->sbdownvalid = sbdownvalid;
4221  col->sbupvalid = sbupvalid;
4222 
4223  /* update strong branching statistics */
4224  if( iter == -1 )
4225  {
4226  /* calculate average iteration number */
4227  iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4228  : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4229  : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4230  : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4231  : 0;
4232  if( iter/2 >= itlim )
4233  iter = 2*itlim;
4234  }
4235  stat->nstrongbranchs++;
4236  stat->nsblpiterations += iter;
4237  if( stat->nnodes == 1 )
4238  {
4239  stat->nrootstrongbranchs++;
4240  stat->nrootsblpiterations += iter;
4241  }
4242  }
4243 
4244  /* stop timing */
4245  SCIPclockStop(stat->strongbranchtime, set);
4246  }
4247  }
4248  assert(*lperror || col->sbdown < SCIP_INVALID);
4249  assert(*lperror || col->sbup < SCIP_INVALID);
4250 
4251  if( down != NULL)
4252  *down = col->sbdown;
4253  if( up != NULL )
4254  *up = col->sbup;
4255  if( downvalid != NULL )
4256  *downvalid = col->sbdownvalid;
4257  if( upvalid != NULL )
4258  *upvalid = col->sbupvalid;
4259 
4260  return SCIP_OKAY;
4261 }
4262 
4263 /** gets strong branching information on column variables */
4265  SCIP_COL** cols, /**< LP columns */
4266  int ncols, /**< number of columns */
4267  SCIP_Bool integral, /**< should integral strong branching be performed? */
4268  SCIP_SET* set, /**< global SCIP settings */
4269  SCIP_STAT* stat, /**< dynamic problem statistics */
4270  SCIP_PROB* prob, /**< problem data */
4271  SCIP_LP* lp, /**< LP data */
4272  int itlim, /**< iteration limit for strong branchings */
4273  SCIP_Real* down, /**< stores dual bounds after branching columns down */
4274  SCIP_Real* up, /**< stores dual bounds after branching columns up */
4275  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4276  * otherwise, they can only be used as an estimate value */
4277  SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4278  * otherwise, they can only be used as an estimate value */
4279  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4280  )
4281 {
4282  SCIP_RETCODE retcode;
4283  SCIP_Real* sbdown;
4284  SCIP_Real* sbup;
4285  SCIP_Bool* sbdownvalid;
4286  SCIP_Bool* sbupvalid;
4287  SCIP_Real* primsols;
4288  SCIP_COL** subcols;
4289  int* lpipos;
4290  int* subidx;
4291  int nsubcols;
4292  int iter;
4293  int j;
4294 
4295  assert(cols != NULL);
4296  assert(set != NULL);
4297  assert(stat != NULL);
4298  assert(lp != NULL);
4299  assert(lp->flushed);
4300  assert(lp->solved);
4301  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4302  assert(lp->validsollp == stat->lpcount);
4303  assert(itlim >= 1);
4304  assert(down != NULL);
4305  assert(up != NULL);
4306  assert(lperror != NULL);
4307 
4308  *lperror = FALSE;
4309 
4310  if ( ncols <= 0 )
4311  return SCIP_OKAY;
4312 
4313  /* start timing */
4314  SCIPclockStart(stat->strongbranchtime, set);
4315 
4316  /* initialize storage */
4317  SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4318  SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4319  SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4320  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4321  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4322  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4323  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4324  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4325 
4326  nsubcols = 0;
4327  for( j = 0; j < ncols; ++j )
4328  {
4329  SCIP_COL* col;
4330  col = cols[j];
4331 
4332  assert(col->lppos < lp->ncols);
4333  assert(lp->cols[col->lppos] == col);
4334  assert(SCIPcolIsIntegral(col));
4335  assert(SCIPvarIsIntegral(col->var));
4336  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4337  assert(SCIPvarGetCol(col->var) == col);
4338  assert(col->primsol < SCIP_INVALID);
4339  assert(col->lpipos >= 0);
4340  assert(col->lppos >= 0);
4341 
4342  if( col->validsblp != stat->lpcount - stat->nsbdivinglps || itlim > col->sbitlim )
4343  {
4344  col->validsblp = stat->lpcount - stat->nsbdivinglps;
4345  col->sbsolval = col->primsol;
4346  col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4347  col->sbnode = stat->nnodes;
4348  assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4349 
4350  /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4351  if( lp->looseobjvalinf > 0 )
4352  {
4353  /* directly set up column and result vectors*/
4354  col->sbdown = -SCIPsetInfinity(set);
4355  col->sbup = -SCIPsetInfinity(set);
4356  col->sbdownvalid = FALSE;
4357  col->sbupvalid = FALSE;
4358  down[j] = col->sbdown;
4359  up[j] = col->sbup;
4360  if( downvalid != NULL )
4361  downvalid[j] = col->sbdownvalid;
4362  if( upvalid != NULL )
4363  upvalid[j] = col->sbupvalid;
4364  }
4365  else
4366  {
4367  col->sbitlim = itlim;
4368  col->nsbcalls++;
4369 
4370  lpipos[nsubcols] = col->lpipos;
4371  primsols[nsubcols] = col->primsol;
4372  assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4373  subidx[nsubcols] = j;
4374  subcols[nsubcols++] = col;
4375  }
4376  }
4377  else
4378  {
4379  /* directly set up resulting values (use stored values) */
4380  down[j] = col->sbdown;
4381  up[j] = col->sbup;
4382  if( downvalid != NULL )
4383  downvalid[j] = col->sbdownvalid;
4384  if( upvalid != NULL )
4385  upvalid[j] = col->sbupvalid;
4386  }
4387  }
4388 
4389  SCIPdebugMessage("performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4390 
4391  /* call LPI strong branching */
4392  if ( integral )
4393  retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4394  else
4395  retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4396 
4397  /* check return code for errors */
4398  if( retcode == SCIP_LPERROR )
4399  {
4400  *lperror = TRUE;
4401 
4402  for( j = 0; j < nsubcols; ++j )
4403  {
4404  SCIP_COL* col;
4405  int idx;
4406 
4407  col = subcols[j];
4408  idx = subidx[j];
4409 
4410  col->sbdown = SCIP_INVALID;
4411  col->sbup = SCIP_INVALID;
4412  col->sbdownvalid = FALSE;
4413  col->sbupvalid = FALSE;
4414  col->validsblp = -1;
4415  col->sbsolval = SCIP_INVALID;
4416  col->sblpobjval = SCIP_INVALID;
4417  col->sbnode = -1;
4418 
4419  down[idx] = col->sbdown;
4420  up[idx] = col->sbup;
4421  if( downvalid != NULL )
4422  downvalid[idx] = col->sbdownvalid;
4423  if( upvalid != NULL )
4424  upvalid[idx] = col->sbupvalid;
4425  }
4426  }
4427  else
4428  {
4429  SCIP_Real looseobjval;
4430 
4431  *lperror = FALSE;
4432  SCIP_CALL( retcode );
4433 
4434  looseobjval = getFiniteLooseObjval(lp, set, prob);
4435 
4436  for( j = 0; j < nsubcols; ++j )
4437  {
4438  SCIP_COL* col;
4439  int idx;
4440 
4441  col = subcols[j];
4442  idx = subidx[j];
4443 
4444  assert( col->sbdown < SCIP_INVALID);
4445  assert( col->sbup < SCIP_INVALID);
4446 
4447  col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4448  col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4449  col->sbdownvalid = sbdownvalid[j];
4450  col->sbupvalid = sbupvalid[j];
4451 
4452  down[idx] = col->sbdown;
4453  up[idx] = col->sbup;
4454  if( downvalid != NULL )
4455  downvalid[idx] = col->sbdownvalid;
4456  if( upvalid != NULL )
4457  upvalid[idx] = col->sbupvalid;
4458  }
4459 
4460  /* update strong branching statistics */
4461  if( iter == -1 )
4462  {
4463  /* calculate average iteration number */
4464  iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4465  : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4466  : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4467  : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4468  : 0;
4469  if( iter/2 >= itlim )
4470  iter = 2*itlim;
4471  }
4472  stat->nstrongbranchs += ncols;
4473  stat->nsblpiterations += iter;
4474  if( stat->nnodes == 1 )
4475  {
4476  stat->nrootstrongbranchs += ncols;
4477  stat->nrootsblpiterations += iter;
4478  }
4479  }
4480 
4481  SCIPsetFreeBufferArray(set, &sbupvalid);
4482  SCIPsetFreeBufferArray(set, &sbdownvalid);
4483  SCIPsetFreeBufferArray(set, &sbup);
4484  SCIPsetFreeBufferArray(set, &sbdown);
4485  SCIPsetFreeBufferArray(set, &primsols);
4486  SCIPsetFreeBufferArray(set, &lpipos);
4487  SCIPsetFreeBufferArray(set, &subidx);
4488  SCIPsetFreeBufferArray(set, &subcols);
4489 
4490  /* stop timing */
4491  SCIPclockStop(stat->strongbranchtime, set);
4492 
4493  return SCIP_OKAY;
4494 }
4495 
4496 /** gets last strong branching information available for a column variable;
4497  * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4498  * keep in mind, that the returned old values may have nothing to do with the current LP solution
4499  */
4501  SCIP_COL* col, /**< LP column */
4502  SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4503  SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4504  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4505  * otherwise, it can only be used as an estimate value */
4506  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4507  * otherwise, it can only be used as an estimate value */
4508  SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4509  SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4510  )
4511 {
4512  assert(col != NULL);
4513 
4514  if( down != NULL )
4515  *down = col->sbdown;
4516  if( up != NULL )
4517  *up = col->sbup;
4518  if( downvalid != NULL )
4519  *downvalid = col->sbdownvalid;
4520  if( upvalid != NULL )
4521  *upvalid = col->sbupvalid;
4522  if( solval != NULL )
4523  *solval = col->sbsolval;
4524  if( lpobjval != NULL )
4525  *lpobjval = col->sblpobjval;
4526 }
4527 
4528 /** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4529  * the LP where the strong branching on this column was applied;
4530  * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4531  */
4533  SCIP_COL* col, /**< LP column */
4534  SCIP_STAT* stat /**< dynamic problem statistics */
4535  )
4536 {
4537  assert(col != NULL);
4538  assert(stat != NULL);
4539 
4540  return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->lpcount - stat->nsbdivinglps - col->validsblp);
4541 }
4542 
4543 /** marks a column to be not removable from the LP in the current node because it became obsolete */
4545  SCIP_COL* col, /**< LP column */
4546  SCIP_STAT* stat /**< problem statistics */
4547  )
4548 {
4549  assert(col != NULL);
4550  assert(stat != NULL);
4551  assert(stat->nnodes > 0);
4552 
4553  /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4554  col->obsoletenode = stat->nnodes;
4555 }
4556 
4557 
4558 /*
4559  * Row methods
4560  */
4561 
4562 /** calculates row norms and min/maxidx from scratch, and checks for sorting */
4563 static
4565  SCIP_ROW* row, /**< LP row */
4566  SCIP_SET* set /**< global SCIP settings */
4567  )
4568 {
4569  int i;
4570 
4571  assert(row != NULL);
4572  assert(set != NULL);
4573 
4574  row->sqrnorm = 0.0;
4575  row->sumnorm = 0.0;
4576  row->objprod = 0.0;
4577  row->maxval = 0.0;
4578  row->nummaxval = 1;
4579  row->minval = SCIPsetInfinity(set);
4580  row->numminval = 1;
4581  row->minidx = INT_MAX;
4582  row->maxidx = INT_MIN;
4583  row->validminmaxidx = TRUE;
4584  row->lpcolssorted = TRUE;
4585  row->nonlpcolssorted = TRUE;
4586 
4587  /* check, if row is sorted
4588  * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4589  */
4590  for( i = 0; i < row->nlpcols; ++i )
4591  {
4592  assert(row->cols[i] != NULL);
4593  assert(!SCIPsetIsZero(set, row->vals[i]));
4594  assert(row->cols[i]->lppos >= 0);
4595  assert(row->linkpos[i] >= 0);
4596  assert(row->cols[i]->index == row->cols_index[i]);
4597 
4598  rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4599  if( i > 0 )
4600  {
4601  assert(row->cols[i-1]->index == row->cols_index[i-1]);
4602  row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4603  }
4604  }
4605  for( i = row->nlpcols; i < row->len; ++i )
4606  {
4607  assert(row->cols[i] != NULL);
4608  assert(!SCIPsetIsZero(set, row->vals[i]));
4609  assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4610  assert(row->cols[i]->index == row->cols_index[i]);
4611 
4612  rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4613  if( i > row->nlpcols )
4614  {
4615  assert(row->cols[i-1]->index == row->cols_index[i-1]);
4616  row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4617  }
4618  }
4619 }
4620 
4621 /** calculates min/maxval and min/maxidx from scratch */
4622 static
4624  SCIP_ROW* row, /**< LP row */
4625  SCIP_SET* set /**< global SCIP settings */
4626  )
4627 {
4628  SCIP_COL* col;
4629  SCIP_Real absval;
4630  int i;
4631 
4632  assert(row != NULL);
4633  assert(set != NULL);
4634 
4635  row->maxval = 0.0;
4636  row->nummaxval = 1;
4637  row->minval = SCIPsetInfinity(set);
4638  row->numminval = 1;
4639  row->minidx = INT_MAX;
4640  row->maxidx = INT_MIN;
4641  row->validminmaxidx = TRUE;
4642 
4643  /* calculate maxval, minval, minidx, and maxidx */
4644  for( i = 0; i < row->len; ++i )
4645  {
4646  col = row->cols[i];
4647  assert(col != NULL);
4648  assert(!SCIPsetIsZero(set, row->vals[i]));
4649 
4650  absval = REALABS(row->vals[i]);
4651  assert(!SCIPsetIsZero(set, absval));
4652 
4653  /* update min/maxidx */
4654  row->minidx = MIN(row->minidx, col->index);
4655  row->maxidx = MAX(row->maxidx, col->index);
4656 
4657  /* update maximal and minimal non-zero value */
4658  if( row->nummaxval > 0 )
4659  {
4660  if( SCIPsetIsGT(set, absval, row->maxval) )
4661  {
4662  row->maxval = absval;
4663  row->nummaxval = 1;
4664  }
4665  else if( SCIPsetIsGE(set, absval, row->maxval) )
4666  row->nummaxval++;
4667  }
4668  if( row->numminval > 0 )
4669  {
4670  if( SCIPsetIsLT(set, absval, row->minval) )
4671  {
4672  row->minval = absval;
4673  row->numminval = 1;
4674  }
4675  else if( SCIPsetIsLE(set, absval, row->minval) )
4676  row->numminval++;
4677  }
4678  }
4679 }
4680 
4681 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4682 static
4684  SCIP_Real val, /**< value that should be scaled to an integral value */
4685  SCIP_Real scalar, /**< scalar that should be tried */
4686  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4687  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4688  SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4689  )
4690 {
4691  SCIP_Real sval;
4692  SCIP_Real downval;
4693  SCIP_Real upval;
4694 
4695  assert(mindelta <= 0.0);
4696  assert(maxdelta >= 0.0);
4697 
4698  sval = val * scalar;
4699  downval = floor(sval);
4700  upval = ceil(sval);
4701 
4702  if( SCIPrelDiff(sval, downval) <= maxdelta )
4703  {
4704  if( intval != NULL )
4705  *intval = downval;
4706  return TRUE;
4707  }
4708  else if( SCIPrelDiff(sval, upval) >= mindelta )
4709  {
4710  if( intval != NULL )
4711  *intval = upval;
4712  return TRUE;
4713  }
4714 
4715  return FALSE;
4716 }
4717 
4718 /** scales row with given factor, and rounds coefficients to integers if close enough;
4719  * the constant is automatically moved to the sides;
4720  * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4721  */
4722 static
4724  SCIP_ROW* row, /**< LP row */
4725  BMS_BLKMEM* blkmem, /**< block memory */
4726  SCIP_SET* set, /**< global SCIP settings */
4727  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4728  SCIP_STAT* stat, /**< problem statistics */
4729  SCIP_LP* lp, /**< current LP data */
4730  SCIP_Real scaleval, /**< value to scale row with */
4731  SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4732  * if they are close to integral values? */
4733  SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4734  * upto which the integral is used instead of the scaled real coefficient */
4735  SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4736  * upto which the integral is used instead of the scaled real coefficient */
4737  )
4738 {
4739  SCIP_COL* col;
4740  SCIP_Real val;
4741  SCIP_Real newval;
4742  SCIP_Real intval;
4743  SCIP_Real mindelta;
4744  SCIP_Real maxdelta;
4745  SCIP_Real lb;
4746  SCIP_Real ub;
4747  SCIP_Bool mindeltainf;
4748  SCIP_Bool maxdeltainf;
4749  int oldlen;
4750  int c;
4751 
4752  assert(row != NULL);
4753  assert(row->len == 0 || row->cols != NULL);
4754  assert(row->len == 0 || row->vals != NULL);
4755  assert(SCIPsetIsPositive(set, scaleval));
4756  assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4757  assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4758 
4759  SCIPdebugMessage("scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4760 
4761  mindelta = 0.0;
4762  maxdelta = 0.0;
4763  mindeltainf = FALSE;
4764  maxdeltainf = FALSE;
4765  oldlen = row->len;
4766 
4767  /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4768  * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4769  * this rounding can lead to
4770  */
4771  row->integral = TRUE;
4772 
4773  c = 0;
4774  while( c < row->len )
4775  {
4776  col = row->cols[c];
4777  val = row->vals[c];
4778  assert(!SCIPsetIsZero(set, val));
4779 
4780  /* get local or global bounds for column, depending on the local or global feasibility of the row */
4781  if( row->local )
4782  {
4783  lb = col->lb;
4784  ub = col->ub;
4785  }
4786  else
4787  {
4788  lb = SCIPvarGetLbGlobal(col->var);
4789  ub = SCIPvarGetUbGlobal(col->var);
4790  }
4791 
4792  /* calculate scaled coefficient */
4793  newval = val * scaleval;
4794  if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
4795  && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
4796  {
4797  if( !SCIPsetIsEQ(set, intval, newval) )
4798  {
4799  if( intval < newval )
4800  {
4801  mindelta += (intval - newval)*ub;
4802  maxdelta += (intval - newval)*lb;
4803  mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
4804  maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
4805  }
4806  else
4807  {
4808  mindelta += (intval - newval)*lb;
4809  maxdelta += (intval - newval)*ub;
4810  mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
4811  maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
4812  }
4813  }
4814  newval = intval;
4815  }
4816 
4817  if( !SCIPsetIsEQ(set, val, newval) )
4818  {
4819  /* if column knows of the row, change the corresponding coefficient in the column */
4820  if( row->linkpos[c] >= 0 )
4821  {
4822  assert(col->rows[row->linkpos[c]] == row);
4823  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
4824  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
4825  }
4826 
4827  /* change the coefficient in the row, and update the norms and integrality status */
4828  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
4829 
4830  /* current coefficient has been deleted from the row because it was almost zero */
4831  if( oldlen != row->len )
4832  {
4833  assert(row->len == oldlen - 1);
4834  c--;
4835  oldlen = row->len;
4836  }
4837 
4838  }
4839  else
4840  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
4841 
4842  ++c;
4843  }
4844 
4845  /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
4846  * to not destroy feasibility due to rounding
4847  */
4848  /**@todo ensure that returned cut does not have infinite lhs and rhs */
4849  if( !SCIPsetIsInfinity(set, -row->lhs) )
4850  {
4851  if( mindeltainf )
4852  newval = -SCIPsetInfinity(set);
4853  else
4854  {
4855  newval = (row->lhs - row->constant) * scaleval + mindelta;
4856  if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
4857  newval = SCIPsetSumCeil(set, newval);
4858  }
4859  SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
4860  }
4861  if( !SCIPsetIsInfinity(set, row->rhs) )
4862  {
4863  if( maxdeltainf )
4864  newval = SCIPsetInfinity(set);
4865  else
4866  {
4867  newval = (row->rhs - row->constant) * scaleval + maxdelta;
4868  if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
4869  newval = SCIPsetSumFloor(set, newval);
4870  }
4871  SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
4872  }
4873 
4874  /* clear the row constant */
4875  SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
4876 
4877  SCIPdebugMessage("scaled row <%s> (integral: %u)\n", row->name, row->integral);
4878  debugRowPrint(row);
4879 
4880 #ifdef SCIP_DEBUG
4881  /* check integrality status of row */
4882  for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
4883  {}
4884  assert(row->integral == (c == row->len));
4885 #endif
4886 
4887  /* invalid the activity */
4888  row->validactivitylp = -1;
4889 
4890  return SCIP_OKAY;
4891 }
4892 
4893 /** creates and captures an LP row */
4895  SCIP_ROW** row, /**< pointer to LP row data */
4896  BMS_BLKMEM* blkmem, /**< block memory */
4897  SCIP_SET* set, /**< global SCIP settings */
4898  SCIP_STAT* stat, /**< problem statistics */
4899  SCIP_LP* lp, /**< current LP data */
4900  const char* name, /**< name of row */
4901  int len, /**< number of nonzeros in the row */
4902  SCIP_COL** cols, /**< array with columns of row entries */
4903  SCIP_Real* vals, /**< array with coefficients of row entries */
4904  SCIP_Real lhs, /**< left hand side of row */
4905  SCIP_Real rhs, /**< right hand side of row */
4906  SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
4907  void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
4908  SCIP_Bool local, /**< is row only valid locally? */
4909  SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
4910  SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
4911  )
4912 {
4913  assert(row != NULL);
4914  assert(blkmem != NULL);
4915  assert(stat != NULL);
4916  assert(len >= 0);
4917  assert(len == 0 || (cols != NULL && vals != NULL));
4918  /* note, that the assert tries to avoid numerical troubles in the LP solver.
4919  * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
4920  * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
4921  */
4922  assert(lhs <= rhs);
4923 
4924  SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
4925 
4926  (*row)->integral = TRUE;
4927  if( len > 0 )
4928  {
4929  SCIP_VAR* var;
4930  int i;
4931 
4932  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
4933  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
4934  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
4935  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
4936 
4937  for( i = 0; i < len; ++i )
4938  {
4939  assert(cols[i] != NULL);
4940  assert(!SCIPsetIsZero(set, vals[i]));
4941 
4942  var = cols[i]->var;
4943  (*row)->cols_index[i] = cols[i]->index;
4944  (*row)->linkpos[i] = -1;
4945  if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
4946  {
4947  (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
4948  (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
4949  }
4950  else
4951  {
4952  (*row)->integral = FALSE;
4953  }
4954  }
4955  }
4956  else
4957  {
4958  (*row)->cols = NULL;
4959  (*row)->cols_index = NULL;
4960  (*row)->vals = NULL;
4961  (*row)->linkpos = NULL;
4962  }
4963 
4964  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
4965  (*row)->constant = 0.0;
4966  (*row)->lhs = lhs;
4967  (*row)->rhs = rhs;
4968  (*row)->flushedlhs = -SCIPsetInfinity(set);
4969  (*row)->flushedrhs = SCIPsetInfinity(set);
4970  (*row)->sqrnorm = 0.0;
4971  (*row)->sumnorm = 0.0;
4972  (*row)->objprod = 0.0;
4973  (*row)->maxval = 0.0;
4974  (*row)->minval = SCIPsetInfinity(set);
4975  (*row)->dualsol = 0.0;
4976  (*row)->activity = SCIP_INVALID;
4977  (*row)->dualfarkas = 0.0;
4978  (*row)->pseudoactivity = SCIP_INVALID;
4979  (*row)->minactivity = SCIP_INVALID;
4980  (*row)->maxactivity = SCIP_INVALID;
4981  (*row)->origin = origin;
4982  (*row)->eventfilter = NULL;
4983  (*row)->index = stat->nrowidx++;
4984  (*row)->size = len;
4985  (*row)->len = len;
4986  (*row)->nlpcols = 0;
4987  (*row)->nunlinked = len;
4988  (*row)->nuses = 0;
4989  (*row)->lppos = -1;
4990  (*row)->lpipos = -1;
4991  (*row)->lpdepth = -1;
4992  (*row)->minidx = INT_MAX;
4993  (*row)->maxidx = INT_MIN;
4994  (*row)->nummaxval = 0;
4995  (*row)->numminval = 0;
4996  (*row)->validactivitylp = -1;
4997  (*row)->validpsactivitydomchg = -1;
4998  (*row)->validactivitybdsdomchg = -1;
4999  (*row)->nlpsaftercreation = 0L;
5000  (*row)->activeinlpcounter = 0L;
5001  (*row)->age = 0;
5002  (*row)->rank = 0;
5003  (*row)->obsoletenode = -1;
5004  (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5005  (*row)->lpcolssorted = TRUE;
5006  (*row)->nonlpcolssorted = (len <= 1);
5007  (*row)->delaysort = FALSE;
5008  (*row)->validminmaxidx = FALSE;
5009  (*row)->lhschanged = FALSE;
5010  (*row)->rhschanged = FALSE;
5011  (*row)->coefchanged = FALSE;
5012  (*row)->local = local;
5013  (*row)->modifiable = modifiable;
5014  (*row)->nlocks = 0;
5015  (*row)->origintype = origintype; /*lint !e641*/
5016  (*row)->removable = removable;
5017  (*row)->inglobalcutpool = FALSE;
5018  (*row)->storedsolvals = NULL;
5019 
5020  /* calculate row norms and min/maxidx, and check if row is sorted */
5021  rowCalcNorms(*row, set);
5022 
5023  /* capture the row */
5024  SCIProwCapture(*row);
5025 
5026  /* create event filter */
5027  SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5028 
5029  return SCIP_OKAY;
5030 } /*lint !e715*/
5031 
5032 /** frees an LP row */
5034  SCIP_ROW** row, /**< pointer to LP row */
5035  BMS_BLKMEM* blkmem, /**< block memory */
5036  SCIP_SET* set, /**< global SCIP settings */
5037  SCIP_LP* lp /**< current LP data */
5038  )
5039 {
5040  assert(blkmem != NULL);
5041  assert(row != NULL);
5042  assert(*row != NULL);
5043  assert((*row)->nuses == 0);
5044  assert((*row)->lppos == -1);
5045  assert((*row)->eventfilter != NULL);
5046 
5047  /* remove column indices from corresponding rows */
5048  SCIP_CALL( rowUnlink(*row, set, lp) );
5049 
5050  /* free event filter */
5051  SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5052 
5053  BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5054  BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5055  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5056  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5057  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5058  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5059  BMSfreeBlockMemory(blkmem, row);
5060 
5061  return SCIP_OKAY;
5062 }
5063 
5064 /** output row to file stream */
5066  SCIP_ROW* row, /**< LP row */
5067  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5068  FILE* file /**< output file (or NULL for standard output) */
5069  )
5070 {
5071  int i;
5072 
5073  assert(row != NULL);
5074 
5075  /* print row name */
5076  if( row->name != NULL && row->name[0] != '\0' )
5077  {
5078  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5079  }
5080 
5081  /* print left hand side */
5082  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5083 
5084  /* print coefficients */
5085  if( row->len == 0 )
5086  SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5087  for( i = 0; i < row->len; ++i )
5088  {
5089  assert(row->cols[i] != NULL);
5090  assert(row->cols[i]->var != NULL);
5091  assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5092  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5093  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5094  }
5095 
5096  /* print constant */
5097  if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
5098  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5099 
5100  /* print right hand side */
5101  SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5102 }
5103 
5104 /** increases usage counter of LP row */
5106  SCIP_ROW* row /**< LP row */
5107  )
5108 {
5109  assert(row != NULL);
5110  assert(row->nuses >= 0);
5111  assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5112 
5113  SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5114  row->nuses++;
5115 }
5116 
5117 /** decreases usage counter of LP row, and frees memory if necessary */
5119  SCIP_ROW** row, /**< pointer to LP row */
5120  BMS_BLKMEM* blkmem, /**< block memory */
5121  SCIP_SET* set, /**< global SCIP settings */
5122  SCIP_LP* lp /**< current LP data */
5123  )
5124 {
5125  assert(blkmem != NULL);
5126  assert(row != NULL);
5127  assert(*row != NULL);
5128  assert((*row)->nuses >= 1);
5129  assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5130 
5131  SCIPdebugMessage("release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5132  (*row)->nuses--;
5133  if( (*row)->nuses == 0 )
5134  {
5135  SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5136  }
5137 
5138  *row = NULL;
5139 
5140  return SCIP_OKAY;
5141 }
5142 
5143 /** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5145  SCIP_ROW* row /**< LP row */
5146  )
5147 {
5148  assert(row != NULL);
5149 
5150  /* check, if row is modifiable */
5151  if( !row->modifiable )
5152  {
5153  SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5154  row->nlocks++;
5155  }
5156 }
5157 
5158 /** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5160  SCIP_ROW* row /**< LP row */
5161  )
5162 {
5163  assert(row != NULL);
5164 
5165  /* check, if row is modifiable */
5166  if( !row->modifiable )
5167  {
5168  SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5169  assert(row->nlocks > 0);
5170  row->nlocks--;
5171  }
5172 }
5173 
5174 /** adds a previously non existing coefficient to an LP row */
5176  SCIP_ROW* row, /**< LP row */
5177  BMS_BLKMEM* blkmem, /**< block memory */
5178  SCIP_SET* set, /**< global SCIP settings */
5179  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5180  SCIP_LP* lp, /**< current LP data */
5181  SCIP_COL* col, /**< LP column */
5182  SCIP_Real val /**< value of coefficient */
5183  )
5184 {
5185  assert(lp != NULL);
5186  assert(!lp->diving || row->lppos == -1);
5187 
5188  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5189 
5190  checkLinks(lp);
5191 
5192  return SCIP_OKAY;
5193 }
5194 
5195 /** deletes coefficient from row */
5197  SCIP_ROW* row, /**< row to be changed */
5198  BMS_BLKMEM* blkmem, /**< block memory */
5199  SCIP_SET* set, /**< global SCIP settings */
5200  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5201  SCIP_LP* lp, /**< current LP data */
5202  SCIP_COL* col /**< coefficient to be deleted */
5203  )
5204 {
5205  int pos;
5206 
5207  assert(row != NULL);
5208  assert(!row->delaysort);
5209  assert(lp != NULL);
5210  assert(!lp->diving || row->lppos == -1);
5211  assert(col != NULL);
5212  assert(col->var != NULL);
5213 
5214  /* search the position of the column in the row's col vector */
5215  pos = rowSearchCoef(row, col);
5216  if( pos == -1 )
5217  {
5218  SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5219  return SCIP_INVALIDDATA;
5220  }
5221  assert(0 <= pos && pos < row->len);
5222  assert(row->cols[pos] == col);
5223  assert(row->cols_index[pos] == col->index);
5224 
5225  /* if column knows of the row, remove the row from the column's row vector */
5226  if( row->linkpos[pos] >= 0 )
5227  {
5228  assert(col->rows[row->linkpos[pos]] == row);
5229  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5230  SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5231  }
5232 
5233  /* delete the column from the row's col vector */
5234  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5235 
5236  checkLinks(lp);
5237 
5238  return SCIP_OKAY;
5239 }
5240 
5241 /** changes or adds a coefficient to an LP row */
5243  SCIP_ROW* row, /**< LP row */
5244  BMS_BLKMEM* blkmem, /**< block memory */
5245  SCIP_SET* set, /**< global SCIP settings */
5246  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5247  SCIP_LP* lp, /**< current LP data */
5248  SCIP_COL* col, /**< LP column */
5249  SCIP_Real val /**< value of coefficient */
5250  )
5251 {
5252  int pos;
5253 
5254  assert(row != NULL);
5255  assert(!row->delaysort);
5256  assert(lp != NULL);
5257  assert(!lp->diving || row->lppos == -1);
5258  assert(col != NULL);
5259 
5260  /* search the position of the column in the row's col vector */
5261  pos = rowSearchCoef(row, col);
5262 
5263  /* check, if column already exists in the row's col vector */
5264  if( pos == -1 )
5265  {
5266  /* add previously not existing coefficient */
5267  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5268  }
5269  else
5270  {
5271  /* modify already existing coefficient */
5272  assert(0 <= pos && pos < row->len);
5273  assert(row->cols[pos] == col);
5274  assert(row->cols_index[pos] == col->index);
5275 
5276  /* if column knows of the row, change the corresponding coefficient in the column */
5277  if( row->linkpos[pos] >= 0 )
5278  {
5279  assert(col->rows[row->linkpos[pos]] == row);
5280  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5281  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5282  }
5283 
5284  /* change the coefficient in the row */
5285  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5286  }
5287 
5288  checkLinks(lp);
5289 
5290  return SCIP_OKAY;
5291 }
5292 
5293 /** increases value of an existing or non-existing coefficient in an LP row */
5295  SCIP_ROW* row, /**< LP row */
5296  BMS_BLKMEM* blkmem, /**< block memory */
5297  SCIP_SET* set, /**< global SCIP settings */
5298  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5299  SCIP_LP* lp, /**< current LP data */
5300  SCIP_COL* col, /**< LP column */
5301  SCIP_Real incval /**< value to add to the coefficient */
5302  )
5303 {
5304  int pos;
5305 
5306  assert(row != NULL);
5307  assert(lp != NULL);
5308  assert(!lp->diving || row->lppos == -1);
5309  assert(col != NULL);
5310 
5311  if( SCIPsetIsZero(set, incval) )
5312  return SCIP_OKAY;
5313 
5314  /* search the position of the column in the row's col vector */
5315  pos = rowSearchCoef(row, col);
5316 
5317  /* check, if column already exists in the row's col vector */
5318  if( pos == -1 )
5319  {
5320  /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5321  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5322  }
5323  else
5324  {
5325  /* modify already existing coefficient */
5326  assert(0 <= pos && pos < row->len);
5327  assert(row->cols[pos] == col);
5328  assert(row->cols_index[pos] == col->index);
5329 
5330  /* if column knows of the row, change the corresponding coefficient in the column */
5331  if( row->linkpos[pos] >= 0 )
5332  {
5333  assert(col->rows[row->linkpos[pos]] == row);
5334  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5335  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5336  }
5337 
5338  /* change the coefficient in the row */
5339  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5340  }
5341 
5342  checkLinks(lp);
5343 
5344  return SCIP_OKAY;
5345 }
5346 
5347 /** changes constant value of a row */
5349  SCIP_ROW* row, /**< LP row */
5350  BMS_BLKMEM* blkmem, /**< block memory */
5351  SCIP_SET* set, /**< global SCIP settings */
5352  SCIP_STAT* stat, /**< problem statistics */
5353  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5354  SCIP_LP* lp, /**< current LP data */
5355  SCIP_Real constant /**< new constant value */
5356  )
5357 {
5358  assert(row != NULL);
5359  assert(row->lhs <= row->rhs);
5360  assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5361  assert(stat != NULL);
5362  assert(lp != NULL);
5363  assert(!lp->diving || row->lppos == -1);
5364 
5365  if( !SCIPsetIsEQ(set, constant, row->constant) )
5366  {
5367  SCIP_Real oldconstant;
5368 
5369  if( row->validpsactivitydomchg == stat->domchgcount )
5370  {
5371  assert(row->pseudoactivity < SCIP_INVALID);
5372  row->pseudoactivity += constant - row->constant;
5373  }
5374  if( row->validactivitybdsdomchg == stat->domchgcount )
5375  {
5376  assert(row->minactivity < SCIP_INVALID);
5377  assert(row->maxactivity < SCIP_INVALID);
5378  row->minactivity += constant - row->constant;
5379  row->maxactivity += constant - row->constant;
5380  }
5381 
5382  if( !SCIPsetIsInfinity(set, -row->lhs) )
5383  {
5384  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5385  }
5386  if( !SCIPsetIsInfinity(set, row->rhs) )
5387  {
5388  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5389  }
5390 
5391  oldconstant = row->constant;
5392 
5393  row->constant = constant;
5394 
5395  /* issue row constant changed event */
5396  SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5397  }
5398 
5399  return SCIP_OKAY;
5400 }
5401 
5402 /** add constant value to a row */
5404  SCIP_ROW* row, /**< LP row */
5405  BMS_BLKMEM* blkmem, /**< block memory */
5406  SCIP_SET* set, /**< global SCIP settings */
5407  SCIP_STAT* stat, /**< problem statistics */
5408  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5409  SCIP_LP* lp, /**< current LP data */
5410  SCIP_Real addval /**< constant value to add to the row */
5411  )
5412 {
5413  assert(row != NULL);
5414  assert(row->lhs <= row->rhs);
5415  assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5416  assert(stat != NULL);
5417  assert(lp != NULL);
5418  assert(!lp->diving || row->lppos == -1);
5419 
5420  if( !SCIPsetIsZero(set, addval) )
5421  {
5422  SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5423  }
5424 
5425  return SCIP_OKAY;
5426 }
5427 
5428 /** changes left hand side of LP row */
5430  SCIP_ROW* row, /**< LP row */
5431  BMS_BLKMEM* blkmem, /**< block memory */
5432  SCIP_SET* set, /**< global SCIP settings */
5433  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5434  SCIP_LP* lp, /**< current LP data */
5435  SCIP_Real lhs /**< new left hand side */
5436  )
5437 {
5438  assert(row != NULL);
5439  assert(lp != NULL);
5440 
5441  if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5442  {
5443  SCIP_Real oldlhs;
5444 
5445  oldlhs = row->lhs;
5446 
5447  row->lhs = lhs;
5448  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5449 
5450  if( !lp->diving )
5451  {
5452  /* issue row side changed event */
5453  SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5454  }
5455  }
5456 
5457  return SCIP_OKAY;
5458 }
5459 
5460 /** changes right hand side of LP row */
5462  SCIP_ROW* row, /**< LP row */
5463  BMS_BLKMEM* blkmem, /**< block memory */
5464  SCIP_SET* set, /**< global SCIP settings */
5465  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5466  SCIP_LP* lp, /**< current LP data */
5467  SCIP_Real rhs /**< new right hand side */
5468  )
5469 {
5470  assert(row != NULL);
5471  assert(lp != NULL);
5472 
5473  if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5474  {
5475  SCIP_Real oldrhs;
5476 
5477  oldrhs = row->rhs;
5478 
5479  row->rhs = rhs;
5480  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5481 
5482  if( !lp->diving )
5483  {
5484  /* issue row side changed event */
5485  SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5486  }
5487  }
5488 
5489  return SCIP_OKAY;
5490 }
5491 
5492 /** changes the local flag of LP row */
5494  SCIP_ROW* row, /**< LP row */
5495  SCIP_Bool local /**< new value for local flag */
5496  )
5497 {
5498  assert(row != NULL);
5499 
5500  row->local = local;
5501 
5502  return SCIP_OKAY;
5503 }
5504 
5505 /** additional scalars that are tried in integrality scaling */
5506 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5507 static const int nscalars = 9;
5508 
5509 /** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5511  SCIP_ROW* row, /**< LP row */
5512  SCIP_SET* set, /**< global SCIP settings */
5513  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5514  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5515  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5516  SCIP_Real maxscale, /**< maximal allowed scalar */
5517  SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5518  SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5519  SCIP_Bool* success /**< stores whether returned value is valid */
5520  )
5521 {
5522 #ifndef NDEBUG
5523  SCIP_COL* col;
5524 #endif
5525  SCIP_Longint gcd;
5526  SCIP_Longint scm;
5527  SCIP_Longint nominator;
5528  SCIP_Longint denominator;
5529  SCIP_Real val;
5530  SCIP_Real absval;
5531  SCIP_Real minval;
5532  SCIP_Real scaleval;
5533  SCIP_Real twomultval;
5534  SCIP_Bool scalable;
5535  SCIP_Bool twomult;
5536  SCIP_Bool rational;
5537  int c;
5538  int s;
5539 
5540  /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5541  assert(row != NULL);
5542  assert(row->len == 0 || row->cols != NULL);
5543  assert(row->len == 0 || row->cols_index != NULL);
5544  assert(row->len == 0 || row->vals != NULL);
5545  assert(maxdnom >= 1);
5546  assert(mindelta < 0.0);
5547  assert(maxdelta > 0.0);
5548  assert(success != NULL);
5549 
5550  SCIPdebugMessage("trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5551  SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5552 
5553  if( intscalar != NULL )
5554  *intscalar = SCIP_INVALID;
5555  *success = FALSE;
5556 
5557  /* get minimal absolute non-zero value */
5558  minval = SCIP_REAL_MAX;
5559  for( c = 0; c < row->len; ++c )
5560  {
5561 #ifndef NDEBUG
5562  col = row->cols[c];
5563  assert(col != NULL);
5564  assert(col->var != NULL);
5565  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
5566  assert(SCIPvarGetCol(col->var) == col);
5567 #endif
5568  val = row->vals[c];
5569  assert(!SCIPsetIsZero(set, val));
5570 
5571  if( val < mindelta || val > maxdelta )
5572  {
5573  absval = REALABS(val);
5574  minval = MIN(minval, absval);
5575  }
5576  }
5577  if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5578  {
5579  /* all coefficients are zero (inside tolerances) */
5580  if( intscalar != NULL )
5581  *intscalar = 1.0;
5582  *success = TRUE;
5583  SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
5584 
5585  return SCIP_OKAY;
5586  }
5587  assert(minval > MIN(-mindelta, maxdelta));
5588  assert(SCIPsetIsPositive(set, minval));
5589  assert(!SCIPsetIsInfinity(set, minval));
5590 
5591  /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5592  * and a power of 2
5593  */
5594  scaleval = 1.0/minval;
5595  scalable = (scaleval <= maxscale);
5596  for( c = 0; c < row->len && scalable; ++c )
5597  {
5598  /* don't look at continuous variables, if we don't have to */
5599  if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5600  continue;
5601 
5602  /* check, if the coefficient can be scaled with a simple scalar */
5603  val = row->vals[c];
5604  absval = REALABS(val);
5605  while( scaleval <= maxscale
5606  && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5607  {
5608  for( s = 0; s < nscalars; ++s )
5609  {
5610  if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5611  {
5612  scaleval *= scalars[s];
5613  break;
5614  }
5615  }
5616  if( s >= nscalars )
5617  scaleval *= 2.0;
5618  }
5619  scalable = (scaleval <= maxscale);
5620  SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
5621  val, scaleval, val*scaleval, scalable);
5622  }
5623  if( scalable )
5624  {
5625  /* make row coefficients integral by dividing them by the smallest coefficient
5626  * (and multiplying them with a power of 2)
5627  */
5628  assert(scaleval <= maxscale);
5629  if( intscalar != NULL )
5630  *intscalar = scaleval;
5631  *success = TRUE;
5632  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5633 
5634  return SCIP_OKAY;
5635  }
5636 
5637  /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5638  twomultval = 1.0;
5639  twomult = (twomultval <= maxscale);
5640  for( c = 0; c < row->len && twomult; ++c )
5641  {
5642  /* don't look at continuous variables, if we don't have to */
5643  if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5644  continue;
5645 
5646  /* check, if the coefficient can be scaled with a simple scalar */
5647  val = row->vals[c];
5648  absval = REALABS(val);
5649  while( twomultval <= maxscale
5650  && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5651  {
5652  for( s = 0; s < nscalars; ++s )
5653  {
5654  if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5655  {
5656  twomultval *= scalars[s];
5657  break;
5658  }
5659  }
5660  if( s >= nscalars )
5661  twomultval *= 2.0;
5662  }
5663  twomult = (twomultval <= maxscale);
5664  SCIPdebugMessage(" -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5665  val, twomultval, val*twomultval, twomult);
5666  }
5667  if( twomult )
5668  {
5669  /* make row coefficients integral by multiplying them with a power of 2 */
5670  assert(twomultval <= maxscale);
5671  if( intscalar != NULL )
5672  *intscalar = twomultval;
5673  *success = TRUE;
5674  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5675 
5676  return SCIP_OKAY;
5677  }
5678 
5679  /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5680  * and the smallest common multiple of the denominators
5681  */
5682  gcd = 1;
5683  scm = 1;
5684  rational = (maxdnom > 1);
5685 
5686  /* first coefficient (to initialize gcd) */
5687  for( c = 0; c < row->len && rational; ++c )
5688  {
5689  if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5690  {
5691  val = row->vals[c];
5692  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5693  if( rational && nominator != 0 )
5694  {
5695  assert(denominator > 0);
5696  gcd = ABS(nominator);
5697  scm = denominator;
5698  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5699  SCIPdebugMessage(" -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5700  val, nominator, denominator, gcd, scm, rational);
5701  break;
5702  }
5703  }
5704  }
5705 
5706  /* remaining coefficients */
5707  for( ++c; c < row->len && rational; ++c )
5708  {
5709  if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5710  {
5711  val = row->vals[c];
5712  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5713  if( rational && nominator != 0 )
5714  {
5715  assert(denominator > 0);
5716  gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5717  scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5718  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5719  SCIPdebugMessage(" -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5720  val, nominator, denominator, gcd, scm, rational);
5721  }
5722  }
5723  }
5724 
5725  if( rational )
5726  {
5727  /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5728  assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5729  if( intscalar != NULL )
5730  *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5731  *success = TRUE;
5732  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5733  (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5734  }
5735  else
5736  {
5737  assert(!(*success));
5738  SCIPdebugMessage(" -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5739  }
5740 
5741  return SCIP_OKAY;
5742 }
5743 
5744 /** tries to scale row, s.t. all coefficients become integral */
5746  SCIP_ROW* row, /**< LP row */
5747  BMS_BLKMEM* blkmem, /**< block memory */
5748  SCIP_SET* set, /**< global SCIP settings */
5749  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5750  SCIP_STAT* stat, /**< problem statistics */
5751  SCIP_LP* lp, /**< current LP data */
5752  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5753  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5754  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5755  SCIP_Real maxscale, /**< maximal value to scale row with */
5756  SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5757  SCIP_Bool* success /**< stores whether row could be made rational */
5758  )
5759 {
5760  SCIP_Real intscalar;
5761 
5762  assert(success != NULL);
5763 
5764  /* calculate scalar to make coefficients integral */
5765  SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
5766  &intscalar, success) );
5767 
5768  if( *success )
5769  {
5770  /* scale the row */
5771  SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
5772  }
5773 
5774  return SCIP_OKAY;
5775 }
5776 
5777 /** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
5778  * higher ones
5779  */
5781  SCIP_ROW* row /**< row to be sorted */
5782  )
5783 {
5784  assert(row != NULL);
5785 
5786  /* sort LP columns */
5787  rowSortLP(row);
5788 
5789  /* sort non-LP columns */
5790  rowSortNonLP(row);
5791 
5792 #ifdef SCIP_MORE_DEBUG
5793  /* check the sorting */
5794  {
5795  int c;
5796  if( !row->delaysort )
5797  {
5798  for( c = 1; c < row->nlpcols; ++c )
5799  assert(row->cols[c]->index >= row->cols[c-1]->index);
5800  for( c = row->nlpcols + 1; c < row->len; ++c )
5801  assert(row->cols[c]->index >= row->cols[c-1]->index);
5802  }
5803  }
5804 #endif
5805 }
5806 
5807 /** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
5808  * zero entries from row
5809  * the row must not be linked to the columns; otherwise, we would need to update the columns as
5810  * well, which is too expensive
5811  */
5812 static
5814  SCIP_ROW* row, /**< row to be sorted */
5815  SCIP_SET* set /**< global SCIP settings */
5816  )
5817 {
5818  assert(row != NULL);
5819  assert(!row->delaysort);
5820  assert(row->nunlinked == row->len);
5821  assert(row->nlpcols == 0);
5822 
5823  SCIPdebugMessage("merging row <%s>\n", row->name);
5824 
5825  /* do nothing on empty rows; if row is sorted, nothing has to be done */
5826  if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
5827  {
5828  SCIP_COL** cols;
5829  int* cols_index;
5830  SCIP_Real* vals;
5831  int s;
5832  int t;
5833 
5834  /* make sure, the row is sorted */
5835  SCIProwSort(row);
5836  assert(row->lpcolssorted);
5837  assert(row->nonlpcolssorted);
5838 
5839  /* merge equal columns, thereby recalculating whether the row's activity is always integral */
5840  cols = row->cols;
5841  cols_index = row->cols_index;
5842  vals = row->vals;
5843  assert(cols != NULL);
5844  assert(cols_index != NULL);
5845  assert(vals != NULL);
5846 
5847  t = 0;
5848  row->integral = TRUE;
5849  assert(!SCIPsetIsZero(set, vals[0]));
5850  assert(row->linkpos[0] == -1);
5851 
5852  for( s = 1; s < row->len; ++s )
5853  {
5854  assert(!SCIPsetIsZero(set, vals[s]));
5855  assert(row->linkpos[s] == -1);
5856 
5857  if( cols[s] == cols[t] )
5858  {
5859  /* merge entries with equal column */
5860  vals[t] += vals[s];
5861  }
5862  else
5863  {
5864  /* go to the next entry, overwriting current entry if coefficient is zero */
5865  if( !SCIPsetIsZero(set, vals[t]) )
5866  {
5867  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
5868  vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
5869 
5870  row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
5871  t++;
5872  }
5873  cols[t] = cols[s];
5874  cols_index[t] = cols_index[s];
5875  vals[t] = vals[s];
5876  }
5877  }
5878  if( !SCIPsetIsZero(set, vals[t]) )
5879  {
5880  row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
5881  t++;
5882  }
5883  assert(s == row->len);
5884  assert(t <= row->len);
5885 
5886  row->len = t;
5887  row->nunlinked = t;
5888 
5889  /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
5890  if( t < s )
5891  rowCalcNorms(row, set);
5892  }
5893 
5894 #ifndef NDEBUG
5895  /* check for double entries */
5896  {
5897  int i;
5898  int j;
5899 
5900  for( i = 0; i < row->len; ++i )
5901  {
5902  assert(row->cols[i] != NULL);
5903  assert(row->cols[i]->index == row->cols_index[i]);
5904  for( j = i+1; j < row->len; ++j )
5905  assert(row->cols[i] != row->cols[j]);
5906  }
5907  }
5908 #endif
5909 }
5910 
5911 /** enables delaying of row sorting */
5913  SCIP_ROW* row /**< LP row */
5914  )
5915 {
5916  assert(row != NULL);
5917  assert(!row->delaysort);
5918 
5919  row->delaysort = TRUE;
5920 }
5921 
5922 /** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
5924  SCIP_ROW* row, /**< LP row */
5925  SCIP_SET* set /**< global SCIP settings */
5926  )
5927 {
5928  assert(row != NULL);
5929  assert(row->delaysort);
5930 
5931  row->delaysort = FALSE;
5932  rowMerge(row, set);
5933 }
5934 
5935 /** recalculates the current activity of a row */
5937  SCIP_ROW* row, /**< LP row */
5938  SCIP_STAT* stat /**< problem statistics */
5939  )
5940 {
5941  SCIP_COL* col;
5942  int c;
5943 
5944  assert(row != NULL);
5945  assert(stat != NULL);
5946 
5947  row->activity = row->constant;
5948  for( c = 0; c < row->nlpcols; ++c )
5949  {
5950  col = row->cols[c];
5951  assert(col != NULL);
5952  assert(col->primsol < SCIP_INVALID);
5953  assert(col->lppos >= 0);
5954  assert(row->linkpos[c] >= 0);
5955  row->activity += row->vals[c] * col->primsol;
5956  }
5957 
5958  if( row->nunlinked > 0 )
5959  {
5960  for( c = row->nlpcols; c < row->len; ++c )
5961  {
5962  col = row->cols[c];
5963  assert(col != NULL);
5964  assert(col->lppos >= 0 || col->primsol == 0.0);
5965  assert(col->lppos == -1 || row->linkpos[c] == -1);
5966  if( col->lppos >= 0 )
5967  row->activity += row->vals[c] * col->primsol;
5968  }
5969  }
5970 #ifndef NDEBUG
5971  else
5972  {
5973  for( c = row->nlpcols; c < row->len; ++c )
5974  {
5975  col = row->cols[c];
5976  assert(col != NULL);
5977  assert(col->primsol == 0.0);
5978  assert(col->lppos == -1);
5979  assert(row->linkpos[c] >= 0);
5980  }
5981  }
5982 #endif
5983 
5984  row->validactivitylp = stat->lpcount;
5985 }
5986 
5987 /** returns the activity of a row in the current LP solution */
5989  SCIP_ROW* row, /**< LP row */
5990  SCIP_SET* set, /**< global SCIP settings */
5991  SCIP_STAT* stat, /**< problem statistics */
5992  SCIP_LP* lp /**< current LP data */
5993  )
5994 {
5995  SCIP_Real inf;
5996  SCIP_Real activity;
5997 
5998  assert(row != NULL);
5999  assert(stat != NULL);
6000  assert(lp != NULL);
6001  assert(row->validactivitylp <= stat->lpcount);
6002  assert(lp->validsollp == stat->lpcount);
6003 
6004  if( row->validactivitylp != stat->lpcount )
6005  SCIProwRecalcLPActivity(row, stat);
6006  assert(row->validactivitylp == stat->lpcount);
6007  assert(row->activity < SCIP_INVALID);
6008 
6009  activity = row->activity;
6010  inf = SCIPsetInfinity(set);
6011  activity = MAX(activity, -inf);
6012  activity = MIN(activity, +inf);
6013 
6014  return activity;
6015 }
6016 
6017 /** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6019  SCIP_ROW* row, /**< LP row */
6020  SCIP_SET* set, /**< global SCIP settings */
6021  SCIP_STAT* stat, /**< problem statistics */
6022  SCIP_LP* lp /**< current LP data */
6023  )
6024 {
6025  SCIP_Real activity;
6026 
6027  assert(row != NULL);
6028 
6029  activity = SCIProwGetLPActivity(row, set, stat, lp);
6030 
6031  return MIN(row->rhs - activity, activity - row->lhs);
6032 }
6033 
6034 /** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6035  *
6036  * @todo Implement calculation of activities similar to LPs.
6037  */
6039  SCIP_ROW* row, /**< LP row */
6040  SCIP_SET* set, /**< global SCIP settings */
6041  SCIP_STAT* stat /**< problem statistics */
6042  )
6043 {
6044  SCIP_Real inf;
6045  SCIP_Real activity;
6046  SCIP_COL* col;
6047  int c;
6048 
6049  assert( row != NULL );
6050  assert( stat != NULL );
6051 
6052  activity = row->constant;
6053  for (c = 0; c < row->nlpcols; ++c)
6054  {
6055  col = row->cols[c];
6056  assert( col != NULL );
6057  assert( col->lppos >= 0 );
6058  assert( col->var != NULL );
6059  assert( row->linkpos[c] >= 0 );
6060  activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6061  }
6062 
6063  if ( row->nunlinked > 0 )
6064  {
6065  for (c = row->nlpcols; c < row->len; ++c)
6066  {
6067  col = row->cols[c];
6068  assert( col != NULL );
6069  assert( col->lppos == -1 || row->linkpos[c] == -1 );
6070  if ( col->lppos >= 0 )
6071  {
6072  assert( col->var != NULL );
6073  activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6074  }
6075  }
6076  }
6077 #ifndef NDEBUG
6078  else
6079  {
6080  for (c = row->nlpcols; c < row->len; ++c)
6081  {
6082  col = row->cols[c];
6083  assert( col != NULL );
6084  assert( col->lppos == -1 );
6085  assert( row->linkpos[c] >= 0 );
6086  }
6087  }
6088 #endif
6089  inf = SCIPsetInfinity(set);
6090  activity = MAX(activity, -inf);
6091  activity = MIN(activity, +inf);
6092 
6093  return MIN(row->rhs - activity, activity - row->lhs);
6094 }
6095 
6096 /** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6097  *
6098  * @todo Implement calculation of activities similar to LPs.
6099  */
6101  SCIP_ROW* row, /**< LP row */
6102  SCIP_SET* set, /**< global SCIP settings */
6103  SCIP_STAT* stat /**< problem statistics */
6104  )
6105 {
6106  SCIP_Real inf;
6107  SCIP_Real activity;
6108  SCIP_COL* col;
6109  int c;
6110 
6111  assert( row != NULL );
6112  assert( stat != NULL );
6113 
6114  activity = row->constant;
6115  for (c = 0; c < row->nlpcols; ++c)
6116  {
6117  col = row->cols[c];
6118  assert( col != NULL );
6119  assert( col->lppos >= 0 );
6120  assert( col->var != NULL );
6121  assert( row->linkpos[c] >= 0 );
6122  activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6123  }
6124 
6125  if ( row->nunlinked > 0 )
6126  {
6127  for (c = row->nlpcols; c < row->len; ++c)
6128  {
6129  col = row->cols[c];
6130  assert( col != NULL );
6131  assert( col->lppos == -1 || row->linkpos[c] == -1 );
6132  if ( col->lppos >= 0 )
6133  {
6134  assert( col->var != NULL );
6135  activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6136  }
6137  }
6138  }
6139 #ifndef NDEBUG
6140  else
6141  {
6142  for (c = row->nlpcols; c < row->len; ++c)
6143  {
6144  col = row->cols[c];
6145  assert( col != NULL );
6146  assert( col->lppos == -1 );
6147  assert( row->linkpos[c] >= 0 );
6148  }
6149  }
6150 #endif
6151  inf = SCIPsetInfinity(set);
6152  activity = MAX(activity, -inf);
6153  activity = MIN(activity, +inf);
6154 
6155  return MIN(row->rhs - activity, activity - row->lhs);
6156 }
6157 
6158 /** calculates the current pseudo activity of a row */
6160  SCIP_ROW* row, /**< row data */
6161  SCIP_STAT* stat /**< problem statistics */
6162  )
6163 {
6164  SCIP_COL* col;
6165  int i;
6166 
6167  assert(row != NULL);
6168  assert(stat != NULL);
6169 
6170  row->pseudoactivity = row->constant;
6171  for( i = 0; i < row->len; ++i )
6172  {
6173  col = row->cols[i];
6174  assert(col != NULL);
6175  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6176  assert(col->var != NULL);
6177  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
6178 
6179  row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6180  }
6181  row->validpsactivitydomchg = stat->domchgcount;
6182  assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6183 }
6184 
6185 /** returns the pseudo activity of a row in the current pseudo solution */
6187  SCIP_ROW* row, /**< LP row */
6188  SCIP_SET* set, /**< global SCIP settings */
6189  SCIP_STAT* stat /**< problem statistics */
6190  )
6191 {
6192  SCIP_Real inf;
6193  SCIP_Real activity;
6194 
6195  assert(row != NULL);
6196  assert(stat != NULL);
6197  assert(row->validpsactivitydomchg <= stat->domchgcount);
6198 
6199  /* check, if pseudo activity has to be calculated */
6200  if( row->validpsactivitydomchg != stat->domchgcount )
6201  SCIProwRecalcPseudoActivity(row, stat);
6202  assert(row->validpsactivitydomchg == stat->domchgcount);
6203  assert(row->pseudoactivity < SCIP_INVALID);
6204 
6205  activity = row->pseudoactivity;
6206  inf = SCIPsetInfinity(set);
6207  activity = MAX(activity, -inf);
6208  activity = MIN(activity, +inf);
6209 
6210  return activity;
6211 }
6212 
6213 /** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6215  SCIP_ROW* row, /**< LP row */
6216  SCIP_SET* set, /**< global SCIP settings */
6217  SCIP_STAT* stat /**< problem statistics */
6218  )
6219 {
6220  SCIP_Real pseudoactivity;
6221 
6222  assert(row != NULL);
6223 
6224  pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6225 
6226  return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6227 }
6228 
6229 /** returns the activity of a row for a given solution */
6231  SCIP_ROW* row, /**< LP row */
6232  SCIP_SET* set, /**< global SCIP settings */
6233  SCIP_STAT* stat, /**< problem statistics data */
6234  SCIP_SOL* sol /**< primal CIP solution */
6235  )
6236 {
6237  SCIP_COL* col;
6238  SCIP_Real inf;
6239  SCIP_Real activity;
6240  SCIP_Real solval;
6241  int i;
6242 
6243  assert(row != NULL);
6244 
6245  activity = row->constant;
6246  for( i = 0; i < row->len; ++i )
6247  {
6248  col = row->cols[i];
6249  assert(col != NULL);
6250  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6251  solval = SCIPsolGetVal(sol, set, stat, col->var);
6252  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6253  {
6254  if( SCIPsetIsInfinity(set, -row->lhs) )
6255  solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6256  else if( SCIPsetIsInfinity(set, row->rhs) )
6257  solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6258  else
6259  solval = (col->lb + col->ub)/2.0;
6260  }
6261  activity += row->vals[i] * solval;
6262  }
6263 
6264  inf = SCIPsetInfinity(set);
6265  activity = MAX(activity, -inf);
6266  activity = MIN(activity, +inf);
6267 
6268  return activity;
6269 }
6270 
6271 /** returns the feasibility of a row for the given solution */
6273  SCIP_ROW* row, /**< LP row */
6274  SCIP_SET* set, /**< global SCIP settings */
6275  SCIP_STAT* stat, /**< problem statistics data */
6276  SCIP_SOL* sol /**< primal CIP solution */
6277  )
6278 {
6279  SCIP_Real activity;
6280 
6281  assert(row != NULL);
6282 
6283  activity = SCIProwGetSolActivity(row, set, stat, sol);
6284 
6285  return MIN(row->rhs - activity, activity - row->lhs);
6286 }
6287 
6288 /** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6289 static
6291  SCIP_ROW* row, /**< row data */
6292  SCIP_SET* set, /**< global SCIP settings */
6293  SCIP_STAT* stat /**< problem statistics data */
6294  )
6295 {
6296  SCIP_COL* col;
6297  SCIP_Real val;
6298  SCIP_Bool mininfinite;
6299  SCIP_Bool maxinfinite;
6300  int i;
6301 
6302  assert(row != NULL);
6303  assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6304  assert(stat != NULL);
6305 
6306  /* calculate activity bounds */
6307  mininfinite = FALSE;
6308  maxinfinite = FALSE;
6309  row->minactivity = row->constant;
6310  row->maxactivity = row->constant;
6311  for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6312  {
6313  col = row->cols[i];
6314  assert(col != NULL);
6315  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6316  val = row->vals[i];
6317  if( val >= 0.0 )
6318  {
6319  mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6320  maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6321  if( !mininfinite )
6322  row->minactivity += val * col->lb;
6323  if( !maxinfinite )
6324  row->maxactivity += val * col->ub;
6325  }
6326  else
6327  {
6328  mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6329  maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6330  if( !mininfinite )
6331  row->minactivity += val * col->ub;
6332  if( !maxinfinite )
6333  row->maxactivity += val * col->lb;
6334  }
6335  }
6336 
6337  if( mininfinite )
6338  row->minactivity = -SCIPsetInfinity(set);
6339  if( maxinfinite )
6340  row->maxactivity = SCIPsetInfinity(set);
6341  row->validactivitybdsdomchg = stat->domchgcount;
6342 
6343  assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIP_DEFAULT_SUMEPSILON
6345  assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIP_DEFAULT_SUMEPSILON
6347 }
6348 
6349 /** returns the minimal activity of a row w.r.t. the columns' bounds */
6351  SCIP_ROW* row, /**< LP row */
6352  SCIP_SET* set, /**< global SCIP settings */
6353  SCIP_STAT* stat /**< problem statistics data */
6354  )
6355 {
6356  assert(row != NULL);
6357  assert(stat != NULL);
6358  assert(row->validactivitybdsdomchg <= stat->domchgcount);
6359 
6360  /* check, if activity bounds has to be calculated */
6361  if( row->validactivitybdsdomchg != stat->domchgcount )
6362  rowCalcActivityBounds(row, set, stat);
6363  assert(row->validactivitybdsdomchg == stat->domchgcount);
6364  assert(row->minactivity < SCIP_INVALID);
6365  assert(row->maxactivity < SCIP_INVALID);
6366 
6367  return row->minactivity;
6368 }
6369 
6370 /** returns the maximal activity of a row w.r.t. the columns' bounds */
6372  SCIP_ROW* row, /**< LP row */
6373  SCIP_SET* set, /**< global SCIP settings */
6374  SCIP_STAT* stat /**< problem statistics data */
6375  )
6376 {
6377  assert(row != NULL);
6378  assert(stat != NULL);
6379  assert(row->validactivitybdsdomchg <= stat->domchgcount);
6380 
6381  /* check, if activity bounds has to be calculated */
6382  if( row->validactivitybdsdomchg != stat->domchgcount )
6383  rowCalcActivityBounds(row, set, stat);
6384  assert(row->validactivitybdsdomchg == stat->domchgcount);
6385  assert(row->minactivity < SCIP_INVALID);
6386  assert(row->maxactivity < SCIP_INVALID);
6387 
6388  return row->maxactivity;
6389 }
6390 
6391 /** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6393  SCIP_ROW* row, /**< LP row */
6394  SCIP_SET* set, /**< global SCIP settings */
6395  SCIP_STAT* stat /**< problem statistics data */
6396  )
6397 {
6398  assert(row != NULL);
6399 
6400  if( row->modifiable )
6401  return FALSE;
6402  if( !SCIPsetIsInfinity(set, -row->lhs) )
6403  {
6404  SCIP_Real minactivity;
6405 
6406  minactivity = SCIProwGetMinActivity(row, set, stat);
6407  if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6408  return FALSE;
6409  }
6410  if( !SCIPsetIsInfinity(set, row->rhs) )
6411  {
6412  SCIP_Real maxactivity;
6413 
6414  maxactivity = SCIProwGetMaxActivity(row, set, stat);
6415  if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6416  return FALSE;
6417  }
6418 
6419  return TRUE;
6420 }
6421 
6422 /** gets maximal absolute value of row vector coefficients */
6424  SCIP_ROW* row, /**< LP row */
6425  SCIP_SET* set /**< global SCIP settings */
6426  )
6427 {
6428  assert(row != NULL);
6429 
6430  if( row->nummaxval == 0 )
6431  rowCalcIdxsAndVals(row, set);
6432  assert(row->nummaxval > 0);
6433  assert(row->maxval >= 0.0 || row->len == 0);
6434 
6435  return row->maxval;
6436 }
6437 
6438 /** gets minimal absolute value of row vector's non-zero coefficients */
6440  SCIP_ROW* row, /**< LP row */
6441  SCIP_SET* set /**< global SCIP settings */
6442  )
6443 {
6444  assert(row != NULL);
6445 
6446  if( row->numminval == 0 )
6447  rowCalcIdxsAndVals(row, set);
6448  assert(row->numminval >= 0);
6449  assert(row->minval >= 0.0 || row->len == 0);
6450 
6451  return row->minval;
6452 }
6453 
6454 /** gets maximal column index of row entries */
6456  SCIP_ROW* row, /**< LP row */
6457  SCIP_SET* set /**< global SCIP settings */
6458  )
6459 {
6460  assert(row != NULL);
6461 
6462  if( row->validminmaxidx == 0 )
6463  rowCalcIdxsAndVals(row, set);
6464  assert(row->maxidx >= 0 || row->len == 0);
6465  assert(row->validminmaxidx);
6466 
6467  return row->maxidx;
6468 }
6469 
6470 /** gets minimal column index of row entries */
6472  SCIP_ROW* row, /**< LP row */
6473  SCIP_SET* set /**< global SCIP settings */
6474  )
6475 {
6476  assert(row != NULL);
6477 
6478  if( row->validminmaxidx == 0 )
6479  rowCalcIdxsAndVals(row, set);
6480  assert(row->minidx >= 0 || row->len == 0);
6481  assert(row->validminmaxidx);
6482 
6483  return row->minidx;
6484 }
6485 
6486 /** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6488  SCIP_ROW* row, /**< LP row */
6489  SCIP_SET* set, /**< global SCIP settings */
6490  SCIP_STAT* stat, /**< problem statistics data */
6491  SCIP_LP* lp /**< current LP data */
6492  )
6493 {
6494  SCIP_Real norm;
6495  SCIP_Real feasibility;
6496  SCIP_Real eps;
6497 
6498  assert(set != NULL);
6499 
6500  switch( set->sepa_efficacynorm )
6501  {
6502  case 'e':
6503  norm = SCIProwGetNorm(row);
6504  break;
6505  case 'm':
6506  norm = SCIProwGetMaxval(row, set);
6507  break;
6508  case 's':
6509  norm = SCIProwGetSumNorm(row);
6510  break;
6511  case 'd':
6512  norm = (row->len == 0 ? 0.0 : 1.0);
6513  break;
6514  default:
6515  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6516  SCIPABORT();
6517  norm = 0.0; /*lint !e527*/
6518  }
6519 
6520  eps = SCIPsetSumepsilon(set);
6521  norm = MAX(norm, eps);
6522  feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6523 
6524  return -feasibility / norm;
6525 }
6526 
6527 /** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6529  SCIP_ROW* row, /**< LP row */
6530  SCIP_SET* set, /**< global SCIP settings */
6531  SCIP_STAT* stat, /**< problem statistics data */
6532  SCIP_LP* lp, /**< current LP data */
6533  SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6534  )
6535 {
6536  SCIP_Real efficacy;
6537 
6538  efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6539 
6540  return SCIPsetIsEfficacious(set, root, efficacy);
6541 }
6542 
6543 /** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6545  SCIP_ROW* row, /**< LP row */
6546  SCIP_SET* set, /**< global SCIP settings */
6547  SCIP_STAT* stat, /**< problem statistics data */
6548  SCIP_SOL* sol /**< primal CIP solution */
6549  )
6550 {
6551  SCIP_Real norm;
6552  SCIP_Real feasibility;
6553  SCIP_Real eps;
6554 
6555  assert(set != NULL);
6556 
6557  switch( set->sepa_efficacynorm )
6558  {
6559  case 'e':
6560  norm = SCIProwGetNorm(row);
6561  break;
6562  case 'm':
6563  norm = SCIProwGetMaxval(row, set);
6564  break;
6565  case 's':
6566  norm = SCIProwGetSumNorm(row);
6567  break;
6568  case 'd':
6569  norm = (row->len == 0 ? 0.0 : 1.0);
6570  break;
6571  default:
6572  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6573  SCIPABORT();
6574  norm = 0.0; /*lint !e527*/
6575  }
6576 
6577  eps = SCIPsetSumepsilon(set);
6578  norm = MAX(norm, eps);
6579  feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6580 
6581  return -feasibility / norm;
6582 }
6583 
6584 /** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6585  * efficacy
6586  */
6588  SCIP_ROW* row, /**< LP row */
6589  SCIP_SET* set, /**< global SCIP settings */
6590  SCIP_STAT* stat, /**< problem statistics data */
6591  SCIP_SOL* sol, /**< primal CIP solution */
6592  SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6593  )
6594 {
6595  SCIP_Real efficacy;
6596 
6597  efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6598 
6599  return SCIPsetIsEfficacious(set, root, efficacy);
6600 }
6601 
6602 /** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6604  SCIP_ROW* row, /**< LP row */
6605  SCIP_SET* set, /**< global SCIP settings */
6606  SCIP_STAT* stat /**< problem statistics data */
6607  )
6608 {
6609  SCIP_Real norm;
6610  SCIP_Real feasibility;
6611  SCIP_Real eps;
6612 
6613  assert(set != NULL);
6614 
6615  switch( set->sepa_efficacynorm )
6616  {
6617  case 'e':
6618  norm = SCIProwGetNorm(row);
6619  break;
6620  case 'm':
6621  norm = SCIProwGetMaxval(row, set);
6622  break;
6623  case 's':
6624  norm = SCIProwGetSumNorm(row);
6625  break;
6626  case 'd':
6627  norm = (row->len == 0 ? 0.0 : 1.0);
6628  break;
6629  default:
6630  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6631  SCIPABORT();
6632  norm = 0.0; /*lint !e527*/
6633  }
6634 
6635  eps = SCIPsetSumepsilon(set);
6636  norm = MAX(norm, eps);
6637  feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6638 
6639  return -feasibility / norm;
6640 }
6641 
6642 /** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6644  SCIP_ROW* row, /**< LP row */
6645  SCIP_SET* set, /**< global SCIP settings */
6646  SCIP_STAT* stat /**< problem statistics data */
6647  )
6648 {
6649  SCIP_Real norm;
6650  SCIP_Real feasibility;
6651  SCIP_Real eps;
6652 
6653  assert(set != NULL);
6654 
6655  switch( set->sepa_efficacynorm )
6656  {
6657  case 'e':
6658  norm = SCIProwGetNorm(row);
6659  break;
6660  case 'm':
6661  norm = SCIProwGetMaxval(row, set);
6662  break;
6663  case 's':
6664  norm = SCIProwGetSumNorm(row);
6665  break;
6666  case 'd':
6667  norm = (row->len == 0 ? 0.0 : 1.0);
6668  break;
6669  default:
6670  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6671  SCIPABORT();
6672  norm = 0.0; /*lint !e527*/
6673  }
6674 
6675  eps = SCIPsetSumepsilon(set);
6676  norm = MAX(norm, eps);
6677  feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6678 
6679  return -feasibility / norm;
6680 }
6681 
6682 /** returns the scalar product of the coefficient vectors of the two given rows
6683  *
6684  * @note the scalar product is computed w.r.t. the current LP columns only
6685  * @todo also consider non-LP columns for the computation?
6686  */
6688  SCIP_ROW* row1, /**< first LP row */
6689  SCIP_ROW* row2 /**< second LP row */
6690  )
6691 {
6692  SCIP_Real scalarprod;
6693  int* row1colsidx;
6694  int* row2colsidx;
6695  int i1;
6696  int i2;
6697 
6698  assert(row1 != NULL);
6699  assert(row2 != NULL);
6700 
6701  /* Sort the column indices of both rows.
6702  *
6703  * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
6704  * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
6705  * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
6706  * for both or one of the non-LP columns for both.
6707  * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
6708  * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
6709  * columns can be added later and remain unlinked while all previously added columns might already be linked.
6710  * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
6711  *
6712  * We distinguish the following cases:
6713  *
6714  * 1) both rows have no unlinked columns
6715  * -> we just check the LP partitions
6716  *
6717  * 2) exactly one row is completely unlinked, the other one is completely linked
6718  * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
6719  * (thus all common LP columns are regarded)
6720  *
6721  * 3) we have unlinked and LP columns in both rows
6722  * -> we need to compare four partitions at once
6723  *
6724  * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
6725  * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
6726  * other row
6727  *
6728  * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
6729  * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
6730  *
6731  * 5) both rows are completely unlinked
6732  * -> we need to compare two partitions: both complete rows
6733  */
6734  SCIProwSort(row1);
6735  assert(row1->lpcolssorted);
6736  assert(row1->nonlpcolssorted);
6737  SCIProwSort(row2);
6738  assert(row2->lpcolssorted);
6739  assert(row2->nonlpcolssorted);
6740 
6741  assert(row1->nunlinked <= row1->len - row1->nlpcols);
6742  assert(row2->nunlinked <= row2->len - row2->nlpcols);
6743 
6744  row1colsidx = row1->cols_index;
6745  row2colsidx = row2->cols_index;
6746 
6747 #ifndef NDEBUG
6748  /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
6749  if( row1->nunlinked == 0 && row2->nunlinked == 0 )
6750  {
6751  i1 = 0;
6752  i2 = row2->nlpcols;
6753  while( i1 < row1->nlpcols && i2 < row2->len )
6754  {
6755  assert(row1->cols[i1] != row2->cols[i2]);
6756  if( row1->cols[i1]->index < row2->cols[i2]->index )
6757  ++i1;
6758  else
6759  {
6760  assert(row1->cols[i1]->index > row2->cols[i2]->index);
6761  ++i2;
6762  }
6763  }
6764  assert(i1 == row1->nlpcols || i2 == row2->len);
6765 
6766  i1 = row1->nlpcols;
6767  i2 = 0;
6768  while( i1 < row1->len && i2 < row2->nlpcols )
6769  {
6770  assert(row1->cols[i1] != row2->cols[i2]);
6771  if( row1->cols[i1]->index < row2->cols[i2]->index )
6772  ++i1;
6773  else
6774  {
6775  assert(row1->cols[i1]->index > row2->cols[i2]->index);
6776  ++i2;
6777  }
6778  }
6779  assert(i1 == row1->len || i2 == row2->nlpcols);
6780  }
6781 #endif
6782 
6783  /* The "easy" cases 1) and 2) */
6784  if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
6785  ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
6786  && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
6787  && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
6788  {
6789  assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
6790  assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
6791 
6792  /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
6793  * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
6794  */
6795  i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
6796  i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
6797  scalarprod = 0.0;
6798 
6799  /* calculate the scalar product */
6800  while( i1 >= 0 && i2 >= 0 )
6801  {
6802  assert(row1->cols[i1]->index == row1colsidx[i1]);
6803  assert(row2->cols[i2]->index == row2colsidx[i2]);
6804  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
6805  if( row1colsidx[i1] < row2colsidx[i2] )
6806  --i2;
6807  else if( row1colsidx[i1] > row2colsidx[i2] )
6808  --i1;
6809  else
6810  {
6811  scalarprod += row1->vals[i1] * row2->vals[i2];
6812  --i1;
6813  --i2;
6814  }
6815  }
6816  }
6817  /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
6818  else
6819  {
6820  SCIP_Bool lpcols;
6821  int ilp1;
6822  int inlp1;
6823  int ilp2;
6824  int inlp2;
6825  int end1;
6826  int end2;
6827 
6828  scalarprod = 0;
6829  ilp1 = 0;
6830  ilp2 = 0;
6831 
6832  /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
6833  inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
6834  inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
6835 
6836  /* handle the case of four partitions (case 3) until one partition is finished;
6837  * cases 4a), 4b), and 5) will fail the while-condition
6838  */
6839  while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
6840  {
6841  assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
6842  assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
6843  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
6844  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
6845  assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
6846  assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
6847  assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
6848  assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
6849 
6850  /* rows have the same linked LP columns */
6851  if( row1colsidx[ilp1] == row2colsidx[ilp2] )
6852  {
6853  scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
6854  ++ilp1;
6855  ++ilp2;
6856  }
6857  /* LP column of row1 is the same as unlinked column of row2 */
6858  else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
6859  {
6860  scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
6861  ++ilp1;
6862  ++inlp2;
6863  }
6864  /* unlinked column of row1 is the same as LP column of row2 */
6865  else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
6866  {
6867  scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
6868  ++inlp1;
6869  ++ilp2;
6870  }
6871  /* two unlinked LP columns are the same */
6872  else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
6873  {
6874  scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
6875  ++inlp1;
6876  ++inlp2;
6877  }
6878  /* increase smallest counter */
6879  else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
6880  {
6881  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6882  {
6883  if( row1colsidx[ilp1] < row2colsidx[ilp2] )
6884  ++ilp1;
6885  else
6886  ++ilp2;
6887  }
6888  else
6889  {
6890  if( row1colsidx[ilp1] < row2colsidx[inlp2] )
6891  ++ilp1;
6892  else
6893  ++inlp2;
6894  }
6895  }
6896  else
6897  {
6898  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6899  {
6900  if( row1colsidx[inlp1] < row2colsidx[ilp2] )
6901  ++inlp1;
6902  else
6903  ++ilp2;
6904  }
6905  else
6906  {
6907  if( row1colsidx[inlp1] < row2colsidx[inlp2] )
6908  ++inlp1;
6909  else
6910  ++inlp2;
6911  }
6912  }
6913  }
6914 
6915  /* One partition was completely handled, we just have to handle the three remaining partitions:
6916  * the remaining partition of this row and the two partitions of the other row.
6917  * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
6918  */
6919  if( ilp1 != row1->nlpcols && inlp1 != row1->len )
6920  {
6921  int tmpilp;
6922  int tmpinlp;
6923 
6924  assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
6925 
6926  SCIPswapPointers((void**) &row1, (void**) &row2);
6927  SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
6928  tmpilp = ilp1;
6929  tmpinlp = inlp1;
6930  ilp1 = ilp2;
6931  inlp1 = inlp2;
6932  ilp2 = tmpilp;
6933  inlp2 = tmpinlp;
6934  }
6935 
6936  /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
6937  * -> this merges cases 4a) and 4b)
6938  */
6939  if( ilp1 == row1->nlpcols )
6940  {
6941  i1 = inlp1;
6942  end1 = row1->len;
6943  lpcols = FALSE;
6944  }
6945  else
6946  {
6947  assert(inlp1 == row1->len);
6948 
6949  i1 = ilp1;
6950  end1 = row1->nlpcols;
6951  lpcols = TRUE;
6952  }
6953 
6954  /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
6955  * case 5) will fail the while-condition
6956  */
6957  while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
6958  {
6959  assert(row1->cols[i1]->index == row1colsidx[i1]);
6960  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
6961  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
6962  assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
6963  assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
6964 
6965  /* current column in row 1 is the same as the current LP column in row 2 */
6966  if( row1colsidx[i1] == row2colsidx[ilp2] )
6967  {
6968  scalarprod += row1->vals[i1] * row2->vals[ilp2];
6969  ++i1;
6970  ++ilp2;
6971  }
6972  /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
6973  else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
6974  {
6975  scalarprod += row1->vals[i1] * row2->vals[inlp2];
6976  ++i1;
6977  ++inlp2;
6978  }
6979  /* increase smallest counter */
6980  else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6981  {
6982  if( row1colsidx[i1] < row2colsidx[ilp2] )
6983  ++i1;
6984  else
6985  ++ilp2;
6986  }
6987  else
6988  {
6989  if( row1colsidx[i1] < row2colsidx[inlp2] )
6990  ++i1;
6991  else
6992  ++inlp2;
6993  }
6994  }
6995 
6996  /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
6997  * the two rows
6998  */
6999  if( i1 < end1 )
7000  {
7001  /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7002  if( ilp2 == row2->nlpcols )
7003  {
7004  i2 = inlp2;
7005  end2 = row2->len;
7006  lpcols = FALSE;
7007  }
7008  else
7009  {
7010  assert(inlp2 == row2->len);
7011 
7012  i2 = ilp2;
7013  end2 = row2->nlpcols;
7014  }
7015 
7016  /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7017  while( i1 < end1 && i2 < end2 )
7018  {
7019  assert(row1->cols[i1]->index == row1colsidx[i1]);
7020  assert(row2->cols[i2]->index == row2colsidx[i2]);
7021  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7022 
7023  /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7024  if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7025  {
7026  scalarprod += row1->vals[i1] * row2->vals[i2];
7027  ++i1;
7028  ++i2;
7029  }
7030  /* increase smallest counter */
7031  else if( row1colsidx[i1] < row2colsidx[i2] )
7032  ++i1;
7033  else
7034  ++i2;
7035  }
7036  }
7037  }
7038 
7039  return scalarprod;
7040 }
7041 
7042 /** returns the discrete scalar product of the coefficient vectors of the two given rows */
7043 static
7045  SCIP_ROW* row1, /**< first LP row */
7046  SCIP_ROW* row2 /**< second LP row */
7047  )
7048 {
7049  int prod;
7050  int* row1colsidx;
7051  int* row2colsidx;
7052  int i1;
7053  int i2;
7054 
7055  assert(row1 != NULL);
7056  assert(row2 != NULL);
7057 
7058  /* Sort the column indices of both rows.
7059  *
7060  * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7061  * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7062  * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7063  * for both or one of the non-LP columns for both.
7064  * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7065  * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7066  * columns can be added later and remain unlinked while all previously added columns might already be linked.
7067  * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7068  *
7069  * We distinguish the following cases:
7070  *
7071  * 1) both rows have no unlinked columns
7072  * -> we just check the LP partitions
7073  *
7074  * 2) exactly one row is completely unlinked, the other one is completely linked
7075  * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7076  * (thus all common LP columns are regarded)
7077  *
7078  * 3) we have unlinked and LP columns in both rows
7079  * -> we need to compare four partitions at once
7080  *
7081  * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7082  * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7083  * other row
7084  *
7085  * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7086  * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7087  *
7088  * 5) both rows are completely unlinked
7089  * -> we need to compare two partitions: both complete rows
7090  */
7091  SCIProwSort(row1);
7092  assert(row1->lpcolssorted);
7093  assert(row1->nonlpcolssorted);
7094  SCIProwSort(row2);
7095  assert(row2->lpcolssorted);
7096  assert(row2->nonlpcolssorted);
7097 
7098  assert(row1->nunlinked <= row1->len - row1->nlpcols);
7099  assert(row2->nunlinked <= row2->len - row2->nlpcols);
7100 
7101  row1colsidx = row1->cols_index;
7102  row2colsidx = row2->cols_index;
7103 
7104 #ifndef NDEBUG
7105  /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7106  if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7107  {
7108  i1 = 0;
7109  i2 = row2->nlpcols;
7110  while( i1 < row1->nlpcols && i2 < row2->len )
7111  {
7112  assert(row1->cols[i1] != row2->cols[i2]);
7113  if( row1->cols[i1]->index < row2->cols[i2]->index )
7114  ++i1;
7115  else
7116  {
7117  assert(row1->cols[i1]->index > row2->cols[i2]->index);
7118  ++i2;
7119  }
7120  }
7121  assert(i1 == row1->nlpcols || i2 == row2->len);
7122 
7123  i1 = row1->nlpcols;
7124  i2 = 0;
7125  while( i1 < row1->len && i2 < row2->nlpcols )
7126  {
7127  assert(row1->cols[i1] != row2->cols[i2]);
7128  if( row1->cols[i1]->index < row2->cols[i2]->index )
7129  ++i1;
7130  else
7131  {
7132  assert(row1->cols[i1]->index > row2->cols[i2]->index);
7133  ++i2;
7134  }
7135  }
7136  assert(i1 == row1->len || i2 == row2->nlpcols);
7137  }
7138 #endif
7139 
7140  /* The "easy" cases 1) and 2) */
7141  if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7142  ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7143  && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7144  && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7145  {
7146  assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7147  assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7148 
7149  /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7150  * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7151  */
7152  i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7153  i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7154  prod = 0;
7155 
7156  /* calculate the scalar product */
7157  while( i1 >= 0 && i2 >= 0 )
7158  {
7159  assert(row1->cols[i1]->index == row1colsidx[i1]);
7160  assert(row2->cols[i2]->index == row2colsidx[i2]);
7161  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7162  if( row1colsidx[i1] < row2colsidx[i2] )
7163  --i2;
7164  else if( row1colsidx[i1] > row2colsidx[i2] )
7165  --i1;
7166  else
7167  {
7168  ++prod;
7169  --i1;
7170  --i2;
7171  }
7172  }
7173  }
7174  /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7175  else
7176  {
7177  SCIP_Bool lpcols;
7178  int ilp1;
7179  int inlp1;
7180  int ilp2;
7181  int inlp2;
7182  int end1;
7183  int end2;
7184 
7185  prod = 0;
7186  ilp1 = 0;
7187  ilp2 = 0;
7188 
7189  /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7190  inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7191  inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7192 
7193  /* handle the case of four partitions (case 3) until one partition is finished;
7194  * cases 4a), 4b), and 5) will fail the while-condition
7195  */
7196  while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7197  {
7198  assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7199  assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7200  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7201  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7202  assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7203  assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7204  assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7205  assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7206 
7207  /* rows have the same linked LP columns */
7208  if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7209  {
7210  ++prod;
7211  ++ilp1;
7212  ++ilp2;
7213  }
7214  /* LP column of row1 is the same as unlinked column of row2 */
7215  else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7216  {
7217  ++prod;
7218  ++ilp1;
7219  ++inlp2;
7220  }
7221  /* unlinked column of row1 is the same as LP column of row2 */
7222  else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7223  {
7224  ++prod;
7225  ++inlp1;
7226  ++ilp2;
7227  }
7228  /* two unlinked LP columns are the same */
7229  else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7230  {
7231  ++prod;
7232  ++inlp1;
7233  ++inlp2;
7234  }
7235  /* increase smallest counter */
7236  else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7237  {
7238  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7239  {
7240  if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7241  ++ilp1;
7242  else
7243  ++ilp2;
7244  }
7245  else
7246  {
7247  if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7248  ++ilp1;
7249  else
7250  ++inlp2;
7251  }
7252  }
7253  else
7254  {
7255  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7256  {
7257  if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7258  ++inlp1;
7259  else
7260  ++ilp2;
7261  }
7262  else
7263  {
7264  if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7265  ++inlp1;
7266  else
7267  ++inlp2;
7268  }
7269  }
7270  }
7271 
7272  /* One partition was completely handled, we just have to handle the three remaining partitions:
7273  * the remaining partition of this row and the two partitions of the other row.
7274  * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7275  */
7276  if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7277  {
7278  int tmpilp;
7279  int tmpinlp;
7280 
7281  assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7282 
7283  SCIPswapPointers((void**) &row1, (void**) &row2);
7284  SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7285  tmpilp = ilp1;
7286  tmpinlp = inlp1;
7287  ilp1 = ilp2;
7288  inlp1 = inlp2;
7289  ilp2 = tmpilp;
7290  inlp2 = tmpinlp;
7291  }
7292 
7293  /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7294  * -> this merges cases 4a) and 4b)
7295  */
7296  if( ilp1 == row1->nlpcols )
7297  {
7298  i1 = inlp1;
7299  end1 = row1->len;
7300  lpcols = FALSE;
7301  }
7302  else
7303  {
7304  assert(inlp1 == row1->len);
7305 
7306  i1 = ilp1;
7307  end1 = row1->nlpcols;
7308  lpcols = TRUE;
7309  }
7310 
7311  /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7312  * case 5) will fail the while-condition
7313  */
7314  while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7315  {
7316  assert(row1->cols[i1]->index == row1colsidx[i1]);
7317  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7318  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7319  assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7320  assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7321 
7322  /* current column in row 1 is the same as the current LP column in row 2 */
7323  if( row1colsidx[i1] == row2colsidx[ilp2] )
7324  {
7325  ++prod;
7326  ++i1;
7327  ++ilp2;
7328  }
7329  /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7330  else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7331  {
7332  ++prod;
7333  ++i1;
7334  ++inlp2;
7335  }
7336  /* increase smallest counter */
7337  else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7338  {
7339  if( row1colsidx[i1] < row2colsidx[ilp2] )
7340  ++i1;
7341  else
7342  ++ilp2;
7343  }
7344  else
7345  {
7346  if( row1colsidx[i1] < row2colsidx[inlp2] )
7347  ++i1;
7348  else
7349  ++inlp2;
7350  }
7351  }
7352 
7353  /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7354  * the two rows
7355  */
7356  if( i1 < end1 )
7357  {
7358  /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7359  if( ilp2 == row2->nlpcols )
7360  {
7361  i2 = inlp2;
7362  end2 = row2->len;
7363  lpcols = FALSE;
7364  }
7365  else
7366  {
7367  assert(inlp2 == row2->len);
7368 
7369  i2 = ilp2;
7370  end2 = row2->nlpcols;
7371  }
7372 
7373  /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7374  while( i1 < end1 && i2 < end2 )
7375  {
7376  assert(row1->cols[i1]->index == row1colsidx[i1]);
7377  assert(row2->cols[i2]->index == row2colsidx[i2]);
7378  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7379 
7380  /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7381  if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7382  {
7383  ++prod;
7384  ++i1;
7385  ++i2;
7386  }
7387  /* increase smallest counter */
7388  else if( row1colsidx[i1] < row2colsidx[i2] )
7389  ++i1;
7390  else
7391  ++i2;
7392  }
7393  }
7394  }
7395 
7396  return prod;
7397 }
7398 
7399 /** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7400  * p = |v*w|/(|v|*|w|);
7401  * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7402  */
7404  SCIP_ROW* row1, /**< first LP row */
7405  SCIP_ROW* row2, /**< second LP row */
7406  char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7407  )
7408 {
7409  SCIP_Real parallelism;
7410  SCIP_Real scalarprod;
7411 
7412  switch( orthofunc )
7413  {
7414  case 'e':
7415  scalarprod = SCIProwGetScalarProduct(row1, row2);
7416  parallelism = (REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2)));
7417  break;
7418  case 'd':
7419  scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7420  parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7421  break;
7422  default:
7423  SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7424  SCIPABORT();
7425  parallelism = 0.0; /*lint !e527*/
7426  }
7427 
7428  return parallelism;
7429 }
7430 
7431 /** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7432  * o = 1 - |v*w|/(|v|*|w|);
7433  * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7434  */
7436  SCIP_ROW* row1, /**< first LP row */
7437  SCIP_ROW* row2, /**< second LP row */
7438  char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7439  )
7440 {
7441  return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7442 }
7443 
7444 /** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7445  * function, if the value is 0, it is orthogonal to the objective function
7446  */
7448  SCIP_ROW* row, /**< LP row */
7449  SCIP_SET* set, /**< global SCIP settings */
7450  SCIP_LP* lp /**< current LP data */
7451  )
7452 {
7453  SCIP_Real prod;
7454  SCIP_Real parallelism;
7455 
7456  assert(row != NULL);
7457  assert(lp != NULL);
7458 
7459  if( lp->objsqrnormunreliable )
7460  SCIPlpRecalculateObjSqrNorm(set, lp);
7461 
7462  assert(!lp->objsqrnormunreliable);
7463  assert(lp->objsqrnorm >= 0.0);
7464 
7465  checkRowSqrnorm(row);
7466  checkRowObjprod(row);
7467 
7468  prod = row->sqrnorm * lp->objsqrnorm;
7469 
7470  parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / SQRT(prod) : 0.0;
7471  assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7472  assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7473  parallelism = MIN(parallelism, 1.0);
7474  parallelism = MAX(parallelism, 0.0);
7475 
7476  return parallelism;
7477 }
7478 
7479 /** includes event handler with given data in row's event filter */
7481  SCIP_ROW* row, /**< row */
7482  BMS_BLKMEM* blkmem, /**< block memory */
7483  SCIP_SET* set, /**< global SCIP settings */
7484  SCIP_EVENTTYPE eventtype, /**< event type to catch */
7485  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7486  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7487  int* filterpos /**< pointer to store position of event filter entry, or NULL */
7488  )
7489 {
7490  assert(row != NULL);
7491  assert(row->eventfilter != NULL);
7492  assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7493  assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7494 
7495  SCIPdebugMessage("catch event of type 0x%x of row <%s> with handler %p and data %p\n",
7496  eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7497 
7498  SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7499 
7500  return SCIP_OKAY;
7501 }
7502 
7503 /** deletes event handler with given data from row's event filter */
7505  SCIP_ROW* row, /**< row */
7506  BMS_BLKMEM* blkmem, /**< block memory */
7507  SCIP_SET* set, /**< global SCIP settings */
7508  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7509  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7510  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7511  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7512  )
7513 {
7514  assert(row != NULL);
7515  assert(row->eventfilter != NULL);
7516 
7517  SCIPdebugMessage("drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7518 
7519  SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7520 
7521  return SCIP_OKAY;
7522 }
7523 
7524 /** marks a row to be not removable from the LP in the current node because it became obsolete */
7526  SCIP_ROW* row, /**< LP row */
7527  SCIP_STAT* stat /**< problem statistics */
7528  )
7529 {
7530  assert(row != NULL);
7531  assert(stat != NULL);
7532  assert(stat->nnodes > 0);
7533 
7534  /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7535  row->obsoletenode = stat->nnodes;
7536 }
7537 
7538 /*
7539  * LP solver data update
7540  */
7541 
7542 /** resets column data to represent a column not in the LP solver */
7543 static
7545  SCIP_COL* col /**< column to be marked deleted */
7546  )
7547 {
7548  assert(col != NULL);
7549 
7550  col->lpipos = -1;
7551  col->primsol = 0.0;
7552  col->redcost = SCIP_INVALID;
7553  col->farkascoef = SCIP_INVALID;
7554  col->sbdown = SCIP_INVALID;
7555  col->sbup = SCIP_INVALID;
7556  col->sbdownvalid = FALSE;
7557  col->sbupvalid = FALSE;
7558  col->validredcostlp = -1;
7559  col->validfarkaslp = -1;
7560  col->sbitlim = -1;
7561  col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7562 }
7563 
7564 /** applies all cached column removals to the LP solver */
7565 static
7567  SCIP_LP* lp /**< current LP data */
7568  )
7569 {
7570  assert(lp != NULL);
7571  assert(lp->lpifirstchgcol <= lp->nlpicols);
7572  assert(lp->lpifirstchgcol <= lp->ncols);
7573 
7574  /* find the first column to change */
7575  while( lp->lpifirstchgcol < lp->nlpicols
7576  && lp->lpifirstchgcol < lp->ncols
7577  && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7578  && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7579  {
7580  assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7581  lp->lpifirstchgcol++;
7582  }
7583 
7584  /* shrink LP to the part which didn't change */
7585  if( lp->lpifirstchgcol < lp->nlpicols )
7586  {
7587  int i;
7588 
7589  assert(!lp->diving);
7590  SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7591  SCIP_CALL( SCIPlpiDelCols(lp->lpi, lp->lpifirstchgcol, lp->nlpicols-1) );
7592  for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7593  {
7594  markColDeleted(lp->lpicols[i]);
7595  }
7596  lp->nlpicols = lp->lpifirstchgcol;
7597  lp->flushdeletedcols = TRUE;
7598 
7599  /* mark the LP unsolved */
7600  lp->solved = FALSE;
7601  lp->primalfeasible = FALSE;
7602  lp->lpobjval = SCIP_INVALID;
7604  }
7605  assert(lp->nlpicols == lp->lpifirstchgcol);
7606 
7607  return SCIP_OKAY;
7608 }
7609 
7610 /** computes for the given column the lower and upper bound that should be flushed into the LP
7611  * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7612  * the bounds are explicitly added to the LP in any case
7613  */
7614 static
7616  SCIP_LP* lp, /**< current LP data */
7617  SCIP_SET* set, /**< global SCIP settings */
7618  SCIP_COL* col, /**< column to compute bounds for */
7619  SCIP_Real lpiinf, /**< infinity value if the LP solver */
7620  SCIP_Real* lb, /**< pointer to store the new lower bound */
7621  SCIP_Real* ub /**< pointer to store the new upper bound */
7622  )
7623 {
7624  assert(lp != NULL);
7625  assert(set != NULL);
7626  assert(col != NULL);
7627  assert(lb != NULL);
7628  assert(ub != NULL);
7629 
7630  /* get the correct new lower bound:
7631  * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7632  * if we are in diving mode, ignore lazy bounds and always take the lower bound
7633  */
7634  if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7635  (*lb) = -lpiinf;
7636  else
7637  (*lb) = col->lb;
7638  /* get the correct new upper bound:
7639  * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7640  * if we are in diving mode, ignore lazy bounds and always take the upper bound
7641  */
7642  if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7643  (*ub) = lpiinf;
7644  else
7645  (*ub) = col->ub;
7646 }
7647 
7648 /** applies all cached column additions to the LP solver */
7649 static
7651  SCIP_LP* lp, /**< current LP data */
7652  BMS_BLKMEM* blkmem, /**< block memory */
7653  SCIP_SET* set, /**< global SCIP settings */
7654  SCIP_EVENTQUEUE* eventqueue /**< event queue */
7655  )
7656 {
7657  SCIP_Real* obj;
7658  SCIP_Real* lb;
7659  SCIP_Real* ub;
7660  int* beg;
7661  int* ind;
7662  SCIP_Real* val;
7663  char** name;
7664  SCIP_COL* col;
7665  SCIP_Real lpiinf;
7666  int c;
7667  int pos;
7668  int nnonz;
7669  int naddcols;
7670  int naddcoefs;
7671  int i;
7672  int lpipos;
7673 
7674  assert(lp != NULL);
7675  assert(lp->lpifirstchgcol == lp->nlpicols);
7676  assert(blkmem != NULL);
7677  assert(set != NULL);
7678 
7679  /* if there are no columns to add, we are ready */
7680  if( lp->ncols == lp->nlpicols )
7681  return SCIP_OKAY;
7682 
7683  /* add the additional columns */
7684  assert(!lp->diving);
7685  assert(lp->ncols > lp->nlpicols);
7686  SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
7687 
7688  /* get the solver's infinity value */
7689  lpiinf = SCIPlpiInfinity(lp->lpi);
7690 
7691  /* count the (maximal) number of added coefficients, calculate the number of added columns */
7692  naddcols = lp->ncols - lp->nlpicols;
7693  naddcoefs = 0;
7694  for( c = lp->nlpicols; c < lp->ncols; ++c )
7695  naddcoefs += lp->cols[c]->len;
7696  assert(naddcols > 0);
7697 
7698  /* get temporary memory for changes */
7699  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
7700  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
7701  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
7702  SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
7703  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
7704  SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
7705  SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
7706 
7707  /* fill temporary memory with column data */
7708  nnonz = 0;
7709  for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
7710  {
7711  col = lp->cols[c];
7712  assert(col != NULL);
7713  assert(col->var != NULL);
7714  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
7715  assert(SCIPvarGetCol(col->var) == col);
7716  assert(col->lppos == c);
7717  assert(nnonz + col->nlprows <= naddcoefs);
7718 
7719  SCIPdebugMessage("flushing added column <%s>: ", SCIPvarGetName(col->var));
7720  debugColPrint(col);
7721 
7722  /* Because the column becomes a member of the LP solver, it now can take values
7723  * different from zero. That means, we have to include the column in the corresponding
7724  * row vectors.
7725  */
7726  SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
7727 
7728  lp->lpicols[c] = col;
7729  col->lpipos = c;
7730  col->primsol = SCIP_INVALID;
7731  col->redcost = SCIP_INVALID;
7732  col->farkascoef = SCIP_INVALID;
7733  col->sbdown = SCIP_INVALID;
7734  col->sbup = SCIP_INVALID;
7735  col->sbdownvalid = FALSE;
7736  col->sbupvalid = FALSE;
7737  col->validredcostlp = -1;
7738  col->validfarkaslp = -1;
7739  col->sbitlim = -1;
7740  col->objchanged = FALSE;
7741  col->lbchanged = FALSE;
7742  col->ubchanged = FALSE;
7743  col->coefchanged = FALSE;
7744  obj[pos] = col->obj;
7745 
7746  /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
7747  computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
7748 
7749  beg[pos] = nnonz;
7750  name[pos] = (char*)SCIPvarGetName(col->var);
7751 
7752  col->flushedobj = obj[pos];
7753  col->flushedlb = lb[pos];
7754  col->flushedub = ub[pos];
7755 
7756  for( i = 0; i < col->nlprows; ++i )
7757  {
7758  assert(col->rows[i] != NULL);
7759  lpipos = col->rows[i]->lpipos;
7760  if( lpipos >= 0 )
7761  {
7762  assert(lpipos < lp->nrows);
7763  assert(nnonz < naddcoefs);
7764  ind[nnonz] = lpipos;
7765  val[nnonz] = col->vals[i];
7766  nnonz++;
7767  }
7768  }
7769 #ifndef NDEBUG
7770  for( i = col->nlprows; i < col->len; ++i )
7771  {
7772  assert(col->rows[i] != NULL);
7773  assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
7774  }
7775 #endif
7776  }
7777 
7778  /* call LP interface */
7779  SCIPdebugMessage("flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
7780  SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
7781  lp->nlpicols = lp->ncols;
7782  lp->lpifirstchgcol = lp->nlpicols;
7783 
7784  /* free temporary memory */
7785  SCIPsetFreeBufferArray(set, &name);
7786  SCIPsetFreeBufferArray(set, &val);
7787  SCIPsetFreeBufferArray(set, &ind);
7788  SCIPsetFreeBufferArray(set, &beg);
7789  SCIPsetFreeBufferArray(set, &ub);
7790  SCIPsetFreeBufferArray(set, &lb);
7791  SCIPsetFreeBufferArray(set, &obj);
7792 
7793  lp->flushaddedcols = TRUE;
7794 
7795  /* mark the LP unsolved */
7796  lp->solved = FALSE;
7797  lp->dualfeasible = FALSE;
7798  lp->lpobjval = SCIP_INVALID;
7800 
7801  return SCIP_OKAY;
7802 }
7803 
7804 /** resets row data to represent a row not in the LP solver */
7805 static
7807  SCIP_ROW* row /**< row to be marked deleted */
7808  )
7809 {
7810  assert(row != NULL);
7811 
7812  row->lpipos = -1;
7813  row->dualsol = 0.0;
7814  row->activity = SCIP_INVALID;
7815  row->dualfarkas = 0.0;
7816  row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
7817  row->validactivitylp = -1;
7818 }
7819 
7820 /** applies all cached row removals to the LP solver */
7821 static
7823  SCIP_LP* lp, /**< current LP data */
7824  BMS_BLKMEM* blkmem, /**< block memory */
7825  SCIP_SET* set /**< global SCIP settings */
7826  )
7827 {
7828  assert(lp != NULL);
7829  assert(lp->lpifirstchgrow <= lp->nlpirows);
7830  assert(lp->lpifirstchgrow <= lp->nrows);
7831 
7832  /* find the first row to change */
7833  while( lp->lpifirstchgrow < lp->nlpirows
7834  && lp->lpifirstchgrow < lp->nrows
7835  && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
7836  && !lp->rows[lp->lpifirstchgrow]->coefchanged )
7837  {
7838  assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
7839  lp->lpifirstchgrow++;
7840  }
7841 
7842  /* shrink LP to the part which didn't change */
7843  if( lp->lpifirstchgrow < lp->nlpirows )
7844  {
7845  int i;
7846 
7847  SCIPdebugMessage("flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
7848  SCIP_CALL( SCIPlpiDelRows(lp->lpi, lp->lpifirstchgrow, lp->nlpirows-1) );
7849  for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
7850  {
7851  markRowDeleted(lp->lpirows[i]);
7852  SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
7853  }
7854  lp->nlpirows = lp->lpifirstchgrow;
7855  lp->flushdeletedrows = TRUE;
7856 
7857  /* mark the LP unsolved */
7858  lp->solved = FALSE;
7859  lp->dualfeasible = FALSE;
7860  lp->lpobjval = SCIP_INVALID;
7862  }
7863  assert(lp->nlpirows == lp->lpifirstchgrow);
7864 
7865  return SCIP_OKAY;
7866 }
7867 
7868 /** applies all cached row additions and removals to the LP solver */
7869 static
7871  SCIP_LP* lp, /**< current LP data */
7872  BMS_BLKMEM* blkmem, /**< block memory */
7873  SCIP_SET* set, /**< global SCIP settings */
7874  SCIP_EVENTQUEUE* eventqueue /**< event queue */
7875  )
7876 {
7877  SCIP_Real* lhs;
7878  SCIP_Real* rhs;
7879  int* beg;
7880  int* ind;
7881  SCIP_Real* val;
7882  char** name;
7883  SCIP_ROW* row;
7884  SCIP_Real lpiinf;
7885  int r;
7886  int pos;
7887  int nnonz;
7888  int naddrows;
7889  int naddcoefs;
7890  int i;
7891  int lpipos;
7892 
7893  assert(lp != NULL);
7894  assert(lp->lpifirstchgrow == lp->nlpirows);
7895  assert(blkmem != NULL);
7896 
7897  /* if there are no rows to add, we are ready */
7898  if( lp->nrows == lp->nlpirows )
7899  return SCIP_OKAY;
7900 
7901  /* add the additional rows */
7902  assert(lp->nrows > lp->nlpirows);
7903  SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
7904 
7905  /* get the solver's infinity value */
7906  lpiinf = SCIPlpiInfinity(lp->lpi);
7907 
7908  /* count the (maximal) number of added coefficients, calculate the number of added rows */
7909  naddrows = lp->nrows - lp->nlpirows;
7910  naddcoefs = 0;
7911  for( r = lp->nlpirows; r < lp->nrows; ++r )
7912  naddcoefs += lp->rows[r]->len;
7913  assert(naddrows > 0);
7914 
7915  /* get temporary memory for changes */
7916  SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
7917  SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
7918  SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
7919  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
7920  SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
7921  SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
7922 
7923  /* fill temporary memory with row data */
7924  nnonz = 0;
7925  for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
7926  {
7927  row = lp->rows[r];
7928  assert(row != NULL);
7929  assert(row->lppos == r);
7930  assert(nnonz + row->nlpcols <= naddcoefs);
7931 
7932  SCIPdebugMessage("flushing added row <%s>: ", row->name);
7933  debugRowPrint(row);
7934 
7935  /* Because the row becomes a member of the LP solver, its dual variable now can take values
7936  * different from zero. That means, we have to include the row in the corresponding
7937  * column vectors.
7938  */
7939  SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
7940 
7941  SCIProwCapture(row);
7942  lp->lpirows[r] = row;
7943  row->lpipos = r;
7944  row->dualsol = SCIP_INVALID;
7945  row->activity = SCIP_INVALID;
7946  row->dualfarkas = SCIP_INVALID;
7947  row->validactivitylp = -1;
7948  row->lhschanged = FALSE;
7949  row->rhschanged = FALSE;
7950  row->coefchanged = FALSE;
7951  if( SCIPsetIsInfinity(set, -row->lhs) )
7952  lhs[pos] = -lpiinf;
7953  else
7954  lhs[pos] = row->lhs - row->constant;
7955  if( SCIPsetIsInfinity(set, row->rhs) )
7956  rhs[pos] = lpiinf;
7957  else
7958  rhs[pos] = row->rhs - row->constant;
7959  beg[pos] = nnonz;
7960  name[pos] = row->name;
7961 
7962  row->flushedlhs = lhs[pos];
7963  row->flushedrhs = rhs[pos];
7964 
7965  SCIPdebugMessage("flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
7966  for( i = 0; i < row->nlpcols; ++i )
7967  {
7968  assert(row->cols[i] != NULL);
7969  lpipos = row->cols[i]->lpipos;
7970  if( lpipos >= 0 )
7971  {
7972  assert(lpipos < lp->ncols);
7973  assert(nnonz < naddcoefs);
7974  SCIPdebugPrintf(" %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
7975  ind[nnonz] = lpipos;
7976  val[nnonz] = row->vals[i];
7977  nnonz++;
7978  }
7979  }
7980  SCIPdebugPrintf(" <= %+g\n", rhs[pos]);
7981 #ifndef NDEBUG
7982  for( i = row->nlpcols; i < row->len; ++i )
7983  {
7984  assert(row->cols[i] != NULL);
7985  assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
7986  }
7987 #endif
7988  }
7989 
7990  /* call LP interface */
7991  SCIPdebugMessage("flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
7992  SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
7993  lp->nlpirows = lp->nrows;
7994  lp->lpifirstchgrow = lp->nlpirows;
7995 
7996  /* free temporary memory */
7997  SCIPsetFreeBufferArray(set, &name);
7998  SCIPsetFreeBufferArray(set, &val);
7999  SCIPsetFreeBufferArray(set, &ind);
8000  SCIPsetFreeBufferArray(set, &beg);
8001  SCIPsetFreeBufferArray(set, &rhs);
8002  SCIPsetFreeBufferArray(set, &lhs);
8003 
8004  lp->flushaddedrows = TRUE;
8005 
8006  /* mark the LP unsolved */
8007  lp->solved = FALSE;
8008  lp->primalfeasible = FALSE;
8009  lp->lpobjval = SCIP_INVALID;
8011 
8012  return SCIP_OKAY;
8013 }
8014 
8015 /** applies all cached column bound and objective changes to the LP */
8016 static
8018  SCIP_LP* lp, /**< current LP data */
8019  SCIP_SET* set /**< global SCIP settings */
8020  )
8021 {
8022 #ifndef NDEBUG
8023  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8024 #endif
8025  SCIP_COL* col;
8026  int* objind;
8027  int* bdind;
8028  SCIP_Real* obj;
8029  SCIP_Real* lb;
8030  SCIP_Real* ub;
8031  SCIP_Real lpiinf;
8032  int nobjchg;
8033  int nbdchg;
8034  int i;
8035 
8036  assert(lp != NULL);
8037 
8038  if( lp->nchgcols == 0 )
8039  return SCIP_OKAY;
8040 
8041  /* get the solver's infinity value */
8042  lpiinf = SCIPlpiInfinity(lp->lpi);
8043 
8044  /* get temporary memory for changes */
8045  SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8046  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, lp->ncols) );
8047  SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8048  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, lp->ncols) );
8049  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, lp->ncols) );
8050 
8051  /* collect all cached bound and objective changes */
8052  nobjchg = 0;
8053  nbdchg = 0;
8054  for( i = 0; i < lp->nchgcols; ++i )
8055  {
8056  col = lp->chgcols[i];
8057  assert(col != NULL);
8058  assert(col->var != NULL);
8059  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8060  assert(SCIPvarGetCol(col->var) == col);
8061 
8062  if( col->lpipos >= 0 )
8063  {
8064 #ifndef NDEBUG
8065  /* do not check consistency of data with LPI in case of LPI=none */
8066  if( !lpinone )
8067  {
8068  SCIP_Real lpiobj;
8069  SCIP_Real lpilb;
8070  SCIP_Real lpiub;
8071 
8072  SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8073  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8074  assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8075  assert(SCIPsetIsFeasEQ(set, lpilb, col->flushedlb));
8076  assert(SCIPsetIsFeasEQ(set, lpiub, col->flushedub));
8077  }
8078 #endif
8079 
8080  if( col->objchanged )
8081  {
8082  SCIP_Real newobj;
8083 
8084  newobj = col->obj;
8085  if( col->flushedobj != newobj ) /*lint !e777*/
8086  {
8087  assert(nobjchg < lp->ncols);
8088  objind[nobjchg] = col->lpipos;
8089  obj[nobjchg] = newobj;
8090  nobjchg++;
8091  col->flushedobj = newobj;
8092  }
8093  col->objchanged = FALSE;
8094  }
8095 
8096  if( col->lbchanged || col->ubchanged )
8097  {
8098  SCIP_Real newlb;
8099  SCIP_Real newub;
8100 
8101  /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8102  computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8103 
8104  if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8105  {
8106  assert(nbdchg < lp->ncols);
8107  bdind[nbdchg] = col->lpipos;
8108  lb[nbdchg] = newlb;
8109  ub[nbdchg] = newub;
8110  nbdchg++;
8111  col->flushedlb = newlb;
8112  col->flushedub = newub;
8113  }
8114  col->lbchanged = FALSE;
8115  col->ubchanged = FALSE;
8116  }
8117  }
8118  /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8119  }
8120 
8121  /* change objective values in LP */
8122  if( nobjchg > 0 )
8123  {
8124  SCIPdebugMessage("flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8125  SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8126 
8127  /* mark the LP unsolved */
8128  lp->solved = FALSE;
8129  lp->dualfeasible = FALSE;
8130  lp->lpobjval = SCIP_INVALID;
8132  }
8133 
8134  /* change bounds in LP */
8135  if( nbdchg > 0 )
8136  {
8137  SCIPdebugMessage("flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8138  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8139 
8140  /* mark the LP unsolved */
8141  lp->solved = FALSE;
8142  lp->primalfeasible = FALSE;
8143  lp->lpobjval = SCIP_INVALID;
8145  }
8146 
8147  lp->nchgcols = 0;
8148 
8149  /* free temporary memory */
8150  SCIPsetFreeBufferArray(set, &ub);
8151  SCIPsetFreeBufferArray(set, &lb);
8152  SCIPsetFreeBufferArray(set, &bdind);
8153  SCIPsetFreeBufferArray(set, &obj);
8154  SCIPsetFreeBufferArray(set, &objind);
8155 
8156  return SCIP_OKAY;
8157 }
8158 
8159 /** applies all cached row side changes to the LP */
8160 static
8162  SCIP_LP* lp, /**< current LP data */
8163  SCIP_SET* set /**< global SCIP settings */
8164  )
8165 {
8166 #ifndef NDEBUG
8167  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8168 #endif
8169  SCIP_ROW* row;
8170  int* ind;
8171  SCIP_Real* lhs;
8172  SCIP_Real* rhs;
8173  SCIP_Real lpiinf;
8174  int i;
8175  int nchg;
8176 
8177  assert(lp != NULL);
8178 
8179  if( lp->nchgrows == 0 )
8180  return SCIP_OKAY;
8181 
8182  /* get the solver's infinity value */
8183  lpiinf = SCIPlpiInfinity(lp->lpi);
8184 
8185  /* get temporary memory for changes */
8186  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, lp->nrows) );
8187  SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, lp->nrows) );
8188  SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, lp->nrows) );
8189 
8190  /* collect all cached left and right hand side changes */
8191  nchg = 0;
8192  for( i = 0; i < lp->nchgrows; ++i )
8193  {
8194  row = lp->chgrows[i];
8195  assert(row != NULL);
8196 
8197  if( row->lpipos >= 0 )
8198  {
8199 #ifndef NDEBUG
8200  /* do not check consistency of data with LPI in case of LPI=none */
8201  if( !lpinone )
8202  {
8203  SCIP_Real lpilhs;
8204  SCIP_Real lpirhs;
8205 
8206  SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8207  assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8208  assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8209  }
8210 #endif
8211  if( row->lhschanged || row->rhschanged )
8212  {
8213  SCIP_Real newlhs;
8214  SCIP_Real newrhs;
8215 
8216  newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8217  newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8218  if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8219  {
8220  assert(nchg < lp->nrows);
8221  ind[nchg] = row->lpipos;
8222  lhs[nchg] = newlhs;
8223  rhs[nchg] = newrhs;
8224  nchg++;
8225  row->flushedlhs = newlhs;
8226  row->flushedrhs = newrhs;
8227  }
8228  row->lhschanged = FALSE;
8229  row->rhschanged = FALSE;
8230  }
8231  }
8232  }
8233 
8234  /* change left and right hand sides in LP */
8235  if( nchg > 0 )
8236  {
8237  SCIPdebugMessage("flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8238  SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8239 
8240  /* mark the LP unsolved */
8241  lp->solved = FALSE;
8242  lp->primalfeasible = FALSE;
8243  lp->lpobjval = SCIP_INVALID;
8245  }
8246 
8247  lp->nchgrows = 0;
8248 
8249  /* free temporary memory */
8250  SCIPsetFreeBufferArray(set, &rhs);
8251  SCIPsetFreeBufferArray(set, &lhs);
8252  SCIPsetFreeBufferArray(set, &ind);
8253 
8254  return SCIP_OKAY;
8255 }
8256 
8257 /** applies all cached changes to the LP solver */
8259  SCIP_LP* lp, /**< current LP data */
8260  BMS_BLKMEM* blkmem, /**< block memory */
8261  SCIP_SET* set, /**< global SCIP settings */
8262  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8263  )
8264 {
8265  assert(lp != NULL);
8266  assert(blkmem != NULL);
8267 
8268  SCIPdebugMessage("flushing LP changes: old (%d cols, %d rows), nchgcols=%d, nchgrows=%d, firstchgcol=%d, firstchgrow=%d, new (%d cols, %d rows), flushed=%u\n",
8269  lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow,
8270  lp->ncols, lp->nrows, lp->flushed);
8271 
8272  if( !lp->flushed )
8273  {
8274  lp->flushdeletedcols = FALSE;
8275  lp->flushaddedcols = FALSE;
8276  lp->flushdeletedrows = FALSE;
8277  lp->flushaddedrows = FALSE;
8278 
8279  SCIP_CALL( lpFlushDelCols(lp) );
8280  SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8281  SCIP_CALL( lpFlushChgCols(lp, set) );
8282  SCIP_CALL( lpFlushChgRows(lp, set) );
8283  SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8284  SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8285 
8286  lp->flushed = TRUE;
8287 
8288  checkLinks(lp);
8289  }
8290 
8291  assert(lp->nlpicols == lp->ncols);
8292  assert(lp->lpifirstchgcol == lp->nlpicols);
8293  assert(lp->nlpirows == lp->nrows);
8294  assert(lp->lpifirstchgrow == lp->nlpirows);
8295  assert(lp->nchgcols == 0);
8296  assert(lp->nchgrows == 0);
8297 #ifndef NDEBUG
8298  {
8299  int ncols;
8300  int nrows;
8301 
8302  SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8303  SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8304  assert(ncols == lp->ncols);
8305  assert(nrows == lp->nrows);
8306  }
8307 #endif
8308 
8309  return SCIP_OKAY;
8310 }
8311 
8312 /** marks the LP to be flushed, even if the LP thinks it is not flushed */
8314  SCIP_LP* lp, /**< current LP data */
8315  SCIP_SET* set /**< global SCIP settings */
8316  )
8317 {
8318 #ifndef NDEBUG
8319  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8320 #endif
8321  int i;
8322 
8323  assert(lp != NULL);
8324 
8325 #ifndef NDEBUG
8326  /* check, if there are really no column or row deletions or coefficient changes left */
8327  while( lp->lpifirstchgcol < lp->nlpicols
8328  && lp->lpifirstchgcol < lp->ncols
8329  && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8330  && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8331  {
8332  assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8333  lp->lpifirstchgcol++;
8334  }
8335  assert(lp->nlpicols == lp->lpifirstchgcol);
8336 
8337  while( lp->lpifirstchgrow < lp->nlpirows
8338  && lp->lpifirstchgrow < lp->nrows
8339  && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8340  && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8341  {
8342  assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8343  lp->lpifirstchgrow++;
8344  }
8345  assert(lp->nlpirows == lp->lpifirstchgrow);
8346 #endif
8347 
8348  lp->lpifirstchgcol = lp->nlpicols;
8349  lp->lpifirstchgrow = lp->nlpirows;
8350 
8351  /* check, if there are really no column or row additions left */
8352  assert(lp->ncols == lp->nlpicols);
8353  assert(lp->nrows == lp->nlpirows);
8354 
8355  /* mark the changed columns to be unchanged, and check, if this is really correct */
8356  for( i = 0; i < lp->nchgcols; ++i )
8357  {
8358  SCIP_COL* col;
8359 
8360  col = lp->chgcols[i];
8361  assert(col != NULL);
8362  assert(col->var != NULL);
8363  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8364  assert(SCIPvarGetCol(col->var) == col);
8365 
8366  if( col->lpipos >= 0 )
8367  {
8368 #ifndef NDEBUG
8369  /* do not check consistency of data with LPI in case of LPI=none */
8370  if( !lpinone )
8371  {
8372  SCIP_Real lpiobj;
8373  SCIP_Real lpilb;
8374  SCIP_Real lpiub;
8375 
8376  SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8377  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8378  assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8379  assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8380  assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8381  assert(col->flushedobj == col->obj); /*lint !e777*/
8382  assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8383  assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8384  }
8385 #endif
8386  col->objchanged = FALSE;
8387  col->lbchanged = FALSE;
8388  col->ubchanged = FALSE;
8389  }
8390  /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8391  }
8392  lp->nchgcols = 0;
8393 
8394  /* mark the changed rows to be unchanged, and check, if this is really correct */
8395  for( i = 0; i < lp->nchgrows; ++i )
8396  {
8397  SCIP_ROW* row;
8398 
8399  row = lp->chgrows[i];
8400  assert(row != NULL);
8401 
8402  if( row->lpipos >= 0 )
8403  {
8404 #ifndef NDEBUG
8405  /* do not check consistency of data with LPI in case of LPI=none */
8406  if( !lpinone )
8407  {
8408  SCIP_Real lpilhs;
8409  SCIP_Real lpirhs;
8410 
8411  SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8412  assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8413  assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8414  assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8415  assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8416  }
8417 #endif
8418  row->lhschanged = FALSE;
8419  row->rhschanged = FALSE;
8420  }
8421  }
8422  lp->nchgrows = 0;
8423 
8424  /* mark the LP to be flushed */
8425  lp->flushed = TRUE;
8426 
8427  checkLinks(lp);
8428 
8429  return SCIP_OKAY;
8430 }
8431 
8432 
8433 
8434 
8435 /*
8436  * LP methods
8437  */
8438 
8439 /** updates link data after addition of column */
8440 static
8442  SCIP_COL* col, /**< LP column */
8443  SCIP_SET* set /**< global SCIP settings */
8444  )
8445 {
8446  SCIP_ROW* row;
8447  int i;
8448  int pos;
8449 
8450  assert(col != NULL);
8451  assert(col->lppos >= 0);
8452 
8453  /* update column arrays of all linked rows */
8454  for( i = 0; i < col->len; ++i )
8455  {
8456  pos = col->linkpos[i];
8457  if( pos >= 0 )
8458  {
8459  row = col->rows[i];
8460  assert(row != NULL);
8461  assert(row->linkpos[pos] == i);
8462  assert(row->cols[pos] == col);
8463  assert(row->nlpcols <= pos && pos < row->len);
8464 
8465  row->nlpcols++;
8466  rowSwapCoefs(row, pos, row->nlpcols-1);
8467  assert(row->cols[row->nlpcols-1] == col);
8468 
8469  /* if no swap was necessary, mark lpcols to be unsorted */
8470  if( pos == row->nlpcols-1 )
8471  row->lpcolssorted = FALSE;
8472 
8473  /* update norms */
8474  rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8475  }
8476  }
8477 }
8478 
8479 /** updates link data after addition of row */
8480 static
8482  SCIP_ROW* row /**< LP row */
8483  )
8484 {
8485  SCIP_COL* col;
8486  int i;
8487  int pos;
8488 
8489  assert(row != NULL);
8490  assert(row->lppos >= 0);
8491 
8492  /* update row arrays of all linked columns */
8493  for( i = 0; i < row->len; ++i )
8494  {
8495  pos = row->linkpos[i];
8496  if( pos >= 0 )
8497  {
8498  col = row->cols[i];
8499  assert(col != NULL);
8500  assert(col->linkpos[pos] == i);
8501  assert(col->rows[pos] == row);
8502  assert(col->nlprows <= pos && pos < col->len);
8503 
8504  col->nlprows++;
8505  colSwapCoefs(col, pos, col->nlprows-1);
8506 
8507  /* if no swap was necessary, mark lprows to be unsorted */
8508  if( pos == col->nlprows-1 )
8509  col->lprowssorted = FALSE;
8510  }
8511  }
8512 }
8513 
8514 /** updates link data after removal of column */
8515 static
8517  SCIP_COL* col, /**< LP column */
8518  SCIP_SET* set /**< global SCIP settings */
8519  )
8520 {
8521  SCIP_ROW* row;
8522  int i;
8523  int pos;
8524 
8525  assert(col != NULL);
8526  assert(col->lppos == -1);
8527 
8528  /* update column arrays of all linked rows */
8529  for( i = 0; i < col->len; ++i )
8530  {
8531  pos = col->linkpos[i];
8532  if( pos >= 0 )
8533  {
8534  row = col->rows[i];
8535  assert(row != NULL);
8536  assert(row->linkpos[pos] == i);
8537  assert(row->cols[pos] == col);
8538  assert(0 <= pos && pos < row->nlpcols);
8539 
8540  /* update norms */
8541  rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8542 
8543  row->nlpcols--;
8544  rowSwapCoefs(row, pos, row->nlpcols);
8545 
8546  /* if no swap was necessary, mark nonlpcols to be unsorted */
8547  if( pos == row->nlpcols )
8548  row->nonlpcolssorted = FALSE;
8549  }
8550  }
8551 }
8552 
8553 /** updates link data after removal of row */
8554 static
8556  SCIP_ROW* row /**< LP row */
8557  )
8558 {
8559  SCIP_COL* col;
8560  int i;
8561  int pos;
8562 
8563  assert(row != NULL);
8564  assert(row->lppos == -1);
8565 
8566  /* update row arrays of all linked columns */
8567  for( i = 0; i < row->len; ++i )
8568  {
8569  pos = row->linkpos[i];
8570  if( pos >= 0 )
8571  {
8572  col = row->cols[i];
8573  assert(col != NULL);
8574  assert(0 <= pos && pos < col->nlprows);
8575  assert(col->linkpos[pos] == i);
8576  assert(col->rows[pos] == row);
8577 
8578  col->nlprows--;
8579  colSwapCoefs(col, pos, col->nlprows);
8580 
8581  /* if no swap was necessary, mark lprows to be unsorted */
8582  if( pos == col->nlprows )
8583  col->nonlprowssorted = FALSE;
8584  }
8585  }
8586 }
8587 
8588 static
8590  SCIP_LP* lp, /**< LP data object */
8591  int initsize /**< initial size of the arrays */
8592  )
8593 {
8594  assert(lp != NULL);
8595  assert(lp->divechgsides == NULL);
8596  assert(lp->divechgsidetypes == NULL);
8597  assert(lp->divechgrows == NULL);
8598  assert(lp->ndivechgsides == 0);
8599  assert(lp->divechgsidessize == 0);
8600  assert(initsize > 0);
8601 
8602  lp->divechgsidessize = initsize;
8606 
8607  return SCIP_OKAY;
8608 }
8609 
8610 static
8612  SCIP_LP* lp, /**< LP data object */
8613  int minsize, /**< minimal number of elements */
8614  SCIP_Real growfact /**< growing factor */
8615  )
8616 {
8617  assert(lp != NULL);
8618  assert(lp->divechgsides != NULL);
8619  assert(lp->divechgsidetypes != NULL);
8620  assert(lp->divechgrows != NULL);
8621  assert(lp->ndivechgsides > 0);
8622  assert(lp->divechgsidessize > 0);
8623  assert(minsize > 0);
8624 
8625  if( minsize <= lp->divechgsidessize )
8626  return SCIP_OKAY;
8627 
8628  lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
8632 
8633  return SCIP_OKAY;
8634 }
8635 
8636 static
8638  SCIP_LP* lp /**< LP data object */
8639  )
8640 {
8641  assert(lp != NULL);
8642  assert(lp->divechgsides != NULL);
8643  assert(lp->divechgsidetypes != NULL);
8644  assert(lp->divechgrows != NULL);
8645  assert(lp->ndivechgsides == 0);
8646  assert(lp->divechgsidessize > 0);
8647 
8651  lp->divechgsidessize = 0;
8652 }
8653 
8654 #define DIVESTACKINITSIZE 100
8655 
8656 /** creates empty LP data object */
8658  SCIP_LP** lp, /**< pointer to LP data object */
8659  SCIP_SET* set, /**< global SCIP settings */
8660  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8661  SCIP_STAT* stat, /**< problem statistics */
8662  const char* name /**< problem name */
8663  )
8664 {
8665  SCIP_Bool success;
8666 
8667  assert(lp != NULL);
8668  assert(set != NULL);
8669  assert(stat != NULL);
8670  assert(name != NULL);
8671 
8672  SCIP_ALLOC( BMSallocMemory(lp) );
8673 
8674  /* open LP Solver interface */
8675  SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
8676 
8677  (*lp)->lpicols = NULL;
8678  (*lp)->lpirows = NULL;
8679  (*lp)->chgcols = NULL;
8680  (*lp)->chgrows = NULL;
8681  (*lp)->cols = NULL;
8682  (*lp)->lazycols = NULL;
8683  (*lp)->rows = NULL;
8684  (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
8685  (*lp)->lpobjval = 0.0;
8686  (*lp)->glbpseudoobjval = 0.0;
8687  (*lp)->relglbpseudoobjval = 0.0;
8688  (*lp)->glbpseudoobjvalid = TRUE;
8689  (*lp)->glbpseudoobjvalinf = 0;
8690  (*lp)->pseudoobjval = 0.0;
8691  (*lp)->relpseudoobjval = 0.0;
8692  (*lp)->pseudoobjvalid = TRUE;
8693  (*lp)->pseudoobjvalinf = 0;
8694  (*lp)->looseobjval = 0.0;
8695  (*lp)->rellooseobjval = 0.0;
8696  (*lp)->looseobjvalid = TRUE;
8697  (*lp)->looseobjvalinf = 0;
8698  (*lp)->nloosevars = 0;
8699  (*lp)->rootlpobjval = SCIP_INVALID;
8700  (*lp)->rootlooseobjval = SCIP_INVALID;
8701  (*lp)->cutoffbound = SCIPsetInfinity(set);
8702  (*lp)->objsqrnorm = 0.0;
8703  (*lp)->objsumnorm = 0.0;
8704  (*lp)->lpicolssize = 0;
8705  (*lp)->nlpicols = 0;
8706  (*lp)->lpirowssize = 0;
8707  (*lp)->nlpirows = 0;
8708  (*lp)->lpifirstchgcol = 0;
8709  (*lp)->lpifirstchgrow = 0;
8710  (*lp)->colssize = 0;
8711  (*lp)->ncols = 0;
8712  (*lp)->lazycolssize = 0;
8713  (*lp)->nlazycols = 0;
8714  (*lp)->rowssize = 0;
8715  (*lp)->nrows = 0;
8716  (*lp)->chgcolssize = 0;
8717  (*lp)->nchgcols = 0;
8718  (*lp)->chgrowssize = 0;
8719  (*lp)->nchgrows = 0;
8720  (*lp)->firstnewcol = 0;
8721  (*lp)->firstnewrow = 0;
8722  (*lp)->nremovablecols = 0;
8723  (*lp)->nremovablerows = 0;
8724  (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
8725  (*lp)->validfarkaslp = -1;
8726  (*lp)->objsqrnormunreliable = FALSE;
8727  (*lp)->flushdeletedcols = FALSE;
8728  (*lp)->flushaddedcols = FALSE;
8729  (*lp)->flushdeletedrows = FALSE;
8730  (*lp)->flushaddedrows = FALSE;
8731  (*lp)->flushed = TRUE;
8732  (*lp)->solved = TRUE;
8733  (*lp)->primalfeasible = TRUE;
8734  (*lp)->dualfeasible = TRUE;
8735  (*lp)->solisbasic = FALSE;
8736  (*lp)->rootlpisrelax = TRUE;
8737  (*lp)->isrelax = TRUE;
8738  (*lp)->installing = FALSE;
8739  (*lp)->strongbranching = FALSE;
8740  (*lp)->strongbranchprobing = FALSE;
8741  (*lp)->probing = FALSE;
8742  (*lp)->diving = FALSE;
8743  (*lp)->divingobjchg = FALSE;
8744  (*lp)->divinglazyapplied = FALSE;
8745  (*lp)->divelpistate = NULL;
8746  (*lp)->divelpwasprimfeas = TRUE;
8747  (*lp)->divelpwasdualfeas = TRUE;
8748  (*lp)->divechgsides = NULL;
8749  (*lp)->divechgsidetypes = NULL;
8750  (*lp)->divechgrows = NULL;
8751  (*lp)->ndivechgsides = 0;
8752  (*lp)->divechgsidessize = 0;
8753  (*lp)->ndivingrows = 0;
8754  (*lp)->divinglpiitlim = INT_MAX;
8755  (*lp)->resolvelperror = FALSE;
8756  (*lp)->adjustlpval = FALSE;
8757  (*lp)->lpiuobjlim = SCIPlpiInfinity((*lp)->lpi);
8758  (*lp)->lpifeastol = SCIPsetLpfeastol(set);
8759  (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
8760  (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
8761  (*lp)->lpifromscratch = FALSE;
8762  (*lp)->lpifastmip = set->lp_fastmip;
8763  (*lp)->lpiscaling = set->lp_scaling;
8764  (*lp)->lpipresolving = set->lp_presolving;
8765  (*lp)->lpilpinfo = set->disp_lpinfo;
8766  (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
8767  (*lp)->lpiconditionlimit = set->lp_conditionlimit;
8768  (*lp)->lpiitlim = INT_MAX;
8769  (*lp)->lpipricing = SCIP_PRICING_AUTO;
8770  (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
8771  (*lp)->lpithreads = set->lp_threads;
8772  (*lp)->lpitiming = (int) set->time_clocktype;
8773  (*lp)->storedsolvals = NULL;
8774 
8775  /* allocate arrays for diving */
8777 
8778  /* set default parameters in LP solver */
8779  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_UOBJLIM, (*lp)->lpiuobjlim, &success) );
8780  if( !success )
8781  {
8782  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8783  "LP Solver <%s>: upper objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
8785  }
8786  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
8787  (*lp)->lpihasfeastol = success;
8788  if( !success )
8789  {
8790  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8791  "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8793  }
8794  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
8795  (*lp)->lpihasdualfeastol = success;
8796  if( !success )
8797  {
8798  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8799  "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8801  }
8802  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
8803  (*lp)->lpihasbarrierconvtol = success;
8804  if( !success )
8805  {
8806  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8807  "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8809  }
8810  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
8811  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
8812  (*lp)->lpihasfastmip = success;
8813  if( !success )
8814  {
8815  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8816  "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
8818  }
8819  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
8820  (*lp)->lpihasscaling = success;
8821  if( !success )
8822  {
8823  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8824  "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
8826  }
8827  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
8828  (*lp)->lpihaspresolving = success;
8829  if( !success )
8830  {
8831  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8832  "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
8834  }
8835  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
8836  if( !success )
8837  {
8838  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8839  "LP Solver <%s>: clock type cannot be set\n",
8841  }
8842  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
8843  if( !success )
8844  {
8845  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8846  "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
8848  }
8849  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
8850  if( !success )
8851  {
8852  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8853  "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
8855  }
8856  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
8857  if( !success )
8858  {
8859  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8860  "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
8862  }
8863  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
8864  (*lp)->lpihasrowrep = success;
8865  if( !success )
8866  {
8867  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8868  "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
8870  }
8871  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
8872  if( !success )
8873  {
8874  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8875  "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
8877  }
8878  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
8879  if( !success )
8880  {
8881  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8882  "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
8884  }
8885 
8886  return SCIP_OKAY;
8887 }
8888 
8889 /** frees LP data object */
8891  SCIP_LP** lp, /**< pointer to LP data object */
8892  BMS_BLKMEM* blkmem, /**< block memory */
8893  SCIP_SET* set, /**< global SCIP settings */
8894  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8895  SCIP_EVENTFILTER* eventfilter /**< global event filter */
8896  )
8897 {
8898  int i;
8899 
8900  assert(lp != NULL);
8901  assert(*lp != NULL);
8902 
8903  SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
8904 
8905  freeDiveChgSideArrays(*lp);
8906 
8907  /* release LPI rows */
8908  for( i = 0; i < (*lp)->nlpirows; ++i )
8909  {
8910  SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
8911  }
8912 
8913  if( (*lp)->lpi != NULL )
8914  {
8915  SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
8916  }
8917 
8918  BMSfreeMemoryNull(&(*lp)->storedsolvals);
8919  BMSfreeMemoryArrayNull(&(*lp)->lpicols);
8920  BMSfreeMemoryArrayNull(&(*lp)->lpirows);
8921  BMSfreeMemoryArrayNull(&(*lp)->chgcols);
8922  BMSfreeMemoryArrayNull(&(*lp)->chgrows);
8923  BMSfreeMemoryArrayNull(&(*lp)->lazycols);
8924  BMSfreeMemoryArrayNull(&(*lp)->cols);
8925  BMSfreeMemoryArrayNull(&(*lp)->rows);
8926  BMSfreeMemory(lp);
8927 
8928  return SCIP_OKAY;
8929 }
8930 
8931 /** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
8932  * changes to the LP solver
8933  */
8935  SCIP_LP* lp, /**< LP data */
8936  BMS_BLKMEM* blkmem, /**< block memory */
8937  SCIP_SET* set, /**< global SCIP settings */
8938  SCIP_STAT* stat, /**< problem statistics */
8939  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8940  SCIP_EVENTFILTER* eventfilter /**< global event filter */
8941  )
8942 {
8943  assert(stat != NULL);
8944 
8945  SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
8946  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
8947 
8948  /* mark the empty LP to be solved */
8950  lp->lpobjval = 0.0;
8951  lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
8952  lp->validfarkaslp = -1;
8953  lp->solved = TRUE;
8954  lp->primalfeasible = TRUE;
8955  lp->dualfeasible = TRUE;
8956  lp->solisbasic = FALSE;
8958 
8959  return SCIP_OKAY;
8960 }
8961 
8962 /** adds a column to the LP */
8964  SCIP_LP* lp, /**< LP data */
8965  SCIP_SET* set, /**< global SCIP settings */
8966  SCIP_COL* col, /**< LP column */
8967  int depth /**< depth in the tree where the column addition is performed */
8968  )
8969 {
8970  assert(lp != NULL);
8971  assert(!lp->diving);
8972  assert(col != NULL);
8973  assert(col->len == 0 || col->rows != NULL);
8974  assert(col->lppos == -1);
8975  assert(col->var != NULL);
8976  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8977  assert(SCIPvarGetCol(col->var) == col);
8978  assert(SCIPvarIsIntegral(col->var) == col->integral);
8979 
8980  SCIPdebugMessage("adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
8981 #ifdef SCIP_DEBUG
8982  {
8983  int i;
8984  SCIPdebugPrintf(" (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
8985  for( i = 0; i < col->len; ++i )
8986  SCIPdebugPrintf(" %+g<%s>", col->vals[i], col->rows[i]->name);
8987  SCIPdebugPrintf("\n");
8988  }
8989 #endif
8990 
8991  SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
8992  lp->cols[lp->ncols] = col;
8993  col->lppos = lp->ncols;
8994  col->lpdepth = depth;
8995  col->age = 0;
8996  lp->ncols++;
8997  if( col->removable )
8998  lp->nremovablecols++;
8999 
9000  if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9001  {
9002  SCIP_CALL( ensureLazycolsSize(lp, set, lp->nlazycols+1) );
9003  lp->lazycols[lp->nlazycols] = col;
9004  lp->nlazycols++;
9005  }
9006 
9007  /* mark the current LP unflushed */
9008  lp->flushed = FALSE;
9009 
9010  /* update column arrays of all linked rows */
9011  colUpdateAddLP(col, set);
9012 
9013  /* update the objective function vector norms */
9014  lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9015 
9016  checkLinks(lp);
9017 
9018  return SCIP_OKAY;
9019 }
9020 
9021 /** adds a row to the LP and captures it */
9023  SCIP_LP* lp, /**< LP data */
9024  BMS_BLKMEM* blkmem, /**< block memory buffers */
9025  SCIP_SET* set, /**< global SCIP settings */
9026  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9027  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9028  SCIP_ROW* row, /**< LP row */
9029  int depth /**< depth in the tree where the row addition is performed */
9030  )
9031 {
9032  assert(lp != NULL);
9033  assert(row != NULL);
9034  assert(row->len == 0 || row->cols != NULL);
9035  assert(row->lppos == -1);
9036 
9037  SCIProwCapture(row);
9038  SCIProwLock(row);
9039 
9040  SCIPdebugMessage("adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9041 #ifdef SCIP_DEBUG
9042  {
9043  int i;
9044  SCIPdebugPrintf(" %g <=", row->lhs);
9045  for( i = 0; i < row->len; ++i )
9046  SCIPdebugPrintf(" %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9047  if( !SCIPsetIsZero(set, row->constant) )
9048  SCIPdebugPrintf(" %+g", row->constant);
9049  SCIPdebugPrintf(" <= %g\n", row->rhs);
9050  }
9051 #endif
9052 
9053  SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9054  lp->rows[lp->nrows] = row;
9055  row->lppos = lp->nrows;
9056  row->lpdepth = depth;
9057  row->age = 0;
9058  lp->nrows++;
9059  if( row->removable )
9060  lp->nremovablerows++;
9061 
9062  /* mark the current LP unflushed */
9063  lp->flushed = FALSE;
9064 
9065  /* update row arrays of all linked columns */
9066  rowUpdateAddLP(row);
9067 
9068  checkLinks(lp);
9069 
9070  rowCalcNorms(row, set);
9071 
9072  /* check, if row addition to LP events are tracked
9073  * if so, issue ROWADDEDLP event
9074  */
9075  if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9076  {
9077  SCIP_EVENT* event;
9078 
9079  SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9080  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9081  }
9082 
9083  return SCIP_OKAY;
9084 }
9085 
9086 
9087 #ifndef NDEBUG
9088 /** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9089  * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9090  * the lazycols array
9091  */
9092 static
9094  SCIP_LP* lp, /**< LP data */
9095  SCIP_SET* set /**< global SCIP settings */
9096  )
9097 {
9098  SCIP_Bool contained;
9099  int c;
9100  int i;
9101 
9102  assert(lp != NULL);
9103 
9104  /* check if each column in the lazy column array has a counter part in the column array */
9105  for( i = 0; i < lp->nlazycols; ++i )
9106  {
9107  /* check if each lazy column has at least on lazy bound */
9108  assert(lp->lazycols[i] != NULL);
9109  assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9110 
9111  contained = FALSE;
9112  for( c = 0; c < lp->ncols; ++c )
9113  {
9114  if( lp->lazycols[i] == lp->cols[c] )
9115  {
9116  assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9117  contained = TRUE;
9118  }
9119  }
9120  assert(contained);
9121  }
9122 
9123  /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9124  * array */
9125  for( c = 0; c < lp->ncols; ++c )
9126  {
9127  contained = FALSE;
9128  assert(lp->cols[c] != NULL);
9129 
9130  for( i = 0; i < lp->nlazycols; ++i )
9131  {
9132  if( lp->lazycols[i] == lp->cols[c] )
9133  {
9134  contained = TRUE;
9135  }
9136  }
9137 
9138  assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9139  }
9140 }
9141 #else
9142 #define checkLazyColArray(lp, set) /**/
9143 #endif
9144 
9145 /** removes all columns after the given number of cols from the LP */
9147  SCIP_LP* lp, /**< LP data */
9148  SCIP_SET* set, /**< global SCIP settings */
9149  int newncols /**< new number of columns in the LP */
9150  )
9151 {
9152  SCIP_COL* col;
9153  int c;
9154 
9155  assert(lp != NULL);
9156  SCIPdebugMessage("shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9157  assert(0 <= newncols);
9158  assert(newncols <= lp->ncols);
9159 
9160  if( newncols < lp->ncols )
9161  {
9162  assert(!lp->diving);
9163 
9164  for( c = lp->ncols-1; c >= newncols; --c )
9165  {
9166  col = lp->cols[c];
9167  assert(col != NULL);
9168  assert(col->len == 0 || col->rows != NULL);
9169  assert(col->var != NULL);
9170  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9171  assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9172  assert(col->lppos == c);
9173 
9174  /* mark column to be removed from the LP */
9175  col->lppos = -1;
9176  col->lpdepth = -1;
9177  lp->ncols--;
9178 
9179  /* count removable columns */
9180  if( col->removable )
9181  lp->nremovablecols--;
9182 
9183  /* update column arrays of all linked rows */
9184  colUpdateDelLP(col, set);
9185 
9186  /* update the objective function vector norms */
9187  lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9188  }
9189  assert(lp->ncols == newncols);
9190  lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9191 
9192  /* remove columns which are deleted from the lazy column array */
9193  c = 0;
9194  while( c < lp->nlazycols )
9195  {
9196  if( lp->lazycols[c]->lppos < 0 )
9197  {
9198  lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9199  lp->nlazycols--;
9200  }
9201  else
9202  c++;
9203  }
9204 
9205  /* mark the current LP unflushed */
9206  lp->flushed = FALSE;
9207 
9208  checkLazyColArray(lp, set);
9209  checkLinks(lp);
9210  }
9211  assert(lp->nremovablecols <= lp->ncols);
9212 
9213  return SCIP_OKAY;
9214 }
9215 
9216 /** removes and releases all rows after the given number of rows from the LP */
9218  SCIP_LP* lp, /**< LP data */
9219  BMS_BLKMEM* blkmem, /**< block memory */
9220  SCIP_SET* set, /**< global SCIP settings */
9221  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9222  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9223  int newnrows /**< new number of rows in the LP */
9224  )
9225 {
9226  SCIP_ROW* row;
9227  int r;
9228 
9229  assert(lp != NULL);
9230  assert(0 <= newnrows && newnrows <= lp->nrows);
9231 
9232  SCIPdebugMessage("shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9233  if( newnrows < lp->nrows )
9234  {
9235  for( r = lp->nrows-1; r >= newnrows; --r )
9236  {
9237  row = lp->rows[r];
9238  assert(row != NULL);
9239  assert(row->len == 0 || row->cols != NULL);
9240  assert(row->lppos == r);
9241 
9242  /* mark row to be removed from the LP */
9243  row->lppos = -1;
9244  row->lpdepth = -1;
9245  lp->nrows--;
9246 
9247  /* count removable rows */
9248  if( row->removable )
9249  lp->nremovablerows--;
9250 
9251  /* update row arrays of all linked columns */
9252  rowUpdateDelLP(row);
9253 
9254  SCIProwUnlock(lp->rows[r]);
9255 
9256  /* check, if row deletion events are tracked
9257  * if so, issue ROWDELETEDLP event
9258  */
9259  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9260  {
9261  SCIP_EVENT* event;
9262 
9263  SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9264  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9265  }
9266 
9267  SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9268  }
9269  assert(lp->nrows == newnrows);
9270  lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9271 
9272  /* mark the current LP unflushed */
9273  lp->flushed = FALSE;
9274 
9275  checkLinks(lp);
9276  }
9277  assert(lp->nremovablerows <= lp->nrows);
9278 
9279  return SCIP_OKAY;
9280 }
9281 
9282 /** removes all columns and rows from LP, releases all rows */
9284  SCIP_LP* lp, /**< LP data */
9285  BMS_BLKMEM* blkmem, /**< block memory */
9286  SCIP_SET* set, /**< global SCIP settings */
9287  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9288  SCIP_EVENTFILTER* eventfilter /**< global event filter */
9289  )
9290 {
9291  assert(lp != NULL);
9292  assert(!lp->diving);
9293 
9294  SCIPdebugMessage("clearing LP\n");
9295  SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9296  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9297 
9298  return SCIP_OKAY;
9299 }
9300 
9301 /** remembers number of columns and rows to track the newly added ones */
9303  SCIP_LP* lp /**< current LP data */
9304  )
9305 {
9306  assert(lp != NULL);
9307  assert(!lp->diving);
9308 
9309  lp->firstnewrow = lp->nrows;
9310  lp->firstnewcol = lp->ncols;
9311 }
9312 
9313 /** sets the remembered number of columns and rows to the given values */
9315  SCIP_LP* lp, /**< current LP data */
9316  int nrows, /**< number of rows to set the size marker to */
9317  int ncols /**< number of columns to set the size marker to */
9318  )
9319 {
9320  assert(lp != NULL);
9321  assert(!lp->diving);
9322 
9323  lp->firstnewrow = nrows;
9324  lp->firstnewcol = ncols;
9325 }
9326 
9327 /** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9329  SCIP_LP* lp, /**< LP data */
9330  int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9331  )
9332 {
9333  assert(lp != NULL);
9334  assert(lp->flushed);
9335  assert(lp->solved);
9336  assert(lp->solisbasic);
9337  assert(basisind != NULL);
9338 
9339  SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9340 
9341  return SCIP_OKAY;
9342 }
9343 
9344 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9346  SCIP_LP* lp, /**< LP data */
9347  int* cstat, /**< array to store column basis status, or NULL */
9348  int* rstat /**< array to store row basis status, or NULL */
9349  )
9350 {
9351  assert(lp != NULL);
9352  assert(lp->flushed);
9353  assert(lp->solved);
9354  assert(lp->solisbasic);
9355 
9356  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9357 
9358  return SCIP_OKAY;
9359 }
9360 
9361 /** gets a row from the inverse basis matrix B^-1 */
9363  SCIP_LP* lp, /**< LP data */
9364  int r, /**< row number */
9365  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9366  int* inds, /**< array to store the non-zero indices, or NULL */
9367  int* ninds /**< pointer to store the number of non-zero indices, or NULL
9368  * (-1: if we do not store sparsity informations) */
9369  )
9370 {
9371  assert(lp != NULL);
9372  assert(lp->flushed);
9373  assert(lp->solved);
9374  assert(lp->solisbasic);
9375  assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9376  assert(coef != NULL);
9377 
9378  SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9379 
9380  return SCIP_OKAY;
9381 }
9382 
9383 /** gets a column from the inverse basis matrix B^-1 */
9385  SCIP_LP* lp, /**< LP data */
9386  int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9387  * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9388  * to get the array which links the B^-1 column numbers to the row and
9389  * column numbers of the LP! c must be between 0 and nrows-1, since the
9390  * basis has the size nrows * nrows */
9391  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9392  int* inds, /**< array to store the non-zero indices, or NULL */
9393  int* ninds /**< pointer to store the number of non-zero indices, or NULL
9394  * (-1: if we do not store sparsity informations) */
9395  )
9396 {
9397  assert(lp != NULL);
9398  assert(lp->flushed);
9399  assert(lp->solved);
9400  assert(lp->solisbasic);
9401  assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9402  assert(coef != NULL);
9403 
9404  SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9405 
9406  return SCIP_OKAY;
9407 }
9408 
9409 /** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9411  SCIP_LP* lp, /**< LP data */
9412  int r, /**< row number */
9413  SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9414  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9415  int* inds, /**< array to store the non-zero indices, or NULL */
9416  int* ninds /**< pointer to store the number of non-zero indices, or NULL
9417  * (-1: if we do not store sparsity informations) */
9418  )
9419 {
9420  assert(lp != NULL);
9421  assert(lp->flushed);
9422  assert(lp->solved);
9423  assert(lp->solisbasic);
9424  assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9425  assert(coef != NULL);
9426 
9427  SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9428 
9429  return SCIP_OKAY;
9430 }
9431 
9432 /** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9433  * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9434  */
9436  SCIP_LP* lp, /**< LP data */
9437  int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9438  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9439  int* inds, /**< array to store the non-zero indices, or NULL */
9440  int* ninds /**< pointer to store the number of non-zero indices, or NULL
9441  * (-1: if we do not store sparsity informations) */
9442  )
9443 {
9444  assert(lp != NULL);
9445  assert(lp->flushed);
9446  assert(lp->solved);
9447  assert(lp->solisbasic);
9448  assert(0 <= c && c < lp->ncols);
9449  assert(coef != NULL);
9450 
9451  SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9452 
9453  return SCIP_OKAY;
9454 }
9455 
9456 /** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9457  * LP row are swapped in the summation
9458  */
9460  SCIP_LP* lp, /**< LP data */
9461  SCIP_SET* set, /**< global SCIP settings */
9462  SCIP_PROB* prob, /**< problem data */
9463  SCIP_Real* weights, /**< row weights in row summation */
9464  SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9465  SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9466  SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9467  )
9468 {
9469  SCIP_ROW* row;
9470  int r;
9471  int i;
9472  int idx;
9473  SCIP_Bool lhsinfinite;
9474  SCIP_Bool rhsinfinite;
9475 
9476  assert(lp != NULL);
9477  assert(prob != NULL);
9478  assert(weights != NULL);
9479  assert(sumcoef != NULL);
9480  assert(sumlhs != NULL);
9481  assert(sumrhs != NULL);
9482 
9483  /**@todo test, if a column based summation is faster */
9484 
9485  SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9486  SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9487  *sumlhs = 0.0;
9488  *sumrhs = 0.0;
9489  lhsinfinite = FALSE;
9490  rhsinfinite = FALSE;
9491  for( r = 0; r < lp->nrows; ++r )
9492  {
9493  if( !SCIPsetIsZero(set, weights[r]) )
9494  {
9495  row = lp->rows[r];
9496  assert(row != NULL);
9497  assert(row->len == 0 || row->cols != NULL);
9498  assert(row->len == 0 || row->cols_index != NULL);
9499  assert(row->len == 0 || row->vals != NULL);
9500 
9501  /* add the row coefficients to the sum */
9502  for( i = 0; i < row->len; ++i )
9503  {
9504  assert(row->cols[i] != NULL);
9505  assert(row->cols[i]->var != NULL);
9506  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9507  assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9508  assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9509  idx = row->cols[i]->var_probindex;
9510  assert(0 <= idx && idx < prob->nvars);
9511  SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
9512  }
9513 
9514  /* add the row sides to the sum, depending on the sign of the weight */
9515  if( weights[r] > 0.0 )
9516  {
9517  lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
9518  if( !lhsinfinite )
9519  (*sumlhs) += weights[r] * (row->lhs - row->constant);
9520  rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
9521  if( !rhsinfinite )
9522  (*sumrhs) += weights[r] * (row->rhs - row->constant);
9523  }
9524  else
9525  {
9526  lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
9527  if( !lhsinfinite )
9528  (*sumlhs) += weights[r] * (row->rhs - row->constant);
9529  rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
9530  if( !rhsinfinite )
9531  (*sumrhs) += weights[r] * (row->lhs - row->constant);
9532  }
9533  }
9534  }
9535 
9536  if( lhsinfinite )
9537  *sumlhs = -SCIPsetInfinity(set);
9538  if( rhsinfinite )
9539  *sumrhs = SCIPsetInfinity(set);
9540 
9541  return SCIP_OKAY;
9542 }
9543 
9544 /** returns the maximum absolute row weight in the given weight vector, and calculates the sparsity pattern of the weights */
9545 static
9547  SCIP_SET* set, /**< global SCIP settings */
9548  SCIP_LP* lp, /**< LP data */
9549  SCIP_Real* weights, /**< row weights in row summation */
9550  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
9551  int* nrowinds, /**< pointer to store number of used rows */
9552  int* rowlensum /**< pointer to store total number of non-zeros in used rows */
9553  )
9554 {
9555  SCIP_Real maxabsweight;
9556  int r;
9557 
9558  assert(set != NULL);
9559  assert(lp != NULL);
9560  assert(weights != NULL);
9561  assert(rowinds != NULL);
9562  assert(nrowinds != NULL);
9563 
9564  *nrowinds = 0;
9565  *rowlensum = 0;
9566 
9567  maxabsweight = 0.0;
9568  for( r = 0; r < lp->nrows; ++r )
9569  {
9570  SCIP_Real absweight;
9571 
9572  /* skip unused rows */
9573  if( SCIPsetIsZero(set, weights[r]) )
9574  continue;
9575 
9576  /* record the row in the sparsity pattern */
9577  rowinds[*nrowinds] = r;
9578  (*nrowinds)++;
9579 
9580  (*rowlensum) += SCIProwGetNNonz(lp->rows[r]);
9581 
9582  absweight = REALABS(weights[r]);
9583  maxabsweight = MAX(maxabsweight, absweight);
9584  }
9585 
9586  return maxabsweight;
9587 }
9588 
9589 /** returns the maximum absolute row weight in the given weight vector using given sparsity pattern */
9590 static
9592  SCIP_SET* set, /**< global SCIP settings */
9593  SCIP_LP* lp, /**< LP data */
9594  SCIP_Real* weights, /**< row weights in row summation */
9595  int* rowinds, /**< array of sparsity pattern of used rows; size lp->nrows */
9596  int* nrowinds, /**< pointer to store number of used rows */
9597  int* rowlensum /**< pointer to store total number of non-zeros in used rows */
9598  )
9599 {
9600  SCIP_Real maxabsweight;
9601  int r; /* index used for reading from the row*/
9602  int w; /* auxiliary index to skip zeros in weights array */
9603 
9604  assert(set != NULL);
9605  assert(lp != NULL);
9606  assert(weights != NULL);
9607  assert(rowinds != NULL);
9608  assert(nrowinds != NULL);
9609 
9610  *rowlensum = 0;
9611 
9612  maxabsweight = 0.0;
9613  w = 0;
9614  for( r = 0; r < *nrowinds; ++r )
9615  {
9616  SCIP_Real absweight;
9617 
9618  /* remove zeros from the sparsity pattern */
9619  if( SCIPsetIsZero(set, weights[rowinds[r]]) )
9620  continue;
9621 
9622  rowinds[w] = rowinds[r];
9623  ++w;
9624 
9625  (*rowlensum) += SCIProwGetNNonz(lp->rows[rowinds[r]]);
9626 
9627  absweight = REALABS(weights[rowinds[r]]);
9628  maxabsweight = MAX(maxabsweight, absweight);
9629  }
9630  (*nrowinds) = w;
9631 
9632  return maxabsweight;
9633 }
9634 
9635 
9636 /** adds a single row to an aggregation */
9637 static
9639  SCIP_SET* set, /**< global SCIP settings */
9640  SCIP_Real* mircoef, /**< array of aggregation coefficients: must be of size prob->nvars */
9641  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9642  int* slacksign, /**< stores the sign of the row's slack variable in summation */
9643  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
9644  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
9645  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
9646  SCIP_ROW* row, /**< row to add to the aggregation */
9647  SCIP_Real weight, /**< weight of row in aggregation */
9648  SCIP_Bool uselhs /**< TRUE if lhs should be used, FALSE if rhs should be used */
9649  )
9650 {
9651  SCIP_Real sideval;
9652  int r;
9653  int i;
9654 
9655  assert(mircoef != NULL);
9656  assert(mirrhs != NULL);
9657  assert(slacksign != NULL);
9658  assert(varused != NULL);
9659  assert(varinds != NULL);
9660  assert(nvarinds != NULL);
9661  assert(row != NULL);
9662  assert(weight != 0.0);
9663 
9664  r = row->lppos;
9665  assert(r >= 0);
9666 
9667  /* update the right hand side */
9668  if( uselhs )
9669  {
9670  slacksign[r] = -1;
9671  sideval = row->lhs - row->constant;
9672  if( row->integral )
9673  sideval = SCIPsetFeasCeil(set, sideval); /* row is integral: round left hand side up */
9674  }
9675  else
9676  {
9677  slacksign[r] = +1;
9678  sideval = row->rhs - row->constant;
9679  if( row->integral )
9680  sideval = SCIPsetFeasFloor(set, sideval); /* row is integral: round right hand side up */
9681  }
9682  (*mirrhs) += weight * sideval;
9683 
9684  /* add the row coefficients to the sum */
9685  for( i = 0; i < row->len; ++i )
9686  {
9687  int idx;
9688 
9689  assert(row->cols[i] != NULL);
9690  assert(row->cols[i]->var != NULL);
9691  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9692  assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9693  assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9694  idx = row->cols[i]->var_probindex;
9695  mircoef[idx] += weight * row->vals[i];
9696 
9697  /* record the variable in the sparsity pattern */
9698  if( !varused[idx] )
9699  {
9700  varused[idx] = TRUE;
9701  varinds[*nvarinds] = idx;
9702  (*nvarinds)++;
9703  }
9704  }
9705 }
9706 
9707 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
9708 static
9710  SCIP_SET* set, /**< global SCIP settings */
9711  SCIP_PROB* prob, /**< problem data */
9712  SCIP_LP* lp, /**< LP data */
9713  SCIP_Real* weights, /**< row weights in row summation */
9714  SCIP_Real knownmaxweight, /**< largest magnitude of weights. Set to 0 if compress == TRUE */
9715  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
9716  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
9717  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
9718  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
9719  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
9720  SCIP_Bool compress, /**< if rowinds is unknown and weights should be compressed */
9721  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size prob->nvars */
9722  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9723  int* slacksign, /**< stores the sign of the row's slack variable in summation */
9724  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
9725  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
9726  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
9727  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
9728  int* nrowinds, /**< pointer to store number of used rows */
9729  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
9730  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
9731  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
9732  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
9733  )
9734 {
9735  SCIP_Real maxweight;
9736  int maxrank = 0;
9737  int rowlensum;
9738  int i;
9739 
9740  assert(prob != NULL);
9741  assert(lp != NULL);
9742  assert(weights != NULL);
9743  assert(!SCIPsetIsZero(set, scale));
9744  assert(maxweightrange >= 1.0);
9745  assert(mircoef != NULL);
9746  assert(mirrhs != NULL);
9747  assert(slacksign != NULL);
9748  assert(varused != NULL);
9749  assert(varinds != NULL);
9750  assert(nvarinds != NULL);
9751  assert(rowinds != NULL);
9752  assert(nrowinds != NULL);
9753  assert(emptyrow != NULL);
9754  assert(localrowsused != NULL);
9755  assert(rowtoolong != NULL);
9756 
9757  rowlensum = 0;
9758  *nvarinds = 0;
9759  *mirrhs = 0.0;
9760  *emptyrow = TRUE;
9761  *localrowsused = FALSE;
9762  *rowtoolong = FALSE;
9763 
9764  /* initialize varused array */
9765  BMSclearMemoryArray(varused, prob->nvars);
9766 
9767  /* if compression of the dense weight vector is required */
9768  /* search the maximal absolute weight and calculate the row sparsity pattern */
9769  if( compress )
9770  {
9771  maxweight = getMaxAbsWeightCalcSparsity(set, lp, weights, rowinds, nrowinds, &rowlensum);
9772  }
9773  else
9774  {
9775  /* search the maximal absolute weight using the given row sparsity pattern */
9776  if( knownmaxweight == -1 )
9777  {
9778  assert(*nrowinds > -1);
9779  maxweight = getMaxAbsWeight(set, lp, weights, rowinds, nrowinds, &rowlensum);
9780  }
9781  else
9782  maxweight = knownmaxweight;
9783  }
9784 
9785  /* if the total number of non-zeros is way too large, we just skip this aggregation */
9786  if( rowlensum/5 > maxmksetcoefs )
9787  {
9788  *rowtoolong = TRUE;
9789  return;
9790  }
9791 
9792  maxweight *= ABS(scale);
9793 
9794  /* calculate the row summation */
9795  BMSclearMemoryArray(mircoef, prob->nvars);
9796  i = 0;
9797  while( i < *nrowinds )
9798  {
9799  SCIP_ROW* row;
9800  SCIP_Real weight;
9801  SCIP_Real absweight;
9802  int r;
9803 
9804  r = rowinds[i];
9805  assert(0 <= r && r < lp->nrows);
9806  assert(weights[r] != 0.0);
9807 
9808  row = lp->rows[r];
9809  assert(row != NULL);
9810  assert(row->len == 0 || row->cols != NULL);
9811  assert(row->len == 0 || row->cols_index != NULL);
9812  assert(row->len == 0 || row->vals != NULL);
9813 
9814  /* modifiable rows cannot be part of a MIR row summation;
9815  * local rows are only included, if the allowlocal flag is set;
9816  * close to zero weights or weights outside the maximal range are ignored
9817  */
9818  weight = scale * weights[r];
9819  absweight = REALABS(weight);
9820  if( !row->modifiable && (allowlocal || !row->local)
9821  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
9822  {
9823  SCIP_Bool uselhs;
9824 
9825  /* choose sides for lhs/rhs of row */
9826  if ( sidetypes != NULL )
9827  {
9828  assert( sidetypes[r] == -1 || sidetypes[r] == 0 || sidetypes[r] == 1 );
9829  if ( sidetypes[r] == -1 )
9830  {
9831  assert( ! SCIPsetIsInfinity(set, -row->lhs) );
9832  uselhs = TRUE;
9833  }
9834  else if ( sidetypes[r] == 1 )
9835  {
9836  assert( ! SCIPsetIsInfinity(set, row->rhs) );
9837  uselhs = FALSE;
9838  }
9839  else
9840  {
9841  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
9842  * If possible, use the side that leads to a positive slack value in the summation.
9843  */
9844  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
9845  uselhs = TRUE;
9846  else
9847  uselhs = FALSE;
9848  }
9849  }
9850  else
9851  {
9852  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
9853  * If possible, use the side that leads to a positive slack value in the summation.
9854  */
9855  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
9856  uselhs = TRUE;
9857  else
9858  uselhs = FALSE;
9859  }
9860 
9861  /* add the row to the aggregation */
9862  addRowToAggregation(set, mircoef, mirrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
9863  *emptyrow = FALSE;
9864  *localrowsused = *localrowsused || row->local;
9865 
9866  SCIPdebugMessage("MIR: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
9867  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
9868  scale, weights[r], slacksign[r], *mirrhs);
9869  debugRowPrint(row);
9870 
9871  /* update the rank of the aggregation */
9872  maxrank = MAX(maxrank, row->rank);
9873 
9874  ++i; /* handle next row */
9875  }
9876  else
9877  {
9878  /* remove row from sparsity pattern, do not increase i (i-th position is filled with last entry) */
9879  rowinds[i] = rowinds[(*nrowinds)-1];
9880  (*nrowinds)--;
9881 #ifndef NDEBUG
9882  slacksign[r] = 0;
9883 #endif
9884  }
9885  }
9886 
9887  /* check if the total number of non-zeros is too large */
9888  if( *nvarinds > maxmksetcoefs )
9889  *rowtoolong = TRUE;
9890 
9891  /* set rank of the aggregated cut */
9892  if( cutrank != NULL )
9893  *cutrank = maxrank + 1;
9894 }
9895 
9896 /** removes all nearly-zero coefficients from MIR row and relaxes the right hand side correspondingly in order to
9897  * prevent numerical rounding errors
9898  */
9899 static
9901  SCIP_SET* set, /**< global SCIP settings */
9902  SCIP_PROB* prob, /**< problem data */
9903  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
9904  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9905  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
9906  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
9907  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
9908  SCIP_Bool cutislocal /**< is the cut only valid locally? */
9909  )
9910 {
9911  SCIP_Bool rhsinf;
9912  int i;
9913 
9914  assert(prob != NULL);
9915  assert(mircoef != NULL);
9916  assert(mirrhs != NULL);
9917  assert(varused != NULL);
9918  assert(varinds != NULL);
9919  assert(nvarinds != NULL);
9920 
9921  rhsinf = SCIPsetIsInfinity(set, *mirrhs);
9922  i = 0;
9923  while( i < *nvarinds )
9924  {
9925  int v;
9926 
9927  v = varinds[i];
9928  assert(0 <= v && v < prob->nvars);
9929  assert(varused[v]);
9930 
9931  if( SCIPsetIsSumZero(set, mircoef[v]) )
9932  {
9933  SCIP_Real bd;
9934 
9935  SCIPdebugMessage("coefficient of <%s> in transformed MIR row is too small: %.12f\n",
9936  SCIPvarGetName(prob->vars[v]), mircoef[v]);
9937 
9938  /* relax the constraint such that the coefficient becomes exactly 0.0 */
9939  if( SCIPsetIsPositive(set, mircoef[v]) )
9940  {
9941  bd = cutislocal ? SCIPvarGetLbLocal(prob->vars[v]) : SCIPvarGetLbGlobal(prob->vars[v]);
9942  rhsinf = SCIPsetIsInfinity(set, -bd);
9943  }
9944  else if( SCIPsetIsNegative(set, mircoef[v]) )
9945  {
9946  bd = cutislocal ? SCIPvarGetUbLocal(prob->vars[v]) : SCIPvarGetUbGlobal(prob->vars[v]);
9947  rhsinf = SCIPsetIsInfinity(set, bd);
9948  }
9949  else
9950  bd = 0.0;
9951  *mirrhs -= bd * mircoef[v];
9952  mircoef[v] = 0.0;
9953 
9954  /* remove variable from sparsity pattern, do not increase i (i-th position is filled with last entry) */
9955  varused[v] = FALSE;
9956  varinds[i] = varinds[(*nvarinds)-1];
9957  (*nvarinds)--;
9958  }
9959  else
9960  ++i;
9961  }
9962  if( rhsinf )
9963  *mirrhs = SCIPsetInfinity(set);
9964 }
9965 
9966 /** finds the best lower bound of the variable to use for MIR transformation */
9967 static
9969  SCIP_SET* set, /**< global SCIP settings */
9970  SCIP_STAT* stat, /**< problem statistics */
9971  SCIP_VAR* var, /**< problem variable */
9972  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
9973  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
9974  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
9975  SCIP_Real* bestlb, /**< pointer to store best bound value */
9976  int* bestlbtype /**< pointer to store best bound type */
9977  )
9978 {
9979  assert(bestlb != NULL);
9980  assert(bestlbtype != NULL);
9981 
9982  *bestlb = SCIPvarGetLbGlobal(var);
9983  *bestlbtype = -1;
9984 
9985  if( allowlocal )
9986  {
9987  SCIP_Real loclb;
9988 
9989  loclb = SCIPvarGetLbLocal(var);
9990  if( SCIPsetIsGT(set, loclb, *bestlb) )
9991  {
9992  *bestlb = loclb;
9993  *bestlbtype = -2;
9994  }
9995  }
9996  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
9997  {
9998  SCIP_Real bestvlb;
9999  int bestvlbidx;
10000 
10001  SCIPvarGetClosestVlb(var, sol, set, stat, &bestvlb, &bestvlbidx);
10002  if( bestvlbidx >= 0
10003  && (bestvlb > *bestlb || (*bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, *bestlb))) )
10004  {
10005  SCIP_VAR** vlbvars;
10006 
10007  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10008  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
10009  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
10010  */
10011  vlbvars = SCIPvarGetVlbVars(var);
10012  assert(vlbvars != NULL);
10013  if( SCIPvarGetProbindex(vlbvars[bestvlbidx]) < SCIPvarGetProbindex(var) )
10014  {
10015  *bestlb = bestvlb;
10016  *bestlbtype = bestvlbidx;
10017  }
10018  }
10019  }
10020 }
10021 
10022 /** finds the best upper bound of the variable to use for MIR transformation */
10023 static
10025  SCIP_SET* set, /**< global SCIP settings */
10026  SCIP_STAT* stat, /**< problem statistics */
10027  SCIP_VAR* var, /**< problem variable */
10028  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10029  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
10030  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
10031  SCIP_Real* bestub, /**< pointer to store best bound value */
10032  int* bestubtype /**< pointer to store best bound type */
10033  )
10034 {
10035  assert(bestub != NULL);
10036  assert(bestubtype != NULL);
10037 
10038  *bestub = SCIPvarGetUbGlobal(var);
10039  *bestubtype = -1;
10040  if( allowlocal )
10041  {
10042  SCIP_Real locub;
10043 
10044  locub = SCIPvarGetUbLocal(var);
10045  if( SCIPsetIsLT(set, locub, *bestub) )
10046  {
10047  *bestub = locub;
10048  *bestubtype = -2;
10049  }
10050  }
10051  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
10052  {
10053  SCIP_Real bestvub;
10054  int bestvubidx;
10055 
10056  SCIPvarGetClosestVub(var, sol, set, stat, &bestvub, &bestvubidx);
10057  if( bestvubidx >= 0
10058  && (bestvub < *bestub || (*bestubtype < 0 && SCIPsetIsLE(set, bestvub, *bestub))) )
10059  {
10060  SCIP_VAR** vubvars;
10061 
10062  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10063  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
10064  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
10065  */
10066  vubvars = SCIPvarGetVubVars(var);
10067  assert(vubvars != NULL);
10068  if( SCIPvarGetProbindex(vubvars[bestvubidx]) < SCIPvarGetProbindex(var) )
10069  {
10070  *bestub = bestvub;
10071  *bestubtype = bestvubidx;
10072  }
10073  }
10074  }
10075 }
10076 
10077 /** Transform equation \f$ a \cdot x = b; lb \leq x \leq ub \f$ into standard form
10078  * \f$ a^\prime \cdot x^\prime = b,\; 0 \leq x^\prime \leq ub' \f$.
10079  *
10080  * Transform variables (lb or ub):
10081  * \f[
10082  * \begin{array}{llll}
10083  * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \mbox{if lb is used in transformation}\\
10084  * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if ub is used in transformation}
10085  * \end{array}
10086  * \f]
10087  * and move the constant terms \f$ a_j\, lb_j \f$ or \f$ a_j\, ub_j \f$ to the rhs.
10088  *
10089  * Transform variables (vlb or vub):
10090  * \f[
10091  * \begin{array}{llll}
10092  * x^\prime_j := x_j - (bl_j\, zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \mbox{if vlb is used in transf.} \\
10093  * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if vub is used in transf.}
10094  * \end{array}
10095  * \f]
10096  * move the constant terms \f$ a_j\, dl_j \f$ or \f$ a_j\, du_j \f$ to the rhs, and update the coefficient of the VLB variable:
10097  * \f[
10098  * \begin{array}{ll}
10099  * a_{zl_j} := a_{zl_j} + a_j\, bl_j,& \mbox{or} \\
10100  * a_{zu_j} := a_{zu_j} + a_j\, bu_j &
10101  * \end{array}
10102  * \f]
10103  */
10104 static
10106  SCIP_SET* set, /**< global SCIP settings */
10107  SCIP_STAT* stat, /**< problem statistics */
10108  SCIP_PROB* prob, /**< problem data */
10109  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10110  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
10111  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
10112  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
10113  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
10114  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
10115  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
10116  * NULL for using closest bound for all variables */
10117  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
10118  * NULL for using closest bound for all variables */
10119  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
10120  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
10121  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10122  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10123  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
10124  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10125  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
10126  int* varsign, /**< stores the sign of the transformed variable in summation */
10127  int* boundtype, /**< stores the bound used for transformed variable:
10128  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
10129  SCIP_Bool* freevariable, /**< stores whether a free variable was found in MIR row -> invalid summation */
10130  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
10131  )
10132 {
10133  SCIP_Real* bestlbs;
10134  SCIP_Real* bestubs;
10135  int* bestlbtypes;
10136  int* bestubtypes;
10137  int i;
10138 
10139  assert(prob != NULL);
10140  assert(mircoef != NULL);
10141  assert(mirrhs != NULL);
10142  assert(varused != NULL);
10143  assert(varinds != NULL);
10144  assert(nvarinds != NULL);
10145  assert(varsign != NULL);
10146  assert(boundtype != NULL);
10147  assert(freevariable != NULL);
10148  assert(localbdsused != NULL);
10149 
10150  *freevariable = FALSE;
10151  *localbdsused = FALSE;
10152 
10153 #ifndef NDEBUG
10154  /* in debug mode, make sure that the whole array is initialized with invalid values */
10155  for( i = 0; i < prob->nvars; i++ )
10156  {
10157  varsign[i] = 0;
10158  boundtype[i] = -1;
10159  }
10160 #endif
10161 
10162  /* allocate temporary memory to store best bounds and bound types */
10163  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbs, prob->nvars) );
10164  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubs, prob->nvars) );
10165  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbtypes, prob->nvars) );
10166  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubtypes, prob->nvars) );
10167 
10168  /* start with continuous variables, because using variable bounds can affect the untransformed integral
10169  * variables, and these changes have to be incorporated in the transformation of the integral variables
10170  * (continuous variables have largest problem indices!)
10171  */
10172  SCIPsortDownInt(varinds, *nvarinds);
10173 
10174  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
10175  * substitute integral variables with best standard bound (lb, ub)
10176  */
10177  i = 0;
10178  while( i < *nvarinds )
10179  {
10180  SCIP_VAR* var;
10181  SCIP_Real bestlb;
10182  SCIP_Real bestub;
10183  SCIP_Bool uselb;
10184  int bestlbtype;
10185  int bestubtype;
10186  int v;
10187 
10188  v = varinds[i];
10189  assert(0 <= v && v < prob->nvars);
10190  assert(varused[v]);
10191 
10192  var = prob->vars[v];
10193  assert(v == SCIPvarGetProbindex(var));
10194 
10195  /* due to variable bound usage cancellation may occur,
10196  * do not increase i, since last element is copied to the i-th position
10197  */
10198  if( SCIPsetIsZero(set, mircoef[v]) )
10199  {
10200  varsign[v] = +1;
10201  boundtype[v] = -1;
10202  mircoef[v] = 0.0;
10203  varused[v] = FALSE;
10204  varinds[i] = varinds[(*nvarinds)-1];
10205  (*nvarinds)--;
10206  continue;
10207  }
10208 
10209  /* check if the user specified a bound to be used */
10210  if( boundsfortrans != NULL && boundsfortrans[v] > -3 )
10211  {
10212  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || ( boundsfortrans[v] == -2 || boundsfortrans[v] == -1 ));
10213 
10214  /* user has explicitly specified a bound to be used */
10215  if( boundtypesfortrans[v] == SCIP_BOUNDTYPE_LOWER )
10216  {
10217  /* user wants to use lower bound */
10218  bestlbtype = boundsfortrans[v];
10219  if( bestlbtype == -1 )
10220  bestlb = SCIPvarGetLbGlobal(var); /* use global standard lower bound */
10221  else if( bestlbtype == -2 )
10222  bestlb = SCIPvarGetLbLocal(var); /* use local standard lower bound */
10223  else
10224  {
10225  SCIP_VAR** vlbvars;
10226  SCIP_Real* vlbcoefs;
10227  SCIP_Real* vlbconsts;
10228  int k;
10229 
10230  /* use the given variable lower bound */
10231  vlbvars = SCIPvarGetVlbVars(var);
10232  vlbcoefs = SCIPvarGetVlbCoefs(var);
10233  vlbconsts = SCIPvarGetVlbConstants(var);
10234  k = boundsfortrans[v];
10235  assert(k >= 0 && k < SCIPvarGetNVlbs(var));
10236  assert(vlbvars != NULL);
10237  assert(vlbcoefs != NULL);
10238  assert(vlbconsts != NULL);
10239 
10240  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10241  if( SCIPvarGetProbindex(vlbvars[k]) < v )
10242  bestlb = vlbcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[k]) : SCIPsolGetVal(sol, set, stat, vlbvars[k])) + vlbconsts[k];
10243  else
10244  {
10245  bestlbtype = -1; /* fall back to global standard bound */
10246  bestlb = SCIPvarGetLbGlobal(var);
10247  }
10248  }
10249 
10250  assert(!SCIPsetIsInfinity(set, -bestlb));
10251  uselb = TRUE;
10252 
10253  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
10254  findBestUb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestub, &bestubtype);
10255  }
10256  else
10257  {
10258  assert(boundtypesfortrans[v] == SCIP_BOUNDTYPE_UPPER);
10259 
10260  /* user wants to use upper bound */
10261  bestubtype = boundsfortrans[v];
10262  if( bestubtype == -1 )
10263  bestub = SCIPvarGetUbGlobal(var); /* use global standard upper bound */
10264  else if( bestubtype == -2 )
10265  bestub = SCIPvarGetUbLocal(var); /* use local standard upper bound */
10266  else
10267  {
10268  SCIP_VAR** vubvars;
10269  SCIP_Real* vubcoefs;
10270  SCIP_Real* vubconsts;
10271  int k;
10272 
10273  /* use the given variable upper bound */
10274  vubvars = SCIPvarGetVubVars(var);
10275  vubcoefs = SCIPvarGetVubCoefs(var);
10276  vubconsts = SCIPvarGetVubConstants(var);
10277  k = boundsfortrans[v];
10278  assert(k >= 0 && k < SCIPvarGetNVubs(var));
10279  assert(vubvars != NULL);
10280  assert(vubcoefs != NULL);
10281  assert(vubconsts != NULL);
10282 
10283  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10284  if( SCIPvarGetProbindex(vubvars[k]) < v )
10285  bestub = vubcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vubvars[k]) : SCIPsolGetVal(sol, set, stat, vubvars[k])) + vubconsts[k];
10286  else
10287  {
10288  bestubtype = -1; /* fall back to global standard bound */
10289  bestub = SCIPvarGetUbGlobal(var);
10290  }
10291  }
10292 
10293  assert(!SCIPsetIsInfinity(set, bestub));
10294  uselb = FALSE;
10295 
10296  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
10297  findBestLb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestlb, &bestlbtype);
10298  }
10299  }
10300  else
10301  {
10302  SCIP_Real varsol;
10303 
10304  /* bound selection should be done automatically */
10305 
10306  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
10307  findBestLb(set, stat, var, sol, usevbds, allowlocal, &bestlb, &bestlbtype);
10308 
10309  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
10310  findBestUb(set, stat, var, sol, usevbds, allowlocal, &bestub, &bestubtype);
10311 
10312  /* check, if variable is free variable */
10313  if( SCIPsetIsInfinity(set, -bestlb) && SCIPsetIsInfinity(set, bestub) )
10314  {
10315  /* we found a free variable in the row with non-zero coefficient
10316  * -> MIR row can't be transformed in standard form
10317  */
10318  *freevariable = TRUE;
10319  goto TERMINATE;
10320  }
10321 
10322  /* select transformation bound */
10323  varsol = (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var));
10324  if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
10325  uselb = TRUE;
10326  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
10327  uselb = FALSE;
10328  else if( bestlbtype == -1 ) /* prefer global standard bounds */
10329  uselb = TRUE;
10330  else if( bestubtype == -1 ) /* prefer global standard bounds */
10331  uselb = FALSE;
10332  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
10333  uselb = TRUE;
10334  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
10335  uselb = FALSE;
10336  else
10337  uselb = TRUE; /* no decision yet? just use lower bound */
10338  }
10339 
10340  /* remember given/best bounds and types */
10341  bestlbs[v] = bestlb;
10342  bestubs[v] = bestub;
10343  bestlbtypes[v] = bestlbtype;
10344  bestubtypes[v] = bestubtype;
10345 
10346  /* perform bound substitution */
10347  if( uselb )
10348  {
10349  assert(!SCIPsetIsInfinity(set, -bestlb));
10350 
10351  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
10352  boundtype[v] = bestlbtype;
10353  varsign[v] = +1;
10354 
10355  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
10356  if( bestlbtype < 0 )
10357  {
10358  (*mirrhs) -= mircoef[v] * bestlb;
10359  *localbdsused = *localbdsused || (bestlbtype == -2);
10360  }
10361  else
10362  {
10363  SCIP_VAR** vlbvars;
10364  SCIP_Real* vlbcoefs;
10365  SCIP_Real* vlbconsts;
10366  int zidx;
10367 
10368  vlbvars = SCIPvarGetVlbVars(var);
10369  vlbcoefs = SCIPvarGetVlbCoefs(var);
10370  vlbconsts = SCIPvarGetVlbConstants(var);
10371  assert(vlbvars != NULL);
10372  assert(vlbcoefs != NULL);
10373  assert(vlbconsts != NULL);
10374 
10375  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
10376  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
10377  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
10378  assert(0 <= zidx && zidx < v);
10379 
10380  (*mirrhs) -= mircoef[v] * vlbconsts[bestlbtype];
10381  mircoef[zidx] += mircoef[v] * vlbcoefs[bestlbtype];
10382 
10383  /* update sparsity pattern */
10384  if( !varused[zidx] )
10385  {
10386  assert(*nvarinds < prob->nvars);
10387  varused[zidx] = TRUE;
10388  varinds[*nvarinds] = zidx;
10389  (*nvarinds)++;
10390  }
10391  }
10392  }
10393  else
10394  {
10395  assert(!SCIPsetIsInfinity(set, bestub));
10396 
10397  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
10398  boundtype[v] = bestubtype;
10399  varsign[v] = -1;
10400 
10401  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
10402  if( bestubtype < 0 )
10403  {
10404  (*mirrhs) -= mircoef[v] * bestub;
10405  *localbdsused = *localbdsused || (bestubtype == -2);
10406  }
10407  else
10408  {
10409  SCIP_VAR** vubvars;
10410  SCIP_Real* vubcoefs;
10411  SCIP_Real* vubconsts;
10412  int zidx;
10413 
10414  vubvars = SCIPvarGetVubVars(var);
10415  vubcoefs = SCIPvarGetVubCoefs(var);
10416  vubconsts = SCIPvarGetVubConstants(var);
10417  assert(vubvars != NULL);
10418  assert(vubcoefs != NULL);
10419  assert(vubconsts != NULL);
10420 
10421  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
10422  assert(SCIPvarIsActive(vubvars[bestubtype]));
10423  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
10424  assert(zidx >= 0);
10425 
10426  (*mirrhs) -= mircoef[v] * vubconsts[bestubtype];
10427  mircoef[zidx] += mircoef[v] * vubcoefs[bestubtype];
10428 
10429  /* update sparsity pattern */
10430  if( !varused[zidx] )
10431  {
10432  assert(*nvarinds < prob->nvars);
10433  varused[zidx] = TRUE;
10434  varinds[*nvarinds] = zidx;
10435  (*nvarinds)++;
10436  }
10437  }
10438  }
10439  ++i; /* increase iterator */
10440 
10441 #ifdef SCIP_DEBUG
10442  if( bestlbtype >= 0 )
10443  {
10444  assert(bestlbtype < SCIPvarGetNVlbs(var));
10445  assert(SCIPvarGetVlbVars(var) != NULL);
10446  assert(SCIPvarGetVlbCoefs(var) != NULL);
10447  assert(SCIPvarGetVlbConstants(var) != NULL);
10448  }
10449  if( bestubtype >= 0 )
10450  {
10451  assert(bestubtype < SCIPvarGetNVubs(var));
10452  assert(SCIPvarGetVubVars(var) != NULL);
10453  assert(SCIPvarGetVubCoefs(var) != NULL);
10454  assert(SCIPvarGetVubConstants(var) != NULL);
10455  }
10456 
10457  SCIPdebugMessage("MIR var <%s>: varsign=%d, boundtype=%d, mircoef=%g, base=%d, sol=%g, lb=%g, ub=%g, vlb=%g<%s>%+g, vub=%g<%s>%+g -> rhs=%g\n",
10458  SCIPvarGetName(var), varsign[v], boundtype[v], mircoef[v],
10460  (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var)), bestlb, bestub,
10461  bestlbtype >= 0 ? SCIPvarGetVlbCoefs(var)[bestlbtype] : 0.0,
10462  bestlbtype >= 0 ? SCIPvarGetName(SCIPvarGetVlbVars(var)[bestlbtype]) : "-",
10463  bestlbtype >= 0 ? SCIPvarGetVlbConstants(var)[bestlbtype] : bestlb,
10464  bestubtype >= 0 ? SCIPvarGetVubCoefs(var)[bestubtype] : 0.0,
10465  bestubtype >= 0 ? SCIPvarGetName(SCIPvarGetVubVars(var)[bestubtype]) : "-",
10466  bestubtype >= 0 ? SCIPvarGetVubConstants(var)[bestubtype] : bestub,
10467  *mirrhs);
10468 #endif
10469  }
10470 
10471  if( fixintegralrhs )
10472  {
10473  SCIP_Real f0;
10474 
10475  /* check if rhs is fractional */
10476  f0 = SCIPsetSumFrac(set, *mirrhs);
10477  if( f0 < minfrac || f0 > maxfrac )
10478  {
10479  SCIP_Real bestviolgain;
10480  SCIP_Real bestnewf0;
10481  int bestv;
10482 
10483  /* choose complementation of one variable differently such that f0 is in correct range */
10484  bestv = -1;
10485  bestviolgain = -1e+100;
10486  bestnewf0 = 1.0;
10487  for( i = 0; i < *nvarinds; i++ )
10488  {
10489  int v;
10490 
10491  v = varinds[i];
10492  assert(0 <= v && v < prob->nvars);
10493  assert(varused[v]);
10494  assert(!SCIPsetIsZero(set, mircoef[v]));
10495 
10496  if( boundtype[v] < 0
10497  && ((varsign[v] == +1 && !SCIPsetIsInfinity(set, bestubs[v]) && bestubtypes[v] < 0)
10498  || (varsign[v] == -1 && !SCIPsetIsInfinity(set, -bestlbs[v]) && bestlbtypes[v] < 0)) )
10499  {
10500  SCIP_Real fj;
10501  SCIP_Real newfj;
10502  SCIP_Real newrhs;
10503  SCIP_Real newf0;
10504  SCIP_Real solval;
10505  SCIP_Real viol;
10506  SCIP_Real newviol;
10507  SCIP_Real violgain;
10508 
10509  /* currently: a'_j = varsign * a_j -> f'_j = a'_j - floor(a'_j)
10510  * after complementation: a''_j = -varsign * a_j -> f''_j = a''_j - floor(a''_j) = 1 - f'_j
10511  * rhs'' = rhs' + varsign * a_j * (lb_j - ub_j)
10512  * cut violation from f0 and fj: f'_0 - f'_j * x'_j
10513  * after complementation: f''_0 - f''_j * x''_j
10514  *
10515  * for continuous variables, we just set f'_j = f''_j = |a'_j|
10516  */
10517  newrhs = *mirrhs + varsign[v] * mircoef[v] * (bestlbs[v] - bestubs[v]);
10518  newf0 = SCIPsetSumFrac(set, newrhs);
10519  if( newf0 < minfrac || newf0 > maxfrac )
10520  continue;
10521  if( SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10522  {
10523  fj = REALABS(mircoef[v]);
10524  newfj = fj;
10525  }
10526  else
10527  {
10528  fj = SCIPsetFrac(set, varsign[v] * mircoef[v]);
10529  newfj = SCIPsetFrac(set, -varsign[v] * mircoef[v]);
10530  }
10531 
10532  solval = (sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
10533  viol = f0 - fj * (varsign[v] == +1 ? solval - bestlbs[v] : bestubs[v] - solval);
10534  newviol = newf0 - newfj * (varsign[v] == -1 ? solval - bestlbs[v] : bestubs[v] - solval);
10535  violgain = newviol - viol;
10536 
10537  /* prefer larger violations; for equal violations, prefer smaller f0 values since then the possibility that
10538  * we f_j > f_0 is larger and we may improve some coefficients in rounding
10539  */
10540  if( SCIPsetIsGT(set, violgain, bestviolgain)
10541  || (SCIPsetIsGE(set, violgain, bestviolgain) && newf0 < bestnewf0) )
10542  {
10543  bestv = v;
10544  bestviolgain = violgain;
10545  bestnewf0 = newf0;
10546  }
10547  }
10548  }
10549 
10550  if( bestv >= 0 )
10551  {
10552  assert(bestv < prob->nvars);
10553  assert(boundtype[bestv] < 0);
10554  assert(!SCIPsetIsInfinity(set, -bestlbs[bestv]));
10555  assert(!SCIPsetIsInfinity(set, bestubs[bestv]));
10556 
10557  /* switch the complementation of this variable */
10558  (*mirrhs) += varsign[bestv] * mircoef[bestv] * (bestlbs[bestv] - bestubs[bestv]);
10559  if( varsign[bestv] == +1 )
10560  {
10561  /* switch to upper bound */
10562  assert(bestubtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
10563  boundtype[bestv] = bestubtypes[bestv];
10564  varsign[bestv] = -1;
10565  }
10566  else
10567  {
10568  /* switch to lower bound */
10569  assert(bestlbtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
10570  boundtype[bestv] = bestlbtypes[bestv];
10571  varsign[bestv] = +1;
10572  }
10573  *localbdsused = *localbdsused || (boundtype[bestv] == -2);
10574  }
10575  }
10576  }
10577 
10578  TERMINATE:
10579 
10580  /*free temporary memory */
10581  SCIPsetFreeBufferArray(set, &bestubtypes);
10582  SCIPsetFreeBufferArray(set, &bestlbtypes);
10583  SCIPsetFreeBufferArray(set, &bestubs);
10584  SCIPsetFreeBufferArray(set, &bestlbs);
10585 
10586  return SCIP_OKAY;
10587 }
10588 
10589 /** Calculate fractionalities \f$ f_0 := b - down(b), f_j := a^\prime_j - down(a^\prime_j) \f$, and derive MIR cut \f$ \tilde{a} \cdot x' \leq down(b) \f$
10590  * \f[
10591  * \begin{array}{rll}
10592  * integers :& \tilde{a}_j = down(a^\prime_j), & if \qquad f_j \leq f_0 \\
10593  * & \tilde{a}_j = down(a^\prime_j) + (f_j - f_0)/(1 - f_0),& if \qquad f_j > f_0 \\
10594  * continuous:& \tilde{a}_j = 0, & if \qquad a^\prime_j \geq 0 \\
10595  * & \tilde{a}_j = a^\prime_j/(1 - f_0), & if \qquad a^\prime_j < 0
10596  * \end{array}
10597  * \f]
10598  *
10599  * Transform inequality back to \f$ \hat{a} \cdot x \leq rhs \f$:
10600  *
10601  * (lb or ub):
10602  * \f[
10603  * \begin{array}{lllll}
10604  * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{if lb was used in transformation} \\
10605  * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{if ub was used in transformation}
10606  * \end{array}
10607  * \f]
10608  * and move the constant terms
10609  * \f[
10610  * \begin{array}{cl}
10611  * -\tilde{a}_j \cdot lb_j = -\hat{a}_j \cdot lb_j,& \mbox{or} \\
10612  * \tilde{a}_j \cdot ub_j = -\hat{a}_j \cdot ub_j &
10613  * \end{array}
10614  * \f]
10615  * to the rhs.
10616  *
10617  * (vlb or vub):
10618  * \f[
10619  * \begin{array}{lllll}
10620  * x^\prime_j := x_j - (bl_j \cdot zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{(vlb)} \\
10621  * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{(vub)}
10622  * \end{array}
10623  * \f]
10624  * move the constant terms
10625  * \f[
10626  * \begin{array}{cl}
10627  * -\tilde{a}_j\, dl_j = -\hat{a}_j\, dl_j,& \mbox{or} \\
10628  * \tilde{a}_j\, du_j = -\hat{a}_j\, du_j &
10629  * \end{array}
10630  * \f]
10631  * to the rhs, and update the VB variable coefficients:
10632  * \f[
10633  * \begin{array}{ll}
10634  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j\, bl_j = \hat{a}_{zl_j} - \hat{a}_j\, bl_j,& \mbox{or} \\
10635  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j\, bu_j = \hat{a}_{zu_j} - \hat{a}_j\, bu_j &
10636  * \end{array}
10637  * \f]
10638  */
10639 static
10641  SCIP_SET* set, /**< global SCIP settings */
10642  SCIP_PROB* prob, /**< problem data */
10643  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10644  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10645  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
10646  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10647  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
10648  int* varsign, /**< stores the sign of the transformed variable in summation */
10649  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub)*/
10650  SCIP_Real f0 /**< fractional value of rhs */
10651  )
10652 {
10653  SCIP_Real onedivoneminusf0;
10654  int i;
10655 
10656  assert(prob != NULL);
10657  assert(mircoef != NULL);
10658  assert(mirrhs != NULL);
10659  assert(varused != NULL);
10660  assert(varinds != NULL);
10661  assert(nvarinds != NULL);
10662  assert(varsign != NULL);
10663  assert(0.0 < f0 && f0 < 1.0);
10664 
10665  onedivoneminusf0 = 1.0 / (1.0 - f0);
10666 
10667  /* Loop backwards to be able to delete coefficients from the sparsity pattern. Additionally, the variable bound
10668  * substitutions are only used in such a way that a variable of higher index is substituted by a variable of a
10669  * lower index. Therefore, we must loop backwards.
10670  */
10671  SCIPsortDownInt(varinds, *nvarinds);
10672 
10673  for( i = *nvarinds-1; i >= 0; i-- )
10674  {
10675  SCIP_VAR* var;
10676  SCIP_Real cutaj;
10677  int v;
10678 
10679  v = varinds[i];
10680  assert(0 <= v && v < prob->nvars);
10681  assert(varused[v]);
10682 
10683  var = prob->vars[v];
10684  assert(var != NULL);
10685  assert(SCIPvarGetProbindex(var) == v);
10686  assert(varsign[v] == +1 || varsign[v] == -1);
10687 
10688  /* calculate the coefficient in the retransformed cut */
10689  if( SCIPvarIsIntegral(var) )
10690  {
10691  SCIP_Real aj;
10692  SCIP_Real downaj;
10693  SCIP_Real fj;
10694 
10695  aj = varsign[v] * mircoef[v]; /* a'_j */
10696  downaj = SCIPsetFloor(set, aj);
10697  fj = aj - downaj;
10698 
10699  if( SCIPsetIsSumLE(set, fj, f0) )
10700  cutaj = varsign[v] * downaj; /* a^_j */
10701  else
10702  cutaj = varsign[v] * (downaj + (fj - f0) * onedivoneminusf0); /* a^_j */
10703  }
10704  else
10705  {
10706  SCIP_Real aj;
10707 
10708  aj = varsign[v] * mircoef[v]; /* a'_j */
10709  if( aj >= 0.0 )
10710  cutaj = 0.0;
10711  else
10712  cutaj = varsign[v] * aj * onedivoneminusf0; /* a^_j */
10713  }
10714 
10715  /* remove zero cut coefficients from sparsity pattern */
10716  if( SCIPsetIsZero(set, cutaj) )
10717  {
10718  mircoef[v] = 0.0;
10719  varused[v] = FALSE;
10720  varinds[i] = varinds[(*nvarinds)-1];
10721  (*nvarinds)--;
10722  continue;
10723  }
10724 
10725  mircoef[v] = cutaj;
10726 
10727  /* check for variable bound use */
10728  if( boundtype[v] < 0 )
10729  {
10730  /* standard bound */
10731 
10732  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
10733  if( varsign[v] == +1 )
10734  {
10735  /* lower bound was used */
10736  if( boundtype[v] == -1 )
10737  {
10738  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
10739  (*mirrhs) += cutaj * SCIPvarGetLbGlobal(var);
10740  }
10741  else
10742  {
10743  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
10744  (*mirrhs) += cutaj * SCIPvarGetLbLocal(var);
10745  }
10746  }
10747  else
10748  {
10749  /* upper bound was used */
10750  if( boundtype[v] == -1 )
10751  {
10752  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
10753  (*mirrhs) += cutaj * SCIPvarGetUbGlobal(var);
10754  }
10755  else
10756  {
10757  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
10758  (*mirrhs) += cutaj * SCIPvarGetUbLocal(var);
10759  }
10760  }
10761  }
10762  else
10763  {
10764  SCIP_VAR** vbz;
10765  SCIP_Real* vbb;
10766  SCIP_Real* vbd;
10767  int vbidx;
10768  int zidx;
10769 
10770  /* variable bound */
10771  vbidx = boundtype[v];
10772 
10773  /* change mirrhs and cutaj of integer variable z_j of variable bound */
10774  if( varsign[v] == +1 )
10775  {
10776  /* variable lower bound was used */
10777  assert(0 <= vbidx && vbidx < SCIPvarGetNVlbs(var));
10778  vbz = SCIPvarGetVlbVars(var);
10779  vbb = SCIPvarGetVlbCoefs(var);
10780  vbd = SCIPvarGetVlbConstants(var);
10781  }
10782  else
10783  {
10784  /* variable upper bound was used */
10785  assert(0 <= vbidx && vbidx < SCIPvarGetNVubs(var));
10786  vbz = SCIPvarGetVubVars(var);
10787  vbb = SCIPvarGetVubCoefs(var);
10788  vbd = SCIPvarGetVubConstants(var);
10789  }
10790  assert(SCIPvarIsActive(vbz[vbidx]));
10791  zidx = SCIPvarGetProbindex(vbz[vbidx]);
10792  assert(0 <= zidx && zidx < v);
10793 
10794  (*mirrhs) += cutaj * vbd[vbidx];
10795  mircoef[zidx] -= cutaj * vbb[vbidx];
10796 
10797  /* add variable to sparsity pattern */
10798  if( !varused[zidx] )
10799  {
10800  assert(*nvarinds < prob->nvars);
10801  varused[zidx] = TRUE;
10802  varinds[*nvarinds] = zidx;
10803  (*nvarinds)++;
10804  }
10805  }
10806  }
10807 }
10808 
10809 /** substitute aggregated slack variables:
10810  *
10811  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
10812  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r]. \f$
10813  *
10814  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
10815  * \f[
10816  * \begin{array}{rll}
10817  * integers : & \hat{a}_r = \tilde{a}_r = down(a^\prime_r), & \mbox{if}\qquad f_r <= f0 \\
10818  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + (f_r - f0)/(1 - f0),& \mbox{if}\qquad f_r > f0 \\
10819  * continuous:& \hat{a}_r = \tilde{a}_r = 0, & \mbox{if}\qquad a^\prime_r >= 0 \\
10820  * & \hat{a}_r = \tilde{a}_r = a^\prime_r/(1 - f0), & \mbox{if}\qquad a^\prime_r < 0
10821  * \end{array}
10822  * \f]
10823  *
10824  * Substitute \f$ \hat{a}_r \cdot s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
10825  */
10826 static
10828  SCIP_SET* set, /**< global SCIP settings */
10829  SCIP_STAT* stat, /**< problem statistics */
10830  SCIP_LP* lp, /**< LP data */
10831  SCIP_Real* weights, /**< row weights in row summation */
10832  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
10833  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10834  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10835  int* slacksign, /**< stores the sign of the row's slack variable in summation */
10836  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
10837  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10838  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
10839  int* rowinds, /**< sparsity pattern of used rows */
10840  int nrowinds, /**< number of used rows */
10841  SCIP_Real f0 /**< fractional value of rhs */
10842  )
10843 { /*lint --e{715}*/
10844  SCIP_Real onedivoneminusf0;
10845  int i;
10846 
10847  assert(lp != NULL);
10848  assert(weights != NULL);
10849  assert(!SCIPsetIsZero(set, scale));
10850  assert(mircoef != NULL);
10851  assert(mirrhs != NULL);
10852  assert(slacksign != NULL);
10853  assert(varused != NULL);
10854  assert(varinds != NULL);
10855  assert(nvarinds != NULL);
10856  assert(rowinds != NULL);
10857  assert(0.0 < f0 && f0 < 1.0);
10858 
10859  onedivoneminusf0 = 1.0 / (1.0 - f0);
10860  for( i = 0; i < nrowinds; i++ )
10861  {
10862  SCIP_ROW* row;
10863  SCIP_Real ar;
10864  SCIP_Real downar;
10865  SCIP_Real cutar;
10866  SCIP_Real fr;
10867  SCIP_Real mul;
10868  int idx;
10869  int r;
10870  int j;
10871 
10872  r = rowinds[i];
10873  assert(0 <= r && r < lp->nrows);
10874  assert(slacksign[r] == -1 || slacksign[r] == +1);
10875  assert(!SCIPsetIsZero(set, weights[r]));
10876 
10877  row = lp->rows[r];
10878  assert(row != NULL);
10879  assert(row->len == 0 || row->cols != NULL);
10880  assert(row->len == 0 || row->cols_index != NULL);
10881  assert(row->len == 0 || row->vals != NULL);
10882 
10883  /* get the slack's coefficient a'_r in the aggregated row */
10884  ar = slacksign[r] * scale * weights[r];
10885 
10886  /* calculate slack variable's coefficient a^_r in the cut */
10887  if( row->integral
10888  && ((slacksign[r] == +1 && SCIPsetIsFeasIntegral(set, row->rhs - row->constant))
10889  || (slacksign[r] == -1 && SCIPsetIsFeasIntegral(set, row->lhs - row->constant))) )
10890  {
10891  /* slack variable is always integral:
10892  * a^_r = a~_r = down(a'_r) , if f_r <= f0
10893  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
10894  */
10895  downar = SCIPsetFloor(set, ar);
10896  fr = ar - downar;
10897  if( SCIPsetIsLE(set, fr, f0) )
10898  cutar = downar;
10899  else
10900  cutar = downar + (fr - f0) * onedivoneminusf0;
10901  }
10902  else
10903  {
10904  /* slack variable is continuous:
10905  * a^_r = a~_r = 0 , if a'_r >= 0
10906  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
10907  */
10908  if( ar >= 0.0 )
10909  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
10910  else
10911  cutar = ar * onedivoneminusf0;
10912  }
10913 
10914  /* if the coefficient was reduced to zero, ignore the slack variable */
10915  if( SCIPsetIsZero(set, cutar) )
10916  continue;
10917 
10918  /* depending on the slack's sign, we have
10919  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
10920  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
10921  */
10922  mul = -slacksign[r] * cutar;
10923 
10924  /* add the slack's definition multiplied with a^_j to the cut */
10925  for( j = 0; j < row->len; ++j )
10926  {
10927  assert(row->cols[j] != NULL);
10928  assert(row->cols[j]->var != NULL);
10929  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
10930  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
10931  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
10932  idx = row->cols[j]->var_probindex;
10933  mircoef[idx] += mul * row->vals[j];
10934 
10935  /* update sparsity pattern */
10936  if( !varused[idx] )
10937  {
10938  varused[idx] = TRUE;
10939  varinds[*nvarinds] = idx;
10940  (*nvarinds)++;
10941  }
10942  }
10943 
10944  /* move slack's constant to the right hand side */
10945  if( slacksign[r] == +1 )
10946  {
10947  SCIP_Real rhs;
10948 
10949  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
10950  assert(!SCIPsetIsInfinity(set, row->rhs));
10951  rhs = row->rhs - row->constant;
10952  if( row->integral )
10953  {
10954  /* the right hand side was implicitly rounded down in row aggregation */
10955  rhs = SCIPsetFeasFloor(set, rhs);
10956  }
10957  *mirrhs -= cutar * rhs;
10958  }
10959  else
10960  {
10961  SCIP_Real lhs;
10962 
10963  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
10964  assert(!SCIPsetIsInfinity(set, -row->lhs));
10965  lhs = row->lhs - row->constant;
10966  if( row->integral )
10967  {
10968  /* the left hand side was implicitly rounded up in row aggregation */
10969  lhs = SCIPsetFeasCeil(set, lhs);
10970  }
10971  *mirrhs += cutar * lhs;
10972  }
10973  }
10974 
10975  /* set rhs to zero, if it's very close to */
10976  if( SCIPsetIsZero(set, *mirrhs) )
10977  *mirrhs = 0.0;
10978 }
10979 
10980 #ifdef SCIP_DEBUG
10981 static
10982 void printMIR(
10983  SCIP_SET* set, /**< global SCIP settings */
10984  SCIP_STAT* stat, /**< problem statistics */
10985  SCIP_PROB* prob, /**< problem data */
10986  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10987  SCIP_Real* mircoef, /**< MIR coefficients */
10988  SCIP_Real mirrhs /**< right hand side of the MIR row */
10989  )
10990 {
10991  SCIP_Real activity;
10992  int i;
10993 
10994  assert(prob != NULL);
10995 
10996  SCIPdebugMessage("MIR:");
10997  activity = 0.0;
10998  for( i = 0; i < prob->nvars; ++i )
10999  {
11000  if( mircoef[i] != 0.0 )
11001  {
11002  SCIPdebugPrintf(" %+g<%s>", mircoef[i], SCIPvarGetName(prob->vars[i]));
11003  activity += mircoef[i] * (sol == NULL ? SCIPvarGetLPSol(prob->vars[i]) : SCIPsolGetVal(sol, set, stat, prob->vars[i]));
11004  }
11005  }
11006  SCIPdebugPrintf(" <= %.6f (activity: %g)\n", mirrhs, activity);
11007 }
11008 #endif
11009 
11010 /** calculates the activity of the given MIR cut */
11011 static
11013  SCIP_SET* set, /**< global SCIP settings */
11014  SCIP_STAT* stat, /**< problem statistics */
11015  SCIP_PROB* prob, /**< problem data */
11016  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
11017  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
11018  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11019  int nvarinds /**< number of non-zero MIR coefficients */
11020  )
11021 {
11022  SCIP_Real act;
11023  int i;
11024 
11025  act = 0.0;
11026  for( i = 0; i < nvarinds; i++ )
11027  {
11028  int v;
11029 
11030  v = varinds[i];
11031  assert(0 <= v && v < prob->nvars);
11032  assert(mircoef[v] != 0.0);
11033 
11034  act += mircoef[v] * ( sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
11035  }
11036 
11037  return act;
11038 }
11039 
11040 /* calculates a MIR cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because these
11041  * rows cannot participate in a MIR cut.
11042  */
11044  SCIP_LP* lp, /**< LP data */
11045  SCIP_SET* set, /**< global SCIP settings */
11046  SCIP_STAT* stat, /**< problem statistics */
11047  SCIP_PROB* prob, /**< problem data */
11048  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
11049  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
11050  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
11051  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
11052  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
11053  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
11054  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
11055  * NULL for using closest bound for all variables */
11056  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
11057  * NULL for using closest bound for all variables */
11058  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
11059  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
11060  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
11061  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
11062  SCIP_Real* weights, /**< row weights in row summation */
11063  SCIP_Real maxweight, /**< largest magnitude of weights; set to -1 if sparsity information is unknown */
11064  int* weightinds, /**< sparsity pattern of weights; size nrowinds; NULL if sparsity info is unknown */
11065  int nweightinds, /**< number of nonzeros in weights; -1 if rowinds is NULL */
11066  int rowlensum, /**< total number of non-zeros in used rows (row associated with nonzero weight coefficient); -1 if unknown */
11067  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
11068  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11069  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
11070  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
11071  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
11072  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
11073  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
11074  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
11075  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
11076  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
11077  )
11078 {
11079  int* slacksign;
11080  int* varsign;
11081  int* boundtype;
11082  SCIP_Bool* varused;
11083  int* varinds;
11084  int* rowinds;
11085  int nvarinds;
11086  int nrowinds;
11087  SCIP_Real rhs;
11088  SCIP_Real downrhs;
11089  SCIP_Real f0;
11090  SCIP_Bool emptyrow;
11091  SCIP_Bool freevariable;
11092  SCIP_Bool localrowsused;
11093  SCIP_Bool localbdsused;
11094  SCIP_Bool rowtoolong;
11095  SCIP_Bool compress;
11096 
11097  assert(lp != NULL);
11098  assert(lp->solved || sol != NULL);
11099  assert(prob != NULL);
11100  assert(weights != NULL);
11101  assert(!SCIPsetIsZero(set, scale));
11102  assert(mircoef != NULL);
11103  assert(mirrhs != NULL);
11104  assert(cutactivity != NULL);
11105  assert(success != NULL);
11106  assert(cutislocal != NULL);
11107 
11108  SCIPdebugMessage("calculating MIR cut (scale: %g)\n", scale);
11109 
11110  /**@todo test, if a column based summation is faster */
11111 
11112  *success = FALSE;
11113  if( mksetcoefsvalid != NULL )
11114  *mksetcoefsvalid = FALSE;
11115 
11116  /* allocate temporary memory */
11117  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
11118  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
11119  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
11120  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
11121  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
11122 
11123  /* if sparse information of weights is known, there is no need
11124  * to compute rowinds */
11125  if( weightinds == NULL )
11126  {
11127  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
11128  compress = TRUE;
11129  }
11130  else
11131  {
11132  compress = FALSE;
11133 
11134  /* weightinds is the indices of the weights vector.
11135  * rowinds is the indices of the weights vector that is modified in the sumMIRRow function.
11136  * duplication of weightinds is necessary to ensure weightinds is not modified. */
11137  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &rowinds, weightinds, nweightinds) );
11138  nrowinds = nweightinds;
11139 
11140  if( rowlensum/5 > maxmksetcoefs )
11141  {
11142  *cutislocal = FALSE;
11143  goto TERMINATE;
11144  }
11145  }
11146 
11147  /* calculate the row summation */
11148  sumMIRRow(set, prob, lp, weights, maxweight, sidetypes, scale, allowlocal,
11149  maxmksetcoefs, maxweightrange, compress, mircoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
11150  &emptyrow, &localrowsused, &rowtoolong, cutrank);
11151  assert(allowlocal || !localrowsused);
11152  *cutislocal = localrowsused;
11153  if( emptyrow || rowtoolong )
11154  goto TERMINATE;
11155  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
11156 
11157  /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
11158  * prevent numerical rounding errors
11159  */
11160  cleanupMIRRow(set, prob, mircoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
11161  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
11162 
11163  /* Transform equation a*x == b, lb <= x <= ub into standard form
11164  * a'*x' == b, 0 <= x' <= ub'.
11165  *
11166  * Transform variables (lb or ub):
11167  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
11168  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
11169  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
11170  *
11171  * Transform variables (vlb or vub):
11172  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
11173  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
11174  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
11175  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
11176  * a_{zu_j} := a_{zu_j} + a_j * bu_j
11177  */
11178  SCIP_CALL( transformMIRRow(set, stat, prob, sol, boundswitch, usevbds, allowlocal, fixintegralrhs, boundsfortrans,
11179  boundtypesfortrans, minfrac, maxfrac, mircoef, &rhs, varused, varinds, &nvarinds, varsign, boundtype,
11180  &freevariable, &localbdsused) );
11181  assert(allowlocal || !localbdsused);
11182  *cutislocal = *cutislocal || localbdsused;
11183 
11184  /* store the coefficients of the variables in the constructed mixed knapsack set */
11185  if( mksetcoefs != NULL )
11186  BMScopyMemoryArray(mksetcoefs, mircoef, prob->nvars);
11187  if( mksetcoefsvalid != NULL )
11188  *mksetcoefsvalid = TRUE;
11189 
11190  if( freevariable )
11191  goto TERMINATE;
11192  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
11193 
11194  /* Calculate fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j) , and derive MIR cut
11195  * a~*x' <= down(b)
11196  * integers : a~_j = down(a'_j) , if f_j <= f_0
11197  * a~_j = down(a'_j) + (f_j - f0)/(1 - f0), if f_j > f_0
11198  * continuous: a~_j = 0 , if a'_j >= 0
11199  * a~_j = a'_j/(1 - f0) , if a'_j < 0
11200  *
11201  * Transform inequality back to a^*x <= rhs:
11202  *
11203  * (lb or ub):
11204  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
11205  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
11206  * and move the constant terms
11207  * -a~_j * lb_j == -a^_j * lb_j, or
11208  * a~_j * ub_j == -a^_j * ub_j
11209  * to the rhs.
11210  *
11211  * (vlb or vub):
11212  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
11213  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
11214  * move the constant terms
11215  * -a~_j * dl_j == -a^_j * dl_j, or
11216  * a~_j * du_j == -a^_j * du_j
11217  * to the rhs, and update the VB variable coefficients:
11218  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
11219  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
11220  */
11221  downrhs = SCIPsetSumFloor(set, rhs);
11222  f0 = rhs - downrhs;
11223  if( f0 < minfrac || f0 > maxfrac )
11224  goto TERMINATE;
11225 
11226  /* We multiply the coefficients of the base inequality roughly by scale/(1-f0).
11227  * If this gives a scalar that is very big, we better do not generate this cut.
11228  */
11229  if( REALABS(scale)/(1.0 - f0) > MAXCMIRSCALE )
11230  goto TERMINATE;
11231 
11232  *mirrhs = downrhs;
11233  roundMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, varsign, boundtype, f0);
11234  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11235 
11236  /* substitute aggregated slack variables:
11237  *
11238  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
11239  * variable only appears in its own row:
11240  * a'_r = scale * weight[r] * slacksign[r].
11241  *
11242  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
11243  * integers : a^_r = a~_r = down(a'_r) , if f_r <= f0
11244  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
11245  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
11246  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
11247  *
11248  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
11249  */
11250  substituteMIRRow(set, stat, lp, weights, scale, mircoef, mirrhs, slacksign,
11251  varused, varinds, &nvarinds, rowinds, nrowinds, f0);
11252  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11253 
11254  /* remove again all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
11255  * prevent numerical rounding errors
11256  */
11257  cleanupMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, *cutislocal);
11258  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11259 
11260  /* calculate cut activity */
11261  *cutactivity = getMIRRowActivity(set, stat, prob, sol, mircoef, varinds, nvarinds);
11262  *success = TRUE;
11263 
11264  TERMINATE:
11265  /* free temporary memory */
11266  SCIPsetFreeBufferArray(set, &rowinds);
11267  SCIPsetFreeBufferArray(set, &varinds);
11268  SCIPsetFreeBufferArray(set, &varused);
11269  SCIPsetFreeBufferArray(set, &boundtype);
11270  SCIPsetFreeBufferArray(set, &varsign);
11271  SCIPsetFreeBufferArray(set, &slacksign);
11272 
11273  /**@todo pass the sparsity pattern to the calling method in order to speed up the calling method's loops */
11274 
11275  return SCIP_OKAY;
11276 }
11277 
11278 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
11279 static
11281  SCIP_SET* set, /**< global SCIP settings */
11282  SCIP_PROB* prob, /**< problem data */
11283  SCIP_LP* lp, /**< LP data */
11284  SCIP_Real* weights, /**< row weights in row summation */
11285  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11286  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
11287  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
11288  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
11289  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size prob->nvars */
11290  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11291  int* slacksign, /**< stores the sign of the row's slack variable in summation */
11292  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
11293  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
11294  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
11295  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
11296  int* nrowinds, /**< pointer to store number of used rows */
11297  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
11298  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
11299  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
11300  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
11301  )
11302 {
11303  SCIP_Real maxweight;
11304  int rowlensum;
11305  int maxrank = 0;
11306  int i;
11307 
11308  assert(prob != NULL);
11309  assert(lp != NULL);
11310  assert(weights != NULL);
11311  assert(!SCIPsetIsZero(set, scale));
11312  assert(maxweightrange >= 1.0);
11313  assert(strongcgcoef != NULL);
11314  assert(strongcgrhs != NULL);
11315  assert(slacksign != NULL);
11316  assert(varused != NULL);
11317  assert(varinds != NULL);
11318  assert(nvarinds != NULL);
11319  assert(rowinds != NULL);
11320  assert(nrowinds != NULL);
11321  assert(emptyrow != NULL);
11322  assert(localrowsused != NULL);
11323 
11324  *nvarinds = 0;
11325  *localrowsused = FALSE;
11326  *strongcgrhs = 0.0;
11327  *emptyrow = TRUE;
11328  *rowtoolong = FALSE;
11329 
11330  /* initialize varused array */
11331  BMSclearMemoryArray(varused, prob->nvars);
11332 
11333  /* search the maximal absolute weight and calculate the row sparsity pattern */
11334  if( *nrowinds == -1 )
11335  maxweight = getMaxAbsWeightCalcSparsity(set, lp, weights, rowinds, nrowinds, &rowlensum);
11336  else
11337  maxweight = getMaxAbsWeight(set, lp, weights, rowinds, nrowinds, &rowlensum);
11338 
11339 
11340  maxweight *= ABS(scale);
11341 
11342  /* if the total number of non-zeros is way too large, we just skip this aggregation */
11343  if( rowlensum/5 > maxmksetcoefs )
11344  {
11345  *rowtoolong = TRUE;
11346  return;
11347  }
11348 
11349  /* calculate the row summation */
11350  BMSclearMemoryArray(strongcgcoef, prob->nvars);
11351  i = 0;
11352  while( i < *nrowinds )
11353  {
11354  SCIP_ROW* row;
11355  SCIP_Real weight;
11356  SCIP_Real absweight;
11357  SCIP_Bool skiprow;
11358  int r;
11359 
11360  r = rowinds[i];
11361  assert(0 <= i && i < lp->nrows);
11362  assert(weights[r] != 0.0);
11363 
11364  row = lp->rows[r];
11365  assert(row != NULL);
11366  assert(row->len == 0 || row->cols != NULL);
11367  assert(row->len == 0 || row->cols_index != NULL);
11368  assert(row->len == 0 || row->vals != NULL);
11369 
11370  /* modifiable rows cannot be part of a strong CG row summation;
11371  * local rows are only included, if the allowlocal flag is set;
11372  * close to zero weights or weights outside the maximal range are ignored
11373  */
11374  weight = scale * weights[r];
11375  absweight = ABS(weight);
11376  skiprow = FALSE;
11377  if( !row->modifiable && (allowlocal || !row->local)
11378  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
11379  {
11380  /*lint --e{644}*/
11381  SCIP_Bool uselhs;
11382 
11383  if( row->integral )
11384  {
11385  /* Row is integral:
11386  * Decide, if we want to use the left or the right hand side of the row in the summation.
11387  * If possible, use the side that leads to a positive slack value in the summation.
11388  */
11389  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
11390  uselhs = TRUE;
11391  else
11392  uselhs = FALSE;
11393  }
11394  else
11395  {
11396  /* Row is NOT integral:
11397  * Decide, if we have to use the left or the right hand side of the row in the summation,
11398  * in order to get a positive slack variable in the summation.
11399  * If not possible, ignore row in summation.
11400  */
11401  if( weight < 0.0 && !SCIPsetIsInfinity(set, -row->lhs) )
11402  uselhs = TRUE;
11403  else if( weight > 0.0 && !SCIPsetIsInfinity(set, row->rhs) )
11404  uselhs = FALSE;
11405  else
11406  skiprow = TRUE;
11407  }
11408 
11409  if( !skiprow )
11410  {
11411  /* add the row to the aggregation */
11412  addRowToAggregation(set, strongcgcoef, strongcgrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
11413  *emptyrow = FALSE;
11414  *localrowsused = *localrowsused || row->local;
11415 
11416  maxrank = MAX(maxrank, row->rank);
11417 
11418  SCIPdebugMessage("strong CG: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
11419  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
11420  scale, weights[r], slacksign[r], *strongcgrhs);
11421  debugRowPrint(row);
11422  }
11423  }
11424  else
11425  skiprow = TRUE;
11426 
11427  if( skiprow )
11428  {
11429  /* remove row from sparsity pattern, do not increase i, since the i-th position is filled with the last element */
11430  rowinds[i] = rowinds[(*nrowinds)-1];
11431  (*nrowinds)--;
11432 #ifndef NDEBUG
11433  slacksign[r] = 0;
11434 #endif
11435  }
11436  else
11437  ++i;
11438  }
11439 
11440  /* check if the total number of non-zeros is too large */
11441  if( *nrowinds > maxmksetcoefs )
11442  *rowtoolong = TRUE;
11443 
11444  /* set rank of the cut */
11445  if( cutrank != NULL )
11446  *cutrank = maxrank + 1;
11447 }
11448 
11449 /** Transform equation \f$ a*x == b \f$, \f$ lb <= x <= ub \f$ into standard form \f$ a^\prime*x^\prime == b\f$, \f$ 0 <= x^\prime <= ub^\prime \f$.
11450  *
11451  * Transform variables (lb or ub):
11452  * \f[
11453  * \begin{array}{llll}
11454  * x^\prime_j := x_j - lb_j,& x_j == x^\prime_j + lb_j,& a^\prime_j == a_j,& \mbox{if lb is used in transformation} \\
11455  * x^\prime_j := ub_j - x_j,& x_j == ub_j - x^\prime_j,& a^\prime_j == -a_j,& \mbox{if ub is used in transformation}
11456  * \end{array}
11457  * \f]
11458  * and move the constant terms \f$ a_j * lb_j \f$ or \f$ a_j * ub_j \f$ to the rhs.
11459  *
11460  * Transform variables (vlb or vub):
11461  * \f[
11462  * \begin{array}{llll}
11463  * x^\prime_j := x_j - (bl_j * zl_j + dl_j),& x_j == x^\prime_j + (bl_j * zl_j + dl_j),& a^\prime_j == a_j,& \mbox{if vlb is used in transf.} \\
11464  * x^\prime_j := (bu_j * zu_j + du_j) - x_j,& x_j == (bu_j * zu_j + du_j) - x^\prime_j,& a^\prime_j == -a_j,& \mbox{if vub is used in transf.}
11465  * \end{array}
11466  * \f]
11467  * move the constant terms \f$ a_j * dl_j \f$ or \f$ a_j * du_j \f$ to the rhs, and update the coefficient of the VLB variable:
11468  * \f[
11469  * \begin{array}{ll}
11470  * a_{zl_j} := a_{zl_j} + a_j * bl_j,& \mbox{or} \\
11471  * a_{zu_j} := a_{zu_j} + a_j * bu_j&
11472  * \end{array}
11473  * \f]
11474  */
11475 static
11477  SCIP_SET* set, /**< global SCIP settings */
11478  SCIP_STAT* stat, /**< problem statistics */
11479  SCIP_PROB* prob, /**< problem data */
11480  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
11481  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
11482  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
11483  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11484  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11485  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11486  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11487  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11488  int* varsign, /**< stores the sign of the transformed variable in summation */
11489  int* boundtype, /**< stores the bound used for transformed variable:
11490  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
11491  SCIP_Bool* freevariable, /**< stores whether a free variable was found in strong CG row -> invalid summation */
11492  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
11493  )
11494 {
11495  int i;
11496 
11497  assert(prob != NULL);
11498  assert(strongcgcoef != NULL);
11499  assert(strongcgrhs != NULL);
11500  assert(varused != NULL);
11501  assert(varinds != NULL);
11502  assert(nvarinds != NULL);
11503  assert(varsign != NULL);
11504  assert(boundtype != NULL);
11505  assert(freevariable != NULL);
11506  assert(localbdsused != NULL);
11507 
11508  *freevariable = FALSE;
11509  *localbdsused = FALSE;
11510 
11511 #ifndef NDEBUG
11512  /* in debug mode, make sure that the whole array is initialized with invalid values */
11513  for( i = 0; i < prob->nvars; i++ )
11514  {
11515  varsign[i] = 0;
11516  boundtype[i] = -1;
11517  }
11518 #endif
11519 
11520  /* start with continuous variables, because using variable bounds can affect the untransformed integral
11521  * variables, and these changes have to be incorporated in the transformation of the integral variables
11522  * (continuous variables have largest problem indices!)
11523  */
11524  SCIPsortDownInt(varinds, *nvarinds);
11525 
11526  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
11527  * substitute integral variables with best standard bound (lb, ub)
11528  */
11529  i = 0;
11530  while( i < *nvarinds )
11531  {
11532  SCIP_VAR* var;
11533  SCIP_Real varsol;
11534  SCIP_Real bestlb;
11535  SCIP_Real bestub;
11536  SCIP_Bool uselb;
11537  int bestlbtype;
11538  int bestubtype;
11539  int v;
11540 
11541  v = varinds[i];
11542  assert(0 <= v && v < prob->nvars);
11543  assert(varused[v]);
11544 
11545  var = prob->vars[v];
11546  assert(v == SCIPvarGetProbindex(var));
11547 
11548  /* due to variable bound usage cancellation may occur;
11549  * do not increase i, since last element is copied to the i-th position
11550  */
11551  if( SCIPsetIsZero(set, strongcgcoef[v]) )
11552  {
11553  varsign[v] = +1;
11554  boundtype[v] = -1;
11555  strongcgcoef[v] = 0.0;
11556  varused[v] = FALSE;
11557  varinds[i] = varinds[(*nvarinds)-1];
11558  (*nvarinds)--;
11559  continue;
11560  }
11561 
11562  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
11563  bestlb = SCIPvarGetLbGlobal(var);
11564  bestlbtype = -1;
11565  if( allowlocal )
11566  {
11567  SCIP_Real loclb;
11568 
11569  loclb = SCIPvarGetLbLocal(var);
11570  if( SCIPsetIsGT(set, loclb, bestlb) )
11571  {
11572  bestlb = loclb;
11573  bestlbtype = -2;
11574  }
11575  }
11576  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
11577  {
11578  SCIP_Real bestvlb;
11579  int bestvlbidx;
11580 
11581  SCIPvarGetClosestVlb(var, NULL, set, stat, &bestvlb, &bestvlbidx);
11582  if( bestvlbidx >= 0
11583  && (bestvlb > bestlb || (bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, bestlb))) )
11584  {
11585  bestlb = bestvlb;
11586  bestlbtype = bestvlbidx;
11587  }
11588  }
11589 
11590  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
11591  bestub = SCIPvarGetUbGlobal(var);
11592  bestubtype = -1;
11593  if( allowlocal )
11594  {
11595  SCIP_Real locub;
11596 
11597  locub = SCIPvarGetUbLocal(var);
11598  if( SCIPsetIsLT(set, locub, bestub) )
11599  {
11600  bestub = locub;
11601  bestubtype = -2;
11602  }
11603  }
11604  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
11605  {
11606  SCIP_Real bestvub;
11607  int bestvubidx;
11608 
11609  SCIPvarGetClosestVub(var, NULL, set, stat, &bestvub, &bestvubidx);
11610  if( bestvubidx >= 0
11611  && (bestvub < bestub || (bestubtype < 0 && SCIPsetIsLE(set, bestvub, bestub))) )
11612  {
11613  bestub = bestvub;
11614  bestubtype = bestvubidx;
11615  }
11616  }
11617 
11618  /* check, if variable is free variable
11619  * (for continuous variable use bound, so that coefficient will be nonnegative)
11620  */
11622  && SCIPsetIsInfinity(set, -bestlb)
11623  && SCIPsetIsInfinity(set, bestub))
11625  && ((strongcgcoef[v] > 0.0 && SCIPsetIsInfinity(set, -bestlb))
11626  || (strongcgcoef[v] < 0.0 && SCIPsetIsInfinity(set, bestub)))) )
11627  {
11628  /* we found a free variable in the row with non-zero coefficient
11629  * -> strong CG row can't be transformed in standard form
11630  */
11631  *freevariable = TRUE;
11632  return;
11633  }
11634 
11635  /* select transformation bound
11636  * (for continuous variable use bound, so that coefficient will be nonnegative)
11637  */
11638  varsol = SCIPvarGetLPSol(var);
11640  uselb = (strongcgcoef[v] > 0.0);
11641  else if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
11642  uselb = TRUE;
11643  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
11644  uselb = FALSE;
11645  else if( bestlbtype == -1 ) /* prefer global standard bounds */
11646  uselb = TRUE;
11647  else if( bestubtype == -1 ) /* prefer global standard bounds */
11648  uselb = FALSE;
11649  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
11650  uselb = TRUE;
11651  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
11652  uselb = FALSE;
11653  else
11654  uselb = TRUE; /* no decision yet? just use lower bound */
11655 
11656  /* perform bound substitution */
11657  if( uselb )
11658  {
11659  assert(!SCIPsetIsInfinity(set, -bestlb));
11660 
11661  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
11662  boundtype[v] = bestlbtype;
11663  varsign[v] = +1;
11664 
11665  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
11666  if( bestlbtype < 0 )
11667  {
11668  (*strongcgrhs) -= strongcgcoef[v] * bestlb;
11669  *localbdsused = *localbdsused || (bestlbtype == -2);
11670  }
11671  else
11672  {
11673  SCIP_VAR** vlbvars = SCIPvarGetVlbVars(var);
11674  SCIP_Real* vlbcoefs = SCIPvarGetVlbCoefs(var);
11675  SCIP_Real* vlbconsts = SCIPvarGetVlbConstants(var);
11676  int zidx;
11677 
11678  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
11679  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
11680  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
11681  assert(0 <= zidx && zidx < v);
11682 
11683  (*strongcgrhs) -= strongcgcoef[v] * vlbconsts[bestlbtype];
11684  strongcgcoef[zidx] += strongcgcoef[v] * vlbcoefs[bestlbtype];
11685 
11686  /* update sparsity pattern */
11687  if( !varused[zidx] )
11688  {
11689  assert(*nvarinds < prob->nvars);
11690  varused[zidx] = TRUE;
11691  varinds[*nvarinds] = zidx;
11692  (*nvarinds)++;
11693  }
11694  }
11695  }
11696  else
11697  {
11698  assert(!SCIPsetIsInfinity(set, bestub));
11699 
11700  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
11701  boundtype[v] = bestubtype;
11702  varsign[v] = -1;
11703 
11704  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
11705  if( bestubtype < 0 )
11706  {
11707  (*strongcgrhs) -= strongcgcoef[v] * bestub;
11708  *localbdsused = *localbdsused || (bestubtype == -2);
11709  }
11710  else
11711  {
11712  SCIP_VAR** vubvars = SCIPvarGetVubVars(var);
11713  SCIP_Real* vubcoefs = SCIPvarGetVubCoefs(var);
11714  SCIP_Real* vubconsts = SCIPvarGetVubConstants(var);
11715  int zidx;
11716 
11717  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
11718  assert(SCIPvarIsActive(vubvars[bestubtype]));
11719  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
11720  assert(zidx >= 0);
11721 
11722  (*strongcgrhs) -= strongcgcoef[v] * vubconsts[bestubtype];
11723  strongcgcoef[zidx] += strongcgcoef[v] * vubcoefs[bestubtype];
11724 
11725  /* update sparsity pattern */
11726  if( !varused[zidx] )
11727  {
11728  assert(*nvarinds < prob->nvars);
11729  varused[zidx] = TRUE;
11730  varinds[*nvarinds] = zidx;
11731  (*nvarinds)++;
11732  }
11733  }
11734  }
11735 
11736 #ifndef NDEBUG
11738  assert(strongcgcoef[v]*varsign[v] > 0.0);
11739 #endif
11740 
11741  SCIPdebugMessage("strong CG var <%s>: varsign=%d, boundtype=%d, strongcgcoef=%g, lb=%g, ub=%g -> rhs=%g\n",
11742  SCIPvarGetName(var), varsign[v], boundtype[v], strongcgcoef[v], bestlb, bestub, *strongcgrhs);
11743 
11744  ++i; /*increase iterator */
11745  }
11746 }
11747 
11748 /** Calculate fractionalities \f$ f_0 := b - down(b) \f$, \f$ f_j := a^\prime_j - down(a^\prime_j) \f$ and
11749  * integer \f$ k >= 1 \f$ with \f$ 1/(k + 1) <= f_0 < 1/k \f$ and \f$ (=> k = up(1/f_0) + 1) \f$
11750  * integer \f$ 1 <= p_j <= k \f$ with \f$ f_0 + ((p_j - 1) * (1 - f_0)/k) < f_j <= f_0 + (p_j * (1 - f_0)/k)\f$ \f$ (=> p_j = up( k*(f_j - f_0)/(1 - f_0) )) \f$
11751  * and derive strong CG cut \f$ \tilde{a}*x^\prime <= down(b) \f$
11752  * \f[
11753  * \begin{array}{rll}
11754  * integers : & \tilde{a}_j = down(a^\prime_j) &, if \qquad f_j <= f_0 \\
11755  * & \tilde{a}_j = down(a^\prime_j) + p_j/(k + 1) &, if \qquad f_j > f_0 \\
11756  * continuous:& \tilde{a}_j = 0 &, if \qquad a^\prime_j >= 0 \\
11757  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_j < 0
11758  * \end{array}
11759  * \f]
11760  *
11761  * Transform inequality back to \f$ \hat{a}*x <= rhs \f$:
11762  *
11763  * (lb or ub):
11764  * \f[
11765  * \begin{array}{lllll}
11766  * x^\prime_j := x_j - lb_j,& x_j == x^\prime_j + lb_j,& a^\prime_j == a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{if lb was used in transformation} \\
11767  * x^\prime_j := ub_j - x_j,& x_j == ub_j - x^\prime_j,& a^\prime_j == -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{if ub was used in transformation}
11768  * \end{array}
11769  * \f]
11770  * and move the constant terms
11771  * \f[
11772  * \begin{array}{rl}
11773  * -\tilde{a}_j * lb_j == -\hat{a}_j * lb_j, & \mbox{or} \\
11774  * \tilde{a}_j * ub_j == -\hat{a}_j * ub_j &
11775  * \end{array}
11776  * \f]
11777  * to the rhs.
11778  *
11779  * (vlb or vub):
11780  * \f[
11781  * \begin{array}{lllll}
11782  * x^\prime_j := x_j - (bl_j * zl_j + dl_j),& x_j == x^\prime_j + (bl_j * zl_j + dl_j),& a^\prime_j == a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{(vlb)} \\
11783  * x^\prime_j := (bu_j * zu_j + du_j) - x_j,& x_j == (bu_j * zu_j + du_j) - x^\prime_j,& a^\prime_j == -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{(vub)}
11784  * \end{array}
11785  * \f]
11786  * move the constant terms
11787  * \f[
11788  * \begin{array}{rl}
11789  * -\tilde{a}_j * dl_j == -\hat{a}_j * dl_j,& \mbox{or} \\
11790  * \tilde{a}_j * du_j == -\hat{a}_j * du_j &
11791  * \end{array}
11792  * \f]
11793  * to the rhs, and update the VB variable coefficients:
11794  * \f[
11795  * \begin{array}{ll}
11796  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j * bl_j == \hat{a}_{zl_j} - \hat{a}_j * bl_j,& \mbox{or} \\
11797  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j * bu_j == \hat{a}_{zu_j} - \hat{a}_j * bu_j &
11798  * \end{array}
11799  * \f]
11800  */
11801 static
11803  SCIP_SET* set, /**< global SCIP settings */
11804  SCIP_PROB* prob, /**< problem data */
11805  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11806  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11807  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11808  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11809  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11810  int* varsign, /**< stores the sign of the transformed variable in summation */
11811  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub)*/
11812  SCIP_Real f0, /**< fractional value of rhs */
11813  SCIP_Real k /**< factor to strengthen strongcg cut */
11814  )
11815 {
11816  SCIP_Real onedivoneminusf0;
11817  int nintvars;
11818  int i;
11819 
11820  assert(prob != NULL);
11821  assert(strongcgcoef != NULL);
11822  assert(strongcgrhs != NULL);
11823  assert(varused != NULL);
11824  assert(varinds != NULL);
11825  assert(nvarinds != NULL);
11826  assert(varsign != NULL);
11827  assert(0.0 < f0 && f0 < 1.0);
11828 
11829  onedivoneminusf0 = 1.0 / (1.0 - f0);
11830  nintvars = prob->nvars - prob->ncontvars;
11831 
11832  /* start with integer variables, since the variable bound substitutions can add up to the integer cut coefficients;
11833  * loop backwards to be able to delete coefficients from the sparsity pattern
11834  */
11835  SCIPsortDownInt(varinds, *nvarinds);
11836 
11837  /* integer variables */
11838  for( i = *nvarinds-1; i >= 0; i-- )
11839  {
11840  SCIP_VAR* var;
11841  SCIP_Real aj;
11842  SCIP_Real downaj;
11843  SCIP_Real cutaj;
11844  SCIP_Real fj;
11845  int v;
11846 
11847  v = varinds[i];
11848  assert(0 <= v && v < prob->nvars);
11849  assert(varused[v]);
11850 
11851  /* stop this loop if we reached the continuous variables */
11852  if( v >= nintvars )
11853  {
11854  assert(!SCIPvarIsIntegral(prob->vars[v]));
11855  assert(SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS);
11856  break;
11857  }
11858 
11859  var = prob->vars[v];
11860  assert(var != NULL);
11861  assert(SCIPvarIsIntegral(var));
11862  assert(SCIPvarGetProbindex(var) == v);
11863  assert(boundtype[v] == -1 || boundtype[v] == -2);
11864  assert(varsign[v] == +1 || varsign[v] == -1);
11865 
11866  /* calculate the coefficient in the retransformed cut */
11867  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
11868  downaj = SCIPsetFloor(set, aj);
11869  fj = aj - downaj;
11870 
11871  if( SCIPsetIsSumLE(set, fj, f0) )
11872  cutaj = varsign[v] * downaj; /* a^_j */
11873  else
11874  {
11875  SCIP_Real pj;
11876 
11877  pj = SCIPsetCeil(set, k * (fj - f0) * onedivoneminusf0);
11878  assert(pj >= 0); /* should be >= 1, but due to rounding bias can be 0 if fj almost equal to f0 */
11879  assert(pj <= k);
11880  cutaj = varsign[v] * (downaj + pj / (k + 1)); /* a^_j */
11881  }
11882 
11883 
11884  /* remove zero cut coefficients from sparsity pattern */
11885  if( SCIPsetIsZero(set, cutaj) )
11886  {
11887  strongcgcoef[v] = 0.0;
11888  varused[v] = FALSE;
11889  varinds[i] = varinds[(*nvarinds)-1];
11890  (*nvarinds)--;
11891  continue;
11892  }
11893 
11894  strongcgcoef[v] = cutaj;
11895 
11896  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
11897  if( varsign[v] == +1 )
11898  {
11899  /* lower bound was used */
11900  if( boundtype[v] == -1 )
11901  {
11902  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
11903  (*strongcgrhs) += cutaj * SCIPvarGetLbGlobal(var);
11904  }
11905  else
11906  {
11907  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
11908  (*strongcgrhs) += cutaj * SCIPvarGetLbLocal(var);
11909  }
11910  }
11911  else
11912  {
11913  /* upper bound was used */
11914  if( boundtype[v] == -1 )
11915  {
11916  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
11917  (*strongcgrhs) += cutaj * SCIPvarGetUbGlobal(var);
11918  }
11919  else
11920  {
11921  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
11922  (*strongcgrhs) += cutaj * SCIPvarGetUbLocal(var);
11923  }
11924  }
11925  }
11926 
11927  /* continuous variables */
11928  for( ; i >= 0; i-- )
11929  {
11930  int v;
11931 
11932  v = varinds[i];
11933  assert(0 <= v && v < prob->nvars);
11934  assert(varused[v]);
11935 
11936 #ifndef NDEBUG
11937  /* in a strong CG cut, cut coefficients of continuous variables are always zero; check this in debug mode */
11938  {
11939  SCIP_VAR* var;
11940  SCIP_Real aj;
11941 
11942  var = prob->vars[v];
11943  assert(var != NULL);
11944  assert(!SCIPvarIsIntegral(var));
11945  assert(SCIPvarGetProbindex(var) == v);
11946  assert(varsign[v] == +1 || varsign[v] == -1);
11947 
11948  /* calculate the coefficient in the retransformed cut */
11949  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
11950  assert(aj >= 0.0);
11951  }
11952 #endif
11953 
11954  strongcgcoef[v] = 0.0;
11955 
11956  /* remove zero cut coefficients from sparsity pattern */
11957  varused[v] = FALSE;
11958  varinds[i] = varinds[(*nvarinds)-1];
11959  (*nvarinds)--;
11960  }
11961 }
11962 
11963 /** substitute aggregated slack variables:
11964  *
11965  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
11966  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r] \f$.
11967  *
11968  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
11969  * \f[
11970  * \begin{array}{rll}
11971  * integers: & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) &, if \qquad f_r <= f0 \\
11972  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + p_r/(k + 1) &, if \qquad f_r > f0 \\
11973  * continuous:& \hat{a}_r = \tilde{a}_r = 0 &, if \qquad a^\prime_r >= 0 \\
11974  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_r < 0
11975  * \end{array}
11976  * \f]
11977  *
11978  * Substitute \f$ \hat{a}_r * s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
11979  */
11980 static
11982  SCIP_SET* set, /**< global SCIP settings */
11983  SCIP_STAT* stat, /**< problem statistics */
11984  SCIP_LP* lp, /**< LP data */
11985  SCIP_Real* weights, /**< row weights in row summation */
11986  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11987  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11988  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11989  int* slacksign, /**< stores the sign of the row's slack variable in summation */
11990  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11991  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11992  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11993  int* rowinds, /**< sparsity pattern of used rows */
11994  int nrowinds, /**< number of used rows */
11995  SCIP_Real f0, /**< fractional value of rhs */
11996  SCIP_Real k /**< factor to strengthen strongcg cut */
11997  )
11998 { /*lint --e{715}*/
11999  SCIP_Real onedivoneminusf0;
12000  int i;
12001 
12002  assert(lp != NULL);
12003  assert(weights != NULL);
12004  assert(!SCIPsetIsZero(set, scale));
12005  assert(strongcgcoef != NULL);
12006  assert(strongcgrhs != NULL);
12007  assert(slacksign != NULL);
12008  assert(varused != NULL);
12009  assert(varinds != NULL);
12010  assert(nvarinds != NULL);
12011  assert(rowinds != NULL);
12012  assert(0.0 < f0 && f0 < 1.0);
12013 
12014  onedivoneminusf0 = 1.0 / (1.0 - f0);
12015 
12016  for( i = 0; i < nrowinds; i++ )
12017  {
12018  SCIP_ROW* row;
12019  SCIP_Real pr;
12020  SCIP_Real ar;
12021  SCIP_Real downar;
12022  SCIP_Real cutar;
12023  SCIP_Real fr;
12024  SCIP_Real mul;
12025  int idx;
12026  int r;
12027  int j;
12028 
12029  r = rowinds[i];
12030  assert(0 <= r && r < lp->nrows);
12031  assert(slacksign[r] == -1 || slacksign[r] == +1);
12032  assert(!SCIPsetIsZero(set, weights[r]));
12033 
12034  row = lp->rows[r];
12035  assert(row != NULL);
12036  assert(row->len == 0 || row->cols != NULL);
12037  assert(row->len == 0 || row->cols_index != NULL);
12038  assert(row->len == 0 || row->vals != NULL);
12039 
12040  /* get the slack's coefficient a'_r in the aggregated row */
12041  ar = slacksign[r] * scale * weights[r];
12042 
12043  /* calculate slack variable's coefficient a^_r in the cut */
12044  if( row->integral )
12045  {
12046  /* slack variable is always integral: */
12047  downar = SCIPsetFloor(set, ar);
12048  fr = ar - downar;
12049 
12050  if( SCIPsetIsLE(set, fr, f0) )
12051  cutar = downar;
12052  else
12053  {
12054  pr = SCIPsetCeil(set, k * (fr - f0) * onedivoneminusf0);
12055  assert(pr >= 0); /* should be >= 1, but due to rounding bias can be 0 if fr almost equal to f0 */
12056  assert(pr <= k);
12057  cutar = downar + pr / (k + 1);
12058  }
12059  }
12060  else
12061  {
12062  /* slack variable is continuous: */
12063  assert(ar >= 0.0);
12064  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
12065  }
12066 
12067  /* if the coefficient was reduced to zero, ignore the slack variable */
12068  if( SCIPsetIsZero(set, cutar) )
12069  continue;
12070 
12071  /* depending on the slack's sign, we have
12072  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
12073  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
12074  */
12075  mul = -slacksign[r] * cutar;
12076 
12077  /* add the slack's definition multiplied with a^_j to the cut */
12078  for( j = 0; j < row->len; ++j )
12079  {
12080  assert(row->cols[j] != NULL);
12081  assert(row->cols[j]->var != NULL);
12082  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
12083  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
12084  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
12085  idx = row->cols[j]->var_probindex;
12086  strongcgcoef[idx] += mul * row->vals[j];
12087 
12088  /* update sparsity pattern */
12089  if( !varused[idx] )
12090  {
12091  varused[idx] = TRUE;
12092  varinds[*nvarinds] = idx;
12093  (*nvarinds)++;
12094  }
12095  }
12096 
12097  /* move slack's constant to the right hand side */
12098  if( slacksign[r] == +1 )
12099  {
12100  SCIP_Real rhs;
12101 
12102  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
12103  assert(!SCIPsetIsInfinity(set, row->rhs));
12104  rhs = row->rhs - row->constant;
12105  if( row->integral )
12106  {
12107  /* the right hand side was implicitly rounded down in row aggregation */
12108  rhs = SCIPsetFeasFloor(set, rhs);
12109  }
12110  *strongcgrhs -= cutar * rhs;
12111  }
12112  else
12113  {
12114  SCIP_Real lhs;
12115 
12116  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
12117  assert(!SCIPsetIsInfinity(set, -row->lhs));
12118  lhs = row->lhs - row->constant;
12119  if( row->integral )
12120  {
12121  /* the left hand side was implicitly rounded up in row aggregation */
12122  lhs = SCIPsetFeasCeil(set, lhs);
12123  }
12124  *strongcgrhs += cutar * lhs;
12125  }
12126  }
12127 
12128  /* set rhs to zero, if it's very close to */
12129  if( SCIPsetIsZero(set, *strongcgrhs) )
12130  *strongcgrhs = 0.0;
12131 }
12132 
12133 /* calculates a strong CG cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because
12134  * these rows cannot participate in a strong CG cut.
12135  */
12137  SCIP_LP* lp, /**< LP data */
12138  SCIP_SET* set, /**< global SCIP settings */
12139  SCIP_STAT* stat, /**< problem statistics */
12140  SCIP_PROB* prob, /**< problem data */
12141  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
12142  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
12143  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
12144  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
12145  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
12146  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce strong CG cut for */
12147  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce strong CG cut for */
12148  SCIP_Real* weights, /**< row weights in row summation */
12149  int* rowinds, /**< array to store indices of non-zero entries of the weights array, or
12150  * NULL */
12151  int nrowinds, /**< number of non-zero entries in weights array, -1 if rowinds is NULL */
12152  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
12153  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
12154  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
12155  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
12156  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid strong CG cut */
12157  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
12158  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
12159  )
12160 {
12161  int* slacksign;
12162  int* varsign;
12163  int* boundtype;
12164  SCIP_Bool* varused;
12165  int* varinds;
12166  int nvarinds;
12167  SCIP_Real rhs;
12168  SCIP_Real downrhs;
12169  SCIP_Real f0;
12170  SCIP_Real k;
12171  SCIP_Bool emptyrow;
12172  SCIP_Bool freevariable;
12173  SCIP_Bool localrowsused;
12174  SCIP_Bool localbdsused;
12175  SCIP_Bool rowtoolong;
12176  SCIP_Bool cleanuprowinds;
12177 
12178  assert(lp != NULL);
12179  assert(lp->solved);
12180  assert(prob != NULL);
12181  assert(weights != NULL);
12182  assert(!SCIPsetIsZero(set, scale));
12183  assert(strongcgcoef != NULL);
12184  assert(strongcgrhs != NULL);
12185  assert(cutactivity != NULL);
12186  assert(success != NULL);
12187  assert(cutislocal != NULL);
12188  assert(rowinds != NULL || nrowinds == -1);
12189 
12190  SCIPdebugMessage("calculating strong CG cut (scale: %g)\n", scale);
12191 
12192  /**@todo test, if a column based summation is faster */
12193 
12194  *success = FALSE;
12195  *cutislocal = FALSE;
12196 
12197  /* allocate temporary memory */
12198  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
12199  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
12200  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
12201  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
12202  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
12203 
12204  /* allocate memory for sparsity structure in case it has not been provided already */
12205  cleanuprowinds = FALSE;
12206  if( rowinds == NULL )
12207  {
12208  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
12209  cleanuprowinds = TRUE;
12210  }
12211 
12212  /* calculate the row summation */
12213  sumStrongCGRow(set, prob, lp, weights, scale, allowlocal,
12214  maxmksetcoefs, maxweightrange, strongcgcoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
12215  &emptyrow, &localrowsused, &rowtoolong, cutrank);
12216  assert(allowlocal || !localrowsused);
12217  *cutislocal = *cutislocal || localrowsused;
12218  if( emptyrow || rowtoolong )
12219  goto TERMINATE;
12220  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12221 
12222  /* remove all nearly-zero coefficients from strong CG row and relaxes the right hand side correspondingly in order to
12223  * prevent numerical rounding errors
12224  */
12225  cleanupMIRRow(set, prob, strongcgcoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
12226  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12227 
12228  /* Transform equation a*x == b, lb <= x <= ub into standard form
12229  * a'*x' == b, 0 <= x' <= ub'.
12230  *
12231  * Transform variables (lb or ub):
12232  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
12233  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
12234  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
12235  *
12236  * Transform variables (vlb or vub):
12237  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
12238  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
12239  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
12240  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
12241  * a_{zu_j} := a_{zu_j} + a_j * bu_j
12242  */
12243  transformStrongCGRow(set, stat, prob, boundswitch, usevbds, allowlocal,
12244  strongcgcoef, &rhs, varused, varinds, &nvarinds, varsign, boundtype, &freevariable, &localbdsused);
12245  assert(allowlocal || !localbdsused);
12246  *cutislocal = *cutislocal || localbdsused;
12247  if( freevariable )
12248  goto TERMINATE;
12249  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12250 
12251  /* Calculate
12252  * - fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j)
12253  * - integer k >= 1 with 1/(k + 1) <= f_0 < 1/k
12254  * (=> k = up(1/f_0) + 1)
12255  * - integer 1 <= p_j <= k with f_0 + ((p_j - 1) * (1 - f_0)/k) < f_j <= f_0 + (p_j * (1 - f_0)/k)
12256  * (=> p_j = up( (f_j - f_0)/((1 - f_0)/k) ))
12257  * and derive strong CG cut
12258  * a~*x' <= (k+1) * down(b)
12259  * integers : a~_j = down(a'_j) , if f_j <= f_0
12260  * a~_j = down(a'_j) + p_j/(k + 1) , if f_j > f_0
12261  * continuous: a~_j = 0 , if a'_j >= 0
12262  * no strong CG cut found , if a'_j < 0
12263  *
12264  * Transform inequality back to a^*x <= rhs:
12265  *
12266  * (lb or ub):
12267  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
12268  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
12269  * and move the constant terms
12270  * -a~_j * lb_j == -a^_j * lb_j, or
12271  * a~_j * ub_j == -a^_j * ub_j
12272  * to the rhs.
12273  *
12274  * (vlb or vub):
12275  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
12276  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
12277  * move the constant terms
12278  * -a~_j * dl_j == -a^_j * dl_j, or
12279  * a~_j * du_j == -a^_j * du_j
12280  * to the rhs, and update the VB variable coefficients:
12281  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
12282  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
12283  */
12284  downrhs = SCIPsetSumFloor(set, rhs);
12285  f0 = rhs - downrhs;
12286  if( f0 < minfrac || f0 > maxfrac )
12287  goto TERMINATE;
12288  k = SCIPsetCeil(set, 1.0 / f0) - 1;
12289 
12290  *strongcgrhs = downrhs;
12291  roundStrongCGRow(set, prob, strongcgcoef, strongcgrhs, varused, varinds, &nvarinds, varsign, boundtype, f0, k);
12292  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs));
12293 
12294  /* substitute aggregated slack variables:
12295  *
12296  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
12297  * variable only appears in its own row:
12298  * a'_r = scale * weight[r] * slacksign[r].
12299  *
12300  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
12301  * integers : a^_r = a~_r = (k + 1) * down(a'_r) , if f_r <= f0
12302  * a^_r = a~_r = (k + 1) * down(a'_r) + p_r , if f_r > f0
12303  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
12304  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
12305  *
12306  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
12307  */
12308  substituteStrongCGRow(set, stat, lp, weights, scale, strongcgcoef, strongcgrhs, slacksign,
12309  varused, varinds, &nvarinds, rowinds, nrowinds, f0, k);
12310  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs));
12311 
12312  /* remove again all nearly-zero coefficients from strong CG row and relax the right hand side correspondingly in order to
12313  * prevent numerical rounding errors
12314  */
12315  cleanupMIRRow(set, prob, strongcgcoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
12316  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12317 
12318  /* calculate cut activity */
12319  *cutactivity = getMIRRowActivity(set, stat, prob, NULL, strongcgcoef, varinds, nvarinds);
12320  *success = TRUE;
12321 
12322  TERMINATE:
12323  /* free temporary memory */
12324  if( cleanuprowinds )
12325  {
12326  SCIPsetFreeBufferArray(set, &rowinds);
12327  }
12328 
12329  SCIPsetFreeBufferArray(set, &varinds);
12330  SCIPsetFreeBufferArray(set, &varused);
12331  SCIPsetFreeBufferArray(set, &boundtype);
12332  SCIPsetFreeBufferArray(set, &varsign);
12333  SCIPsetFreeBufferArray(set, &slacksign);
12334 
12335  return SCIP_OKAY;
12336 }
12337 
12338 /** stores LP state (like basis information) into LP state object */
12340  SCIP_LP* lp, /**< LP data */
12341  BMS_BLKMEM* blkmem, /**< block memory */
12342  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
12343  )
12344 {
12345  assert(lp != NULL);
12346  assert(lp->flushed);
12347  assert(lp->solved);
12348  assert(blkmem != NULL);
12349  assert(lpistate != NULL);
12350 
12351  /* check whether there is no lp */
12352  if( lp->nlpicols == 0 && lp->nlpirows == 0 )
12353  *lpistate = NULL;
12354  else
12355  {
12356  SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
12357  }
12358 
12359  return SCIP_OKAY;
12360 }
12361 
12362 /** loads LP state (like basis information) into solver */
12364  SCIP_LP* lp, /**< LP data */
12365  BMS_BLKMEM* blkmem, /**< block memory */
12366  SCIP_SET* set, /**< global SCIP settings */
12367  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12368  SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
12369  SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
12370  SCIP_Bool wasdualfeas /**< dual feasibility when LP state information was stored */
12371  )
12372 {
12373  assert(lp != NULL);
12374  assert(blkmem != NULL);
12375 
12376  /* flush changes to the LP solver */
12377  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
12378  assert(lp->flushed);
12379 
12380  if( lp->solved && lp->solisbasic )
12381  return SCIP_OKAY;
12382 
12383  /* set LPI state in the LP solver */
12384  if( lpistate == NULL )
12385  lp->solisbasic = FALSE;
12386  else
12387  {
12388  SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
12389  lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
12390  }
12391  /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
12392  * flushed and solved, also, e.g., when we hit the iteration limit
12393  */
12394  lp->primalfeasible = wasprimfeas;
12395  lp->dualfeasible = wasdualfeas;
12396 
12397  return SCIP_OKAY;
12398 }
12399 
12400 /** frees LP state information */
12402  SCIP_LP* lp, /**< LP data */
12403  BMS_BLKMEM* blkmem, /**< block memory */
12404  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
12405  )
12406 {
12407  assert(lp != NULL);
12408 
12409  if( *lpistate != NULL )
12410  {
12411  SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
12412  }
12413 
12414  return SCIP_OKAY;
12415 }
12416 
12417 /** stores pricing norms into LP norms object */
12419  SCIP_LP* lp, /**< LP data */
12420  BMS_BLKMEM* blkmem, /**< block memory */
12421  SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
12422  )
12423 {
12424  assert(lp != NULL);
12425  assert(lp->flushed);
12426  assert(lp->solved);
12427  assert(blkmem != NULL);
12428  assert(lpinorms != NULL);
12429 
12430  /* check whether there is no lp */
12431  if( lp->nlpicols == 0 && lp->nlpirows == 0 )
12432  *lpinorms = NULL;
12433  else
12434  {
12435  SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
12436  }
12437 
12438  return SCIP_OKAY;
12439 }
12440 
12441 /** loads pricing norms from LP norms object into solver */
12443  SCIP_LP* lp, /**< LP data */
12444  BMS_BLKMEM* blkmem, /**< block memory */
12445  SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
12446  )
12447 {
12448  assert(lp != NULL);
12449  assert(blkmem != NULL);
12450  assert(lp->flushed);
12451 
12452  /* set LPI norms in the LP solver */
12453  if( lpinorms != NULL )
12454  {
12455  SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
12456  }
12457 
12458  return SCIP_OKAY;
12459 }
12460 
12461 /** frees pricing norms information */
12463  SCIP_LP* lp, /**< LP data */
12464  BMS_BLKMEM* blkmem, /**< block memory */
12465  SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
12466  )
12467 {
12468  assert(lp != NULL);
12469 
12470  SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
12471 
12472  return SCIP_OKAY;
12473 }
12474 
12475 /** sets the upper objective limit of the LP solver */
12477  SCIP_LP* lp, /**< current LP data */
12478  SCIP_SET* set, /**< global SCIP settings */
12479  SCIP_PROB* prob, /**< problem data */
12480  SCIP_Real cutoffbound /**< new upper objective limit */
12481  )
12482 {
12483  assert(lp != NULL);
12484 
12485  SCIPdebugMessage("setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
12486 
12487  /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
12488  * in SCIPendDive())
12489  */
12490  if( SCIPlpDivingObjChanged(lp) )
12491  {
12492  assert(SCIPsetIsInfinity(set, lp->cutoffbound));
12493  return SCIP_OKAY;
12494  }
12495 
12496  /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
12497  if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
12498  {
12499  /* mark the current solution invalid */
12500  lp->solved = FALSE;
12501  lp->lpobjval = SCIP_INVALID;
12503  }
12504  /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
12505  * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
12506  */
12508  && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
12509  {
12510  assert(lp->flushed);
12511  assert(lp->solved);
12513  }
12514 
12515  lp->cutoffbound = cutoffbound;
12516 
12517  return SCIP_OKAY;
12518 }
12519 
12520 /** returns the name of the given LP algorithm */
12521 static
12522 const char* lpalgoName(
12523  SCIP_LPALGO lpalgo /**< LP algorithm */
12524  )
12525 {
12526  switch( lpalgo )
12527  {
12529  return "primal simplex";
12531  return "dual simplex";
12532  case SCIP_LPALGO_BARRIER:
12533  return "barrier";
12535  return "barrier/crossover";
12536  default:
12537  SCIPerrorMessage("invalid LP algorithm\n");
12538  SCIPABORT();
12539  return "invalid"; /*lint !e527*/
12540  }
12541 }
12542 
12543 /** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
12544 static
12546  SCIP_LP* lp, /**< current LP data */
12547  SCIP_SET* set, /**< global SCIP settings */
12548  SCIP_STAT* stat, /**< problem statistics */
12549  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12550  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12551  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12552  )
12553 {
12554  SCIP_Real timedelta;
12555  SCIP_RETCODE retcode;
12556  int iterations;
12557 
12558  assert(lp != NULL);
12559  assert(lp->flushed);
12560  assert(set != NULL);
12561  assert(stat != NULL);
12562  assert(lperror != NULL);
12563 
12564  SCIPdebugMessage("solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
12565  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
12566 
12567  *lperror = FALSE;
12568 
12569 #if 0 /* for debugging: write all node LP's */
12570  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
12571  {
12572  char fname[SCIP_MAXSTRLEN];
12573  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
12574  SCIP_CALL( SCIPlpWrite(lp, fname) );
12575  SCIPmessagePrintInfo("wrote LP to file <%s> (primal simplex, uobjlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
12576  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol,
12577  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
12578  }
12579 #endif
12580 
12581  /* start timing */
12582  if( lp->diving || lp->probing )
12583  {
12584  if( lp->strongbranchprobing )
12585  SCIPclockStart(stat->strongbranchtime, set);
12586  else
12587  SCIPclockStart(stat->divinglptime, set);
12588 
12589  timedelta = 0.0; /* unused for diving or probing */
12590  }
12591  else
12592  {
12593  SCIPclockStart(stat->primallptime, set);
12594  timedelta = -SCIPclockGetTime(stat->primallptime);
12595  }
12596 
12597  /* call primal simplex */
12598  retcode = SCIPlpiSolvePrimal(lp->lpi);
12599  if( retcode == SCIP_LPERROR )
12600  {
12601  *lperror = TRUE;
12602  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
12603  }
12604  else
12605  {
12606  SCIP_CALL( retcode );
12607  }
12609  lp->solisbasic = TRUE;
12610 
12611  /* stop timing */
12612  if( lp->diving || lp->probing )
12613  {
12614  if( lp->strongbranchprobing )
12615  SCIPclockStop(stat->strongbranchtime, set);
12616  else
12617  SCIPclockStop(stat->divinglptime, set);
12618  }
12619  else
12620  {
12621  timedelta += SCIPclockGetTime(stat->primallptime);
12622  SCIPclockStop(stat->primallptime, set);
12623  }
12624 
12625  /* count number of iterations */
12626  stat->lpcount++;
12627  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12628  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12629  {
12630  if( !lp->strongbranchprobing )
12631  {
12632  stat->nlps++;
12633  stat->nlpiterations += iterations;
12634  }
12635  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12636  {
12637  stat->nprimalresolvelps++;
12638  stat->nprimalresolvelpiterations += iterations;
12639  }
12640  if( lp->diving || lp->probing )
12641  {
12642  if( lp->strongbranchprobing )
12643  {
12644  stat->nsbdivinglps++;
12645  stat->nsbdivinglpiterations += iterations;
12646  }
12647  else
12648  {
12649  stat->lastdivenode = stat->nnodes;
12650  stat->ndivinglps++;
12651  stat->ndivinglpiterations += iterations;
12652  }
12653  }
12654  else
12655  {
12656  stat->nprimallps++;
12657  stat->nprimallpiterations += iterations;
12658  }
12659  }
12660  else
12661  {
12662  if ( ! lp->diving && ! lp->probing )
12663  {
12664  stat->nprimalzeroitlps++;
12665  stat->primalzeroittime += timedelta;
12666  }
12667 
12668  if ( keepsol && !(*lperror) )
12669  {
12670  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
12671  if( lp->validsollp == stat->lpcount-1 )
12672  lp->validsollp = stat->lpcount;
12673  if( lp->validfarkaslp == stat->lpcount-1 )
12674  lp->validfarkaslp = stat->lpcount;
12675  }
12676  }
12677 
12678  SCIPdebugMessage("solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
12679  stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
12680 
12681  return SCIP_OKAY;
12682 }
12683 
12684 /** calls LPI to perform dual simplex, measures time and counts iterations */
12685 static
12687  SCIP_LP* lp, /**< current LP data */
12688  SCIP_SET* set, /**< global SCIP settings */
12689  SCIP_STAT* stat, /**< problem statistics */
12690  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12691  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12692  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12693  )
12694 {
12695  SCIP_Real timedelta;
12696  SCIP_RETCODE retcode;
12697  int iterations;
12698 
12699  assert(lp != NULL);
12700  assert(lp->flushed);
12701  assert(set != NULL);
12702  assert(stat != NULL);
12703  assert(lperror != NULL);
12704 
12705  SCIPdebugMessage("solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
12706  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12707 
12708  *lperror = FALSE;
12709 
12710 #if 0 /* for debugging: write all node LP's */
12711  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
12712  {
12713  char fname[SCIP_MAXSTRLEN];
12714  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
12715  SCIP_CALL( SCIPlpWrite(lp, fname) );
12716  SCIPmessagePrintInfo("wrote LP to file <%s> (dual simplex, uobjlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
12717  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol,
12718  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
12719  }
12720 #endif
12721 
12722  /* start timing */
12723  if( lp->diving || lp->probing )
12724  {
12725  if( lp->strongbranchprobing )
12726  SCIPclockStart(stat->strongbranchtime, set);
12727  else
12728  SCIPclockStart(stat->divinglptime, set);
12729 
12730  timedelta = 0.0; /* unused for diving or probing */
12731  }
12732  else
12733  {
12734  SCIPclockStart(stat->duallptime, set);
12735  timedelta = -SCIPclockGetTime(stat->duallptime);
12736  }
12737 
12738  /* call dual simplex */
12739  retcode = SCIPlpiSolveDual(lp->lpi);
12740  if( retcode == SCIP_LPERROR )
12741  {
12742  *lperror = TRUE;
12743  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
12744  }
12745  else
12746  {
12747  SCIP_CALL( retcode );
12748  }
12750  lp->solisbasic = TRUE;
12751 
12752  /* stop timing */
12753  if( lp->diving || lp->probing )
12754  {
12755  if( lp->strongbranchprobing )
12756  SCIPclockStop(stat->strongbranchtime, set);
12757  else
12758  SCIPclockStop(stat->divinglptime, set);
12759  }
12760  else
12761  {
12762  timedelta += SCIPclockGetTime(stat->duallptime);
12763  SCIPclockStop(stat->duallptime, set);
12764  }
12765 
12766  /* count number of iterations */
12767  stat->lpcount++;
12768  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12769  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12770  {
12771  if( !lp->strongbranchprobing )
12772  {
12773  stat->nlps++;
12774  stat->nlpiterations += iterations;
12775  }
12776  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12777  {
12778  stat->ndualresolvelps++;
12779  stat->ndualresolvelpiterations += iterations;
12780  }
12781  if( lp->diving || lp->probing )
12782  {
12783  if( lp->strongbranchprobing )
12784  {
12785  stat->nsbdivinglps++;
12786  stat->nsbdivinglpiterations += iterations;
12787  }
12788  else
12789  {
12790  stat->lastdivenode = stat->nnodes;
12791  stat->ndivinglps++;
12792  stat->ndivinglpiterations += iterations;
12793  }
12794  }
12795  else
12796  {
12797  stat->nduallps++;
12798  stat->nduallpiterations += iterations;
12799  }
12800  }
12801  else
12802  {
12803  if ( ! lp->diving && ! lp->probing )
12804  {
12805  stat->ndualzeroitlps++;
12806  stat->dualzeroittime += timedelta;
12807  }
12808 
12809  if( keepsol && !(*lperror) )
12810  {
12811  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
12812  if( lp->validsollp == stat->lpcount-1 )
12813  lp->validsollp = stat->lpcount;
12814  if( lp->validfarkaslp == stat->lpcount-1 )
12815  lp->validfarkaslp = stat->lpcount;
12816  }
12817  }
12818 
12819  SCIPdebugMessage("solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
12820  stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12821 
12822  return SCIP_OKAY;
12823 }
12824 
12825 /** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
12826  *
12827  * We follow the approach of the following paper to find a lexicographically minimal optimal
12828  * solution:
12829  *
12830  * Zanette, Fischetti, Balas@n
12831  * Can pure cutting plane algorithms work?@n
12832  * IPCO 2008, Bertinoro, Italy.
12833  *
12834  * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
12835  * heuristic, i.e., we limit the number of components which are minimized.
12836  *
12837  * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
12838  * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
12839  * variables) that have nonzero reduced cost. This fixes the objective function value, because only
12840  * pivots that will not change the objective are allowed afterwards.
12841  *
12842  * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
12843  * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
12844  * candidate is found, we set the objective to minimize this variable. We run the primal simplex
12845  * algorithm (since the objective is changed the solution is not dual feasible anymore; if
12846  * variables out of the basis have been fixed to their lower bound, the basis is also not primal
12847  * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
12848  * reduced cost. We then choose the next variable and iterate.
12849  *
12850  * We stop the process once we do not find candidates or have performed a maximum number of
12851  * iterations.
12852  *
12853  * @todo Does this really produce a lexicographically minimal solution?
12854  * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
12855  * guarantee that these variables will not be changed in later stages? We can fix these variables
12856  * to their lower bound, but this destroys the basis.
12857  * @todo Should we use lexicographical minimization in diving/probing or not?
12858  */
12859 static
12861  SCIP_LP* lp, /**< current LP data */
12862  SCIP_SET* set, /**< global SCIP settings */
12863  SCIP_STAT* stat, /**< problem statistics */
12864  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12865  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12866  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12867  )
12868 {
12869  SCIP_Real timedelta;
12870  SCIP_RETCODE retcode;
12871  int totalIterations;
12872  int lexIterations;
12873  int iterations;
12874  int rounds;
12875 
12876  assert(lp != NULL);
12877  assert(lp->flushed);
12878  assert(set != NULL);
12879  assert(stat != NULL);
12880  assert(lperror != NULL);
12881 
12882  SCIPdebugMessage("solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
12883  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12884 
12885  *lperror = FALSE;
12886 
12887  /* start timing */
12888  if( lp->diving || lp->probing )
12889  {
12890  if( lp->strongbranchprobing )
12891  SCIPclockStart(stat->strongbranchtime, set);
12892  else
12893  SCIPclockStart(stat->divinglptime, set);
12894 
12895  timedelta = 0.0; /* unused for diving or probing */
12896  }
12897  else
12898  {
12899  SCIPclockStart(stat->duallptime, set);
12900  timedelta = -SCIPclockGetTime(stat->duallptime);
12901  }
12902 
12903  /* call dual simplex for first lp */
12904  retcode = SCIPlpiSolveDual(lp->lpi);
12905  if( retcode == SCIP_LPERROR )
12906  {
12907  *lperror = TRUE;
12908  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
12909  }
12910  else
12911  {
12912  SCIP_CALL( retcode );
12913  }
12914  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12915  totalIterations = iterations;
12916 
12917  /* stop timing */
12918  if( lp->diving || lp->probing )
12919  {
12920  if( lp->strongbranchprobing )
12921  SCIPclockStop(stat->strongbranchtime, set);
12922  else
12923  SCIPclockStop(stat->divinglptime, set);
12924  }
12925  else
12926  {
12927  timedelta += SCIPclockGetTime(stat->duallptime);
12928  SCIPclockStop(stat->duallptime, set);
12929  }
12930 
12931  /* count number of iterations */
12932  stat->lpcount++;
12933  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12934  {
12935  if( lp->strongbranchprobing )
12936  {
12937  stat->nlpiterations += iterations;
12938  }
12939  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12940  {
12941  stat->ndualresolvelps++;
12942  stat->ndualresolvelpiterations += iterations;
12943  }
12944  if( lp->diving || lp->probing )
12945  {
12946  if( lp->strongbranchprobing )
12947  {
12948  stat->nsbdivinglps++;
12949  stat->nsbdivinglpiterations += iterations;
12950  }
12951  else
12952  {
12953  stat->lastdivenode = stat->nnodes;
12954  stat->ndivinglps++;
12955  stat->ndivinglpiterations += iterations;
12956  }
12957  }
12958  else
12959  {
12960  stat->nduallps++;
12961  stat->nduallpiterations += iterations;
12962  }
12963  }
12964  else
12965  {
12966  if ( ! lp->diving && ! lp->probing )
12967  {
12968  stat->ndualzeroitlps++;
12969  stat->dualzeroittime += timedelta;
12970  }
12971  }
12972  lexIterations = 0;
12973 
12974  /* search for lexicographically minimal optimal solution */
12975  if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
12976  {
12977  SCIP_Bool chooseBasic;
12978  SCIP_Real* primsol;
12979  SCIP_Real* dualsol;
12980  SCIP_Real* redcost;
12981  int* cstat;
12982  int* rstat;
12983  SCIP_Real* newobj;
12984  SCIP_Real* newlb;
12985  SCIP_Real* newub;
12986  SCIP_Real* newlhs;
12987  SCIP_Real* newrhs;
12988  SCIP_Real* oldlb;
12989  SCIP_Real* oldub;
12990  SCIP_Real* oldlhs;
12991  SCIP_Real* oldrhs;
12992  SCIP_Real* oldobj;
12993  SCIP_Bool* fixedc;
12994  SCIP_Bool* fixedr;
12995  int* indcol;
12996  int* indrow;
12997  int* indallcol;
12998  int* indallrow;
12999  int nDualDeg;
13000  int r, c;
13001  int cntcol;
13002  int cntrow;
13003  int nruns;
13004  int pos;
13005 
13006  chooseBasic = set->lp_lexdualbasic;
13007 
13008  /* start timing */
13009  SCIPclockStart(stat->lexduallptime, set);
13010 
13011  /* get all solution information */
13012  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
13013  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
13014  if( chooseBasic )
13015  {
13016  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
13017  }
13018  else
13019  primsol = NULL;
13020 
13021  /* get basic and nonbasic information */
13022  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
13023  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
13024 
13025  /* save bounds, lhs/rhs, and objective */
13026  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldobj, lp->nlpicols) );
13027  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlb, lp->nlpicols) );
13028  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldub, lp->nlpicols) );
13029  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlhs, lp->nlpirows) );
13030  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldrhs, lp->nlpirows) );
13031  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
13032  SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
13033  SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
13034 
13035  /* get storage for several arrays */
13036  SCIP_CALL( SCIPsetAllocBufferArray(set, &newlb, lp->nlpicols) );
13037  SCIP_CALL( SCIPsetAllocBufferArray(set, &newub, lp->nlpicols) );
13038  SCIP_CALL( SCIPsetAllocBufferArray(set, &indcol, lp->nlpicols) );
13039 
13040  SCIP_CALL( SCIPsetAllocBufferArray(set, &newlhs, lp->nlpirows) );
13041  SCIP_CALL( SCIPsetAllocBufferArray(set, &newrhs, lp->nlpirows) );
13042  SCIP_CALL( SCIPsetAllocBufferArray(set, &indrow, lp->nlpirows) );
13043 
13044  SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
13045  SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
13046 
13047  SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedc, lp->nlpicols) );
13048  SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedr, lp->nlpirows) );
13049 
13050  /* initialize: set objective to 0, get fixed variables */
13051  SCIP_CALL( SCIPsetAllocBufferArray(set, &newobj, lp->nlpicols) );
13052  for( c = 0; c < lp->nlpicols; ++c )
13053  {
13054  newobj[c] = 0.0;
13055  indallcol[c] = c;
13056  if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
13057  fixedc[c] = TRUE;
13058  else
13059  fixedc[c] = FALSE;
13060  }
13061 
13062  /* initialize: get fixed slack variables */
13063  for( r = 0; r < lp->nlpirows; ++r )
13064  {
13065  indallrow[r] = r;
13066  if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
13067  fixedr[r] = TRUE;
13068  else
13069  fixedr[r] = FALSE;
13070  }
13071 
13072 #ifdef DEBUG_LEXDUAL
13073  {
13074  int j;
13075 
13076  if( !chooseBasic )
13077  {
13078  assert(primsol == NULL);
13079  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
13080  }
13081  assert(primsol != NULL);
13082  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
13083  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
13084 
13085  for( j = 0; j < lp->nlpicols; ++j )
13086  {
13087  if( fixedc[j] )
13088  {
13089  SCIPdebugMessage("%f (%d) [f] ", primsol[j], j);
13090  }
13091  else
13092  {
13093  char type;
13094  switch( (SCIP_BASESTAT) cstat[j] )
13095  {
13096  case SCIP_BASESTAT_LOWER:
13097  type = 'l';
13098  break;
13099  case SCIP_BASESTAT_UPPER:
13100  type = 'u';
13101  break;
13102  case SCIP_BASESTAT_ZERO:
13103  type = 'z';
13104  break;
13105  case SCIP_BASESTAT_BASIC:
13106  type = 'b';
13107  break;
13108  default:
13109  type = '?';
13110  SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
13111  SCIPABORT();
13112  }
13113  SCIPdebugMessage("%f (%d) [%c] ", primsol[j], j, type);
13114  }
13115  }
13116  SCIPdebugMessage("\n\n");
13117 
13118  if( !chooseBasic )
13119  {
13120  SCIPsetFreeBufferArray(set, &primsol);
13121  assert(primsol == NULL);
13122  }
13123  }
13124 #endif
13125 
13126  /* perform lexicographic rounds */
13127  pos = -1;
13128  nruns = 0;
13129  rounds = 0;
13130  /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
13131  do
13132  {
13133  int oldpos;
13134 
13135  /* get current solution */
13136  if( chooseBasic )
13137  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
13138  else
13139  {
13140  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
13141  assert(primsol == NULL);
13142  }
13143 
13144  /* get current basis */
13145  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
13146 
13147  /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
13148  nDualDeg = 0;
13149  cntcol = 0;
13150  oldpos = pos;
13151  pos = -1;
13152  for( c = 0; c < lp->nlpicols; ++c )
13153  {
13154  if( !fixedc[c] )
13155  {
13156  /* check whether variable is in basis */
13157  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
13158  {
13159  /* store first candidate */
13160  if( pos == -1 && c > oldpos )
13161  {
13162  if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
13163  pos = c;
13164  }
13165  }
13166  else
13167  {
13168  /* reduced cost == 0 -> possible candidate */
13169  if( SCIPsetIsDualfeasZero(set, redcost[c]) )
13170  {
13171  ++nDualDeg;
13172  /* only if we have not yet found a candidate */
13173  if( pos == -1 && c > oldpos )
13174  {
13175  /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
13176  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
13177  {
13178  newlb[cntcol] = oldlb[c];
13179  newub[cntcol] = oldlb[c];
13180  indcol[cntcol++] = c;
13181  fixedc[c] = TRUE;
13182  }
13183  else /* found a non-fixed candidate */
13184  {
13185  if( !chooseBasic )
13186  pos = c;
13187  }
13188  }
13189  }
13190  else
13191  {
13192  /* nonzero reduced cost -> variable can be fixed */
13193  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
13194  {
13195  newlb[cntcol] = oldlb[c];
13196  newub[cntcol] = oldlb[c];
13197  }
13198  else
13199  {
13200  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
13201  {
13202  newlb[cntcol] = oldub[c];
13203  newub[cntcol] = oldub[c];
13204  }
13205  else
13206  {
13207  assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
13208  newlb[cntcol] = 0.0;
13209  newub[cntcol] = 0.0;
13210  }
13211  }
13212  indcol[cntcol++] = c;
13213  fixedc[c] = TRUE;
13214  }
13215  }
13216  }
13217  }
13218 
13219  /* check rows */
13220  cntrow = 0;
13221  for( r = 0; r < lp->nlpirows; ++r )
13222  {
13223  if( !fixedr[r] )
13224  {
13225  /* consider only nonbasic rows */
13226  if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
13227  {
13228  assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
13229  if( SCIPsetIsFeasZero(set, dualsol[r]) )
13230  ++nDualDeg;
13231  else
13232  {
13233  if( SCIPsetIsFeasPositive(set, dualsol[r]) )
13234  {
13235  assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
13236  newlhs[cntrow] = oldlhs[r];
13237  newrhs[cntrow] = oldlhs[r];
13238  }
13239  else
13240  {
13241  assert(!SCIPsetIsInfinity(set, oldrhs[r]));
13242  newlhs[cntrow] = oldrhs[r];
13243  newrhs[cntrow] = oldrhs[r];
13244  }
13245  indrow[cntrow++] = r;
13246  fixedr[r] = TRUE;
13247  }
13248  }
13249  }
13250  }
13251 
13252  if( nDualDeg > 0 && pos >= 0 )
13253  {
13254  assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
13255 
13256  /* change objective */
13257  if( nruns == 0 )
13258  {
13259  /* set objective to appropriate unit vector for first run */
13260  newobj[pos] = 1.0;
13261  SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
13262  }
13263  else
13264  {
13265  /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
13266  SCIP_Real obj = 1.0;
13267  SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
13268  }
13269 
13270  /* fix variables */
13271  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
13272  SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
13273 
13274  /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
13275  retcode = SCIPlpiSolvePrimal(lp->lpi);
13276  if( retcode == SCIP_LPERROR )
13277  {
13278  *lperror = TRUE;
13279  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
13280  }
13281  else
13282  {
13283  SCIP_CALL( retcode );
13284  }
13285  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13286  lexIterations += iterations;
13287 
13288 #ifdef DEBUG_LEXDUAL
13289  if( iterations > 0 )
13290  {
13291  int j;
13292 
13293  if( !chooseBasic )
13294  {
13295  assert(primsol == NULL);
13296  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
13297  }
13298  assert(primsol != NULL);
13299  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
13300 
13301  for( j = 0; j < lp->nlpicols; ++j )
13302  {
13303  if( fixedc[j] )
13304  {
13305  SCIPdebugMessage("%f (%d) [f] ", primsol[j], j);
13306  }
13307  else
13308  {
13309  char cstart = '[';
13310  char cend = ']';
13311  char type;
13312 
13313  if(j == pos)
13314  {
13315  cstart = '*';
13316  cend = '*';
13317  }
13318 
13319  switch( (SCIP_BASESTAT) cstat[j] )
13320  {
13321  case SCIP_BASESTAT_LOWER:
13322  type = 'l';
13323  break;
13324  case SCIP_BASESTAT_UPPER:
13325  type = 'u';
13326  break;
13327  case SCIP_BASESTAT_ZERO:
13328  type = 'z';
13329  break;
13330  case SCIP_BASESTAT_BASIC:
13331  type = 'b';
13332  break;
13333  default:
13334  type = '?';
13335  SCIPerrorMessage("unknown base state %d\n", cstat[j]);
13336  SCIPABORT();
13337  }
13338  SCIPdebugMessage("%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
13339  }
13340  }
13341  SCIPdebugMessage("\n\n");
13342 
13343  if( !chooseBasic )
13344  {
13345  SCIPsetFreeBufferArray(set, &primsol);
13346  assert(primsol == NULL);
13347  }
13348  }
13349 #endif
13350 
13351  /* count only as round if iterations have been performed */
13352  if( iterations > 0 )
13353  ++rounds;
13354  ++nruns;
13355  }
13356  }
13357  while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
13358 
13359  /* reset bounds, lhs/rhs, and obj */
13360  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
13361  SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
13362  SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
13363 
13364  /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
13365  retcode = SCIPlpiSolveDual(lp->lpi);
13366  if( retcode == SCIP_LPERROR )
13367  {
13368  *lperror = TRUE;
13369  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
13370  }
13371  else
13372  {
13373  SCIP_CALL( retcode );
13374  }
13375  assert(SCIPlpiIsOptimal(lp->lpi));
13376  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13377  lexIterations += iterations;
13378 
13379  /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
13380 
13381  /* count number of iterations */
13382  if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
13383  stat->nlps++;
13384 
13385  if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
13386  {
13387  stat->nlpiterations += lexIterations;
13388  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
13389  {
13390  stat->nlexdualresolvelps++;
13391  stat->nlexdualresolvelpiterations += lexIterations;
13392  }
13393  stat->nlexduallps++;
13394  stat->nlexduallpiterations += lexIterations;
13395 
13396  totalIterations += lexIterations;
13397  }
13398 
13399  /* free space */
13400  SCIPsetFreeBufferArray(set, &newobj);
13401 
13402  SCIPsetFreeBufferArray(set, &fixedr);
13403  SCIPsetFreeBufferArray(set, &fixedc);
13404 
13405  SCIPsetFreeBufferArray(set, &indallrow);
13406  SCIPsetFreeBufferArray(set, &indallcol);
13407 
13408  SCIPsetFreeBufferArray(set, &indrow);
13409  SCIPsetFreeBufferArray(set, &newrhs);
13410  SCIPsetFreeBufferArray(set, &newlhs);
13411 
13412  SCIPsetFreeBufferArray(set, &indcol);
13413  SCIPsetFreeBufferArray(set, &newub);
13414  SCIPsetFreeBufferArray(set, &newlb);
13415 
13416  SCIPsetFreeBufferArray(set, &oldobj);
13417  SCIPsetFreeBufferArray(set, &oldrhs);
13418  SCIPsetFreeBufferArray(set, &oldlhs);
13419  SCIPsetFreeBufferArray(set, &oldub);
13420  SCIPsetFreeBufferArray(set, &oldlb);
13421 
13422  SCIPsetFreeBufferArray(set, &rstat);
13423  SCIPsetFreeBufferArray(set, &cstat);
13424 
13425  SCIPsetFreeBufferArray(set, &redcost);
13426  SCIPsetFreeBufferArray(set, &dualsol);
13427  if( chooseBasic )
13428  SCIPsetFreeBufferArray(set, &primsol);
13429 
13430  /* stop timing */
13431  SCIPclockStop(stat->lexduallptime, set);
13432 
13433  SCIPdebugMessage("solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
13434  stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
13435  }
13437  lp->solisbasic = TRUE;
13438 
13439  if( totalIterations > 0 && !lp->strongbranchprobing )
13440  stat->nlps++;
13441  else
13442  {
13443  if( keepsol && !(*lperror) )
13444  {
13445  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
13446  if( lp->validsollp == stat->lpcount-1 )
13447  lp->validsollp = stat->lpcount;
13448  if( lp->validfarkaslp == stat->lpcount-1 )
13449  lp->validfarkaslp = stat->lpcount;
13450  }
13451  }
13452 
13453  return SCIP_OKAY;
13454 }
13455 
13456 /** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
13457 static
13459  SCIP_LP* lp, /**< current LP data */
13460  SCIP_SET* set, /**< global SCIP settings */
13461  SCIP_STAT* stat, /**< problem statistics */
13462  SCIP_Bool crossover, /**< should crossover be performed? */
13463  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13464  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13465  )
13466 {
13467  SCIP_Real timedelta;
13468  SCIP_RETCODE retcode;
13469  int iterations;
13470 
13471  assert(lp != NULL);
13472  assert(lp->flushed);
13473  assert(set != NULL);
13474  assert(stat != NULL);
13475  assert(lperror != NULL);
13476 
13477  SCIPdebugMessage("solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
13478  stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
13479  stat->nbarrierlps, stat->ndivinglps);
13480 
13481  *lperror = FALSE;
13482 
13483 #if 0 /* for debugging: write all node LP's */
13484  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
13485  {
13486  char fname[SCIP_MAXSTRLEN];
13487  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
13488  SCIP_CALL( SCIPlpWrite(lp, fname) );
13489  SCIPmessagePrintInfo("wrote LP to file <%s> (barrier, uobjlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
13490  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
13491  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
13492  }
13493 #endif
13494 
13495  /* start timing */
13496  if( lp->diving || lp->probing )
13497  {
13498  if( lp->strongbranchprobing )
13499  SCIPclockStart(stat->strongbranchtime, set);
13500  else
13501  SCIPclockStart(stat->divinglptime, set);
13502 
13503  timedelta = 0.0; /* unused for diving or probing */
13504  }
13505  else
13506  {
13507  SCIPclockStart(stat->barrierlptime, set);
13508  timedelta = -SCIPclockGetTime(stat->duallptime);
13509  }
13510 
13511  /* call barrier algorithm */
13512  retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
13513  if( retcode == SCIP_LPERROR )
13514  {
13515  *lperror = TRUE;
13516  SCIPdebugMessage("(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
13517  }
13518  else
13519  {
13520  SCIP_CALL( retcode );
13521  }
13523  lp->solisbasic = crossover;
13524 
13525  /* stop timing */
13526  if( lp->diving || lp->probing )
13527  {
13528  if( lp->strongbranchprobing )
13529  SCIPclockStop(stat->strongbranchtime, set);
13530  else
13531  SCIPclockStop(stat->divinglptime, set);
13532  }
13533  else
13534  {
13535  SCIPclockStop(stat->barrierlptime, set);
13536  timedelta = -SCIPclockGetTime(stat->duallptime);
13537  }
13538 
13539  /* count number of iterations */
13540  stat->lpcount++;
13541  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13542  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
13543  {
13544  if( !lp->strongbranchprobing )
13545  {
13546  stat->nlps++;
13547  stat->nlpiterations += iterations;
13548  }
13549  if( lp->diving || lp->probing )
13550  {
13551  if( lp->strongbranchprobing )
13552  {
13553  stat->nsbdivinglps++;
13554  stat->nsbdivinglpiterations += iterations;
13555  }
13556  else
13557  {
13558  stat->lastdivenode = stat->nnodes;
13559  stat->ndivinglps++;
13560  stat->ndivinglpiterations += iterations;
13561  }
13562  }
13563  else
13564  {
13565  stat->nbarrierlps++;
13566  stat->nbarrierlpiterations += iterations;
13567  }
13568  }
13569  else
13570  {
13571  if ( ! lp->diving && ! lp->probing )
13572  {
13573  stat->nbarrierzeroitlps++;
13574  stat->barrierzeroittime += timedelta;
13575  }
13576 
13577  if( keepsol && !(*lperror) )
13578  {
13579  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
13580  if( lp->validsollp == stat->lpcount-1 )
13581  lp->validsollp = stat->lpcount;
13582  if( lp->validfarkaslp == stat->lpcount-1 )
13583  lp->validfarkaslp = stat->lpcount;
13584  }
13585  }
13586 
13587  SCIPdebugMessage("solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
13588  stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
13589 
13590  return SCIP_OKAY;
13591 }
13592 
13593 /** solves the LP with the given algorithm */
13594 static
13596  SCIP_LP* lp, /**< current LP data */
13597  SCIP_SET* set, /**< global SCIP settings */
13598  SCIP_STAT* stat, /**< problem statistics */
13599  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
13600  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
13601  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13602  SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
13603  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13604  )
13605 {
13606  SCIP_Real lptimelimit;
13607  SCIP_Bool success;
13608 
13609  assert(lp != NULL);
13610  assert(lp->flushed);
13611  assert(lperror != NULL);
13612 
13613  /* check if a time limit is set, and set time limit for LP solver accordingly */
13614  lptimelimit = SCIPsetInfinity(set);
13615  if( set->istimelimitfinite )
13616  lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
13617 
13618  success = FALSE;
13619  if( lptimelimit > 0.0 )
13620  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
13621 
13622  if( lptimelimit <= 0.0 || !success )
13623  {
13624  SCIPdebugMessage("time limit of %f seconds could not be set\n", lptimelimit);
13625  *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
13626  *timelimit = TRUE;
13627  return SCIP_OKAY;
13628  }
13629  SCIPdebugMessage("calling LP algorithm <%s> with a time limit of %f seconds\n", lpalgoName(lpalgo), lptimelimit);
13630 
13631  /* call appropriate LP algorithm */
13632  switch( lpalgo )
13633  {
13635  SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, lperror) );
13636  break;
13637 
13639  /* run dual lexicographic simplex if required */
13640  if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
13641  {
13642  SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
13643  }
13644  else
13645  {
13646  SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
13647  }
13648  break;
13649 
13650  case SCIP_LPALGO_BARRIER:
13651  SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
13652  break;
13653 
13655  SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
13656  break;
13657 
13658  default:
13659  SCIPerrorMessage("invalid LP algorithm\n");
13660  return SCIP_INVALIDDATA;
13661  }
13662 
13663  if( !(*lperror) )
13664  {
13665  /* check for primal and dual feasibility */
13667 
13668  SCIPdebugMessage("LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
13669  }
13670 
13671  return SCIP_OKAY;
13672 }
13673 
13674 #define FEASTOLTIGHTFAC 0.001
13675 /** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
13676 static
13678  SCIP_LP* lp, /**< current LP data */
13679  SCIP_SET* set, /**< global SCIP settings */
13680  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
13681  SCIP_STAT* stat, /**< problem statistics */
13682  SCIP_PROB* prob, /**< problem data */
13683  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
13684  int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
13685  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
13686  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
13687  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
13688  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
13689  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
13690  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
13691  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13692  SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
13693  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13694  )
13695 {
13696  SCIP_Bool success;
13697  SCIP_Bool success2;
13698  SCIP_Bool success3;
13699  SCIP_Bool simplex;
13700  SCIP_Bool itlimishard;
13701 
13702  assert(lp != NULL);
13703  assert(lp->flushed);
13704  assert(set != NULL);
13705  assert(stat != NULL);
13706  assert(lperror != NULL);
13707  assert(timelimit != NULL);
13708 
13709  *lperror = FALSE;
13710 
13711  /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
13712  * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
13713  * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
13714  * SCIP_LP such that we can return a primal ray
13715  */
13716  if( lp->looseobjvalinf > 0 )
13717  {
13718  SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
13719  return SCIP_ERROR;
13720  }
13721 
13722  /* check, whether we solve with a simplex algorithm */
13723  simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
13724 
13725  /* check whether the iteration limit is a hard one */
13726  itlimishard = (itlim == harditlim);
13727 
13728  /* solve with given settings (usually fast but imprecise) */
13729  if( SCIPsetIsInfinity(set, lp->cutoffbound) )
13730  {
13731  SCIP_CALL( lpSetUobjlim(lp, set, lp->cutoffbound) );
13732  }
13733  else
13734  {
13735  SCIP_CALL( lpSetUobjlim(lp, set, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) );
13736  }
13737  SCIP_CALL( lpSetIterationLimit(lp, itlim) );
13738  SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * SCIPsetLpfeastol(set) : SCIPsetLpfeastol(set), &success) );
13739  SCIP_CALL( lpSetDualfeastol(lp, tightdualfeastol ? FEASTOLTIGHTFAC * SCIPsetDualfeastol(set) : SCIPsetDualfeastol(set),
13740  &success) );
13741  SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
13742  : SCIPsetBarrierconvtol(set), &success) );
13743  SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
13744  SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
13745  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
13746  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
13747  SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
13748  SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
13749  SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
13750  SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
13751  SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
13752  SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
13753  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13754  resolve = FALSE; /* only the first solve should be counted as resolving call */
13755 
13756  /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
13757  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13758  return SCIP_OKAY;
13759  else if( !set->lp_checkstability )
13760  {
13761  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13762  if( success )
13763  {
13764  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13765  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13766  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13767  return SCIP_OKAY;
13768  }
13769  }
13770 
13771  /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
13772  * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
13773  */
13774 
13775  /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
13776  * do this only if the iteration limit was not exceeded in the last LP solving call
13777  */
13778  if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
13779  {
13780  SCIP_CALL( lpSetFastmip(lp, 0, &success) );
13781  if( success )
13782  {
13783  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13784  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again with %s without FASTMIP\n",
13785  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13786  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13787 
13788  /* check for stability */
13789  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13790  return SCIP_OKAY;
13791  else if( !set->lp_checkstability )
13792  {
13793  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13794  if( success )
13795  {
13796  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13797  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13798  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13799  return SCIP_OKAY;
13800  }
13801  }
13802  }
13803  }
13804 
13805  /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
13806  * and go directly to solving the LP from scratch
13807  */
13808  if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
13809  {
13810  /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
13811  SCIP_CALL( lpSetScaling(lp, !set->lp_scaling, &success) );
13812  if( success )
13813  {
13814  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13815  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again with %s %s scaling\n",
13816  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_scaling ? "with" : "without");
13817  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13818 
13819  /* check for stability */
13820  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13821  return SCIP_OKAY;
13822  else if( !set->lp_checkstability )
13823  {
13824  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13825  if( success )
13826  {
13827  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13828  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13829  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13830  return SCIP_OKAY;
13831  }
13832  }
13833 
13834  /* reset scaling */
13835  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
13836  assert(success);
13837  }
13838  }
13839 
13840  /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
13841  * and go directly to solving the LP from scratch
13842  */
13843  if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
13844  {
13845  /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
13846  SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
13847  if( success )
13848  {
13849  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13850  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again with %s %s presolving\n",
13851  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
13852  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13853 
13854  /* check for stability */
13855  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13856  return SCIP_OKAY;
13857  else if( !set->lp_checkstability )
13858  {
13859  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13860  if( success )
13861  {
13862  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13863  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13864  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13865  return SCIP_OKAY;
13866  }
13867  }
13868 
13869  /* reset presolving */
13870  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
13871  assert(success);
13872  }
13873  }
13874 
13875  /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
13876  * do this only if the iteration limit was not exceeded in the last LP solving call
13877  */
13878  if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
13879  ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
13880  {
13881  success = FALSE;
13882  if( !tightprimfeastol )
13883  {
13884  SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * SCIPsetLpfeastol(set), &success) );
13885  }
13886 
13887  success2 = FALSE;
13888  if( !tightdualfeastol )
13889  {
13891  }
13892 
13893  success3 = FALSE;
13894  if( !simplex && !tightprimfeastol && !tightdualfeastol )
13895  {
13897  }
13898 
13899  if( success || success2 || success3 )
13900  {
13901  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13902  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again with %s with tighter primal and dual feasibility tolerance\n",
13903  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13904  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13905 
13906  /* check for stability */
13907  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13908  return SCIP_OKAY;
13909  else if( !set->lp_checkstability )
13910  {
13911  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13912  if( success )
13913  {
13914  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13915  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13916  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13917  return SCIP_OKAY;
13918  }
13919  }
13920 
13921  /* reset feasibility tolerance */
13922  if( !tightprimfeastol )
13923  {
13924  SCIP_CALL( lpSetFeastol(lp, SCIPsetLpfeastol(set), &success) );
13925  }
13926  if( !tightdualfeastol )
13927  {
13928  SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
13929  }
13930  if( !simplex && !tightprimfeastol && !tightdualfeastol )
13931  {
13932  SCIP_CALL( lpSetBarrierconvtol(lp, SCIPsetBarrierconvtol(set), &success) );
13933  }
13934  }
13935  }
13936 
13937  /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
13938  * the given iteration limit might be a soft one to restrict resolving calls only */
13939  SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
13940 
13941  /* if not already done, solve again from scratch */
13942  if( !fromscratch && simplex )
13943  {
13944  SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
13945  if( success )
13946  {
13947  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13948  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again from scratch with %s\n",
13949  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13950  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13951 
13952  /* check for stability */
13953  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13954  return SCIP_OKAY;
13955  else if( !set->lp_checkstability )
13956  {
13957  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13958  if( success )
13959  {
13960  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13961  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13962  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13963  return SCIP_OKAY;
13964  }
13965  }
13966  }
13967  }
13968 
13969  /* solve again, use other simplex this time */
13970  if( simplex )
13971  {
13973  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13974  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again from scratch with %s\n",
13975  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13976  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13977 
13978  /* check for stability */
13979  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13980  return SCIP_OKAY;
13981  else if( !set->lp_checkstability )
13982  {
13983  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13984  if( success )
13985  {
13986  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13987  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
13988  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13989  return SCIP_OKAY;
13990  }
13991  }
13992 
13993  /* solve again with opposite scaling and other simplex */
13994  SCIP_CALL( lpSetScaling(lp, !set->lp_scaling, &success) );
13995  if( success )
13996  {
13997  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13998  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again from scratch with %s %s scaling\n",
13999  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_scaling ? "with" : "without");
14000  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
14001 
14002  /* check for stability */
14003  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
14004  return SCIP_OKAY;
14005  else if( !set->lp_checkstability )
14006  {
14007  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
14008  if( success )
14009  {
14010  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14011  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
14012  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
14013  return SCIP_OKAY;
14014  }
14015  }
14016 
14017  /* reset scaling */
14018  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
14019  assert(success);
14020  }
14021 
14022  /* solve again with opposite presolving and other simplex */
14023  SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
14024  if( success )
14025  {
14026  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14027  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again from scratch with %s %s presolving\n",
14028  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
14029  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
14030 
14031  /* check for stability */
14032  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
14033  return SCIP_OKAY;
14034  else if( !set->lp_checkstability )
14035  {
14036  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
14037  if( success )
14038  {
14039  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14040  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
14041  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
14042  return SCIP_OKAY;
14043  }
14044  }
14045 
14046  /* reset presolving */
14047  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
14048  assert(success);
14049  }
14050 
14051  /* solve again with tighter feasibility tolerance, use other simplex this time */
14052  if( !tightprimfeastol || !tightdualfeastol )
14053  {
14054  success = FALSE;
14055  if( !tightprimfeastol )
14056  {
14057  SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * SCIPsetLpfeastol(set), &success) );
14058  }
14059 
14060  success2 = FALSE;
14061  if( !tightdualfeastol )
14062  {
14064  }
14065 
14066  if( success || success2 )
14067  {
14068  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14069  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- solve again from scratch with %s with tighter feasibility tolerance\n",
14070  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
14071  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
14072 
14073  /* check for stability */
14074  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
14075  return SCIP_OKAY;
14076  else if( !set->lp_checkstability )
14077  {
14078  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
14079  if( success )
14080  {
14081  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14082  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ignoring instability of %s\n",
14083  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
14084  return SCIP_OKAY;
14085  }
14086  }
14087 
14088  /* reset feasibility tolerance */
14089  if( !tightprimfeastol )
14090  {
14091  SCIP_CALL( lpSetFeastol(lp, SCIPsetLpfeastol(set), &success) );
14092  }
14093  if( !tightdualfeastol )
14094  {
14095  SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
14096  }
14097  }
14098  }
14099  }
14100 
14101  /* nothing worked -- exit with an LPERROR */
14102  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH, "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT "\n",
14103  stat->nnodes, stat->nlps);
14104  *lperror = TRUE;
14105 
14106  return SCIP_OKAY;
14107 }
14108 
14109 /** adjust the LP objective value if its greater/less than +/- SCIPsetInfinity() */
14110 static
14112  SCIP_LP* lp, /**< current LP data */
14113  SCIP_SET* set, /**< global SCIP settings */
14114  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
14115  )
14116 {
14117  assert(lp != NULL);
14118  assert(set != NULL);
14119 
14120  if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
14121  {
14122  if( !lp->adjustlpval )
14123  {
14124  SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
14125  lp->adjustlpval = TRUE;
14126  }
14127  lp->lpobjval = SCIPsetInfinity(set);
14128  }
14129  else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
14130  {
14131  if( !lp->adjustlpval )
14132  {
14133  SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
14134  lp->adjustlpval = TRUE;
14135  }
14136  lp->lpobjval = -SCIPsetInfinity(set);
14137  }
14138 }
14139 
14140 /** solves the LP with the given algorithm and evaluates return status */
14141 static
14143  SCIP_LP* lp, /**< current LP data */
14144  SCIP_SET* set, /**< global SCIP settings */
14145  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
14146  SCIP_STAT* stat, /**< problem statistics */
14147  SCIP_PROB* prob, /**< problem data */
14148  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
14149  int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
14150  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
14151  SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
14152  SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
14153  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
14154  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
14155  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
14156  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
14157  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
14158  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
14159  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
14160  )
14161 {
14162  SCIP_Bool solvedprimal;
14163  SCIP_Bool solveddual;
14164  SCIP_Bool timelimit;
14165  int itlim;
14166 
14167  assert(lp != NULL);
14168  assert(lp->flushed);
14169  assert(set != NULL);
14170  assert(stat != NULL);
14171  assert(lperror != NULL);
14172 
14173  checkLinks(lp);
14174 
14175  solvedprimal = FALSE;
14176  solveddual = FALSE;
14177  timelimit = FALSE;
14178 
14179  /* select the basic iteration limit depending on whether this is a resolving call or not */
14180  itlim = ( resolve ? resolveitlim : harditlim );
14181 
14182  SOLVEAGAIN:
14183  /* call simplex */
14184  SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
14185  keepsol, &timelimit, lperror) );
14186  resolve = FALSE; /* only the first solve should be counted as resolving call */
14187  solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
14188  solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
14189 
14190  /* check, if an error occurred */
14191  if( *lperror )
14192  {
14193  SCIPdebugMessage("unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
14194  lp->solved = FALSE;
14196  return SCIP_OKAY;
14197  }
14198 
14199  /* check, if a time limit was exceeded */
14200  if( timelimit )
14201  {
14202  SCIPdebugMessage("time limit exceeded before solving LP\n");
14203  lp->solved = TRUE;
14205  lp->lpobjval = -SCIPsetInfinity(set);
14206  return SCIP_OKAY;
14207  }
14208 
14209  /* only one should return true */
14210  assert(!(SCIPlpiIsOptimal(lp->lpi) && SCIPlpiIsObjlimExc(lp->lpi) && SCIPlpiIsPrimalInfeasible(lp->lpi) &&
14212 
14213  /* evaluate solution status */
14214  if( SCIPlpiIsOptimal(lp->lpi) )
14215  {
14216  assert(lp->primalfeasible);
14217  assert(lp->dualfeasible);
14219  SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
14220  adjustLPobjval(lp, set, messagehdlr);
14221 
14222  if( !SCIPsetIsInfinity(set, lp->lpiuobjlim) && SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) )
14223  {
14224  /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
14225  SCIPdebugMessage("optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiuobjlim);
14227  lp->lpobjval = SCIPsetInfinity(set);
14228  }
14229  /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
14230  * reached if the LP objective value is greater than the cutoff bound
14231  */
14233  || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
14234  }
14235  else if( SCIPlpiIsObjlimExc(lp->lpi) )
14236  {
14237  assert(!lpCutoffDisabled(set));
14239  lp->lpobjval = SCIPsetInfinity(set);
14240  }
14241  else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
14242  {
14243  /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
14244  if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
14245  {
14246  assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
14247  lpalgo = SCIP_LPALGO_DUALSIMPLEX;
14248  goto SOLVEAGAIN;
14249  }
14251  lp->lpobjval = SCIPsetInfinity(set);
14252  }
14253  else if( SCIPlpiExistsPrimalRay(lp->lpi) )
14254  {
14255  /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
14256  if( needprimalray && !SCIPlpiHasPrimalRay(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
14257  {
14258  assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
14259  lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
14260  goto SOLVEAGAIN;
14261  }
14263  lp->lpobjval = -SCIPsetInfinity(set);
14264  }
14265  else if( SCIPlpiIsIterlimExc(lp->lpi) )
14266  {
14267  SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
14268  adjustLPobjval(lp, set, messagehdlr);
14270  }
14271  else if( SCIPlpiIsTimelimExc(lp->lpi) )
14272  {
14273  lp->lpobjval = -SCIPsetInfinity(set);
14275  }
14276  else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
14277  {
14278  assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
14279  lpalgo = SCIP_LPALGO_DUALSIMPLEX;
14280  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14281  "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
14282  stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
14283  goto SOLVEAGAIN;
14284  }
14285  else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
14286  {
14287  assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
14288  lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
14289  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14290  "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
14291  stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
14292  goto SOLVEAGAIN;
14293  }
14294  else
14295  {
14296  SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
14297  stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
14299  return SCIP_LPERROR;
14300  }
14301 
14302  lp->solved = TRUE;
14303 
14304  SCIPdebugMessage("solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
14307 
14308  return SCIP_OKAY;
14309 }
14310 
14311 /** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
14312 static
14314  SCIP_LP* lp, /**< current LP data */
14315  BMS_BLKMEM* blkmem, /**< block memory */
14316  SCIP_SET* set, /**< global SCIP settings */
14317  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
14318  SCIP_STAT* stat, /**< problem statistics */
14319  SCIP_PROB* prob, /**< problem data */
14320  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14321  int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
14322  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
14323  SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
14324  SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
14325  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
14326  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
14327  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
14328  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
14329  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
14330  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
14331  )
14332 {
14333  SCIP_Bool resolve;
14334  char algo;
14335 
14336  assert(lp != NULL);
14337  assert(set != NULL);
14338  assert(lperror != NULL);
14339 
14340  /* flush changes to the LP solver */
14341  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
14342  fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
14343 
14344  /* select LP algorithm to apply */
14345  resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
14346  algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
14347 
14348  switch( algo )
14349  {
14350  case 's':
14351  /* select simplex method */
14352  if( lp->dualfeasible || !lp->primalfeasible )
14353  {
14354  SCIPdebugMessage("solving dual LP\n");
14355  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
14356  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14357  }
14358  else
14359  {
14360  SCIPdebugMessage("solving primal LP\n");
14361  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
14362  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14363  }
14364  break;
14365 
14366  case 'p':
14367  SCIPdebugMessage("solving primal LP\n");
14368  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
14369  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14370  break;
14371 
14372  case 'd':
14373  SCIPdebugMessage("solving dual LP\n");
14374  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
14375  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14376  break;
14377 
14378  case 'b':
14379  SCIPdebugMessage("solving barrier LP\n");
14380  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
14381  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14382  break;
14383 
14384  case 'c':
14385  SCIPdebugMessage("solving barrier LP with crossover\n");
14386  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
14387  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14388  break;
14389 
14390  default:
14391  SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
14392  return SCIP_PARAMETERWRONGVAL;
14393  }
14394  assert(!(*lperror) || !lp->solved);
14395 
14396  return SCIP_OKAY;
14397 }
14398 
14399 #ifndef NDEBUG
14400 /** checks if the lazy bounds are valid */
14401 static
14403  SCIP_LP* lp, /**< LP data */
14404  SCIP_SET* set /**< global SCIP settings */
14405  )
14406 {
14407  SCIP_COL* col;
14408  int c;
14409 
14410  assert(lp->flushed);
14411 
14412  for( c = 0; c < lp->nlazycols; ++c )
14413  {
14414  col = lp->lazycols[c];
14415 
14416  /* in case lazy bounds are given, check that the primal solution satisfies them */
14417  assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
14418  assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
14419  }
14420 }
14421 #else
14422 #define checkLazyBounds(lp, set) /**/
14423 #endif
14424 
14425 /** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
14426  * diving
14427  */
14428 static
14430  SCIP_LP* lp, /**< LP data */
14431  SCIP_SET* set /**< global SCIP settings */
14432  )
14433 {
14434  SCIP_COL* col;
14435  int c;
14436 
14437  assert(lp->nlazycols > 0);
14438 
14439  /* return, if we are in diving, and bounds were already applied
14440  * or if we are not in diving and bounds were not applied
14441  */
14442  if( lp->diving == lp->divinglazyapplied )
14443  return SCIP_OKAY;
14444 
14445  SCIPdebugMessage("mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
14446  lp->diving, lp->divinglazyapplied);
14447 
14448  for( c = 0; c < lp->nlazycols; ++c )
14449  {
14450  col = lp->lazycols[c];
14451 
14452  /* if the column has a lazy lower bound, mark its lower bounds as changed */
14453  if( !SCIPsetIsInfinity(set, -col->lazylb) )
14454  {
14455  assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb)); /*lint !e777*/
14456  assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
14457  || (col->flushedlb == -SCIPlpiInfinity(lp->lpi))); /*lint !e777*/
14458 
14459  /* insert column in the chgcols list (if not already there) */
14460  SCIP_CALL( insertColChgcols(col, set, lp) );
14461 
14462  /* mark bound change in the column */
14463  col->lbchanged = TRUE;
14464  }
14465 
14466  /* if the column has a lazy upper bound, mark its upper bounds as changed */
14467  if( !SCIPsetIsInfinity(set, col->lazyub) )
14468  {
14469  assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub)); /*lint !e777*/
14470  assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
14471  || (col->flushedub == SCIPlpiInfinity(lp->lpi))); /*lint !e777*/
14472 
14473  /* insert column in the chgcols list (if not already there) */
14474  SCIP_CALL( insertColChgcols(col, set, lp) );
14475 
14476  /* mark bound change in the column */
14477  col->ubchanged = TRUE;
14478  }
14479  }
14480 
14481  /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
14482  * if not, we just removed them
14483  */
14484  lp->divinglazyapplied = lp->diving;
14485 
14486  return SCIP_OKAY;
14487 }
14488 
14489 /** returns the iteration limit for an LP resolving call */
14490 static
14492  SCIP_SET* set, /**< global SCIP settings */
14493  SCIP_STAT* stat, /**< dynamic problem statistics */
14494  int itlim /**< hard iteration limit */
14495  )
14496 {
14497  /* no limit set or average not yet reliable */
14498  if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
14499  return itlim;
14500  /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
14501  if( itlim == -1 )
14502  itlim = INT_MAX;
14503  /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
14504  return (int) MIN(itlim, MAX(set->lp_resolveitermin,
14505  (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
14506 }
14507 
14508 
14509 
14510 /** solves the LP with simplex algorithm, and copy the solution into the column's data */
14512  SCIP_LP* lp, /**< LP data */
14513  SCIP_SET* set, /**< global SCIP settings */
14514  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
14515  BMS_BLKMEM* blkmem, /**< block memory buffers */
14516  SCIP_STAT* stat, /**< problem statistics */
14517  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14518  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14519  SCIP_PROB* prob, /**< problem data */
14520  SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
14521  SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
14522  * (limit is computed within the method w.r.t. the average LP iterations) */
14523  SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
14524  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
14525  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
14526  )
14527 {
14528  SCIP_RETCODE retcode;
14529  SCIP_Bool needprimalray;
14530  SCIP_Bool needdualray;
14531  int harditlim;
14532  int resolveitlim;
14533 
14534  assert(lp != NULL);
14535  assert(prob != NULL);
14536  assert(prob->nvars >= lp->ncols);
14537  assert(lperror != NULL);
14538 
14539  SCIPdebugMessage("solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
14540  lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
14541 
14542  retcode = SCIP_OKAY;
14543  *lperror = FALSE;
14544 
14545  /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
14546  needprimalray = TRUE;
14547  needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
14548  || (set->conf_enable && set->conf_useinflp));
14549 
14550  /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
14551  harditlim = (int) MIN(itlim, INT_MAX);
14552  resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
14553  assert(harditlim == -1 || (resolveitlim <= harditlim));
14554 
14555  /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
14556  * or removed from the LP (diving was ended)
14557  */
14558  if( lp->nlazycols > 0 )
14559  {
14560  /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
14561  * first resolve LP?
14562  */
14563  SCIP_CALL( updateLazyBounds(lp, set) );
14564  assert(lp->diving == lp->divinglazyapplied);
14565  }
14566 
14567  /* flush changes to the LP solver */
14568  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
14569  assert(lp->flushed);
14570 
14571  /* 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
14572  * to run again anyway, since there seems to be some time left / the time limit was increased
14573  */
14574  if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
14575  {
14576  SCIP_Bool* primalfeaspointer;
14577  SCIP_Bool* dualfeaspointer;
14578  SCIP_Bool primalfeasible;
14579  SCIP_Bool dualfeasible;
14580  SCIP_Bool rayfeasible;
14581  SCIP_Bool tightprimfeastol;
14582  SCIP_Bool tightdualfeastol;
14583  SCIP_Bool fromscratch;
14584  SCIP_Bool wasfromscratch;
14585  SCIP_Longint oldnlps;
14586  int fastmip;
14587 
14588  /* set initial LP solver settings */
14589  fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
14590  tightprimfeastol = FALSE;
14591  tightdualfeastol = FALSE;
14592  fromscratch = FALSE;
14593  primalfeasible = FALSE;
14594  dualfeasible = FALSE;
14595  wasfromscratch = (stat->nlps == 0);
14596 
14597  SOLVEAGAIN:
14598  /* solve the LP */
14599  oldnlps = stat->nlps;
14600  SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
14601  needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14602  SCIPdebugMessage("lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
14603  assert(!(*lperror) || !lp->solved);
14604 
14605  /* check for error */
14606  if( *lperror )
14607  {
14608  retcode = SCIP_OKAY;
14609  goto TERMINATE;
14610  }
14611 
14612  /* evaluate solution status */
14613  switch( SCIPlpGetSolstat(lp) )
14614  {
14616  /* get LP solution and possibly check the solution's feasibility again */
14617  if( set->lp_checkprimfeas )
14618  primalfeaspointer = &primalfeasible;
14619  else
14620  {
14621  /* believe in the primal feasibility of the LP solution */
14622  primalfeasible = TRUE;
14623  primalfeaspointer = NULL;
14624  }
14625  if( set->lp_checkdualfeas )
14626  dualfeaspointer = &dualfeasible;
14627  else
14628  {
14629  /* believe in the dual feasibility of the LP solution */
14630  dualfeasible = TRUE;
14631  dualfeaspointer = NULL;
14632  }
14633 
14634  SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
14635 
14636  /* in debug mode, check that lazy bounds (if present) are not violated */
14637  checkLazyBounds(lp, set);
14638 
14639  if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
14640  {
14641  /* update ages and remove obsolete columns and rows from LP */
14642  SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
14643  if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
14644  {
14645  SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
14646  }
14647 
14648  if( !lp->solved )
14649  {
14650  /* resolve LP after removing obsolete columns and rows */
14651  SCIPdebugMessage("removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
14652  aging = FALSE; /* to prevent infinite loops */
14653  goto SOLVEAGAIN;
14654  }
14655  }
14656  if( !primalfeasible || !dualfeasible )
14657  {
14659 
14660  if( (fastmip > 0) && simplex )
14661  {
14662  /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
14663  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14664  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, dfeas=%d) -- solving again without FASTMIP\n",
14665  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14666  fastmip = 0;
14667  goto SOLVEAGAIN;
14668  }
14669  else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
14670  {
14671  /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
14672  * tolerance
14673  */
14674  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14675  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, dfeas=%d) -- solving again with tighter feasibility tolerance\n",
14676  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14677  tightprimfeastol = tightprimfeastol || !primalfeasible;
14678  tightdualfeastol = tightdualfeastol || !dualfeasible;
14679  goto SOLVEAGAIN;
14680  }
14681  else if( !fromscratch && !wasfromscratch && simplex )
14682  {
14683  /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
14684  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14685  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, dfeas=%d) -- solving again from scratch\n",
14686  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14687  fromscratch = TRUE;
14688  goto SOLVEAGAIN;
14689  }
14690  else
14691  {
14692  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14693  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
14694  lp->solved = FALSE;
14696  *lperror = TRUE;
14697  }
14698  }
14699  SCIPdebugMessage(" -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
14700  lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
14701  lp->lpsolstat, lp->cutoffbound);
14702  break;
14703 
14705  SCIPdebugMessage(" -> LP infeasible\n");
14706  if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
14707  {
14708  if( SCIPlpiHasDualRay(lp->lpi) )
14709  {
14710  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
14711  }
14712  /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
14713  * with the primal simplex due to numerical problems) - treat this case like an LP error
14714  */
14715  else
14716  {
14717  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14718  "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
14719  lp->solved = FALSE;
14721  *lperror = TRUE;
14722  }
14723  }
14724  break;
14725 
14727  if( set->lp_checkprimfeas )
14728  {
14729  /* get unbounded LP solution and check the solution's feasibility again */
14730  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
14731  }
14732  else
14733  {
14734  /* get unbounded LP solution believing in the feasibility of the LP solution */
14735  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
14736 
14737  primalfeasible = TRUE;
14738  rayfeasible = TRUE;
14739  }
14740 
14741  /* in debug mode, check that lazy bounds (if present) are not violated */
14742  checkLazyBounds(lp, set);
14743 
14744  SCIPdebugMessage(" -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
14745  primalfeasible, rayfeasible);
14746 
14747  if( !primalfeasible || !rayfeasible )
14748  {
14750 
14751  if( (fastmip > 0) && simplex )
14752  {
14753  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
14754  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14755  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, rfeas=%d) -- solving again without FASTMIP\n",
14756  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14757  fastmip = 0;
14758  goto SOLVEAGAIN;
14759  }
14760  else if( !tightprimfeastol )
14761  {
14762  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
14763  * tolerance
14764  */
14765  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14766  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, rfeas=%d) -- solving again with tighter primal feasibility tolerance\n",
14767  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14768  tightprimfeastol = TRUE;
14769  goto SOLVEAGAIN;
14770  }
14771  else if( !fromscratch && simplex )
14772  {
14773  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
14774  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14775  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%d, rfeas=%d) -- solving again from scratch\n",
14776  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14777  fromscratch = TRUE;
14778  goto SOLVEAGAIN;
14779  }
14780  else
14781  {
14782  /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
14783  * forget about the LP at this node and mark it to be unsolved
14784  */
14785  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14786  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in unbounded LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
14787  lp->solved = FALSE;
14789  *lperror = TRUE;
14790  }
14791  }
14792 
14793  break;
14794 
14796  assert(!lpCutoffDisabled(set));
14797  /* if we do branch-and-price, make sure that a dual feasible solution exists, that exceeds the objective limit;
14798  * With FASTMIP setting, CPLEX does not apply the final pivot to reach the dual solution exceeding the objective
14799  * limit. Therefore, we have to either turn off FASTMIP and resolve the problem or continue solving it without
14800  * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
14801  * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
14802  * FASTMIP and solve again.
14803  */
14804  if( !SCIPprobAllColsInLP(prob, set, lp) && fastmip )
14805  {
14806  SCIP_LPI* lpi;
14807  SCIP_Real objval;
14808 
14809  lpi = SCIPlpGetLPI(lp);
14810 
14811  assert(lpi != NULL);
14812  /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
14813  * the assert by using !SCIPsetIsFeasNegative()
14814  */
14815  assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiuobjlim));
14816 
14817  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14818 
14819  /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
14820  if( SCIPsetIsLT(set, objval, lp->lpiuobjlim) )
14821  {
14822  SCIP_Real tmpcutoff;
14823  char tmppricingchar;
14824  SCIP_LPSOLSTAT solstat;
14825 
14826  SCIPdebugMessage("objval = %f < %f = lp->lpiuobjlim, but status objlimit\n", objval, lp->lpiuobjlim);
14827 
14828  /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
14829  fromscratch = FALSE;
14830 
14831  /* temporarily disable cutoffbound, which also disables the objective limit */
14832  tmpcutoff = lp->cutoffbound;
14833  lp->cutoffbound = SCIPlpiInfinity(lpi);
14834 
14835  /* set lp pricing strategy to steepest edge */
14836  SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
14837  SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
14838 
14839  /* resolve LP with an iteration limit of 1 */
14840  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
14841  FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14842 
14843  /* reinstall old cutoff bound and lp pricing strategy */
14844  lp->cutoffbound = tmpcutoff;
14845  SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
14846 
14847  /* get objective value */
14848  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14849 
14850  /* get solution status for the lp */
14851  solstat = SCIPlpGetSolstat(lp);
14852  assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
14853 
14854  if( !(*lperror) && solstat != SCIP_LPSOLSTAT_ERROR && solstat != SCIP_LPSOLSTAT_NOTSOLVED )
14855  {
14856  SCIPdebugMessage(" ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
14857  }
14858 
14859  /* disable fastmip for subsequent LP calls (if objective limit is not yet exceeded or LP solution is infeasible) */
14860  fastmip = 0;
14861 
14862  /* the solution is still not exceeding the objective limit and the solving process
14863  * was stopped due to time or iteration limit, solve again with fastmip turned off
14864  */
14865  if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
14866  SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
14867  {
14868  assert(!(*lperror));
14869 
14870  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
14871  FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14872 
14873  /* get objective value */
14874  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14875 
14876  /* get solution status for the lp */
14877  solstat = SCIPlpGetSolstat(lp);
14878 
14879  SCIPdebugMessage(" ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
14880  }
14881 
14882  /* check for lp errors */
14883  if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
14884  {
14885  SCIPdebugMessage("unresolved error while resolving LP in order to exceed the objlimit\n");
14886  lp->solved = FALSE;
14888 
14889  retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
14890  goto TERMINATE;
14891  }
14892 
14893  lp->solved = TRUE;
14894 
14895  /* optimal solution / objlimit with fastmip turned off / itlimit or timelimit, but objlimit exceeded */
14896  if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
14897  || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
14898  && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
14899  {
14900  /* get LP solution and possibly check the solution's feasibility again */
14901  if( set->lp_checkprimfeas )
14902  primalfeaspointer = &primalfeasible;
14903  else
14904  {
14905  /* believe in the primal feasibility of the LP solution */
14906  primalfeasible = TRUE;
14907  primalfeaspointer = NULL;
14908  }
14909  if( set->lp_checkdualfeas )
14910  dualfeaspointer = &dualfeasible;
14911  else
14912  {
14913  /* believe in the dual feasibility of the LP solution */
14914  dualfeasible = TRUE;
14915  dualfeaspointer = NULL;
14916  }
14917 
14918  SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
14919 
14920  /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
14921  if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
14922  {
14923  checkLazyBounds(lp, set);
14924  }
14925 
14926  /* if objective value is larger than the cutoff bound, set solution status to objective
14927  * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
14928  * this was already done in the lpSolve() method
14929  */
14930  if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
14931  {
14933  lp->lpobjval = SCIPsetInfinity(set);
14934  }
14935 
14936  /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
14937  * the cutoffbound; mark the LP to be unsolved
14938  */
14939  if( !primalfeasible || !dualfeasible
14940  || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
14941  !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
14942  {
14943  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
14944  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
14945  lp->solved = FALSE;
14947  *lperror = TRUE;
14948  }
14949 
14950  SCIPdebugMessage(" -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
14951  lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
14952  lp->lpsolstat, lp->cutoffbound);
14953  }
14954  /* infeasible solution */
14955  else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
14956  {
14957  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
14958  SCIPdebugMessage(" -> LP infeasible\n");
14959  }
14960  /* unbounded solution */
14961  else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
14962  {
14963  if( set->lp_checkprimfeas )
14964  {
14965  /* get unbounded LP solution and check the solution's feasibility again */
14966  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
14967  }
14968  else
14969  {
14970  /* get unbounded LP solution believing in its feasibility */
14971  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
14972 
14973  primalfeasible = TRUE;
14974  rayfeasible = TRUE;
14975  }
14976 
14977  SCIPdebugMessage(" -> LP has unbounded primal ray\n");
14978 
14979  /* in debug mode, check that lazy bounds (if present) are not violated */
14980  checkLazyBounds(lp, set);
14981 
14982  if( !primalfeasible || !rayfeasible )
14983  {
14984  /* unbounded solution is infeasible (this can happen due to numerical problems):
14985  * forget about the LP at this node and mark it to be unsolved
14986 
14987  * @todo: like in the default LP solving evaluation, solve without fastmip,
14988  * with tighter feasibility tolerance and from scratch
14989  */
14990  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14991  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles in unbounded LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
14992  lp->solved = FALSE;
14994  *lperror = TRUE;
14995  }
14996 
14997  }
14998 
14999  assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
15000  assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
15002  }
15003  else
15004  {
15005  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
15006  }
15007  }
15008  else if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
15009  {
15010  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
15011  }
15012  SCIPdebugMessage(" -> LP objective limit reached\n");
15013  break;
15014 
15016  SCIPdebugMessage(" -> LP iteration limit exceeded\n");
15017  break;
15018 
15020  SCIPdebugMessage(" -> LP time limit exceeded\n");
15021 
15022  /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
15023  stat->nclockskipsleft = 0;
15024  if( !SCIPsolveIsStopped(set, stat, FALSE) )
15025  {
15026  SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
15027  "you might consider switching the clock type of SCIP\n");
15028  stat->status = SCIP_STATUS_TIMELIMIT;
15029  }
15030  break;
15031 
15032  case SCIP_LPSOLSTAT_ERROR:
15034  SCIPerrorMessage("error in LP solver\n");
15035  retcode = SCIP_LPERROR;
15036  goto TERMINATE;
15037 
15038  default:
15039  SCIPerrorMessage("unknown LP solution status\n");
15040  retcode = SCIP_ERROR;
15041  goto TERMINATE;
15042  }
15043  }
15044  assert(!(*lperror) || !lp->solved);
15045 
15046  TERMINATE:
15047  /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
15048  * may happen that we continue to solve from scratch during strong branching */
15049  if( lp->lpifromscratch )
15050  {
15051  SCIP_Bool success;
15052  (void) lpSetFromscratch(lp, FALSE, &success);
15053  SCIPdebugMessage("resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
15054  }
15055 
15056  return retcode;
15057 }
15058 
15059 /** gets solution status of current LP */
15061  SCIP_LP* lp /**< current LP data */
15062  )
15063 {
15064  assert(lp != NULL);
15065  assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
15066 
15067  return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
15068 }
15069 
15070 /** gets objective value of current LP
15071  *
15072  * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
15073  * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
15074  * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
15075  */
15077  SCIP_LP* lp, /**< current LP data */
15078  SCIP_SET* set, /**< global SCIP settings */
15079  SCIP_PROB* prob /**< problem data */
15080  )
15081 {
15082  assert(lp != NULL);
15083  assert(lp->solved);
15084  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
15085  assert(set != NULL);
15086 
15087  if( !lp->flushed )
15088  return SCIP_INVALID;
15089  else if( SCIPsetIsInfinity(set, lp->lpobjval) || SCIPsetIsInfinity(set, -lp->lpobjval))
15090  return lp->lpobjval;
15091  else if( lp->looseobjvalinf > 0 )
15092  return -SCIPsetInfinity(set);
15093  else
15094  {
15095  /* recalculate the loose objective value, if needed */
15096  if( !lp->looseobjvalid )
15097  recomputeLooseObjectiveValue(lp, set, prob);
15098 
15099  return lp->lpobjval + lp->looseobjval;
15100  }
15101 }
15102 
15103 /** gets part of objective value of current LP that results from COLUMN variables only */
15105  SCIP_LP* lp /**< current LP data */
15106  )
15107 {
15108  assert(lp != NULL);
15109  assert(lp->solved);
15110 
15111  return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
15112 }
15113 
15114 /** gets part of objective value of current LP that results from LOOSE variables only */
15116  SCIP_LP* lp, /**< current LP data */
15117  SCIP_SET* set, /**< global SCIP settings */
15118  SCIP_PROB* prob /**< problem data */
15119  )
15120 {
15121  assert(lp != NULL);
15122  assert(lp->solved);
15123  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
15124  assert(set != NULL);
15125 
15126  if( !lp->flushed )
15127  return SCIP_INVALID;
15128  else if( lp->looseobjvalinf > 0 )
15129  return -SCIPsetInfinity(set);
15130  else
15131  return getFiniteLooseObjval(lp, set, prob);
15132 }
15133 
15134 /** remembers the current LP objective value as root solution value */
15136  SCIP_LP* lp, /**< current LP data */
15137  SCIP_SET* set, /**< global SCIP settings */
15138  SCIP_PROB* prob /**< problem data */
15139  )
15140 {
15141  assert(lp != NULL);
15142 
15144  lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
15145 }
15146 
15147 /** invalidates the root LP solution value */
15149  SCIP_LP* lp /**< current LP data */
15150  )
15151 {
15152  assert(lp != NULL);
15153 
15154  lp->rootlpobjval = SCIP_INVALID;
15156 }
15157 
15158 /** recomputes local and global pseudo objective values */
15160  SCIP_LP* lp, /**< current LP data */
15161  SCIP_SET* set, /**< global SCIP settings */
15162  SCIP_PROB* prob /**< problem data */
15163  )
15164 {
15165  SCIP_VAR** vars;
15166  int nvars;
15167  int v;
15168 
15169  assert(lp != NULL);
15170  assert(set != NULL);
15171  assert(prob != NULL);
15172 
15173  vars = prob->vars;
15174  nvars = prob->nvars;
15175 
15176  lp->glbpseudoobjvalinf = 0;
15177  lp->glbpseudoobjval = 0.0;
15178 
15179  lp->pseudoobjvalinf = 0;
15180  lp->pseudoobjval = 0.0;
15181 
15182  for( v = 0; v < nvars; ++v )
15183  {
15184  SCIP_Real obj = SCIPvarGetObj(vars[v]);
15185 
15186  if( SCIPsetIsPositive(set, obj) )
15187  {
15188  /* update the global pseudo objective value */
15189  if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
15190  ++(lp->glbpseudoobjvalinf);
15191  else
15192  lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
15193 
15194  /* update the local pseudo objective value */
15195  if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
15196  ++(lp->pseudoobjvalinf);
15197  else
15198  lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
15199  }
15200 
15201  if( SCIPsetIsNegative(set, obj) )
15202  {
15203  /* update the global pseudo objective value */
15204  if( SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
15205  ++(lp->glbpseudoobjvalinf);
15206  else
15207  lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
15208 
15209  /* update the local pseudo objective value */
15210  if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
15211  ++(lp->pseudoobjvalinf);
15212  else
15213  lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
15214  }
15215  }
15216 
15217  /* the recomputed values are reliable */
15219  lp->glbpseudoobjvalid = TRUE;
15220  lp->relpseudoobjval = lp->pseudoobjval;
15221  lp->pseudoobjvalid = TRUE;
15222 }
15223 
15224 /** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
15225  * global bound
15226  */
15228  SCIP_LP* lp, /**< current LP data */
15229  SCIP_SET* set, /**< global SCIP settings */
15230  SCIP_PROB* prob /**< problem data */
15231  )
15232 {
15233  assert(lp != NULL);
15234  assert(lp->glbpseudoobjvalinf >= 0);
15235  assert(set != NULL);
15236 
15237  if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
15238  return -SCIPsetInfinity(set);
15239  else
15240  {
15241  /* recalculate the global pseudo solution value, if needed */
15242  if( !lp->glbpseudoobjvalid )
15243  recomputeGlbPseudoObjectiveValue(lp, set, prob);
15244 
15245  /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
15246  if( SCIPsetIsInfinity(set, -lp->glbpseudoobjval) )
15247  return -SCIPsetInfinity(set);
15248 
15249  return lp->glbpseudoobjval;
15250  }
15251 }
15252 
15253 /** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
15254  * objective function) local bound
15255  */
15257  SCIP_LP* lp, /**< current LP data */
15258  SCIP_SET* set, /**< global SCIP settings */
15259  SCIP_PROB* prob /**< problem data */
15260  )
15261 {
15262  assert(lp != NULL);
15263  assert(lp->pseudoobjvalinf >= 0);
15264  assert(set != NULL);
15265 
15266  if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
15267  return -SCIPsetInfinity(set);
15268  else
15269  {
15270  /* recalculate the pseudo solution value, if needed */
15271  if( !lp->pseudoobjvalid )
15272  recomputePseudoObjectiveValue(lp, set, prob);
15273 
15274  /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
15275  if( SCIPsetIsInfinity(set, -lp->pseudoobjval) )
15276  return -SCIPsetInfinity(set);
15277 
15278  return lp->pseudoobjval;
15279  }
15280 }
15281 
15282 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
15284  SCIP_LP* lp, /**< current LP data */
15285  SCIP_SET* set, /**< global SCIP settings */
15286  SCIP_PROB* prob, /**< problem data */
15287  SCIP_VAR* var, /**< problem variable */
15288  SCIP_Real oldbound, /**< old value for bound */
15289  SCIP_Real newbound, /**< new value for bound */
15290  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
15291  )
15292 {
15293  SCIP_Real pseudoobjval;
15294  int pseudoobjvalinf;
15295  SCIP_Real obj;
15296 
15297  pseudoobjval = getFinitePseudoObjval(lp, set, prob);
15298  pseudoobjvalinf = lp->pseudoobjvalinf;
15299  obj = SCIPvarGetObj(var);
15300  if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
15301  {
15302  if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
15303  pseudoobjvalinf--;
15304  else
15305  pseudoobjval -= oldbound * obj;
15306  assert(pseudoobjvalinf >= 0);
15307  if( SCIPsetIsInfinity(set, REALABS(newbound)) )
15308  pseudoobjvalinf++;
15309  else
15310  pseudoobjval += newbound * obj;
15311  }
15312  assert(pseudoobjvalinf >= 0);
15313 
15314  if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
15315  return -SCIPsetInfinity(set);
15316  else
15317  return pseudoobjval;
15318 }
15319 
15320 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
15321  * perform calculations with interval arithmetic to get an exact lower bound
15322  */
15324  SCIP_LP* lp, /**< current LP data */
15325  SCIP_SET* set, /**< global SCIP settings */
15326  SCIP_VAR* var, /**< problem variable */
15327  SCIP_Real oldbound, /**< old value for bound */
15328  SCIP_Real newbound, /**< new value for bound */
15329  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
15330  )
15331 {
15332  SCIP_Real pseudoobjval;
15333  int pseudoobjvalinf;
15334  SCIP_Real obj;
15335 
15336  assert(lp->pseudoobjvalid);
15337 
15338  pseudoobjval = lp->pseudoobjval;
15339  pseudoobjvalinf = lp->pseudoobjvalinf;
15340  obj = SCIPvarGetObj(var);
15341  if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
15342  {
15343  SCIP_INTERVAL objint;
15344  SCIP_INTERVAL bd;
15345  SCIP_INTERVAL prod;
15346  SCIP_INTERVAL psval;
15347 
15348  SCIPintervalSet(&psval, pseudoobjval);
15349  SCIPintervalSet(&objint, SCIPvarGetObj(var));
15350 
15351  if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
15352  pseudoobjvalinf--;
15353  else
15354  {
15355  SCIPintervalSet(&bd, oldbound);
15356  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
15357  SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
15358  }
15359  assert(pseudoobjvalinf >= 0);
15360  if( SCIPsetIsInfinity(set, REALABS(newbound)) )
15361  pseudoobjvalinf++;
15362  else
15363  {
15364  SCIPintervalSet(&bd, newbound);
15365  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
15366  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
15367  }
15368 
15369  pseudoobjval = SCIPintervalGetInf(psval);
15370  }
15371  assert(pseudoobjvalinf >= 0);
15372 
15373  if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
15374  return -SCIPsetInfinity(set);
15375  else
15376  return pseudoobjval;
15377 }
15378 
15379 /** compute the objective delta due the new objective coefficient */
15380 static
15382  SCIP_SET* set, /**< global SCIP settings */
15383  SCIP_Real oldobj, /**< old objective value of variable */
15384  SCIP_Real newobj, /**< new objective value of variable */
15385  SCIP_Real lb, /**< lower bound of variable */
15386  SCIP_Real ub, /**< upper bound of variable */
15387  SCIP_Real* deltaval, /**< pointer to store the delta value */
15388  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15389  )
15390 {
15391  assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
15392  assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
15393  assert(!SCIPsetIsInfinity(set, lb));
15394  assert(!SCIPsetIsInfinity(set, -ub));
15395  assert(!SCIPsetIsEQ(set, oldobj, newobj));
15396 
15397  (*deltaval) = 0.0;
15398  (*deltainf) = 0;
15399 
15400  if( SCIPsetIsPositive(set, oldobj) )
15401  {
15402  /* sign of objective did not change */
15403  if( SCIPsetIsPositive(set, newobj) )
15404  {
15405  /* if the bound is finite, calculate the deltaval */
15406  if( !SCIPsetIsInfinity(set, -lb) )
15407  (*deltaval) = lb * (newobj - oldobj);
15408  }
15409  /* sign of objective did change, so the best bound does change */
15410  else if( SCIPsetIsNegative(set, newobj) )
15411  {
15412  if( SCIPsetIsInfinity(set, -lb) )
15413  {
15414  /* old best bound was infinite while new one is not */
15415  if( !SCIPsetIsInfinity(set, ub) )
15416  {
15417  (*deltainf) = -1;
15418  (*deltaval) = ub * newobj;
15419  }
15420  }
15421  else
15422  {
15423  /* new best bound is infinite while old one was not */
15424  if( SCIPsetIsInfinity(set, ub) )
15425  {
15426  (*deltainf) = 1;
15427  (*deltaval) = -lb * oldobj;
15428  }
15429  /* neither old nor new best bound is infinite, so just calculate the deltaval */
15430  else
15431  {
15432  (*deltaval) = (ub * newobj) - (lb * oldobj);
15433  }
15434  }
15435  }
15436  /* new objective is 0.0 */
15437  else
15438  {
15439  if( SCIPsetIsInfinity(set, -lb) )
15440  (*deltainf) = -1;
15441  else
15442  (*deltaval) = -lb * oldobj;
15443  }
15444 
15445  }
15446  else if( SCIPsetIsNegative(set, oldobj) )
15447  {
15448  /* sign of objective did not change */
15449  if( SCIPsetIsNegative(set, newobj) )
15450  {
15451  /* if the bound is finite, calculate the deltaval */
15452  if( !SCIPsetIsInfinity(set, ub) )
15453  (*deltaval) = ub * (newobj - oldobj);
15454  }
15455  /* sign of objective did change, so the best bound does change */
15456  else if( SCIPsetIsPositive(set, newobj) )
15457  {
15458  if( SCIPsetIsInfinity(set, ub) )
15459  {
15460  /* old best bound was infinite while new one is not */
15461  if( !SCIPsetIsInfinity(set, -lb) )
15462  {
15463  (*deltainf) = -1;
15464  (*deltaval) = lb * newobj;
15465  }
15466  }
15467  else
15468  {
15469  /* new best bound is infinite while old one was not */
15470  if( SCIPsetIsInfinity(set, -lb) )
15471  {
15472  (*deltainf) = 1;
15473  (*deltaval) = -ub * oldobj;
15474  }
15475  /* neither old nor new best bound is infinite, so just calculate the deltaval */
15476  else
15477  {
15478  (*deltaval) = (lb * newobj) - (ub * oldobj);
15479  }
15480  }
15481  }
15482  /* new objective is 0.0 */
15483  else
15484  {
15485  if( SCIPsetIsInfinity(set, ub) )
15486  (*deltainf) = -1;
15487  else
15488  (*deltaval) = -ub * oldobj;
15489  }
15490  }
15491  /* old objective was 0.0 */
15492  else
15493  {
15494  if( SCIPsetIsNegative(set, newobj) )
15495  {
15496  if( SCIPsetIsInfinity(set, ub) )
15497  (*deltainf) = 1;
15498  else
15499  (*deltaval) = ub * newobj;
15500  }
15501  else if( SCIPsetIsPositive(set, newobj) )
15502  {
15503  if( SCIPsetIsInfinity(set, -lb) )
15504  (*deltainf) = 1;
15505  else
15506  (*deltaval) = lb * newobj;
15507  }
15508  }
15509 }
15510 
15511 /** compute the objective delta due the new lower bound */
15512 static
15514  SCIP_SET* set, /**< global SCIP settings */
15515  SCIP_Real obj, /**< objective value of variable */
15516  SCIP_Real oldlb, /**< old lower bound of variable */
15517  SCIP_Real newlb, /**< new lower bound of variable */
15518  SCIP_Real* deltaval, /**< pointer to store the delta value */
15519  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15520  )
15521 {
15522  assert(!SCIPsetIsInfinity(set, REALABS(obj)));
15523  assert(!SCIPsetIsInfinity(set, oldlb));
15524  assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
15525  assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
15526 
15527  if( SCIPsetIsInfinity(set, -oldlb) )
15528  {
15529  if( !SCIPsetIsInfinity(set, newlb) )
15530  {
15531  (*deltainf) = -1;
15532  (*deltaval) = newlb * obj;
15533  }
15534  else
15535  {
15536  (*deltainf) = 0;
15537  (*deltaval) = 0.0;
15538  }
15539  }
15540  else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
15541  {
15542  (*deltainf) = 1;
15543  (*deltaval) = -oldlb * obj;
15544  }
15545  else
15546  {
15547  (*deltainf) = 0;
15548  (*deltaval) = obj * (newlb - oldlb);
15549  }
15550 }
15551 
15552 /** compute the objective delta due the new upper bound */
15553 static
15555  SCIP_SET* set, /**< global SCIP settings */
15556  SCIP_Real obj, /**< objective value of variable */
15557  SCIP_Real oldub, /**< old upper bound of variable */
15558  SCIP_Real newub, /**< new upper bound of variable */
15559  SCIP_Real* deltaval, /**< pointer to store the delta value */
15560  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15561  )
15562 {
15563  assert(!SCIPsetIsInfinity(set, REALABS(obj)));
15564  assert(!SCIPsetIsInfinity(set, -oldub));
15565  assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
15566  assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
15567 
15568  if( SCIPsetIsInfinity(set, oldub) )
15569  {
15570  if( !SCIPsetIsInfinity(set, -newub) )
15571  {
15572  (*deltainf) = -1;
15573  (*deltaval) = newub * obj;
15574  }
15575  else
15576  {
15577  (*deltainf) = 0;
15578  (*deltaval) = 0.0;
15579  }
15580  }
15581  else if( SCIPsetIsInfinity(set, REALABS(newub)) )
15582  {
15583  (*deltainf) = 1;
15584  (*deltaval) = -oldub * obj;
15585  }
15586  else
15587  {
15588  (*deltainf) = 0;
15589  (*deltaval) = obj * (newub - oldub);
15590  }
15591 }
15592 
15593 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
15594 static
15596  SCIP_LP* lp, /**< current LP data */
15597  SCIP_SET* set, /**< global SCIP settings */
15598  SCIP_VAR* var, /**< problem variable that changed */
15599  SCIP_Real deltaval, /**< delta value in the objective function */
15600  int deltainf, /**< delta value for the number of variables with infinite best bound */
15601  SCIP_Bool local, /**< should the local pseudo objective value be updated? */
15602  SCIP_Bool loose, /**< should the loose objective value be updated? */
15603  SCIP_Bool global /**< should the global pseudo objective value be updated? */
15604  )
15605 {
15606  assert(lp != NULL);
15607  assert(lp->looseobjvalinf >= 0);
15608  assert(lp->pseudoobjvalinf >= 0);
15609  assert(lp->glbpseudoobjvalinf >= 0);
15610 
15611  /* update the pseudo objective value */
15612  if( local )
15613  {
15614  lp->pseudoobjvalinf += deltainf;
15615  if( lp->pseudoobjvalid )
15616  {
15617  lp->pseudoobjval += deltaval;
15618 
15619  /* if the absolute value was increased, this is regarded as reliable,
15620  * otherwise, we check whether we can still trust the updated value
15621  */
15622  if( REALABS(lp->relpseudoobjval) < REALABS(lp->pseudoobjval) )
15623  lp->relpseudoobjval = lp->pseudoobjval;
15624  else if( SCIPsetIsUpdateUnreliable(set, lp->pseudoobjval, lp->relpseudoobjval) )
15625  lp->pseudoobjvalid = FALSE;
15626  }
15627 
15628  /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
15630  loose = TRUE;
15631  }
15632  /* update the loose objective value */
15633  if( loose )
15634  {
15635  lp->looseobjvalinf += deltainf;
15636 
15637  if( deltaval != 0.0 && lp->looseobjvalid )
15638  {
15639  lp->looseobjval += deltaval;
15640 
15641  /* if the absolute value was increased, this is regarded as reliable,
15642  * otherwise, we check whether we can still trust the updated value
15643  */
15644  if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
15645  lp->rellooseobjval = lp->looseobjval;
15646  else if( SCIPsetIsUpdateUnreliable(set, lp->looseobjval, lp->rellooseobjval) )
15647  lp->looseobjvalid = FALSE;
15648  }
15649  }
15650  /* update the root pseudo objective values */
15651  if( global )
15652  {
15653  lp->glbpseudoobjvalinf += deltainf;
15654  if( lp->glbpseudoobjvalid )
15655  {
15656  lp->glbpseudoobjval += deltaval;
15657 
15658  /* if the absolute value was increased, this is regarded as reliable,
15659  * otherwise, we check whether we can still trust the updated value
15660  */
15664  lp->glbpseudoobjvalid = FALSE;
15665  }
15666  }
15667 
15668  assert(lp->looseobjvalinf >= 0);
15669  assert(lp->pseudoobjvalinf >= 0);
15670  assert(lp->glbpseudoobjvalinf >= 0);
15671 }
15672 
15673 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
15674  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
15675  */
15676 static
15678  SCIP_LP* lp, /**< current LP data */
15679  SCIP_SET* set, /**< global SCIP settings */
15680  SCIP_VAR* var, /**< problem variable that changed */
15681  SCIP_Real oldobj, /**< old objective value of variable */
15682  SCIP_Real oldlb, /**< old objective value of variable */
15683  SCIP_Real oldub, /**< old objective value of variable */
15684  SCIP_Real newobj, /**< new objective value of variable */
15685  SCIP_Real newlb, /**< new objective value of variable */
15686  SCIP_Real newub /**< new objective value of variable */
15687  )
15688 {
15689  SCIP_INTERVAL deltaval;
15690  SCIP_INTERVAL bd;
15691  SCIP_INTERVAL obj;
15692  SCIP_INTERVAL prod;
15693  SCIP_INTERVAL psval;
15694  int deltainf;
15695 
15696  assert(lp != NULL);
15697  assert(lp->pseudoobjvalinf >= 0);
15698  assert(lp->looseobjvalinf >= 0);
15699  assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
15700  assert(!SCIPsetIsInfinity(set, oldlb));
15701  assert(!SCIPsetIsInfinity(set, -oldub));
15702  assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
15703  assert(!SCIPsetIsInfinity(set, newlb));
15704  assert(!SCIPsetIsInfinity(set, -newub));
15705  assert(var != NULL);
15706 
15708  {
15709  SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
15710  return SCIP_INVALIDDATA;
15711  }
15712 
15713  assert(SCIPvarGetProbindex(var) >= 0);
15714 
15715  SCIPintervalSet(&deltaval, 0.0);
15716  deltainf = 0;
15717 
15718  /* subtract old pseudo objective value */
15719  if( oldobj > 0.0 )
15720  {
15721  if( SCIPsetIsInfinity(set, -oldlb) )
15722  deltainf--;
15723  else
15724  {
15725  SCIPintervalSet(&bd, oldlb);
15726  SCIPintervalSet(&obj, oldobj);
15727  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15728  SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
15729  }
15730  }
15731  else if( oldobj < 0.0 )
15732  {
15733  if( SCIPsetIsInfinity(set, oldub) )
15734  deltainf--;
15735  else
15736  {
15737  SCIPintervalSet(&bd, oldub);
15738  SCIPintervalSet(&obj, oldobj);
15739  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15740  SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
15741  }
15742  }
15743 
15744  /* add new pseudo objective value */
15745  if( newobj > 0.0 )
15746  {
15747  if( SCIPsetIsInfinity(set, -newlb) )
15748  deltainf++;
15749  else
15750  {
15751  SCIPintervalSet(&bd, newlb);
15752  SCIPintervalSet(&obj, newobj);
15753  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15754  SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
15755  }
15756  }
15757  else if( newobj < 0.0 )
15758  {
15759  if( SCIPsetIsInfinity(set, newub) )
15760  deltainf++;
15761  else
15762  {
15763  SCIPintervalSet(&bd, newub);
15764  SCIPintervalSet(&obj, newobj);
15765  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15766  SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
15767  }
15768  }
15769 
15770  /* update the pseudo and loose objective values */
15771  SCIPintervalSet(&psval, lp->pseudoobjval);
15772  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
15773  lp->pseudoobjval = SCIPintervalGetInf(psval);
15774  lp->pseudoobjvalinf += deltainf;
15776  {
15777  SCIPintervalSet(&psval, lp->looseobjval);
15778  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
15779  lp->looseobjval = SCIPintervalGetInf(psval);
15780  lp->looseobjvalinf += deltainf;
15781  }
15782 
15783  assert(lp->pseudoobjvalinf >= 0);
15784  assert(lp->looseobjvalinf >= 0);
15785 
15786  return SCIP_OKAY;
15787 }
15788 
15789 /** updates current pseudo and loose objective value for a change in a variable's objective value */
15791  SCIP_LP* lp, /**< current LP data */
15792  SCIP_SET* set, /**< global SCIP settings */
15793  SCIP_VAR* var, /**< problem variable that changed */
15794  SCIP_Real oldobj, /**< old objective value of variable */
15795  SCIP_Real newobj /**< new objective value of variable */
15796  )
15797 {
15798  assert(set != NULL);
15799  assert(var != NULL);
15800 
15801  if( set->misc_exactsolve )
15802  {
15803  if( oldobj != newobj ) /*lint !e777*/
15804  {
15805  SCIP_CALL( lpUpdateVarProved(lp, set, var, oldobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
15806  newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
15807  }
15808  }
15809  else
15810  {
15811  if( !SCIPsetIsEQ(set, oldobj, newobj) )
15812  {
15813  SCIP_Real deltaval;
15814  int deltainf;
15815 
15817  assert(SCIPvarGetProbindex(var) >= 0);
15818 
15819  /* the objective coefficient can only be changed during presolving, that implies that the global and local
15820  * domain of the variable are the same
15821  */
15822  assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
15823  assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
15824 
15825  /* compute the pseudo objective delta due the new objective coefficient */
15826  getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
15827 
15828  /* update the local pseudo objective value */
15829  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
15830 
15831  /* compute the pseudo objective delta due the new objective coefficient */
15832  getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
15833 
15834  /* update the global pseudo objective value */
15835  lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
15836  }
15837  }
15838 
15839  return SCIP_OKAY;
15840 }
15841 
15842 
15843 /** updates current root pseudo objective value for a global change in a variable's lower bound */
15845  SCIP_LP* lp, /**< current LP data */
15846  SCIP_SET* set, /**< global SCIP settings */
15847  SCIP_VAR* var, /**< problem variable that changed */
15848  SCIP_Real oldlb, /**< old lower bound of variable */
15849  SCIP_Real newlb /**< new lower bound of variable */
15850  )
15851 {
15852  assert(set != NULL);
15853  assert(var != NULL);
15854 
15855  if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
15856  {
15857  SCIP_Real deltaval;
15858  int deltainf;
15859 
15860  /* compute the pseudo objective delta due the new lower bound */
15861  getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
15862 
15863  /* update the root pseudo objective values */
15864  lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
15865 
15866  }
15867 
15868  return SCIP_OKAY;
15869 }
15870 
15871 /** updates current pseudo and loose objective value for a change in a variable's lower bound */
15873  SCIP_LP* lp, /**< current LP data */
15874  SCIP_SET* set, /**< global SCIP settings */
15875  SCIP_VAR* var, /**< problem variable that changed */
15876  SCIP_Real oldlb, /**< old lower bound of variable */
15877  SCIP_Real newlb /**< new lower bound of variable */
15878  )
15879 {
15880  assert(set != NULL);
15881  assert(var != NULL);
15882 
15883  if( set->misc_exactsolve )
15884  {
15885  if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
15886  {
15887  SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
15888  SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
15889  }
15890  }
15891  else
15892  {
15893  if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
15894  {
15895  SCIP_Real deltaval;
15896  int deltainf;
15897 
15899  assert(SCIPvarGetProbindex(var) >= 0);
15900 
15901  /* compute the pseudo objective delta due the new lower bound */
15902  getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
15903 
15904  /* update the pseudo and loose objective values */
15905  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
15906  }
15907  }
15908 
15909  return SCIP_OKAY;
15910 }
15911 
15912 /** updates current root pseudo objective value for a global change in a variable's upper bound */
15914  SCIP_LP* lp, /**< current LP data */
15915  SCIP_SET* set, /**< global SCIP settings */
15916  SCIP_VAR* var, /**< problem variable that changed */
15917  SCIP_Real oldub, /**< old upper bound of variable */
15918  SCIP_Real newub /**< new upper bound of variable */
15919  )
15920 {
15921  assert(set != NULL);
15922  assert(var != NULL);
15923 
15924  if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
15925  {
15926  SCIP_Real deltaval;
15927  int deltainf;
15928 
15929  /* compute the pseudo objective delta due the new upper bound */
15930  getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
15931 
15932  /* update the root pseudo objective values */
15933  lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
15934  }
15935 
15936  return SCIP_OKAY;
15937 }
15938 
15939 /** updates current pseudo objective value for a change in a variable's upper bound */
15941  SCIP_LP* lp, /**< current LP data */
15942  SCIP_SET* set, /**< global SCIP settings */
15943  SCIP_VAR* var, /**< problem variable that changed */
15944  SCIP_Real oldub, /**< old upper bound of variable */
15945  SCIP_Real newub /**< new upper bound of variable */
15946  )
15947 {
15948  assert(set != NULL);
15949  assert(var != NULL);
15950 
15951  if( set->misc_exactsolve )
15952  {
15953  if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
15954  {
15955  SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
15956  SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
15957  }
15958  }
15959  else
15960  {
15961  if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
15962  {
15963  SCIP_Real deltaval;
15964  int deltainf;
15965 
15967  assert(SCIPvarGetProbindex(var) >= 0);
15968 
15969  /* compute the pseudo objective delta due the new upper bound */
15970  getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
15971 
15972  /* update the pseudo and loose objective values */
15973  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
15974  }
15975  }
15976 
15977  return SCIP_OKAY;
15978 }
15979 
15980 /** informs LP, that given variable was added to the problem */
15982  SCIP_LP* lp, /**< current LP data */
15983  SCIP_SET* set, /**< global SCIP settings */
15984  SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
15985  )
15986 {
15987  assert(lp != NULL);
15989  assert(SCIPvarGetProbindex(var) >= 0);
15990 
15991  /* add the variable to the loose objective value sum */
15992  SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
15993 
15994  /* update the loose variables counter */
15996  lp->nloosevars++;
15997 
15998  return SCIP_OKAY;
15999 }
16000 
16001 /** informs LP, that given variable is to be deleted from the problem */
16003  SCIP_LP* lp, /**< current LP data */
16004  SCIP_SET* set, /**< global SCIP settings */
16005  SCIP_VAR* var /**< variable that will be deleted from the problem */
16006  )
16007 {
16008  assert(lp != NULL);
16010  assert(SCIPvarGetProbindex(var) >= 0);
16011 
16012  /* subtract the variable from the loose objective value sum */
16013  SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
16014 
16015  /* update the loose variables counter */
16017  {
16018  SCIPlpDecNLoosevars(lp);
16019  }
16020 
16021  return SCIP_OKAY;
16022 }
16023 
16024 /** informs LP, that given formerly loose problem variable is now a column variable */
16025 static
16027  SCIP_LP* lp, /**< current LP data */
16028  SCIP_SET* set, /**< global SCIP settings */
16029  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
16030  )
16031 {
16032  SCIP_Real obj;
16033  SCIP_Real lb;
16034  SCIP_Real ub;
16035 
16036  assert(lp != NULL);
16037  assert(lp->nloosevars > 0);
16038  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16039  assert(SCIPvarGetProbindex(var) >= 0);
16040  assert(lp->looseobjvalinf >= 0);
16041 
16042  obj = SCIPvarGetObj(var);
16043 
16044  /* update loose objective value */
16045  if( SCIPsetIsPositive(set, obj) )
16046  {
16047  lb = SCIPvarGetLbLocal(var);
16048  if( SCIPsetIsInfinity(set, -lb) )
16049  lp->looseobjvalinf--;
16050  else
16051  lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
16052  }
16053  else if( SCIPsetIsNegative(set, obj) )
16054  {
16055  ub = SCIPvarGetUbLocal(var);
16056  if( SCIPsetIsInfinity(set, ub) )
16057  lp->looseobjvalinf--;
16058  else
16059  lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
16060  }
16061 
16062  SCIPlpDecNLoosevars(lp);
16063 
16064  assert(lp->looseobjvalinf >= 0);
16065 
16066  return SCIP_OKAY;
16067 }
16068 
16069 /** informs LP, that given formerly loose problem variable is now a column variable
16070  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
16071  */
16072 static
16074  SCIP_LP* lp, /**< current LP data */
16075  SCIP_SET* set, /**< global SCIP settings */
16076  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
16077  )
16078 {
16079  SCIP_INTERVAL bd;
16080  SCIP_INTERVAL ob;
16081  SCIP_INTERVAL prod;
16082  SCIP_INTERVAL loose;
16083  SCIP_Real obj;
16084  SCIP_Real lb;
16085  SCIP_Real ub;
16086 
16087  assert(lp != NULL);
16088  assert(lp->nloosevars > 0);
16089  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16090  assert(SCIPvarGetProbindex(var) >= 0);
16091 
16092  obj = SCIPvarGetObj(var);
16093 
16094  SCIPintervalSet(&loose, lp->looseobjval);
16095 
16096  /* update loose objective value corresponding to the deletion of variable */
16097  if( obj > 0.0 )
16098  {
16099  lb = SCIPvarGetLbLocal(var);
16100  if( SCIPsetIsInfinity(set, -lb) )
16101  lp->looseobjvalinf--;
16102  else
16103  {
16104  SCIPintervalSet(&bd, lb);
16105  SCIPintervalSet(&ob, obj);
16106  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
16107  SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
16108  }
16109  }
16110  else if( SCIPsetIsNegative(set, obj) )
16111  {
16112  ub = SCIPvarGetUbLocal(var);
16113  if( SCIPsetIsInfinity(set, ub) )
16114  lp->looseobjvalinf--;
16115  else
16116  {
16117  SCIPintervalSet(&bd, ub);
16118  SCIPintervalSet(&ob, obj);
16119  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
16120  SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
16121  }
16122  }
16123  lp->nloosevars--;
16124 
16125  /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
16126  if( lp->nloosevars == 0 )
16127  {
16128  assert(lp->looseobjvalinf == 0);
16129  lp->looseobjval = 0.0;
16130  }
16131  else
16132  lp->looseobjval = SCIPintervalGetInf(loose);
16133 
16134  return SCIP_OKAY;
16135 }
16136 
16137 /** informs LP, that given formerly loose problem variable is now a column variable */
16139  SCIP_LP* lp, /**< current LP data */
16140  SCIP_SET* set, /**< global SCIP settings */
16141  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
16142  )
16143 {
16144  assert(set != NULL);
16145 
16146  if( set->misc_exactsolve )
16147  {
16148  SCIP_CALL( lpUpdateVarColumnProved(lp, set, var) );
16149  }
16150  else
16151  {
16152  SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
16153  }
16154 
16155  return SCIP_OKAY;
16156 }
16157 
16158 /** informs LP, that given formerly column problem variable is now again a loose variable */
16159 static
16161  SCIP_LP* lp, /**< current LP data */
16162  SCIP_SET* set, /**< global SCIP settings */
16163  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
16164  )
16165 {
16166  SCIP_Real obj;
16167  SCIP_Real lb;
16168  SCIP_Real ub;
16169 
16170  assert(lp != NULL);
16171  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
16172  assert(SCIPvarGetProbindex(var) >= 0);
16173  assert(lp->looseobjvalinf >= 0);
16174 
16175  obj = SCIPvarGetObj(var);
16176 
16177  /* update loose objective value corresponding to the addition of variable */
16178  if( SCIPsetIsPositive(set, obj) )
16179  {
16180  lb = SCIPvarGetLbLocal(var);
16181  if( SCIPsetIsInfinity(set, -lb) )
16182  lp->looseobjvalinf++;
16183  else
16184  lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
16185  }
16186  else if( SCIPsetIsNegative(set, obj) )
16187  {
16188  ub = SCIPvarGetUbLocal(var);
16189  if( SCIPsetIsInfinity(set, ub) )
16190  lp->looseobjvalinf++;
16191  else
16192  lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
16193  }
16194  lp->nloosevars++;
16195 
16196  assert(lp->looseobjvalinf >= 0);
16197 
16198  return SCIP_OKAY;
16199 }
16200 
16201 /** informs LP, that given formerly column problem variable is now again a loose variable
16202  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
16203  */
16204 static
16206  SCIP_LP* lp, /**< current LP data */
16207  SCIP_SET* set, /**< global SCIP settings */
16208  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
16209  )
16210 {
16211  SCIP_INTERVAL bd;
16212  SCIP_INTERVAL ob;
16213  SCIP_INTERVAL prod;
16214  SCIP_INTERVAL loose;
16215  SCIP_Real obj;
16216  SCIP_Real lb;
16217  SCIP_Real ub;
16218 
16219  assert(lp != NULL);
16220  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
16221  assert(SCIPvarGetProbindex(var) >= 0);
16222 
16223  obj = SCIPvarGetObj(var);
16224 
16225  SCIPintervalSet(&loose, lp->looseobjval);
16226 
16227  /* update loose objective value corresponding to the deletion of variable */
16228  if( obj > 0.0 )
16229  {
16230  lb = SCIPvarGetLbLocal(var);
16231  if( SCIPsetIsInfinity(set, -lb) )
16232  lp->looseobjvalinf++;
16233  else
16234  {
16235  SCIPintervalSet(&bd, lb);
16236  SCIPintervalSet(&ob, obj);
16237  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
16238  SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
16239  }
16240  }
16241  else if( SCIPsetIsNegative(set, obj) )
16242  {
16243  ub = SCIPvarGetUbLocal(var);
16244  if( SCIPsetIsInfinity(set, ub) )
16245  lp->looseobjvalinf++;
16246  else
16247  {
16248  SCIPintervalSet(&bd, ub);
16249  SCIPintervalSet(&ob, obj);
16250  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
16251  SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
16252  }
16253  }
16254  lp->nloosevars++;
16255 
16256  lp->looseobjval = SCIPintervalGetInf(loose);
16257 
16258  return SCIP_OKAY;
16259 }
16260 
16261 /** informs LP, that given formerly column problem variable is now again a loose variable */
16263  SCIP_LP* lp, /**< current LP data */
16264  SCIP_SET* set, /**< global SCIP settings */
16265  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
16266  )
16267 {
16268  assert(set != NULL);
16269 
16270  if( set->misc_exactsolve )
16271  {
16272  SCIP_CALL( lpUpdateVarLooseProved(lp, set, var) );
16273  }
16274  else
16275  {
16276  SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
16277  }
16278 
16279  return SCIP_OKAY;
16280 }
16281 
16282 /** decrease the number of loose variables by one */
16284  SCIP_LP* lp /**< current LP data */
16285  )
16286 {
16287  assert(lp != NULL);
16288  assert(lp->nloosevars > 0);
16289 
16290  lp->nloosevars--;
16291 
16292  /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
16293  if( lp->nloosevars == 0 )
16294  {
16295  assert(lp->looseobjvalinf == 0);
16296  lp->looseobjval = 0.0;
16297  }
16298 }
16299 
16300 /** stores the LP solution in the columns and rows */
16302  SCIP_LP* lp, /**< current LP data */
16303  SCIP_SET* set, /**< global SCIP settings */
16304  SCIP_STAT* stat, /**< problem statistics */
16305  SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
16306  SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
16307  )
16308 {
16309  SCIP_COL** lpicols;
16310  SCIP_ROW** lpirows;
16311  SCIP_Real* primsol;
16312  SCIP_Real* dualsol;
16313  SCIP_Real* activity;
16314  SCIP_Real* redcost;
16315  SCIP_Real primalbound;
16316  SCIP_Real dualbound;
16317  SCIP_Bool stillprimalfeasible;
16318  SCIP_Bool stilldualfeasible;
16319  int* cstat;
16320  int* rstat;
16321  SCIP_Longint lpcount;
16322  int nlpicols;
16323  int nlpirows;
16324  int c;
16325  int r;
16326 
16327  assert(lp != NULL);
16328  assert(lp->flushed);
16329  assert(lp->solved);
16330  assert(set != NULL);
16331  assert(stat != NULL);
16332  assert(lp->validsollp <= stat->lpcount);
16333 
16334  /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
16335  * corresponding flag immediately to FALSE to skip all checks
16336  */
16337  if( primalfeasible == NULL )
16338  stillprimalfeasible = FALSE;
16339  else
16340  {
16341  *primalfeasible = TRUE;
16342  stillprimalfeasible = TRUE;
16343  }
16344  if( dualfeasible == NULL )
16345  stilldualfeasible = FALSE;
16346  else
16347  {
16348  *dualfeasible = TRUE;
16349  stilldualfeasible = TRUE;
16350  }
16351 
16352  /* check if the values are already calculated */
16353  if( lp->validsollp == stat->lpcount )
16354  return SCIP_OKAY;
16355  lp->validsollp = stat->lpcount;
16356 
16357  SCIPdebugMessage("getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
16358  stat->lpcount, SCIPlpGetSolstat(lp));
16359 
16360  lpicols = lp->lpicols;
16361  lpirows = lp->lpirows;
16362  nlpicols = lp->nlpicols;
16363  nlpirows = lp->nlpirows;
16364  lpcount = stat->lpcount;
16365 
16366  /* get temporary memory */
16367  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
16368  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
16369  SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
16370  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
16371  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
16372  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
16373 
16374  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
16375  if( lp->solisbasic )
16376  {
16377  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
16378  }
16379  else
16380  {
16381  BMSclearMemoryArray(cstat, nlpicols);
16382  BMSclearMemoryArray(rstat, nlpirows);
16383  }
16384 
16385  primalbound = 0.0;
16386  dualbound = 0.0;
16387 
16388  /* copy primal solution and reduced costs into columns */
16389  for( c = 0; c < nlpicols; ++c )
16390  {
16391  assert( 0 <= cstat[c] && cstat[c] < 4 );
16392  lpicols[c]->primsol = primsol[c];
16393  lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
16394  lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
16395  lpicols[c]->redcost = redcost[c];
16396  lpicols[c]->basisstatus = (unsigned int) cstat[c];
16397  lpicols[c]->validredcostlp = lpcount;
16398  if( stillprimalfeasible )
16399  {
16400  stillprimalfeasible =
16401  (SCIPsetIsInfinity(set, -lpicols[c]->lb) || !SCIPsetIsFeasNegative(set, lpicols[c]->primsol - lpicols[c]->lb))
16402  && (SCIPsetIsInfinity(set, lpicols[c]->ub) || !SCIPsetIsFeasPositive(set, lpicols[c]->primsol - lpicols[c]->ub));
16403  primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
16404  }
16405  if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
16406  {
16407  double compslack;
16408 
16409  /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
16410  * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
16411  * variables, which would magnify even the tiniest violation in the dual multiplier
16412  */
16413  if( stilldualfeasible )
16414  {
16415  compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
16416  stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
16417  }
16418  if( stilldualfeasible )
16419  {
16420  compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
16421  stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
16422  }
16423 
16424  SCIPdebugMessage(" col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16425  SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
16426  SCIPsetIsFeasGE(set, lpicols[c]->primsol, lpicols[c]->lb),
16427  SCIPsetIsFeasLE(set, lpicols[c]->primsol, lpicols[c]->ub),
16428  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16429  !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
16430  !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
16431  dualfeasible != NULL ? stilldualfeasible : TRUE);
16432  }
16433  else
16434  {
16435  /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
16436  if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
16437  {
16438  lpicols[c]->redcost = 0.0;
16439  }
16440 
16441  /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
16442  * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
16443  * bounds, its reduced cost must be zero
16444  */
16445  if( stilldualfeasible
16446  && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPsetIsFeasGT(set, lpicols[c]->primsol, lpicols[c]->lb)) )
16447  stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
16448  if( stilldualfeasible
16449  && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPsetIsFeasLT(set, lpicols[c]->primsol, lpicols[c]->ub)) )
16450  stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
16451 
16452  SCIPdebugMessage(" col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16453  SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
16454  SCIPsetIsFeasGE(set, lpicols[c]->primsol, lpicols[c]->lb),
16455  SCIPsetIsFeasLE(set, lpicols[c]->primsol, lpicols[c]->ub),
16456  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16457  !SCIPsetIsFeasGT(set, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
16458  !SCIPsetIsFeasLT(set, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
16459  dualfeasible != NULL ? stilldualfeasible : TRUE);
16460  }
16461 
16462  /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
16463  * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
16464  * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
16465  */
16466  if( stilldualfeasible )
16467  {
16468  if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
16469  dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
16470  else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
16471  dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
16472  }
16473  }
16474 
16475  /* copy dual solution and activities into rows */
16476  for( r = 0; r < nlpirows; ++r )
16477  {
16478  assert( 0 <= rstat[r] && rstat[r] < 4 );
16479  lpirows[r]->dualsol = dualsol[r];
16480  lpirows[r]->activity = activity[r] + lpirows[r]->constant;
16481  lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
16482  lpirows[r]->validactivitylp = lpcount;
16483  if( stillprimalfeasible )
16484  {
16485  stillprimalfeasible =
16486  (SCIPsetIsInfinity(set,-lpirows[r]->lhs) ||SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs))
16487  && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs));
16488  }
16489  if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
16490  {
16491  double compslack;
16492 
16493  /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
16494  * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
16495  * variables, which would magnify even the tiniest violation in the dual multiplier
16496  */
16497  if( stilldualfeasible )
16498  {
16499  compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
16500  stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
16501  }
16502  if( stilldualfeasible )
16503  {
16504  compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
16505  stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
16506  }
16507 
16508  SCIPdebugMessage(" row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16509  lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
16510  SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs),
16511  SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs),
16512  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16513  !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
16514  !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
16515  dualfeasible != NULL ? stilldualfeasible : TRUE);
16516  }
16517  else
16518  {
16519  /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
16520  * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
16521  * strictly within left-hand and right-hand side, its dual multiplier must be zero
16522  */
16523  if( stilldualfeasible &&
16524  (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPsetIsFeasGT(set, lpirows[r]->activity, lpirows[r]->lhs)) )
16525  stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
16526  if( stilldualfeasible &&
16527  (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPsetIsFeasLT(set, lpirows[r]->activity, lpirows[r]->rhs)) )
16528  stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
16529 
16530  SCIPdebugMessage(" row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16531  lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
16532  SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs),
16533  SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs),
16534  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16535  !SCIPsetIsFeasGT(set, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
16536  !SCIPsetIsFeasLT(set, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
16537  dualfeasible != NULL ? stilldualfeasible : TRUE);
16538  }
16539 
16540  /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
16541  * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
16542  * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
16543  */
16544  if( stilldualfeasible )
16545  {
16546  if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -(lpirows[r]->lhs - lpirows[r]->constant)) )
16547  dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
16548  else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs - lpirows[r]->constant) )
16549  dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
16550  }
16551  }
16552 
16553  /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
16554  * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
16555  * infinity
16556  */
16557  /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
16558  if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
16559  && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
16560  {
16561  stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
16562  SCIPdebugMessage(" primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
16563  SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
16564  }
16565 
16566  /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
16567  * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
16568  */
16569  /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
16570  if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
16571  && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
16572  {
16573  stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
16574  SCIPdebugMessage(" dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
16575  SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
16576  }
16577 
16578  if( primalfeasible != NULL )
16579  *primalfeasible = stillprimalfeasible;
16580  if( dualfeasible != NULL )
16581  *dualfeasible = stilldualfeasible;
16582 
16583  /* free temporary memory */
16584  SCIPsetFreeBufferArray(set, &rstat);
16585  SCIPsetFreeBufferArray(set, &cstat);
16586  SCIPsetFreeBufferArray(set, &redcost);
16587  SCIPsetFreeBufferArray(set, &activity);
16588  SCIPsetFreeBufferArray(set, &dualsol);
16589  SCIPsetFreeBufferArray(set, &primsol);
16590 
16591  return SCIP_OKAY;
16592 }
16593 
16594 /** stores LP solution with infinite objective value in the columns and rows */
16596  SCIP_LP* lp, /**< current LP data */
16597  SCIP_SET* set, /**< global SCIP settings */
16598  SCIP_STAT* stat, /**< problem statistics */
16599  SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
16600  SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
16601  )
16602 {
16603  SCIP_COL** lpicols;
16604  SCIP_ROW** lpirows;
16605  SCIP_Real* primsol;
16606  SCIP_Real* activity;
16607  SCIP_Real* ray;
16608  SCIP_Real rayobjval;
16609  SCIP_Real rayscale;
16610  SCIP_Longint lpcount;
16611  int nlpicols;
16612  int nlpirows;
16613  int c;
16614  int r;
16615 
16616  assert(lp != NULL);
16617  assert(lp->flushed);
16618  assert(lp->solved);
16619  assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
16620  assert(SCIPsetIsInfinity(set, -lp->lpobjval));
16621  assert(set != NULL);
16622  assert(stat != NULL);
16623  assert(lp->validsollp <= stat->lpcount);
16624 
16625  if( primalfeasible != NULL )
16626  *primalfeasible = TRUE;
16627  if( rayfeasible != NULL )
16628  *rayfeasible = TRUE;
16629 
16630  /* check if the values are already calculated */
16631  if( lp->validsollp == stat->lpcount )
16632  return SCIP_OKAY;
16633 
16634  /* check if the LP solver is able to provide a primal unbounded ray */
16635  if( !SCIPlpiHasPrimalRay(lp->lpi) )
16636  {
16637  SCIPerrorMessage("LP solver has no primal ray to prove unboundedness\n");
16638  return SCIP_LPERROR;
16639  }
16640 
16641  lp->validsollp = stat->lpcount;
16642 
16643  SCIPdebugMessage("getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
16644 
16645  /* get temporary memory */
16646  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
16647  SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
16648  SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, lp->nlpicols) );
16649 
16650  /* get primal feasible point */
16651  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, activity, NULL) );
16652 
16653  /* get primal unbounded ray */
16654  SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
16655 
16656  lpicols = lp->lpicols;
16657  lpirows = lp->lpirows;
16658  nlpicols = lp->nlpicols;
16659  nlpirows = lp->nlpirows;
16660  lpcount = stat->lpcount;
16661 
16662  /* calculate the objective value decrease of the ray */
16663  rayobjval = 0.0;
16664  for( c = 0; c < nlpicols; ++c )
16665  {
16666  assert(lpicols[c] != NULL);
16667  assert(lpicols[c]->var != NULL);
16668 
16669  /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
16670  if( rayfeasible != NULL )
16671  *rayfeasible = *rayfeasible
16672  && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -lpicols[c]->lb))
16673  && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, lpicols[c]->ub));
16674 
16675  /* check primal feasibility of (finite) primal solution; note that the comparisons ensure that the primal
16676  * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined
16677  */
16678  if( primalfeasible != NULL )
16679  *primalfeasible = *primalfeasible
16680  && !SCIPsetIsFeasNegative(set, primsol[c] - lpicols[c]->lb)
16681  && !SCIPsetIsFeasPositive(set, primsol[c] - lpicols[c]->ub);
16682 
16683  if( !SCIPsetIsZero(set, ray[c]) )
16684  rayobjval += ray[c] * lpicols[c]->obj;
16685  }
16686 
16687  /* if the finite point is already infeasible, we do not have to add the ray */
16688  if( primalfeasible != NULL && !(*primalfeasible) )
16689  {
16690  rayscale = 0.0;
16691  }
16692  /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
16693  else if( rayfeasible != NULL && !(*rayfeasible) )
16694  {
16695  rayscale = 0.0;
16696  }
16697  /* due to numerical problems, the objective of the ray might be nonnegative,
16698  *
16699  * @todo How to check for negative objective value here?
16700  */
16701  else if( !SCIPsetIsNegative(set, rayobjval) )
16702  {
16703  if( rayfeasible != NULL )
16704  {
16705  *rayfeasible = FALSE;
16706  }
16707 
16708  rayscale = 0.0;
16709  }
16710  else
16711  {
16712  assert(rayobjval != 0.0);
16713 
16714  /* scale the ray, such that the resulting point has infinite objective value */
16715  rayscale = -2*SCIPsetInfinity(set)/rayobjval;
16716  assert(SCIPsetIsFeasPositive(set, rayscale));
16717 
16718  /* ensure that unbounded point does not violate the bounds of the variables */
16719  for( c = 0; c < nlpicols; ++c )
16720  {
16721  if( SCIPsetIsPositive(set, ray[c]) )
16722  rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c])/ray[c]);
16723  else if( SCIPsetIsNegative(set, ray[c]) )
16724  rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c])/ray[c]);
16725 
16726  assert(SCIPsetIsFeasPositive(set, rayscale));
16727  }
16728  }
16729 
16730  SCIPdebugMessage("unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
16731 
16732  /* calculate the unbounded point: x' = x + rayscale * ray */
16733  for( c = 0; c < nlpicols; ++c )
16734  {
16735  if( SCIPsetIsZero(set, ray[c]) )
16736  lpicols[c]->primsol = primsol[c];
16737  else
16738  lpicols[c]->primsol = primsol[c] + rayscale * ray[c];
16739  lpicols[c]->redcost = SCIP_INVALID;
16740  lpicols[c]->validredcostlp = -1;
16741  }
16742 
16743  for( r = 0; r < nlpirows; ++r )
16744  {
16745  lpirows[r]->dualsol = SCIP_INVALID;
16746  lpirows[r]->activity = activity[r] + lpirows[r]->constant;
16747  lpirows[r]->validactivitylp = lpcount;
16748 
16749  /* check for feasibility of the rows */
16750  if( primalfeasible != NULL )
16751  *primalfeasible = *primalfeasible
16752  && (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs))
16753  && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs));
16754  }
16755 
16756  /* free temporary memory */
16757  SCIPsetFreeBufferArray(set, &ray);
16758  SCIPsetFreeBufferArray(set, &activity);
16759  SCIPsetFreeBufferArray(set, &primsol);
16760 
16761  return SCIP_OKAY;
16762 }
16763 
16764 /** returns primal ray proving the unboundedness of the current LP */
16766  SCIP_LP* lp, /**< current LP data */
16767  SCIP_SET* set, /**< global SCIP settings */
16768  SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
16769  * so the size of this array should be at least number of active variables
16770  * (all entries have to be initialized to 0 before) */
16771  )
16772 {
16773  SCIP_COL** lpicols;
16774  SCIP_Real* lpiray;
16775  SCIP_VAR* var;
16776  int nlpicols;
16777  int c;
16778 
16779  assert(lp != NULL);
16780  assert(set != NULL);
16781  assert(ray != NULL);
16782  assert(lp->flushed);
16783  assert(lp->solved);
16784  assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
16785  assert(SCIPsetIsInfinity(set, -lp->lpobjval));
16786 
16787  /* check if the LP solver is able to provide a primal unbounded ray */
16788  if( !SCIPlpiHasPrimalRay(lp->lpi) )
16789  {
16790  SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
16791  return SCIP_LPERROR;
16792  }
16793 
16794  /* get temporary memory */
16795  SCIP_CALL( SCIPsetAllocBufferArray(set, &lpiray, lp->nlpicols) );
16796 
16797  SCIPdebugMessage("getting primal ray values\n");
16798 
16799  /* get primal unbounded ray */
16800  SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
16801 
16802  lpicols = lp->lpicols;
16803  nlpicols = lp->nlpicols;
16804 
16805  /* store the ray values of active problem variables */
16806  for( c = 0; c < nlpicols; c++ )
16807  {
16808  assert(lpicols[c] != NULL);
16809 
16810  var = lpicols[c]->var;
16811  assert(var != NULL);
16812  assert(SCIPvarGetProbindex(var) != -1);
16813  ray[SCIPvarGetProbindex(var)] = lpiray[c];
16814  }
16815 
16816  SCIPsetFreeBufferArray(set, &lpiray);
16817 
16818  return SCIP_OKAY;
16819 }
16820 
16821 /** stores the dual Farkas multipliers for infeasibility proof in rows */
16823  SCIP_LP* lp, /**< current LP data */
16824  SCIP_SET* set, /**< global SCIP settings */
16825  SCIP_STAT* stat /**< problem statistics */
16826  )
16827 {
16828  SCIP_COL** lpicols;
16829  SCIP_ROW** lpirows;
16830  SCIP_Real* dualfarkas;
16831  int nlpicols;
16832  int nlpirows;
16833  int c;
16834  int r;
16835 
16836  assert(lp != NULL);
16837  assert(lp->flushed);
16838  assert(lp->solved);
16839  assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
16840  assert(set != NULL);
16841  assert(stat != NULL);
16842  assert(lp->validfarkaslp <= stat->lpcount);
16843 
16844  /* check if the values are already calculated */
16845  if( lp->validfarkaslp == stat->lpcount )
16846  return SCIP_OKAY;
16847  lp->validfarkaslp = stat->lpcount;
16848 
16849  /* get temporary memory */
16850  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
16851 
16852  /* get dual Farkas infeasibility proof */
16853  SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
16854 
16855  lpicols = lp->lpicols;
16856  lpirows = lp->lpirows;
16857  nlpicols = lp->nlpicols;
16858  nlpirows = lp->nlpirows;
16859 
16860  /* store infeasibility proof in rows */
16861  SCIPdebugMessage("LP is infeasible:\n");
16862  for( r = 0; r < nlpirows; ++r )
16863  {
16864  SCIPdebugMessage(" row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
16865  lpirows[r]->dualfarkas = dualfarkas[r];
16866  lpirows[r]->dualsol = SCIP_INVALID;
16867  lpirows[r]->activity = 0.0;
16868  lpirows[r]->validactivitylp = -1L;
16869  lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
16870  }
16871 
16872  /* set columns as invalid */
16873  for( c = 0; c < nlpicols; ++c )
16874  {
16875  lpicols[c]->primsol = SCIP_INVALID;
16876  lpicols[c]->redcost = SCIP_INVALID;
16877  lpicols[c]->validredcostlp = -1L;
16878  lpicols[c]->validfarkaslp = -1L;
16879  }
16880 
16881  /* free temporary memory */
16882  SCIPsetFreeBufferArray(set, &dualfarkas);
16883 
16884  return SCIP_OKAY;
16885 }
16886 
16887 /** get number of iterations used in last LP solve */
16889  SCIP_LP* lp, /**< current LP data */
16890  int* iterations /**< pointer to store the iteration count */
16891  )
16892 {
16893  assert(lp != NULL);
16894 
16895  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
16896 
16897  return SCIP_OKAY;
16898 }
16899 
16900 /** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
16901  * resets age of non-zero columns and sharp rows
16902  */
16904  SCIP_LP* lp, /**< current LP data */
16905  SCIP_STAT* stat /**< problem statistics */
16906  )
16907 {
16908  SCIP_COL** lpicols;
16909  SCIP_ROW** lpirows;
16910  int nlpicols;
16911  int nlpirows;
16912  int c;
16913  int r;
16914 
16915  assert(lp != NULL);
16916  assert(lp->flushed);
16917  assert(lp->solved);
16918  assert(lp->nlpicols == lp->ncols);
16919  assert(lp->nlpirows == lp->nrows);
16920  assert(stat != NULL);
16921  assert(lp->validsollp == stat->lpcount);
16922 
16923  SCIPdebugMessage("updating LP ages\n");
16924 
16925  lpicols = lp->lpicols;
16926  lpirows = lp->lpirows;
16927  nlpicols = lp->nlpicols;
16928  nlpirows = lp->nlpirows;
16929 
16930  for( c = 0; c < nlpicols; ++c )
16931  {
16932  assert(lpicols[c] == lp->cols[c]);
16933  if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
16934  lpicols[c]->age++;
16935  else
16936  lpicols[c]->age = 0;
16937  /*debugMessage(" -> col <%s>: primsol=%f, age=%d\n",
16938  SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
16939  }
16940 
16941  for( r = 0; r < nlpirows; ++r )
16942  {
16943  lpirows[r]->nlpsaftercreation++;
16944  assert(lpirows[r] == lp->rows[r]);
16945 
16946  if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
16947  lpirows[r]->age++;
16948  else
16949  {
16950  lpirows[r]->activeinlpcounter++;
16951  lpirows[r]->age = 0;
16952  }
16953  /*debugMessage(" -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
16954  }
16955 
16956  return SCIP_OKAY;
16957 }
16958 
16959 /* deletes the marked columns from the LP and the LP interface */
16960 static
16962  SCIP_LP* lp, /**< current LP data */
16963  SCIP_SET* set, /**< global SCIP settings */
16964  int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
16965  )
16966 {
16967  SCIP_COL* col;
16968  int ncols;
16969  int c;
16970 
16971  assert(lp != NULL);
16972  assert(lp->flushed);
16973  assert(lp->ncols == lp->nlpicols);
16974  assert(!lp->diving);
16975  assert(coldstat != NULL);
16976  assert(lp->nlazycols <= lp->ncols);
16977 
16978  ncols = lp->ncols;
16979 
16980  /* delete columns in LP solver */
16981  SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
16982 
16983  /* update LP data respectively */
16984  for( c = 0; c < ncols; ++c )
16985  {
16986  col = lp->cols[c];
16987  assert(col != NULL);
16988  assert(col == lp->lpicols[c]);
16989  assert(coldstat[c] <= c);
16990  col->lppos = coldstat[c];
16991  if( coldstat[c] == -1 )
16992  {
16993  assert(col->removable);
16994 
16995  /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
16996  * function vector norms
16997  */
16998  markColDeleted(col);
16999  colUpdateDelLP(col, set);
17000  lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
17001  col->lpdepth = -1;
17002 
17003  lp->cols[c] = NULL;
17004  lp->lpicols[c] = NULL;
17005  lp->ncols--;
17006  lp->nremovablecols--;
17007  lp->nlpicols--;
17008  }
17009  else if( coldstat[c] < c )
17010  {
17011  assert(lp->cols[coldstat[c]] == NULL);
17012  assert(lp->lpicols[coldstat[c]] == NULL);
17013  lp->cols[coldstat[c]] = col;
17014  lp->lpicols[coldstat[c]] = col;
17015  lp->cols[coldstat[c]]->lppos = coldstat[c];
17016  lp->cols[coldstat[c]]->lpipos = coldstat[c];
17017  lp->cols[c] = NULL;
17018  lp->lpicols[c] = NULL;
17019  }
17020  }
17021 
17022  /* remove columns which are deleted from the lazy column array */
17023  c = 0;
17024  while( c < lp->nlazycols )
17025  {
17026  if( lp->lazycols[c]->lpipos < 0 )
17027  {
17028  lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
17029  lp->nlazycols--;
17030  }
17031  else
17032  c++;
17033  }
17034 
17035  /* mark LP to be unsolved */
17036  if( lp->ncols < ncols )
17037  {
17038  assert(lp->ncols == lp->nlpicols);
17039  assert(lp->nchgcols == 0);
17040  assert(lp->flushed);
17041 
17042  lp->lpifirstchgcol = lp->nlpicols;
17043 
17044  /* mark the current solution invalid */
17045  lp->solved = FALSE;
17046  lp->primalfeasible = FALSE;
17047  lp->lpobjval = SCIP_INVALID;
17049  }
17050 
17051  checkLazyColArray(lp, set);
17052  checkLinks(lp);
17053 
17054  return SCIP_OKAY;
17055 }
17056 
17057 /* deletes the marked rows from the LP and the LP interface */
17058 static
17060  SCIP_LP* lp, /**< current LP data */
17061  BMS_BLKMEM* blkmem, /**< block memory buffers */
17062  SCIP_SET* set, /**< global SCIP settings */
17063  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17064  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17065  int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
17066  )
17067 {
17068  SCIP_ROW* row;
17069  int nrows;
17070  int r;
17071 
17072  assert(lp != NULL);
17073  assert(lp->flushed);
17074  assert(lp->nrows == lp->nlpirows);
17075  assert(!lp->diving);
17076  assert(rowdstat != NULL);
17077 
17078  nrows = lp->nrows;
17079 
17080  /* delete rows in LP solver */
17081  SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
17082 
17083  /* update LP data respectively */
17084  for( r = 0; r < nrows; ++r )
17085  {
17086  row = lp->rows[r];
17087  assert(row == lp->lpirows[r]);
17088  assert(rowdstat[r] <= r);
17089  assert(row != NULL);
17090  row->lppos = rowdstat[r];
17091  if( rowdstat[r] == -1 )
17092  {
17093  if( row->removable )
17094  lp->nremovablerows--;
17095 
17096  /* mark row to be deleted from the LPI and update row arrays of all linked columns */
17097  markRowDeleted(row);
17098  rowUpdateDelLP(row);
17099  row->lpdepth = -1;
17100 
17101  /* check, if row deletion events are tracked
17102  * if so, issue ROWDELETEDLP event
17103  */
17104  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
17105  {
17106  SCIP_EVENT* event;
17107 
17108  SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
17109  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
17110  }
17111 
17112  SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
17113  SCIProwUnlock(lp->rows[r]);
17114  SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
17115  assert(lp->lpirows[r] == NULL);
17116  assert(lp->rows[r] == NULL);
17117  lp->nrows--;
17118  lp->nlpirows--;
17119  }
17120  else if( rowdstat[r] < r )
17121  {
17122  assert(lp->rows[rowdstat[r]] == NULL);
17123  assert(lp->lpirows[rowdstat[r]] == NULL);
17124  lp->rows[rowdstat[r]] = row;
17125  lp->lpirows[rowdstat[r]] = row;
17126  lp->rows[rowdstat[r]]->lppos = rowdstat[r];
17127  lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
17128  lp->rows[r] = NULL;
17129  lp->lpirows[r] = NULL;
17130  }
17131  }
17132 
17133  /* mark LP to be unsolved */
17134  if( lp->nrows < nrows )
17135  {
17136  assert(lp->nrows == lp->nlpirows);
17137  assert(lp->nchgrows == 0);
17138  assert(lp->flushed);
17139 
17140  lp->lpifirstchgrow = lp->nlpirows;
17141 
17142  /* mark the current solution invalid */
17143  lp->solved = FALSE;
17144  lp->dualfeasible = FALSE;
17145  lp->lpobjval = SCIP_INVALID;
17147  }
17148 
17149  checkLinks(lp);
17150 
17151  return SCIP_OKAY;
17152 }
17153 
17154 /** removes all non-basic columns, that are too old, beginning with the given firstcol */
17155 static
17157  SCIP_LP* lp, /**< current LP data */
17158  SCIP_SET* set, /**< global SCIP settings */
17159  SCIP_STAT* stat, /**< problem statistics */
17160  int firstcol /**< first column to check for clean up */
17161  )
17162 {
17163  SCIP_COL** cols;
17164 #ifndef NDEBUG
17165  SCIP_COL** lpicols;
17166 #endif
17167  int* coldstat;
17168  int ncols;
17169  int ndelcols;
17170  int c;
17171 
17172  assert(lp != NULL);
17173  assert(lp->flushed);
17174  assert(lp->ncols == lp->nlpicols);
17175  assert(lp->nremovablecols <= lp->ncols);
17176  assert(!lp->diving);
17177  assert(set != NULL);
17178  assert(stat != NULL);
17179 
17180  if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
17181  return SCIP_OKAY;
17182 
17183  ncols = lp->ncols;
17184  cols = lp->cols;
17185 #ifndef NDEBUG
17186  lpicols = lp->lpicols;
17187 #endif
17188 
17189  /* get temporary memory */
17190  SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
17191 
17192  /* mark obsolete columns to be deleted */
17193  ndelcols = 0;
17194  BMSclearMemoryArray(coldstat, ncols);
17195  for( c = firstcol; c < ncols; ++c )
17196  {
17197  assert(cols[c] == lpicols[c]);
17198  assert(cols[c]->lppos == c);
17199  assert(cols[c]->lpipos == c);
17200  if( cols[c]->removable
17201  && 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 */
17202  && cols[c]->age > set->lp_colagelimit
17204  && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
17205  {
17206  assert(cols[c]->primsol == 0.0);
17207  coldstat[c] = 1;
17208  ndelcols++;
17209  cols[c]->obsoletenode = stat->nnodes;
17210  SCIPdebugMessage("removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
17211  SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
17212  }
17213  }
17214 
17215  SCIPdebugMessage("removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
17216 
17217  /* delete the marked columns in the LP solver interface, update the LP respectively */
17218  if( ndelcols > 0 )
17219  {
17220  SCIP_CALL( lpDelColset(lp, set, coldstat) );
17221  }
17222  assert(lp->ncols == ncols - ndelcols);
17223 
17224  /* release temporary memory */
17225  SCIPsetFreeBufferArray(set, &coldstat);
17226 
17227  return SCIP_OKAY;
17228 }
17229 
17230 /** removes all basic rows, that are too old, beginning with the given firstrow */
17231 static
17233  SCIP_LP* lp, /**< current LP data */
17234  BMS_BLKMEM* blkmem, /**< block memory buffers */
17235  SCIP_SET* set, /**< global SCIP settings */
17236  SCIP_STAT* stat, /**< problem statistics */
17237  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17238  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17239  int firstrow /**< first row to check for clean up */
17240  )
17241 {
17242  SCIP_ROW** rows;
17243 #ifndef NDEBUG
17244  SCIP_ROW** lpirows;
17245 #endif
17246  int* rowdstat;
17247  int nrows;
17248  int ndelrows;
17249  int r;
17250 
17251  assert(lp != NULL);
17252  assert(lp->flushed);
17253  assert(lp->nrows == lp->nlpirows);
17254  assert(lp->nremovablerows <= lp->nrows);
17255  assert(!lp->diving);
17256  assert(set != NULL);
17257  assert(stat != NULL);
17258 
17259  if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
17260  return SCIP_OKAY;
17261 
17262  nrows = lp->nrows;
17263  rows = lp->rows;
17264 #ifndef NDEBUG
17265  lpirows = lp->lpirows;
17266 #endif
17267 
17268  /* get temporary memory */
17269  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
17270 
17271  /* mark obsolete rows to be deleted */
17272  ndelrows = 0;
17273  BMSclearMemoryArray(rowdstat, nrows);
17274  for( r = firstrow; r < nrows; ++r )
17275  {
17276  assert(rows[r] == lpirows[r]);
17277  assert(rows[r]->lppos == r);
17278  assert(rows[r]->lpipos == r);
17279  if( rows[r]->removable
17280  && 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 */
17281  && rows[r]->age > set->lp_rowagelimit
17283  {
17284  rowdstat[r] = 1;
17285  ndelrows++;
17286  rows[r]->obsoletenode = stat->nnodes;
17287  SCIPdebugMessage("removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
17288  rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
17289  }
17290  }
17291 
17292  SCIPdebugMessage("removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
17293 
17294  /* delete the marked rows in the LP solver interface, update the LP respectively */
17295  if( ndelrows > 0 )
17296  {
17297  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
17298  }
17299  assert(lp->nrows == nrows - ndelrows);
17300 
17301  /* release temporary memory */
17302  SCIPsetFreeBufferArray(set, &rowdstat);
17303 
17304  return SCIP_OKAY;
17305 }
17306 
17307 /** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
17309  SCIP_LP* lp, /**< current LP data */
17310  BMS_BLKMEM* blkmem, /**< block memory buffers */
17311  SCIP_SET* set, /**< global SCIP settings */
17312  SCIP_STAT* stat, /**< problem statistics */
17313  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17314  SCIP_EVENTFILTER* eventfilter /**< global event filter */
17315  )
17316 {
17317  assert(lp != NULL);
17318  assert(lp->solved);
17319  assert(!lp->diving);
17321  assert(set != NULL);
17322 
17323  SCIPdebugMessage("removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
17324  lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
17325 
17326  if( lp->firstnewcol < lp->ncols )
17327  {
17328  SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
17329  }
17330  if( lp->firstnewrow < lp->nrows )
17331  {
17332  SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
17333  }
17334 
17335  return SCIP_OKAY;
17336 }
17337 
17338 /** removes all non-basic columns and basic rows in whole LP, that are too old */
17340  SCIP_LP* lp, /**< current LP data */
17341  BMS_BLKMEM* blkmem, /**< block memory buffers */
17342  SCIP_SET* set, /**< global SCIP settings */
17343  SCIP_STAT* stat, /**< problem statistics */
17344  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17345  SCIP_EVENTFILTER* eventfilter /**< global event filter */
17346  )
17347 {
17348  assert(lp != NULL);
17349  assert(lp->solved);
17350  assert(!lp->diving);
17352  assert(set != NULL);
17353 
17354  SCIPdebugMessage("removing all obsolete columns and rows\n");
17355 
17356  if( 0 < lp->ncols )
17357  {
17358  SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
17359  }
17360  if( 0 < lp->nrows )
17361  {
17362  SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
17363  }
17364 
17365  return SCIP_OKAY;
17366 }
17367 
17368 /** removes all non-basic columns at 0.0 beginning with the given firstcol */
17369 static
17371  SCIP_LP* lp, /**< current LP data */
17372  SCIP_SET* set, /**< global SCIP settings */
17373  SCIP_STAT* stat, /**< problem statistics */
17374  int firstcol /**< first column to check for clean up */
17375  )
17376 {
17377  SCIP_COL** cols;
17378  SCIP_COL** lpicols;
17379  int* coldstat;
17380  int ncols;
17381  int ndelcols;
17382  int c;
17383 
17384  assert(lp != NULL);
17385  assert(lp->flushed);
17386  assert(lp->ncols == lp->nlpicols);
17387  assert(!lp->diving);
17388  assert(stat != NULL);
17389  assert(lp->validsollp == stat->lpcount);
17390  assert(0 <= firstcol && firstcol < lp->ncols);
17391 
17392  if( lp->nremovablecols == 0 || !lp->solisbasic )
17393  return SCIP_OKAY;
17394 
17395  ncols = lp->ncols;
17396  cols = lp->cols;
17397  lpicols = lp->lpicols;
17398 
17399  /* get temporary memory */
17400  SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
17401 
17402  /* mark unused columns to be deleted */
17403  ndelcols = 0;
17404  BMSclearMemoryArray(coldstat, ncols);
17405  for( c = firstcol; c < ncols; ++c )
17406  {
17407  assert(cols[c] == lpicols[c]);
17408  assert(cols[c]->lppos == c);
17409  assert(cols[c]->lpipos == c);
17410  if( lpicols[c]->removable
17411  && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
17412  && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
17413  && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
17414  {
17415  coldstat[c] = 1;
17416  ndelcols++;
17417  }
17418  }
17419 
17420  SCIPdebugMessage("removing %d/%d unused columns from LP\n", ndelcols, ncols);
17421 
17422  /* delete the marked columns in the LP solver interface, update the LP respectively */
17423  if( ndelcols > 0 )
17424  {
17425  SCIP_CALL( lpDelColset(lp, set, coldstat) );
17426  }
17427  assert(lp->ncols == ncols - ndelcols);
17428 
17429  /* release temporary memory */
17430  SCIPsetFreeBufferArray(set, &coldstat);
17431 
17432  return SCIP_OKAY;
17433 }
17434 
17435 /** removes all basic rows beginning with the given firstrow */
17436 static
17438  SCIP_LP* lp, /**< current LP data */
17439  BMS_BLKMEM* blkmem, /**< block memory buffers */
17440  SCIP_SET* set, /**< global SCIP settings */
17441  SCIP_STAT* stat, /**< problem statistics */
17442  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17443  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17444  int firstrow /**< first row to check for clean up */
17445  )
17446 {
17447 #ifndef NDEBUG
17448  SCIP_ROW** rows;
17449 #endif
17450  SCIP_ROW** lpirows;
17451  int* rowdstat;
17452  int nrows;
17453  int ndelrows;
17454  int r;
17455 
17456  assert(lp != NULL);
17457  assert(lp->flushed);
17458  assert(lp->ncols == lp->nlpicols);
17459  assert(lp->nrows == lp->nlpirows);
17460  assert(!lp->diving);
17461  assert(stat != NULL);
17462  assert(lp->validsollp == stat->lpcount);
17463  assert(0 <= firstrow && firstrow < lp->nrows);
17464 
17465  if( lp->nremovablerows == 0 || !lp->solisbasic )
17466  return SCIP_OKAY;
17467 
17468 #ifndef NDEBUG
17469  rows = lp->rows;
17470 #endif
17471  nrows = lp->nrows;
17472  lpirows = lp->lpirows;
17473 
17474  /* get temporary memory */
17475  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
17476 
17477  /* mark unused rows to be deleted */
17478  ndelrows = 0;
17479  BMSclearMemoryArray(rowdstat, nrows);
17480  for( r = firstrow; r < nrows; ++r )
17481  {
17482  assert(rows[r] == lpirows[r]);
17483  assert(rows[r]->lppos == r);
17484  assert(rows[r]->lpipos == r);
17485  if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
17486  {
17487  rowdstat[r] = 1;
17488  ndelrows++;
17489  }
17490  }
17491 
17492  SCIPdebugMessage("removing %d/%d unused rows from LP\n", ndelrows, nrows);
17493 
17494  /* delete the marked rows in the LP solver interface, update the LP respectively */
17495  if( ndelrows > 0 )
17496  {
17497  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
17498  }
17499  assert(lp->nrows == nrows - ndelrows);
17500 
17501  /* release temporary memory */
17502  SCIPsetFreeBufferArray(set, &rowdstat);
17503 
17504  return SCIP_OKAY;
17505 }
17506 
17507 /** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
17509  SCIP_LP* lp, /**< current LP data */
17510  BMS_BLKMEM* blkmem, /**< block memory buffers */
17511  SCIP_SET* set, /**< global SCIP settings */
17512  SCIP_STAT* stat, /**< problem statistics */
17513  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17514  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17515  SCIP_Bool root /**< are we at the root node? */
17516  )
17517 {
17518  SCIP_Bool cleanupcols;
17519  SCIP_Bool cleanuprows;
17520 
17521  assert(lp != NULL);
17522  assert(lp->solved);
17523  assert(!lp->diving);
17525  assert(set != NULL);
17526 
17527  /* check, if we want to clean up the columns and rows */
17528  cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
17529  cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
17530 
17531  SCIPdebugMessage("removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
17532  lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
17533 
17534  if( cleanupcols && lp->firstnewcol < lp->ncols )
17535  {
17536  SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
17537  }
17538  if( cleanuprows && lp->firstnewrow < lp->nrows )
17539  {
17540  SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
17541  }
17542 
17543  return SCIP_OKAY;
17544 }
17545 
17546 /** removes all non-basic columns at 0.0 and basic rows in the whole LP */
17548  SCIP_LP* lp, /**< current LP data */
17549  BMS_BLKMEM* blkmem, /**< block memory buffers */
17550  SCIP_SET* set, /**< global SCIP settings */
17551  SCIP_STAT* stat, /**< problem statistics */
17552  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17553  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17554  SCIP_Bool root /**< are we at the root node? */
17555  )
17556 {
17557  SCIP_Bool cleanupcols;
17558  SCIP_Bool cleanuprows;
17559 
17560  assert(lp != NULL);
17561  assert(lp->solved);
17562  assert(!lp->diving);
17564  assert(set != NULL);
17565 
17566  /* check, if we want to clean up the columns and rows */
17567  cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
17568  cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
17569 
17570  SCIPdebugMessage("removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
17571  cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
17572 
17573  if( cleanupcols && 0 < lp->ncols )
17574  {
17575  SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
17576  }
17577  if( cleanuprows && 0 < lp->nrows )
17578  {
17579  SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
17580  }
17581 
17582  return SCIP_OKAY;
17583 }
17584 
17585 /** removes all redundant rows that were added at the current node */
17587  SCIP_LP* lp, /**< current LP data */
17588  BMS_BLKMEM* blkmem, /**< block memory buffers */
17589  SCIP_SET* set, /**< global SCIP settings */
17590  SCIP_STAT* stat, /**< problem statistics */
17591  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17592  SCIP_EVENTFILTER* eventfilter /**< global event filter */
17593  )
17594 {
17595 #ifndef NDEBUG
17596  SCIP_ROW** rows;
17597 #endif
17598  SCIP_ROW** lpirows;
17599  int* rowdstat;
17600  int nrows;
17601  int ndelrows;
17602  int r;
17603 
17604  assert(lp != NULL);
17605  assert(lp->flushed);
17606  assert(lp->ncols == lp->nlpicols);
17607  assert(lp->nrows == lp->nlpirows);
17608  assert(!lp->diving);
17609  assert(stat != NULL);
17610  assert(lp->validsollp == stat->lpcount);
17611  assert(lp->firstnewrow <= lp->nrows);
17612 
17613  if( lp->firstnewrow == lp->nrows )
17614  return SCIP_OKAY;
17615 
17616 #ifndef NDEBUG
17617  rows = lp->rows;
17618 #endif
17619  nrows = lp->nrows;
17620  lpirows = lp->lpirows;
17621 
17622  /* get temporary memory */
17623  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
17624 
17625  /* mark redundant rows to be deleted (only delete basic rows!) */
17626  ndelrows = 0;
17627  BMSclearMemoryArray(rowdstat, nrows);
17628  for( r = lp->firstnewrow; r < nrows; ++r )
17629  {
17630  assert(rows[r] == lpirows[r]);
17631  assert(rows[r]->lppos == r);
17632  assert(rows[r]->lpipos == r);
17633  if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
17634  && SCIProwIsRedundant(lpirows[r], set, stat) )
17635  {
17636  SCIPdebugMessage("basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
17637  SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
17638  SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
17639  rowdstat[r] = 1;
17640  ndelrows++;
17641  }
17642  }
17643 
17644  SCIPdebugMessage("removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
17645 
17646  /* delete the marked rows in the LP solver interface, update the LP respectively */
17647  if( ndelrows > 0 )
17648  {
17649  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
17650  }
17651  assert(lp->nrows == nrows - ndelrows);
17652 
17653  /* release temporary memory */
17654  SCIPsetFreeBufferArray(set, &rowdstat);
17655 
17656  return SCIP_OKAY;
17657 }
17658 
17659 /** initiates LP diving */
17661  SCIP_LP* lp, /**< current LP data */
17662  BMS_BLKMEM* blkmem, /**< block memory */
17663  SCIP_SET* set, /**< global SCIP settings */
17664  SCIP_STAT* stat /**< problem statistics */
17665  )
17666 {
17667  int c;
17668  int r;
17669 
17670  assert(lp != NULL);
17671  assert(lp->flushed || !lp->solved);
17672  assert(!lp->diving);
17673  assert(!lp->probing);
17674  assert(lp->divelpistate == NULL);
17675  assert(lp->divelpwasprimfeas);
17676  assert(lp->divelpwasdualfeas);
17677  assert(lp->validsollp <= stat->lpcount);
17678  assert(blkmem != NULL);
17679  assert(set != NULL);
17680  assert(lp->ndivechgsides == 0);
17681 
17682  SCIPdebugMessage("diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
17683  lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
17684 
17685 #ifndef NDEBUG
17686  for( c = 0; c < lp->ncols; ++c )
17687  {
17688  assert(lp->cols[c] != NULL);
17689  assert(lp->cols[c]->var != NULL);
17690  assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
17691  assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
17692  assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
17693  assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
17694  assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
17695  }
17696 #endif
17697 
17698  /* save current LPI state (basis information) */
17699  SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
17701  lp->divelpwasdualfeas = lp->dualfeasible;
17702 
17703  /* save current LP values dependent on the solution */
17704  SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
17705  assert(lp->storedsolvals != NULL);
17706  if( !set->lp_resolverestore && lp->solved )
17707  {
17708  SCIP_Bool store = TRUE;
17709 
17710  switch ( lp->lpsolstat )
17711  {
17713  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
17714  assert(lp->validsollp == stat->lpcount);
17715  break;
17717  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
17718  assert(lp->validsollp == stat->lpcount);
17719  break;
17723  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
17724  assert(lp->validsollp == stat->lpcount);
17725  break;
17727  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
17728  break;
17730  case SCIP_LPSOLSTAT_ERROR:
17731  default:
17732  store = FALSE;
17733  }
17734 
17735  if ( store )
17736  {
17737  for( c = 0; c < lp->ncols; ++c )
17738  {
17739  SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
17740  }
17741  for( r = 0; r < lp->nrows; ++r )
17742  {
17744  }
17745  }
17746  }
17747 
17748  /* store LPI iteration limit */
17750 
17751  /* store current number of rows */
17752  lp->ndivingrows = lp->nrows;
17753 
17754  /* switch to diving mode */
17755  lp->diving = TRUE;
17756 
17757  return SCIP_OKAY;
17758 }
17759 
17760 /** quits LP diving and resets bounds and objective values of columns to the current node's values */
17762  SCIP_LP* lp, /**< current LP data */
17763  BMS_BLKMEM* blkmem, /**< block memory */
17764  SCIP_SET* set, /**< global SCIP settings */
17765  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17766  SCIP_STAT* stat, /**< problem statistics */
17767  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17768  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17769  SCIP_PROB* prob, /**< problem data */
17770  SCIP_VAR** vars, /**< array with all active variables */
17771  int nvars /**< number of active variables */
17772  )
17773 {
17774  SCIP_VAR* var;
17775  int v;
17776 
17777  assert(lp != NULL);
17778  assert(lp->diving);
17779  assert(blkmem != NULL);
17780  assert(nvars == 0 || vars != NULL);
17781 
17782  SCIPdebugMessage("diving ended (LP flushed: %u, solstat: %d)\n",
17783  lp->flushed, SCIPlpGetSolstat(lp));
17784 
17785  /* reset all columns' objective values and bounds to its original values */
17786  for( v = 0; v < nvars; ++v )
17787  {
17788  var = vars[v];
17789  assert(var != NULL);
17791  {
17792  SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, SCIPvarGetObj(var)) );
17793  SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, SCIPvarGetLbLocal(var)) );
17794  SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, SCIPvarGetUbLocal(var)) );
17795  }
17796  }
17797 
17798  /* remove rows which were added in diving mode */
17799  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
17800 
17801  /* undo changes to left hand sides and right hand sides */
17802  while( lp->ndivechgsides > 0 )
17803  {
17804  SCIP_Real oldside;
17805  SCIP_SIDETYPE sidetype;
17806  SCIP_ROW* row;
17807 
17808  lp->ndivechgsides--;
17809  oldside = lp->divechgsides[lp->ndivechgsides];
17810  sidetype = lp->divechgsidetypes[lp->ndivechgsides];
17811  row = lp->divechgrows[lp->ndivechgsides];
17812 
17813  if( sidetype == SCIP_SIDETYPE_LEFT )
17814  {
17815  SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
17816  }
17817  else
17818  {
17819  SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
17820  }
17821  }
17822 
17823  /* restore LPI iteration limit */
17825 
17826  /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
17827  * happens
17828  */
17829  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, lp->divelpistate,
17831  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
17832  lp->divelpwasprimfeas = TRUE;
17833  lp->divelpwasdualfeas = TRUE;
17834  assert(lp->divelpistate == NULL);
17835 
17836  /* switch to standard (non-diving) mode */
17837  lp->diving = FALSE;
17838  lp->divingobjchg = FALSE;
17839 
17840  /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
17841  * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
17842  * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
17843  * the parameter resolverestore to TRUE
17844  * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
17845  */
17846  assert(lp->storedsolvals != NULL);
17847  if( lp->storedsolvals->lpissolved
17848  && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL) )
17849  {
17850  SCIP_Bool lperror;
17851 
17852  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) );
17853  if( lperror )
17854  {
17855  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
17856  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles while resolving LP %" SCIP_LONGINT_FORMAT " after diving\n", stat->nnodes, stat->nlps);
17857  lp->resolvelperror = TRUE;
17858  }
17863  {
17864  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
17865  "LP was not resolved to a sufficient status after diving\n");
17866  lp->resolvelperror = TRUE;
17867  }
17868  }
17869  /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
17870  * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
17871  * re-solve as above can lead to a different LP status
17872  */
17873  else
17874  {
17875  int c;
17876  int r;
17877 
17878  /* if there are lazy bounds, remove them from the LP */
17879  if( lp->nlazycols > 0 )
17880  {
17881  /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
17882  * first resolve LP?
17883  */
17884  SCIP_CALL( updateLazyBounds(lp, set) );
17885  assert(lp->diving == lp->divinglazyapplied);
17886 
17887  /* flush changes to the LP solver */
17888  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
17889  }
17890 
17891  /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
17892  stat->lpcount++;
17893 
17894  /* restore LP solution values in lp data, columns and rows */
17895  if( lp->storedsolvals->lpissolved &&
17902  )
17903  {
17904  SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
17905 
17906  for( c = 0; c < lp->ncols; ++c )
17907  {
17908  SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
17909  }
17910  for( r = 0; r < lp->nrows; ++r )
17911  {
17912  SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
17913  }
17914  }
17915  else
17916  {
17917  SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
17918  }
17919  }
17920 
17921 #ifndef NDEBUG
17922  {
17923  int c;
17924  for( c = 0; c < lp->ncols; ++c )
17925  {
17926  assert(lp->cols[c] != NULL);
17927  assert(lp->cols[c]->var != NULL);
17928  assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
17929  assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
17930  assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
17931  assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
17932  assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
17933  }
17934  }
17935 #endif
17936 
17937  return SCIP_OKAY;
17938 }
17939 
17940 #define DIVESTACKGROWFACT 1.5
17941 
17942 /** records a current row side such that any change will be undone after diving */
17944  SCIP_LP* lp, /**< LP data object */
17945  SCIP_ROW* row, /**< row affected by the change */
17946  SCIP_SIDETYPE sidetype /**< side type */
17947  )
17948 {
17949  assert(lp != NULL);
17950  assert(row != NULL);
17951 
17952  if( lp->ndivechgsides == lp->divechgsidessize )
17953  {
17955  }
17956  assert(lp->ndivechgsides < lp->divechgsidessize);
17957 
17958  lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
17959  lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
17960  lp->divechgrows[lp->ndivechgsides] = row;
17961  lp->ndivechgsides++;
17962 
17963  return SCIP_OKAY;
17964 }
17965 
17966 /** informs the LP that probing mode was initiated */
17968  SCIP_LP* lp /**< current LP data */
17969  )
17970 {
17971  assert(lp != NULL);
17972  assert(!lp->probing);
17973  assert(!lp->strongbranching);
17974  assert(!lp->strongbranchprobing);
17975 
17976  lp->probing = TRUE;
17977 
17978  return SCIP_OKAY;
17979 }
17980 
17981 /** informs the LP that probing mode was finished */
17983  SCIP_LP* lp /**< current LP data */
17984  )
17985 {
17986  assert(lp != NULL);
17987  assert(lp->probing);
17988  assert(!lp->strongbranching);
17989  assert(!lp->strongbranchprobing);
17990 
17991  lp->probing = FALSE;
17992 
17993  return SCIP_OKAY;
17994 }
17995 
17996 /** informs the LP that the probing mode is now used for strongbranching */
17998  SCIP_LP* lp /**< current LP data */
17999  )
18000 {
18001  assert(lp != NULL);
18002  assert(lp->probing);
18003  assert(!lp->strongbranching);
18004  assert(!lp->strongbranchprobing);
18005 
18006  lp->strongbranchprobing = TRUE;
18007 }
18008 
18009 /** informs the LP that the probing mode is not used for strongbranching anymore */
18011  SCIP_LP* lp /**< current LP data */
18012  )
18013 {
18014  assert(lp != NULL);
18015  assert(lp->probing);
18016  assert(!lp->strongbranching);
18017  assert(lp->strongbranchprobing);
18018 
18019  lp->strongbranchprobing = FALSE;
18020 }
18021 
18022 /** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
18023  * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
18024  * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
18025  * we have only left hand sides):
18026  * min{cx | b <= Ax, lb <= x <= ub}
18027  * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
18028  * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
18029  * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
18030  * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
18031  */
18032 static
18034  SCIP_LP* lp, /**< current LP data */
18035  SCIP_SET* set, /**< global SCIP settings */
18036  SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
18037  SCIP_Real* bound /**< result of interval arithmetic minimization */
18038  )
18039 {
18040  SCIP_INTERVAL* yinter;
18041  SCIP_INTERVAL b;
18042  SCIP_INTERVAL ytb;
18043  SCIP_INTERVAL prod;
18044  SCIP_INTERVAL diff;
18045  SCIP_INTERVAL x;
18046  SCIP_INTERVAL minprod;
18047  SCIP_INTERVAL a;
18048  SCIP_ROW* row;
18049  SCIP_COL* col;
18050  SCIP_Real y;
18051  SCIP_Real c;
18052  int i;
18053  int j;
18054 
18055  assert(lp != NULL);
18056  assert(lp->solved);
18057  assert(set != NULL);
18058  assert(bound != NULL);
18059 
18060  /* allocate buffer for storing y in interval arithmetic */
18061  SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
18062 
18063  /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
18064  SCIPintervalSet(&ytb, 0.0);
18065  for( j = 0; j < lp->nrows; ++j )
18066  {
18067  row = lp->rows[j];
18068  assert(row != NULL);
18069 
18070  y = (usefarkas ? row->dualfarkas : row->dualsol);
18071 
18072  if( SCIPsetIsFeasPositive(set, y) )
18073  {
18074  SCIPintervalSet(&yinter[j], y);
18075  SCIPintervalSet(&b, row->lhs - row->constant);
18076  }
18077  else if( SCIPsetIsFeasNegative(set, y) )
18078  {
18079  SCIPintervalSet(&yinter[j], y);
18080  SCIPintervalSet(&b, row->rhs - row->constant);
18081  }
18082  else
18083  {
18084  SCIPintervalSet(&yinter[j], 0.0);
18085  SCIPintervalSet(&b, 0.0);
18086  }
18087 
18088  SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
18089  SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
18090  }
18091 
18092  /* calculate min{(c^T - y^TA)x} */
18093  SCIPintervalSet(&minprod, 0.0);
18094  for( j = 0; j < lp->ncols; ++j )
18095  {
18096  col = lp->cols[j];
18097  assert(col != NULL);
18098  assert(col->nunlinked == 0);
18099 
18101 
18102  c = usefarkas ? 0.0 : col->obj;
18103  SCIPintervalSet(&diff, c);
18104 
18105  for( i = 0; i < col->nlprows; ++i )
18106  {
18107  assert(col->rows[i] != NULL);
18108  assert(col->rows[i]->lppos >= 0);
18109  assert(col->linkpos[i] >= 0);
18110  SCIPintervalSet(&a, col->vals[i]);
18111  SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
18112  SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
18113  }
18114 
18115 #ifndef NDEBUG
18116  for( i = col->nlprows; i < col->len; ++i )
18117  {
18118  assert(col->rows[i] != NULL);
18119  assert(col->rows[i]->lppos == -1);
18120  assert(col->rows[i]->dualsol == 0.0);
18121  assert(col->rows[i]->dualfarkas == 0.0);
18122  assert(col->linkpos[i] >= 0);
18123  }
18124 #endif
18125 
18126  SCIPintervalSetBounds(&x, col->lb, col->ub);
18127  SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
18128  SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
18129  }
18130 
18131  /* add y^Tb */
18132  SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
18133 
18134  /* free buffer for storing y in interval arithmetic */
18135  SCIPsetFreeBufferArray(set, &yinter);
18136 
18137  *bound = SCIPintervalGetInf(minprod);
18138 
18139  return SCIP_OKAY;
18140 }
18141 
18142 /** gets proven lower (dual) bound of last LP solution */
18144  SCIP_LP* lp, /**< current LP data */
18145  SCIP_SET* set, /**< global SCIP settings */
18146  SCIP_Real* bound /**< pointer to store proven dual bound */
18147  )
18148 {
18149  SCIP_CALL( provedBound(lp, set, FALSE, bound) );
18150 
18151  SCIPdebugMessage("proved lower bound of LP: %.15g\n", *bound);
18152 
18153  return SCIP_OKAY;
18154 }
18155 
18156 /** gets proven dual bound of last LP solution */
18158  SCIP_LP* lp, /**< current LP data */
18159  SCIP_SET* set, /**< global SCIP settings */
18160  SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
18161  )
18162 {
18163  SCIP_Real bound;
18164 
18165  assert(proved != NULL);
18166 
18167  SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
18168 
18169  *proved = (bound > 0.0);
18170 
18171  SCIPdebugMessage("proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
18172 
18173  return SCIP_OKAY;
18174 }
18175 
18176 
18177 
18178 /** writes LP to a file */
18180  SCIP_LP* lp, /**< current LP data */
18181  const char* fname /**< file name */
18182  )
18183 {
18184  assert(lp != NULL);
18185  assert(lp->flushed);
18186  assert(fname != NULL);
18187 
18188  SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
18189 
18190  return SCIP_OKAY;
18191 }
18192 
18193 /** writes MIP relaxation of the current B&B node to a file */
18195  SCIP_LP* lp, /**< current LP data */
18196  SCIP_SET* set, /**< global SCIP settings */
18197  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18198  const char* fname, /**< file name */
18199  SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
18200  * troubles with reserved symbols? */
18201  SCIP_Bool origobj, /**< should the original objective function be used? */
18202  SCIP_OBJSENSE objsense, /**< objective sense */
18203  SCIP_Real objscale, /**< objective scaling factor */
18204  SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
18205  SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
18206  )
18207 {
18208  FILE* file;
18209  int i;
18210  int j;
18211  char rowname[SCIP_MAXSTRLEN];
18212  SCIP_Real coeff;
18213 
18214  assert(lp != NULL);
18215  assert(lp->flushed);
18216  assert(fname != NULL);
18217 
18218  SCIPdebugMessage("Start to write MIP to file <%s>\n", fname);
18219  file = fopen(fname, "w");
18220  if( file == NULL )
18221  {
18222  SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
18223  SCIPprintSysError(fname);
18224  return SCIP_FILECREATEERROR;
18225  }
18226 
18227  /* print comments */
18228  if( genericnames )
18229  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
18230  else
18231  {
18232  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
18233  SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
18234  }
18235 
18236  if( origobj && objoffset != 0.0 )
18237  {
18238  SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
18239  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
18240  }
18241 
18242  /* print objective function */
18243  /**@note the transformed problem in SCIP is always a minimization problem */
18244  if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
18245  SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
18246  else
18247  SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
18248 
18249  /* print objective */
18250  SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
18251  j = 0;
18252  for( i = 0; i < lp->ncols; ++i )
18253  {
18254  if( lp->cols[i]->obj != 0.0 )
18255  {
18256  coeff = lp->cols[i]->obj;
18257  if( origobj )
18258  {
18259  coeff *= (SCIP_Real) objsense;
18260  coeff *= objscale;
18261  }
18262 
18263  if( genericnames )
18264  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
18265  else
18266  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
18267 
18268  ++j;
18269  if( j % 10 == 0 )
18270  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
18271  }
18272  }
18273  /* add artificial variable 'objoffset' to transfer objective offset */
18274  if( origobj && objoffset != 0.0 )
18275  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
18276 
18277  /* print constraint section */
18278  SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
18279  for( i = 0; i < lp->nrows; i++ )
18280  {
18281  char type = 'i';
18282 
18283  /* skip removable rows if we want to write them as lazy constraints */
18284  if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
18285  continue;
18286 
18287  /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
18288  * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
18289  * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
18290  * type 'i' means: lhs and rhs are both infinite */
18291  if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18292  type = 'r';
18293  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18294  type = 'l';
18295  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
18296  type = 'e';
18297  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18298  type = 'b';
18299 
18300  /* print name of row */
18301  if( genericnames )
18302  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
18303  else
18304  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
18305 
18306  WRITEROW:
18307  switch( type )
18308  {
18309  case 'r':
18310  case 'l':
18311  case 'e':
18312  if( strlen(rowname) > 0 )
18313  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
18314  break;
18315  case 'i':
18316  SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
18317  SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
18318  SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
18319  type = 'b';
18320  /*lint -fallthrough*/
18321  case 'b':
18322  SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
18323  break;
18324  case 'B':
18325  SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
18326  break;
18327  default:
18328  SCIPerrorMessage("Undefined row type!\n");
18329  return SCIP_ERROR;
18330  }
18331 
18332  /* print coefficients and variables */
18333  for( j = 0; j < lp->rows[i]->nlpcols; ++j )
18334  {
18335  if( genericnames )
18336  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
18337  else
18338  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
18339 
18340  if( (j+1) % 10 == 0 )
18341  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
18342  }
18343 
18344  /* print right hand side */
18345  switch( type )
18346  {
18347  case 'b':
18348  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18349  type = 'B';
18350  goto WRITEROW;
18351  case 'l':
18352  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18353  break;
18354  case 'B':
18355  case 'r':
18356  SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
18357  break;
18358  case 'e':
18359  SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18360  break;
18361  default:
18362  SCIPerrorMessage("Undefined row type!\n");
18363  return SCIP_ERROR;
18364  }
18365  }
18366 
18367  if ( lazyconss )
18368  {
18369  /* print lazy constraint section */
18370  SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
18371  for( i = 0; i < lp->nrows; i++ )
18372  {
18373  char type = 'i';
18374 
18375  /* skip non-removable rows if we want to write lazy constraints */
18376  if ( ! SCIProwIsRemovable(lp->rows[i]) )
18377  continue;
18378 
18379  /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
18380  * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
18381  * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
18382  * type 'i' means: lhs and rhs are both infinite */
18383  if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18384  type = 'r';
18385  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18386  type = 'l';
18387  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
18388  type = 'e';
18389  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18390  type = 'b';
18391 
18392  /* print name of row */
18393  if( genericnames )
18394  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
18395  else
18396  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
18397 
18398  WRITELAZYROW:
18399  switch( type )
18400  {
18401  case 'r':
18402  case 'l':
18403  case 'e':
18404  if( strlen(rowname) > 0 )
18405  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
18406  break;
18407  case 'i':
18408  SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
18409  SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
18410  SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
18411  type = 'b';
18412  /*lint -fallthrough*/
18413  case 'b':
18414  SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
18415  break;
18416  case 'B':
18417  SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
18418  break;
18419  default:
18420  SCIPerrorMessage("Undefined row type!\n");
18421  return SCIP_ERROR;
18422  }
18423 
18424  /* print coefficients and variables */
18425  for( j = 0; j < lp->rows[i]->nlpcols; ++j )
18426  {
18427  if( genericnames )
18428  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
18429  else
18430  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
18431 
18432  if( (j+1) % 10 == 0 )
18433  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
18434  }
18435 
18436  /* print right hand side */
18437  switch( type )
18438  {
18439  case 'b':
18440  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18441  type = 'B';
18442  goto WRITELAZYROW;
18443  case 'l':
18444  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18445  break;
18446  case 'B':
18447  case 'r':
18448  SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
18449  break;
18450  case 'e':
18451  SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18452  break;
18453  default:
18454  SCIPerrorMessage("Undefined row type!\n");
18455  return SCIP_ERROR;
18456  }
18457  }
18458  }
18459 
18460  /* print variable bounds */
18461  SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
18462  for( i = 0; i < lp->ncols; ++i )
18463  {
18464  if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
18465  {
18466  /* print lower bound as far this one is not infinity */
18467  if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
18468  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
18469 
18470  /* print variable name */
18471  if( genericnames )
18472  SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
18473  else
18474  SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
18475 
18476  /* print upper bound as far this one is not infinity */
18477  if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
18478  SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
18479  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
18480  }
18481  }
18482  if( origobj && objoffset != 0.0 )
18483  SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
18484 
18485  /* print integer variables */
18486  SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
18487  j = 0;
18488  for( i = 0; i < lp->ncols; ++i )
18489  {
18490  if( SCIPvarIsIntegral(lp->cols[i]->var) )
18491  {
18492  /* print variable name */
18493  if( genericnames )
18494  SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
18495  else
18496  SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
18497 
18498  j++;
18499  if( j % 10 == 0 )
18500  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
18501  }
18502  }
18503 
18504  SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
18505  fclose(file);
18506 
18507  return SCIP_OKAY;
18508 }
18509 
18510 /*
18511  * simple functions implemented as defines
18512  */
18513 
18514 /* In debug mode, the following methods are implemented as function calls to ensure
18515  * type validity.
18516  * In optimized mode, the methods are implemented as defines to improve performance.
18517  * However, we want to have them in the library anyways, so we have to undef the defines.
18518  */
18519 
18520 #undef SCIPcolGetObj
18521 #undef SCIPcolGetLb
18522 #undef SCIPcolGetUb
18523 #undef SCIPcolGetBestBound
18524 #undef SCIPcolGetPrimsol
18525 #undef SCIPcolGetMinPrimsol
18526 #undef SCIPcolGetMaxPrimsol
18527 #undef SCIPcolGetBasisStatus
18528 #undef SCIPcolGetVar
18529 #undef SCIPcolGetIndex
18530 #undef SCIPcolIsIntegral
18531 #undef SCIPcolIsRemovable
18532 #undef SCIPcolGetLPPos
18533 #undef SCIPcolGetLPDepth
18534 #undef SCIPcolIsInLP
18535 #undef SCIPcolGetNNonz
18536 #undef SCIPcolGetNLPNonz
18537 #undef SCIPcolGetRows
18538 #undef SCIPcolGetVals
18539 #undef SCIPcolGetStrongbranchNode
18540 #undef SCIPcolGetNStrongbranchs
18541 #undef SCIPboundtypeOpposite
18542 #undef SCIProwGetNNonz
18543 #undef SCIProwGetNLPNonz
18544 #undef SCIProwGetCols
18545 #undef SCIProwGetVals
18546 #undef SCIProwGetConstant
18547 #undef SCIProwGetNorm
18548 #undef SCIProwGetSumNorm
18549 #undef SCIProwGetLhs
18550 #undef SCIProwGetRhs
18551 #undef SCIProwGetDualsol
18552 #undef SCIProwGetDualfarkas
18553 #undef SCIProwGetBasisStatus
18554 #undef SCIProwGetName
18555 #undef SCIProwGetIndex
18556 #undef SCIProwGetAge
18557 #undef SCIProwGetRank
18558 #undef SCIProwIsIntegral
18559 #undef SCIProwIsLocal
18560 #undef SCIProwIsModifiable
18561 #undef SCIProwIsRemovable
18562 #undef SCIProwGetOrigintype
18563 #undef SCIProwGetOriginCons
18564 #undef SCIProwGetOriginSepa
18565 #undef SCIProwIsInGlobalCutpool
18566 #undef SCIProwGetLPPos
18567 #undef SCIProwGetLPDepth
18568 #undef SCIProwIsInLP
18569 #undef SCIProwGetActiveLPCount
18570 #undef SCIProwGetNLPsAfterCreation
18571 #undef SCIProwChgRank
18572 #undef SCIPlpGetCols
18573 #undef SCIPlpGetNCols
18574 #undef SCIPlpGetRows
18575 #undef SCIPlpGetNRows
18576 #undef SCIPlpGetNewcols
18577 #undef SCIPlpGetNNewcols
18578 #undef SCIPlpGetNewrows
18579 #undef SCIPlpGetNNewrows
18580 #undef SCIPlpGetObjNorm
18581 #undef SCIPlpGetRootObjval
18582 #undef SCIPlpGetRootColumnObjval
18583 #undef SCIPlpGetRootLooseObjval
18584 #undef SCIPlpGetLPI
18585 #undef SCIPlpSetIsRelax
18586 #undef SCIPlpIsRelax
18587 #undef SCIPlpIsSolved
18588 #undef SCIPlpIsSolBasic
18589 #undef SCIPlpDiving
18590 #undef SCIPlpDivingObjChanged
18591 #undef SCIPlpMarkDivingObjChanged
18592 #undef SCIPlpUnmarkDivingObjChanged
18593 #undef SCIPlpDivingRowsChanged
18594 
18595 /** gets objective value of column */
18597  SCIP_COL* col /**< LP column */
18598  )
18599 {
18600  assert(col != NULL);
18601 
18602  return col->obj;
18603 }
18604 
18605 /** gets lower bound of column */
18607  SCIP_COL* col /**< LP column */
18608  )
18609 {
18610  assert(col != NULL);
18611 
18612  return col->lb;
18613 }
18614 
18615 /** gets upper bound of column */
18617  SCIP_COL* col /**< LP column */
18618  )
18619 {
18620  assert(col != NULL);
18621 
18622  return col->ub;
18623 }
18624 
18625 /** gets best bound of column with respect to the objective function */
18627  SCIP_COL* col /**< LP column */
18628  )
18629 {
18630  assert(col != NULL);
18631 
18632  if( col->obj >= 0.0 )
18633  return col->lb;
18634  else
18635  return col->ub;
18636 }
18637 
18638 /** gets the primal LP solution of a column */
18640  SCIP_COL* col /**< LP column */
18641  )
18642 {
18643  assert(col != NULL);
18644 
18645  if( col->lppos >= 0 )
18646  return col->primsol;
18647  else
18648  return 0.0;
18649 }
18650 
18651 /** gets the minimal LP solution value, this column ever assumed */
18653  SCIP_COL* col /**< LP column */
18654  )
18655 {
18656  assert(col != NULL);
18657 
18658  return col->minprimsol;
18659 }
18660 
18661 /** gets the maximal LP solution value, this column ever assumed */
18663  SCIP_COL* col /**< LP column */
18664  )
18665 {
18666  assert(col != NULL);
18667 
18668  return col->maxprimsol;
18669 }
18670 
18671 /** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
18672  * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
18673  */
18675  SCIP_COL* col /**< LP column */
18676  )
18677 {
18678  assert(col != NULL);
18679  assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
18680 
18681  return (SCIP_BASESTAT)col->basisstatus;
18682 }
18683 
18684 /** gets variable this column represents */
18686  SCIP_COL* col /**< LP column */
18687  )
18688 {
18689  assert(col != NULL);
18690 
18691  return col->var;
18692 }
18693 
18694 /** gets unique index of col */
18696  SCIP_COL* col /**< LP col */
18697  )
18698 {
18699  assert(col != NULL);
18700 
18701  return col->index;
18702 }
18703 
18704 /** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
18706  SCIP_COL* col /**< LP column */
18707  )
18708 {
18709  assert(col != NULL);
18710  assert(SCIPvarIsIntegral(col->var) == col->integral);
18711 
18712  return col->integral;
18713 }
18714 
18715 /** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
18717  SCIP_COL* col /**< LP column */
18718  )
18719 {
18720  assert(col != NULL);
18721 
18722  return col->removable;
18723 }
18724 
18725 /** gets position of column in current LP, or -1 if it is not in LP */
18727  SCIP_COL* col /**< LP column */
18728  )
18729 {
18730  assert(col != NULL);
18731  assert((col->lppos == -1) == (col->lpdepth == -1));
18732 
18733  return col->lppos;
18734 }
18735 
18736 /** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
18738  SCIP_COL* col /**< LP column */
18739  )
18740 {
18741  assert(col != NULL);
18742  assert((col->lppos == -1) == (col->lpdepth == -1));
18743 
18744  return col->lpdepth;
18745 }
18746 
18747 /** returns TRUE iff column is member of current LP */
18749  SCIP_COL* col /**< LP column */
18750  )
18751 {
18752  assert(col != NULL);
18753  assert((col->lppos == -1) == (col->lpdepth == -1));
18754 
18755  return (col->lppos >= 0);
18756 }
18757 
18758 /** get number of nonzero entries in column vector */
18760  SCIP_COL* col /**< LP column */
18761  )
18762 {
18763  assert(col != NULL);
18764 
18765  return col->len;
18766 }
18767 
18768 /** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
18769  *
18770  * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
18771  * 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
18772  */
18774  SCIP_COL* col /**< LP column */
18775  )
18776 {
18777  assert(col != NULL);
18778  assert(col->nunlinked == 0);
18779 
18780  return col->nlprows;
18781 }
18782 
18783 /** gets array with rows of nonzero entries */
18785  SCIP_COL* col /**< LP column */
18786  )
18787 {
18788  assert(col != NULL);
18789 
18790  return col->rows;
18791 }
18792 
18793 /** gets array with coefficients of nonzero entries */
18795  SCIP_COL* col /**< LP column */
18796  )
18797 {
18798  assert(col != NULL);
18799 
18800  return col->vals;
18801 }
18802 
18803 /** gets node number of the last node in current branch and bound run, where strong branching was used on the
18804  * given column, or -1 if strong branching was never applied to the column in current run
18805  */
18807  SCIP_COL* col /**< LP column */
18808  )
18809 {
18810  assert(col != NULL);
18811 
18812  return col->sbnode;
18813 }
18814 
18815 /** gets number of times, strong branching was applied in current run on the given column */
18817  SCIP_COL* col /**< LP column */
18818  )
18819 {
18820  assert(col != NULL);
18821 
18822  return col->nsbcalls;
18823 }
18824 
18825 /** gets opposite bound type of given bound type */
18827  SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
18828  )
18829 {
18830  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
18831 
18833 }
18834 
18835 /** get number of nonzero entries in row vector */
18837  SCIP_ROW* row /**< LP row */
18838  )
18839 {
18840  assert(row != NULL);
18841 
18842  return row->len;
18843 }
18844 
18845 /** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
18846  *
18847  * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
18848  * 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
18849  */
18851  SCIP_ROW* row /**< LP row */
18852  )
18853 {
18854  assert(row != NULL);
18855  assert(row->nunlinked == 0);
18856 
18857  return row->nlpcols;
18858 }
18859 
18860 /** gets array with columns of nonzero entries */
18862  SCIP_ROW* row /**< LP row */
18863  )
18864 {
18865  assert(row != NULL);
18866 
18867  return row->cols;
18868 }
18869 
18870 /** gets array with coefficients of nonzero entries */
18872  SCIP_ROW* row /**< LP row */
18873  )
18874 {
18875  assert(row != NULL);
18876 
18877  return row->vals;
18878 }
18879 
18880 /** gets constant shift of row */
18882  SCIP_ROW* row /**< LP row */
18883  )
18884 {
18885  assert(row != NULL);
18886 
18887  return row->constant;
18888 }
18889 
18890 /** gets Euclidean norm of row vector */
18892  SCIP_ROW* row /**< LP row */
18893  )
18894 {
18895  assert(row != NULL);
18896 
18897  checkRowSqrnorm(row);
18898 
18899  return sqrt(row->sqrnorm);
18900 }
18901 
18902 /** gets sum norm of row vector (sum of absolute values of coefficients) */
18904  SCIP_ROW* row /**< LP row */
18905  )
18906 {
18907  assert(row != NULL);
18908 
18909  checkRowSumnorm(row);
18910 
18911  return row->sumnorm;
18912 }
18913 
18914 /** returns the left hand side of the row */
18916  SCIP_ROW* row /**< LP row */
18917  )
18918 {
18919  assert(row != NULL);
18920 
18921  return row->lhs;
18922 }
18923 
18924 /** returns the right hand side of the row */
18926  SCIP_ROW* row /**< LP row */
18927  )
18928 {
18929  assert(row != NULL);
18930 
18931  return row->rhs;
18932 }
18933 
18934 /** gets the dual LP solution of a row */
18936  SCIP_ROW* row /**< LP row */
18937  )
18938 {
18939  assert(row != NULL);
18940 
18941  if( row->lppos >= 0 )
18942  return row->dualsol;
18943  else
18944  return 0.0;
18945 }
18946 
18947 /** gets the dual Farkas coefficient of a row in an infeasible LP */
18949  SCIP_ROW* row /**< LP row */
18950  )
18951 {
18952  assert(row != NULL);
18953 
18954  if( row->lppos >= 0 )
18955  return row->dualfarkas;
18956  else
18957  return 0.0;
18958 }
18959 
18960 /** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
18961  * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
18962  */
18964  SCIP_ROW* row /**< LP row */
18965  )
18966 {
18967  assert(row != NULL);
18968  assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
18969 
18970  return (SCIP_BASESTAT)row->basisstatus;
18971 }
18972 
18973 /** returns the name of the row */
18974 const char* SCIProwGetName(
18975  SCIP_ROW* row /**< LP row */
18976  )
18977 {
18978  assert(row != NULL);
18979 
18980  return row->name;
18981 }
18982 
18983 /** gets unique index of row */
18985  SCIP_ROW* row /**< LP row */
18986  )
18987 {
18988  assert(row != NULL);
18989 
18990  return row->index;
18991 }
18992 
18993 /** gets age of row */
18995  SCIP_ROW* row /**< LP row */
18996  )
18997 {
18998  assert(row != NULL);
18999 
19000  return row->age;
19001 }
19002 
19003 /** gets rank of row */
19005  SCIP_ROW* row /**< LP row */
19006  )
19007 {
19008  assert(row != NULL);
19009 
19010  return row->rank;
19011 }
19012 
19013 /** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
19015  SCIP_ROW* row /**< LP row */
19016  )
19017 {
19018  assert(row != NULL);
19019 
19020  return row->integral;
19021 }
19022 
19023 /** returns TRUE iff row is only valid locally */
19025  SCIP_ROW* row /**< LP row */
19026  )
19027 {
19028  assert(row != NULL);
19029 
19030  return row->local;
19031 }
19032 
19033 /** returns TRUE iff row is modifiable during node processing (subject to column generation) */
19035  SCIP_ROW* row /**< LP row */
19036  )
19037 {
19038  assert(row != NULL);
19039 
19040  return row->modifiable;
19041 }
19042 
19043 /** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
19045  SCIP_ROW* row /**< LP row */
19046  )
19047 {
19048  assert(row != NULL);
19049 
19050  return row->removable;
19051 }
19052 
19053 /** returns type of origin that created the row */
19055  SCIP_ROW* row /**< LP row */
19056  )
19057 {
19058  assert( row != NULL );
19059 
19060  return (SCIP_ROWORIGINTYPE) row->origintype;
19061 }
19062 
19063 /** returns origin constraint handler that created the row (NULL if not available) */
19065  SCIP_ROW* row /**< LP row */
19066  )
19067 {
19068  assert( row != NULL );
19069 
19071  {
19072  assert( row->origin != NULL );
19073  return (SCIP_CONSHDLR*) row->origin;
19074  }
19075  return NULL;
19076 }
19077 
19078 /** returns origin separator that created the row (NULL if not available) */
19080  SCIP_ROW* row /**< LP row */
19081  )
19082 {
19083  assert( row != NULL );
19084 
19086  {
19087  assert( row->origin != NULL );
19088  return (SCIP_SEPA*) row->origin;
19089  }
19090  return NULL;
19091 }
19092 
19093 /** returns TRUE iff row is member of the global cut pool */
19095  SCIP_ROW* row /**< LP row */
19096  )
19097 {
19098  assert(row != NULL);
19099 
19100  return row->inglobalcutpool;
19101 }
19102 
19103 /** gets position of row in current LP, or -1 if it is not in LP */
19105  SCIP_ROW* row /**< LP row */
19106  )
19107 {
19108  assert(row != NULL);
19109  assert((row->lppos == -1) == (row->lpdepth == -1));
19110 
19111  return row->lppos;
19112 }
19113 
19114 /** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
19116  SCIP_ROW* row /**< LP row */
19117  )
19118 {
19119  assert(row != NULL);
19120  assert((row->lppos == -1) == (row->lpdepth == -1));
19121 
19122  return row->lpdepth;
19123 }
19124 
19125 /** returns TRUE iff row is member of current LP */
19127  SCIP_ROW* row /**< LP row */
19128  )
19129 {
19130  assert(row != NULL);
19131  assert((row->lppos == -1) == (row->lpdepth == -1));
19132 
19133  return (row->lppos >= 0);
19134 }
19135 
19136 /** changes the rank of LP row */
19138  SCIP_ROW* row, /**< LP row */
19139  int rank /**< new value for rank */
19140  )
19141 {
19142  assert(row != NULL);
19143 
19144  row->rank = rank;
19145 }
19146 
19147 /** returns the number of times that this row has been sharp in an optimal LP solution */
19149  SCIP_ROW* row /**< row */
19150  )
19151 {
19152  assert(row != NULL);
19153 
19154  return row->activeinlpcounter;
19155 }
19156 
19157 /** returns the number of LPs since this row has been created */
19159  SCIP_ROW* row /**< row */
19160  )
19161 {
19162  assert(row != NULL);
19163 
19164  return row->nlpsaftercreation;
19165 }
19166 
19167 /** gets array with columns of the LP */
19169  SCIP_LP* lp /**< current LP data */
19170  )
19171 {
19172  assert(lp != NULL);
19173 
19174  return lp->cols;
19175 }
19176 
19177 /** gets current number of columns in LP */
19179  SCIP_LP* lp /**< current LP data */
19180  )
19181 {
19182  assert(lp != NULL);
19183 
19184  return lp->ncols;
19185 }
19186 
19187 /** gets array with rows of the LP */
19189  SCIP_LP* lp /**< current LP data */
19190  )
19191 {
19192  assert(lp != NULL);
19193 
19194  return lp->rows;
19195 }
19196 
19197 /** gets current number of rows in LP */
19199  SCIP_LP* lp /**< current LP data */
19200  )
19201 {
19202  assert(lp != NULL);
19203 
19204  return lp->nrows;
19205 }
19206 
19207 /** gets array with newly added columns after the last mark */
19209  SCIP_LP* lp /**< current LP data */
19210  )
19211 {
19212  assert(lp != NULL);
19213  assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
19214 
19215  return &(lp->cols[lp->firstnewcol]);
19216 }
19217 
19218 /** gets number of newly added columns after the last mark */
19220  SCIP_LP* lp /**< current LP data */
19221  )
19222 {
19223  assert(lp != NULL);
19224  assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
19225 
19226  return lp->ncols - lp->firstnewcol;
19227 }
19228 
19229 /** gets array with newly added rows after the last mark */
19231  SCIP_LP* lp /**< current LP data */
19232  )
19233 {
19234  assert(lp != NULL);
19235  assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
19236 
19237  return &(lp->rows[lp->firstnewrow]);
19238 }
19239 
19240 /** gets number of newly added rows after the last mark */
19242  SCIP_LP* lp /**< current LP data */
19243  )
19244 {
19245  assert(lp != NULL);
19246  assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
19247 
19248  return lp->nrows - lp->firstnewrow;
19249 }
19250 
19251 /** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
19253  SCIP_SET* set, /**< global SCIP settings */
19254  SCIP_LP* lp /**< LP data */
19255  )
19256 {
19257  if( lp->objsqrnormunreliable )
19258  {
19259  SCIP_COL** cols;
19260  int c;
19261 
19262  cols = lp->cols;
19263  assert(cols != NULL || lp->ncols == 0);
19264 
19265  lp->objsqrnorm = 0.0;
19266 
19267  for( c = lp->ncols - 1; c >= 0; --c )
19268  {
19269  lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
19270  }
19271  assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
19272 
19273  /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
19274  lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
19275 
19277  }
19278  return;
19279 }
19280 
19281 /** gets Euclidean norm of objective function vector of column variables, only use this method if
19282  * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
19284  SCIP_LP* lp /**< LP data */
19285  )
19286 {
19287  assert(lp != NULL);
19288  assert(!lp->objsqrnormunreliable);
19289  assert(lp->objsqrnorm >= 0.0);
19290 
19291  return SQRT(lp->objsqrnorm);
19292 }
19293 
19294 /** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
19296  SCIP_LP* lp, /**< LP data */
19297  SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
19298  )
19299 {
19300  assert(lp != NULL);
19301 
19302  lp->rootlpisrelax = isrelax;
19303 }
19304 
19305 /** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
19307  SCIP_LP* lp /**< LP data */
19308  )
19309 {
19310  assert(lp != NULL);
19311 
19312  return lp->rootlpisrelax;
19313 }
19314 
19315 /** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
19317  SCIP_LP* lp /**< LP data */
19318  )
19319 {
19320  assert(lp != NULL);
19321 
19322  return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
19323 }
19324 
19325 /** gets part of the objective value of the root node LP that results from COLUMN variables only;
19326  * returns SCIP_INVALID if the root node LP was not (yet) solved
19327  */
19329  SCIP_LP* lp /**< LP data */
19330  )
19331 {
19332  assert(lp != NULL);
19333 
19334  return lp->rootlpobjval;
19335 }
19336 
19337 /** gets part of the objective value of the root node LP that results from LOOSE variables only;
19338  * returns SCIP_INVALID if the root node LP was not (yet) solved
19339  */
19341  SCIP_LP* lp /**< LP data */
19342  )
19343 {
19344  assert(lp != NULL);
19345 
19346  return lp->rootlooseobjval;
19347 }
19348 
19349 /** gets the LP solver interface */
19351  SCIP_LP* lp /**< current LP data */
19352  )
19353 {
19354  assert(lp != NULL);
19355 
19356  return lp->lpi;
19357 }
19358 
19359 /** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
19361  SCIP_LP* lp, /**< LP data */
19362  SCIP_Bool relax /**< is the current lp a relaxation? */
19363  )
19364 {
19365  assert(lp != NULL);
19366 
19367  lp->isrelax = relax;
19368 }
19369 
19370 /** returns whether the current LP is a relaxation of the problem for which it has been solved and its
19371  * solution value a valid local lower bound?
19372  */
19374  SCIP_LP* lp /**< LP data */
19375  )
19376 {
19377  assert(lp != NULL);
19378 
19379  return lp->isrelax;
19380 }
19381 
19382 /** returns whether the current LP is flushed and solved */
19384  SCIP_LP* lp /**< current LP data */
19385  )
19386 {
19387  assert(lp != NULL);
19388 
19389  return lp->flushed && lp->solved;
19390 }
19391 
19392 /** returns whether the current LP solution is a basic solution */
19394  SCIP_LP* lp /**< current LP data */
19395  )
19396 {
19397  assert(lp != NULL);
19398 
19399  return lp->solisbasic;
19400 }
19401 
19402 /** returns whether the LP is in diving mode */
19404  SCIP_LP* lp /**< current LP data */
19405  )
19406 {
19407  assert(lp != NULL);
19408 
19409  return lp->diving;
19410 }
19411 
19412 /** returns whether the LP is in diving mode and the objective value of at least one column was changed */
19414  SCIP_LP* lp /**< current LP data */
19415  )
19416 {
19417  assert(lp != NULL);
19418 
19419  return lp->divingobjchg;
19420 }
19421 
19422 /** marks the diving LP to have a changed objective function */
19424  SCIP_LP* lp /**< current LP data */
19425  )
19426 {
19427  assert(lp != NULL);
19428  assert(lp->diving || lp->probing);
19429 
19430  lp->divingobjchg = TRUE;
19431 }
19432 
19433 /** marks the diving LP to not have a changed objective function anymore */
19435  SCIP_LP* lp /**< current LP data */
19436  )
19437 {
19438  assert(lp != NULL);
19439  assert(lp->diving || lp->probing);
19440 
19441  lp->divingobjchg = FALSE;
19442 }
19443 
19444 /* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
19446  SCIP_LP* lp /**< current LP data */
19447  )
19448 {
19449  assert(lp != NULL);
19450  assert(lp->diving || lp->ndivechgsides == 0);
19451 
19452  return (lp->ndivechgsides > 0);
19453 }
19454 
19455 /** compute relative interior point
19456  *
19457  * We use the approach of@par
19458  * R. Freund, R. Roundy, M. J. Todd@par
19459  * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
19460  * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
19461  *
19462  * to compute a relative interior point for the current LP.
19463  *
19464  * Assume the original LP looks as follows:
19465  * \f[
19466  * \begin{array}{rrl}
19467  * \min & c^T x &\\
19468  * & A x & \geq a\\
19469  * & B x & \leq b\\
19470  * & D x & = d.
19471  * \end{array}
19472  * \f]
19473  * Note that bounds should be included in the system.
19474  *
19475  * To find an interior point the following LP does the job:
19476  * \f[
19477  * \begin{array}{rrl}
19478  * \max & 1^T y &\\
19479  * & A x - y - \alpha a & \geq 0\\
19480  * & B x + y - \alpha b & \leq 0\\
19481  * & D x - \alpha d & = 0\\
19482  * & 0 \leq y & \leq 1\\
19483  * & \alpha & \geq 1.
19484  * \end{array}
19485  * \f]
19486  * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
19487  * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
19488  * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
19489  */
19491  SCIP_SET* set, /**< global SCIP settings */
19492  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
19493  SCIP_LP* lp, /**< LP data */
19494  SCIP_PROB* prob, /**< problem data */
19495  SCIP_Bool relaxrows, /**< should the rows be relaxed */
19496  SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
19497  SCIP_Real timelimit, /**< time limit for LP solver */
19498  int iterlimit, /**< iteration limit for LP solver */
19499  SCIP_Real* point, /**< array to store relative interior point on exit */
19500  SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
19501  )
19502 {
19503  SCIP_LPI* lpi;
19504  SCIP_Real* obj;
19505  SCIP_Real* lb;
19506  SCIP_Real* ub;
19507  SCIP_Real* primal;
19508  SCIP_Real* colvals;
19509  SCIP_Real zero;
19510  SCIP_Real minusinf;
19511  SCIP_Real plusinf;
19512  SCIP_Real objval;
19513  SCIP_Real alpha;
19514  SCIP_RETCODE retcode;
19515  int* colinds;
19516  int nnewcols;
19517 #ifndef NDEBUG
19518  int nslacks;
19519 #endif
19520  int beg;
19521  int cnt;
19522  int i;
19523  int j;
19524 
19525  assert(set != NULL);
19526  assert(lp != NULL);
19527  assert(point != NULL);
19528  assert(success != NULL);
19529 
19530  *success = FALSE;
19531 
19532  /* check time and iteration limits */
19533  if ( timelimit <= 0.0 || iterlimit <= 0 )
19534  return SCIP_OKAY;
19535 
19536  /* exit if there are no columns */
19537  assert(lp->nrows >= 0);
19538  assert(lp->ncols >= 0);
19539  if( lp->ncols == 0 )
19540  return SCIP_OKAY;
19541 
19542  /* disable objective cutoff if we have none */
19543  if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
19544  inclobjcutoff = FALSE;
19545 
19546  SCIPdebugMessage("Computing relative interior point to current LP.\n");
19547 
19548  /* if there are no rows, we return the zero point */
19549  if( lp->nrows == 0 && !inclobjcutoff )
19550  {
19551  /* create zero point */
19552  BMSclearMemoryArray(point, lp->ncols);
19553  *success = TRUE;
19554 
19555  return SCIP_OKAY;
19556  }
19557 
19558  /* create auxiliary LP */
19559  SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
19560 
19562  if( retcode != SCIP_OKAY && retcode != SCIP_PARAMETERUNKNOWN )
19563  {
19564  SCIP_CALL( retcode );
19565  }
19566 
19568  if( retcode != SCIP_OKAY && retcode != SCIP_PARAMETERUNKNOWN )
19569  {
19570  SCIP_CALL( retcode );
19571  }
19572 
19573  /* get storage */
19574  nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
19575  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
19576  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
19577  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
19578 
19579  /* create original columns (bounds are relaxed below, unless the variable is fixed) */
19580  for( j = 0; j < lp->ncols; ++j )
19581  {
19582  /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
19583  obj[j] = 0.0;
19584  lb[j] = -SCIPlpiInfinity(lpi);
19585  ub[j] = SCIPlpiInfinity(lpi);
19586  /* note: we could also use the original bounds - free variables seem to be faster. */
19587  }
19588 
19589  /* add artificial alpha variable */
19590  nnewcols = lp->ncols;
19591  obj[nnewcols] = 0.0;
19592  lb[nnewcols] = 1.0;
19593  ub[nnewcols] = SCIPlpiInfinity(lpi);
19594  ++nnewcols;
19595 
19596  /* create slacks for rows */
19597  for( i = 0; i < lp->nrows; ++i )
19598  {
19599  SCIP_ROW* row;
19600 
19601  row = lp->rows[i];
19602  assert( row != NULL );
19603 
19604  if( SCIProwIsModifiable(row) )
19605  continue;
19606 
19607  /* make sure row is sorted */
19608  rowSortLP(row);
19609  assert( row->lpcolssorted );
19610 
19611  /* check whether we have an equation */
19612  if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
19613  {
19614  assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
19615  assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
19616  }
19617  else if( relaxrows )
19618  {
19619  /* otherwise add slacks for each side if necessary */
19620  if( !SCIPsetIsInfinity(set, REALABS(row->lhs)) )
19621  {
19622  obj[nnewcols] = 1.0;
19623  lb[nnewcols] = 0.0;
19624  ub[nnewcols] = 1.0;
19625  ++nnewcols;
19626  }
19627  if( !SCIPsetIsInfinity(set, REALABS(row->rhs)) )
19628  {
19629  obj[nnewcols] = 1.0;
19630  lb[nnewcols] = 0.0;
19631  ub[nnewcols] = 1.0;
19632  ++nnewcols;
19633  }
19634  }
19635  }
19636 
19637  /* create slacks for objective cutoff row */
19638  if( inclobjcutoff && relaxrows )
19639  {
19640  /* add slacks for right hand side */
19641  obj[nnewcols] = 1.0;
19642  lb[nnewcols] = 0.0;
19643  ub[nnewcols] = 1.0;
19644  ++nnewcols;
19645  }
19646 
19647  /* create slacks for bounds */
19648  for( j = 0; j < lp->ncols; ++j )
19649  {
19650  SCIP_COL* col;
19651 
19652  col = lp->cols[j];
19653  assert( col != NULL );
19654 
19655  /* no slacks for fixed variables */
19656  if( SCIPsetIsEQ(set, col->lb, col->ub) )
19657  continue;
19658 
19659  /* add slacks for each bound if necessary */
19660  if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
19661  {
19662  obj[nnewcols] = 1.0;
19663  lb[nnewcols] = 0.0;
19664  ub[nnewcols] = 1.0;
19665  ++nnewcols;
19666  }
19667  if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
19668  {
19669  obj[nnewcols] = 1.0;
19670  lb[nnewcols] = 0.0;
19671  ub[nnewcols] = 1.0;
19672  ++nnewcols;
19673  }
19674  }
19675 #ifndef NDEBUG
19676  nslacks = nnewcols - lp->ncols - 1;
19677  assert( nslacks >= 0 );
19678  assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
19679 #endif
19680 
19681  /* add columns */
19682  SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
19683 
19684  /* free storage */
19685  SCIPsetFreeBufferArray(set, &obj);
19686  SCIPsetFreeBufferArray(set, &ub);
19687  SCIPsetFreeBufferArray(set, &lb);
19688 
19689  /* prepare storage for rows */
19690  SCIP_CALL( SCIPsetAllocBufferArray(set, &colinds, lp->ncols+2) );
19691  SCIP_CALL( SCIPsetAllocBufferArray(set, &colvals, lp->ncols+2) );
19692 
19693  /* create rows arising from original rows */
19694  cnt = 0;
19695  beg = 0;
19696  zero = 0.0;
19697  minusinf = -SCIPlpiInfinity(lpi);
19698  plusinf = SCIPlpiInfinity(lpi);
19699  for( i = 0; i < lp->nrows; ++i )
19700  {
19701  SCIP_ROW* row;
19702  SCIP_COL** rowcols;
19703  SCIP_Real* rowvals;
19704  SCIP_Real lhs;
19705  SCIP_Real rhs;
19706  int nnonz;
19707 
19708  row = lp->rows[i];
19709  assert( row != NULL );
19710 
19711  if( SCIProwIsModifiable(row) )
19712  continue;
19713  assert( row->lpcolssorted );
19714 
19715  /* get row data */
19716  lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
19717  rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
19718  nnonz = row->nlpcols;
19719  assert( nnonz <= lp->ncols );
19720  rowcols = row->cols;
19721  rowvals = row->vals;
19722 
19723  /* set up indices */
19724  for( j = 0; j < nnonz; ++j )
19725  {
19726  assert( rowcols[j] != NULL );
19727  assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
19728  assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
19729  colinds[j] = rowcols[j]->lppos;
19730  colvals[j] = rowvals[j];
19731  }
19732 
19733  /* if we have an equation */
19734  if( SCIPsetIsEQ(set, lhs, rhs) )
19735  {
19736  /* add artificial variable */
19737  colinds[nnonz] = lp->ncols;
19738  colvals[nnonz] = -rhs;
19739 
19740  /* add row */
19741  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &zero, NULL, nnonz+1, &beg, colinds, colvals) );
19742  }
19743  else
19744  {
19745  SCIP_Real abslhs = REALABS(lhs);
19746  SCIP_Real absrhs = REALABS(rhs);
19747 
19748  /* treat lhs */
19749  if( !SCIPsetIsInfinity(set, abslhs) )
19750  {
19751  assert(!SCIPsetIsEQ(set, lhs, rhs));
19752 
19753  /* add artificial variable */
19754  colinds[nnonz] = lp->ncols;
19755  colvals[nnonz] = -lhs;
19756 
19757  if( relaxrows )
19758  {
19759  /* add slack variable */
19760  colinds[nnonz+1] = lp->ncols + 1 + cnt; /*lint !e679*/
19761  colvals[nnonz+1] = -MAX(1.0, lhs); /*lint !e679*/
19762  ++cnt;
19763  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, nnonz+2, &beg, colinds, colvals) );
19764  }
19765  else
19766  {
19767  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, nnonz+1, &beg, colinds, colvals) );
19768  }
19769  }
19770 
19771  /* treat rhs */
19772  if( !SCIPsetIsInfinity(set, absrhs) )
19773  {
19774  assert(!SCIPsetIsEQ(set, lhs, rhs));
19775 
19776  /* add artificial variable */
19777  colinds[nnonz] = lp->ncols;
19778  colvals[nnonz] = -rhs;
19779 
19780  if( relaxrows )
19781  {
19782  /* add slack variable */
19783  colinds[nnonz+1] = lp->ncols + 1 + cnt; /*lint !e679*/
19784  colvals[nnonz+1] = MAX(1.0, absrhs); /*lint !e679*/
19785  ++cnt;
19786  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz+2, &beg, colinds, colvals) );
19787  }
19788  else
19789  {
19790  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz+1, &beg, colinds, colvals) );
19791  }
19792  }
19793  }
19794  }
19795 
19796  /* create row arising from objective cutoff */
19797  if( inclobjcutoff )
19798  {
19799  SCIP_Real rhs;
19800  int nnonz;
19801 
19802  /* get row data */
19803  assert(lp->looseobjvalinf == 0);
19804  rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
19805 
19806  /* set up indices and coefficients */
19807  nnonz = 0;
19808  for( j = 0; j < lp->ncols; ++j )
19809  {
19810  assert( lp->cols[j] != NULL );
19811  assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
19812  assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
19813  if( lp->cols[j]->obj == 0.0 )
19814  continue;
19815  colinds[nnonz] = lp->cols[j]->lppos;
19816  colvals[nnonz] = lp->cols[j]->obj;
19817  ++nnonz;
19818  }
19819 
19820  /* treat rhs */
19821  /* add artificial variable */
19822  colinds[nnonz] = lp->ncols;
19823  colvals[nnonz] = -rhs;
19824  ++nnonz;
19825 
19826  if( relaxrows )
19827  {
19828  SCIP_Real absrhs = REALABS(rhs);
19829 
19830  /* add slack variable */
19831  colinds[nnonz] = lp->ncols + 1 + cnt;
19832  colvals[nnonz] = MAX(1.0, absrhs);
19833  ++cnt;
19834  ++nnonz;
19835  }
19836  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz, &beg, colinds, colvals) );
19837  }
19838 
19839  /* create rows arising from bounds */
19840  for( j = 0; j < lp->ncols; ++j )
19841  {
19842  SCIP_COL* col;
19843  SCIP_Real abscollb;
19844  SCIP_Real abscolub;
19845 
19846  col = lp->cols[j];
19847  assert( col != NULL );
19848  assert( col->lppos == j );
19849 
19850  /* set up index of column */
19851  colinds[0] = j;
19852  colvals[0] = 1.0;
19853 
19854  /* fixed variable */
19855  if( SCIPsetIsEQ(set, col->lb, col->ub) )
19856  {
19857  /* add artificial variable */
19858  colinds[1] = lp->ncols;
19859  colvals[1] = -col->lb;
19860 
19861  /* add row */
19862  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &zero, NULL, 2, &beg, colinds, colvals) );
19863 
19864  continue;
19865  }
19866 
19867  abscollb = REALABS(col->lb);
19868  abscolub = REALABS(col->ub);
19869 
19870  /* lower bound */
19871  if( !SCIPsetIsInfinity(set, abscollb) )
19872  {
19873  /* add artificial variable */
19874  colinds[1] = lp->ncols;
19875  colvals[1] = -col->lb;
19876 
19877  /* add slack variable */
19878  colinds[2] = lp->ncols + 1 + cnt;
19879  colvals[2] = -MAX(1.0, abscollb);
19880  ++cnt;
19881  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, 3, &beg, colinds, colvals) );
19882  }
19883 
19884  /* upper bound */
19885  if( !SCIPsetIsInfinity(set, abscolub) )
19886  {
19887  /* add artificial variable */
19888  colinds[1] = lp->ncols;
19889  colvals[1] = -col->ub;
19890 
19891  /* add slack variable */
19892  colinds[2] = lp->ncols + 1 + cnt;
19893  colvals[2] = MAX(1.0, abscolub);
19894  ++cnt;
19895  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, 3, &beg, colinds, colvals) );
19896  }
19897  }
19898  assert( cnt == nslacks );
19899 
19900  SCIPsetFreeBufferArray(set, &colvals);
19901  SCIPsetFreeBufferArray(set, &colinds);
19902 
19903 #ifdef SCIP_OUTPUT
19904  SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
19905 #endif
19906 
19907 #ifndef NDEBUG
19908  {
19909  int ncols;
19910  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
19911  assert( ncols == nnewcols );
19912  }
19913 #endif
19914 
19915  /* set time limit */
19916  retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
19917 
19918  /* check, if parameter is unknown */
19919  if ( retcode == SCIP_PARAMETERUNKNOWN )
19920  SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
19921 
19922  /* set iteration limit */
19923  retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
19924 
19925  /* check, if parameter is unknown */
19926  if ( retcode == SCIP_PARAMETERUNKNOWN )
19927  SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
19928 
19929  /* solve and store point */
19930  /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
19931  retcode = SCIPlpiSolveDual(lpi); /* dual is usually faster */
19932 
19933  /* detect possible error in LP solver */
19934  if ( retcode != SCIP_OKAY )
19935  {
19936  SCIP_CALL( SCIPlpiFree(&lpi) );
19937  return SCIP_OKAY;
19938  }
19939 
19940 #ifndef NDEBUG
19941  if ( SCIPlpiIsIterlimExc(lpi) )
19942  SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
19943  if ( SCIPlpiIsTimelimExc(lpi) )
19944  SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
19945 #endif
19946 
19947  if( SCIPlpiIsOptimal(lpi) )
19948  {
19949  /* get primal solution */
19950  SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
19951  SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
19952  alpha = primal[lp->ncols];
19953  assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
19954 
19955  SCIPdebugMessage("Solved relative interior lp with objective %g.\n", objval);
19956 
19957  /* construct relative interior point */
19958  for( j = 0; j < lp->ncols; ++j )
19959  point[j] = primal[j]/alpha;
19960 
19961 #ifdef SCIP_DEBUG
19962  /* check whether the point is a relative interior point */
19963  cnt = 0;
19964  if( relaxrows )
19965  {
19966  for( i = 0; i < lp->nrows; ++i )
19967  {
19968  SCIP_ROW* row;
19969  SCIP_COL** rowcols;
19970  SCIP_Real* rowvals;
19971  SCIP_Real lhs;
19972  SCIP_Real rhs;
19973  SCIP_Real sum;
19974  int nnonz;
19975 
19976  row = lp->rows[i];
19977  assert( row != NULL );
19978 
19979  /* get row data */
19980  lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
19981  rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
19982  nnonz = row->nlpcols;
19983  assert( nnonz <= lp->ncols );
19984  rowcols = row->cols;
19985  rowvals = row->vals;
19986 
19987  sum = 0.0;
19988  for( j = 0; j < nnonz; ++j )
19989  sum += rowvals[j] * primal[rowcols[j]->lppos];
19990  sum /= alpha;
19991 
19992  /* if we have an equation */
19993  if( SCIPsetIsEQ(set, lhs, rhs) )
19994  {
19995  assert( SCIPsetIsFeasEQ(set, sum, lhs) );
19996  }
19997  else
19998  {
19999  /* treat lhs */
20000  if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
20001  {
20002  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
20003  ++cnt;
20004  }
20005  /* treat rhs */
20006  if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
20007  {
20008  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
20009  ++cnt;
20010  }
20011  }
20012  }
20013  if( inclobjcutoff )
20014  {
20015  SCIP_Real sum;
20016 #ifndef NDEBUG
20017  SCIP_Real rhs;
20018 
20019  rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
20020 #endif
20021  sum = 0.0;
20022  for( j = 0; j < lp->ncols; ++j )
20023  sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
20024  sum /= alpha;
20025 
20026  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
20027  ++cnt;
20028  }
20029  }
20030  /* check bounds */
20031  for( j = 0; j < lp->ncols; ++j )
20032  {
20033  SCIP_COL* col;
20034 #ifndef NDEBUG
20035  SCIP_Real val;
20036 #endif
20037 
20038  col = lp->cols[j];
20039  assert( col != NULL );
20040 #ifndef NDEBUG
20041  val = primal[col->lppos] / alpha;
20042 #endif
20043  /* if the variable is not fixed */
20044  if( !SCIPsetIsEQ(set, col->lb, col->ub) )
20045  {
20046  /* treat lb */
20047  if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
20048  {
20049  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
20050  ++cnt;
20051  }
20052  /* treat rhs */
20053  if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
20054  {
20055  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
20056  ++cnt;
20057  }
20058  }
20059  }
20060 #endif
20061 
20062  /* free */
20063  SCIPsetFreeBufferArray(set, &primal);
20064 
20065  *success = TRUE;
20066  }
20067  SCIP_CALL( SCIPlpiFree(&lpi) );
20068 
20069  return SCIP_OKAY;
20070 }
static SCIP_RETCODE lpRestoreSolVals(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_Longint validlp)
Definition: lp.c:367
SCIP_Longint nlexduallps
Definition: struct_stat.h:148
SCIP_Bool SCIPsetIsUpdateUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: set.c:6287
SCIP_Longint nprimallps
Definition: struct_stat.h:144
SCIP_Bool solisbasic
Definition: struct_lp.h:341
SCIP_Real lazyub
Definition: struct_lp.h:131
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1650
SCIP_Longint ndualresolvelpiterations
Definition: struct_stat.h:54
SCIP_Bool lpissolved
Definition: struct_lp.h:113
int nunlinked
Definition: struct_lp.h:225
void SCIPcolMarkNotRemovableLocal(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4544
int firstnewrow
Definition: struct_lp.h:312
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:18143
SCIP_Real SCIProwGetSolFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6272
SCIP_Real sbup
Definition: struct_lp.h:142
void SCIPlpInvalidateRootObjval(SCIP_LP *lp)
Definition: lp.c:15148
SCIP_CONSHDLR * SCIProwGetOriginCons(SCIP_ROW *row)
Definition: lp.c:19064
void SCIPcolGetStrongbranchLast(SCIP_COL *col, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Real *solval, SCIP_Real *lpobjval)
Definition: lp.c:4500
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:69
SCIP_Longint nsbdivinglps
Definition: struct_stat.h:158
int nsbcalls
Definition: struct_lp.h:164
static SCIP_RETCODE lpStoreSolVals(SCIP_LP *lp, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: lp.c:335
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5180
SCIP_Bool SCIPsetIsSumGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5483
static SCIP_RETCODE lpSetBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value, SCIP_Bool *success)
Definition: lp.c:2488
static SCIP_RETCODE lpSetFastmip(SCIP_LP *lp, int fastmip, SCIP_Bool *success)
Definition: lp.c:2773
int SCIProwGetMaxidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6455
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:406
static void roundStrongCGRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Real f0, SCIP_Real k)
Definition: lp.c:11802
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:422
static SCIP_RETCODE lpSetDualfeastol(SCIP_LP *lp, SCIP_Real dualfeastol, SCIP_Bool *success)
Definition: lp.c:2675
static SCIP_RETCODE lpUpdateVarProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real oldlb, SCIP_Real oldub, SCIP_Real newobj, SCIP_Real newlb, SCIP_Real newub)
Definition: lp.c:15677
SCIP_Real maxactivity
Definition: struct_lp.h:206
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13376
static void colUpdateDelLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8516
SCIP_RETCODE SCIPeventCreateRowAddedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:781
internal methods for managing events
SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:12462
SCIP_Real obj
Definition: struct_lp.h:125
SCIP_Bool SCIPlpDivingRowsChanged(SCIP_LP *lp)
Definition: lp.c:19445
static SCIP_RETCODE lpSetFromscratch(SCIP_LP *lp, SCIP_Bool fromscratch, SCIP_Bool *success)
Definition: lp.c:2748
static int SCIProwGetDiscreteScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7044
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5238
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2486
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition: lp.c:19241
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5688
internal methods for storing primal CIP solutions
static SCIP_RETCODE lpSetRowrepswitch(SCIP_LP *lp, SCIP_Real rowrepswitch, SCIP_Bool *success)
Definition: lp.c:2874
void * origin
Definition: struct_lp.h:213
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:19094
SCIP_EVENTFILTER * eventfilter
Definition: struct_lp.h:219
static SCIP_RETCODE rowScale(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real scaleval, SCIP_Bool integralcontvars, SCIP_Real minrounddelta, SCIP_Real maxrounddelta)
Definition: lp.c:4723
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1705
static void cleanupMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, SCIP_Bool cutislocal)
Definition: lp.c:9900
SCIP_RETCODE SCIPlpUpdateAddVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:15981
SCIP_STATUS status
Definition: struct_stat.h:139
SCIP_Longint nlpiterations
Definition: struct_stat.h:46
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:19403
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3422
SCIP_Real farkascoef
Definition: struct_lp.h:138
unsigned int ubchanged
Definition: struct_lp.h:172
static SCIP_RETCODE colChgCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos, SCIP_Real val)
Definition: lp.c:1815
SCIP_RETCODE SCIPlpShrinkRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int newnrows)
Definition: lp.c:9217
int nummaxval
Definition: struct_lp.h:232
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:19360
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_clp.cpp:2721
SCIP_Longint validactivitylp
Definition: struct_lp.h:220
int lpifirstchgrow
Definition: struct_lp.h:298
static SCIP_RETCODE colUnlink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2340
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5501
static SCIP_Bool isNewValueUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: lp.c:3450
static void rowSwapCoefs(SCIP_ROW *row, int pos1, int pos2)
Definition: lp.c:1352
#define SCIP_EVENTTYPE_ROWADDEDLP
Definition: type_event.h:87
SCIP_Real SCIProwGetMinval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6439
enum SCIP_LPAlgo SCIP_LPALGO
Definition: type_lp.h:77
SCIP_Longint SCIProwGetNLPsAfterCreation(SCIP_ROW *row)
Definition: lp.c:19158
int * cols_index
Definition: struct_lp.h:216
void SCIPlpEndStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:18010
int nremovablecols
Definition: struct_lp.h:307
char * name
Definition: struct_var.h:227
static SCIP_RETCODE lpCleanupCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:17370
SCIP_Bool primalfeasible
Definition: struct_lp.h:339
SCIP_RETCODE SCIPlpComputeRelIntPoint(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_LP *lp, SCIP_PROB *prob, SCIP_Bool relaxrows, SCIP_Bool inclobjcutoff, SCIP_Real timelimit, int iterlimit, SCIP_Real *point, SCIP_Bool *success)
Definition: lp.c:19490
static SCIP_Real getFiniteLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:856
static SCIP_RETCODE lpSetConditionLimit(SCIP_LP *lp, SCIP_Real condlimit, SCIP_Bool *success)
Definition: lp.c:3023
SCIP_Longint nlexdualresolvelps
Definition: struct_stat.h:153
SCIP_RETCODE SCIPeventCreateRowDeletedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:800
int nchgrows
Definition: struct_lp.h:302
static SCIP_RETCODE ensureLpirowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:216
#define MAXCMIRSCALE
Definition: lp.c:54
SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8258
SCIP_RETCODE SCIPlpGetBInvCol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9384
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3127
char * name
Definition: struct_lp.h:214
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5367
static void findBestUb(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_SOL *sol, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *bestub, int *bestubtype)
Definition: lp.c:10024
SCIP_Real SCIProwGetRelaxFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6038
SCIP_RETCODE SCIPcolChgCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: lp.c:3319
int nlpicols
Definition: struct_lp.h:294
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5578
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1790
static SCIP_RETCODE rowStoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Bool infeasible)
Definition: lp.c:495
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:84
SCIP_RETCODE SCIPlpRemoveAllObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:17339
SCIP_Real SCIProwGetPseudoActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6186
void SCIPlpSetRootLPIsRelax(SCIP_LP *lp, SCIP_Bool isrelax)
Definition: lp.c:19295
SCIP_Longint nlps
Definition: struct_stat.h:142
SCIP_Longint activeinlpcounter
Definition: struct_lp.h:210
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2057
SCIP_Longint nbarrierlpiterations
Definition: struct_stat.h:52
SCIP_Bool SCIProwIsRedundant(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6392
SCIP_LPALGO lastlpalgo
Definition: struct_lp.h:327
#define SCIP_MAXSTRLEN
Definition: def.h:201
static SCIP_RETCODE lpFlushAddCols(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:7650
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3330
void SCIProwRecalcLPActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:5936
SCIP_Bool lpiscaling
Definition: struct_lp.h:355
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1788
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_clp.cpp:3593
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17195
void SCIPlpRecalculateObjSqrNorm(SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:19252
enum SCIP_RowOriginType SCIP_ROWORIGINTYPE
Definition: type_lp.h:67
internal methods for clocks and timing issues
unsigned int origintype
Definition: struct_lp.h:251
static void getObjvalDeltaUb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldub, SCIP_Real newub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:15554
int lpdepth
Definition: struct_lp.h:229
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3089
static SCIP_Real getMaxAbsWeightCalcSparsity(SCIP_SET *set, SCIP_LP *lp, SCIP_Real *weights, int *rowinds, int *nrowinds, int *rowlensum)
Definition: lp.c:9546
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5303
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Real objsumnorm
Definition: struct_lp.h:277
SCIP_RETCODE SCIPlpCalcMIR(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, SCIP_Real maxweight, int *weightinds, int nweightinds, int rowlensum, int *sidetypes, SCIP_Real scale, SCIP_Real *mksetcoefs, SCIP_Bool *mksetcoefsvalid, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank)
Definition: lp.c:11043
SCIP_Longint ndivinglps
Definition: struct_stat.h:156
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1808
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17323
SCIP_ROW ** chgrows
Definition: struct_lp.h:282
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5105
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17261
SCIP_COL ** chgcols
Definition: struct_lp.h:281
SCIP_RETCODE SCIProwChgConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real constant)
Definition: lp.c:5348
static SCIP_RETCODE lpDelColset(SCIP_LP *lp, SCIP_SET *set, int *coldstat)
Definition: lp.c:16961
SCIP_RETCODE SCIPlpGetIterations(SCIP_LP *lp, int *iterations)
Definition: lp.c:16888
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
static void adjustLPobjval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr)
Definition: lp.c:14111
int rank
Definition: struct_lp.h:235
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2236
SCIP_DECL_SORTPTRCOMP(SCIProwComp)
Definition: lp.c:901
SCIP_Longint nrootstrongbranchs
Definition: struct_stat.h:160
static void rowSortLP(SCIP_ROW *row)
Definition: lp.c:984
interface methods for specific LP solvers
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5042
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17291
static void colMoveCoef(SCIP_COL *col, int oldpos, int newpos)
Definition: lp.c:1219
int rowssize
Definition: struct_lp.h:309
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:18748
static void rowUpdateAddLP(SCIP_ROW *row)
Definition: lp.c:8481
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2620
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3504
static void markColDeleted(SCIP_COL *col)
Definition: lp.c:7544
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15227
SCIP_RETCODE SCIPlpUpdateVarLb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:15872
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_clp.cpp:1475
static SCIP_RETCODE lpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16160
SCIP_RETCODE SCIProwEnsureSize(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:580
SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
Definition: lp.c:19079
unsigned int nonlprowssorted
Definition: struct_lp.h:169
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:18850
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:18596
int nclockskipsleft
Definition: struct_stat.h:222
SCIP_COL ** cols
Definition: struct_lp.h:283
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:12401
static void colSwapCoefs(SCIP_COL *col, int pos1, int pos2)
Definition: lp.c:1255
int nlpirows
Definition: struct_lp.h:297
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3162
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:638
SCIP_Longint nstrongbranchs
Definition: struct_stat.h:159
#define SCIP_EVENTTYPE_ROWSIDECHANGED
Definition: type_event.h:91
#define SCIP_EVENTTYPE_ROWCHANGED
Definition: type_event.h:122
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3086
static const int nscalars
Definition: lp.c:5507
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:7842
static void substituteMIRRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int nrowinds, SCIP_Real f0)
Definition: lp.c:10827
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_clp.cpp:1513
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:18984
SCIP_Longint nrootsblpiterations
Definition: struct_stat.h:62
enum SCIP_ClockType SCIP_CLOCKTYPE
Definition: type_clock.h:38
SCIP_RETCODE SCIPlpUpdateVarLbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:15844
SCIP_ROW ** rows
Definition: struct_lp.h:149
#define FALSE
Definition: def.h:56
int lppos
Definition: struct_lp.h:160
SCIP_Real lazylb
Definition: struct_lp.h:129
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1830
void SCIPsortIntPtrIntReal(int *intarray1, void **ptrarray, int *intarray2, SCIP_Real *realarray, int len)
void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_RETCODE SCIPlpWrite(SCIP_LP *lp, const char *fname)
Definition: lp.c:18179
int pseudoobjvalinf
Definition: struct_lp.h:316
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:19393
static SCIP_RETCODE ensureLazycolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:262
SCIP_RETCODE SCIPlpUpdateVarUbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:15913
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5721
static void recomputeLooseObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:730
static SCIP_RETCODE insertColChgcols(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:3425
int divinglpiitlim
Definition: struct_lp.h:320
SCIP_Bool solved
Definition: struct_lp.h:338
static SCIP_RETCODE colAddCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val, int linkpos)
Definition: lp.c:1649
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:8455
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_Longint nrootlps
Definition: struct_stat.h:143
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17169
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2518
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5292
SCIP_RETCODE SCIPlpIsInfeasibilityProved(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool *proved)
Definition: lp.c:18157
#define TRUE
Definition: def.h:55
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:18963
static SCIP_RETCODE lpFlushAddRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:7870
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool lpifromscratch
Definition: struct_lp.h:354
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_clp.cpp:538
unsigned int basisstatus
Definition: struct_lp.h:236
static SCIP_RETCODE lpSetBarrierconvtol(SCIP_LP *lp, SCIP_Real barrierconvtol, SCIP_Bool *success)
Definition: lp.c:2711
void SCIPcolSort(SCIP_COL *col)
Definition: lp.c:3241
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6487
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:12339
SCIP_Real SCIPlpGetRootColumnObjval(SCIP_LP *lp)
Definition: lp.c:19328
void SCIPlpStartStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:17997
SCIP_Real dualsol
Definition: struct_lp.h:97
SCIP_Real redcost
Definition: struct_lp.h:137
static SCIP_RETCODE lpCheckIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value)
Definition: lp.c:2528
SCIP_RETCODE SCIProwChgCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val)
Definition: lp.c:5242
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_clp.cpp:3447
SCIP_Bool pseudoobjvalid
Definition: struct_lp.h:332
SCIP_RETCODE SCIPlpSetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LPISTATE *lpistate, SCIP_Bool wasprimfeas, SCIP_Bool wasdualfeas)
Definition: lp.c:12363
unsigned int sbdownvalid
Definition: struct_lp.h:176
unsigned int objchanged
Definition: struct_lp.h:170
#define DIVESTACKGROWFACT
Definition: lp.c:17940
unsigned int delaysort
Definition: struct_lp.h:239
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4766
unsigned int basisstatus
Definition: struct_lp.h:167
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
SCIP_Real lpidualfeastol
Definition: struct_lp.h:273
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:61
SCIP_RETCODE SCIPlpRemoveNewObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:17308
SCIP_Real sbsolval
Definition: struct_lp.h:143
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_clp.cpp:1567
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5389
static SCIP_RETCODE lpSetLPInfo(SCIP_LP *lp, SCIP_Bool lpinfo)
Definition: lp.c:3000
static void freeDiveChgSideArrays(SCIP_LP *lp)
Definition: lp.c:8637
SCIP_Real sumnorm
Definition: struct_lp.h:197
int lpifastmip
Definition: struct_lp.h:322
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6643
static void rowAddNorms(SCIP_ROW *row, SCIP_SET *set, SCIP_COL *col, SCIP_Real val, SCIP_Bool updateidxvals)
Definition: lp.c:1859
SCIP_RETCODE SCIPlpEndDive(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_VAR **vars, int nvars)
Definition: lp.c:17761
SCIP_RETCODE SCIProwMakeIntegral(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Bool *success)
Definition: lp.c:5745
int index
Definition: struct_lp.h:155
SCIP_Real relpseudoobjval
Definition: struct_lp.h:267
static SCIP_RETCODE lpSetPresolving(SCIP_LP *lp, SCIP_Bool presolving, SCIP_Bool *success)
Definition: lp.c:2849
SCIP_Real dualfarkas
Definition: struct_lp.h:203
static void sumStrongCGRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int *nrowinds, SCIP_Bool *emptyrow, SCIP_Bool *localrowsused, SCIP_Bool *rowtoolong, int *cutrank)
Definition: lp.c:11280
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:14511
SCIP_Real minprimsol
Definition: struct_lp.h:139
SCIP_CLOCK * barrierlptime
Definition: struct_stat.h:122
static SCIP_RETCODE updateLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:14429
SCIP_Real pseudoobjval
Definition: struct_lp.h:265
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:19188
SCIP_Bool diving
Definition: struct_lp.h:349
#define SCIPdebugMessage
Definition: pub_message.h:77
static SCIP_RETCODE lpFlushDelCols(SCIP_LP *lp)
Definition: lp.c:7566
static void lpUpdateObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real deltaval, int deltainf, SCIP_Bool local, SCIP_Bool loose, SCIP_Bool global)
Definition: lp.c:15595
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15256
SCIP_Real rootlooseobjval
Definition: struct_lp.h:269
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_RETCODE SCIPcolIncCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real incval)
Definition: lp.c:3370
int firstnewcol
Definition: struct_lp.h:308
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
SCIP_RETCODE SCIPlpCleanupAll(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:17547
SCIP_RETCODE SCIPcolDelCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row)
Definition: lp.c:3274
SCIP_RETCODE SCIProwCreate(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, const char *name, int len, SCIP_COL **cols, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_ROWORIGINTYPE origintype, void *origin, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: lp.c:4894
unsigned int coefchanged
Definition: struct_lp.h:173
SCIP_RETCODE SCIPlpUpdateAges(SCIP_LP *lp, SCIP_STAT *stat)
Definition: lp.c:16903
unsigned int integral
Definition: struct_lp.h:244
static SCIP_RETCODE colStoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem)
Definition: lp.c:421
int SCIProwGetLPDepth(SCIP_ROW *row)
Definition: lp.c:19115
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lp.c:12442
static int colSearchCoef(SCIP_COL *col, const SCIP_ROW *row)
Definition: lp.c:1088
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
#define SCIP_EVENTTYPE_ROWDELETEDLP
Definition: type_event.h:88
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5314
static SCIP_RETCODE lpSetPricing(SCIP_LP *lp, SCIP_PRICING pricing)
Definition: lp.c:2935
static void rowSortNonLP(SCIP_ROW *row)
Definition: lp.c:1017
#define SCIP_LONGINT_MAX
Definition: def.h:113
static SCIP_RETCODE ensureChgcolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:147
int lpifirstchgcol
Definition: struct_lp.h:295
int index
Definition: struct_lp.h:221
unsigned int basisstatus
Definition: struct_lp.h:99
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_RETCODE SCIPlpEndProbing(SCIP_LP *lp)
Definition: lp.c:17982
static SCIP_RETCODE lpSetRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value, SCIP_Bool *success)
Definition: lp.c:2500
#define checkRow(row)
Definition: lp.c:646
SCIP_Real SCIPsetSumFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5534
int maxdepth
Definition: struct_stat.h:183
static SCIP_RETCODE reallocDiveChgSideArrays(SCIP_LP *lp, int minsize, SCIP_Real growfact)
Definition: lp.c:8611
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:74
int looseobjvalinf
Definition: struct_lp.h:313
SCIP_Real obj
Definition: struct_var.h:201
SCIP_Bool flushdeletedcols
Definition: struct_lp.h:333
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2556
unsigned int rhschanged
Definition: struct_lp.h:242
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition: lp.c:5294
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_clp.cpp:1273
int nlpcols
Definition: struct_lp.h:224
SCIP_COL ** lpicols
Definition: struct_lp.h:279
static SCIP_RETCODE lpAlgorithm(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPALGO lpalgo, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool *timelimit, SCIP_Bool *lperror)
Definition: lp.c:13595
unsigned int lprowssorted
Definition: struct_lp.h:168
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:15060
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5378
SCIP_Longint SCIPcolGetStrongbranchLPAge(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4532
SCIP_Real dualzeroittime
Definition: struct_stat.h:102
internal methods for LP management
int lazycolssize
Definition: struct_lp.h:305
static SCIP_RETCODE lpUpdateVarColumnProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16073
static void recomputeGlbPseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:814
SCIP_Real objprod
Definition: struct_lp.h:198
SCIP_Bool SCIPlpIsRootLPRelax(SCIP_LP *lp)
Definition: lp.c:19306
int colssize
Definition: struct_lp.h:303
SCIP_Bool objsqrnormunreliable
Definition: struct_lp.h:328
SCIP_RETCODE SCIPlpRecordOldRowSideDive(SCIP_LP *lp, SCIP_ROW *row, SCIP_SIDETYPE sidetype)
Definition: lp.c:17943
SCIP_Bool lpihasfastmip
Definition: struct_lp.h:361
SCIP_Bool divelpwasdualfeas
Definition: struct_lp.h:368
SCIP_Bool lpipresolving
Definition: struct_lp.h:356
int nremovablerows
Definition: struct_lp.h:311
SCIP_Real SCIProwGetScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:6687
SCIP_Real lpiuobjlim
Definition: struct_lp.h:271
SCIP_Bool strongbranching
Definition: struct_lp.h:346
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1245
SCIP_Bool dualfeasible
Definition: struct_lp.h:111
#define checkLinks(lp)
Definition: lp.c:1575
SCIP_Longint nsblpiterations
Definition: struct_stat.h:61
int lpithreads
Definition: struct_lp.h:323
int ndivechgsides
Definition: struct_lp.h:318
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:19178
#define EPSISINT(x, eps)
Definition: def.h:164
static void checkLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:14402
SCIP_Real primalzeroittime
Definition: struct_stat.h:101
int * linkpos
Definition: struct_lp.h:218
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2604
#define FEASTOLTIGHTFAC
Definition: lp.c:13674
#define SCIP_DEFAULT_EPSILON
Definition: def.h:133
static SCIP_RETCODE lpSolveStable(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LPALGO lpalgo, int itlim, int harditlim, SCIP_Bool resolve, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, SCIP_Bool keepsol, SCIP_Bool *timelimit, SCIP_Bool *lperror)
Definition: lp.c:13677
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5274
#define BMSfreeBlockMemoryNull(mem, ptr)
Definition: memory.h:420
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition: lp.c:18662
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
Definition: set.c:6042
static SCIP_RETCODE colLink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2296
SCIP_Real * vals
Definition: struct_lp.h:217
unsigned int integral
Definition: struct_lp.h:174
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:7215
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:2693
SCIP_RETCODE SCIPlpCalcStrongCG(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, int *rowinds, int nrowinds, SCIP_Real scale, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank)
Definition: lp.c:12136
int nloosevars
Definition: struct_lp.h:314
static void rowDelNorms(SCIP_ROW *row, SCIP_SET *set, SCIP_COL *col, SCIP_Real val, SCIP_Bool forcenormupdate, SCIP_Bool updateindex, SCIP_Bool updateval)
Definition: lp.c:1928
SCIP_Real SCIPlpGetRootObjval(SCIP_LP *lp)
Definition: lp.c:19316
SCIP_Longint nlexduallpiterations
Definition: struct_stat.h:51
SCIP_Real SCIPcolCalcRedcost(SCIP_COL *col, SCIP_Real *dualsol)
Definition: lp.c:3653
static void rowCalcIdxsAndVals(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4623
int lppos
Definition: struct_lp.h:227
void SCIProwForceSort(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:5923
int divechgsidessize
Definition: struct_lp.h:319
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5220
SCIP_RETCODE SCIPlpCleanupNew(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:17508
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18726
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18674
int * linkpos
Definition: struct_lp.h:154
SCIP_Bool rootlpisrelax
Definition: struct_lp.h:342
SCIP_Bool SCIPsetIsSumLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5447
SCIP_Real flushedlb
Definition: struct_lp.h:134
int lpiitlim
Definition: struct_lp.h:321
#define BMSfreeMemoryNull(ptr)
Definition: memory.h:101
void SCIProwUnlock(SCIP_ROW *row)
Definition: lp.c:5159
SCIP_Real barrierzeroittime
Definition: struct_stat.h:103
SCIP_Real lb
Definition: struct_lp.h:126
SCIP_Real dualsol
Definition: struct_lp.h:201
SCIP_RETCODE SCIProwCatchEvent(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: lp.c:7480
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_clp.cpp:1255
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lpi_clp.cpp:3409
SCIP_Real lpibarrierconvtol
Definition: struct_lp.h:274
SCIP_RETCODE SCIPcolAddCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: lp.c:3253
int glbpseudoobjvalinf
Definition: struct_lp.h:315
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition: lp.c:19219
SCIP_RETCODE SCIPlpUpdateVarUb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:15940
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:416
static SCIP_RETCODE rowUnlink(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:2422
static SCIP_RETCODE lpUpdateVarLooseProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16205
static SCIP_RETCODE colRestoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer)
Definition: lp.c:448
SCIP_RETCODE SCIPlpStartDive(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:17660
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18784
SCIP_Real sbdown
Definition: struct_lp.h:141
int SCIProwGetMinidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6471
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition: lp.c:17967
SCIP_RETCODE SCIProwChgLhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real lhs)
Definition: lp.c:5429
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2393
SCIP_ROW ** divechgrows
Definition: struct_lp.h:289
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17303
SCIP_Real lpirowrepswitch
Definition: struct_lp.h:365
static SCIP_RETCODE lpFlushDelRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: lp.c:7822
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1715
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:19034
SCIP_RETCODE SCIPlpWriteMip(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *fname, SCIP_Bool genericnames, SCIP_Bool origobj, SCIP_OBJSENSE objsense, SCIP_Real objscale, SCIP_Real objoffset, SCIP_Bool lazyconss)
Definition: lp.c:18194
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:18705
SCIP_Bool installing
Definition: struct_lp.h:345
internal methods for storing and manipulating the main problem
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Real *intval)
Definition: lp.c:4683
SCIP_Real SCIPsetLpfeastol(SCIP_SET *set)
Definition: set.c:5104
#define SCIPerrorMessage
Definition: pub_message.h:45
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:662
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:16283
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
interval arithmetics for provable bounds
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7403
#define SCIPdebugPrintf
Definition: pub_message.h:80
SCIP_Real sqrnorm
Definition: struct_lp.h:196
SCIP_Longint lpcount
Definition: struct_stat.h:141
SCIP_Bool lpilpinfo
Definition: struct_lp.h:357
void SCIPsortPtrRealInt(void **ptrarray, SCIP_Real *realarray, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18639
SCIP_Real pseudoactivity
Definition: struct_lp.h:204
SCIP_PRICING lpipricing
Definition: struct_lp.h:325
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition: lp.c:8963
SCIP_COL ** cols
Definition: struct_lp.h:215
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
int SCIProwGetAge(SCIP_ROW *row)
Definition: lp.c:18994
static void colSortNonLP(SCIP_COL *col)
Definition: lp.c:953
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_clp.cpp:1536
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:19004
SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
Definition: lp.c:9146
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:19168
SCIP_Bool adjustlpval
Definition: struct_lp.h:353
#define debugColPrint(x)
Definition: lp.c:138
SCIP_Real minval
Definition: struct_lp.h:200
static SCIP_Real colCalcInternalFarkasCoef(SCIP_COL *col)
Definition: lp.c:3888
SCIP_Real flushedub
Definition: struct_lp.h:135
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3312
SCIP_ROW ** lpirows
Definition: struct_lp.h:280
unsigned int sbupvalid
Definition: struct_lp.h:178
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2169
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2427
static SCIP_RETCODE lpCleanupRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int firstrow)
Definition: lp.c:17437
static void addRowToAggregation(SCIP_SET *set, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, SCIP_ROW *row, SCIP_Real weight, SCIP_Bool uselhs)
Definition: lp.c:9638
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5493
SCIP_Longint validfarkaslp
Definition: struct_lp.h:292
SCIP_RETCODE SCIPlpSumRows(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *weights, SCIP_REALARRAY *sumcoef, SCIP_Real *sumlhs, SCIP_Real *sumrhs)
Definition: lp.c:9459
int SCIPcolGetNStrongbranchs(SCIP_COL *col)
Definition: lp.c:18816
SCIP_Longint validactivitybdsdomchg
Definition: struct_lp.h:208
SCIP_Real lhs
Definition: struct_lp.h:192
void SCIPlpMarkSize(SCIP_LP *lp)
Definition: lp.c:9302
SCIP_Real SCIPsetBarrierconvtol(SCIP_SET *set)
Definition: set.c:5125
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
#define BMSallocMemory(ptr)
Definition: memory.h:74
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:19024
#define SCIP_EVENTTYPE_ROWCONSTCHANGED
Definition: type_event.h:90
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
int nuses
Definition: struct_lp.h:226
static SCIP_Real getMIRRowActivity(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Real *mircoef, int *varinds, int nvarinds)
Definition: lp.c:11012
static SCIP_RETCODE rowAddCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val, int linkpos)
Definition: lp.c:1986
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3696
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5758
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_clp.cpp:844
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:411
SCIP_Real SCIProwGetNLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6100
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_clp.cpp:1007
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1821
SCIP_RETCODE SCIPlpGetUnboundedSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *rayfeasible)
Definition: lp.c:16595
void SCIProwDelaySort(SCIP_ROW *row)
Definition: lp.c:5912
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_clp.cpp:2634
SCIP_Real cutoffbound
Definition: struct_lp.h:270
SCIP_Real SCIProwGetPseudoFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6214
SCIP_Longint nsbdivinglpiterations
Definition: struct_stat.h:60
SCIP_RETCODE SCIPlpAddRow(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_ROW *row, int depth)
Definition: lp.c:9022
internal miscellaneous methods
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13451
static SCIP_RETCODE lpPrimalSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12545
SCIP_Bool isrelax
Definition: struct_lp.h:343
SCIP_Real SCIPlpGetObjNorm(SCIP_LP *lp)
Definition: lp.c:19283
SCIP_Longint nprimalresolvelpiterations
Definition: struct_stat.h:53
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
SCIP_Real SCIPsetFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5400
int maxidx
Definition: struct_lp.h:231
SCIP_LPSOLVALS * storedsolvals
Definition: struct_lp.h:290
static SCIP_RETCODE lpSetFeastol(SCIP_LP *lp, SCIP_Real feastol, SCIP_Bool *success)
Definition: lp.c:2639
SCIP_Bool looseobjvalid
Definition: struct_lp.h:330
static void roundMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Real f0)
Definition: lp.c:10640
const char * SCIPlpiGetSolverName(void)
Definition: lpi_clp.cpp:433
SCIP_RETCODE SCIPlpGetDualfarkas(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:16822
internal methods for global SCIP settings
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2500
SCIP_Real activity
Definition: struct_lp.h:98
static SCIP_RETCODE lpSetScaling(SCIP_LP *lp, SCIP_Bool scaling, SCIP_Bool *success)
Definition: lp.c:2799
static void sumMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real knownmaxweight, int *sidetypes, SCIP_Real scale, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Bool compress, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int *nrowinds, SCIP_Bool *emptyrow, SCIP_Bool *localrowsused, SCIP_Bool *rowtoolong, int *cutrank)
Definition: lp.c:9709
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5666
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:82
static void rowCalcActivityBounds(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6290
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:18773
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:19198
#define BMSfreeMemory(ptr)
Definition: memory.h:100
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:578
SCIP_Longint nlpsaftercreation
Definition: struct_lp.h:211
void SCIPlpMarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:19423
SCIP_Longint nduallpiterations
Definition: struct_stat.h:50
SCIP_Longint nbarrierzeroitlps
Definition: struct_stat.h:150
SCIP_Bool flushaddedrows
Definition: struct_lp.h:336
SCIP_Bool resolvelperror
Definition: struct_lp.h:352
unsigned int removable
Definition: struct_lp.h:175
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
static SCIP_RETCODE lpFlushChgCols(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8017
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2374
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5202
#define lpCutoffDisabled(set)
Definition: lp.c:2593
int lpicolssize
Definition: struct_lp.h:293
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:19350
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15076
SCIP_LPI * lpi
Definition: struct_lp.h:278
void SCIProwLock(SCIP_ROW *row)
Definition: lp.c:5144
unsigned int eventmask
Definition: struct_event.h:179
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:5065
static SCIP_RETCODE rowLink(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2379
static SCIP_RETCODE colDelCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos)
Definition: lp.c:1770
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:876
SCIP_Real glbpseudoobjval
Definition: struct_lp.h:262
SCIP_Bool SCIPcolIsRemovable(SCIP_COL *col)
Definition: lp.c:18716
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5622
SCIP_Bool SCIProwIsSolEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Bool root)
Definition: lp.c:6587
SCIP_Longint nprimalresolvelps
Definition: struct_stat.h:151
SCIP_SIDETYPE * divechgsidetypes
Definition: struct_lp.h:288
static SCIP_RETCODE rowSideChanged(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp, SCIP_SIDETYPE sidetype)
Definition: lp.c:2243
SCIP_RETCODE SCIPlpStartStrongbranch(SCIP_LP *lp)
Definition: lp.c:3986
SCIP_CLOCK * divinglptime
Definition: struct_stat.h:123
static SCIP_RETCODE rowEventSideChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1475
static SCIP_RETCODE allocDiveChgSideArrays(SCIP_LP *lp, int initsize)
Definition: lp.c:8589
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_clp.cpp:2652
static void colUpdateAddLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8441
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5118
int var_probindex
Definition: struct_lp.h:166
static SCIP_RETCODE lpSolve(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LPALGO lpalgo, int resolveitlim, int harditlim, SCIP_Bool needprimalray, SCIP_Bool needdualray, SCIP_Bool resolve, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:14142
SCIP_Longint nduallps
Definition: struct_stat.h:146
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:103
SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
Definition: lp.c:18652
SCIP_Real SCIProwGetSolActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6230
SCIP_Real sblpobjval
Definition: struct_lp.h:144
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17205
internal methods for problem variables
SCIP_Real SCIPcolGetBestBound(SCIP_COL *col)
Definition: lp.c:18626
static void computeLPBounds(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, SCIP_Real lpiinf, SCIP_Real *lb, SCIP_Real *ub)
Definition: lp.c:7615
#define SCIP_UNKNOWN
Definition: def.h:148
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_RETCODE SCIPlpGetBasisInd(SCIP_LP *lp, int *basisind)
Definition: lp.c:9328
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5325
int nchgcols
Definition: struct_lp.h:300
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
int len
Definition: struct_lp.h:157
SCIP_Real SCIPlpGetRootLooseObjval(SCIP_LP *lp)
Definition: lp.c:19340
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:19137
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17444
SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9283
#define SCIP_Bool
Definition: def.h:53
void SCIPlpRecomputeLocalAndGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15159
SCIP_Real redcost
Definition: struct_lp.h:86
SCIP_Real SCIPsetSumepsilon(SCIP_SET *set)
Definition: set.c:5074
SCIP_Longint ndualresolvelps
Definition: struct_stat.h:152
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:408
int numminval
Definition: struct_lp.h:233
int lpipos
Definition: struct_lp.h:228
int size
Definition: struct_lp.h:222
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_clp.cpp:3491
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition: lp.c:18891
unsigned int modifiable
Definition: struct_lp.h:246
static void recomputePseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:772
int ncontvars
Definition: struct_prob.h:64
void SCIPprintSysError(const char *message)
Definition: misc.c:8110
static SCIP_RETCODE lpDelRowset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int *rowdstat)
Definition: lp.c:17059
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_RETCODE SCIPlpFree(SCIP_LP **lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:8890
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, int *ind, SCIP_Real *obj)
Definition: lpi_clp.cpp:1078
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_clp.cpp:2696
static void rowMerge(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:5813
#define SCIP_EVENTTYPE_ROWCOEFCHANGED
Definition: type_event.h:89
static SCIP_Real colCalcInternalRedcost(SCIP_COL *col)
Definition: lp.c:3705
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17313
SCIP_RETCODE SCIPeventCreateRowSideChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:867
SCIP_Longint nlexdualresolvelpiterations
Definition: struct_stat.h:55
int chgrowssize
Definition: struct_lp.h:301
SCIP_ROW ** SCIPlpGetNewrows(SCIP_LP *lp)
Definition: lp.c:19230
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_clp.cpp:3639
SCIP_Longint validfarkaslp
Definition: struct_lp.h:152
static SCIP_RETCODE ensureRowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:285
unsigned int lbchanged
Definition: struct_lp.h:171
SCIP_Bool divingobjchg
Definition: struct_lp.h:350
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:16915
SCIP_RETCODE SCIPlpGetBInvRow(SCIP_LP *lp, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9362
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
SCIP_Longint sbnode
Definition: struct_lp.h:145
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:19413
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3563
#define MAX(x, y)
Definition: tclique_def.h:75
static int colSearchCoefPart(SCIP_COL *col, const SCIP_ROW *row, int minpos, int maxpos)
Definition: lp.c:1052
unsigned int basisstatus
Definition: struct_lp.h:87
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17281
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2190
#define DIVESTACKINITSIZE
Definition: lp.c:8654
SCIP_Longint lastdivenode
Definition: struct_stat.h:82
SCIP_Real unchangedobj
Definition: struct_lp.h:128
void SCIPcolSetStrongbranchData(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real lpobjval, SCIP_Real primsol, SCIP_Real sbdown, SCIP_Real sbup, SCIP_Bool sbdownvalid, SCIP_Bool sbupvalid, SCIP_Longint iter, int itlim)
Definition: lp.c:4016
int minidx
Definition: struct_lp.h:230
static SCIP_RETCODE rowDelCoefPos(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos)
Definition: lp.c:2127
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2140
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_clp.cpp:2798
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:419
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
int nlprows
Definition: struct_lp.h:158
SCIP_RETCODE SCIProwDelCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col)
Definition: lp.c:5196
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1632
SCIP_RETCODE SCIPlpCreate(SCIP_LP **lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *name)
Definition: lp.c:8657
SCIP_RETCODE SCIPlpGetBase(SCIP_LP *lp, int *cstat, int *rstat)
Definition: lp.c:9345
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:18826
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:736
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17249
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
unsigned int lpcolssorted
Definition: struct_lp.h:237
SCIP_Bool divinglazyapplied
Definition: struct_lp.h:351
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18606
SCIP_Longint validsollp
Definition: struct_lp.h:291
SCIP_RETCODE SCIPsetSetCharParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *name, char value)
Definition: set.c:2910
void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
Definition: lp.c:9314
#define debugRowPrint(x)
Definition: lp.c:106
static void colSortLP(SCIP_COL *col)
Definition: lp.c:920
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13177
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:782
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6544
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_clp.cpp:3775
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6603
static SCIP_RETCODE ensureColsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:239
SCIP_Real ub
Definition: struct_lp.h:127
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2326
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:17586
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5600
SCIP_Bool SCIPsetIsSumEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5411
SCIP_ROW ** rows
Definition: struct_lp.h:285
SCIP_Longint validredcostlp
Definition: struct_lp.h:151
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3608
static int rowSearchCoef(SCIP_ROW *row, const SCIP_COL *col)
Definition: lp.c:1166
SCIP_LPISTATE * divelpistate
Definition: struct_lp.h:286
SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:12418
SCIP_RETCODE SCIPsetGetCharParam(SCIP_SET *set, const char *name, char *value)
Definition: set.c:2650
SCIP_RETCODE SCIProwDropEvent(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: lp.c:7504
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3183
void SCIPcolPrint(SCIP_COL *col, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:3213
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition: lp.c:14491
static int rowSearchCoefPart(SCIP_ROW *row, const SCIP_COL *col, int minpos, int maxpos)
Definition: lp.c:1127
SCIP_RETCODE SCIPeventCreateRowCoefChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:819
SCIP_Real flushedrhs
Definition: struct_lp.h:195
static void getObjvalDeltaObj(SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj, SCIP_Real lb, SCIP_Real ub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:15381
SCIP_CLOCK * lexduallptime
Definition: struct_stat.h:121
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7435
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3393
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17431
SCIP_RETCODE SCIPlpReset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:8934
SCIP_RETCODE SCIPcolGetStrongbranches(SCIP_COL **cols, int ncols, SCIP_Bool integral, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *lperror)
Definition: lp.c:4264
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_Real maxval
Definition: struct_lp.h:199
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5912
SCIP_Real minactivity
Definition: struct_lp.h:205
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6371
SCIP_Real rhs
Definition: struct_lp.h:193
static void getObjvalDeltaLb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:15513
static SCIP_RETCODE lpBarrier(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool crossover, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:13458
SCIP_Longint nrootlpiterations
Definition: struct_stat.h:47
SCIP_Real constant
Definition: struct_lp.h:191
#define checkRowObjprod(row)
Definition: lp.c:721
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15115
static SCIP_RETCODE provedBound(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool usefarkas, SCIP_Real *bound)
Definition: lp.c:18033
static void markRowDeleted(SCIP_ROW *row)
Definition: lp.c:7806
SCIP_Real SCIPlpGetModifiedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:15283
unsigned int removable
Definition: struct_lp.h:247
static SCIP_RETCODE rowRestoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer, SCIP_Bool infeasible)
Definition: lp.c:532
unsigned int lhschanged
Definition: struct_lp.h:241
static SCIP_RETCODE lpCheckRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value)
Definition: lp.c:2564
SCIP_CLOCK * strongbranchtime
Definition: struct_stat.h:124
SCIP_COL ** lazycols
Definition: struct_lp.h:284
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_clp.cpp:941
static SCIP_RETCODE rowEventCoefChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1417
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5747
SCIP_Real relglbpseudoobjval
Definition: struct_lp.h:264
int sbitlim
Definition: struct_lp.h:163
static SCIP_RETCODE lpRemoveObsoleteCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:17156
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17271
void SCIPlpStoreRootObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:15135
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_Bool SCIProwIsLPEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool root)
Definition: lp.c:6528
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2588
int age
Definition: struct_lp.h:165
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3202
SCIP_Longint validpsactivitydomchg
Definition: struct_lp.h:207
SCIP_COLSOLVALS * storedsolvals
Definition: struct_lp.h:147
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:18935
SCIP_Real * vals
Definition: struct_lp.h:150
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6350
SCIP_Bool strongbranchprobing
Definition: struct_lp.h:348
SCIP_Real rellooseobjval
Definition: struct_lp.h:260
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:108
SCIP_Longint SCIProwGetActiveLPCount(SCIP_ROW *row)
Definition: lp.c:19148
static void rowUpdateDelLP(SCIP_ROW *row)
Definition: lp.c:8555
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:12476
static const SCIP_Real scalars[]
Definition: lp.c:5506
int lpipos
Definition: struct_lp.h:161
int chgcolssize
Definition: struct_lp.h:299
static void substituteStrongCGRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int nrowinds, SCIP_Real f0, SCIP_Real k)
Definition: lp.c:11981
int lpitiming
Definition: struct_lp.h:324
#define REALABS(x)
Definition: def.h:151
internal methods for main solving loop and node processing
SCIP_Longint domchgcount
Definition: struct_stat.h:85
SCIP_ROWSOLVALS * storedsolvals
Definition: struct_lp.h:212
SCIP_Real * divechgsides
Definition: struct_lp.h:287
SCIP_RETCODE SCIPlpMarkFlushed(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8313
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3242
static void coefChanged(SCIP_ROW *row, SCIP_COL *col, SCIP_LP *lp)
Definition: lp.c:1584
SCIP_Real rootlpobjval
Definition: struct_lp.h:268
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_clp.cpp:469
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1675
unsigned int coefchanged
Definition: struct_lp.h:243
SCIP_CLOCK * solvingtime
Definition: struct_stat.h:115
SCIP_Longint nbarrierlps
Definition: struct_stat.h:149
SCIP_Longint nprimalzeroitlps
Definition: struct_stat.h:145
SCIP_Bool flushed
Definition: struct_lp.h:337
static SCIP_RETCODE lpFlushChgRows(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8161
SCIP_CLOCK * primallptime
Definition: struct_stat.h:119
SCIP_RETCODE SCIPlpUpdateVarObj(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:15790
SCIP_Real SCIPsetSumCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5545
int lpdepth
Definition: struct_lp.h:162
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
unsigned int inglobalcutpool
Definition: struct_lp.h:248
int nrows
Definition: struct_lp.h:310
#define checkRowSqrnorm(row)
Definition: lp.c:719
static SCIP_RETCODE lpRemoveObsoleteRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int firstrow)
Definition: lp.c:17232
#define SCIP_DEFAULT_SUMEPSILON
Definition: def.h:134
static SCIP_RETCODE lpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16026
static SCIP_RETCODE ensureChgrowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:170
public methods for message output
static void rowCalcNorms(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4564
SCIP_Bool divelpwasprimfeas
Definition: struct_lp.h:367
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:602
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6018
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5256
int ndivingrows
Definition: struct_lp.h:317
void SCIPsortDownInt(int *intarray, int len)
SCIP_Real lpobjval
Definition: struct_lp.h:257
SCIP_RETCODE SCIPcolGetStrongbranch(SCIP_COL *col, SCIP_Bool integral, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *lperror)
Definition: lp.c:4105
SCIP_Real primsol
Definition: struct_lp.h:85
SCIP_Longint SCIPcolGetStrongbranchNode(SCIP_COL *col)
Definition: lp.c:18806
SCIP_Bool SCIProwIsIntegral(SCIP_ROW *row)
Definition: lp.c:19014
#define SCIP_Real
Definition: def.h:127
internal methods for problem statistics
SCIP_Bool solisbasic
Definition: struct_lp.h:112
SCIP_VAR ** vars
Definition: struct_prob.h:54
SCIP_Real flushedobj
Definition: struct_lp.h:133
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:19383
int size
Definition: struct_lp.h:156
#define MIN(x, y)
Definition: memory.c:67
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7447
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5699
SCIP_Longint validsblp
Definition: struct_lp.h:153
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:2417
void SCIProwSort(SCIP_ROW *row)
Definition: lp.c:5780
SCIP_Real SCIPsetDualfeastol(SCIP_SET *set)
Definition: set.c:5094
static SCIP_RETCODE lpSetUobjlim(SCIP_LP *lp, SCIP_SET *set, SCIP_Real uobjlim)
Definition: lp.c:2597
int lpirowssize
Definition: struct_lp.h:296
int nunlinked
Definition: struct_lp.h:159
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:19054
SCIP_Real SCIPcolGetFarkasValue(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3967
static void findBestLb(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_SOL *sol, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *bestlb, int *bestlbtype)
Definition: lp.c:9968
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_clp.cpp:2281
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1795
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16262
#define SCIP_INVALID
Definition: def.h:147
SCIP_RETCODE SCIProwChgRhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real rhs)
Definition: lp.c:5461
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2215
SCIP_Real primsol
Definition: struct_lp.h:136
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:19373
SCIP_CLOCK * duallptime
Definition: struct_stat.h:120
SCIP_Real maxprimsol
Definition: struct_lp.h:140
#define SCIP_Longint
Definition: def.h:112
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5901
static const char * lpalgoName(SCIP_LPALGO lpalgo)
Definition: lp.c:12522
static SCIP_RETCODE lpSetPricingChar(SCIP_LP *lp, char pricingchar)
Definition: lp.c:2958
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_clp.cpp:2753
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3054
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:16765
SCIP_Longint nprimallpiterations
Definition: struct_stat.h:49
static SCIP_RETCODE lpSetIterationLimit(SCIP_LP *lp, int itlim)
Definition: lp.c:2899
SCIP_RETCODE SCIProwCalcIntegralScalar(SCIP_ROW *row, SCIP_SET *set, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: lp.c:5510
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_clp.cpp:705
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5644
SCIP_VAR * var
Definition: struct_lp.h:148
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:19104
SCIP_RETCODE SCIPlpGetBInvARow(SCIP_LP *lp, int r, SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9410
void SCIProwMarkNotRemovableLocal(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:7525
int nlazycols
Definition: struct_lp.h:306
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18616
SCIP_Longint ndualzeroitlps
Definition: struct_stat.h:147
void SCIPintervalSub(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
static SCIP_RETCODE colEnsureSize(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:308
SCIP_Bool dualfeasible
Definition: struct_lp.h:340
static void transformStrongCGRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Bool *freevariable, SCIP_Bool *localbdsused)
Definition: lp.c:11476
SCIP_Real SCIProwGetMaxval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6423
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3941
SCIP_Real SCIProwGetLPActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:5988
unsigned int nlocks
Definition: struct_lp.h:250
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2344
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5923
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:78
SCIP_Real SCIPcolGetFeasibility(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3782
#define EPSEQ(x, y, eps)
Definition: def.h:152
SCIP_Longint obsoletenode
Definition: struct_lp.h:146
SCIP_Real SCIPsetSumFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5567
SCIP_RETCODE SCIPlpGetBInvACol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9435
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16138
SCIP_Longint obsoletenode
Definition: struct_lp.h:209
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:64
SCIP_Real lpifeastol
Definition: struct_lp.h:272
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:15323
static SCIP_Real getFinitePseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:878
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
void SCIPcolInvalidateStrongbranchData(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4070
SCIP_RETCODE SCIPlpUpdateDelVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16002
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:18948
static SCIP_RETCODE rowEventConstantChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1447
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition: lp.c:18903
SCIP_Bool SCIProwIsRemovable(SCIP_ROW *row)
Definition: lp.c:19044
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition: lp.c:19208
SCIP_RETCODE SCIProwAddCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val)
Definition: lp.c:5175
SCIP_Bool primalfeasible
Definition: struct_lp.h:110
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:18794
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:18759
unsigned int validminmaxidx
Definition: struct_lp.h:240
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3758
SCIP_RETCODE SCIPlpGetSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lp.c:16301
#define SCIP_ALLOC(x)
Definition: def.h:277
SCIP_Real SCIPlpGetColumnObjval(SCIP_LP *lp)
Definition: lp.c:15104
void SCIProwRecalcPseudoActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6159
#define SCIPABORT()
Definition: def.h:238
static SCIP_RETCODE lpSetThreads(SCIP_LP *lp, int threads, SCIP_Bool *success)
Definition: lp.c:2824
static SCIP_RETCODE ensureLpicolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:193
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:326
static SCIP_RETCODE rowChgCoefPos(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos, SCIP_Real val)
Definition: lp.c:2187
static SCIP_RETCODE lpSetIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value, SCIP_Bool *success)
Definition: lp.c:2461
unsigned int nonlpcolssorted
Definition: struct_lp.h:238
SCIP_Bool flushaddedcols
Definition: struct_lp.h:334
static SCIP_RETCODE lpLexDualSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12860
SCIP_Bool glbpseudoobjvalid
Definition: struct_lp.h:331
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7083
int SCIPcolGetIndex(SCIP_COL *col)
Definition: lp.c:18695
static SCIP_Real getMaxAbsWeight(SCIP_SET *set, SCIP_LP *lp, SCIP_Real *weights, int *rowinds, int *nrowinds, int *rowlensum)
Definition: lp.c:9591
int ncols
Definition: struct_lp.h:304
static SCIP_RETCODE lpCheckBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value)
Definition: lp.c:2553
SCIP_RETCODE SCIPlpEndStrongbranch(SCIP_LP *lp)
Definition: lp.c:4001
static SCIP_RETCODE lpDualSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12686
SCIP_Real lpobjval
Definition: struct_lp.h:109
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:19434
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:412
SCIP_Real objsqrnorm
Definition: struct_lp.h:276
static void rowMoveCoef(SCIP_ROW *row, int oldpos, int newpos)
Definition: lp.c:1315
static void lpUpdateObjNorms(SCIP_LP *lp, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:3468
unsigned int local
Definition: struct_lp.h:245
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_clp.cpp:3002
SCIP_Real activity
Definition: struct_lp.h:202
SCIP_RETCODE SCIProwFree(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5033
SCIP_Bool probing
Definition: struct_lp.h:347
SCIP_Bool flushdeletedrows
Definition: struct_lp.h:335
SCIP_Real looseobjval
Definition: struct_lp.h:258
static SCIP_RETCODE transformMIRRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Bool *freevariable, SCIP_Bool *localbdsused)
Definition: lp.c:10105
int len
Definition: struct_lp.h:223
int age
Definition: struct_lp.h:234
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_clp.cpp:1780
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5710
static SCIP_RETCODE lpFlushAndSolve(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, int resolveitlim, int harditlim, SCIP_Bool needprimalray, SCIP_Bool needdualray, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:14313
static void checkLazyColArray(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:9093
int SCIPcolGetLPDepth(SCIP_COL *col)
Definition: lp.c:18737
SCIP_Real flushedlhs
Definition: struct_lp.h:194
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition: lp.c:5403
SCIP_RETCODE SCIPeventCreateRowConstChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:844
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:2572
SCIP_Real SCIPcolCalcFarkasCoef(SCIP_COL *col, SCIP_Real *dualfarkas)
Definition: lp.c:3836
SCIP_Real lpiconditionlimit
Definition: struct_lp.h:275
static SCIP_RETCODE lpSetTiming(SCIP_LP *lp, SCIP_CLOCKTYPE timing, SCIP_Bool enabled, SCIP_Bool *success)
Definition: lp.c:3048
SCIP_Longint ndivinglpiterations
Definition: struct_stat.h:58
enum SCIP_SideType SCIP_SIDETYPE
Definition: type_lp.h:58
#define checkRowSumnorm(row)
Definition: lp.c:720