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-2014 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/event.h"
50 #include "scip/pub_message.h"
51 #include "lpi/lpi.h"
52 
53 #define MAXCMIRSCALE 1e+6 /**< maximal scaling (scale/(1-f0)) allowed in c-MIR calculations */
54 
55 
56 
57 /*
58  * debug messages
59  */
60 
61 #ifdef SCIP_DEBUG
62 /** method is to print in row in case SCIP_DEBUG is defined */
63 static
64 void debugRowPrint(
65  SCIP_ROW* row /**< LP row */
66  )
67 {
68  int i;
69 
70  assert(row != NULL);
71 
72  /* print row name */
73  if( row->name != NULL && row->name[0] != '\0' )
74  {
75  SCIPdebugPrintf("%s: ", row->name);
76  }
77 
78  /* print left hand side */
79  SCIPdebugPrintf("%.15g <= ", row->lhs);
80 
81  /* print coefficients */
82  if( row->len == 0 )
83  {
84  SCIPdebugPrintf("0 ");
85  }
86  for( i = 0; i < row->len; ++i )
87  {
88  assert(row->cols[i] != NULL);
89  assert(row->cols[i]->var != NULL);
90  assert(SCIPvarGetName(row->cols[i]->var) != NULL);
91  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
92  SCIPdebugPrintf("%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
93  }
94 
95  /* print constant */
97  {
98  SCIPdebugPrintf("%+.15g ", row->constant);
99  }
100 
101  /* print right hand side */
102  SCIPdebugPrintf("<= %.15g\n", row->rhs);
103 }
104 #else
105 #define debugRowPrint(x) /**/
106 #endif
107 
108 #ifdef SCIP_DEBUG
109 /** method to output column if SCIP_DEBUG is define */
110 static
111 void debugColPrint(
112  SCIP_COL* col /**< LP column */
113  )
114 {
115  int r;
116 
117  assert(col != NULL);
118  assert(col->var != NULL);
119 
120  /* print bounds */
121  SCIPdebugPrintf("(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
122 
123  /* print coefficients */
124  if( col->len == 0 )
125  {
126  SCIPdebugPrintf("<empty>");
127  }
128  for( r = 0; r < col->len; ++r )
129  {
130  assert(col->rows[r] != NULL);
131  assert(col->rows[r]->name != NULL);
132  SCIPdebugPrintf("%+.15g<%s> ", col->vals[r], col->rows[r]->name);
133  }
134  SCIPdebugPrintf("\n");
135 }
136 #else
137 #define debugColPrint(x) /**/
138 #endif
139 
140 /*
141  * memory growing methods for dynamically allocated arrays
142  */
143 
144 /** ensures, that chgcols array can store at least num entries */
145 static
147  SCIP_LP* lp, /**< current LP data */
148  SCIP_SET* set, /**< global SCIP settings */
149  int num /**< minimum number of entries to store */
150  )
151 {
152  assert(lp->nchgcols <= lp->chgcolssize);
153 
154  if( num > lp->chgcolssize )
155  {
156  int newsize;
157 
158  newsize = SCIPsetCalcMemGrowSize(set, num);
159  SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
160  lp->chgcolssize = newsize;
161  }
162  assert(num <= lp->chgcolssize);
163 
164  return SCIP_OKAY;
165 }
166 
167 /** ensures, that chgrows array can store at least num entries */
168 static
170  SCIP_LP* lp, /**< current LP data */
171  SCIP_SET* set, /**< global SCIP settings */
172  int num /**< minimum number of entries to store */
173  )
174 {
175  assert(lp->nchgrows <= lp->chgrowssize);
176 
177  if( num > lp->chgrowssize )
178  {
179  int newsize;
180 
181  newsize = SCIPsetCalcMemGrowSize(set, num);
182  SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
183  lp->chgrowssize = newsize;
184  }
185  assert(num <= lp->chgrowssize);
186 
187  return SCIP_OKAY;
188 }
189 
190 /** ensures, that lpicols array can store at least num entries */
191 static
193  SCIP_LP* lp, /**< current LP data */
194  SCIP_SET* set, /**< global SCIP settings */
195  int num /**< minimum number of entries to store */
196  )
197 {
198  assert(lp->nlpicols <= lp->lpicolssize);
199 
200  if( num > lp->lpicolssize )
201  {
202  int newsize;
203 
204  newsize = SCIPsetCalcMemGrowSize(set, num);
205  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
206  lp->lpicolssize = newsize;
207  }
208  assert(num <= lp->lpicolssize);
209 
210  return SCIP_OKAY;
211 }
212 
213 /** ensures, that lpirows array can store at least num entries */
214 static
216  SCIP_LP* lp, /**< current LP data */
217  SCIP_SET* set, /**< global SCIP settings */
218  int num /**< minimum number of entries to store */
219  )
220 {
221  assert(lp->nlpirows <= lp->lpirowssize);
222 
223  if( num > lp->lpirowssize )
224  {
225  int newsize;
226 
227  newsize = SCIPsetCalcMemGrowSize(set, num);
228  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
229  lp->lpirowssize = newsize;
230  }
231  assert(num <= lp->lpirowssize);
232 
233  return SCIP_OKAY;
234 }
235 
236 /** ensures, that cols array can store at least num entries */
237 static
239  SCIP_LP* lp, /**< current LP data */
240  SCIP_SET* set, /**< global SCIP settings */
241  int num /**< minimum number of entries to store */
242  )
243 {
244  assert(lp->ncols <= lp->colssize);
245 
246  if( num > lp->colssize )
247  {
248  int newsize;
249 
250  newsize = SCIPsetCalcMemGrowSize(set, num);
251  SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
252  lp->colssize = newsize;
253  }
254  assert(num <= lp->colssize);
255 
256  return SCIP_OKAY;
257 }
258 
259 /** ensures, that lazy cols array can store at least num entries */
260 static
262  SCIP_LP* lp, /**< current LP data */
263  SCIP_SET* set, /**< global SCIP settings */
264  int num /**< minimum number of entries to store */
265  )
266 {
267  assert(lp->nlazycols <= lp->lazycolssize);
268 
269  if( num > lp->lazycolssize )
270  {
271  int newsize;
272 
273  newsize = SCIPsetCalcMemGrowSize(set, num);
274  SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
275  lp->lazycolssize = newsize;
276  }
277  assert(num <= lp->lazycolssize);
278 
279  return SCIP_OKAY;
280 }
281 
282 /** ensures, that rows array can store at least num entries */
283 static
285  SCIP_LP* lp, /**< current LP data */
286  SCIP_SET* set, /**< global SCIP settings */
287  int num /**< minimum number of entries to store */
288  )
289 {
290  assert(lp->nrows <= lp->rowssize);
291 
292  if( num > lp->rowssize )
293  {
294  int newsize;
295 
296  newsize = SCIPsetCalcMemGrowSize(set, num);
297  SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
298  lp->rowssize = newsize;
299  }
300  assert(num <= lp->rowssize);
301 
302  return SCIP_OKAY;
303 }
304 
305 /** ensures, that row array of column can store at least num entries */
306 static
308  SCIP_COL* col, /**< LP column */
309  BMS_BLKMEM* blkmem, /**< block memory */
310  SCIP_SET* set, /**< global SCIP settings */
311  int num /**< minimum number of entries to store */
312  )
313 {
314  assert(col != NULL);
315  assert(col->len <= col->size);
316 
317  if( num > col->size )
318  {
319  int newsize;
320 
321  newsize = SCIPsetCalcMemGrowSize(set, num);
322  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
323  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
324  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
325  col->size = newsize;
326  }
327  assert(num <= col->size);
328 
329  return SCIP_OKAY;
330 }
331 
332 /** save current LP values dependent on the solution */
333 static
335  SCIP_LP* lp, /**< LP data */
336  SCIP_STAT* stat, /**< problem statistics */
337  BMS_BLKMEM* blkmem /**< block memory */
338  )
339 {
340  SCIP_LPSOLVALS* storedsolvals;
341 
342  assert(lp != NULL);
343  assert(stat != NULL);
344  assert(blkmem != NULL);
345 
346  /* allocate memory for storage */
347  if( lp->storedsolvals == NULL )
348  {
350  }
351  storedsolvals = lp->storedsolvals;
352 
353  /* store values */
354  storedsolvals->lpsolstat = lp->lpsolstat;
355  storedsolvals->lpobjval = lp->lpobjval;
356  storedsolvals->primalfeasible = lp->primalfeasible;
357  storedsolvals->dualfeasible = lp->dualfeasible;
358  storedsolvals->solisbasic = lp->solisbasic;
359  storedsolvals->lpissolved = lp->solved;
360 
361  return SCIP_OKAY;
362 }
363 
364 /** restore LP solution values in column */
365 static
367  SCIP_LP* lp, /**< LP data */
368  BMS_BLKMEM* blkmem, /**< block memory */
369  SCIP_Longint validlp /**< number of lp for which restored values are valid */
370  )
371 {
372  SCIP_LPSOLVALS* storedsolvals;
373 
374  assert(lp != NULL);
375  assert(blkmem != NULL);
376 
377  /* if stored values are available, restore them */
378  storedsolvals = lp->storedsolvals;
379  if( storedsolvals != NULL )
380  {
381  lp->solved = storedsolvals->lpissolved;
382  lp->validsollp = validlp;
383 
384  lp->lpsolstat = storedsolvals->lpsolstat;
385  lp->lpobjval = storedsolvals->lpobjval;
386  lp->primalfeasible = storedsolvals->primalfeasible;
387  lp->dualfeasible = storedsolvals->dualfeasible;
388  lp->solisbasic = storedsolvals->solisbasic;
389 
390  /* solution values are stored only for LPs solved to optimality or unboundedness */
391  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
397  lp->validsollp == -1);
398  }
399  /* no values available, mark LP as unsolved */
400  else
401  {
402  lp->solved = FALSE;
403  lp->validsollp = -1;
404 
406  lp->lpobjval = SCIP_INVALID;
407  lp->primalfeasible = FALSE;
408  lp->dualfeasible = FALSE;
409  lp->solisbasic = FALSE;
410  lp->validfarkaslp = -1;
411  }
412 
413  /* intentionally keep storage space allocated */
414 
415  return SCIP_OKAY;
416 }
417 
418 /** save current LP solution values stored in each column */
419 static
421  SCIP_COL* col, /**< LP column */
422  BMS_BLKMEM* blkmem /**< block memory */
423  )
424 {
425  SCIP_COLSOLVALS* storedsolvals;
426 
427  assert(col != NULL);
428  assert(blkmem != NULL);
429 
430  /* allocate memory for storage */
431  if( col->storedsolvals == NULL )
432  {
433  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &col->storedsolvals) );
434  }
435  storedsolvals = col->storedsolvals;
436 
437  /* store values */
438  storedsolvals->primsol = col->primsol;
439  storedsolvals->redcost = col->redcost;
440  storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
441 
442  return SCIP_OKAY;
443 }
444 
445 /** restore LP solution values in column */
446 static
448  SCIP_COL* col, /**< LP column */
449  BMS_BLKMEM* blkmem, /**< block memory */
450  SCIP_Longint validlp, /**< number of lp for which restored values are valid */
451  SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */
452  )
453 {
454  SCIP_COLSOLVALS* storedsolvals;
455 
456  assert(col != NULL);
457  assert(blkmem != NULL);
458 
459  /* if stored values are available, restore them */
460  storedsolvals = col->storedsolvals;
461  if( storedsolvals != NULL )
462  {
463  col->primsol = storedsolvals->primsol;
464  col->redcost = storedsolvals->redcost;
465  col->validredcostlp = validlp;
466  col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
467 
468  /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
469  col->validfarkaslp = -1;
470  }
471  /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
472  * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
473  */
474  else
475  {
476  col->primsol = 0.0;
477  col->validredcostlp = -1;
478  col->validfarkaslp = -1;
479  col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
480  }
481 
482  /* free memory */
483  if( freebuffer )
484  {
485  BMSfreeBlockMemoryNull(blkmem, &col->storedsolvals);
486  assert(col->storedsolvals == NULL);
487  }
488 
489  return SCIP_OKAY;
490 }
491 
492 /** save current LP solution values stored in each column */
493 static
495  SCIP_ROW* row, /**< LP row */
496  BMS_BLKMEM* blkmem, /**< block memory */
497  SCIP_Bool infeasible /**< is the solution infeasible? */
498  )
499 {
500  SCIP_ROWSOLVALS* storedsolvals;
501 
502  assert(row != NULL);
503  assert(blkmem != NULL);
504 
505  /* allocate memory for storage */
506  if( row->storedsolvals == NULL )
507  {
508  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &row->storedsolvals) );
509  }
510  storedsolvals = row->storedsolvals;
511 
512  /* store values */
513  if ( infeasible )
514  {
515  storedsolvals->dualsol = row->dualfarkas;
516  storedsolvals->activity = SCIP_INVALID;
517  storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
518  }
519  else
520  {
521  storedsolvals->dualsol = row->dualsol;
522  storedsolvals->activity = row->activity;
523  storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
524  }
525 
526  return SCIP_OKAY;
527 }
528 
529 /** restore LP solution values in row */
530 static
532  SCIP_ROW* row, /**< LP column */
533  BMS_BLKMEM* blkmem, /**< block memory */
534  SCIP_Longint validlp, /**< number of lp for which restored values are valid */
535  SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */
536  SCIP_Bool infeasible /**< is the solution infeasible? */
537  )
538 {
539  SCIP_ROWSOLVALS* storedsolvals;
540 
541  assert(row != NULL);
542  assert(blkmem != NULL);
543 
544  /* if stored values are available, restore them */
545  storedsolvals = row->storedsolvals;
546  if( storedsolvals != NULL )
547  {
548  if ( infeasible )
549  row->dualfarkas = storedsolvals->dualsol;
550  else
551  row->dualsol = storedsolvals->dualsol;
552  row->activity = storedsolvals->activity;
553  row->validactivitylp = validlp;
554  row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
555  }
556  /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
557  * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
558  */
559  else
560  {
561  row->dualsol = 0.0;
562  row->dualfarkas = 0.0;
563  row->activity = SCIP_INVALID;
564  row->validactivitylp = -1;
565  row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
566  }
567 
568  /* free memory */
569  if( freebuffer )
570  {
571  BMSfreeBlockMemoryNull(blkmem, &row->storedsolvals);
572  assert(row->storedsolvals == NULL);
573  }
574 
575  return SCIP_OKAY;
576 }
577 
578 /** ensures, that column array of row can store at least num entries */
580  SCIP_ROW* row, /**< LP row */
581  BMS_BLKMEM* blkmem, /**< block memory */
582  SCIP_SET* set, /**< global SCIP settings */
583  int num /**< minimum number of entries to store */
584  )
585 {
586  assert(row != NULL);
587  assert(row->len <= row->size);
588 
589  if( num > row->size )
590  {
591  int newsize;
592 
593  newsize = SCIPsetCalcMemGrowSize(set, num);
594  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
595  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
596  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
597  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
598  row->size = newsize;
599  }
600  assert(num <= row->size);
601 
602  return SCIP_OKAY;
603 }
604 
605 
606 #if 0
607 static SCIP_Bool msgdisp_checkrow = FALSE;
608 
609 static
610 void checkRow(
611  SCIP_ROW* row
612  )
613 {
614  int i;
615 
616  if( !msgdisp_checkrow )
617  {
618  printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
619  msgdisp_checkrow = TRUE;
620  }
621 
622  /* validate sorting of LP part of row */
623  if( row->lpcolssorted && row->nlpcols > 0)
624  {
625  assert(row->cols_index[0] == row->cols[0]->index);
626  for( i = 1; i < row->nlpcols; ++i )
627  {
628  assert(row->cols_index[i] == row->cols[i]->index);
629  assert(row->cols_index[i] >= row->cols_index[i-1]);
630  }
631  }
632 
633  /* validate sorting of non-LP part of row */
634  if( row->nonlpcolssorted && row->len > row->nlpcols )
635  {
636  assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
637  for( i = row->nlpcols + 1; i < row->len; ++i )
638  {
639  assert(row->cols_index[i] == row->cols[i]->index);
640  assert(row->cols_index[i] >= row->cols_index[i-1]);
641  }
642  }
643 }
644 #else
645 #define checkRow(row) /**/
646 #endif
647 
648 #if 0
649 static
650 void checkRowSqrnorm(
651  SCIP_ROW* row
652  )
653 {
654  SCIP_COL** cols;
655  SCIP_Real sqrnorm;
656  int c;
657 
658  cols = row->cols;
659  assert(cols != NULL || row->len == 0);
660 
661  sqrnorm = 0.0;
662 
663  for( c = row->len - 1; c >= 0; --c )
664  {
665  if( cols[c]->lppos >= 0 )
666  sqrnorm += SQR(row->vals[c]);
667  }
668 
669  assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
670 }
671 
672 static
673 void checkRowSumnorm(
674  SCIP_ROW* row
675  )
676 {
677  SCIP_COL** cols;
678  SCIP_Real sumnorm;
679  int c;
680 
681  cols = row->cols;
682  assert(cols != NULL || row->len == 0);
683 
684  sumnorm = 0.0;
685 
686  for( c = row->len - 1; c >= 0; --c )
687  {
688  if( cols[c]->lppos >= 0 )
689  sumnorm += REALABS(row->vals[c]);
690  }
691 
692  assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
693 }
694 
695 static
696 void checkRowObjprod(
697  SCIP_ROW* row
698  )
699 {
700  SCIP_COL** cols;
701  SCIP_Real objprod;
702  int c;
703 
704  cols = row->cols;
705  assert(cols != NULL || row->len == 0);
706 
707  objprod = 0.0;
708 
709  for( c = row->len - 1; c >= 0; --c )
710  {
711  if( cols[c]->lppos >= 0 )
712  objprod += row->vals[c] * cols[c]->obj;
713  }
714 
715  assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
716 }
717 #else
718 #define checkRowSqrnorm(row) /**/
719 #define checkRowSumnorm(row) /**/
720 #define checkRowObjprod(row) /**/
721 #endif
722 
723 /*
724  * Local methods for pseudo and loose objective values
725  */
726 
727 /* recompute the loose objective value from scratch, if it was marked to be unreliable before */
728 static
730  SCIP_LP* lp, /**< current LP data */
731  SCIP_SET* set, /**< global SCIP settings */
732  SCIP_PROB* prob /**< problem data */
733  )
734 {
735  SCIP_VAR** vars;
736  SCIP_Real obj;
737  int nvars;
738  int v;
739 
740  assert(lp != NULL);
741  assert(set != NULL);
742  assert(prob != NULL);
743  assert(!lp->looseobjvalid);
744 
745  vars = prob->vars;
746  nvars = prob->nvars;
747  lp->looseobjval = 0.0;
748 
749  /* iterate over all variables in the problem */
750  for( v = 0; v < nvars; ++v )
751  {
752  if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
753  {
754  obj = SCIPvarGetObj(vars[v]);
755 
756  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
757  if( SCIPsetIsPositive(set, obj) && !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
758  lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
759  else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
760  lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
761  }
762  }
763 
764  /* the recomputed value is reliable */
765  lp->rellooseobjval = lp->looseobjval;
766  lp->looseobjvalid = TRUE;
767 }
768 
769 /* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
770 static
772  SCIP_LP* lp, /**< current LP data */
773  SCIP_SET* set, /**< global SCIP settings */
774  SCIP_PROB* prob /**< problem data */
775  )
776 {
777  SCIP_VAR** vars;
778  int nvars;
779  int v;
780 
781  assert(lp != NULL);
782  assert(set != NULL);
783  assert(prob != NULL);
784  assert(!lp->pseudoobjvalid);
785 
786  vars = prob->vars;
787  nvars = prob->nvars;
788  lp->pseudoobjval = 0.0;
789 
790  /* iterate over all variables in the problem */
791  for( v = 0; v < nvars; ++v )
792  {
793  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
794  if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
795  !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
796  {
797  lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
798  }
799  else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
800  !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
801  {
802  lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
803  }
804  }
805 
806  /* the recomputed value is reliable */
807  lp->relpseudoobjval = lp->pseudoobjval;
808  lp->pseudoobjvalid = TRUE;
809 }
810 
811 /* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
812 static
814  SCIP_LP* lp, /**< current LP data */
815  SCIP_SET* set, /**< global SCIP settings */
816  SCIP_PROB* prob /**< problem data */
817  )
818 {
819  SCIP_VAR** vars;
820  int nvars;
821  int v;
822 
823  assert(lp != NULL);
824  assert(set != NULL);
825  assert(prob != NULL);
826  assert(!lp->glbpseudoobjvalid);
827 
828  vars = prob->vars;
829  nvars = prob->nvars;
830  lp->glbpseudoobjval = 0.0;
831 
832  /* iterate over all variables in the problem */
833  for( v = 0; v < nvars; ++v )
834  {
835  /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
836  if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
837  !SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
838  {
839  lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
840  }
841  else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
842  !SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
843  {
844  lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
845  }
846  }
847 
848  /* the recomputed value is reliable */
850  lp->glbpseudoobjvalid = TRUE;
851 }
852 
853 /** gets finite part of objective value of current LP that results from LOOSE variables only */
854 static
856  SCIP_LP* lp, /**< current LP data */
857  SCIP_SET* set, /**< global SCIP settings */
858  SCIP_PROB* prob /**< problem data */
859  )
860 {
861  assert(lp != NULL);
862  assert(set != NULL);
863  assert(prob != NULL);
864  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
865  assert(lp->flushed);
866  assert(lp->looseobjvalinf == 0);
867 
868  /* recalculate the loose objective value, if needed */
869  if( !lp->looseobjvalid )
870  recomputeLooseObjectiveValue(lp, set, prob);
871 
872  return lp->looseobjval;
873 }
874 
875 /** gets finite part of pseudo objective value of current LP */
876 static
878  SCIP_LP* lp, /**< current LP data */
879  SCIP_SET* set, /**< global SCIP settings */
880  SCIP_PROB* prob /**< problem data */
881  )
882 {
883  assert(lp != NULL);
884  assert(set != NULL);
885  assert(prob != NULL);
886 
887  /* recalculate the pseudo objective value, if needed */
888  if( !lp->pseudoobjvalid )
889  recomputePseudoObjectiveValue(lp, set, prob);
890 
891  return lp->pseudoobjval;
892 }
893 
894 /*
895  * Sorting and searching rows and columns
896  */
897 
898 
899 /** comparison method for sorting rows by non-decreasing index */
901 {
902  assert(elem1 != NULL);
903  assert(elem2 != NULL);
904 
905  if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
906  return -1;
907  else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
908  return +1;
909  else
910  {
911  assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
912  return 0;
913  }
914 }
915 
916 
917 /** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
918 static
920  SCIP_COL* col /**< column to be sorted */
921  )
922 {
923  int i;
924 
925  assert(col != NULL);
926 
927  /* check, if column is already sorted in the LP part */
928  if( col->lprowssorted )
929  return;
930 
931  /* sort coefficients */
932  SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
933 
934  /* update links */
935  for( i = 0; i < col->nlprows; ++i )
936  {
937  if( col->linkpos[i] >= 0 )
938  {
939  assert(col->rows[i]->cols[col->linkpos[i]] == col);
940  assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
941  col->rows[i]->linkpos[col->linkpos[i]] = i;
942  }
943  }
944 
945  col->lprowssorted = TRUE;
946 }
947 
948 /** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
949  * ones
950  */
951 static
953  SCIP_COL* col /**< column to be sorted */
954  )
955 {
956  int i;
957 
958  assert(col != NULL);
959 
960  /* check, if column is already sorted in the non-LP part */
961  if( col->nonlprowssorted )
962  return;
963 
964  /* sort coefficients */
965  SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
966 
967  /* update links */
968  for( i = col->nlprows; i < col->len; ++i )
969  {
970  if( col->linkpos[i] >= 0 )
971  {
972  assert(col->rows[i]->cols[col->linkpos[i]] == col);
973  assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
974  col->rows[i]->linkpos[col->linkpos[i]] = i;
975  }
976  }
977 
978  col->nonlprowssorted = TRUE;
979 }
980 
981 /** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
982 static
984  SCIP_ROW* row /**< row to be sorted */
985  )
986 {
987  int i;
988 
989  assert(row != NULL);
990 
991  /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
992  if( row->lpcolssorted || row->delaysort )
993  return;
994 
995  /* sort coefficients */
996  SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
997 
998  /* update links */
999  for( i = 0; i < row->nlpcols; ++i )
1000  {
1001  if( row->linkpos[i] >= 0 )
1002  {
1003  assert(row->cols[i]->rows[row->linkpos[i]] == row);
1004  assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1005  row->cols[i]->linkpos[row->linkpos[i]] = i;
1006  }
1007  }
1008 
1009  row->lpcolssorted = TRUE;
1010 }
1011 
1012 /** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1013  * higher ones
1014  */
1015 static
1017  SCIP_ROW* row /**< row to be sorted */
1018  )
1019 {
1020  int i;
1021 
1022  assert(row != NULL);
1023 
1024  checkRow(row);
1025 
1026  /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1027  if( row->nonlpcolssorted || row->delaysort )
1028  return;
1029 
1030  /* sort coefficients */
1031  SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1032 
1033  /* update links */
1034  for( i = row->nlpcols; i < row->len; ++i )
1035  {
1036  if( row->linkpos[i] >= 0 )
1037  {
1038  assert(row->cols[i]->rows[row->linkpos[i]] == row);
1039  assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1040  row->cols[i]->linkpos[row->linkpos[i]] = i;
1041  }
1042  }
1043 
1044  checkRow(row);
1045 
1046  row->nonlpcolssorted = TRUE;
1047 }
1048 
1049 /** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1050 static
1052  SCIP_COL* col, /**< column to be searched in */
1053  const SCIP_ROW* row, /**< coefficient to be searched for */
1054  int minpos, /**< first position of search range */
1055  int maxpos /**< last position of search range */
1056  )
1057 {
1058  int pos;
1059  int idx;
1060  int searchidx;
1061 
1062  assert(col != NULL);
1063  assert(row != NULL);
1064 
1065  /* binary search */
1066  searchidx = row->index;
1067  while(minpos <= maxpos)
1068  {
1069  pos = (minpos + maxpos)/2;
1070  assert(0 <= pos && pos < col->len);
1071  assert(col->rows[pos] != NULL);
1072  assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1073  idx = col->rows[pos]->index;
1074  if( searchidx == idx )
1075  return pos;
1076  else if( searchidx < idx )
1077  maxpos = pos-1;
1078  else
1079  minpos = pos+1;
1080  }
1081 
1082  return -1;
1083 }
1084 
1085 /** searches coefficient in column, returns position in col vector or -1 if not found */
1086 static
1088  SCIP_COL* col, /**< column to be searched in */
1089  const SCIP_ROW* row /**< coefficient to be searched for */
1090  )
1091 {
1092  int pos;
1093 
1094  assert(col != NULL);
1095  assert(row != NULL);
1096 
1097  pos = -1;
1098 
1099  /* search in the linked LP rows */
1100  if( row->lppos >= 0 )
1101  {
1102  /* column has to be sorted, such that binary search works */
1103  colSortLP(col);
1104  assert(col->lprowssorted);
1105 
1106  pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1107  if( pos >= 0 )
1108  return pos;
1109  }
1110 
1111  /* search in the non-LP/unlinked rows */
1112  if( row->lppos == -1 || col->nunlinked > 0 )
1113  {
1114  /* column has to be sorted, such that binary search works */
1115  colSortNonLP(col);
1116  assert(col->nonlprowssorted);
1117 
1118  pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1119  }
1120 
1121  return pos;
1122 }
1123 
1124 /** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1125 static
1127  SCIP_ROW* row, /**< row to be searched in */
1128  const SCIP_COL* col, /**< coefficient to be searched for */
1129  int minpos, /**< first position of search range */
1130  int maxpos /**< last position of search range */
1131  )
1132 {
1133  int pos;
1134  int idx;
1135  int searchidx;
1136 
1137  assert(row != NULL);
1138  assert(col != NULL);
1139 
1140  /* binary search */
1141  searchidx = col->index;
1142  while(minpos <= maxpos)
1143  {
1144  pos = (minpos + maxpos)/2;
1145  assert(0 <= pos && pos < row->len);
1146  assert(row->cols[pos] != NULL);
1147  assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1148  assert(row->cols_index[pos] == row->cols[pos]->index);
1149  idx = row->cols_index[pos];
1150  if( searchidx == idx )
1151  return pos;
1152  else if( searchidx < idx )
1153  maxpos = pos-1;
1154  else
1155  minpos = pos+1;
1156  }
1157 
1158  return -1;
1159 }
1160 
1161 /** searches coefficient in row, returns position in row vector or -1 if not found;
1162  * if the sorting of the row is delayed, returns -1
1163  */
1164 static
1166  SCIP_ROW* row, /**< row to be searched in */
1167  const SCIP_COL* col /**< coefficient to be searched for */
1168  )
1169 {
1170  int pos;
1171 
1172  assert(row != NULL);
1173  assert(col != NULL);
1174 
1175  if( row->delaysort )
1176  return -1;
1177 
1178  pos = -1;
1179 
1180  /* search in the linked LP columns */
1181  if( col->lppos >= 0 )
1182  {
1183  /* row has to be sorted, such that binary search works */
1184  rowSortLP(row);
1185  assert(row->lpcolssorted);
1186 
1187  pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1188  }
1189 
1190  /* search in the non-LP/unlinked columns */
1191  if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1192  {
1193  /* row has to be sorted, such that binary search works */
1194  rowSortNonLP(row);
1195  assert(row->nonlpcolssorted);
1196 
1197  pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1198  }
1199 
1200 #ifndef NDEBUG
1201  /* validate result */
1202  assert(-1 <= pos && pos < row->len);
1203  if( pos >= 0 )
1204  assert(row->cols[pos] == col);
1205  else
1206  {
1207  int i;
1208  for( i = 0; i < row->len; ++i )
1209  assert(row->cols[i] != col);
1210  }
1211 #endif
1212 
1213  return pos;
1214 }
1215 
1216 /** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1217 static
1219  SCIP_COL* col, /**< LP column */
1220  int oldpos, /**< old position of coefficient */
1221  int newpos /**< new position of coefficient */
1222  )
1223 {
1224  assert(col != NULL);
1225  assert(0 <= oldpos && oldpos < col->len);
1226  assert(0 <= newpos && newpos < col->len);
1227  assert(col->rows[oldpos] != NULL);
1228 
1229  if( oldpos == newpos )
1230  return;
1231 
1232  col->rows[newpos] = col->rows[oldpos];
1233  col->vals[newpos] = col->vals[oldpos];
1234  col->linkpos[newpos] = col->linkpos[oldpos];
1235 
1236  /* update link position in row */
1237  if( col->linkpos[newpos] >= 0 )
1238  {
1239  assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1240  assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1241 
1242  col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1243  }
1244 
1245  /* update sorted flags */
1246  if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1247  col->lprowssorted = FALSE;
1248  else
1249  col->nonlprowssorted = FALSE;
1250 }
1251 
1252 /** swaps two coefficients in a column, and updates all corresponding data structures */
1253 static
1255  SCIP_COL* col, /**< LP column */
1256  int pos1, /**< position of first coefficient */
1257  int pos2 /**< position of second coefficient */
1258  )
1259 {
1260  SCIP_ROW* tmprow;
1261  SCIP_Real tmpval;
1262  int tmplinkpos;
1263 
1264  assert(col != NULL);
1265  assert(0 <= pos1 && pos1 < col->len);
1266  assert(0 <= pos2 && pos2 < col->len);
1267  assert(col->rows[pos1] != NULL);
1268 
1269  if( pos1 == pos2 )
1270  return;
1271 
1272  /* swap coefficients */
1273  tmprow = col->rows[pos2];
1274  tmpval = col->vals[pos2];
1275  tmplinkpos = col->linkpos[pos2];
1276 
1277  col->rows[pos2] = col->rows[pos1];
1278  col->vals[pos2] = col->vals[pos1];
1279  col->linkpos[pos2] = col->linkpos[pos1];
1280 
1281  col->rows[pos1] = tmprow;
1282  col->vals[pos1] = tmpval;
1283  col->linkpos[pos1] = tmplinkpos;
1284 
1285  /* update link position in rows */
1286  if( col->linkpos[pos1] >= 0 )
1287  {
1288  assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1289  assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1290 
1291  col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1292  }
1293  if( col->linkpos[pos2] >= 0 )
1294  {
1295  assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1296  assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1297 
1298  col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1299  }
1300 
1301  /* update sorted flags */
1302  if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1303  col->lprowssorted = FALSE;
1304  else
1305  col->nonlprowssorted = FALSE;
1306  if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1307  col->lprowssorted = FALSE;
1308  else
1309  col->nonlprowssorted = FALSE;
1310 }
1311 
1312 /** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1313 static
1315  SCIP_ROW* row, /**< LP row */
1316  int oldpos, /**< old position of coefficient */
1317  int newpos /**< new position of coefficient */
1318  )
1319 {
1320  assert(row != NULL);
1321  assert(0 <= oldpos && oldpos < row->len);
1322  assert(0 <= newpos && newpos < row->len);
1323  assert(row->cols[oldpos] != NULL);
1324 
1325  if( oldpos == newpos )
1326  return;
1327 
1328  row->cols[newpos] = row->cols[oldpos];
1329  row->cols_index[newpos] = row->cols_index[oldpos];
1330  row->vals[newpos] = row->vals[oldpos];
1331  row->linkpos[newpos] = row->linkpos[oldpos];
1332 
1333  /* update link position in column */
1334  if( row->linkpos[newpos] >= 0 )
1335  {
1336  assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1337  assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1338 
1339  row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1340  }
1341 
1342  /* update sorted flags */
1343  if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1344  row->lpcolssorted = FALSE;
1345  else
1346  row->nonlpcolssorted = FALSE;
1347 }
1348 
1349 /** swaps two coefficients in a row, and updates all corresponding data structures */
1350 static
1352  SCIP_ROW* row, /**< LP row */
1353  int pos1, /**< position of first coefficient */
1354  int pos2 /**< position of second coefficient */
1355  )
1356 {
1357  SCIP_COL* tmpcol;
1358  SCIP_Real tmpval;
1359  int tmpindex;
1360  int tmplinkpos;
1361 
1362  assert(row != NULL);
1363  assert(0 <= pos1 && pos1 < row->len);
1364  assert(0 <= pos2 && pos2 < row->len);
1365  assert(row->cols[pos1] != NULL);
1366  assert(row->cols[pos1]->index == row->cols_index[pos1]);
1367 
1368  if( pos1 == pos2 )
1369  return;
1370 
1371  /* swap coefficients */
1372  tmpcol = row->cols[pos2];
1373  tmpindex = row->cols_index[pos2];
1374  tmpval = row->vals[pos2];
1375  tmplinkpos = row->linkpos[pos2];
1376 
1377  row->cols[pos2] = row->cols[pos1];
1378  row->cols_index[pos2] = row->cols_index[pos1];
1379  row->vals[pos2] = row->vals[pos1];
1380  row->linkpos[pos2] = row->linkpos[pos1];
1381 
1382  row->cols[pos1] = tmpcol;
1383  row->cols_index[pos1] = tmpindex;
1384  row->vals[pos1] = tmpval;
1385  row->linkpos[pos1] = tmplinkpos;
1386 
1387  /* update link position in columns */
1388  if( row->linkpos[pos1] >= 0 )
1389  {
1390  assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1391  assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1392 
1393  row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1394  }
1395  if( row->linkpos[pos2] >= 0 )
1396  {
1397  assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1398  assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1399 
1400  row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1401  }
1402 
1403  /* update sorted flags */
1404  if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1405  row->lpcolssorted = FALSE;
1406  else
1407  row->nonlpcolssorted = FALSE;
1408  if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1409  row->lpcolssorted = FALSE;
1410  else
1411  row->nonlpcolssorted = FALSE;
1412 }
1413 
1414 /** issues a ROWCOEFCHANGED event on the given row */
1415 static
1417  SCIP_ROW* row, /**< row which coefficient has changed */
1418  BMS_BLKMEM* blkmem, /**< block memory */
1419  SCIP_SET* set, /**< global SCIP settings */
1420  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1421  SCIP_COL* col, /**< the column which coefficient has changed */
1422  SCIP_Real oldval, /**< old value of the coefficient */
1423  SCIP_Real newval /**< new value of the coefficient */
1424  )
1425 {
1426  assert(row != NULL);
1427  assert(row->eventfilter != NULL);
1428  assert(col != NULL);
1429 
1430  /* check, if the row is being tracked for coefficient changes
1431  * if so, issue ROWCOEFCHANGED event
1432  */
1433  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1434  {
1435  SCIP_EVENT* event;
1436 
1437  SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1438  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1439  }
1440 
1441  return SCIP_OKAY;
1442 }
1443 
1444 /** issues a ROWCONSTCHANGED event on the given row */
1445 static
1447  SCIP_ROW* row, /**< row which coefficient has changed */
1448  BMS_BLKMEM* blkmem, /**< block memory */
1449  SCIP_SET* set, /**< global SCIP settings */
1450  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1451  SCIP_Real oldval, /**< old value of the constant */
1452  SCIP_Real newval /**< new value of the constant */
1453  )
1454 {
1455  assert(row != NULL);
1456  assert(row->eventfilter != NULL);
1457 
1458  /* check, if the row is being tracked for coefficient changes
1459  * if so, issue ROWCONSTCHANGED event
1460  */
1461  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCONSTCHANGED) != 0) )
1462  {
1463  SCIP_EVENT* event;
1464 
1465  SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1466  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1467  }
1468 
1469  return SCIP_OKAY;
1470 }
1471 
1472 /** issues a ROWSIDECHANGED event on the given row */
1473 static
1475  SCIP_ROW* row, /**< row which coefficient has changed */
1476  BMS_BLKMEM* blkmem, /**< block memory */
1477  SCIP_SET* set, /**< global SCIP settings */
1478  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1479  SCIP_SIDETYPE side, /**< the side that has changed */
1480  SCIP_Real oldval, /**< old value of side */
1481  SCIP_Real newval /**< new value of side */
1482  )
1483 {
1484  assert(row != NULL);
1485  assert(row->eventfilter != NULL);
1486 
1487  /* check, if the row is being tracked for coefficient changes
1488  * if so, issue ROWSIDECHANGED event
1489  */
1490  if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED) != 0) )
1491  {
1492  SCIP_EVENT* event;
1493 
1494  SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1495  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1496  }
1497 
1498  return SCIP_OKAY;
1499 }
1500 
1501 #if 0
1502 
1503 #ifdef NDEBUG
1504 #define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1505 #else
1506 #define ASSERT(x) assert(x)
1507 #endif
1508 
1509 static SCIP_Bool msgdisp_checklinks = FALSE;
1510 
1511 
1512 static
1513 void checkLinks(
1514  SCIP_LP* lp /**< current LP data */
1515  )
1516 {
1517  SCIP_COL* col;
1518  SCIP_ROW* row;
1519  int i;
1520  int j;
1521 
1522  ASSERT(lp != NULL);
1523 
1524  if( !msgdisp_checklinks )
1525  {
1526  printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1527  msgdisp_checklinks = TRUE;
1528  }
1529 
1530  for( i = 0; i < lp->ncols; ++i )
1531  {
1532  col = lp->cols[i];
1533  ASSERT(col != NULL);
1534  ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1535  ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1536  ASSERT(col->nlprows <= col->len);
1537  ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1538 
1539  for( j = 0; j < col->len; ++j )
1540  {
1541  row = col->rows[j];
1542  ASSERT(row != NULL);
1543  ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1544  ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1545  ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1546  ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1547  }
1548  }
1549 
1550  for( i = 0; i < lp->nrows; ++i )
1551  {
1552  row = lp->rows[i];
1553  ASSERT(row != NULL);
1554  ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1555  ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1556  ASSERT(row->nlpcols <= row->len);
1557  ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1558 
1559  for( j = 0; j < row->len; ++j )
1560  {
1561  col = row->cols[j];
1562  ASSERT(col != NULL);
1563  ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1564  ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1565  ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1566  ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1567  }
1568  }
1569 }
1570 
1571 #undef ASSERT
1572 
1573 #else
1574 #define checkLinks(lp) /**/
1575 #endif
1576 
1577 /*
1578  * Changing announcements
1579  */
1580 
1581 /** announces, that the given coefficient in the constraint matrix changed */
1582 static
1584  SCIP_ROW* row, /**< LP row */
1585  SCIP_COL* col, /**< LP col */
1586  SCIP_LP* lp /**< current LP data */
1587  )
1588 {
1589  assert(row != NULL);
1590  assert(col != NULL);
1591  assert(lp != NULL);
1592 
1593  if( row->lpipos >= 0 && col->lpipos >= 0 )
1594  {
1595  assert(row->lpipos < lp->nlpirows);
1596  assert(col->lpipos < lp->nlpicols);
1597 
1598  /* we have to remember the change only in the row or in the column,
1599  * because the readdition of one vector would change the other automatically.
1600  */
1601  if( row->lpipos >= lp->lpifirstchgrow )
1602  row->coefchanged = TRUE;
1603  else if( col->lpipos >= lp->lpifirstchgcol )
1604  col->coefchanged = TRUE;
1605  else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1606  {
1607  row->coefchanged = TRUE;
1608  lp->lpifirstchgrow = row->lpipos;
1609  }
1610  else
1611  {
1612  col->coefchanged = TRUE;
1613  lp->lpifirstchgcol = col->lpipos;
1614  }
1615 
1616  /* mark the current LP unflushed */
1617  lp->flushed = FALSE;
1618  }
1619 
1621  row->minactivity = SCIP_INVALID;
1622  row->maxactivity = SCIP_INVALID;
1623  row->validpsactivitydomchg = -1;
1624  row->validactivitybdsdomchg = -1;
1625 }
1626 
1627 
1628 
1629 /*
1630  * local column changing methods
1631  */
1632 
1633 /* forward declaration for colAddCoef() */
1634 static
1636  SCIP_ROW* row, /**< LP row */
1637  BMS_BLKMEM* blkmem, /**< block memory */
1638  SCIP_SET* set, /**< global SCIP settings */
1639  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1640  SCIP_LP* lp, /**< current LP data */
1641  SCIP_COL* col, /**< LP column */
1642  SCIP_Real val, /**< value of coefficient */
1643  int linkpos /**< position of row in the column's row array, or -1 */
1644  );
1645 
1646 /** adds a previously non existing coefficient to an LP column */
1647 static
1649  SCIP_COL* col, /**< LP column */
1650  BMS_BLKMEM* blkmem, /**< block memory */
1651  SCIP_SET* set, /**< global SCIP settings */
1652  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1653  SCIP_LP* lp, /**< current LP data */
1654  SCIP_ROW* row, /**< LP row */
1655  SCIP_Real val, /**< value of coefficient */
1656  int linkpos /**< position of column in the row's col array, or -1 */
1657  )
1658 {
1659  int pos;
1660 
1661  assert(blkmem != NULL);
1662  assert(col != NULL);
1663  assert(col->nlprows <= col->len);
1664  assert(col->var != NULL);
1665  assert(row != NULL);
1666  assert(!SCIPsetIsZero(set, val));
1667  /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1668 
1669  SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1670  assert(col->rows != NULL);
1671  assert(col->vals != NULL);
1672  assert(col->linkpos != NULL);
1673 
1674  pos = col->len;
1675  col->len++;
1676 
1677  /* 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
1678  * part of the column's arrays
1679  */
1680  if( row->lppos >= 0 && linkpos >= 0 )
1681  {
1682  /* move the first non-LP/not linked row to the end */
1683  if( col->nlprows < pos )
1684  {
1685  colMoveCoef(col, col->nlprows, pos);
1686  pos = col->nlprows;
1687  }
1688  col->nlprows++;
1689  }
1690 
1691  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1692  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1693 
1694  /* insert the row at the correct position and update the links */
1695  col->rows[pos] = row;
1696  col->vals[pos] = val;
1697  col->linkpos[pos] = linkpos;
1698  if( linkpos == -1 )
1699  {
1700  col->nunlinked++;
1701 
1702  /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1703  * of the row is not complete
1704  */
1705  if( col->lppos >= 0 )
1706  {
1707  /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1708  * has to be updated
1709  */
1710  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1711  if( row->lppos >= 0 )
1712  pos = col->nlprows-1;
1713  linkpos = col->linkpos[pos];
1714 
1715  assert(0 <= linkpos && linkpos < row->len);
1716  assert(row->cols[linkpos] == col);
1717  assert(col->rows[pos] == row);
1718  assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1719  assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1720  }
1721  }
1722  else
1723  {
1724  assert(row->linkpos[linkpos] == -1);
1725  assert(row->nunlinked > 0);
1726  row->linkpos[linkpos] = pos;
1727  row->nunlinked--;
1728 
1729  /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1730  * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1731  */
1732  if( col->lppos >= 0 )
1733  {
1734  row->nlpcols++;
1735  rowSwapCoefs(row, linkpos, row->nlpcols-1);
1736 
1737  /* if no swap was necessary, mark nonlpcols to be unsorted */
1738  if( linkpos == row->nlpcols-1 )
1739  row->lpcolssorted = FALSE;
1740  }
1741  }
1742 
1743  /* update the sorted flags */
1744  if( row->lppos >= 0 && linkpos >= 0 )
1745  {
1746  assert(col->nlprows >= 1);
1747  assert(col->rows[col->nlprows-1] == row);
1748  if( col->nlprows > 1 )
1749  col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1750  }
1751  else
1752  {
1753  assert(col->len - col->nlprows >= 1);
1754  assert(col->rows[col->len-1] == row);
1755  if( col->len - col->nlprows > 1 )
1756  col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1757  }
1758 
1759  coefChanged(row, col, lp);
1760 
1761  SCIPdebugMessage("added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1762  val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1763 
1764  return SCIP_OKAY;
1765 }
1766 
1767 /** deletes coefficient at given position from column */
1768 static
1770  SCIP_COL* col, /**< column to be changed */
1771  SCIP_SET* set, /**< global SCIP settings */
1772  SCIP_LP* lp, /**< current LP data */
1773  int pos /**< position in column vector to delete */
1774  )
1775 {
1776  SCIP_ROW* row;
1777 
1778  assert(col != NULL);
1779  assert(col->var != NULL);
1780  assert(set != NULL);
1781  assert(0 <= pos && pos < col->len);
1782  assert(col->rows[pos] != NULL);
1783  assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1784  assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1785 
1786  row = col->rows[pos];
1787  assert((row->lppos >= 0) == (pos < col->nlprows));
1788 
1789  /*debugMessage("deleting coefficient %g * <%s> at position %d from column <%s>\n",
1790  col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1791 
1792  if( col->linkpos[pos] == -1 )
1793  col->nunlinked--;
1794 
1795  /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1796  if( pos < col->nlprows )
1797  {
1798  colMoveCoef(col, col->nlprows-1, pos);
1799  col->nlprows--;
1800  pos = col->nlprows;
1801  }
1802 
1803  /* move last coefficient to position of empty slot */
1804  colMoveCoef(col, col->len-1, pos);
1805  col->len--;
1806 
1807  coefChanged(row, col, lp);
1808 
1809  return SCIP_OKAY;
1810 }
1811 
1812 /** changes a coefficient at given position of an LP column */
1813 static
1815  SCIP_COL* col, /**< LP column */
1816  SCIP_SET* set, /**< global SCIP settings */
1817  SCIP_LP* lp, /**< current LP data */
1818  int pos, /**< position in column vector to change */
1819  SCIP_Real val /**< value of coefficient */
1820  )
1821 {
1822  assert(col != NULL);
1823  assert(col->var != NULL);
1824  assert(0 <= pos && pos < col->len);
1825  assert(col->rows[pos] != NULL);
1826  assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1827 
1828  /*debugMessage("changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1829  col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1830 
1831  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1832  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1833 
1834  if( SCIPsetIsZero(set, val) )
1835  {
1836  /* delete existing coefficient */
1837  SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1838  }
1839  else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1840  {
1841  /* change existing coefficient */
1842  col->vals[pos] = val;
1843  coefChanged(col->rows[pos], col, lp);
1844  }
1845 
1846  return SCIP_OKAY;
1847 }
1848 
1849 
1850 
1851 
1852 /*
1853  * local row changing methods
1854  */
1855 
1856 /** update row norms after addition of coefficient */
1857 static
1859  SCIP_ROW* row, /**< LP row */
1860  SCIP_SET* set, /**< global SCIP settings */
1861  SCIP_COL* col, /**< column of added coefficient */
1862  SCIP_Real val, /**< value of added coefficient */
1863  SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */
1864  )
1865 {
1866  SCIP_Real absval;
1867 
1868  assert(row != NULL);
1869  assert(row->nummaxval >= 0);
1870  assert(row->numminval >= 0);
1871  assert(set != NULL);
1872  assert(col != NULL);
1873 
1874  absval = REALABS(val);
1875  assert(!SCIPsetIsZero(set, absval));
1876 
1877  /* Euclidean norm, sum norm, and objective function scalar product only take into accout LP columns */
1878  if( col->lppos >= 0 )
1879  {
1880  /* update squared Euclidean norm and sum norm */
1881  row->sqrnorm += SQR(absval);
1882  row->sumnorm += absval;
1883 
1884  /* update objective function scalar product */
1885  row->objprod += val * col->obj;
1886  }
1887 
1888  if( updateidxvals )
1889  {
1890  /* update min/maxidx */
1891  row->minidx = MIN(row->minidx, col->index);
1892  row->maxidx = MAX(row->maxidx, col->index);
1893 
1894  /* update maximal and minimal non-zero value */
1895  if( row->nummaxval > 0 )
1896  {
1897  if( SCIPsetIsGT(set, absval, row->maxval) )
1898  {
1899  row->maxval = absval;
1900  row->nummaxval = 1;
1901  }
1902  else if( SCIPsetIsGE(set, absval, row->maxval) )
1903  row->nummaxval++;
1904  }
1905  if( row->numminval > 0 )
1906  {
1907  if( SCIPsetIsLT(set, absval, row->minval) )
1908  {
1909  row->minval = absval;
1910  row->numminval = 1;
1911  }
1912  else if( SCIPsetIsLE(set, absval, row->minval) )
1913  row->numminval++;
1914  }
1915  }
1916  else
1917  {
1918  assert(row->minidx <= col->index);
1919  assert(row->maxidx >= col->index);
1920  assert(row->numminval <= 0 || SCIPsetIsGE(set, absval, row->minval));
1921  assert(row->nummaxval <= 0 || SCIPsetIsLE(set, absval, row->maxval));
1922  }
1923 }
1924 
1925 /** update row norms after deletion of coefficient */
1926 static
1928  SCIP_ROW* row, /**< LP row */
1929  SCIP_SET* set, /**< global SCIP settings */
1930  SCIP_COL* col, /**< column of deleted coefficient */
1931  SCIP_Real val, /**< value of deleted coefficient */
1932  SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */
1933  SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */
1934  SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */
1935  )
1936 {
1937  SCIP_Real absval;
1938 
1939  assert(row != NULL);
1940  assert(row->nummaxval >= 0);
1941  assert(row->numminval >= 0);
1942  assert(set != NULL);
1943  assert(col != NULL);
1944 
1945  absval = REALABS(val);
1946  assert(!SCIPsetIsZero(set, absval));
1947  assert(row->nummaxval == 0 || SCIPsetIsGE(set, row->maxval, absval));
1948  assert(row->numminval == 0 || SCIPsetIsLE(set, row->minval, absval));
1949 
1950  /* update min/maxidx validity */
1951  if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
1952  row->validminmaxidx = FALSE;
1953 
1954  /* Euclidean norm, sum norm, and objective function scalar product only take into accout LP columns */
1955  if( forcenormupdate || col->lppos >= 0 )
1956  {
1957  /* update squared Euclidean norm and sum norm */
1958  row->sqrnorm -= SQR(absval);
1959  row->sqrnorm = MAX(row->sqrnorm, 0.0);
1960  row->sumnorm -= absval;
1961  row->sumnorm = MAX(row->sumnorm, 0.0);
1962 
1963  /* update objective function scalar product */
1964  row->objprod -= val * col->obj;
1965  }
1966 
1967  if( updateval )
1968  {
1969  /* update maximal and minimal non-zero value */
1970  if( row->nummaxval > 0 )
1971  {
1972  if( SCIPsetIsGE(set, absval, row->maxval) )
1973  row->nummaxval--;
1974  }
1975  if( row->numminval > 0 )
1976  {
1977  if( SCIPsetIsLE(set, absval, row->minval) )
1978  row->numminval--;
1979  }
1980  }
1981 }
1982 
1983 /** adds a previously non existing coefficient to an LP row */
1984 static
1986  SCIP_ROW* row, /**< LP row */
1987  BMS_BLKMEM* blkmem, /**< block memory */
1988  SCIP_SET* set, /**< global SCIP settings */
1989  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1990  SCIP_LP* lp, /**< current LP data */
1991  SCIP_COL* col, /**< LP column */
1992  SCIP_Real val, /**< value of coefficient */
1993  int linkpos /**< position of row in the column's row array, or -1 */
1994  )
1995 {
1996  int pos;
1997 
1998  assert(row != NULL);
1999  assert(row->nlpcols <= row->len);
2000  assert(blkmem != NULL);
2001  assert(col != NULL);
2002  assert(col->var != NULL);
2003  assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2004  assert(!SCIPsetIsZero(set, val));
2005  /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2006 
2007  if( row->nlocks > 0 )
2008  {
2009  SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2010  return SCIP_INVALIDDATA;
2011  }
2012 
2013  SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2014  assert(row->cols != NULL);
2015  assert(row->vals != NULL);
2016 
2017  pos = row->len;
2018  row->len++;
2019 
2020  /* 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
2021  * part of the row's arrays
2022  */
2023  if( col->lppos >= 0 && linkpos >= 0 )
2024  {
2025  /* move the first non-LP/not linked column to the end */
2026  if( row->nlpcols < pos )
2027  {
2028  rowMoveCoef(row, row->nlpcols, pos);
2029  pos = row->nlpcols;
2030  }
2031  row->nlpcols++;
2032  }
2033 
2034  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2035  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2036 
2037  /* insert the column at the correct position and update the links */
2038  row->cols[pos] = col;
2039  row->cols_index[pos] = col->index;
2040  row->vals[pos] = val;
2041  row->linkpos[pos] = linkpos;
2042  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2043  if( linkpos == -1 )
2044  {
2045  row->nunlinked++;
2046 
2047  /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2048  * of the column is not complete
2049  */
2050  if( row->lppos >= 0 )
2051  {
2052  /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2053  * has to be updated
2054  */
2055  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2056  if( col->lppos >= 0 )
2057  pos = row->nlpcols-1;
2058  linkpos = row->linkpos[pos];
2059 
2060  assert(0 <= linkpos && linkpos < col->len);
2061  assert(col->rows[linkpos] == row);
2062  assert(row->cols[pos] == col);
2063  assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2064  assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2065  }
2066  }
2067  else
2068  {
2069  assert(col->linkpos[linkpos] == -1);
2070  assert(col->nunlinked > 0);
2071  col->linkpos[linkpos] = pos;
2072  col->nunlinked--;
2073 
2074  /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2075  * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2076  */
2077  if( row->lppos >= 0 )
2078  {
2079  col->nlprows++;
2080  colSwapCoefs(col, linkpos, col->nlprows-1);
2081 
2082  /* if no swap was necessary, mark lprows to be unsorted */
2083  if( linkpos == col->nlprows-1 )
2084  col->lprowssorted = FALSE;
2085  }
2086  }
2087 
2088  /* update the sorted flags */
2089  if( col->lppos >= 0 && linkpos >= 0 )
2090  {
2091  assert(row->nlpcols >= 1);
2092  assert(row->cols[row->nlpcols-1] == col);
2093  if( row->nlpcols > 1 )
2094  {
2095  assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2096  row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2097  }
2098  }
2099  else
2100  {
2101  assert(row->len - row->nlpcols >= 1);
2102  assert(row->cols[row->len-1] == col);
2103  if( row->len - row->nlpcols > 1 )
2104  {
2105  assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2106  row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2107  }
2108  }
2109 
2110  /* update row norm */
2111  rowAddNorms(row, set, col, val, TRUE);
2112 
2113  coefChanged(row, col, lp);
2114 
2115  SCIPdebugMessage("added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2116  val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2117 
2118  /* issue row coefficient changed event */
2119  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2120 
2121  return SCIP_OKAY;
2122 }
2123 
2124 /** deletes coefficient at given position from row */
2125 static
2127  SCIP_ROW* row, /**< row to be changed */
2128  BMS_BLKMEM* blkmem, /**< block memory */
2129  SCIP_SET* set, /**< global SCIP settings */
2130  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2131  SCIP_LP* lp, /**< current LP data */
2132  int pos /**< position in row vector to delete */
2133  )
2134 {
2135  SCIP_COL* col;
2136  SCIP_Real val;
2137 
2138  assert(row != NULL);
2139  assert(set != NULL);
2140  assert(0 <= pos && pos < row->len);
2141  assert(row->cols[pos] != NULL);
2142  assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2143 
2144  col = row->cols[pos];
2145  val = row->vals[pos];
2146  assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2147 
2148  /*debugMessage("deleting coefficient %g * <%s> at position %d from row <%s>\n",
2149  val, SCIPvarGetName(col->var), pos, row->name);*/
2150 
2151  if( row->nlocks > 0 )
2152  {
2153  SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2154  return SCIP_INVALIDDATA;
2155  }
2156 
2157  if( row->linkpos[pos] == -1 )
2158  row->nunlinked--;
2159 
2160  /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2161  if( pos < row->nlpcols )
2162  {
2163  rowMoveCoef(row, row->nlpcols-1, pos);
2164  assert(!row->lpcolssorted);
2165  row->nlpcols--;
2166  pos = row->nlpcols;
2167  }
2168 
2169  /* move last coefficient to position of empty slot */
2170  rowMoveCoef(row, row->len-1, pos);
2171  row->len--;
2172 
2173  /* update norms */
2174  rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2175 
2176  coefChanged(row, col, lp);
2177 
2178  /* issue row coefficient changed event */
2179  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2180 
2181  return SCIP_OKAY;
2182 }
2183 
2184 /** changes a coefficient at given position of an LP row */
2185 static
2187  SCIP_ROW* row, /**< LP row */
2188  BMS_BLKMEM* blkmem, /**< block memory */
2189  SCIP_SET* set, /**< global SCIP settings */
2190  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2191  SCIP_LP* lp, /**< current LP data */
2192  int pos, /**< position in row vector to change */
2193  SCIP_Real val /**< value of coefficient */
2194  )
2195 {
2196  SCIP_COL* col;
2197 
2198  assert(row != NULL);
2199  assert(0 <= pos && pos < row->len);
2200 
2201  /*debugMessage("changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2202  row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2203 
2204  if( row->nlocks > 0 )
2205  {
2206  SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2207  return SCIP_INVALIDDATA;
2208  }
2209 
2210  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2211  val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2212  col = row->cols[pos];
2213  assert(row->cols[pos] != NULL);
2214 
2215  if( SCIPsetIsZero(set, val) )
2216  {
2217  /* delete existing coefficient */
2218  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2219  }
2220  else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2221  {
2222  SCIP_Real oldval;
2223 
2224  oldval = row->vals[pos];
2225 
2226  /* change existing coefficient */
2227  rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2228  row->vals[pos] = val;
2229  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2230  rowAddNorms(row, set, col, row->vals[pos], TRUE);
2231  coefChanged(row, col, lp);
2232 
2233  /* issue row coefficient changed event */
2234  SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2235  }
2236 
2237  return SCIP_OKAY;
2238 }
2239 
2240 /** notifies LP row, that its sides were changed */
2241 static
2243  SCIP_ROW* row, /**< LP row */
2244  SCIP_SET* set, /**< global SCIP settings */
2245  SCIP_LP* lp, /**< current LP data */
2246  SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */
2247  )
2248 {
2249  assert(row != NULL);
2250  assert(lp != NULL);
2251 
2252  if( row->lpipos >= 0 )
2253  {
2254  /* insert row in the chgrows list (if not already there) */
2255  if( !row->lhschanged && !row->rhschanged )
2256  {
2257  SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2258  lp->chgrows[lp->nchgrows] = row;
2259  lp->nchgrows++;
2260  }
2261 
2262  /* mark side change in the row */
2263  switch( sidetype )
2264  {
2265  case SCIP_SIDETYPE_LEFT:
2266  row->lhschanged = TRUE;
2267  break;
2268  case SCIP_SIDETYPE_RIGHT:
2269  row->rhschanged = TRUE;
2270  break;
2271  default:
2272  SCIPerrorMessage("unknown row side type\n");
2273  SCIPABORT();
2274  return SCIP_INVALIDDATA; /*lint !e527*/
2275  }
2276 
2277  /* mark the current LP unflushed */
2278  lp->flushed = FALSE;
2279 
2280  assert(lp->nchgrows > 0);
2281  }
2282 
2283  return SCIP_OKAY;
2284 }
2285 
2286 
2287 
2288 
2289 /*
2290  * double linked coefficient matrix methods
2291  */
2292 
2293 /** insert column coefficients in corresponding rows */
2294 static
2296  SCIP_COL* col, /**< column data */
2297  BMS_BLKMEM* blkmem, /**< block memory */
2298  SCIP_SET* set, /**< global SCIP settings */
2299  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2300  SCIP_LP* lp /**< current LP data */
2301  )
2302 {
2303  int i;
2304 
2305  assert(col != NULL);
2306  assert(col->var != NULL);
2307  assert(blkmem != NULL);
2308  assert(set != NULL);
2309  assert(lp != NULL);
2310 
2311  if( col->nunlinked > 0 )
2312  {
2313  SCIPdebugMessage("linking column <%s>\n", SCIPvarGetName(col->var));
2314 
2315  /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2316  for( i = col->nlprows; i < col->len; ++i )
2317  {
2318  assert(!SCIPsetIsZero(set, col->vals[i]));
2319  if( col->linkpos[i] == -1 )
2320  {
2321  /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2322  SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2323  }
2324  assert(col->rows[i]->cols[col->linkpos[i]] == col);
2325  assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2326  assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2327  assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2328  }
2329  }
2330  assert(col->nunlinked == 0);
2331 
2332  checkLinks(lp);
2333 
2334  return SCIP_OKAY;
2335 }
2336 
2337 /** removes column coefficients from corresponding rows */
2338 static
2340  SCIP_COL* col, /**< column data */
2341  BMS_BLKMEM* blkmem, /**< block memory */
2342  SCIP_SET* set, /**< global SCIP settings */
2343  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2344  SCIP_LP* lp /**< current LP data */
2345  )
2346 {
2347  int i;
2348 
2349  assert(col != NULL);
2350  assert(col->var != NULL);
2351  assert(blkmem != NULL);
2352  assert(set != NULL);
2353  assert(lp != NULL);
2354 
2355  if( col->nunlinked < col->len )
2356  {
2357  SCIPdebugMessage("unlinking column <%s>\n", SCIPvarGetName(col->var));
2358  for( i = 0; i < col->len; ++i )
2359  {
2360  if( col->linkpos[i] >= 0 )
2361  {
2362  assert(col->rows[i]->cols[col->linkpos[i]] == col);
2363  SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2364  col->linkpos[i] = -1;
2365  col->nunlinked++;
2366  }
2367  }
2368  }
2369  assert(col->nunlinked == col->len);
2370 
2371  checkLinks(lp);
2372 
2373  return SCIP_OKAY;
2374 }
2375 
2376 /** insert row coefficients in corresponding columns */
2377 static
2379  SCIP_ROW* row, /**< row data */
2380  BMS_BLKMEM* blkmem, /**< block memory */
2381  SCIP_SET* set, /**< global SCIP settings */
2382  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2383  SCIP_LP* lp /**< current LP data */
2384  )
2385 {
2386  int i;
2387 
2388  assert(row != NULL);
2389  assert(blkmem != NULL);
2390  assert(set != NULL);
2391  assert(lp != NULL);
2392 
2393  if( row->nunlinked > 0 )
2394  {
2395  SCIPdebugMessage("linking row <%s>\n", row->name);
2396 
2397  /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2398  for( i = row->nlpcols; i < row->len; ++i )
2399  {
2400  assert(!SCIPsetIsZero(set, row->vals[i]));
2401  if( row->linkpos[i] == -1 )
2402  {
2403  /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2404  SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2405  }
2406  assert(row->cols[i]->rows[row->linkpos[i]] == row);
2407  assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2408  assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2409  assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2410  }
2411  }
2412  assert(row->nunlinked == 0);
2413 
2414  checkLinks(lp);
2415 
2416  return SCIP_OKAY;
2417 }
2418 
2419 /** removes row coefficients from corresponding columns */
2420 static
2422  SCIP_ROW* row, /**< row data */
2423  SCIP_SET* set, /**< global SCIP settings */
2424  SCIP_LP* lp /**< current LP data */
2425  )
2426 {
2427  int i;
2428 
2429  assert(row != NULL);
2430  assert(set != NULL);
2431  assert(lp != NULL);
2432 
2433  if( row->nunlinked < row->len )
2434  {
2435  SCIPdebugMessage("unlinking row <%s>\n", row->name);
2436  for( i = 0; i < row->len; ++i )
2437  {
2438  if( row->linkpos[i] >= 0 )
2439  {
2440  assert(row->cols[i]->rows[row->linkpos[i]] == row);
2441  SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2442  row->nunlinked++;
2443  }
2444  }
2445  }
2446  assert(row->nunlinked == row->len);
2447 
2448  return SCIP_OKAY;
2449 }
2450 
2451 
2452 
2453 
2454 /*
2455  * local LP parameter methods
2456  */
2457 
2458 /** sets parameter of type int in LP solver, ignoring unknown parameters */
2459 static
2461  SCIP_LP* lp, /**< current LP data */
2462  SCIP_LPPARAM lpparam, /**< LP parameter */
2463  int value, /**< value to set parameter to */
2464  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2465  )
2466 {
2467  SCIP_RETCODE retcode;
2468 
2469  assert(lp != NULL);
2470  assert(success != NULL);
2471 
2472  retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2473 
2474  /* check, if parameter is unknown */
2475  if( retcode == SCIP_PARAMETERUNKNOWN )
2476  {
2477  *success = FALSE;
2478  return SCIP_OKAY;
2479  }
2480  *success = TRUE;
2481 
2482  return retcode;
2483 }
2484 
2485 /** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2486 static
2488  SCIP_LP* lp, /**< current LP data */
2489  SCIP_LPPARAM lpparam, /**< LP parameter */
2490  SCIP_Bool value, /**< value to set parameter to */
2491  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2492  )
2493 {
2494  return lpSetIntpar(lp, lpparam, (int)value, success);
2495 }
2496 
2497 /** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2498 static
2500  SCIP_LP* lp, /**< current LP data */
2501  SCIP_LPPARAM lpparam, /**< LP parameter */
2502  SCIP_Real value, /**< value to set parameter to */
2503  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2504  )
2505 {
2506  SCIP_RETCODE retcode;
2507 
2508  assert(lp != NULL);
2509  assert(success != NULL);
2510 
2511  retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2512 
2513  /* check, if parameter is unknown */
2514  if( retcode == SCIP_PARAMETERUNKNOWN )
2515  {
2516  *success = FALSE;
2517  return SCIP_OKAY;
2518  }
2519  *success = TRUE;
2520 
2521  return retcode;
2522 }
2523 
2524 #ifndef NDEBUG
2525 /** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2526 static
2528  SCIP_LP* lp, /**< current LP data */
2529  SCIP_LPPARAM lpparam, /**< LP parameter */
2530  int value /**< value parameter should have */
2531  )
2532 {
2533  SCIP_RETCODE retcode;
2534  int lpivalue;
2535 
2536  assert(lp != NULL);
2537 
2538  retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2539 
2540  /* ignore unknown parameter error */
2541  if( retcode == SCIP_PARAMETERUNKNOWN )
2542  return SCIP_OKAY;
2543 
2544  /* check value */
2545  assert(lpivalue == value);
2546 
2547  return retcode;
2548 }
2549 
2550 /** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2551 static
2553  SCIP_LP* lp, /**< current LP data */
2554  SCIP_LPPARAM lpparam, /**< LP parameter */
2555  SCIP_Bool value /**< value parameter should have */
2556  )
2557 {
2558  return lpCheckIntpar(lp, lpparam, (int)value);
2559 }
2560 
2561 /** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2562 static
2564  SCIP_LP* lp, /**< current LP data */
2565  SCIP_LPPARAM lpparam, /**< LP parameter */
2566  SCIP_Real value /**< value parameter should have */
2567  )
2568 {
2569  SCIP_RETCODE retcode;
2570  SCIP_Real lpivalue;
2571 
2572  assert(lp != NULL);
2573 
2574  retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2575 
2576  /* ignore unknown parameter error */
2577  if( retcode == SCIP_PARAMETERUNKNOWN )
2578  return SCIP_OKAY;
2579 
2580  /* check value */
2581  assert(lpivalue == value); /*lint !e777*/
2582 
2583  return retcode;
2584 }
2585 #else
2586 #define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2587 #define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2588 #define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2589 #endif
2590 
2591 /** should the objective limit of the LP solver be disabled */
2592 #define lpCutoffDisabled(set) (set->lp_disablecutoff == 1 || (set->nactivepricers > 0 && set->lp_disablecutoff == 2))
2593 
2594 /** sets the upper objective limit of the LP solver */
2595 static
2597  SCIP_LP* lp, /**< current LP data */
2598  SCIP_SET* set, /**< global SCIP settings */
2599  SCIP_Real uobjlim /**< new feasibility tolerance */
2600  )
2601 {
2602  assert(lp != NULL);
2603  assert(set != NULL);
2604 
2605  /* we disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP
2606  * solver's objective limit handling, so we return here and do not apply the objective limit
2607  */
2608  if( lpCutoffDisabled(set) || set->misc_exactsolve )
2609  return SCIP_OKAY;
2610 
2611  /* convert SCIP infinity value to lp-solver infinity value if necessary */
2612  if( SCIPsetIsInfinity(set, uobjlim) )
2613  uobjlim = SCIPlpiInfinity(lp->lpi);
2614 
2616 
2617  if( uobjlim != lp->lpiuobjlim ) /*lint !e777*/
2618  {
2619  SCIP_Bool success;
2620 
2621  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_UOBJLIM, uobjlim, &success) );
2622  if( success )
2623  {
2624  /* mark the current solution invalid */
2625  lp->solved = FALSE;
2626  lp->primalfeasible = FALSE;
2627  lp->lpobjval = SCIP_INVALID;
2629  lp->lpiuobjlim = uobjlim;
2630  }
2631  }
2632 
2633  return SCIP_OKAY;
2634 }
2635 
2636 /** sets the feasibility tolerance of the LP solver */
2637 static
2639  SCIP_LP* lp, /**< current LP data */
2640  SCIP_Real feastol, /**< new feasibility tolerance */
2641  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2642  )
2643 {
2644  assert(lp != NULL);
2645  assert(feastol >= 0.0);
2646  assert(success != NULL);
2647 
2649 
2650  if( feastol != lp->lpifeastol ) /*lint !e777*/
2651  {
2652  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2653  if( *success )
2654  {
2655  if( lp->nrows > 0 && feastol < lp->lpifeastol )
2656  {
2657  /* mark the current solution invalid */
2658  lp->solved = FALSE;
2659  lp->primalfeasible = FALSE;
2660  lp->lpobjval = SCIP_INVALID;
2662  }
2663  lp->lpifeastol = feastol;
2664  }
2665  }
2666  else
2667  *success = FALSE;
2668 
2669  return SCIP_OKAY;
2670 }
2671 
2672 /** sets the reduced costs feasibility tolerance of the LP solver */
2673 static
2675  SCIP_LP* lp, /**< current LP data */
2676  SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2677  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2678  )
2679 {
2680  assert(lp != NULL);
2681  assert(dualfeastol >= 0.0);
2682  assert(success != NULL);
2683 
2685 
2686  if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2687  {
2688  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2689  if( *success )
2690  {
2691  if( lp->nrows > 0 && dualfeastol < lp->lpidualfeastol )
2692  {
2693  /* mark the current solution invalid */
2694  lp->solved = FALSE;
2695  lp->dualfeasible = FALSE;
2696  lp->lpobjval = SCIP_INVALID;
2698  }
2699  lp->lpidualfeastol = dualfeastol;
2700  }
2701  }
2702  else
2703  *success = FALSE;
2704 
2705  return SCIP_OKAY;
2706 }
2707 
2708 /** sets the convergence tolerance used in barrier algorithm of the LP solver */
2709 static
2711  SCIP_LP* lp, /**< current LP data */
2712  SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2713  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2714  )
2715 {
2716  assert(lp != NULL);
2717  assert(barrierconvtol >= 0.0);
2718  assert(success != NULL);
2719 
2721 
2722  if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2723  {
2724  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2725  if( *success )
2726  {
2727  if( lp->nrows > 0 && barrierconvtol < lp->lpibarrierconvtol
2729  {
2730  /* mark the current solution invalid */
2731  lp->solved = FALSE;
2732  lp->dualfeasible = FALSE;
2733  lp->lpobjval = SCIP_INVALID;
2735  }
2736  lp->lpibarrierconvtol = barrierconvtol;
2737  }
2738  }
2739  else
2740  *success = FALSE;
2741 
2742  return SCIP_OKAY;
2743 }
2744 
2745 /** sets the FROMSCRATCH setting of the LP solver */
2746 static
2748  SCIP_LP* lp, /**< current LP data */
2749  SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2750  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2751  )
2752 {
2753  assert(lp != NULL);
2754  assert(success != NULL);
2755 
2757 
2758  if( fromscratch != lp->lpifromscratch )
2759  {
2760  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2761  if( *success )
2762  lp->lpifromscratch = fromscratch;
2763  }
2764  else
2765  *success = FALSE;
2766 
2767  return SCIP_OKAY;
2768 }
2769 
2770 /** sets the FASTMIP setting of the LP solver */
2771 static
2773  SCIP_LP* lp, /**< current LP data */
2774  int fastmip, /**< new FASTMIP setting */
2775  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2776  )
2777 {
2778  assert(lp != NULL);
2779  assert(success != NULL);
2780  assert(0 <= fastmip && fastmip <= 1);
2781 
2783 
2784  if( fastmip != lp->lpifastmip )
2785  {
2786  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2787  if( *success )
2788  lp->lpifastmip = fastmip;
2789  }
2790  else
2791  *success = FALSE;
2792 
2793  return SCIP_OKAY;
2794 }
2795 
2796 /** sets the SCALING setting of the LP solver */
2797 static
2799  SCIP_LP* lp, /**< current LP data */
2800  SCIP_Bool scaling, /**< new SCALING setting */
2801  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2802  )
2803 {
2804  assert(lp != NULL);
2805  assert(success != NULL);
2806 
2808 
2809  if( scaling != lp->lpiscaling )
2810  {
2811  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2812  if( *success )
2813  lp->lpiscaling = scaling;
2814  }
2815  else
2816  *success = FALSE;
2817 
2818  return SCIP_OKAY;
2819 }
2820 
2821 /** sets the number of THREADS of the LP solver */
2822 static
2824  SCIP_LP* lp, /**< current LP data */
2825  int threads, /**< new number of threads used to solve the LP */
2826  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2827  )
2828 {
2829  assert(lp != NULL);
2830  assert(success != NULL);
2831 
2833 
2834  if( threads != lp->lpithreads )
2835  {
2836  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2837  if( *success )
2838  lp->lpithreads = threads;
2839  }
2840  else
2841  *success = FALSE;
2842 
2843  return SCIP_OKAY;
2844 }
2845 
2846 /** sets the PRESOLVING setting of the LP solver */
2847 static
2849  SCIP_LP* lp, /**< current LP data */
2850  SCIP_Bool presolving, /**< new PRESOLVING setting */
2851  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2852  )
2853 {
2854  assert(lp != NULL);
2855  assert(success != NULL);
2856 
2858 
2859  if( presolving != lp->lpipresolving )
2860  {
2861  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2862  if( *success )
2863  lp->lpipresolving = presolving;
2864  }
2865  else
2866  *success = FALSE;
2867 
2868  return SCIP_OKAY;
2869 }
2870 
2871 /** sets the ROWREPSWITCH setting of the LP solver */
2872 static
2874  SCIP_LP* lp, /**< current LP data */
2875  SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2876  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2877  )
2878 {
2879  assert(lp != NULL);
2880  assert(success != NULL);
2881 
2883 
2884  if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2885  {
2886  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2887  if( *success )
2888  lp->lpirowrepswitch = rowrepswitch;
2889  }
2890  else
2891  *success = FALSE;
2892 
2893  return SCIP_OKAY;
2894 }
2895 
2896 /** sets the iteration limit of the LP solver */
2897 static
2899  SCIP_LP* lp, /**< current LP data */
2900  int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2901  )
2902 {
2903  SCIP_Bool success;
2904 
2905  assert(lp != NULL);
2906  assert(itlim >= -1);
2907 
2908  if( itlim == -1 )
2909  itlim = INT_MAX;
2910 
2912 
2913  if( itlim != lp->lpiitlim )
2914  {
2915  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
2916  if( success )
2917  {
2918  if( itlim > lp->lpiitlim )
2919  {
2920  /* mark the current solution invalid */
2921  lp->solved = FALSE;
2922  lp->lpobjval = SCIP_INVALID;
2924  }
2925  lp->lpiitlim = itlim;
2926  }
2927  }
2928 
2929  return SCIP_OKAY;
2930 }
2931 
2932 /** sets the pricing strategy of the LP solver */
2933 static
2935  SCIP_LP* lp, /**< current LP data */
2936  SCIP_PRICING pricing /**< pricing strategy */
2937  )
2938 {
2939  SCIP_Bool success;
2940 
2941  assert(lp != NULL);
2942 
2944 
2945  if( pricing != lp->lpipricing )
2946  {
2947  SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
2948  if( success )
2949  lp->lpipricing = pricing;
2950  }
2951 
2952  return SCIP_OKAY;
2953 }
2954 
2955 /** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
2956 static
2958  SCIP_LP* lp, /**< current LP data */
2959  char pricingchar /**< character representing the pricing strategy */
2960  )
2961 {
2962  SCIP_PRICING pricing;
2963 
2964  switch( pricingchar )
2965  {
2966  case 'l':
2967  pricing = SCIP_PRICING_LPIDEFAULT;
2968  break;
2969  case 'a':
2970  pricing = SCIP_PRICING_AUTO;
2971  break;
2972  case 'f':
2973  pricing = SCIP_PRICING_FULL;
2974  break;
2975  case 'p':
2976  pricing = SCIP_PRICING_PARTIAL;
2977  break;
2978  case 's':
2979  pricing = SCIP_PRICING_STEEP;
2980  break;
2981  case 'q':
2982  pricing = SCIP_PRICING_STEEPQSTART;
2983  break;
2984  case 'd':
2985  pricing = SCIP_PRICING_DEVEX;
2986  break;
2987  default:
2988  SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
2989  return SCIP_INVALIDDATA;
2990  }
2991 
2992  SCIP_CALL( lpSetPricing(lp, pricing) );
2993 
2994  return SCIP_OKAY;
2995 }
2996 
2997 /** sets the verbosity of the LP solver */
2998 static
3000  SCIP_LP* lp, /**< current LP data */
3001  SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3002  )
3003 {
3004  SCIP_Bool success;
3005 
3006  assert(lp != NULL);
3007 
3009 
3010  if( lpinfo != lp->lpilpinfo )
3011  {
3012  SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3013  if( success )
3014  lp->lpilpinfo = lpinfo;
3015  }
3016 
3017  return SCIP_OKAY;
3018 }
3019 
3020 /** sets the CONDITIONLIMIT setting of the LP solver */
3021 static
3023  SCIP_LP* lp, /**< current LP data */
3024  SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3025  SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3026  )
3027 {
3028  assert(lp != NULL);
3029  assert(success != NULL);
3030 
3032 
3033  if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3034  {
3035  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3036  if( *success )
3037  lp->lpiconditionlimit = condlimit;
3038  }
3039  else
3040  *success = FALSE;
3041 
3042  return SCIP_OKAY;
3043 }
3044 
3045 
3046 /*
3047  * Column methods
3048  */
3049 
3050 /** creates an LP column */
3052  SCIP_COL** col, /**< pointer to column data */
3053  BMS_BLKMEM* blkmem, /**< block memory */
3054  SCIP_SET* set, /**< global SCIP settings */
3055  SCIP_STAT* stat, /**< problem statistics */
3056  SCIP_VAR* var, /**< variable, this column represents */
3057  int len, /**< number of nonzeros in the column */
3058  SCIP_ROW** rows, /**< array with rows of column entries */
3059  SCIP_Real* vals, /**< array with coefficients of column entries */
3060  SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3061  )
3062 {
3063  int i;
3064 
3065  assert(col != NULL);
3066  assert(blkmem != NULL);
3067  assert(set != NULL);
3068  assert(stat != NULL);
3069  assert(var != NULL);
3070  assert(len >= 0);
3071  assert(len == 0 || (rows != NULL && vals != NULL));
3072 
3073  SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3074 
3075  if( len > 0 )
3076  {
3077  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3078  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3079  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3080 
3081  for( i = 0; i < len; ++i )
3082  {
3083  assert(rows[i] != NULL);
3084  assert(!SCIPsetIsZero(set, vals[i]));
3085  (*col)->linkpos[i] = -1;
3086  }
3087  }
3088  else
3089  {
3090  (*col)->rows = NULL;
3091  (*col)->vals = NULL;
3092  (*col)->linkpos = NULL;
3093  }
3094 
3095  (*col)->var = var;
3096  (*col)->obj = SCIPvarGetObj(var);
3097  (*col)->lb = SCIPvarGetLbLocal(var);
3098  (*col)->ub = SCIPvarGetUbLocal(var);
3099  (*col)->flushedobj = 0.0;
3100  (*col)->flushedlb = 0.0;
3101  (*col)->flushedub = 0.0;
3102  (*col)->index = stat->ncolidx++;
3103  (*col)->size = len;
3104  (*col)->len = len;
3105  (*col)->nlprows = 0;
3106  (*col)->nunlinked = len;
3107  (*col)->lppos = -1;
3108  (*col)->lpipos = -1;
3109  (*col)->lpdepth = -1;
3110  (*col)->primsol = 0.0;
3111  (*col)->redcost = SCIP_INVALID;
3112  (*col)->farkascoef = SCIP_INVALID;
3113  (*col)->minprimsol = (*col)->ub;
3114  (*col)->maxprimsol = (*col)->lb;
3115  (*col)->sbdown = SCIP_INVALID;
3116  (*col)->sbup = SCIP_INVALID;
3117  (*col)->sbsolval = SCIP_INVALID;
3118  (*col)->sblpobjval = SCIP_INVALID;
3119  (*col)->sbnode = -1;
3120  (*col)->validredcostlp = -1;
3121  (*col)->validfarkaslp = -1;
3122  (*col)->validsblp = -1;
3123  (*col)->sbitlim = -1;
3124  (*col)->nsbcalls = 0;
3125  (*col)->age = 0;
3126  (*col)->obsoletenode = -1;
3127  (*col)->var_probindex = SCIPvarGetProbindex(var);
3128  (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3129  (*col)->lprowssorted = TRUE;
3130  (*col)->nonlprowssorted = (len <= 1);
3131  (*col)->objchanged = FALSE;
3132  (*col)->lbchanged = FALSE;
3133  (*col)->ubchanged = FALSE;
3134  (*col)->coefchanged = FALSE;
3135  (*col)->integral = SCIPvarIsIntegral(var);
3136  (*col)->removable = removable;
3137  (*col)->sbdownvalid = FALSE;
3138  (*col)->sbupvalid = FALSE;
3139  (*col)->lazylb = SCIPvarGetLbLazy(var);
3140  (*col)->lazyub = SCIPvarGetUbLazy(var);
3141  (*col)->storedsolvals = NULL;
3142 
3143  return SCIP_OKAY;
3144 }
3145 
3146 /** frees an LP column */
3148  SCIP_COL** col, /**< pointer to LP column */
3149  BMS_BLKMEM* blkmem, /**< block memory */
3150  SCIP_SET* set, /**< global SCIP settings */
3151  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3152  SCIP_LP* lp /**< current LP data */
3153  )
3154 {
3155  assert(blkmem != NULL);
3156  assert(col != NULL);
3157  assert(*col != NULL);
3158  assert((*col)->var != NULL);
3159  assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3160  assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3161  assert((*col)->lppos == -1);
3162  assert((*col)->lpipos == -1);
3163 
3164  /* remove column indices from corresponding rows */
3165  SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3166 
3167  BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3168  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3169  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3170  BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3171  BMSfreeBlockMemory(blkmem, col);
3172 
3173  return SCIP_OKAY;
3174 }
3175 
3176 /** output column to file stream */
3178  SCIP_COL* col, /**< LP column */
3179  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3180  FILE* file /**< output file (or NULL for standard output) */
3181  )
3182 {
3183  int r;
3184 
3185  assert(col != NULL);
3186  assert(col->var != NULL);
3187 
3188  /* print bounds */
3189  SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3190 
3191  /* print coefficients */
3192  if( col->len == 0 )
3193  SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3194  for( r = 0; r < col->len; ++r )
3195  {
3196  assert(col->rows[r] != NULL);
3197  assert(col->rows[r]->name != NULL);
3198  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3199  }
3200  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3201 }
3202 
3203 /** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3204  */
3206  SCIP_COL* col /**< column to be sorted */
3207  )
3208 {
3209  /* sort LP rows */
3210  colSortLP(col);
3211 
3212  /* sort non-LP rows */
3213  colSortNonLP(col);
3214 }
3215 
3216 /** adds a previously non existing coefficient to an LP column */
3218  SCIP_COL* col, /**< LP column */
3219  BMS_BLKMEM* blkmem, /**< block memory */
3220  SCIP_SET* set, /**< global SCIP settings */
3221  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3222  SCIP_LP* lp, /**< current LP data */
3223  SCIP_ROW* row, /**< LP row */
3224  SCIP_Real val /**< value of coefficient */
3225  )
3226 {
3227  assert(lp != NULL);
3228  assert(!lp->diving);
3229 
3230  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3231 
3232  checkLinks(lp);
3233 
3234  return SCIP_OKAY;
3235 }
3236 
3237 /** deletes existing coefficient from column */
3239  SCIP_COL* col, /**< column to be changed */
3240  BMS_BLKMEM* blkmem, /**< block memory */
3241  SCIP_SET* set, /**< global SCIP settings */
3242  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3243  SCIP_LP* lp, /**< current LP data */
3244  SCIP_ROW* row /**< coefficient to be deleted */
3245  )
3246 {
3247  int pos;
3248 
3249  assert(col != NULL);
3250  assert(col->var != NULL);
3251  assert(lp != NULL);
3252  assert(!lp->diving);
3253  assert(row != NULL);
3254 
3255  /* search the position of the row in the column's row vector */
3256  pos = colSearchCoef(col, row);
3257  if( pos == -1 )
3258  {
3259  SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3260  return SCIP_INVALIDDATA;
3261  }
3262  assert(0 <= pos && pos < col->len);
3263  assert(col->rows[pos] == row);
3264 
3265  /* if row knows of the column, remove the column from the row's col vector */
3266  if( col->linkpos[pos] >= 0 )
3267  {
3268  assert(row->cols[col->linkpos[pos]] == col);
3269  assert(row->cols_index[col->linkpos[pos]] == col->index);
3270  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3271  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3272  }
3273 
3274  /* delete the row from the column's row vector */
3275  SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3276 
3277  checkLinks(lp);
3278 
3279  return SCIP_OKAY;
3280 }
3281 
3282 /** changes or adds a coefficient to an LP column */
3284  SCIP_COL* col, /**< LP column */
3285  BMS_BLKMEM* blkmem, /**< block memory */
3286  SCIP_SET* set, /**< global SCIP settings */
3287  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3288  SCIP_LP* lp, /**< current LP data */
3289  SCIP_ROW* row, /**< LP row */
3290  SCIP_Real val /**< value of coefficient */
3291  )
3292 {
3293  int pos;
3294 
3295  assert(col != NULL);
3296  assert(lp != NULL);
3297  assert(!lp->diving);
3298  assert(row != NULL);
3299 
3300  /* search the position of the row in the column's row vector */
3301  pos = colSearchCoef(col, row);
3302 
3303  /* check, if row already exists in the column's row vector */
3304  if( pos == -1 )
3305  {
3306  /* add previously not existing coefficient */
3307  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3308  }
3309  else
3310  {
3311  /* modify already existing coefficient */
3312  assert(0 <= pos && pos < col->len);
3313  assert(col->rows[pos] == row);
3314 
3315  /* if row knows of the column, change the corresponding coefficient in the row */
3316  if( col->linkpos[pos] >= 0 )
3317  {
3318  assert(row->cols[col->linkpos[pos]] == col);
3319  assert(row->cols_index[col->linkpos[pos]] == col->index);
3320  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3321  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3322  }
3323 
3324  /* change the coefficient in the column */
3325  SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3326  }
3327 
3328  checkLinks(lp);
3329 
3330  return SCIP_OKAY;
3331 }
3332 
3333 /** increases value of an existing or non-existing coefficient in an LP column */
3335  SCIP_COL* col, /**< LP column */
3336  BMS_BLKMEM* blkmem, /**< block memory */
3337  SCIP_SET* set, /**< global SCIP settings */
3338  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3339  SCIP_LP* lp, /**< current LP data */
3340  SCIP_ROW* row, /**< LP row */
3341  SCIP_Real incval /**< value to add to the coefficient */
3342  )
3343 {
3344  int pos;
3345 
3346  assert(col != NULL);
3347  assert(lp != NULL);
3348  assert(!lp->diving);
3349  assert(row != NULL);
3350 
3351  if( SCIPsetIsZero(set, incval) )
3352  return SCIP_OKAY;
3353 
3354  /* search the position of the row in the column's row vector */
3355  pos = colSearchCoef(col, row);
3356 
3357  /* check, if row already exists in the column's row vector */
3358  if( pos == -1 )
3359  {
3360  /* add previously not existing coefficient */
3361  SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3362  }
3363  else
3364  {
3365  /* modify already existing coefficient */
3366  assert(0 <= pos && pos < col->len);
3367  assert(col->rows[pos] == row);
3368 
3369  /* if row knows of the column, change the corresponding coefficient in the row */
3370  if( col->linkpos[pos] >= 0 )
3371  {
3372  assert(row->cols[col->linkpos[pos]] == col);
3373  assert(row->cols_index[col->linkpos[pos]] == col->index);
3374  assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3375  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3376  }
3377 
3378  /* change the coefficient in the column */
3379  SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3380  }
3381 
3382  checkLinks(lp);
3383 
3384  return SCIP_OKAY;
3385 }
3386 
3387 /** insert column in the chgcols list (if not already there) */
3388 static
3390  SCIP_COL* col, /**< LP column to change */
3391  SCIP_SET* set, /**< global SCIP settings */
3392  SCIP_LP* lp /**< current LP data */
3393  )
3394 {
3395  if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3396  {
3397  SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3398  lp->chgcols[lp->nchgcols] = col;
3399  lp->nchgcols++;
3400  }
3401 
3402  /* mark the current LP unflushed */
3403  lp->flushed = FALSE;
3404 
3405  return SCIP_OKAY;
3406 }
3407 
3408 /** changes objective value of column */
3410  SCIP_COL* col, /**< LP column to change */
3411  SCIP_SET* set, /**< global SCIP settings */
3412  SCIP_LP* lp, /**< current LP data */
3413  SCIP_Real newobj /**< new objective value */
3414  )
3415 {
3416  assert(col != NULL);
3417  assert(col->var != NULL);
3418  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3419  assert(SCIPvarGetCol(col->var) == col);
3420  assert(lp != NULL);
3421 
3422  SCIPdebugMessage("changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3423 
3424  /* only add actual changes */
3425  if( !SCIPsetIsEQ(set, col->obj, newobj) )
3426  {
3427  /* only variables with a real position in the LPI can be inserted */
3428  if( col->lpipos >= 0 )
3429  {
3430  /* insert column in the chgcols list (if not already there) */
3431  SCIP_CALL( insertColChgcols(col, set, lp) );
3432 
3433  /* mark objective value change in the column */
3434  col->objchanged = TRUE;
3435 
3436  assert(lp->nchgcols > 0);
3437  }
3438  /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3439  * LP and the LP has to be flushed
3440  */
3441  else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3442  || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3443  {
3444  /* mark the LP unflushed */
3445  lp->flushed = FALSE;
3446  }
3447  }
3448 
3449  /* store new objective function value */
3450  col->obj = newobj;
3451 
3452  return SCIP_OKAY;
3453 }
3454 
3455 /** changes lower bound of column */
3457  SCIP_COL* col, /**< LP column to change */
3458  SCIP_SET* set, /**< global SCIP settings */
3459  SCIP_LP* lp, /**< current LP data */
3460  SCIP_Real newlb /**< new lower bound value */
3461  )
3462 {
3463  assert(col != NULL);
3464  assert(col->var != NULL);
3465  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3466  assert(SCIPvarGetCol(col->var) == col);
3467  assert(lp != NULL);
3468 
3469  SCIPdebugMessage("changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3470 
3471  /* only add actual changes */
3472  if( !SCIPsetIsEQ(set, col->lb, newlb) )
3473  {
3474  /* only variables with a real position in the LPI can be inserted */
3475  if( col->lpipos >= 0 )
3476  {
3477  /* insert column in the chgcols list (if not already there) */
3478  SCIP_CALL( insertColChgcols(col, set, lp) );
3479 
3480  /* mark bound change in the column */
3481  col->lbchanged = TRUE;
3482 
3483  assert(lp->nchgcols > 0);
3484  }
3485  /* 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
3486  * flushed
3487  */
3488  else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3489  {
3490  /* mark the LP unflushed */
3491  lp->flushed = FALSE;
3492  }
3493  }
3494 
3495  col->lb = newlb;
3496 
3497  return SCIP_OKAY;
3498 }
3499 
3500 /** changes upper bound of column */
3502  SCIP_COL* col, /**< LP column to change */
3503  SCIP_SET* set, /**< global SCIP settings */
3504  SCIP_LP* lp, /**< current LP data */
3505  SCIP_Real newub /**< new upper bound value */
3506  )
3507 {
3508  assert(col != NULL);
3509  assert(col->var != NULL);
3510  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3511  assert(SCIPvarGetCol(col->var) == col);
3512  assert(lp != NULL);
3513 
3514  SCIPdebugMessage("changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3515 
3516  /* only add actual changes */
3517  if( !SCIPsetIsEQ(set, col->ub, newub) )
3518  {
3519  /* only variables with a real position in the LPI can be inserted */
3520  if( col->lpipos >= 0 )
3521  {
3522  /* insert column in the chgcols list (if not already there) */
3523  SCIP_CALL( insertColChgcols(col, set, lp) );
3524 
3525  /* mark bound change in the column */
3526  col->ubchanged = TRUE;
3527 
3528  assert(lp->nchgcols > 0);
3529  }
3530  /* 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
3531  * flushed
3532  */
3533  else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3534  {
3535  /* mark the LP unflushed */
3536  lp->flushed = FALSE;
3537  }
3538  }
3539 
3540  col->ub = newub;
3541 
3542  return SCIP_OKAY;
3543 }
3544 
3545 /** calculates the reduced costs of a column using the given dual solution vector */
3547  SCIP_COL* col, /**< LP column */
3548  SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3549  )
3550 {
3551  SCIP_ROW* row;
3552  SCIP_Real redcost;
3553  int i;
3554 
3555  assert(col != NULL);
3556  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3557  assert(SCIPvarGetCol(col->var) == col);
3558  assert(dualsol != NULL);
3559 
3560  redcost = col->obj;
3561  for( i = 0; i < col->nlprows; ++i )
3562  {
3563  row = col->rows[i];
3564  assert(row != NULL);
3565  assert(row->lppos >= 0);
3566  redcost -= col->vals[i] * dualsol[row->lppos];
3567  }
3568 
3569  if( col->nunlinked > 0 )
3570  {
3571  for( i = col->nlprows; i < col->len; ++i )
3572  {
3573  row = col->rows[i];
3574  assert(row != NULL);
3575  assert(row->lppos == -1 || col->linkpos[i] == -1);
3576  if( row->lppos >= 0 )
3577  redcost -= col->vals[i] * dualsol[row->lppos];
3578  }
3579  }
3580 #ifndef NDEBUG
3581  else
3582  {
3583  for( i = col->nlprows; i < col->len; ++i )
3584  {
3585  row = col->rows[i];
3586  assert(row != NULL);
3587  assert(row->lppos == -1);
3588  assert(col->linkpos[i] >= 0);
3589  }
3590  }
3591 #endif
3592 
3593  return redcost;
3594 }
3595 
3596 /** calculates the reduced costs of a column using the dual solution stored in the rows */
3597 static
3599  SCIP_COL* col /**< LP column */
3600  )
3601 {
3602  SCIP_ROW* row;
3603  SCIP_Real redcost;
3604  int i;
3605 
3606  assert(col != NULL);
3607  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3608  assert(SCIPvarGetCol(col->var) == col);
3609 
3610  redcost = col->obj;
3611  for( i = 0; i < col->nlprows; ++i )
3612  {
3613  row = col->rows[i];
3614  assert(row != NULL);
3615  assert(row->dualsol < SCIP_INVALID);
3616  assert(row->lppos >= 0);
3617  assert(col->linkpos[i] >= 0);
3618  redcost -= col->vals[i] * row->dualsol;
3619  }
3620 
3621  if( col->nunlinked > 0 )
3622  {
3623  for( i = col->nlprows; i < col->len; ++i )
3624  {
3625  row = col->rows[i];
3626  assert(row != NULL);
3627  assert(row->lppos >= 0 || row->dualsol == 0.0);
3628  assert(row->lppos == -1 || col->linkpos[i] == -1);
3629  if( row->lppos >= 0 )
3630  redcost -= col->vals[i] * row->dualsol;
3631  }
3632  }
3633 #ifndef NDEBUG
3634  else
3635  {
3636  for( i = col->nlprows; i < col->len; ++i )
3637  {
3638  row = col->rows[i];
3639  assert(row != NULL);
3640  assert(row->dualsol == 0.0);
3641  assert(row->lppos == -1);
3642  assert(col->linkpos[i] >= 0);
3643  }
3644  }
3645 #endif
3646 
3647  return redcost;
3648 }
3649 
3650 /** gets the reduced costs of a column in last LP or after recalculation */
3652  SCIP_COL* col, /**< LP column */
3653  SCIP_STAT* stat, /**< problem statistics */
3654  SCIP_LP* lp /**< current LP data */
3655  )
3656 {
3657  assert(col != NULL);
3658  assert(stat != NULL);
3659  assert(lp != NULL);
3660  assert(col->validredcostlp <= stat->lpcount);
3661  assert(lp->validsollp == stat->lpcount);
3662 
3663  if( col->validredcostlp < stat->lpcount )
3664  {
3665  col->redcost = colCalcInternalRedcost(col);
3666  col->validredcostlp = stat->lpcount;
3667  }
3668  assert(col->validredcostlp == stat->lpcount);
3669  assert(col->redcost < SCIP_INVALID);
3670 
3671  return col->redcost;
3672 }
3673 
3674 /** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3676  SCIP_COL* col, /**< LP column */
3677  SCIP_SET* set, /**< global SCIP settings */
3678  SCIP_STAT* stat, /**< problem statistics */
3679  SCIP_LP* lp /**< current LP data */
3680  )
3681 {
3682  assert(col != NULL);
3683  assert(set != NULL);
3684  assert(stat != NULL);
3685  assert(lp != NULL);
3686  assert(lp->validsollp == stat->lpcount);
3687 
3688  /* A column's reduced cost is defined as
3689  * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3690  * The activity is equal to the activity of the corresponding row in the dual LP.
3691  * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3692  * The sides of the dual row depend on the bounds of the column:
3693  * - lb == ub : dual row is a free row with infinite sides
3694  * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3695  * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3696  * - lb < ub <= 0: obj <= activity => redcost <= 0
3697  */
3698  if( SCIPsetIsEQ(set, col->lb, col->ub) )
3699  {
3700  /* dual row is free */
3701  return SCIPsetInfinity(set);
3702  }
3703  else
3704  {
3705  SCIP_Real redcost;
3706 
3707  /* calculate reduced costs */
3708  redcost = SCIPcolGetRedcost(col, stat, lp);
3709 
3710  if( !SCIPsetIsNegative(set, col->lb) )
3711  {
3712  /* dual row is activity <= obj <=> redcost >= 0 */
3713  return redcost;
3714  }
3715  else if( SCIPsetIsPositive(set, col->ub) )
3716  {
3717  /* dual row is activity == obj <=> redcost == 0 */
3718  return -REALABS(redcost);
3719  }
3720  else
3721  {
3722  /* dual row is activity >= obj <=> redcost <= 0 */
3723  return -redcost;
3724  }
3725  }
3726 }
3727 
3728 /** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
3730  SCIP_COL* col, /**< LP column */
3731  SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
3732  )
3733 {
3734  SCIP_ROW* row;
3735  SCIP_Real farkas;
3736  int i;
3737 
3738  assert(col != NULL);
3739  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3740  assert(SCIPvarGetCol(col->var) == col);
3741  assert(dualfarkas != NULL);
3742 
3743  farkas = 0.0;
3744  for( i = 0; i < col->nlprows; ++i )
3745  {
3746  row = col->rows[i];
3747  assert(row != NULL);
3748  assert(row->lppos >= 0);
3749  farkas += col->vals[i] * dualfarkas[row->lppos];
3750  }
3751 
3752  if( col->nunlinked > 0 )
3753  {
3754  for( i = col->nlprows; i < col->len; ++i )
3755  {
3756  row = col->rows[i];
3757  assert(row != NULL);
3758  assert(row->lppos == -1 || col->linkpos[i] == -1);
3759  if( row->lppos >= 0 )
3760  farkas += col->vals[i] * dualfarkas[row->lppos];
3761  }
3762  }
3763 #ifndef NDEBUG
3764  else
3765  {
3766  for( i = col->nlprows; i < col->len; ++i )
3767  {
3768  row = col->rows[i];
3769  assert(row != NULL);
3770  assert(row->lppos == -1);
3771  assert(col->linkpos[i] >= 0);
3772  }
3773  }
3774 #endif
3775 
3776  return farkas;
3777 }
3778 
3779 /** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
3780 static
3782  SCIP_COL* col /**< LP column */
3783  )
3784 {
3785  SCIP_ROW* row;
3786  SCIP_Real farkas;
3787  int i;
3788 
3789  assert(col != NULL);
3790  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3791  assert(SCIPvarGetCol(col->var) == col);
3792 
3793  farkas = 0.0;
3794  for( i = 0; i < col->nlprows; ++i )
3795  {
3796  row = col->rows[i];
3797  assert(row != NULL);
3798  assert(row->dualfarkas < SCIP_INVALID);
3799  assert(row->lppos >= 0);
3800  assert(col->linkpos[i] >= 0);
3801  farkas += col->vals[i] * row->dualfarkas;
3802  }
3803 
3804  if( col->nunlinked > 0 )
3805  {
3806  for( i = col->nlprows; i < col->len; ++i )
3807  {
3808  row = col->rows[i];
3809  assert(row != NULL);
3810  assert(row->lppos >= 0 || row->dualfarkas == 0.0);
3811  assert(row->lppos == -1 || col->linkpos[i] == -1);
3812  if( row->lppos >= 0 )
3813  farkas += col->vals[i] * row->dualfarkas;
3814  }
3815  }
3816 #ifndef NDEBUG
3817  else
3818  {
3819  for( i = col->nlprows; i < col->len; ++i )
3820  {
3821  row = col->rows[i];
3822  assert(row != NULL);
3823  assert(row->dualfarkas == 0.0);
3824  assert(row->lppos == -1);
3825  assert(col->linkpos[i] >= 0);
3826  }
3827  }
3828 #endif
3829 
3830  return farkas;
3831 }
3832 
3833 /** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
3835  SCIP_COL* col, /**< LP column */
3836  SCIP_STAT* stat, /**< problem statistics */
3837  SCIP_LP* lp /**< current LP data */
3838  )
3839 {
3840  assert(col != NULL);
3841  assert(stat != NULL);
3842  assert(lp != NULL);
3843  assert(col->validfarkaslp <= stat->lpcount);
3844  assert(lp->validfarkaslp == stat->lpcount);
3845 
3846  if( col->validfarkaslp < stat->lpcount )
3847  {
3849  col->validfarkaslp = stat->lpcount;
3850  }
3851  assert(col->validfarkaslp == stat->lpcount);
3852  assert(col->farkascoef < SCIP_INVALID);
3853 
3854  return col->farkascoef;
3855 }
3856 
3857 /** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
3858  * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
3859  */
3861  SCIP_COL* col, /**< LP column */
3862  SCIP_STAT* stat, /**< problem statistics */
3863  SCIP_LP* lp /**< current LP data */
3864  )
3865 {
3866  SCIP_Real farkascoef;
3867 
3868  assert(col != NULL);
3869 
3870  farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
3871 
3872  if( farkascoef > 0.0 )
3873  return col->ub * farkascoef;
3874  else
3875  return col->lb * farkascoef;
3876 }
3877 
3878 /** start strong branching - call before any strong branching */
3880  SCIP_LP* lp /**< LP data */
3881  )
3882 {
3883  assert(lp != NULL);
3884  assert(!lp->strongbranching);
3885 
3886  lp->strongbranching = TRUE;
3887  SCIPdebugMessage("starting strong branching ...\n");
3889 
3890  return SCIP_OKAY;
3891 }
3892 
3893 /** end strong branching - call after any strong branching */
3895  SCIP_LP* lp /**< LP data */
3896  )
3897 {
3898  assert(lp != NULL);
3899  assert(lp->strongbranching);
3900 
3901  lp->strongbranching = FALSE;
3902  SCIPdebugMessage("ending strong branching ...\n");
3904 
3905  return SCIP_OKAY;
3906 }
3907 
3908 /** sets strong branching information for a column variable */
3910  SCIP_COL* col, /**< LP column */
3911  SCIP_SET* set, /**< global SCIP settings */
3912  SCIP_STAT* stat, /**< dynamic problem statistics */
3913  SCIP_LP* lp, /**< LP data */
3914  SCIP_Real lpobjval, /**< objective value of the current LP */
3915  SCIP_Real primsol, /**< primal solution value of the column in the current LP */
3916  SCIP_Real sbdown, /**< dual bound after branching column down */
3917  SCIP_Real sbup, /**< dual bound after branching column up */
3918  SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
3919  SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
3920  SCIP_Longint iter, /**< total number of strong branching iterations */
3921  int itlim /**< iteration limit applied to the strong branching call */
3922  )
3923 {
3924  assert(col != NULL);
3925  assert(col->var != NULL);
3926  assert(SCIPcolIsIntegral(col));
3927  assert(SCIPvarIsIntegral(col->var));
3928  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3929  assert(SCIPvarGetCol(col->var) == col);
3930  assert(col->lpipos >= 0);
3931  assert(col->lppos >= 0);
3932  assert(set != NULL);
3933  assert(stat != NULL);
3934  assert(lp != NULL);
3935  assert(lp->strongbranchprobing);
3936  assert(col->lppos < lp->ncols);
3937  assert(lp->cols[col->lppos] == col);
3938  assert(itlim >= 1);
3939 
3940  col->sblpobjval = lpobjval;
3941  col->sbsolval = primsol;
3942  col->validsblp = stat->lpcount - stat->nsbdivinglps;
3943  col->sbnode = stat->nnodes;
3944 
3945  col->sbitlim = itlim;
3946  col->nsbcalls++;
3947 
3948  col->sbdown = MIN(sbdown, lp->cutoffbound);
3949  col->sbup = MIN(sbup, lp->cutoffbound);
3950  col->sbdownvalid = sbdownvalid;
3951  col->sbupvalid = sbupvalid;
3952 
3953  stat->nstrongbranchs++;
3954  stat->nsblpiterations += iter;
3955  if( stat->nnodes == 1 )
3956  {
3957  stat->nrootstrongbranchs++;
3958  stat->nrootsblpiterations += iter;
3959  }
3960 }
3961 
3962 /** invalidates strong branching information for a column variable */
3964  SCIP_COL* col, /**< LP column */
3965  SCIP_SET* set, /**< global SCIP settings */
3966  SCIP_STAT* stat, /**< dynamic problem statistics */
3967  SCIP_LP* lp /**< LP data */
3968  )
3969 {
3970  assert(col != NULL);
3971  assert(col->var != NULL);
3972  assert(SCIPcolIsIntegral(col));
3973  assert(SCIPvarIsIntegral(col->var));
3974  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3975  assert(SCIPvarGetCol(col->var) == col);
3976  assert(col->lpipos >= 0);
3977  assert(col->lppos >= 0);
3978  assert(set != NULL);
3979  assert(stat != NULL);
3980  assert(lp != NULL);
3981  assert(lp->strongbranchprobing);
3982  assert(col->lppos < lp->ncols);
3983  assert(lp->cols[col->lppos] == col);
3984 
3985  col->sbdown = SCIP_INVALID;
3986  col->sbup = SCIP_INVALID;
3987  col->sbdownvalid = FALSE;
3988  col->sbupvalid = FALSE;
3989  col->validsblp = -1;
3990  col->sbsolval = SCIP_INVALID;
3991  col->sblpobjval = SCIP_INVALID;
3992  col->sbnode = -1;
3993  col->sbitlim = -1;
3994 }
3995 
3996 
3997 /** gets strong branching information on a column variable */
3999  SCIP_COL* col, /**< LP column */
4000  SCIP_Bool integral, /**< should integral strong branching be performed? */
4001  SCIP_SET* set, /**< global SCIP settings */
4002  SCIP_STAT* stat, /**< dynamic problem statistics */
4003  SCIP_PROB* prob, /**< problem data */
4004  SCIP_LP* lp, /**< LP data */
4005  int itlim, /**< iteration limit for strong branchings */
4006  SCIP_Real* down, /**< stores dual bound after branching column down */
4007  SCIP_Real* up, /**< stores dual bound after branching column up */
4008  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4009  * otherwise, it can only be used as an estimate value */
4010  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4011  * otherwise, it can only be used as an estimate value */
4012  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4013  )
4014 {
4015  assert(col != NULL);
4016  assert(col->var != NULL);
4017  assert(SCIPcolIsIntegral(col));
4018  assert(SCIPvarIsIntegral(col->var));
4019  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4020  assert(SCIPvarGetCol(col->var) == col);
4021  assert(col->primsol < SCIP_INVALID);
4022  assert(col->lpipos >= 0);
4023  assert(col->lppos >= 0);
4024  assert(set != NULL);
4025  assert(stat != NULL);
4026  assert(lp != NULL);
4027  assert(lp->flushed);
4028  assert(lp->solved);
4029  assert(lp->strongbranching);
4030  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4031  assert(lp->validsollp == stat->lpcount);
4032  assert(col->lppos < lp->ncols);
4033  assert(lp->cols[col->lppos] == col);
4034  assert(itlim >= 1);
4035  /* assert(down != NULL);
4036  * assert(up != NULL); temporary hack for cloud branching
4037  */
4038  assert(lperror != NULL);
4039 
4040  *lperror = FALSE;
4041 
4042  if( col->validsblp != stat->lpcount - stat->nsbdivinglps || itlim > col->sbitlim )
4043  {
4044  col->validsblp = stat->lpcount - stat->nsbdivinglps;
4045  col->sbsolval = col->primsol;
4046  col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4047  col->sbnode = stat->nnodes;
4048  assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4049 
4050  /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4051  if( lp->looseobjvalinf > 0 )
4052  {
4053  col->sbdown = -SCIPsetInfinity(set);
4054  col->sbup = -SCIPsetInfinity(set);
4055  col->sbdownvalid = FALSE;
4056  col->sbupvalid = FALSE;
4057  }
4058  else
4059  {
4060  SCIP_RETCODE retcode;
4061  SCIP_Real sbdown;
4062  SCIP_Real sbup;
4063  SCIP_Bool sbdownvalid;
4064  SCIP_Bool sbupvalid;
4065  int iter;
4066 
4067  SCIPdebugMessage("performing strong branching on variable <%s>(%g) with %d iterations\n",
4068  SCIPvarGetName(col->var), col->primsol, itlim);
4069 
4070  /* start timing */
4071  SCIPclockStart(stat->strongbranchtime, set);
4072 
4073  /* call LPI strong branching */
4074  col->sbitlim = itlim;
4075  col->nsbcalls++;
4076 
4077  sbdown = lp->lpobjval;
4078  sbup = lp->lpobjval;
4079 
4080  if( integral )
4081  retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4082  else
4083  {
4084  assert( ! SCIPsetIsIntegral(set, col->primsol) );
4085  retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4086  }
4087 
4088 
4089  /* check return code for errors */
4090  if( retcode == SCIP_LPERROR )
4091  {
4092  *lperror = TRUE;
4093  col->sbdown = SCIP_INVALID;
4094  col->sbup = SCIP_INVALID;
4095  col->sbdownvalid = FALSE;
4096  col->sbupvalid = FALSE;
4097  col->validsblp = -1;
4098  col->sbsolval = SCIP_INVALID;
4099  col->sblpobjval = SCIP_INVALID;
4100  col->sbnode = -1;
4101  }
4102  else
4103  {
4104  SCIP_Real looseobjval;
4105 
4106  *lperror = FALSE;
4107  SCIP_CALL( retcode );
4108 
4109  looseobjval = getFiniteLooseObjval(lp, set, prob);
4110  col->sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4111  col->sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4112 
4113  col->sbdownvalid = sbdownvalid;
4114  col->sbupvalid = sbupvalid;
4115 
4116  /* update strong branching statistics */
4117  if( iter == -1 )
4118  {
4119  /* calculate average iteration number */
4120  iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4121  : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4122  : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4123  : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4124  : 0;
4125  if( iter/2 >= itlim )
4126  iter = 2*itlim;
4127  }
4128  stat->nstrongbranchs++;
4129  stat->nsblpiterations += iter;
4130  if( stat->nnodes == 1 )
4131  {
4132  stat->nrootstrongbranchs++;
4133  stat->nrootsblpiterations += iter;
4134  }
4135  }
4136 
4137  /* stop timing */
4138  SCIPclockStop(stat->strongbranchtime, set);
4139  }
4140  }
4141  assert(*lperror || col->sbdown < SCIP_INVALID);
4142  assert(*lperror || col->sbup < SCIP_INVALID);
4143 
4144  if( down != NULL)
4145  *down = col->sbdown;
4146  if( up != NULL )
4147  *up = col->sbup;
4148  if( downvalid != NULL )
4149  *downvalid = col->sbdownvalid;
4150  if( upvalid != NULL )
4151  *upvalid = col->sbupvalid;
4152 
4153  return SCIP_OKAY;
4154 }
4155 
4156 /** gets strong branching information on column variables */
4158  SCIP_COL** cols, /**< LP columns */
4159  int ncols, /**< number of columns */
4160  SCIP_Bool integral, /**< should integral strong branching be performed? */
4161  SCIP_SET* set, /**< global SCIP settings */
4162  SCIP_STAT* stat, /**< dynamic problem statistics */
4163  SCIP_PROB* prob, /**< problem data */
4164  SCIP_LP* lp, /**< LP data */
4165  int itlim, /**< iteration limit for strong branchings */
4166  SCIP_Real* down, /**< stores dual bounds after branching columns down */
4167  SCIP_Real* up, /**< stores dual bounds after branching columns up */
4168  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4169  * otherwise, they can only be used as an estimate value */
4170  SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4171  * otherwise, they can only be used as an estimate value */
4172  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4173  )
4174 {
4175  SCIP_RETCODE retcode;
4176  SCIP_Real* sbdown;
4177  SCIP_Real* sbup;
4178  SCIP_Bool* sbdownvalid;
4179  SCIP_Bool* sbupvalid;
4180  SCIP_Real* primsols;
4181  SCIP_COL** subcols;
4182  int* lpipos;
4183  int* subidx;
4184  int nsubcols;
4185  int iter;
4186  int j;
4187 
4188  assert(cols != NULL);
4189  assert(set != NULL);
4190  assert(stat != NULL);
4191  assert(lp != NULL);
4192  assert(lp->flushed);
4193  assert(lp->solved);
4194  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4195  assert(lp->validsollp == stat->lpcount);
4196  assert(itlim >= 1);
4197  assert(down != NULL);
4198  assert(up != NULL);
4199  assert(lperror != NULL);
4200 
4201  *lperror = FALSE;
4202 
4203  if ( ncols <= 0 )
4204  return SCIP_OKAY;
4205 
4206  /* start timing */
4207  SCIPclockStart(stat->strongbranchtime, set);
4208 
4209  /* initialize storage */
4210  SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4211  SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4212  SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4213  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4214  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4215  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4216  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4217  SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4218 
4219  nsubcols = 0;
4220  for( j = 0; j < ncols; ++j )
4221  {
4222  SCIP_COL* col;
4223  col = cols[j];
4224 
4225  assert(col->lppos < lp->ncols);
4226  assert(lp->cols[col->lppos] == col);
4227  assert(SCIPcolIsIntegral(col));
4228  assert(SCIPvarIsIntegral(col->var));
4229  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4230  assert(SCIPvarGetCol(col->var) == col);
4231  assert(col->primsol < SCIP_INVALID);
4232  assert(col->lpipos >= 0);
4233  assert(col->lppos >= 0);
4234 
4235  if( col->validsblp != stat->lpcount - stat->nsbdivinglps || itlim > col->sbitlim )
4236  {
4237  col->validsblp = stat->lpcount - stat->nsbdivinglps;
4238  col->sbsolval = col->primsol;
4239  col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4240  col->sbnode = stat->nnodes;
4241  assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4242 
4243  /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4244  if( lp->looseobjvalinf > 0 )
4245  {
4246  /* directly set up column and result vectors*/
4247  col->sbdown = -SCIPsetInfinity(set);
4248  col->sbup = -SCIPsetInfinity(set);
4249  col->sbdownvalid = FALSE;
4250  col->sbupvalid = FALSE;
4251  down[j] = col->sbdown;
4252  up[j] = col->sbup;
4253  if( downvalid != NULL )
4254  downvalid[j] = col->sbdownvalid;
4255  if( upvalid != NULL )
4256  upvalid[j] = col->sbupvalid;
4257  }
4258  else
4259  {
4260  col->sbitlim = itlim;
4261  col->nsbcalls++;
4262 
4263  lpipos[nsubcols] = col->lpipos;
4264  primsols[nsubcols] = col->primsol;
4265  assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4266  subidx[nsubcols] = j;
4267  subcols[nsubcols++] = col;
4268  }
4269  }
4270  else
4271  {
4272  /* directly set up resulting values (use stored values) */
4273  down[j] = col->sbdown;
4274  up[j] = col->sbup;
4275  if( downvalid != NULL )
4276  downvalid[j] = col->sbdownvalid;
4277  if( upvalid != NULL )
4278  upvalid[j] = col->sbupvalid;
4279  }
4280  }
4281 
4282  SCIPdebugMessage("performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4283 
4284  /* call LPI strong branching */
4285  if ( integral )
4286  retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4287  else
4288  retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4289 
4290  /* check return code for errors */
4291  if( retcode == SCIP_LPERROR )
4292  {
4293  *lperror = TRUE;
4294 
4295  for( j = 0; j < nsubcols; ++j )
4296  {
4297  SCIP_COL* col;
4298  int idx;
4299 
4300  col = subcols[j];
4301  idx = subidx[j];
4302 
4303  col->sbdown = SCIP_INVALID;
4304  col->sbup = SCIP_INVALID;
4305  col->sbdownvalid = FALSE;
4306  col->sbupvalid = FALSE;
4307  col->validsblp = -1;
4308  col->sbsolval = SCIP_INVALID;
4309  col->sblpobjval = SCIP_INVALID;
4310  col->sbnode = -1;
4311 
4312  down[idx] = col->sbdown;
4313  up[idx] = col->sbup;
4314  if( downvalid != NULL )
4315  downvalid[idx] = col->sbdownvalid;
4316  if( upvalid != NULL )
4317  upvalid[idx] = col->sbupvalid;
4318  }
4319  }
4320  else
4321  {
4322  SCIP_Real looseobjval;
4323 
4324  *lperror = FALSE;
4325  SCIP_CALL( retcode );
4326 
4327  looseobjval = getFiniteLooseObjval(lp, set, prob);
4328 
4329  for( j = 0; j < nsubcols; ++j )
4330  {
4331  SCIP_COL* col;
4332  int idx;
4333 
4334  col = subcols[j];
4335  idx = subidx[j];
4336 
4337  assert( col->sbdown < SCIP_INVALID);
4338  assert( col->sbup < SCIP_INVALID);
4339 
4340  col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4341  col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4342  col->sbdownvalid = sbdownvalid[j];
4343  col->sbupvalid = sbupvalid[j];
4344 
4345  down[idx] = col->sbdown;
4346  up[idx] = col->sbup;
4347  if( downvalid != NULL )
4348  downvalid[idx] = col->sbdownvalid;
4349  if( upvalid != NULL )
4350  upvalid[idx] = col->sbupvalid;
4351  }
4352 
4353  /* update strong branching statistics */
4354  if( iter == -1 )
4355  {
4356  /* calculate average iteration number */
4357  iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4358  : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4359  : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4360  : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4361  : 0;
4362  if( iter/2 >= itlim )
4363  iter = 2*itlim;
4364  }
4365  stat->nstrongbranchs += ncols;
4366  stat->nsblpiterations += iter;
4367  if( stat->nnodes == 1 )
4368  {
4369  stat->nrootstrongbranchs += ncols;
4370  stat->nrootsblpiterations += iter;
4371  }
4372  }
4373 
4374  SCIPsetFreeBufferArray(set, &sbupvalid);
4375  SCIPsetFreeBufferArray(set, &sbdownvalid);
4376  SCIPsetFreeBufferArray(set, &sbup);
4377  SCIPsetFreeBufferArray(set, &sbdown);
4378  SCIPsetFreeBufferArray(set, &primsols);
4379  SCIPsetFreeBufferArray(set, &lpipos);
4380  SCIPsetFreeBufferArray(set, &subidx);
4381  SCIPsetFreeBufferArray(set, &subcols);
4382 
4383  /* stop timing */
4384  SCIPclockStop(stat->strongbranchtime, set);
4385 
4386  return SCIP_OKAY;
4387 }
4388 
4389 /** gets last strong branching information available for a column variable;
4390  * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4391  * keep in mind, that the returned old values may have nothing to do with the current LP solution
4392  */
4394  SCIP_COL* col, /**< LP column */
4395  SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4396  SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4397  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4398  * otherwise, it can only be used as an estimate value */
4399  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4400  * otherwise, it can only be used as an estimate value */
4401  SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4402  SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4403  )
4404 {
4405  assert(col != NULL);
4406 
4407  if( down != NULL )
4408  *down = col->sbdown;
4409  if( up != NULL )
4410  *up = col->sbup;
4411  if( downvalid != NULL )
4412  *downvalid = col->sbdownvalid;
4413  if( upvalid != NULL )
4414  *upvalid = col->sbupvalid;
4415  if( solval != NULL )
4416  *solval = col->sbsolval;
4417  if( lpobjval != NULL )
4418  *lpobjval = col->sblpobjval;
4419 }
4420 
4421 /** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4422  * the LP where the strong branching on this column was applied;
4423  * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4424  */
4426  SCIP_COL* col, /**< LP column */
4427  SCIP_STAT* stat /**< dynamic problem statistics */
4428  )
4429 {
4430  assert(col != NULL);
4431  assert(stat != NULL);
4432 
4433  return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->lpcount - stat->nsbdivinglps - col->validsblp);
4434 }
4435 
4436 /** marks a column to be not removable from the LP in the current node because it became obsolete */
4438  SCIP_COL* col, /**< LP column */
4439  SCIP_STAT* stat /**< problem statistics */
4440  )
4441 {
4442  assert(col != NULL);
4443  assert(stat != NULL);
4444  assert(stat->nnodes > 0);
4445 
4446  /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4447  col->obsoletenode = stat->nnodes;
4448 }
4449 
4450 
4451 /*
4452  * Row methods
4453  */
4454 
4455 /** calculates row norms and min/maxidx from scratch, and checks for sorting */
4456 static
4458  SCIP_ROW* row, /**< LP row */
4459  SCIP_SET* set /**< global SCIP settings */
4460  )
4461 {
4462  int i;
4463 
4464  assert(row != NULL);
4465  assert(set != NULL);
4466 
4467  row->sqrnorm = 0.0;
4468  row->sumnorm = 0.0;
4469  row->objprod = 0.0;
4470  row->maxval = 0.0;
4471  row->nummaxval = 1;
4472  row->minval = SCIPsetInfinity(set);
4473  row->numminval = 1;
4474  row->minidx = INT_MAX;
4475  row->maxidx = INT_MIN;
4476  row->validminmaxidx = TRUE;
4477  row->lpcolssorted = TRUE;
4478  row->nonlpcolssorted = TRUE;
4479 
4480  /* check, if row is sorted
4481  * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4482  */
4483  for( i = 0; i < row->nlpcols; ++i )
4484  {
4485  assert(row->cols[i] != NULL);
4486  assert(!SCIPsetIsZero(set, row->vals[i]));
4487  assert(row->cols[i]->lppos >= 0);
4488  assert(row->linkpos[i] >= 0);
4489  assert(row->cols[i]->index == row->cols_index[i]);
4490 
4491  rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4492  if( i > 0 )
4493  {
4494  assert(row->cols[i-1]->index == row->cols_index[i-1]);
4495  row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4496  }
4497  }
4498  for( i = row->nlpcols; i < row->len; ++i )
4499  {
4500  assert(row->cols[i] != NULL);
4501  assert(!SCIPsetIsZero(set, row->vals[i]));
4502  assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4503  assert(row->cols[i]->index == row->cols_index[i]);
4504 
4505  rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4506  if( i > row->nlpcols )
4507  {
4508  assert(row->cols[i-1]->index == row->cols_index[i-1]);
4509  row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4510  }
4511  }
4512 }
4513 
4514 /** calculates min/maxval and min/maxidx from scratch */
4515 static
4517  SCIP_ROW* row, /**< LP row */
4518  SCIP_SET* set /**< global SCIP settings */
4519  )
4520 {
4521  SCIP_COL* col;
4522  SCIP_Real absval;
4523  int i;
4524 
4525  assert(row != NULL);
4526  assert(set != NULL);
4527 
4528  row->maxval = 0.0;
4529  row->nummaxval = 1;
4530  row->minval = SCIPsetInfinity(set);
4531  row->numminval = 1;
4532  row->minidx = INT_MAX;
4533  row->maxidx = INT_MIN;
4534  row->validminmaxidx = TRUE;
4535 
4536  /* calculate maxval, minval, minidx, and maxidx */
4537  for( i = 0; i < row->len; ++i )
4538  {
4539  col = row->cols[i];
4540  assert(col != NULL);
4541  assert(!SCIPsetIsZero(set, row->vals[i]));
4542 
4543  absval = REALABS(row->vals[i]);
4544  assert(!SCIPsetIsZero(set, absval));
4545 
4546  /* update min/maxidx */
4547  row->minidx = MIN(row->minidx, col->index);
4548  row->maxidx = MAX(row->maxidx, col->index);
4549 
4550  /* update maximal and minimal non-zero value */
4551  if( row->nummaxval > 0 )
4552  {
4553  if( SCIPsetIsGT(set, absval, row->maxval) )
4554  {
4555  row->maxval = absval;
4556  row->nummaxval = 1;
4557  }
4558  else if( SCIPsetIsGE(set, absval, row->maxval) )
4559  row->nummaxval++;
4560  }
4561  if( row->numminval > 0 )
4562  {
4563  if( SCIPsetIsLT(set, absval, row->minval) )
4564  {
4565  row->minval = absval;
4566  row->numminval = 1;
4567  }
4568  else if( SCIPsetIsLE(set, absval, row->minval) )
4569  row->numminval++;
4570  }
4571  }
4572 }
4573 
4574 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4575 static
4577  SCIP_Real val, /**< value that should be scaled to an integral value */
4578  SCIP_Real scalar, /**< scalar that should be tried */
4579  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4580  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4581  SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4582  )
4583 {
4584  SCIP_Real sval;
4585  SCIP_Real downval;
4586  SCIP_Real upval;
4587 
4588  assert(mindelta <= 0.0);
4589  assert(maxdelta >= 0.0);
4590 
4591  sval = val * scalar;
4592  downval = floor(sval);
4593  upval = ceil(sval);
4594 
4595  if( SCIPrelDiff(sval, downval) <= maxdelta )
4596  {
4597  if( intval != NULL )
4598  *intval = downval;
4599  return TRUE;
4600  }
4601  else if( SCIPrelDiff(sval, upval) >= mindelta )
4602  {
4603  if( intval != NULL )
4604  *intval = upval;
4605  return TRUE;
4606  }
4607 
4608  return FALSE;
4609 }
4610 
4611 /** scales row with given factor, and rounds coefficients to integers if close enough;
4612  * the constant is automatically moved to the sides;
4613  * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4614  */
4615 static
4617  SCIP_ROW* row, /**< LP row */
4618  BMS_BLKMEM* blkmem, /**< block memory */
4619  SCIP_SET* set, /**< global SCIP settings */
4620  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4621  SCIP_STAT* stat, /**< problem statistics */
4622  SCIP_LP* lp, /**< current LP data */
4623  SCIP_Real scaleval, /**< value to scale row with */
4624  SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4625  * if they are close to integral values? */
4626  SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4627  * upto which the integral is used instead of the scaled real coefficient */
4628  SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4629  * upto which the integral is used instead of the scaled real coefficient */
4630  )
4631 {
4632  SCIP_COL* col;
4633  SCIP_Real val;
4634  SCIP_Real newval;
4635  SCIP_Real intval;
4636  SCIP_Real mindelta;
4637  SCIP_Real maxdelta;
4638  SCIP_Real lb;
4639  SCIP_Real ub;
4640  SCIP_Bool mindeltainf;
4641  SCIP_Bool maxdeltainf;
4642  int oldlen;
4643  int c;
4644 
4645  assert(row != NULL);
4646  assert(row->len == 0 || row->cols != NULL);
4647  assert(row->len == 0 || row->vals != NULL);
4648  assert(SCIPsetIsPositive(set, scaleval));
4649  assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4650  assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4651 
4652  SCIPdebugMessage("scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4653 
4654  mindelta = 0.0;
4655  maxdelta = 0.0;
4656  mindeltainf = FALSE;
4657  maxdeltainf = FALSE;
4658  oldlen = row->len;
4659 
4660  /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4661  * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4662  * this rounding can lead to
4663  */
4664  row->integral = TRUE;
4665 
4666  c = 0;
4667  while( c < row->len )
4668  {
4669  col = row->cols[c];
4670  val = row->vals[c];
4671  assert(!SCIPsetIsZero(set, val));
4672 
4673  /* get local or global bounds for column, depending on the local or global feasibility of the row */
4674  if( row->local )
4675  {
4676  lb = col->lb;
4677  ub = col->ub;
4678  }
4679  else
4680  {
4681  lb = SCIPvarGetLbGlobal(col->var);
4682  ub = SCIPvarGetUbGlobal(col->var);
4683  }
4684 
4685  /* calculate scaled coefficient */
4686  newval = val * scaleval;
4687  if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
4688  && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
4689  {
4690  if( !SCIPsetIsEQ(set, intval, newval) )
4691  {
4692  if( intval < newval )
4693  {
4694  mindelta += (intval - newval)*ub;
4695  maxdelta += (intval - newval)*lb;
4696  mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
4697  maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
4698  }
4699  else
4700  {
4701  mindelta += (intval - newval)*lb;
4702  maxdelta += (intval - newval)*ub;
4703  mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
4704  maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
4705  }
4706  }
4707  newval = intval;
4708  }
4709 
4710  if( !SCIPsetIsEQ(set, val, newval) )
4711  {
4712  /* if column knows of the row, change the corresponding coefficient in the column */
4713  if( row->linkpos[c] >= 0 )
4714  {
4715  assert(col->rows[row->linkpos[c]] == row);
4716  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
4717  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
4718  }
4719 
4720  /* change the coefficient in the row, and update the norms and integrality status */
4721  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
4722 
4723  /* current coefficient has been deleted from the row because it was almost zero */
4724  if( oldlen != row->len )
4725  {
4726  assert(row->len == oldlen - 1);
4727  c--;
4728  oldlen = row->len;
4729  }
4730 
4731  }
4732  else
4733  row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
4734 
4735  ++c;
4736  }
4737 
4738  /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
4739  * to not destroy feasibility due to rounding
4740  */
4741  /**@todo ensure that returned cut does not have infinite lhs and rhs */
4742  if( !SCIPsetIsInfinity(set, -row->lhs) )
4743  {
4744  if( mindeltainf )
4745  newval = -SCIPsetInfinity(set);
4746  else
4747  {
4748  newval = (row->lhs - row->constant) * scaleval + mindelta;
4749  if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
4750  newval = SCIPsetSumCeil(set, newval);
4751  }
4752  SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
4753  }
4754  if( !SCIPsetIsInfinity(set, row->rhs) )
4755  {
4756  if( maxdeltainf )
4757  newval = SCIPsetInfinity(set);
4758  else
4759  {
4760  newval = (row->rhs - row->constant) * scaleval + maxdelta;
4761  if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
4762  newval = SCIPsetSumFloor(set, newval);
4763  }
4764  SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
4765  }
4766 
4767  /* clear the row constant */
4768  SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
4769 
4770  SCIPdebugMessage("scaled row <%s> (integral: %u)\n", row->name, row->integral);
4771  debugRowPrint(row);
4772 
4773 #ifdef SCIP_DEBUG
4774  /* check integrality status of row */
4775  for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
4776  {}
4777  assert(row->integral == (c == row->len));
4778 #endif
4779 
4780  /* invalid the activity */
4781  row->validactivitylp = -1;
4782 
4783  return SCIP_OKAY;
4784 }
4785 
4786 /** creates and captures an LP row */
4788  SCIP_ROW** row, /**< pointer to LP row data */
4789  BMS_BLKMEM* blkmem, /**< block memory */
4790  SCIP_SET* set, /**< global SCIP settings */
4791  SCIP_STAT* stat, /**< problem statistics */
4792  const char* name, /**< name of row */
4793  int len, /**< number of nonzeros in the row */
4794  SCIP_COL** cols, /**< array with columns of row entries */
4795  SCIP_Real* vals, /**< array with coefficients of row entries */
4796  SCIP_Real lhs, /**< left hand side of row */
4797  SCIP_Real rhs, /**< right hand side of row */
4798  SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
4799  void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
4800  SCIP_Bool local, /**< is row only valid locally? */
4801  SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
4802  SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
4803  )
4804 {
4805  assert(row != NULL);
4806  assert(blkmem != NULL);
4807  assert(stat != NULL);
4808  assert(len >= 0);
4809  assert(len == 0 || (cols != NULL && vals != NULL));
4810  /* note, that the assert tries to avoid numerical troubles in the LP solver.
4811  * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
4812  * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
4813  */
4814  assert(lhs <= rhs);
4815 
4816  SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
4817 
4818  (*row)->integral = TRUE;
4819  if( len > 0 )
4820  {
4821  SCIP_VAR* var;
4822  int i;
4823 
4824  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
4825  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
4826  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
4827  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
4828 
4829  for( i = 0; i < len; ++i )
4830  {
4831  assert(cols[i] != NULL);
4832  assert(!SCIPsetIsZero(set, vals[i]));
4833 
4834  var = cols[i]->var;
4835  (*row)->cols_index[i] = cols[i]->index;
4836  (*row)->linkpos[i] = -1;
4837  if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
4838  {
4839  (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
4840  (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
4841  }
4842  else
4843  {
4844  (*row)->integral = FALSE;
4845  }
4846  }
4847  }
4848  else
4849  {
4850  (*row)->cols = NULL;
4851  (*row)->cols_index = NULL;
4852  (*row)->vals = NULL;
4853  (*row)->linkpos = NULL;
4854  }
4855 
4856  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
4857  (*row)->constant = 0.0;
4858  (*row)->lhs = lhs;
4859  (*row)->rhs = rhs;
4860  (*row)->flushedlhs = -SCIPsetInfinity(set);
4861  (*row)->flushedrhs = SCIPsetInfinity(set);
4862  (*row)->sqrnorm = 0.0;
4863  (*row)->sumnorm = 0.0;
4864  (*row)->objprod = 0.0;
4865  (*row)->maxval = 0.0;
4866  (*row)->minval = SCIPsetInfinity(set);
4867  (*row)->dualsol = 0.0;
4868  (*row)->activity = SCIP_INVALID;
4869  (*row)->dualfarkas = 0.0;
4870  (*row)->pseudoactivity = SCIP_INVALID;
4871  (*row)->minactivity = SCIP_INVALID;
4872  (*row)->maxactivity = SCIP_INVALID;
4873  (*row)->origin = origin;
4874  (*row)->eventfilter = NULL;
4875  (*row)->index = stat->nrowidx++;
4876  (*row)->size = len;
4877  (*row)->len = len;
4878  (*row)->nlpcols = 0;
4879  (*row)->nunlinked = len;
4880  (*row)->nuses = 0;
4881  (*row)->lppos = -1;
4882  (*row)->lpipos = -1;
4883  (*row)->lpdepth = -1;
4884  (*row)->minidx = INT_MAX;
4885  (*row)->maxidx = INT_MIN;
4886  (*row)->nummaxval = 0;
4887  (*row)->numminval = 0;
4888  (*row)->validactivitylp = -1;
4889  (*row)->validpsactivitydomchg = -1;
4890  (*row)->validactivitybdsdomchg = -1;
4891  (*row)->age = 0;
4892  (*row)->rank = 0;
4893  (*row)->obsoletenode = -1;
4894  (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
4895  (*row)->lpcolssorted = TRUE;
4896  (*row)->nonlpcolssorted = (len <= 1);
4897  (*row)->delaysort = FALSE;
4898  (*row)->validminmaxidx = FALSE;
4899  (*row)->lhschanged = FALSE;
4900  (*row)->rhschanged = FALSE;
4901  (*row)->coefchanged = FALSE;
4902  (*row)->local = local;
4903  (*row)->modifiable = modifiable;
4904  (*row)->nlocks = 0;
4905  (*row)->origintype = origintype; /*lint !e641*/
4906  (*row)->removable = removable;
4907  (*row)->inglobalcutpool = FALSE;
4908  (*row)->storedsolvals = NULL;
4909 
4910  /* calculate row norms and min/maxidx, and check if row is sorted */
4911  rowCalcNorms(*row, set);
4912 
4913  /* capture the row */
4914  SCIProwCapture(*row);
4915 
4916  /* create event filter */
4917  SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
4918 
4919  return SCIP_OKAY;
4920 }
4921 
4922 /** frees an LP row */
4924  SCIP_ROW** row, /**< pointer to LP row */
4925  BMS_BLKMEM* blkmem, /**< block memory */
4926  SCIP_SET* set, /**< global SCIP settings */
4927  SCIP_LP* lp /**< current LP data */
4928  )
4929 {
4930  assert(blkmem != NULL);
4931  assert(row != NULL);
4932  assert(*row != NULL);
4933  assert((*row)->nuses == 0);
4934  assert((*row)->lppos == -1);
4935  assert((*row)->eventfilter != NULL);
4936 
4937  /* remove column indices from corresponding rows */
4938  SCIP_CALL( rowUnlink(*row, set, lp) );
4939 
4940  /* free event filter */
4941  SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
4942 
4943  BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
4944  BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
4945  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
4946  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
4947  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
4948  BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
4949  BMSfreeBlockMemory(blkmem, row);
4950 
4951  return SCIP_OKAY;
4952 }
4953 
4954 /** output row to file stream */
4956  SCIP_ROW* row, /**< LP row */
4957  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4958  FILE* file /**< output file (or NULL for standard output) */
4959  )
4960 {
4961  int i;
4962 
4963  assert(row != NULL);
4964 
4965  /* print row name */
4966  if( row->name != NULL && row->name[0] != '\0' )
4967  {
4968  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
4969  }
4970 
4971  /* print left hand side */
4972  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
4973 
4974  /* print coefficients */
4975  if( row->len == 0 )
4976  SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
4977  for( i = 0; i < row->len; ++i )
4978  {
4979  assert(row->cols[i] != NULL);
4980  assert(row->cols[i]->var != NULL);
4981  assert(SCIPvarGetName(row->cols[i]->var) != NULL);
4982  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
4983  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
4984  }
4985 
4986  /* print constant */
4987  if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
4988  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
4989 
4990  /* print right hand side */
4991  SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
4992 }
4993 
4994 /** increases usage counter of LP row */
4996  SCIP_ROW* row /**< LP row */
4997  )
4998 {
4999  assert(row != NULL);
5000  assert(row->nuses >= 0);
5001  assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5002 
5003  SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5004  row->nuses++;
5005 }
5006 
5007 /** decreases usage counter of LP row, and frees memory if necessary */
5009  SCIP_ROW** row, /**< pointer to LP row */
5010  BMS_BLKMEM* blkmem, /**< block memory */
5011  SCIP_SET* set, /**< global SCIP settings */
5012  SCIP_LP* lp /**< current LP data */
5013  )
5014 {
5015  assert(blkmem != NULL);
5016  assert(row != NULL);
5017  assert(*row != NULL);
5018  assert((*row)->nuses >= 1);
5019  assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5020 
5021  SCIPdebugMessage("release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5022  (*row)->nuses--;
5023  if( (*row)->nuses == 0 )
5024  {
5025  SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5026  }
5027 
5028  *row = NULL;
5029 
5030  return SCIP_OKAY;
5031 }
5032 
5033 /** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5035  SCIP_ROW* row /**< LP row */
5036  )
5037 {
5038  assert(row != NULL);
5039 
5040  /* check, if row is modifiable */
5041  if( !row->modifiable )
5042  {
5043  SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5044  row->nlocks++;
5045  }
5046 }
5047 
5048 /** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5050  SCIP_ROW* row /**< LP row */
5051  )
5052 {
5053  assert(row != NULL);
5054 
5055  /* check, if row is modifiable */
5056  if( !row->modifiable )
5057  {
5058  SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5059  assert(row->nlocks > 0);
5060  row->nlocks--;
5061  }
5062 }
5063 
5064 /** adds a previously non existing coefficient to an LP row */
5066  SCIP_ROW* row, /**< LP row */
5067  BMS_BLKMEM* blkmem, /**< block memory */
5068  SCIP_SET* set, /**< global SCIP settings */
5069  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5070  SCIP_LP* lp, /**< current LP data */
5071  SCIP_COL* col, /**< LP column */
5072  SCIP_Real val /**< value of coefficient */
5073  )
5074 {
5075  assert(lp != NULL);
5076  assert(!lp->diving || row->lppos == -1);
5077 
5078  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5079 
5080  checkLinks(lp);
5081 
5082  return SCIP_OKAY;
5083 }
5084 
5085 /** deletes coefficient from row */
5087  SCIP_ROW* row, /**< row to be changed */
5088  BMS_BLKMEM* blkmem, /**< block memory */
5089  SCIP_SET* set, /**< global SCIP settings */
5090  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5091  SCIP_LP* lp, /**< current LP data */
5092  SCIP_COL* col /**< coefficient to be deleted */
5093  )
5094 {
5095  int pos;
5096 
5097  assert(row != NULL);
5098  assert(!row->delaysort);
5099  assert(lp != NULL);
5100  assert(!lp->diving || row->lppos == -1);
5101  assert(col != NULL);
5102  assert(col->var != NULL);
5103 
5104  /* search the position of the column in the row's col vector */
5105  pos = rowSearchCoef(row, col);
5106  if( pos == -1 )
5107  {
5108  SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5109  return SCIP_INVALIDDATA;
5110  }
5111  assert(0 <= pos && pos < row->len);
5112  assert(row->cols[pos] == col);
5113  assert(row->cols_index[pos] == col->index);
5114 
5115  /* if column knows of the row, remove the row from the column's row vector */
5116  if( row->linkpos[pos] >= 0 )
5117  {
5118  assert(col->rows[row->linkpos[pos]] == row);
5119  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5120  SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5121  }
5122 
5123  /* delete the column from the row's col vector */
5124  SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5125 
5126  checkLinks(lp);
5127 
5128  return SCIP_OKAY;
5129 }
5130 
5131 /** changes or adds a coefficient to an LP row */
5133  SCIP_ROW* row, /**< LP row */
5134  BMS_BLKMEM* blkmem, /**< block memory */
5135  SCIP_SET* set, /**< global SCIP settings */
5136  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5137  SCIP_LP* lp, /**< current LP data */
5138  SCIP_COL* col, /**< LP column */
5139  SCIP_Real val /**< value of coefficient */
5140  )
5141 {
5142  int pos;
5143 
5144  assert(row != NULL);
5145  assert(!row->delaysort);
5146  assert(lp != NULL);
5147  assert(!lp->diving || row->lppos == -1);
5148  assert(col != NULL);
5149 
5150  /* search the position of the column in the row's col vector */
5151  pos = rowSearchCoef(row, col);
5152 
5153  /* check, if column already exists in the row's col vector */
5154  if( pos == -1 )
5155  {
5156  /* add previously not existing coefficient */
5157  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5158  }
5159  else
5160  {
5161  /* modify already existing coefficient */
5162  assert(0 <= pos && pos < row->len);
5163  assert(row->cols[pos] == col);
5164  assert(row->cols_index[pos] == col->index);
5165 
5166  /* if column knows of the row, change the corresponding coefficient in the column */
5167  if( row->linkpos[pos] >= 0 )
5168  {
5169  assert(col->rows[row->linkpos[pos]] == row);
5170  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5171  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5172  }
5173 
5174  /* change the coefficient in the row */
5175  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5176  }
5177 
5178  checkLinks(lp);
5179 
5180  return SCIP_OKAY;
5181 }
5182 
5183 /** increases value of an existing or non-existing coefficient in an LP row */
5185  SCIP_ROW* row, /**< LP row */
5186  BMS_BLKMEM* blkmem, /**< block memory */
5187  SCIP_SET* set, /**< global SCIP settings */
5188  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5189  SCIP_LP* lp, /**< current LP data */
5190  SCIP_COL* col, /**< LP column */
5191  SCIP_Real incval /**< value to add to the coefficient */
5192  )
5193 {
5194  int pos;
5195 
5196  assert(row != NULL);
5197  assert(lp != NULL);
5198  assert(!lp->diving || row->lppos == -1);
5199  assert(col != NULL);
5200 
5201  if( SCIPsetIsZero(set, incval) )
5202  return SCIP_OKAY;
5203 
5204  /* search the position of the column in the row's col vector */
5205  pos = rowSearchCoef(row, col);
5206 
5207  /* check, if column already exists in the row's col vector */
5208  if( pos == -1 )
5209  {
5210  /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5211  SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5212  }
5213  else
5214  {
5215  /* modify already existing coefficient */
5216  assert(0 <= pos && pos < row->len);
5217  assert(row->cols[pos] == col);
5218  assert(row->cols_index[pos] == col->index);
5219 
5220  /* if column knows of the row, change the corresponding coefficient in the column */
5221  if( row->linkpos[pos] >= 0 )
5222  {
5223  assert(col->rows[row->linkpos[pos]] == row);
5224  assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5225  SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5226  }
5227 
5228  /* change the coefficient in the row */
5229  SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5230  }
5231 
5232  checkLinks(lp);
5233 
5234  return SCIP_OKAY;
5235 }
5236 
5237 /** changes constant value of a row */
5239  SCIP_ROW* row, /**< LP row */
5240  BMS_BLKMEM* blkmem, /**< block memory */
5241  SCIP_SET* set, /**< global SCIP settings */
5242  SCIP_STAT* stat, /**< problem statistics */
5243  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5244  SCIP_LP* lp, /**< current LP data */
5245  SCIP_Real constant /**< new constant value */
5246  )
5247 {
5248  assert(row != NULL);
5249  assert(row->lhs <= row->rhs);
5250  assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5251  assert(stat != NULL);
5252  assert(lp != NULL);
5253  assert(!lp->diving || row->lppos == -1);
5254 
5255  if( !SCIPsetIsEQ(set, constant, row->constant) )
5256  {
5257  SCIP_Real oldconstant;
5258 
5259  if( row->validpsactivitydomchg == stat->domchgcount )
5260  {
5261  assert(row->pseudoactivity < SCIP_INVALID);
5262  row->pseudoactivity += constant - row->constant;
5263  }
5264  if( row->validactivitybdsdomchg == stat->domchgcount )
5265  {
5266  assert(row->minactivity < SCIP_INVALID);
5267  assert(row->maxactivity < SCIP_INVALID);
5268  row->minactivity += constant - row->constant;
5269  row->maxactivity += constant - row->constant;
5270  }
5271 
5272  if( !SCIPsetIsInfinity(set, -row->lhs) )
5273  {
5274  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5275  }
5276  if( !SCIPsetIsInfinity(set, row->rhs) )
5277  {
5278  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5279  }
5280 
5281  oldconstant = row->constant;
5282 
5283  row->constant = constant;
5284 
5285  /* issue row constant changed event */
5286  SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5287  }
5288 
5289  return SCIP_OKAY;
5290 }
5291 
5292 /** add constant value to a row */
5294  SCIP_ROW* row, /**< LP row */
5295  BMS_BLKMEM* blkmem, /**< block memory */
5296  SCIP_SET* set, /**< global SCIP settings */
5297  SCIP_STAT* stat, /**< problem statistics */
5298  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5299  SCIP_LP* lp, /**< current LP data */
5300  SCIP_Real addval /**< constant value to add to the row */
5301  )
5302 {
5303  assert(row != NULL);
5304  assert(row->lhs <= row->rhs);
5305  assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5306  assert(stat != NULL);
5307  assert(lp != NULL);
5308  assert(!lp->diving || row->lppos == -1);
5309 
5310  if( !SCIPsetIsZero(set, addval) )
5311  {
5312  SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5313  }
5314 
5315  return SCIP_OKAY;
5316 }
5317 
5318 /** changes left hand side of LP row */
5320  SCIP_ROW* row, /**< LP row */
5321  BMS_BLKMEM* blkmem, /**< block memory */
5322  SCIP_SET* set, /**< global SCIP settings */
5323  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5324  SCIP_LP* lp, /**< current LP data */
5325  SCIP_Real lhs /**< new left hand side */
5326  )
5327 {
5328  assert(row != NULL);
5329  assert(lp != NULL);
5330 
5331  if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5332  {
5333  SCIP_Real oldlhs;
5334 
5335  oldlhs = row->lhs;
5336 
5337  row->lhs = lhs;
5338  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5339 
5340  if( !lp->diving )
5341  {
5342  /* issue row side changed event */
5343  SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5344  }
5345  }
5346 
5347  return SCIP_OKAY;
5348 }
5349 
5350 /** changes right hand side of LP row */
5352  SCIP_ROW* row, /**< LP row */
5353  BMS_BLKMEM* blkmem, /**< block memory */
5354  SCIP_SET* set, /**< global SCIP settings */
5355  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5356  SCIP_LP* lp, /**< current LP data */
5357  SCIP_Real rhs /**< new right hand side */
5358  )
5359 {
5360  assert(row != NULL);
5361  assert(lp != NULL);
5362 
5363  if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5364  {
5365  SCIP_Real oldrhs;
5366 
5367  oldrhs = row->rhs;
5368 
5369  row->rhs = rhs;
5370  SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5371 
5372  if( !lp->diving )
5373  {
5374  /* issue row side changed event */
5375  SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5376  }
5377  }
5378 
5379  return SCIP_OKAY;
5380 }
5381 
5382 /** changes the local flag of LP row */
5384  SCIP_ROW* row, /**< LP row */
5385  SCIP_Bool local /**< new value for local flag */
5386  )
5387 {
5388  assert(row != NULL);
5389 
5390  row->local = local;
5391 
5392  return SCIP_OKAY;
5393 }
5394 
5395 /** additional scalars that are tried in integrality scaling */
5396 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5397 static const int nscalars = 9;
5398 
5399 /** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5401  SCIP_ROW* row, /**< LP row */
5402  SCIP_SET* set, /**< global SCIP settings */
5403  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5404  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5405  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5406  SCIP_Real maxscale, /**< maximal allowed scalar */
5407  SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5408  SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5409  SCIP_Bool* success /**< stores whether returned value is valid */
5410  )
5411 {
5412 #ifndef NDEBUG
5413  SCIP_COL* col;
5414 #endif
5415  SCIP_Longint gcd;
5416  SCIP_Longint scm;
5417  SCIP_Longint nominator;
5418  SCIP_Longint denominator;
5419  SCIP_Real val;
5420  SCIP_Real absval;
5421  SCIP_Real minval;
5422  SCIP_Real scaleval;
5423  SCIP_Real twomultval;
5424  SCIP_Bool scalable;
5425  SCIP_Bool twomult;
5426  SCIP_Bool rational;
5427  int c;
5428  int s;
5429 
5430  /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5431  assert(row != NULL);
5432  assert(row->len == 0 || row->cols != NULL);
5433  assert(row->len == 0 || row->cols_index != NULL);
5434  assert(row->len == 0 || row->vals != NULL);
5435  assert(maxdnom >= 1);
5436  assert(mindelta < 0.0);
5437  assert(maxdelta > 0.0);
5438  assert(success != NULL);
5439 
5440  SCIPdebugMessage("trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5441  SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5442 
5443  if( intscalar != NULL )
5444  *intscalar = SCIP_INVALID;
5445  *success = FALSE;
5446 
5447  /* get minimal absolute non-zero value */
5448  minval = SCIP_REAL_MAX;
5449  for( c = 0; c < row->len; ++c )
5450  {
5451 #ifndef NDEBUG
5452  col = row->cols[c];
5453  assert(col != NULL);
5454  assert(col->var != NULL);
5455  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
5456  assert(SCIPvarGetCol(col->var) == col);
5457 #endif
5458  val = row->vals[c];
5459  assert(!SCIPsetIsZero(set, val));
5460 
5461  if( val < mindelta || val > maxdelta )
5462  {
5463  absval = REALABS(val);
5464  minval = MIN(minval, absval);
5465  }
5466  }
5467  if( minval == SCIP_REAL_MAX )
5468  {
5469  /* all coefficients are zero (inside tolerances) */
5470  if( intscalar != NULL )
5471  *intscalar = 1.0;
5472  *success = TRUE;
5473  SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
5474 
5475  return SCIP_OKAY;
5476  }
5477  assert(minval > MIN(-mindelta, maxdelta));
5478  assert(SCIPsetIsPositive(set, minval));
5479  assert(!SCIPsetIsInfinity(set, minval));
5480 
5481  /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5482  * and a power of 2
5483  */
5484  scaleval = 1.0/minval;
5485  scalable = (scaleval <= maxscale);
5486  for( c = 0; c < row->len && scalable; ++c )
5487  {
5488  /* don't look at continuous variables, if we don't have to */
5489  if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5490  continue;
5491 
5492  /* check, if the coefficient can be scaled with a simple scalar */
5493  val = row->vals[c];
5494  absval = REALABS(val);
5495  while( scaleval <= maxscale
5496  && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5497  {
5498  for( s = 0; s < nscalars; ++s )
5499  {
5500  if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5501  {
5502  scaleval *= scalars[s];
5503  break;
5504  }
5505  }
5506  if( s >= nscalars )
5507  scaleval *= 2.0;
5508  }
5509  scalable = (scaleval <= maxscale);
5510  SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
5511  val, scaleval, val*scaleval, scalable);
5512  }
5513  if( scalable )
5514  {
5515  /* make row coefficients integral by dividing them by the smallest coefficient
5516  * (and multiplying them with a power of 2)
5517  */
5518  assert(scaleval <= maxscale);
5519  if( intscalar != NULL )
5520  *intscalar = scaleval;
5521  *success = TRUE;
5522  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5523 
5524  return SCIP_OKAY;
5525  }
5526 
5527  /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5528  twomultval = 1.0;
5529  twomult = (twomultval <= maxscale);
5530  for( c = 0; c < row->len && twomult; ++c )
5531  {
5532  /* don't look at continuous variables, if we don't have to */
5533  if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5534  continue;
5535 
5536  /* check, if the coefficient can be scaled with a simple scalar */
5537  val = row->vals[c];
5538  absval = REALABS(val);
5539  while( twomultval <= maxscale
5540  && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5541  {
5542  for( s = 0; s < nscalars; ++s )
5543  {
5544  if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5545  {
5546  twomultval *= scalars[s];
5547  break;
5548  }
5549  }
5550  if( s >= nscalars )
5551  twomultval *= 2.0;
5552  }
5553  twomult = (twomultval <= maxscale);
5554  SCIPdebugMessage(" -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5555  val, twomultval, val*twomultval, twomult);
5556  }
5557  if( twomult )
5558  {
5559  /* make row coefficients integral by multiplying them with a power of 2 */
5560  assert(twomultval <= maxscale);
5561  if( intscalar != NULL )
5562  *intscalar = twomultval;
5563  *success = TRUE;
5564  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5565 
5566  return SCIP_OKAY;
5567  }
5568 
5569  /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5570  * and the smallest common multiple of the denominators
5571  */
5572  gcd = 1;
5573  scm = 1;
5574  rational = (maxdnom > 1);
5575 
5576  /* first coefficient (to initialize gcd) */
5577  for( c = 0; c < row->len && rational; ++c )
5578  {
5579  if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5580  {
5581  val = row->vals[c];
5582  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5583  if( rational && nominator != 0 )
5584  {
5585  assert(denominator > 0);
5586  gcd = ABS(nominator);
5587  scm = denominator;
5588  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5589  SCIPdebugMessage(" -> first rational: val: %g == %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT", gcd=%"SCIP_LONGINT_FORMAT", scm=%"SCIP_LONGINT_FORMAT", rational=%u\n",
5590  val, nominator, denominator, gcd, scm, rational);
5591  break;
5592  }
5593  }
5594  }
5595 
5596  /* remaining coefficients */
5597  for( ++c; c < row->len && rational; ++c )
5598  {
5599  if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5600  {
5601  val = row->vals[c];
5602  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5603  if( rational && nominator != 0 )
5604  {
5605  assert(denominator > 0);
5606  gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5607  scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5608  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5609  SCIPdebugMessage(" -> next rational : val: %g == %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT", gcd=%"SCIP_LONGINT_FORMAT", scm=%"SCIP_LONGINT_FORMAT", rational=%u\n",
5610  val, nominator, denominator, gcd, scm, rational);
5611  }
5612  }
5613  }
5614 
5615  if( rational )
5616  {
5617  /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5618  assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5619  if( intscalar != NULL )
5620  *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5621  *success = TRUE;
5622  SCIPdebugMessage(" -> integrality can be achieved by scaling with %g (rational:%"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT")\n",
5623  (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5624  }
5625  else
5626  {
5627  assert(!(*success));
5628  SCIPdebugMessage(" -> rationalizing failed: gcd=%"SCIP_LONGINT_FORMAT", scm=%"SCIP_LONGINT_FORMAT", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5629  }
5630 
5631  return SCIP_OKAY;
5632 }
5633 
5634 /** tries to scale row, s.t. all coefficients become integral */
5636  SCIP_ROW* row, /**< LP row */
5637  BMS_BLKMEM* blkmem, /**< block memory */
5638  SCIP_SET* set, /**< global SCIP settings */
5639  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5640  SCIP_STAT* stat, /**< problem statistics */
5641  SCIP_LP* lp, /**< current LP data */
5642  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5643  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5644  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5645  SCIP_Real maxscale, /**< maximal value to scale row with */
5646  SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5647  SCIP_Bool* success /**< stores whether row could be made rational */
5648  )
5649 {
5650  SCIP_Real intscalar;
5651 
5652  assert(success != NULL);
5653 
5654  /* calculate scalar to make coefficients integral */
5655  SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
5656  &intscalar, success) );
5657 
5658  if( *success )
5659  {
5660  /* scale the row */
5661  SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
5662  }
5663 
5664  return SCIP_OKAY;
5665 }
5666 
5667 /** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
5668  * higher ones
5669  */
5671  SCIP_ROW* row /**< row to be sorted */
5672  )
5673 {
5674  assert(row != NULL);
5675 
5676  /* sort LP columns */
5677  rowSortLP(row);
5678 
5679  /* sort non-LP columns */
5680  rowSortNonLP(row);
5681 
5682 #ifdef SCIP_MORE_DEBUG
5683  /* check the sorting */
5684  {
5685  int c;
5686  if( !row->delaysort )
5687  {
5688  for( c = 1; c < row->nlpcols; ++c )
5689  assert(row->cols[c]->index > row->cols[c-1]->index);
5690  for( c = row->nlpcols + 1; c < row->len; ++c )
5691  assert(row->cols[c]->index > row->cols[c-1]->index);
5692  }
5693  }
5694 #endif
5695 }
5696 
5697 /** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
5698  * zero entries from row
5699  * the row must not be linked to the columns; otherwise, we would need to update the columns as
5700  * well, which is too expensive
5701  */
5702 static
5704  SCIP_ROW* row, /**< row to be sorted */
5705  SCIP_SET* set /**< global SCIP settings */
5706  )
5707 {
5708  assert(row != NULL);
5709  assert(!row->delaysort);
5710  assert(row->nunlinked == row->len);
5711  assert(row->nlpcols == 0);
5712 
5713  SCIPdebugMessage("merging row <%s>\n", row->name);
5714 
5715  /* do nothing on empty rows; if row is sorted, nothing has to be done */
5716  if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
5717  {
5718  SCIP_COL** cols;
5719  int* cols_index;
5720  SCIP_Real* vals;
5721  int s;
5722  int t;
5723 
5724  /* make sure, the row is sorted */
5725  SCIProwSort(row);
5726  assert(row->lpcolssorted);
5727  assert(row->nonlpcolssorted);
5728 
5729  /* merge equal columns, thereby recalculating whether the row's activity is always integral */
5730  cols = row->cols;
5731  cols_index = row->cols_index;
5732  vals = row->vals;
5733  assert(cols != NULL);
5734  assert(cols_index != NULL);
5735  assert(vals != NULL);
5736 
5737  t = 0;
5738  row->integral = TRUE;
5739  assert(!SCIPsetIsZero(set, vals[0]));
5740  assert(row->linkpos[0] == -1);
5741 
5742  for( s = 1; s < row->len; ++s )
5743  {
5744  assert(!SCIPsetIsZero(set, vals[s]));
5745  assert(row->linkpos[s] == -1);
5746 
5747  if( cols[s] == cols[t] )
5748  {
5749  /* merge entries with equal column */
5750  vals[t] += vals[s];
5751  }
5752  else
5753  {
5754  /* go to the next entry, overwriting current entry if coefficient is zero */
5755  if( !SCIPsetIsZero(set, vals[t]) )
5756  {
5757  /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
5758  vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
5759 
5760  row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
5761  t++;
5762  }
5763  cols[t] = cols[s];
5764  cols_index[t] = cols_index[s];
5765  vals[t] = vals[s];
5766  }
5767  }
5768  if( !SCIPsetIsZero(set, vals[t]) )
5769  {
5770  row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
5771  t++;
5772  }
5773  assert(s == row->len);
5774  assert(t <= row->len);
5775 
5776  row->len = t;
5777  row->nunlinked = t;
5778 
5779  /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
5780  if( t < s )
5781  rowCalcNorms(row, set);
5782  }
5783 
5784 #ifndef NDEBUG
5785  /* check for double entries */
5786  {
5787  int i;
5788  int j;
5789 
5790  for( i = 0; i < row->len; ++i )
5791  {
5792  assert(row->cols[i] != NULL);
5793  assert(row->cols[i]->index == row->cols_index[i]);
5794  for( j = i+1; j < row->len; ++j )
5795  assert(row->cols[i] != row->cols[j]);
5796  }
5797  }
5798 #endif
5799 }
5800 
5801 /** enables delaying of row sorting */
5803  SCIP_ROW* row /**< LP row */
5804  )
5805 {
5806  assert(row != NULL);
5807  assert(!row->delaysort);
5808 
5809  row->delaysort = TRUE;
5810 }
5811 
5812 /** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
5814  SCIP_ROW* row, /**< LP row */
5815  SCIP_SET* set /**< global SCIP settings */
5816  )
5817 {
5818  assert(row != NULL);
5819  assert(row->delaysort);
5820 
5821  row->delaysort = FALSE;
5822  rowMerge(row, set);
5823 }
5824 
5825 /** recalculates the current activity of a row */
5827  SCIP_ROW* row, /**< LP row */
5828  SCIP_STAT* stat /**< problem statistics */
5829  )
5830 {
5831  SCIP_COL* col;
5832  int c;
5833 
5834  assert(row != NULL);
5835  assert(stat != NULL);
5836 
5837  row->activity = row->constant;
5838  for( c = 0; c < row->nlpcols; ++c )
5839  {
5840  col = row->cols[c];
5841  assert(col != NULL);
5842  assert(col->primsol < SCIP_INVALID);
5843  assert(col->lppos >= 0);
5844  assert(row->linkpos[c] >= 0);
5845  row->activity += row->vals[c] * col->primsol;
5846  }
5847 
5848  if( row->nunlinked > 0 )
5849  {
5850  for( c = row->nlpcols; c < row->len; ++c )
5851  {
5852  col = row->cols[c];
5853  assert(col != NULL);
5854  assert(col->lppos >= 0 || col->primsol == 0.0);
5855  assert(col->lppos == -1 || row->linkpos[c] == -1);
5856  if( col->lppos >= 0 )
5857  row->activity += row->vals[c] * col->primsol;
5858  }
5859  }
5860 #ifndef NDEBUG
5861  else
5862  {
5863  for( c = row->nlpcols; c < row->len; ++c )
5864  {
5865  col = row->cols[c];
5866  assert(col != NULL);
5867  assert(col->primsol == 0.0);
5868  assert(col->lppos == -1);
5869  assert(row->linkpos[c] >= 0);
5870  }
5871  }
5872 #endif
5873 
5874  row->validactivitylp = stat->lpcount;
5875 }
5876 
5877 /** returns the activity of a row in the current LP solution */
5879  SCIP_ROW* row, /**< LP row */
5880  SCIP_SET* set, /**< global SCIP settings */
5881  SCIP_STAT* stat, /**< problem statistics */
5882  SCIP_LP* lp /**< current LP data */
5883  )
5884 {
5885  SCIP_Real inf;
5886  SCIP_Real activity;
5887 
5888  assert(row != NULL);
5889  assert(stat != NULL);
5890  assert(lp != NULL);
5891  assert(row->validactivitylp <= stat->lpcount);
5892  assert(lp->validsollp == stat->lpcount);
5893 
5894  if( row->validactivitylp != stat->lpcount )
5895  SCIProwRecalcLPActivity(row, stat);
5896  assert(row->validactivitylp == stat->lpcount);
5897  assert(row->activity < SCIP_INVALID);
5898 
5899  activity = row->activity;
5900  inf = SCIPsetInfinity(set);
5901  activity = MAX(activity, -inf);
5902  activity = MIN(activity, +inf);
5903 
5904  return activity;
5905 }
5906 
5907 /** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
5909  SCIP_ROW* row, /**< LP row */
5910  SCIP_SET* set, /**< global SCIP settings */
5911  SCIP_STAT* stat, /**< problem statistics */
5912  SCIP_LP* lp /**< current LP data */
5913  )
5914 {
5915  SCIP_Real activity;
5916 
5917  assert(row != NULL);
5918 
5919  activity = SCIProwGetLPActivity(row, set, stat, lp);
5920 
5921  return MIN(row->rhs - activity, activity - row->lhs);
5922 }
5923 
5924 /** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
5925  *
5926  * @todo Implement calculation of activities similar to LPs.
5927  */
5929  SCIP_ROW* row, /**< LP row */
5930  SCIP_SET* set, /**< global SCIP settings */
5931  SCIP_STAT* stat /**< problem statistics */
5932  )
5933 {
5934  SCIP_Real inf;
5935  SCIP_Real activity;
5936  SCIP_COL* col;
5937  int c;
5938 
5939  assert( row != NULL );
5940  assert( stat != NULL );
5941 
5942  activity = row->constant;
5943  for (c = 0; c < row->nlpcols; ++c)
5944  {
5945  col = row->cols[c];
5946  assert( col != NULL );
5947  assert( col->lppos >= 0 );
5948  assert( col->var != NULL );
5949  assert( row->linkpos[c] >= 0 );
5950  activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
5951  }
5952 
5953  if ( row->nunlinked > 0 )
5954  {
5955  for (c = row->nlpcols; c < row->len; ++c)
5956  {
5957  col = row->cols[c];
5958  assert( col != NULL );
5959  assert( col->lppos == -1 || row->linkpos[c] == -1 );
5960  if ( col->lppos >= 0 )
5961  {
5962  assert( col->var != NULL );
5963  activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
5964  }
5965  }
5966  }
5967 #ifndef NDEBUG
5968  else
5969  {
5970  for (c = row->nlpcols; c < row->len; ++c)
5971  {
5972  col = row->cols[c];
5973  assert( col != NULL );
5974  assert( col->lppos == -1 );
5975  assert( row->linkpos[c] >= 0 );
5976  }
5977  }
5978 #endif
5979  inf = SCIPsetInfinity(set);
5980  activity = MAX(activity, -inf);
5981  activity = MIN(activity, +inf);
5982 
5983  return MIN(row->rhs - activity, activity - row->lhs);
5984 }
5985 
5986 /** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
5987  *
5988  * @todo Implement calculation of activities similar to LPs.
5989  */
5991  SCIP_ROW* row, /**< LP row */
5992  SCIP_SET* set, /**< global SCIP settings */
5993  SCIP_STAT* stat /**< problem statistics */
5994  )
5995 {
5996  SCIP_Real inf;
5997  SCIP_Real activity;
5998  SCIP_COL* col;
5999  int c;
6000 
6001  assert( row != NULL );
6002  assert( stat != NULL );
6003 
6004  activity = row->constant;
6005  for (c = 0; c < row->nlpcols; ++c)
6006  {
6007  col = row->cols[c];
6008  assert( col != NULL );
6009  assert( col->lppos >= 0 );
6010  assert( col->var != NULL );
6011  assert( row->linkpos[c] >= 0 );
6012  activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6013  }
6014 
6015  if ( row->nunlinked > 0 )
6016  {
6017  for (c = row->nlpcols; c < row->len; ++c)
6018  {
6019  col = row->cols[c];
6020  assert( col != NULL );
6021  assert( col->lppos == -1 || row->linkpos[c] == -1 );
6022  if ( col->lppos >= 0 )
6023  {
6024  assert( col->var != NULL );
6025  activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6026  }
6027  }
6028  }
6029 #ifndef NDEBUG
6030  else
6031  {
6032  for (c = row->nlpcols; c < row->len; ++c)
6033  {
6034  col = row->cols[c];
6035  assert( col != NULL );
6036  assert( col->lppos == -1 );
6037  assert( row->linkpos[c] >= 0 );
6038  }
6039  }
6040 #endif
6041  inf = SCIPsetInfinity(set);
6042  activity = MAX(activity, -inf);
6043  activity = MIN(activity, +inf);
6044 
6045  return MIN(row->rhs - activity, activity - row->lhs);
6046 }
6047 
6048 /** calculates the current pseudo activity of a row */
6050  SCIP_ROW* row, /**< row data */
6051  SCIP_STAT* stat /**< problem statistics */
6052  )
6053 {
6054  SCIP_COL* col;
6055  int i;
6056 
6057  assert(row != NULL);
6058  assert(stat != NULL);
6059 
6060  row->pseudoactivity = row->constant;
6061  for( i = 0; i < row->len; ++i )
6062  {
6063  col = row->cols[i];
6064  assert(col != NULL);
6065  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6066  assert(col->var != NULL);
6067  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
6068 
6069  row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6070  }
6071  row->validpsactivitydomchg = stat->domchgcount;
6072  assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6073 }
6074 
6075 /** returns the pseudo activity of a row in the current pseudo solution */
6077  SCIP_ROW* row, /**< LP row */
6078  SCIP_SET* set, /**< global SCIP settings */
6079  SCIP_STAT* stat /**< problem statistics */
6080  )
6081 {
6082  SCIP_Real inf;
6083  SCIP_Real activity;
6084 
6085  assert(row != NULL);
6086  assert(stat != NULL);
6087  assert(row->validpsactivitydomchg <= stat->domchgcount);
6088 
6089  /* check, if pseudo activity has to be calculated */
6090  if( row->validpsactivitydomchg != stat->domchgcount )
6091  SCIProwRecalcPseudoActivity(row, stat);
6092  assert(row->validpsactivitydomchg == stat->domchgcount);
6093  assert(row->pseudoactivity < SCIP_INVALID);
6094 
6095  activity = row->pseudoactivity;
6096  inf = SCIPsetInfinity(set);
6097  activity = MAX(activity, -inf);
6098  activity = MIN(activity, +inf);
6099 
6100  return activity;
6101 }
6102 
6103 /** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6105  SCIP_ROW* row, /**< LP row */
6106  SCIP_SET* set, /**< global SCIP settings */
6107  SCIP_STAT* stat /**< problem statistics */
6108  )
6109 {
6110  SCIP_Real pseudoactivity;
6111 
6112  assert(row != NULL);
6113 
6114  pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6115 
6116  return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6117 }
6118 
6119 /** returns the activity of a row for a given solution */
6121  SCIP_ROW* row, /**< LP row */
6122  SCIP_SET* set, /**< global SCIP settings */
6123  SCIP_STAT* stat, /**< problem statistics data */
6124  SCIP_SOL* sol /**< primal CIP solution */
6125  )
6126 {
6127  SCIP_COL* col;
6128  SCIP_Real inf;
6129  SCIP_Real activity;
6130  SCIP_Real solval;
6131  int i;
6132 
6133  assert(row != NULL);
6134 
6135  activity = row->constant;
6136  for( i = 0; i < row->len; ++i )
6137  {
6138  col = row->cols[i];
6139  assert(col != NULL);
6140  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6141  solval = SCIPsolGetVal(sol, set, stat, col->var);
6142  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6143  {
6144  if( SCIPsetIsInfinity(set, -row->lhs) )
6145  solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6146  else if( SCIPsetIsInfinity(set, row->rhs) )
6147  solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6148  else
6149  solval = (col->lb + col->ub)/2.0;
6150  }
6151  activity += row->vals[i] * solval;
6152  }
6153 
6154  inf = SCIPsetInfinity(set);
6155  activity = MAX(activity, -inf);
6156  activity = MIN(activity, +inf);
6157 
6158  return activity;
6159 }
6160 
6161 /** returns the feasibility of a row for the given solution */
6163  SCIP_ROW* row, /**< LP row */
6164  SCIP_SET* set, /**< global SCIP settings */
6165  SCIP_STAT* stat, /**< problem statistics data */
6166  SCIP_SOL* sol /**< primal CIP solution */
6167  )
6168 {
6169  SCIP_Real activity;
6170 
6171  assert(row != NULL);
6172 
6173  activity = SCIProwGetSolActivity(row, set, stat, sol);
6174 
6175  return MIN(row->rhs - activity, activity - row->lhs);
6176 }
6177 
6178 /** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6179 static
6181  SCIP_ROW* row, /**< row data */
6182  SCIP_SET* set, /**< global SCIP settings */
6183  SCIP_STAT* stat /**< problem statistics data */
6184  )
6185 {
6186  SCIP_COL* col;
6187  SCIP_Real val;
6188  SCIP_Bool mininfinite;
6189  SCIP_Bool maxinfinite;
6190  int i;
6191 
6192  assert(row != NULL);
6193  assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6194  assert(stat != NULL);
6195 
6196  /* calculate activity bounds */
6197  mininfinite = FALSE;
6198  maxinfinite = FALSE;
6199  row->minactivity = row->constant;
6200  row->maxactivity = row->constant;
6201  for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6202  {
6203  col = row->cols[i];
6204  assert(col != NULL);
6205  assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6206  val = row->vals[i];
6207  if( val >= 0.0 )
6208  {
6209  mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6210  maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6211  if( !mininfinite )
6212  row->minactivity += val * col->lb;
6213  if( !maxinfinite )
6214  row->maxactivity += val * col->ub;
6215  }
6216  else
6217  {
6218  mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6219  maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6220  if( !mininfinite )
6221  row->minactivity += val * col->ub;
6222  if( !maxinfinite )
6223  row->maxactivity += val * col->lb;
6224  }
6225  }
6226 
6227  if( mininfinite )
6228  row->minactivity = -SCIPsetInfinity(set);
6229  if( maxinfinite )
6230  row->maxactivity = SCIPsetInfinity(set);
6231  row->validactivitybdsdomchg = stat->domchgcount;
6232 
6233  assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIP_DEFAULT_SUMEPSILON
6235  assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIP_DEFAULT_SUMEPSILON
6237 }
6238 
6239 /** returns the minimal activity of a row w.r.t. the columns' bounds */
6241  SCIP_ROW* row, /**< LP row */
6242  SCIP_SET* set, /**< global SCIP settings */
6243  SCIP_STAT* stat /**< problem statistics data */
6244  )
6245 {
6246  assert(row != NULL);
6247  assert(stat != NULL);
6248  assert(row->validactivitybdsdomchg <= stat->domchgcount);
6249 
6250  /* check, if activity bounds has to be calculated */
6251  if( row->validactivitybdsdomchg != stat->domchgcount )
6252  rowCalcActivityBounds(row, set, stat);
6253  assert(row->validactivitybdsdomchg == stat->domchgcount);
6254  assert(row->minactivity < SCIP_INVALID);
6255  assert(row->maxactivity < SCIP_INVALID);
6256 
6257  return row->minactivity;
6258 }
6259 
6260 /** returns the maximal activity of a row w.r.t. the columns' bounds */
6262  SCIP_ROW* row, /**< LP row */
6263  SCIP_SET* set, /**< global SCIP settings */
6264  SCIP_STAT* stat /**< problem statistics data */
6265  )
6266 {
6267  assert(row != NULL);
6268  assert(stat != NULL);
6269  assert(row->validactivitybdsdomchg <= stat->domchgcount);
6270 
6271  /* check, if activity bounds has to be calculated */
6272  if( row->validactivitybdsdomchg != stat->domchgcount )
6273  rowCalcActivityBounds(row, set, stat);
6274  assert(row->validactivitybdsdomchg == stat->domchgcount);
6275  assert(row->minactivity < SCIP_INVALID);
6276  assert(row->maxactivity < SCIP_INVALID);
6277 
6278  return row->maxactivity;
6279 }
6280 
6281 /** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6283  SCIP_ROW* row, /**< LP row */
6284  SCIP_SET* set, /**< global SCIP settings */
6285  SCIP_STAT* stat /**< problem statistics data */
6286  )
6287 {
6288  assert(row != NULL);
6289 
6290  if( row->modifiable )
6291  return FALSE;
6292  if( !SCIPsetIsInfinity(set, -row->lhs) )
6293  {
6294  SCIP_Real minactivity;
6295 
6296  minactivity = SCIProwGetMinActivity(row, set, stat);
6297  if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6298  return FALSE;
6299  }
6300  if( !SCIPsetIsInfinity(set, row->rhs) )
6301  {
6302  SCIP_Real maxactivity;
6303 
6304  maxactivity = SCIProwGetMaxActivity(row, set, stat);
6305  if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6306  return FALSE;
6307  }
6308 
6309  return TRUE;
6310 }
6311 
6312 /** gets maximal absolute value of row vector coefficients */
6314  SCIP_ROW* row, /**< LP row */
6315  SCIP_SET* set /**< global SCIP settings */
6316  )
6317 {
6318  assert(row != NULL);
6319 
6320  if( row->nummaxval == 0 )
6321  rowCalcIdxsAndVals(row, set);
6322  assert(row->nummaxval > 0);
6323  assert(row->maxval >= 0.0 || row->len == 0);
6324 
6325  return row->maxval;
6326 }
6327 
6328 /** gets minimal absolute value of row vector's non-zero coefficients */
6330  SCIP_ROW* row, /**< LP row */
6331  SCIP_SET* set /**< global SCIP settings */
6332  )
6333 {
6334  assert(row != NULL);
6335 
6336  if( row->numminval == 0 )
6337  rowCalcIdxsAndVals(row, set);
6338  assert(row->numminval >= 0);
6339  assert(row->minval >= 0.0 || row->len == 0);
6340 
6341  return row->minval;
6342 }
6343 
6344 /** gets maximal column index of row entries */
6346  SCIP_ROW* row, /**< LP row */
6347  SCIP_SET* set /**< global SCIP settings */
6348  )
6349 {
6350  assert(row != NULL);
6351 
6352  if( row->validminmaxidx == 0 )
6353  rowCalcIdxsAndVals(row, set);
6354  assert(row->maxidx >= 0 || row->len == 0);
6355  assert(row->validminmaxidx);
6356 
6357  return row->maxidx;
6358 }
6359 
6360 /** gets minimal column index of row entries */
6362  SCIP_ROW* row, /**< LP row */
6363  SCIP_SET* set /**< global SCIP settings */
6364  )
6365 {
6366  assert(row != NULL);
6367 
6368  if( row->validminmaxidx == 0 )
6369  rowCalcIdxsAndVals(row, set);
6370  assert(row->minidx >= 0 || row->len == 0);
6371  assert(row->validminmaxidx);
6372 
6373  return row->minidx;
6374 }
6375 
6376 /** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6378  SCIP_ROW* row, /**< LP row */
6379  SCIP_SET* set, /**< global SCIP settings */
6380  SCIP_STAT* stat, /**< problem statistics data */
6381  SCIP_LP* lp /**< current LP data */
6382  )
6383 {
6384  SCIP_Real norm;
6385  SCIP_Real feasibility;
6386  SCIP_Real eps;
6387 
6388  assert(set != NULL);
6389 
6390  switch( set->sepa_efficacynorm )
6391  {
6392  case 'e':
6393  norm = SCIProwGetNorm(row);
6394  break;
6395  case 'm':
6396  norm = SCIProwGetMaxval(row, set);
6397  break;
6398  case 's':
6399  norm = SCIProwGetSumNorm(row);
6400  break;
6401  case 'd':
6402  norm = (row->len == 0 ? 0.0 : 1.0);
6403  break;
6404  default:
6405  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6406  SCIPABORT();
6407  norm = 0.0; /*lint !e527*/
6408  }
6409 
6410  eps = SCIPsetSumepsilon(set);
6411  norm = MAX(norm, eps);
6412  feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6413 
6414  return -feasibility / norm;
6415 }
6416 
6417 /** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6419  SCIP_ROW* row, /**< LP row */
6420  SCIP_SET* set, /**< global SCIP settings */
6421  SCIP_STAT* stat, /**< problem statistics data */
6422  SCIP_LP* lp, /**< current LP data */
6423  SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6424  )
6425 {
6426  SCIP_Real efficacy;
6427 
6428  efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6429 
6430  return SCIPsetIsEfficacious(set, root, efficacy);
6431 }
6432 
6433 /** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6435  SCIP_ROW* row, /**< LP row */
6436  SCIP_SET* set, /**< global SCIP settings */
6437  SCIP_STAT* stat, /**< problem statistics data */
6438  SCIP_SOL* sol /**< primal CIP solution */
6439  )
6440 {
6441  SCIP_Real norm;
6442  SCIP_Real feasibility;
6443  SCIP_Real eps;
6444 
6445  assert(set != NULL);
6446 
6447  switch( set->sepa_efficacynorm )
6448  {
6449  case 'e':
6450  norm = SCIProwGetNorm(row);
6451  break;
6452  case 'm':
6453  norm = SCIProwGetMaxval(row, set);
6454  break;
6455  case 's':
6456  norm = SCIProwGetSumNorm(row);
6457  break;
6458  case 'd':
6459  norm = (row->len == 0 ? 0.0 : 1.0);
6460  break;
6461  default:
6462  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6463  SCIPABORT();
6464  norm = 0.0; /*lint !e527*/
6465  }
6466 
6467  eps = SCIPsetSumepsilon(set);
6468  norm = MAX(norm, eps);
6469  feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6470 
6471  return -feasibility / norm;
6472 }
6473 
6474 /** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6475  * efficacy
6476  */
6478  SCIP_ROW* row, /**< LP row */
6479  SCIP_SET* set, /**< global SCIP settings */
6480  SCIP_STAT* stat, /**< problem statistics data */
6481  SCIP_SOL* sol, /**< primal CIP solution */
6482  SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6483  )
6484 {
6485  SCIP_Real efficacy;
6486 
6487  efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6488 
6489  return SCIPsetIsEfficacious(set, root, efficacy);
6490 }
6491 
6492 /** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6494  SCIP_ROW* row, /**< LP row */
6495  SCIP_SET* set, /**< global SCIP settings */
6496  SCIP_STAT* stat /**< problem statistics data */
6497  )
6498 {
6499  SCIP_Real norm;
6500  SCIP_Real feasibility;
6501  SCIP_Real eps;
6502 
6503  assert(set != NULL);
6504 
6505  switch( set->sepa_efficacynorm )
6506  {
6507  case 'e':
6508  norm = SCIProwGetNorm(row);
6509  break;
6510  case 'm':
6511  norm = SCIProwGetMaxval(row, set);
6512  break;
6513  case 's':
6514  norm = SCIProwGetSumNorm(row);
6515  break;
6516  case 'd':
6517  norm = (row->len == 0 ? 0.0 : 1.0);
6518  break;
6519  default:
6520  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6521  SCIPABORT();
6522  norm = 0.0; /*lint !e527*/
6523  }
6524 
6525  eps = SCIPsetSumepsilon(set);
6526  norm = MAX(norm, eps);
6527  feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6528 
6529  return -feasibility / norm;
6530 }
6531 
6532 /** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6534  SCIP_ROW* row, /**< LP row */
6535  SCIP_SET* set, /**< global SCIP settings */
6536  SCIP_STAT* stat /**< problem statistics data */
6537  )
6538 {
6539  SCIP_Real norm;
6540  SCIP_Real feasibility;
6541  SCIP_Real eps;
6542 
6543  assert(set != NULL);
6544 
6545  switch( set->sepa_efficacynorm )
6546  {
6547  case 'e':
6548  norm = SCIProwGetNorm(row);
6549  break;
6550  case 'm':
6551  norm = SCIProwGetMaxval(row, set);
6552  break;
6553  case 's':
6554  norm = SCIProwGetSumNorm(row);
6555  break;
6556  case 'd':
6557  norm = (row->len == 0 ? 0.0 : 1.0);
6558  break;
6559  default:
6560  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6561  SCIPABORT();
6562  norm = 0.0; /*lint !e527*/
6563  }
6564 
6565  eps = SCIPsetSumepsilon(set);
6566  norm = MAX(norm, eps);
6567  feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6568 
6569  return -feasibility / norm;
6570 }
6571 
6572 /** returns the scalar product of the coefficient vectors of the two given rows
6573  *
6574  * @note the scalar product is computed w.r.t. the current LP columns only
6575  * @todo also consider non-LP columns for the computation?
6576  */
6578  SCIP_ROW* row1, /**< first LP row */
6579  SCIP_ROW* row2 /**< second LP row */
6580  )
6581 {
6582  SCIP_Real scalarprod;
6583  int* row1colsidx;
6584  int* row2colsidx;
6585  int i1;
6586  int i2;
6587 
6588  assert(row1 != NULL);
6589  assert(row2 != NULL);
6590 
6591  /* Sort the column indices of both rows.
6592  *
6593  * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
6594  * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
6595  * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
6596  * for both or one of the non-LP columns for both.
6597  * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
6598  * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
6599  * columns can be added later and remain unlinked while all previously added columns might already be linked.
6600  * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
6601  *
6602  * We distinguish the following cases:
6603  *
6604  * 1) both rows have no unlinked columns
6605  * -> we just check the LP partitions
6606  *
6607  * 2) exactly one row is completely unlinked, the other one is completely linked
6608  * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
6609  * (thus all common LP columns are regarded)
6610  *
6611  * 3) we have unlinked and LP columns in both rows
6612  * -> we need to compare four partitions at once
6613  *
6614  * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
6615  * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
6616  * other row
6617  *
6618  * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
6619  * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
6620  *
6621  * 5) both rows are completely unlinked
6622  * -> we need to compare two partitions: both complete rows
6623  */
6624  SCIProwSort(row1);
6625  assert(row1->lpcolssorted);
6626  assert(row1->nonlpcolssorted);
6627  SCIProwSort(row2);
6628  assert(row2->lpcolssorted);
6629  assert(row2->nonlpcolssorted);
6630 
6631  assert(row1->nunlinked <= row1->len - row1->nlpcols);
6632  assert(row2->nunlinked <= row2->len - row2->nlpcols);
6633 
6634  row1colsidx = row1->cols_index;
6635  row2colsidx = row2->cols_index;
6636 
6637 #ifndef NDEBUG
6638  /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
6639  if( row1->nunlinked == 0 && row2->nunlinked == 0 )
6640  {
6641  i1 = 0;
6642  i2 = row2->nlpcols;
6643  while( i1 < row1->nlpcols && i2 < row2->len )
6644  {
6645  assert(row1->cols[i1] != row2->cols[i2]);
6646  if( row1->cols[i1]->index < row2->cols[i2]->index )
6647  ++i1;
6648  else
6649  {
6650  assert(row1->cols[i1]->index > row2->cols[i2]->index);
6651  ++i2;
6652  }
6653  }
6654  assert(i1 == row1->nlpcols || i2 == row2->len);
6655 
6656  i1 = row1->nlpcols;
6657  i2 = 0;
6658  while( i1 < row1->len && i2 < row2->nlpcols )
6659  {
6660  assert(row1->cols[i1] != row2->cols[i2]);
6661  if( row1->cols[i1]->index < row2->cols[i2]->index )
6662  ++i1;
6663  else
6664  {
6665  assert(row1->cols[i1]->index > row2->cols[i2]->index);
6666  ++i2;
6667  }
6668  }
6669  assert(i1 == row1->len || i2 == row2->nlpcols);
6670  }
6671 #endif
6672 
6673  /* The "easy" cases 1) and 2) */
6674  if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
6675  ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
6676  && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
6677  && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
6678  {
6679  assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
6680  assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
6681 
6682  /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
6683  * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
6684  */
6685  i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
6686  i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
6687  scalarprod = 0.0;
6688 
6689  /* calculate the scalar product */
6690  while( i1 >= 0 && i2 >= 0 )
6691  {
6692  assert(row1->cols[i1]->index == row1colsidx[i1]);
6693  assert(row2->cols[i2]->index == row2colsidx[i2]);
6694  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
6695  if( row1colsidx[i1] < row2colsidx[i2] )
6696  --i2;
6697  else if( row1colsidx[i1] > row2colsidx[i2] )
6698  --i1;
6699  else
6700  {
6701  scalarprod += row1->vals[i1] * row2->vals[i2];
6702  --i1;
6703  --i2;
6704  }
6705  }
6706  }
6707  /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
6708  else
6709  {
6710  SCIP_Bool lpcols;
6711  int ilp1;
6712  int inlp1;
6713  int ilp2;
6714  int inlp2;
6715  int end1;
6716  int end2;
6717 
6718  scalarprod = 0;
6719  ilp1 = 0;
6720  ilp2 = 0;
6721 
6722  /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
6723  inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
6724  inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
6725 
6726  /* handle the case of four partitions (case 3) until one partition is finished;
6727  * cases 4a), 4b), and 5) will fail the while-condition
6728  */
6729  while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
6730  {
6731  assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
6732  assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
6733  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
6734  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
6735  assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
6736  assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
6737  assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
6738  assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
6739 
6740  /* rows have the same linked LP columns */
6741  if( row1colsidx[ilp1] == row2colsidx[ilp2] )
6742  {
6743  scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
6744  ++ilp1;
6745  ++ilp2;
6746  }
6747  /* LP column of row1 is the same as unlinked column of row2 */
6748  else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
6749  {
6750  scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
6751  ++ilp1;
6752  ++inlp2;
6753  }
6754  /* unlinked column of row1 is the same as LP column of row2 */
6755  else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
6756  {
6757  scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
6758  ++inlp1;
6759  ++ilp2;
6760  }
6761  /* two unlinked LP columns are the same */
6762  else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
6763  {
6764  scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
6765  ++inlp1;
6766  ++inlp2;
6767  }
6768  /* increase smallest counter */
6769  else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
6770  {
6771  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6772  {
6773  if( row1colsidx[ilp1] < row2colsidx[ilp2] )
6774  ++ilp1;
6775  else
6776  ++ilp2;
6777  }
6778  else
6779  {
6780  if( row1colsidx[ilp1] < row2colsidx[inlp2] )
6781  ++ilp1;
6782  else
6783  ++inlp2;
6784  }
6785  }
6786  else
6787  {
6788  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6789  {
6790  if( row1colsidx[inlp1] < row2colsidx[ilp2] )
6791  ++inlp1;
6792  else
6793  ++ilp2;
6794  }
6795  else
6796  {
6797  if( row1colsidx[inlp1] < row2colsidx[inlp2] )
6798  ++inlp1;
6799  else
6800  ++inlp2;
6801  }
6802  }
6803  }
6804 
6805  /* One partition was completely handled, we just have to handle the three remaining partitions:
6806  * the remaining partition of this row and the two partitions of the other row.
6807  * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
6808  */
6809  if( ilp1 != row1->nlpcols && inlp1 != row1->len )
6810  {
6811  int tmpilp;
6812  int tmpinlp;
6813 
6814  assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
6815 
6816  SCIPswapPointers((void**) &row1, (void**) &row2);
6817  SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
6818  tmpilp = ilp1;
6819  tmpinlp = inlp1;
6820  ilp1 = ilp2;
6821  inlp1 = inlp2;
6822  ilp2 = tmpilp;
6823  inlp2 = tmpinlp;
6824  }
6825 
6826  /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
6827  * -> this merges cases 4a) and 4b)
6828  */
6829  if( ilp1 == row1->nlpcols )
6830  {
6831  i1 = inlp1;
6832  end1 = row1->len;
6833  lpcols = FALSE;
6834  }
6835  else
6836  {
6837  assert(inlp1 == row1->len);
6838 
6839  i1 = ilp1;
6840  end1 = row1->nlpcols;
6841  lpcols = TRUE;
6842  }
6843 
6844  /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
6845  * case 5) will fail the while-condition
6846  */
6847  while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
6848  {
6849  assert(row1->cols[i1]->index == row1colsidx[i1]);
6850  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
6851  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
6852  assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
6853  assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
6854 
6855  /* current column in row 1 is the same as the current LP column in row 2 */
6856  if( row1colsidx[i1] == row2colsidx[ilp2] )
6857  {
6858  scalarprod += row1->vals[i1] * row2->vals[ilp2];
6859  ++i1;
6860  ++ilp2;
6861  }
6862  /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
6863  else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
6864  {
6865  scalarprod += row1->vals[i1] * row2->vals[inlp2];
6866  ++i1;
6867  ++inlp2;
6868  }
6869  /* increase smallest counter */
6870  else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
6871  {
6872  if( row1colsidx[i1] < row2colsidx[ilp2] )
6873  ++i1;
6874  else
6875  ++ilp2;
6876  }
6877  else
6878  {
6879  if( row1colsidx[i1] < row2colsidx[inlp2] )
6880  ++i1;
6881  else
6882  ++inlp2;
6883  }
6884  }
6885 
6886  /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
6887  * the two rows
6888  */
6889  if( i1 < end1 )
6890  {
6891  /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
6892  if( ilp2 == row2->nlpcols )
6893  {
6894  i2 = inlp2;
6895  end2 = row2->len;
6896  lpcols = FALSE;
6897  }
6898  else
6899  {
6900  assert(inlp2 == row2->len);
6901 
6902  i2 = ilp2;
6903  end2 = row2->nlpcols;
6904  }
6905 
6906  /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
6907  while( i1 < end1 && i2 < end2 )
6908  {
6909  assert(row1->cols[i1]->index == row1colsidx[i1]);
6910  assert(row2->cols[i2]->index == row2colsidx[i2]);
6911  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
6912 
6913  /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
6914  if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
6915  {
6916  scalarprod += row1->vals[i1] * row2->vals[i2];
6917  ++i1;
6918  ++i2;
6919  }
6920  /* increase smallest counter */
6921  else if( row1colsidx[i1] < row2colsidx[i2] )
6922  ++i1;
6923  else
6924  ++i2;
6925  }
6926  }
6927  }
6928 
6929  return scalarprod;
6930 }
6931 
6932 /** returns the discrete scalar product of the coefficient vectors of the two given rows */
6933 static
6935  SCIP_ROW* row1, /**< first LP row */
6936  SCIP_ROW* row2 /**< second LP row */
6937  )
6938 {
6939  int prod;
6940  int* row1colsidx;
6941  int* row2colsidx;
6942  int i1;
6943  int i2;
6944 
6945  assert(row1 != NULL);
6946  assert(row2 != NULL);
6947 
6948  /* Sort the column indices of both rows.
6949  *
6950  * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
6951  * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
6952  * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
6953  * for both or one of the non-LP columns for both.
6954  * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
6955  * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
6956  * columns can be added later and remain unlinked while all previously added columns might already be linked.
6957  * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
6958  *
6959  * We distinguish the following cases:
6960  *
6961  * 1) both rows have no unlinked columns
6962  * -> we just check the LP partitions
6963  *
6964  * 2) exactly one row is completely unlinked, the other one is completely linked
6965  * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
6966  * (thus all common LP columns are regarded)
6967  *
6968  * 3) we have unlinked and LP columns in both rows
6969  * -> we need to compare four partitions at once
6970  *
6971  * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
6972  * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
6973  * other row
6974  *
6975  * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
6976  * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
6977  *
6978  * 5) both rows are completely unlinked
6979  * -> we need to compare two partitions: both complete rows
6980  */
6981  SCIProwSort(row1);
6982  assert(row1->lpcolssorted);
6983  assert(row1->nonlpcolssorted);
6984  SCIProwSort(row2);
6985  assert(row2->lpcolssorted);
6986  assert(row2->nonlpcolssorted);
6987 
6988  assert(row1->nunlinked <= row1->len - row1->nlpcols);
6989  assert(row2->nunlinked <= row2->len - row2->nlpcols);
6990 
6991  row1colsidx = row1->cols_index;
6992  row2colsidx = row2->cols_index;
6993 
6994 #ifndef NDEBUG
6995  /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
6996  if( row1->nunlinked == 0 && row2->nunlinked == 0 )
6997  {
6998  i1 = 0;
6999  i2 = row2->nlpcols;
7000  while( i1 < row1->nlpcols && i2 < row2->len )
7001  {
7002  assert(row1->cols[i1] != row2->cols[i2]);
7003  if( row1->cols[i1]->index < row2->cols[i2]->index )
7004  ++i1;
7005  else
7006  {
7007  assert(row1->cols[i1]->index > row2->cols[i2]->index);
7008  ++i2;
7009  }
7010  }
7011  assert(i1 == row1->nlpcols || i2 == row2->len);
7012 
7013  i1 = row1->nlpcols;
7014  i2 = 0;
7015  while( i1 < row1->len && i2 < row2->nlpcols )
7016  {
7017  assert(row1->cols[i1] != row2->cols[i2]);
7018  if( row1->cols[i1]->index < row2->cols[i2]->index )
7019  ++i1;
7020  else
7021  {
7022  assert(row1->cols[i1]->index > row2->cols[i2]->index);
7023  ++i2;
7024  }
7025  }
7026  assert(i1 == row1->len || i2 == row2->nlpcols);
7027  }
7028 #endif
7029 
7030  /* The "easy" cases 1) and 2) */
7031  if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7032  ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7033  && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7034  && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7035  {
7036  assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7037  assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7038 
7039  /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7040  * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7041  */
7042  i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7043  i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7044  prod = 0;
7045 
7046  /* calculate the scalar product */
7047  while( i1 >= 0 && i2 >= 0 )
7048  {
7049  assert(row1->cols[i1]->index == row1colsidx[i1]);
7050  assert(row2->cols[i2]->index == row2colsidx[i2]);
7051  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7052  if( row1colsidx[i1] < row2colsidx[i2] )
7053  --i2;
7054  else if( row1colsidx[i1] > row2colsidx[i2] )
7055  --i1;
7056  else
7057  {
7058  ++prod;
7059  --i1;
7060  --i2;
7061  }
7062  }
7063  }
7064  /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7065  else
7066  {
7067  SCIP_Bool lpcols;
7068  int ilp1;
7069  int inlp1;
7070  int ilp2;
7071  int inlp2;
7072  int end1;
7073  int end2;
7074 
7075  prod = 0;
7076  ilp1 = 0;
7077  ilp2 = 0;
7078 
7079  /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7080  inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7081  inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7082 
7083  /* handle the case of four partitions (case 3) until one partition is finished;
7084  * cases 4a), 4b), and 5) will fail the while-condition
7085  */
7086  while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7087  {
7088  assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7089  assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7090  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7091  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7092  assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7093  assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7094  assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7095  assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7096 
7097  /* rows have the same linked LP columns */
7098  if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7099  {
7100  ++prod;
7101  ++ilp1;
7102  ++ilp2;
7103  }
7104  /* LP column of row1 is the same as unlinked column of row2 */
7105  else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7106  {
7107  ++prod;
7108  ++ilp1;
7109  ++inlp2;
7110  }
7111  /* unlinked column of row1 is the same as LP column of row2 */
7112  else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7113  {
7114  ++prod;
7115  ++inlp1;
7116  ++ilp2;
7117  }
7118  /* two unlinked LP columns are the same */
7119  else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7120  {
7121  ++prod;
7122  ++inlp1;
7123  ++inlp2;
7124  }
7125  /* increase smallest counter */
7126  else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7127  {
7128  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7129  {
7130  if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7131  ++ilp1;
7132  else
7133  ++ilp2;
7134  }
7135  else
7136  {
7137  if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7138  ++ilp1;
7139  else
7140  ++inlp2;
7141  }
7142  }
7143  else
7144  {
7145  if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7146  {
7147  if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7148  ++inlp1;
7149  else
7150  ++ilp2;
7151  }
7152  else
7153  {
7154  if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7155  ++inlp1;
7156  else
7157  ++inlp2;
7158  }
7159  }
7160  }
7161 
7162  /* One partition was completely handled, we just have to handle the three remaining partitions:
7163  * the remaining partition of this row and the two partitions of the other row.
7164  * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7165  */
7166  if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7167  {
7168  int tmpilp;
7169  int tmpinlp;
7170 
7171  assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7172 
7173  SCIPswapPointers((void**) &row1, (void**) &row2);
7174  SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7175  tmpilp = ilp1;
7176  tmpinlp = inlp1;
7177  ilp1 = ilp2;
7178  inlp1 = inlp2;
7179  ilp2 = tmpilp;
7180  inlp2 = tmpinlp;
7181  }
7182 
7183  /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7184  * -> this merges cases 4a) and 4b)
7185  */
7186  if( ilp1 == row1->nlpcols )
7187  {
7188  i1 = inlp1;
7189  end1 = row1->len;
7190  lpcols = FALSE;
7191  }
7192  else
7193  {
7194  assert(inlp1 == row1->len);
7195 
7196  i1 = ilp1;
7197  end1 = row1->nlpcols;
7198  lpcols = TRUE;
7199  }
7200 
7201  /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7202  * case 5) will fail the while-condition
7203  */
7204  while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7205  {
7206  assert(row1->cols[i1]->index == row1colsidx[i1]);
7207  assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7208  assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7209  assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7210  assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7211 
7212  /* current column in row 1 is the same as the current LP column in row 2 */
7213  if( row1colsidx[i1] == row2colsidx[ilp2] )
7214  {
7215  ++prod;
7216  ++i1;
7217  ++ilp2;
7218  }
7219  /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7220  else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7221  {
7222  ++prod;
7223  ++i1;
7224  ++inlp2;
7225  }
7226  /* increase smallest counter */
7227  else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7228  {
7229  if( row1colsidx[i1] < row2colsidx[ilp2] )
7230  ++i1;
7231  else
7232  ++ilp2;
7233  }
7234  else
7235  {
7236  if( row1colsidx[i1] < row2colsidx[inlp2] )
7237  ++i1;
7238  else
7239  ++inlp2;
7240  }
7241  }
7242 
7243  /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7244  * the two rows
7245  */
7246  if( i1 < end1 )
7247  {
7248  /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7249  if( ilp2 == row2->nlpcols )
7250  {
7251  i2 = inlp2;
7252  end2 = row2->len;
7253  lpcols = FALSE;
7254  }
7255  else
7256  {
7257  assert(inlp2 == row2->len);
7258 
7259  i2 = ilp2;
7260  end2 = row2->nlpcols;
7261  }
7262 
7263  /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7264  while( i1 < end1 && i2 < end2 )
7265  {
7266  assert(row1->cols[i1]->index == row1colsidx[i1]);
7267  assert(row2->cols[i2]->index == row2colsidx[i2]);
7268  assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7269 
7270  /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7271  if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7272  {
7273  ++prod;
7274  ++i1;
7275  ++i2;
7276  }
7277  /* increase smallest counter */
7278  else if( row1colsidx[i1] < row2colsidx[i2] )
7279  ++i1;
7280  else
7281  ++i2;
7282  }
7283  }
7284  }
7285 
7286  return prod;
7287 }
7288 
7289 /** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7290  * p = |v*w|/(|v|*|w|);
7291  * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7292  */
7294  SCIP_ROW* row1, /**< first LP row */
7295  SCIP_ROW* row2, /**< second LP row */
7296  char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7297  )
7298 {
7299  SCIP_Real parallelism;
7300  SCIP_Real scalarprod;
7301 
7302  switch( orthofunc )
7303  {
7304  case 'e':
7305  scalarprod = SCIProwGetScalarProduct(row1, row2);
7306  parallelism = (REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2)));
7307  break;
7308  case 'd':
7309  scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7310  parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7311  break;
7312  default:
7313  SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7314  SCIPABORT();
7315  parallelism = 0.0; /*lint !e527*/
7316  }
7317 
7318  return parallelism;
7319 }
7320 
7321 /** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7322  * o = 1 - |v*w|/(|v|*|w|);
7323  * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7324  */
7326  SCIP_ROW* row1, /**< first LP row */
7327  SCIP_ROW* row2, /**< second LP row */
7328  char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7329  )
7330 {
7331  return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7332 }
7333 
7334 /** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7335  * function, if the value is 0, it is orthogonal to the objective function
7336  */
7338  SCIP_ROW* row, /**< LP row */
7339  SCIP_SET* set, /**< global SCIP settings */
7340  SCIP_LP* lp /**< current LP data */
7341  )
7342 {
7343  SCIP_Real prod;
7344  SCIP_Real parallelism;
7345 
7346  assert(row != NULL);
7347  assert(lp != NULL);
7348 
7349  if( lp->objsqrnormunreliable )
7350  SCIPlpRecalculateObjSqrNorm(set, lp);
7351 
7352  assert(!lp->objsqrnormunreliable);
7353  assert(lp->objsqrnorm >= 0.0);
7354 
7355  checkRowSqrnorm(row);
7356  checkRowObjprod(row);
7357 
7358  prod = row->sqrnorm * lp->objsqrnorm;
7359 
7360  parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / SQRT(prod) : 0.0;
7361  assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7362  assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7363  parallelism = MIN(parallelism, 1.0);
7364  parallelism = MAX(parallelism, 0.0);
7365 
7366  return parallelism;
7367 }
7368 
7369 /** includes event handler with given data in row's event filter */
7371  SCIP_ROW* row, /**< row */
7372  BMS_BLKMEM* blkmem, /**< block memory */
7373  SCIP_SET* set, /**< global SCIP settings */
7374  SCIP_EVENTTYPE eventtype, /**< event type to catch */
7375  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7376  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7377  int* filterpos /**< pointer to store position of event filter entry, or NULL */
7378  )
7379 {
7380  assert(row != NULL);
7381  assert(row->eventfilter != NULL);
7382  assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7383  assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7384 
7385  SCIPdebugMessage("catch event of type 0x%x of row <%s> with handler %p and data %p\n",
7386  eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7387 
7388  SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7389 
7390  return SCIP_OKAY;
7391 }
7392 
7393 /** deletes event handler with given data from row's event filter */
7395  SCIP_ROW* row, /**< row */
7396  BMS_BLKMEM* blkmem, /**< block memory */
7397  SCIP_SET* set, /**< global SCIP settings */
7398  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7399  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7400  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7401  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7402  )
7403 {
7404  assert(row != NULL);
7405  assert(row->eventfilter != NULL);
7406 
7407  SCIPdebugMessage("drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7408 
7409  SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7410 
7411  return SCIP_OKAY;
7412 }
7413 
7414 /** marks a row to be not removable from the LP in the current node because it became obsolete */
7416  SCIP_ROW* row, /**< LP row */
7417  SCIP_STAT* stat /**< problem statistics */
7418  )
7419 {
7420  assert(row != NULL);
7421  assert(stat != NULL);
7422  assert(stat->nnodes > 0);
7423 
7424  /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7425  row->obsoletenode = stat->nnodes;
7426 }
7427 
7428 /*
7429  * LP solver data update
7430  */
7431 
7432 /** resets column data to represent a column not in the LP solver */
7433 static
7435  SCIP_COL* col /**< column to be marked deleted */
7436  )
7437 {
7438  assert(col != NULL);
7439 
7440  col->lpipos = -1;
7441  col->primsol = 0.0;
7442  col->redcost = SCIP_INVALID;
7443  col->farkascoef = SCIP_INVALID;
7444  col->sbdown = SCIP_INVALID;
7445  col->sbup = SCIP_INVALID;
7446  col->sbdownvalid = FALSE;
7447  col->sbupvalid = FALSE;
7448  col->validredcostlp = -1;
7449  col->validfarkaslp = -1;
7450  col->sbitlim = -1;
7451  col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7452 }
7453 
7454 /** applies all cached column removals to the LP solver */
7455 static
7457  SCIP_LP* lp /**< current LP data */
7458  )
7459 {
7460  assert(lp != NULL);
7461  assert(lp->lpifirstchgcol <= lp->nlpicols);
7462  assert(lp->lpifirstchgcol <= lp->ncols);
7463 
7464  /* find the first column to change */
7465  while( lp->lpifirstchgcol < lp->nlpicols
7466  && lp->lpifirstchgcol < lp->ncols
7467  && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7468  && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7469  {
7470  assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7471  lp->lpifirstchgcol++;
7472  }
7473 
7474  /* shrink LP to the part which didn't change */
7475  if( lp->lpifirstchgcol < lp->nlpicols )
7476  {
7477  int i;
7478 
7479  assert(!lp->diving);
7480  SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7481  SCIP_CALL( SCIPlpiDelCols(lp->lpi, lp->lpifirstchgcol, lp->nlpicols-1) );
7482  for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7483  {
7484  markColDeleted(lp->lpicols[i]);
7485  }
7486  lp->nlpicols = lp->lpifirstchgcol;
7487  lp->flushdeletedcols = TRUE;
7488 
7489  /* mark the LP unsolved */
7490  lp->solved = FALSE;
7491  lp->primalfeasible = FALSE;
7492  lp->lpobjval = SCIP_INVALID;
7494  }
7495  assert(lp->nlpicols == lp->lpifirstchgcol);
7496 
7497  return SCIP_OKAY;
7498 }
7499 
7500 /** computes for the given column the lower and upper bound that should be flushed into the LP
7501  * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7502  * the bounds are explicitly added to the LP in any case
7503  */
7504 static
7506  SCIP_LP* lp, /**< current LP data */
7507  SCIP_SET* set, /**< global SCIP settings */
7508  SCIP_COL* col, /**< column to compute bounds for */
7509  SCIP_Real lpiinf, /**< infinity value if the LP solver */
7510  SCIP_Real* lb, /**< pointer to store the new lower bound */
7511  SCIP_Real* ub /**< pointer to store the new upper bound */
7512  )
7513 {
7514  assert(lp != NULL);
7515  assert(set != NULL);
7516  assert(col != NULL);
7517  assert(lb != NULL);
7518  assert(ub != NULL);
7519 
7520  /* get the correct new lower bound:
7521  * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7522  * if we are in diving mode, ignore lazy bounds and always take the lower bound
7523  */
7524  if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7525  (*lb) = -lpiinf;
7526  else
7527  (*lb) = col->lb;
7528  /* get the correct new upper bound:
7529  * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7530  * if we are in diving mode, ignore lazy bounds and always take the upper bound
7531  */
7532  if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7533  (*ub) = lpiinf;
7534  else
7535  (*ub) = col->ub;
7536 }
7537 
7538 /** applies all cached column additions to the LP solver */
7539 static
7541  SCIP_LP* lp, /**< current LP data */
7542  BMS_BLKMEM* blkmem, /**< block memory */
7543  SCIP_SET* set, /**< global SCIP settings */
7544  SCIP_EVENTQUEUE* eventqueue /**< event queue */
7545  )
7546 {
7547  SCIP_Real* obj;
7548  SCIP_Real* lb;
7549  SCIP_Real* ub;
7550  int* beg;
7551  int* ind;
7552  SCIP_Real* val;
7553  char** name;
7554  SCIP_COL* col;
7555  SCIP_Real lpiinf;
7556  int c;
7557  int pos;
7558  int nnonz;
7559  int naddcols;
7560  int naddcoefs;
7561  int i;
7562  int lpipos;
7563 
7564  assert(lp != NULL);
7565  assert(lp->lpifirstchgcol == lp->nlpicols);
7566  assert(blkmem != NULL);
7567  assert(set != NULL);
7568 
7569  /* if there are no columns to add, we are ready */
7570  if( lp->ncols == lp->nlpicols )
7571  return SCIP_OKAY;
7572 
7573  /* add the additional columns */
7574  assert(!lp->diving);
7575  assert(lp->ncols > lp->nlpicols);
7576  SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
7577 
7578  /* get the solver's infinity value */
7579  lpiinf = SCIPlpiInfinity(lp->lpi);
7580 
7581  /* count the (maximal) number of added coefficients, calculate the number of added columns */
7582  naddcols = lp->ncols - lp->nlpicols;
7583  naddcoefs = 0;
7584  for( c = lp->nlpicols; c < lp->ncols; ++c )
7585  naddcoefs += lp->cols[c]->len;
7586  assert(naddcols > 0);
7587 
7588  /* get temporary memory for changes */
7589  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
7590  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
7591  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
7592  SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
7593  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
7594  SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
7595  SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
7596 
7597  /* fill temporary memory with column data */
7598  nnonz = 0;
7599  for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
7600  {
7601  col = lp->cols[c];
7602  assert(col != NULL);
7603  assert(col->var != NULL);
7604  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
7605  assert(SCIPvarGetCol(col->var) == col);
7606  assert(col->lppos == c);
7607  assert(nnonz + col->nlprows <= naddcoefs);
7608 
7609  SCIPdebugMessage("flushing added column <%s>: ", SCIPvarGetName(col->var));
7610  debugColPrint(col);
7611 
7612  /* Because the column becomes a member of the LP solver, it now can take values
7613  * different from zero. That means, we have to include the column in the corresponding
7614  * row vectors.
7615  */
7616  SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
7617 
7618  lp->lpicols[c] = col;
7619  col->lpipos = c;
7620  col->primsol = SCIP_INVALID;
7621  col->redcost = SCIP_INVALID;
7622  col->farkascoef = SCIP_INVALID;
7623  col->sbdown = SCIP_INVALID;
7624  col->sbup = SCIP_INVALID;
7625  col->sbdownvalid = FALSE;
7626  col->sbupvalid = FALSE;
7627  col->validredcostlp = -1;
7628  col->validfarkaslp = -1;
7629  col->sbitlim = -1;
7630  col->objchanged = FALSE;
7631  col->lbchanged = FALSE;
7632  col->ubchanged = FALSE;
7633  col->coefchanged = FALSE;
7634  obj[pos] = col->obj;
7635 
7636  /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
7637  computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
7638 
7639  beg[pos] = nnonz;
7640  name[pos] = (char*)SCIPvarGetName(col->var);
7641 
7642  col->flushedobj = obj[pos];
7643  col->flushedlb = lb[pos];
7644  col->flushedub = ub[pos];
7645 
7646  for( i = 0; i < col->nlprows; ++i )
7647  {
7648  assert(col->rows[i] != NULL);
7649  lpipos = col->rows[i]->lpipos;
7650  if( lpipos >= 0 )
7651  {
7652  assert(lpipos < lp->nrows);
7653  assert(nnonz < naddcoefs);
7654  ind[nnonz] = lpipos;
7655  val[nnonz] = col->vals[i];
7656  nnonz++;
7657  }
7658  }
7659 #ifndef NDEBUG
7660  for( i = col->nlprows; i < col->len; ++i )
7661  {
7662  assert(col->rows[i] != NULL);
7663  assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
7664  }
7665 #endif
7666  }
7667 
7668  /* call LP interface */
7669  SCIPdebugMessage("flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
7670  SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
7671  lp->nlpicols = lp->ncols;
7672  lp->lpifirstchgcol = lp->nlpicols;
7673 
7674  /* free temporary memory */
7675  SCIPsetFreeBufferArray(set, &name);
7676  SCIPsetFreeBufferArray(set, &val);
7677  SCIPsetFreeBufferArray(set, &ind);
7678  SCIPsetFreeBufferArray(set, &beg);
7679  SCIPsetFreeBufferArray(set, &ub);
7680  SCIPsetFreeBufferArray(set, &lb);
7681  SCIPsetFreeBufferArray(set, &obj);
7682 
7683  lp->flushaddedcols = TRUE;
7684 
7685  /* mark the LP unsolved */
7686  lp->solved = FALSE;
7687  lp->dualfeasible = FALSE;
7688  lp->lpobjval = SCIP_INVALID;
7690 
7691  return SCIP_OKAY;
7692 }
7693 
7694 /** resets row data to represent a row not in the LP solver */
7695 static
7697  SCIP_ROW* row /**< row to be marked deleted */
7698  )
7699 {
7700  assert(row != NULL);
7701 
7702  row->lpipos = -1;
7703  row->dualsol = 0.0;
7704  row->activity = SCIP_INVALID;
7705  row->dualfarkas = 0.0;
7706  row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
7707  row->validactivitylp = -1;
7708 }
7709 
7710 /** applies all cached row removals to the LP solver */
7711 static
7713  SCIP_LP* lp, /**< current LP data */
7714  BMS_BLKMEM* blkmem, /**< block memory */
7715  SCIP_SET* set /**< global SCIP settings */
7716  )
7717 {
7718  assert(lp != NULL);
7719  assert(lp->lpifirstchgrow <= lp->nlpirows);
7720  assert(lp->lpifirstchgrow <= lp->nrows);
7721 
7722  /* find the first row to change */
7723  while( lp->lpifirstchgrow < lp->nlpirows
7724  && lp->lpifirstchgrow < lp->nrows
7725  && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
7726  && !lp->rows[lp->lpifirstchgrow]->coefchanged )
7727  {
7728  assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
7729  lp->lpifirstchgrow++;
7730  }
7731 
7732  /* shrink LP to the part which didn't change */
7733  if( lp->lpifirstchgrow < lp->nlpirows )
7734  {
7735  int i;
7736 
7737  SCIPdebugMessage("flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
7738  SCIP_CALL( SCIPlpiDelRows(lp->lpi, lp->lpifirstchgrow, lp->nlpirows-1) );
7739  for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
7740  {
7741  markRowDeleted(lp->lpirows[i]);
7742  SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
7743  }
7744  lp->nlpirows = lp->lpifirstchgrow;
7745  lp->flushdeletedrows = TRUE;
7746 
7747  /* mark the LP unsolved */
7748  lp->solved = FALSE;
7749  lp->dualfeasible = FALSE;
7750  lp->lpobjval = SCIP_INVALID;
7752  }
7753  assert(lp->nlpirows == lp->lpifirstchgrow);
7754 
7755  return SCIP_OKAY;
7756 }
7757 
7758 /** applies all cached row additions and removals to the LP solver */
7759 static
7761  SCIP_LP* lp, /**< current LP data */
7762  BMS_BLKMEM* blkmem, /**< block memory */
7763  SCIP_SET* set, /**< global SCIP settings */
7764  SCIP_EVENTQUEUE* eventqueue /**< event queue */
7765  )
7766 {
7767  SCIP_Real* lhs;
7768  SCIP_Real* rhs;
7769  int* beg;
7770  int* ind;
7771  SCIP_Real* val;
7772  char** name;
7773  SCIP_ROW* row;
7774  SCIP_Real lpiinf;
7775  int r;
7776  int pos;
7777  int nnonz;
7778  int naddrows;
7779  int naddcoefs;
7780  int i;
7781  int lpipos;
7782 
7783  assert(lp != NULL);
7784  assert(lp->lpifirstchgrow == lp->nlpirows);
7785  assert(blkmem != NULL);
7786 
7787  /* if there are no rows to add, we are ready */
7788  if( lp->nrows == lp->nlpirows )
7789  return SCIP_OKAY;
7790 
7791  /* add the additional rows */
7792  assert(lp->nrows > lp->nlpirows);
7793  SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
7794 
7795  /* get the solver's infinity value */
7796  lpiinf = SCIPlpiInfinity(lp->lpi);
7797 
7798  /* count the (maximal) number of added coefficients, calculate the number of added rows */
7799  naddrows = lp->nrows - lp->nlpirows;
7800  naddcoefs = 0;
7801  for( r = lp->nlpirows; r < lp->nrows; ++r )
7802  naddcoefs += lp->rows[r]->len;
7803  assert(naddrows > 0);
7804 
7805  /* get temporary memory for changes */
7806  SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
7807  SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
7808  SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
7809  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
7810  SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
7811  SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
7812 
7813  /* fill temporary memory with row data */
7814  nnonz = 0;
7815  for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
7816  {
7817  row = lp->rows[r];
7818  assert(row != NULL);
7819  assert(row->lppos == r);
7820  assert(nnonz + row->nlpcols <= naddcoefs);
7821 
7822  SCIPdebugMessage("flushing added row <%s>: ", row->name);
7823  debugRowPrint(row);
7824 
7825  /* Because the row becomes a member of the LP solver, its dual variable now can take values
7826  * different from zero. That means, we have to include the row in the corresponding
7827  * column vectors.
7828  */
7829  SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
7830 
7831  SCIProwCapture(row);
7832  lp->lpirows[r] = row;
7833  row->lpipos = r;
7834  row->dualsol = SCIP_INVALID;
7835  row->activity = SCIP_INVALID;
7836  row->dualfarkas = SCIP_INVALID;
7837  row->validactivitylp = -1;
7838  row->lhschanged = FALSE;
7839  row->rhschanged = FALSE;
7840  row->coefchanged = FALSE;
7841  if( SCIPsetIsInfinity(set, -row->lhs) )
7842  lhs[pos] = -lpiinf;
7843  else
7844  lhs[pos] = row->lhs - row->constant;
7845  if( SCIPsetIsInfinity(set, row->rhs) )
7846  rhs[pos] = lpiinf;
7847  else
7848  rhs[pos] = row->rhs - row->constant;
7849  beg[pos] = nnonz;
7850  name[pos] = row->name;
7851 
7852  row->flushedlhs = lhs[pos];
7853  row->flushedrhs = rhs[pos];
7854 
7855  SCIPdebugMessage("flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
7856  for( i = 0; i < row->nlpcols; ++i )
7857  {
7858  assert(row->cols[i] != NULL);
7859  lpipos = row->cols[i]->lpipos;
7860  if( lpipos >= 0 )
7861  {
7862  assert(lpipos < lp->ncols);
7863  assert(nnonz < naddcoefs);
7864  SCIPdebugPrintf(" %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
7865  ind[nnonz] = lpipos;
7866  val[nnonz] = row->vals[i];
7867  nnonz++;
7868  }
7869  }
7870  SCIPdebugPrintf(" <= %+g\n", rhs[pos]);
7871 #ifndef NDEBUG
7872  for( i = row->nlpcols; i < row->len; ++i )
7873  {
7874  assert(row->cols[i] != NULL);
7875  assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
7876  }
7877 #endif
7878  }
7879 
7880  /* call LP interface */
7881  SCIPdebugMessage("flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
7882  SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
7883  lp->nlpirows = lp->nrows;
7884  lp->lpifirstchgrow = lp->nlpirows;
7885 
7886  /* free temporary memory */
7887  SCIPsetFreeBufferArray(set, &name);
7888  SCIPsetFreeBufferArray(set, &val);
7889  SCIPsetFreeBufferArray(set, &ind);
7890  SCIPsetFreeBufferArray(set, &beg);
7891  SCIPsetFreeBufferArray(set, &rhs);
7892  SCIPsetFreeBufferArray(set, &lhs);
7893 
7894  lp->flushaddedrows = TRUE;
7895 
7896  /* mark the LP unsolved */
7897  lp->solved = FALSE;
7898  lp->primalfeasible = FALSE;
7899  lp->lpobjval = SCIP_INVALID;
7901 
7902  return SCIP_OKAY;
7903 }
7904 
7905 /** applies all cached column bound and objective changes to the LP */
7906 static
7908  SCIP_LP* lp, /**< current LP data */
7909  SCIP_SET* set /**< global SCIP settings */
7910  )
7911 {
7912 #ifndef NDEBUG
7913  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
7914 #endif
7915  SCIP_COL* col;
7916  int* objind;
7917  int* bdind;
7918  SCIP_Real* obj;
7919  SCIP_Real* lb;
7920  SCIP_Real* ub;
7921  SCIP_Real lpiinf;
7922  int nobjchg;
7923  int nbdchg;
7924  int i;
7925 
7926  assert(lp != NULL);
7927 
7928  if( lp->nchgcols == 0 )
7929  return SCIP_OKAY;
7930 
7931  /* get the solver's infinity value */
7932  lpiinf = SCIPlpiInfinity(lp->lpi);
7933 
7934  /* get temporary memory for changes */
7935  SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
7936  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, lp->ncols) );
7937  SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
7938  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, lp->ncols) );
7939  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, lp->ncols) );
7940 
7941  /* collect all cached bound and objective changes */
7942  nobjchg = 0;
7943  nbdchg = 0;
7944  for( i = 0; i < lp->nchgcols; ++i )
7945  {
7946  col = lp->chgcols[i];
7947  assert(col != NULL);
7948  assert(col->var != NULL);
7949  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
7950  assert(SCIPvarGetCol(col->var) == col);
7951 
7952  if( col->lpipos >= 0 )
7953  {
7954 #ifndef NDEBUG
7955  /* do not check consistency of data with LPI in case of LPI=none */
7956  if( !lpinone )
7957  {
7958  SCIP_Real lpiobj;
7959  SCIP_Real lpilb;
7960  SCIP_Real lpiub;
7961 
7962  SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
7963  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
7964  assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
7965  assert(SCIPsetIsFeasEQ(set, lpilb, col->flushedlb));
7966  assert(SCIPsetIsFeasEQ(set, lpiub, col->flushedub));
7967  }
7968 #endif
7969 
7970  if( col->objchanged )
7971  {
7972  SCIP_Real newobj;
7973 
7974  newobj = col->obj;
7975  if( col->flushedobj != newobj ) /*lint !e777*/
7976  {
7977  assert(nobjchg < lp->ncols);
7978  objind[nobjchg] = col->lpipos;
7979  obj[nobjchg] = newobj;
7980  nobjchg++;
7981  col->flushedobj = newobj;
7982  }
7983  col->objchanged = FALSE;
7984  }
7985 
7986  if( col->lbchanged || col->ubchanged )
7987  {
7988  SCIP_Real newlb;
7989  SCIP_Real newub;
7990 
7991  /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
7992  computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
7993 
7994  if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
7995  {
7996  assert(nbdchg < lp->ncols);
7997  bdind[nbdchg] = col->lpipos;
7998  lb[nbdchg] = newlb;
7999  ub[nbdchg] = newub;
8000  nbdchg++;
8001  col->flushedlb = newlb;
8002  col->flushedub = newub;
8003  }
8004  col->lbchanged = FALSE;
8005  col->ubchanged = FALSE;
8006  }
8007  }
8008  /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8009  }
8010 
8011  /* change objective values in LP */
8012  if( nobjchg > 0 )
8013  {
8014  SCIPdebugMessage("flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8015  SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8016 
8017  /* mark the LP unsolved */
8018  lp->solved = FALSE;
8019  lp->dualfeasible = FALSE;
8020  lp->lpobjval = SCIP_INVALID;
8022  }
8023 
8024  /* change bounds in LP */
8025  if( nbdchg > 0 )
8026  {
8027  SCIPdebugMessage("flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8028  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8029 
8030  /* mark the LP unsolved */
8031  lp->solved = FALSE;
8032  lp->primalfeasible = FALSE;
8033  lp->lpobjval = SCIP_INVALID;
8035  }
8036 
8037  lp->nchgcols = 0;
8038 
8039  /* free temporary memory */
8040  SCIPsetFreeBufferArray(set, &ub);
8041  SCIPsetFreeBufferArray(set, &lb);
8042  SCIPsetFreeBufferArray(set, &bdind);
8043  SCIPsetFreeBufferArray(set, &obj);
8044  SCIPsetFreeBufferArray(set, &objind);
8045 
8046  return SCIP_OKAY;
8047 }
8048 
8049 /** applies all cached row side changes to the LP */
8050 static
8052  SCIP_LP* lp, /**< current LP data */
8053  SCIP_SET* set /**< global SCIP settings */
8054  )
8055 {
8056 #ifndef NDEBUG
8057  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8058 #endif
8059  SCIP_ROW* row;
8060  int* ind;
8061  SCIP_Real* lhs;
8062  SCIP_Real* rhs;
8063  SCIP_Real lpiinf;
8064  int i;
8065  int nchg;
8066 
8067  assert(lp != NULL);
8068 
8069  if( lp->nchgrows == 0 )
8070  return SCIP_OKAY;
8071 
8072  /* get the solver's infinity value */
8073  lpiinf = SCIPlpiInfinity(lp->lpi);
8074 
8075  /* get temporary memory for changes */
8076  SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, lp->nrows) );
8077  SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, lp->nrows) );
8078  SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, lp->nrows) );
8079 
8080  /* collect all cached left and right hand side changes */
8081  nchg = 0;
8082  for( i = 0; i < lp->nchgrows; ++i )
8083  {
8084  row = lp->chgrows[i];
8085  assert(row != NULL);
8086 
8087  if( row->lpipos >= 0 )
8088  {
8089 #ifndef NDEBUG
8090  /* do not check consistency of data with LPI in case of LPI=none */
8091  if( !lpinone )
8092  {
8093  SCIP_Real lpilhs;
8094  SCIP_Real lpirhs;
8095 
8096  SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8097  assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8098  assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8099  }
8100 #endif
8101  if( row->lhschanged || row->rhschanged )
8102  {
8103  SCIP_Real newlhs;
8104  SCIP_Real newrhs;
8105 
8106  newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8107  newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8108  if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8109  {
8110  assert(nchg < lp->nrows);
8111  ind[nchg] = row->lpipos;
8112  lhs[nchg] = newlhs;
8113  rhs[nchg] = newrhs;
8114  nchg++;
8115  row->flushedlhs = newlhs;
8116  row->flushedrhs = newrhs;
8117  }
8118  row->lhschanged = FALSE;
8119  row->rhschanged = FALSE;
8120  }
8121  }
8122  }
8123 
8124  /* change left and right hand sides in LP */
8125  if( nchg > 0 )
8126  {
8127  SCIPdebugMessage("flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8128  SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8129 
8130  /* mark the LP unsolved */
8131  lp->solved = FALSE;
8132  lp->primalfeasible = FALSE;
8133  lp->lpobjval = SCIP_INVALID;
8135  }
8136 
8137  lp->nchgrows = 0;
8138 
8139  /* free temporary memory */
8140  SCIPsetFreeBufferArray(set, &rhs);
8141  SCIPsetFreeBufferArray(set, &lhs);
8142  SCIPsetFreeBufferArray(set, &ind);
8143 
8144  return SCIP_OKAY;
8145 }
8146 
8147 /** applies all cached changes to the LP solver */
8149  SCIP_LP* lp, /**< current LP data */
8150  BMS_BLKMEM* blkmem, /**< block memory */
8151  SCIP_SET* set, /**< global SCIP settings */
8152  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8153  )
8154 {
8155  assert(lp != NULL);
8156  assert(blkmem != NULL);
8157 
8158  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",
8159  lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow,
8160  lp->ncols, lp->nrows, lp->flushed);
8161 
8162  if( !lp->flushed )
8163  {
8164  lp->flushdeletedcols = FALSE;
8165  lp->flushaddedcols = FALSE;
8166  lp->flushdeletedrows = FALSE;
8167  lp->flushaddedrows = FALSE;
8168 
8169  SCIP_CALL( lpFlushDelCols(lp) );
8170  SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8171  SCIP_CALL( lpFlushChgCols(lp, set) );
8172  SCIP_CALL( lpFlushChgRows(lp, set) );
8173  SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8174  SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8175 
8176  lp->flushed = TRUE;
8177 
8178  checkLinks(lp);
8179  }
8180 
8181  assert(lp->nlpicols == lp->ncols);
8182  assert(lp->lpifirstchgcol == lp->nlpicols);
8183  assert(lp->nlpirows == lp->nrows);
8184  assert(lp->lpifirstchgrow == lp->nlpirows);
8185  assert(lp->nchgcols == 0);
8186  assert(lp->nchgrows == 0);
8187 #ifndef NDEBUG
8188  {
8189  int ncols;
8190  int nrows;
8191 
8192  SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8193  SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8194  assert(ncols == lp->ncols);
8195  assert(nrows == lp->nrows);
8196  }
8197 #endif
8198 
8199  return SCIP_OKAY;
8200 }
8201 
8202 /** marks the LP to be flushed, even if the LP thinks it is not flushed */
8204  SCIP_LP* lp, /**< current LP data */
8205  SCIP_SET* set /**< global SCIP settings */
8206  )
8207 {
8208 #ifndef NDEBUG
8209  SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8210 #endif
8211  int i;
8212 
8213  assert(lp != NULL);
8214 
8215 #ifndef NDEBUG
8216  /* check, if there are really no column or row deletions or coefficient changes left */
8217  while( lp->lpifirstchgcol < lp->nlpicols
8218  && lp->lpifirstchgcol < lp->ncols
8219  && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8220  && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8221  {
8222  assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8223  lp->lpifirstchgcol++;
8224  }
8225  assert(lp->nlpicols == lp->lpifirstchgcol);
8226 
8227  while( lp->lpifirstchgrow < lp->nlpirows
8228  && lp->lpifirstchgrow < lp->nrows
8229  && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8230  && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8231  {
8232  assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8233  lp->lpifirstchgrow++;
8234  }
8235  assert(lp->nlpirows == lp->lpifirstchgrow);
8236 #endif
8237 
8238  lp->lpifirstchgcol = lp->nlpicols;
8239  lp->lpifirstchgrow = lp->nlpirows;
8240 
8241  /* check, if there are really no column or row additions left */
8242  assert(lp->ncols == lp->nlpicols);
8243  assert(lp->nrows == lp->nlpirows);
8244 
8245  /* mark the changed columns to be unchanged, and check, if this is really correct */
8246  for( i = 0; i < lp->nchgcols; ++i )
8247  {
8248  SCIP_COL* col;
8249 
8250  col = lp->chgcols[i];
8251  assert(col != NULL);
8252  assert(col->var != NULL);
8253  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8254  assert(SCIPvarGetCol(col->var) == col);
8255 
8256  if( col->lpipos >= 0 )
8257  {
8258 #ifndef NDEBUG
8259  /* do not check consistency of data with LPI in case of LPI=none */
8260  if( !lpinone )
8261  {
8262  SCIP_Real lpiobj;
8263  SCIP_Real lpilb;
8264  SCIP_Real lpiub;
8265 
8266  SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8267  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8268  assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8269  assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8270  assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8271  assert(col->flushedobj == col->obj); /*lint !e777*/
8272  assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8273  assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8274  }
8275 #endif
8276  col->objchanged = FALSE;
8277  col->lbchanged = FALSE;
8278  col->ubchanged = FALSE;
8279  }
8280  /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8281  }
8282  lp->nchgcols = 0;
8283 
8284  /* mark the changed rows to be unchanged, and check, if this is really correct */
8285  for( i = 0; i < lp->nchgrows; ++i )
8286  {
8287  SCIP_ROW* row;
8288 
8289  row = lp->chgrows[i];
8290  assert(row != NULL);
8291 
8292  if( row->lpipos >= 0 )
8293  {
8294 #ifndef NDEBUG
8295  /* do not check consistency of data with LPI in case of LPI=none */
8296  if( !lpinone )
8297  {
8298  SCIP_Real lpilhs;
8299  SCIP_Real lpirhs;
8300 
8301  SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8302  assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8303  assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8304  assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8305  assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8306  }
8307 #endif
8308  row->lhschanged = FALSE;
8309  row->rhschanged = FALSE;
8310  }
8311  }
8312  lp->nchgrows = 0;
8313 
8314  /* mark the LP to be flushed */
8315  lp->flushed = TRUE;
8316 
8317  checkLinks(lp);
8318 
8319  return SCIP_OKAY;
8320 }
8321 
8322 
8323 
8324 
8325 /*
8326  * LP methods
8327  */
8328 
8329 /** updates link data after addition of column */
8330 static
8332  SCIP_COL* col, /**< LP column */
8333  SCIP_SET* set /**< global SCIP settings */
8334  )
8335 {
8336  SCIP_ROW* row;
8337  int i;
8338  int pos;
8339 
8340  assert(col != NULL);
8341  assert(col->lppos >= 0);
8342 
8343  /* update column arrays of all linked rows */
8344  for( i = 0; i < col->len; ++i )
8345  {
8346  pos = col->linkpos[i];
8347  if( pos >= 0 )
8348  {
8349  row = col->rows[i];
8350  assert(row != NULL);
8351  assert(row->linkpos[pos] == i);
8352  assert(row->cols[pos] == col);
8353  assert(row->nlpcols <= pos && pos < row->len);
8354 
8355  row->nlpcols++;
8356  rowSwapCoefs(row, pos, row->nlpcols-1);
8357  assert(row->cols[row->nlpcols-1] == col);
8358 
8359  /* if no swap was necessary, mark lpcols to be unsorted */
8360  if( pos == row->nlpcols-1 )
8361  row->lpcolssorted = FALSE;
8362 
8363  /* update norms */
8364  rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8365  }
8366  }
8367 }
8368 
8369 /** updates link data after addition of row */
8370 static
8372  SCIP_ROW* row /**< LP row */
8373  )
8374 {
8375  SCIP_COL* col;
8376  int i;
8377  int pos;
8378 
8379  assert(row != NULL);
8380  assert(row->lppos >= 0);
8381 
8382  /* update row arrays of all linked columns */
8383  for( i = 0; i < row->len; ++i )
8384  {
8385  pos = row->linkpos[i];
8386  if( pos >= 0 )
8387  {
8388  col = row->cols[i];
8389  assert(col != NULL);
8390  assert(col->linkpos[pos] == i);
8391  assert(col->rows[pos] == row);
8392  assert(col->nlprows <= pos && pos < col->len);
8393 
8394  col->nlprows++;
8395  colSwapCoefs(col, pos, col->nlprows-1);
8396 
8397  /* if no swap was necessary, mark lprows to be unsorted */
8398  if( pos == col->nlprows-1 )
8399  col->lprowssorted = FALSE;
8400  }
8401  }
8402 }
8403 
8404 /** updates link data after removal of column */
8405 static
8407  SCIP_COL* col, /**< LP column */
8408  SCIP_SET* set /**< global SCIP settings */
8409  )
8410 {
8411  SCIP_ROW* row;
8412  int i;
8413  int pos;
8414 
8415  assert(col != NULL);
8416  assert(col->lppos == -1);
8417 
8418  /* update column arrays of all linked rows */
8419  for( i = 0; i < col->len; ++i )
8420  {
8421  pos = col->linkpos[i];
8422  if( pos >= 0 )
8423  {
8424  row = col->rows[i];
8425  assert(row != NULL);
8426  assert(row->linkpos[pos] == i);
8427  assert(row->cols[pos] == col);
8428  assert(0 <= pos && pos < row->nlpcols);
8429 
8430  /* update norms */
8431  rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8432 
8433  row->nlpcols--;
8434  rowSwapCoefs(row, pos, row->nlpcols);
8435 
8436  /* if no swap was necessary, mark nonlpcols to be unsorted */
8437  if( pos == row->nlpcols )
8438  row->nonlpcolssorted = FALSE;
8439  }
8440  }
8441 }
8442 
8443 /** updates link data after removal of row */
8444 static
8446  SCIP_ROW* row /**< LP row */
8447  )
8448 {
8449  SCIP_COL* col;
8450  int i;
8451  int pos;
8452 
8453  assert(row != NULL);
8454  assert(row->lppos == -1);
8455 
8456  /* update row arrays of all linked columns */
8457  for( i = 0; i < row->len; ++i )
8458  {
8459  pos = row->linkpos[i];
8460  if( pos >= 0 )
8461  {
8462  col = row->cols[i];
8463  assert(col != NULL);
8464  assert(0 <= pos && pos < col->nlprows);
8465  assert(col->linkpos[pos] == i);
8466  assert(col->rows[pos] == row);
8467 
8468  col->nlprows--;
8469  colSwapCoefs(col, pos, col->nlprows);
8470 
8471  /* if no swap was necessary, mark lprows to be unsorted */
8472  if( pos == col->nlprows )
8473  col->nonlprowssorted = FALSE;
8474  }
8475  }
8476 }
8477 
8478 static
8480  SCIP_LP* lp, /**< LP data object */
8481  int initsize /**< initial size of the arrays */
8482  )
8483 {
8484  assert(lp != NULL);
8485  assert(lp->divechgsides == NULL);
8486  assert(lp->divechgsidetypes == NULL);
8487  assert(lp->divechgrows == NULL);
8488  assert(lp->ndivechgsides == 0);
8489  assert(lp->divechgsidessize == 0);
8490  assert(initsize > 0);
8491 
8492  lp->divechgsidessize = initsize;
8496 
8497  return SCIP_OKAY;
8498 }
8499 
8500 static
8502  SCIP_LP* lp, /**< LP data object */
8503  int minsize, /**< minimal number of elements */
8504  SCIP_Real growfact /**< growing factor */
8505  )
8506 {
8507  assert(lp != NULL);
8508  assert(lp->divechgsides != NULL);
8509  assert(lp->divechgsidetypes != NULL);
8510  assert(lp->divechgrows != NULL);
8511  assert(lp->ndivechgsides > 0);
8512  assert(lp->divechgsidessize > 0);
8513  assert(minsize > 0);
8514 
8515  if( minsize <= lp->divechgsidessize )
8516  return SCIP_OKAY;
8517 
8518  lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
8522 
8523  return SCIP_OKAY;
8524 }
8525 
8526 static
8528  SCIP_LP* lp /**< LP data object */
8529  )
8530 {
8531  assert(lp != NULL);
8532  assert(lp->divechgsides != NULL);
8533  assert(lp->divechgsidetypes != NULL);
8534  assert(lp->divechgrows != NULL);
8535  assert(lp->ndivechgsides == 0);
8536  assert(lp->divechgsidessize > 0);
8537 
8541  lp->divechgsidessize = 0;
8542 }
8543 
8544 #define DIVESTACKINITSIZE 100
8545 
8546 /** creates empty LP data object */
8548  SCIP_LP** lp, /**< pointer to LP data object */
8549  SCIP_SET* set, /**< global SCIP settings */
8550  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8551  SCIP_STAT* stat, /**< problem statistics */
8552  const char* name /**< problem name */
8553  )
8554 {
8555  SCIP_Bool success;
8556 
8557  assert(lp != NULL);
8558  assert(set != NULL);
8559  assert(stat != NULL);
8560  assert(name != NULL);
8561 
8562  SCIP_ALLOC( BMSallocMemory(lp) );
8563 
8564  /* open LP Solver interface */
8565  SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
8566 
8567  (*lp)->lpicols = NULL;
8568  (*lp)->lpirows = NULL;
8569  (*lp)->chgcols = NULL;
8570  (*lp)->chgrows = NULL;
8571  (*lp)->cols = NULL;
8572  (*lp)->lazycols = NULL;
8573  (*lp)->rows = NULL;
8574  (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
8575  (*lp)->lpobjval = 0.0;
8576  (*lp)->glbpseudoobjval = 0.0;
8577  (*lp)->relglbpseudoobjval = 0.0;
8578  (*lp)->glbpseudoobjvalid = TRUE;
8579  (*lp)->glbpseudoobjvalinf = 0;
8580  (*lp)->pseudoobjval = 0.0;
8581  (*lp)->relpseudoobjval = 0.0;
8582  (*lp)->pseudoobjvalid = TRUE;
8583  (*lp)->pseudoobjvalinf = 0;
8584  (*lp)->looseobjval = 0.0;
8585  (*lp)->rellooseobjval = 0.0;
8586  (*lp)->looseobjvalid = TRUE;
8587  (*lp)->looseobjvalinf = 0;
8588  (*lp)->nloosevars = 0;
8589  (*lp)->rootlpobjval = SCIP_INVALID;
8590  (*lp)->rootlooseobjval = SCIP_INVALID;
8591  (*lp)->cutoffbound = SCIPsetInfinity(set);
8592  (*lp)->objsqrnorm = 0.0;
8593  (*lp)->objsumnorm = 0.0;
8594  (*lp)->lpicolssize = 0;
8595  (*lp)->nlpicols = 0;
8596  (*lp)->lpirowssize = 0;
8597  (*lp)->nlpirows = 0;
8598  (*lp)->lpifirstchgcol = 0;
8599  (*lp)->lpifirstchgrow = 0;
8600  (*lp)->colssize = 0;
8601  (*lp)->ncols = 0;
8602  (*lp)->lazycolssize = 0;
8603  (*lp)->nlazycols = 0;
8604  (*lp)->rowssize = 0;
8605  (*lp)->nrows = 0;
8606  (*lp)->chgcolssize = 0;
8607  (*lp)->nchgcols = 0;
8608  (*lp)->chgrowssize = 0;
8609  (*lp)->nchgrows = 0;
8610  (*lp)->firstnewcol = 0;
8611  (*lp)->firstnewrow = 0;
8612  (*lp)->nremovablecols = 0;
8613  (*lp)->nremovablerows = 0;
8614  (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
8615  (*lp)->validfarkaslp = -1;
8616  (*lp)->objsqrnormunreliable = FALSE;
8617  (*lp)->flushdeletedcols = FALSE;
8618  (*lp)->flushaddedcols = FALSE;
8619  (*lp)->flushdeletedrows = FALSE;
8620  (*lp)->flushaddedrows = FALSE;
8621  (*lp)->flushed = TRUE;
8622  (*lp)->solved = TRUE;
8623  (*lp)->primalfeasible = TRUE;
8624  (*lp)->dualfeasible = TRUE;
8625  (*lp)->solisbasic = FALSE;
8626  (*lp)->rootlpisrelax = TRUE;
8627  (*lp)->isrelax = TRUE;
8628  (*lp)->installing = FALSE;
8629  (*lp)->strongbranching = FALSE;
8630  (*lp)->strongbranchprobing = FALSE;
8631  (*lp)->probing = FALSE;
8632  (*lp)->diving = FALSE;
8633  (*lp)->divingobjchg = FALSE;
8634  (*lp)->divinglazyapplied = FALSE;
8635  (*lp)->divelpistate = NULL;
8636  (*lp)->divelpwasprimfeas = TRUE;
8637  (*lp)->divelpwasdualfeas = TRUE;
8638  (*lp)->divechgsides = NULL;
8639  (*lp)->divechgsidetypes = NULL;
8640  (*lp)->divechgrows = NULL;
8641  (*lp)->ndivechgsides = 0;
8642  (*lp)->divechgsidessize = 0;
8643  (*lp)->ndivingrows = 0;
8644  (*lp)->divinglpiitlim = INT_MAX;
8645  (*lp)->resolvelperror = FALSE;
8646  (*lp)->lpiuobjlim = SCIPlpiInfinity((*lp)->lpi);
8647  (*lp)->lpifeastol = SCIPsetLpfeastol(set);
8648  (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
8649  (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
8650  (*lp)->lpifromscratch = FALSE;
8651  (*lp)->lpifastmip = set->lp_fastmip;
8652  (*lp)->lpiscaling = set->lp_scaling;
8653  (*lp)->lpipresolving = set->lp_presolving;
8654  (*lp)->lpilpinfo = set->disp_lpinfo;
8655  (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
8656  (*lp)->lpiconditionlimit = set->lp_conditionlimit;
8657  (*lp)->lpiitlim = INT_MAX;
8658  (*lp)->lpipricing = SCIP_PRICING_AUTO;
8659  (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
8660  (*lp)->lpithreads = set->lp_threads;
8661  (*lp)->storedsolvals = NULL;
8662 
8663  /* allocate arrays for diving */
8665 
8666  /* set default parameters in LP solver */
8667  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_UOBJLIM, (*lp)->lpiuobjlim, &success) );
8668  if( !success )
8669  {
8670  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8671  "LP Solver <%s>: upper objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
8673  }
8674  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
8675  (*lp)->lpihasfeastol = success;
8676  if( !success )
8677  {
8678  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8679  "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8681  }
8682  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
8683  (*lp)->lpihasdualfeastol = success;
8684  if( !success )
8685  {
8686  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8687  "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8689  }
8690  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
8691  (*lp)->lpihasbarrierconvtol = success;
8692  if( !success )
8693  {
8694  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8695  "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
8697  }
8698  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
8699  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
8700  (*lp)->lpihasfastmip = success;
8701  if( !success )
8702  {
8703  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8704  "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
8706  }
8707  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
8708  (*lp)->lpihasscaling = success;
8709  if( !success )
8710  {
8711  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8712  "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
8714  }
8715  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
8716  (*lp)->lpihaspresolving = success;
8717  if( !success )
8718  {
8719  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8720  "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
8722  }
8723  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
8724  if( !success )
8725  {
8726  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8727  "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
8729  }
8730  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
8731  if( !success )
8732  {
8733  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8734  "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
8736  }
8737  SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
8738  if( !success )
8739  {
8740  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8741  "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
8743  }
8744  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
8745  (*lp)->lpihasrowrep = success;
8746  if( !success )
8747  {
8748  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8749  "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
8751  }
8752  SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
8753  if( !success )
8754  {
8755  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8756  "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
8758  }
8759  SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
8760  if( !success )
8761  {
8762  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
8763  "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
8765  }
8766 
8767  return SCIP_OKAY;
8768 }
8769 
8770 /** frees LP data object */
8772  SCIP_LP** lp, /**< pointer to LP data object */
8773  BMS_BLKMEM* blkmem, /**< block memory */
8774  SCIP_SET* set, /**< global SCIP settings */
8775  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8776  SCIP_EVENTFILTER* eventfilter /**< global event filter */
8777  )
8778 {
8779  int i;
8780 
8781  assert(lp != NULL);
8782  assert(*lp != NULL);
8783 
8784  SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
8785 
8786  freeDiveChgSideArrays(*lp);
8787 
8788  /* release LPI rows */
8789  for( i = 0; i < (*lp)->nlpirows; ++i )
8790  {
8791  SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
8792  }
8793 
8794  if( (*lp)->lpi != NULL )
8795  {
8796  SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
8797  }
8798 
8799  BMSfreeMemoryNull(&(*lp)->storedsolvals);
8800  BMSfreeMemoryArrayNull(&(*lp)->lpicols);
8801  BMSfreeMemoryArrayNull(&(*lp)->lpirows);
8802  BMSfreeMemoryArrayNull(&(*lp)->chgcols);
8803  BMSfreeMemoryArrayNull(&(*lp)->chgrows);
8804  BMSfreeMemoryArrayNull(&(*lp)->lazycols);
8805  BMSfreeMemoryArrayNull(&(*lp)->cols);
8806  BMSfreeMemoryArrayNull(&(*lp)->rows);
8807  BMSfreeMemory(lp);
8808 
8809  return SCIP_OKAY;
8810 }
8811 
8812 /** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
8813  * changes to the LP solver
8814  */
8816  SCIP_LP* lp, /**< LP data */
8817  BMS_BLKMEM* blkmem, /**< block memory */
8818  SCIP_SET* set, /**< global SCIP settings */
8819  SCIP_STAT* stat, /**< problem statistics */
8820  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8821  SCIP_EVENTFILTER* eventfilter /**< global event filter */
8822  )
8823 {
8824  assert(stat != NULL);
8825 
8826  SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
8827  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
8828 
8829  /* mark the empty LP to be solved */
8831  lp->lpobjval = 0.0;
8832  lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
8833  lp->validfarkaslp = -1;
8834  lp->solved = TRUE;
8835  lp->primalfeasible = TRUE;
8836  lp->dualfeasible = TRUE;
8837  lp->solisbasic = FALSE;
8839 
8840  return SCIP_OKAY;
8841 }
8842 
8843 /** adds a column to the LP */
8845  SCIP_LP* lp, /**< LP data */
8846  SCIP_SET* set, /**< global SCIP settings */
8847  SCIP_COL* col, /**< LP column */
8848  int depth /**< depth in the tree where the column addition is performed */
8849  )
8850 {
8851  assert(lp != NULL);
8852  assert(!lp->diving);
8853  assert(col != NULL);
8854  assert(col->len == 0 || col->rows != NULL);
8855  assert(col->lppos == -1);
8856  assert(col->var != NULL);
8857  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8858  assert(SCIPvarGetCol(col->var) == col);
8859  assert(SCIPvarIsIntegral(col->var) == col->integral);
8860 
8861  SCIPdebugMessage("adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
8862 #ifdef SCIP_DEBUG
8863  {
8864  int i;
8865  SCIPdebugPrintf(" (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
8866  for( i = 0; i < col->len; ++i )
8867  SCIPdebugPrintf(" %+g<%s>", col->vals[i], col->rows[i]->name);
8868  SCIPdebugPrintf("\n");
8869  }
8870 #endif
8871 
8872  SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
8873  lp->cols[lp->ncols] = col;
8874  col->lppos = lp->ncols;
8875  col->lpdepth = depth;
8876  col->age = 0;
8877  lp->ncols++;
8878  if( col->removable )
8879  lp->nremovablecols++;
8880 
8881  if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
8882  {
8883  SCIP_CALL( ensureLazycolsSize(lp, set, lp->nlazycols+1) );
8884  lp->lazycols[lp->nlazycols] = col;
8885  lp->nlazycols++;
8886  }
8887 
8888  /* mark the current LP unflushed */
8889  lp->flushed = FALSE;
8890 
8891  /* update column arrays of all linked rows */
8892  colUpdateAddLP(col, set);
8893 
8894  checkLinks(lp);
8895 
8896  return SCIP_OKAY;
8897 }
8898 
8899 /** adds a row to the LP and captures it */
8901  SCIP_LP* lp, /**< LP data */
8902  BMS_BLKMEM* blkmem, /**< block memory buffers */
8903  SCIP_SET* set, /**< global SCIP settings */
8904  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8905  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8906  SCIP_ROW* row, /**< LP row */
8907  int depth /**< depth in the tree where the row addition is performed */
8908  )
8909 {
8910  assert(lp != NULL);
8911  assert(row != NULL);
8912  assert(row->len == 0 || row->cols != NULL);
8913  assert(row->lppos == -1);
8914 
8915  SCIProwCapture(row);
8916  SCIProwLock(row);
8917 
8918  SCIPdebugMessage("adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
8919 #ifdef SCIP_DEBUG
8920  {
8921  int i;
8922  SCIPdebugPrintf(" %g <=", row->lhs);
8923  for( i = 0; i < row->len; ++i )
8924  SCIPdebugPrintf(" %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
8925  if( !SCIPsetIsZero(set, row->constant) )
8926  SCIPdebugPrintf(" %+g", row->constant);
8927  SCIPdebugPrintf(" <= %g\n", row->rhs);
8928  }
8929 #endif
8930 
8931  SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
8932  lp->rows[lp->nrows] = row;
8933  row->lppos = lp->nrows;
8934  row->lpdepth = depth;
8935  row->age = 0;
8936  lp->nrows++;
8937  if( row->removable )
8938  lp->nremovablerows++;
8939 
8940  /* mark the current LP unflushed */
8941  lp->flushed = FALSE;
8942 
8943  /* update row arrays of all linked columns */
8944  rowUpdateAddLP(row);
8945 
8946  checkLinks(lp);
8947 
8948  rowCalcNorms(row, set);
8949 
8950  /* check, if row addition to LP events are tracked
8951  * if so, issue ROWADDEDLP event
8952  */
8953  if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
8954  {
8955  SCIP_EVENT* event;
8956 
8957  SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
8958  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
8959  }
8960 
8961  return SCIP_OKAY;
8962 }
8963 
8964 
8965 #ifndef NDEBUG
8966 /** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
8967  * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
8968  * the lazycols array
8969  */
8970 static
8972  SCIP_LP* lp, /**< LP data */
8973  SCIP_SET* set /**< global SCIP settings */
8974  )
8975 {
8976  SCIP_Bool contained;
8977  int c;
8978  int i;
8979 
8980  assert(lp != NULL);
8981 
8982  /* check if each column in the lazy column array has a counter part in the column array */
8983  for( i = 0; i < lp->nlazycols; ++i )
8984  {
8985  /* check if each lazy column has at least on lazy bound */
8986  assert(lp->lazycols[i] != NULL);
8987  assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
8988 
8989  contained = FALSE;
8990  for( c = 0; c < lp->ncols; ++c )
8991  {
8992  if( lp->lazycols[i] == lp->cols[c] )
8993  {
8994  assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
8995  contained = TRUE;
8996  }
8997  }
8998  assert(contained);
8999  }
9000 
9001  /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9002  * array */
9003  for( c = 0; c < lp->ncols; ++c )
9004  {
9005  contained = FALSE;
9006  assert(lp->cols[c] != NULL);
9007 
9008  for( i = 0; i < lp->nlazycols; ++i )
9009  {
9010  if( lp->lazycols[i] == lp->cols[c] )
9011  {
9012  contained = TRUE;
9013  }
9014  }
9015 
9016  assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9017  }
9018 }
9019 #else
9020 #define checkLazyColArray(lp, set) /**/
9021 #endif
9022 
9023 /** removes all columns after the given number of cols from the LP */
9025  SCIP_LP* lp, /**< LP data */
9026  SCIP_SET* set, /**< global SCIP settings */
9027  int newncols /**< new number of columns in the LP */
9028  )
9029 {
9030  SCIP_COL* col;
9031  int c;
9032 
9033  assert(lp != NULL);
9034  SCIPdebugMessage("shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9035  assert(0 <= newncols);
9036  assert(newncols <= lp->ncols);
9037 
9038  if( newncols < lp->ncols )
9039  {
9040  assert(!lp->diving);
9041 
9042  for( c = lp->ncols-1; c >= newncols; --c )
9043  {
9044  col = lp->cols[c];
9045  assert(col != NULL);
9046  assert(col->len == 0 || col->rows != NULL);
9047  assert(col->var != NULL);
9048  assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9049  assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9050  assert(col->lppos == c);
9051 
9052  /* mark column to be removed from the LP */
9053  col->lppos = -1;
9054  col->lpdepth = -1;
9055  lp->ncols--;
9056 
9057  /* count removable columns */
9058  if( col->removable )
9059  lp->nremovablecols--;
9060 
9061  /* update column arrays of all linked rows */
9062  colUpdateDelLP(col, set);
9063  }
9064  assert(lp->ncols == newncols);
9065  lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9066 
9067  /* remove columns which are deleted from the lazy column array */
9068  c = 0;
9069  while( c < lp->nlazycols )
9070  {
9071  if( lp->lazycols[c]->lppos < 0 )
9072  {
9073  lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9074  lp->nlazycols--;
9075  }
9076  else
9077  c++;
9078  }
9079 
9080  /* mark the current LP unflushed */
9081  lp->flushed = FALSE;
9082 
9083  checkLazyColArray(lp, set);
9084  checkLinks(lp);
9085  }
9086  assert(lp->nremovablecols <= lp->ncols);
9087 
9088  return SCIP_OKAY;
9089 }
9090 
9091 /** removes and releases all rows after the given number of rows from the LP */
9093  SCIP_LP* lp, /**< LP data */
9094  BMS_BLKMEM* blkmem, /**< block memory */
9095  SCIP_SET* set, /**< global SCIP settings */
9096  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9097  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9098  int newnrows /**< new number of rows in the LP */
9099  )
9100 {
9101  SCIP_ROW* row;
9102  int r;
9103 
9104  assert(lp != NULL);
9105  assert(0 <= newnrows && newnrows <= lp->nrows);
9106 
9107  SCIPdebugMessage("shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9108  if( newnrows < lp->nrows )
9109  {
9110  for( r = lp->nrows-1; r >= newnrows; --r )
9111  {
9112  row = lp->rows[r];
9113  assert(row != NULL);
9114  assert(row->len == 0 || row->cols != NULL);
9115  assert(row->lppos == r);
9116 
9117  /* mark row to be removed from the LP */
9118  row->lppos = -1;
9119  row->lpdepth = -1;
9120  lp->nrows--;
9121 
9122  /* count removable rows */
9123  if( row->removable )
9124  lp->nremovablerows--;
9125 
9126  /* update row arrays of all linked columns */
9127  rowUpdateDelLP(row);
9128 
9129  SCIProwUnlock(lp->rows[r]);
9130 
9131  /* check, if row deletion events are tracked
9132  * if so, issue ROWDELETEDLP event
9133  */
9134  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9135  {
9136  SCIP_EVENT* event;
9137 
9138  SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9139  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9140  }
9141 
9142  SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9143  }
9144  assert(lp->nrows == newnrows);
9145  lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9146 
9147  /* mark the current LP unflushed */
9148  lp->flushed = FALSE;
9149 
9150  checkLinks(lp);
9151  }
9152  assert(lp->nremovablerows <= lp->nrows);
9153 
9154  return SCIP_OKAY;
9155 }
9156 
9157 /** removes all columns and rows from LP, releases all rows */
9159  SCIP_LP* lp, /**< LP data */
9160  BMS_BLKMEM* blkmem, /**< block memory */
9161  SCIP_SET* set, /**< global SCIP settings */
9162  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9163  SCIP_EVENTFILTER* eventfilter /**< global event filter */
9164  )
9165 {
9166  assert(lp != NULL);
9167  assert(!lp->diving);
9168 
9169  SCIPdebugMessage("clearing LP\n");
9170  SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9171  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9172 
9173  return SCIP_OKAY;
9174 }
9175 
9176 /** remembers number of columns and rows to track the newly added ones */
9178  SCIP_LP* lp /**< current LP data */
9179  )
9180 {
9181  assert(lp != NULL);
9182  assert(!lp->diving);
9183 
9184  lp->firstnewrow = lp->nrows;
9185  lp->firstnewcol = lp->ncols;
9186 }
9187 
9188 /** sets the remembered number of columns and rows to the given values */
9190  SCIP_LP* lp, /**< current LP data */
9191  int nrows, /**< number of rows to set the size marker to */
9192  int ncols /**< number of columns to set the size marker to */
9193  )
9194 {
9195  assert(lp != NULL);
9196  assert(!lp->diving);
9197 
9198  lp->firstnewrow = nrows;
9199  lp->firstnewcol = ncols;
9200 }
9201 
9202 /** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9204  SCIP_LP* lp, /**< LP data */
9205  int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9206  )
9207 {
9208  assert(lp != NULL);
9209  assert(lp->flushed);
9210  assert(lp->solved);
9211  assert(lp->solisbasic);
9212  assert(basisind != NULL);
9213 
9214  SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9215 
9216  return SCIP_OKAY;
9217 }
9218 
9219 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9221  SCIP_LP* lp, /**< LP data */
9222  int* cstat, /**< array to store column basis status, or NULL */
9223  int* rstat /**< array to store row basis status, or NULL */
9224  )
9225 {
9226  assert(lp != NULL);
9227  assert(lp->flushed);
9228  assert(lp->solved);
9229  assert(lp->solisbasic);
9230 
9231  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9232 
9233  return SCIP_OKAY;
9234 }
9235 
9236 /** gets a row from the inverse basis matrix B^-1 */
9238  SCIP_LP* lp, /**< LP data */
9239  int r, /**< row number */
9240  SCIP_Real* coef /**< pointer to store the coefficients of the row */
9241  )
9242 {
9243  assert(lp != NULL);
9244  assert(lp->flushed);
9245  assert(lp->solved);
9246  assert(lp->solisbasic);
9247  assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9248  assert(coef != NULL);
9249 
9250  SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef) );
9251 
9252  return SCIP_OKAY;
9253 }
9254 
9255 /** gets a column from the inverse basis matrix B^-1 */
9257  SCIP_LP* lp, /**< LP data */
9258  int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9259  * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9260  * to get the array which links the B^-1 column numbers to the row and
9261  * column numbers of the LP! c must be between 0 and nrows-1, since the
9262  * basis has the size nrows * nrows */
9263  SCIP_Real* coef /**< pointer to store the coefficients of the column */
9264  )
9265 {
9266  assert(lp != NULL);
9267  assert(lp->flushed);
9268  assert(lp->solved);
9269  assert(lp->solisbasic);
9270  assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9271  assert(coef != NULL);
9272 
9273  SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef) );
9274 
9275  return SCIP_OKAY;
9276 }
9277 
9278 /** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9280  SCIP_LP* lp, /**< LP data */
9281  int r, /**< row number */
9282  SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9283  SCIP_Real* coef /**< pointer to store the coefficients of the row */
9284  )
9285 {
9286  assert(lp != NULL);
9287  assert(lp->flushed);
9288  assert(lp->solved);
9289  assert(lp->solisbasic);
9290  assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9291  assert(coef != NULL);
9292 
9293  SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef) );
9294 
9295  return SCIP_OKAY;
9296 }
9297 
9298 /** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9299  * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9300  */
9302  SCIP_LP* lp, /**< LP data */
9303  int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9304  SCIP_Real* coef /**< pointer to store the coefficients of the column */
9305  )
9306 {
9307  assert(lp != NULL);
9308  assert(lp->flushed);
9309  assert(lp->solved);
9310  assert(lp->solisbasic);
9311  assert(0 <= c && c < lp->ncols);
9312  assert(coef != NULL);
9313 
9314  SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef) );
9315 
9316  return SCIP_OKAY;
9317 }
9318 
9319 /** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9320  * LP row are swapped in the summation
9321  */
9323  SCIP_LP* lp, /**< LP data */
9324  SCIP_SET* set, /**< global SCIP settings */
9325  SCIP_PROB* prob, /**< problem data */
9326  SCIP_Real* weights, /**< row weights in row summation */
9327  SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9328  SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9329  SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9330  )
9331 {
9332  SCIP_ROW* row;
9333  int r;
9334  int i;
9335  int idx;
9336  SCIP_Bool lhsinfinite;
9337  SCIP_Bool rhsinfinite;
9338 
9339  assert(lp != NULL);
9340  assert(prob != NULL);
9341  assert(weights != NULL);
9342  assert(sumcoef != NULL);
9343  assert(sumlhs != NULL);
9344  assert(sumrhs != NULL);
9345 
9346  /**@todo test, if a column based summation is faster */
9347 
9348  SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9349  SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9350  *sumlhs = 0.0;
9351  *sumrhs = 0.0;
9352  lhsinfinite = FALSE;
9353  rhsinfinite = FALSE;
9354  for( r = 0; r < lp->nrows; ++r )
9355  {
9356  if( !SCIPsetIsZero(set, weights[r]) )
9357  {
9358  row = lp->rows[r];
9359  assert(row != NULL);
9360  assert(row->len == 0 || row->cols != NULL);
9361  assert(row->len == 0 || row->cols_index != NULL);
9362  assert(row->len == 0 || row->vals != NULL);
9363 
9364  /* add the row coefficients to the sum */
9365  for( i = 0; i < row->len; ++i )
9366  {
9367  assert(row->cols[i] != NULL);
9368  assert(row->cols[i]->var != NULL);
9369  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9370  assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9371  assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9372  idx = row->cols[i]->var_probindex;
9373  assert(0 <= idx && idx < prob->nvars);
9374  SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
9375  }
9376 
9377  /* add the row sides to the sum, depending on the sign of the weight */
9378  if( weights[r] > 0.0 )
9379  {
9380  lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
9381  if( !lhsinfinite )
9382  (*sumlhs) += weights[r] * (row->lhs - row->constant);
9383  rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
9384  if( !rhsinfinite )
9385  (*sumrhs) += weights[r] * (row->rhs - row->constant);
9386  }
9387  else
9388  {
9389  lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
9390  if( !lhsinfinite )
9391  (*sumlhs) += weights[r] * (row->rhs - row->constant);
9392  rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
9393  if( !rhsinfinite )
9394  (*sumrhs) += weights[r] * (row->lhs - row->constant);
9395  }
9396  }
9397  }
9398 
9399  if( lhsinfinite )
9400  *sumlhs = -SCIPsetInfinity(set);
9401  if( rhsinfinite )
9402  *sumrhs = SCIPsetInfinity(set);
9403 
9404  return SCIP_OKAY;
9405 }
9406 
9407 /** returns the maximum absolute row weight in the given weight vector, and calculates the sparsity pattern of the weights */
9408 static
9410  SCIP_LP* lp, /**< LP data */
9411  SCIP_Real* weights, /**< row weights in row summation */
9412  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
9413  int* nrowinds, /**< pointer to store number of used rows */
9414  int* rowlensum /**< pointer to store total number of non-zeros in used rows */
9415  )
9416 {
9417  SCIP_Real maxabsweight;
9418  int r;
9419 
9420  assert(lp != NULL);
9421  assert(weights != NULL);
9422  assert(rowinds != NULL);
9423  assert(nrowinds != NULL);
9424 
9425  *nrowinds = 0;
9426  *rowlensum = 0;
9427 
9428  maxabsweight = 0.0;
9429  for( r = 0; r < lp->nrows; ++r )
9430  {
9431  SCIP_Real absweight;
9432 
9433  /* skip unused rows */
9434  if( weights[r] == 0.0 )
9435  continue;
9436 
9437  /* record the row in the sparsity pattern */
9438  rowinds[*nrowinds] = r;
9439  (*nrowinds)++;
9440 
9441  (*rowlensum) += SCIProwGetNNonz(lp->rows[r]);
9442 
9443  absweight = REALABS(weights[r]);
9444  maxabsweight = MAX(maxabsweight, absweight);
9445  }
9446 
9447  return maxabsweight;
9448 }
9449 
9450 /** adds a single row to an aggregation */
9451 static
9453  SCIP_SET* set, /**< global SCIP settings */
9454  SCIP_Real* mircoef, /**< array of aggregation coefficients: must be of size prob->nvars */
9455  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9456  int* slacksign, /**< stores the sign of the row's slack variable in summation */
9457  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
9458  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
9459  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
9460  SCIP_ROW* row, /**< row to add to the aggregation */
9461  SCIP_Real weight, /**< weight of row in aggregation */
9462  SCIP_Bool uselhs /**< TRUE if lhs should be used, FALSE if rhs should be used */
9463  )
9464 {
9465  SCIP_Real sideval;
9466  int r;
9467  int i;
9468 
9469  assert(mircoef != NULL);
9470  assert(mirrhs != NULL);
9471  assert(slacksign != NULL);
9472  assert(varused != NULL);
9473  assert(varinds != NULL);
9474  assert(nvarinds != NULL);
9475  assert(row != NULL);
9476  assert(weight != 0.0);
9477 
9478  r = row->lppos;
9479  assert(r >= 0);
9480 
9481  /* update the right hand side */
9482  if( uselhs )
9483  {
9484  slacksign[r] = -1;
9485  sideval = row->lhs - row->constant;
9486  if( row->integral )
9487  sideval = SCIPsetFeasCeil(set, sideval); /* row is integral: round left hand side up */
9488  }
9489  else
9490  {
9491  slacksign[r] = +1;
9492  sideval = row->rhs - row->constant;
9493  if( row->integral )
9494  sideval = SCIPsetFeasFloor(set, sideval); /* row is integral: round right hand side up */
9495  }
9496  (*mirrhs) += weight * sideval;
9497 
9498  /* add the row coefficients to the sum */
9499  for( i = 0; i < row->len; ++i )
9500  {
9501  int idx;
9502 
9503  assert(row->cols[i] != NULL);
9504  assert(row->cols[i]->var != NULL);
9505  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9506  assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9507  assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9508  idx = row->cols[i]->var_probindex;
9509  mircoef[idx] += weight * row->vals[i];
9510 
9511  /* record the variable in the sparsity pattern */
9512  if( !varused[idx] )
9513  {
9514  varused[idx] = TRUE;
9515  varinds[*nvarinds] = idx;
9516  (*nvarinds)++;
9517  }
9518  }
9519 }
9520 
9521 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
9522 static
9524  SCIP_SET* set, /**< global SCIP settings */
9525  SCIP_PROB* prob, /**< problem data */
9526  SCIP_LP* lp, /**< LP data */
9527  SCIP_Real* weights, /**< row weights in row summation */
9528  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
9529  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
9530  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
9531  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
9532  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
9533  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size prob->nvars */
9534  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9535  int* slacksign, /**< stores the sign of the row's slack variable in summation */
9536  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
9537  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
9538  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
9539  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
9540  int* nrowinds, /**< pointer to store number of used rows */
9541  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
9542  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
9543  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
9544  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
9545  )
9546 {
9547  SCIP_Real maxweight;
9548  int maxrank = 0;
9549  int rowlensum;
9550  int i;
9551 
9552  assert(prob != NULL);
9553  assert(lp != NULL);
9554  assert(weights != NULL);
9555  assert(!SCIPsetIsZero(set, scale));
9556  assert(maxweightrange >= 1.0);
9557  assert(mircoef != NULL);
9558  assert(mirrhs != NULL);
9559  assert(slacksign != NULL);
9560  assert(varused != NULL);
9561  assert(varinds != NULL);
9562  assert(nvarinds != NULL);
9563  assert(rowinds != NULL);
9564  assert(nrowinds != NULL);
9565  assert(emptyrow != NULL);
9566  assert(localrowsused != NULL);
9567  assert(rowtoolong != NULL);
9568 
9569  *nvarinds = 0;
9570  *nrowinds = 0;
9571  *mirrhs = 0.0;
9572  *emptyrow = TRUE;
9573  *localrowsused = FALSE;
9574  *rowtoolong = FALSE;
9575 
9576  /* initialize varused array */
9577  BMSclearMemoryArray(varused, prob->nvars);
9578 
9579  /* search the maximal absolute weight and calculate the row sparsity pattern */
9580  maxweight = getMaxAbsWeightCalcSparsity(lp, weights, rowinds, nrowinds, &rowlensum);
9581  maxweight *= ABS(scale);
9582 
9583  /* if the total number of non-zeros is way too large, we just skip this aggregation */
9584  if( rowlensum/5 > maxmksetcoefs )
9585  {
9586  *rowtoolong = TRUE;
9587  return;
9588  }
9589 
9590  /* calculate the row summation */
9591  BMSclearMemoryArray(mircoef, prob->nvars);
9592  i = 0;
9593  while( i < *nrowinds )
9594  {
9595  SCIP_ROW* row;
9596  SCIP_Real weight;
9597  SCIP_Real absweight;
9598  int r;
9599 
9600  r = rowinds[i];
9601  assert(0 <= r && r < lp->nrows);
9602  assert(weights[r] != 0.0);
9603 
9604  row = lp->rows[r];
9605  assert(row != NULL);
9606  assert(row->len == 0 || row->cols != NULL);
9607  assert(row->len == 0 || row->cols_index != NULL);
9608  assert(row->len == 0 || row->vals != NULL);
9609 
9610  /* modifiable rows cannot be part of a MIR row summation;
9611  * local rows are only included, if the allowlocal flag is set;
9612  * close to zero weights or weights outside the maximal range are ignored
9613  */
9614  weight = scale * weights[r];
9615  absweight = REALABS(weight);
9616  if( !row->modifiable && (allowlocal || !row->local)
9617  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
9618  {
9619  SCIP_Bool uselhs;
9620 
9621  /* choose sides for lhs/rhs of row */
9622  if ( sidetypes != NULL )
9623  {
9624  assert( sidetypes[r] == -1 || sidetypes[r] == 0 || sidetypes[r] == 1 );
9625  if ( sidetypes[r] == -1 )
9626  {
9627  assert( ! SCIPsetIsInfinity(set, -row->lhs) );
9628  uselhs = TRUE;
9629  }
9630  else if ( sidetypes[r] == 1 )
9631  {
9632  assert( ! SCIPsetIsInfinity(set, row->rhs) );
9633  uselhs = FALSE;
9634  }
9635  else
9636  {
9637  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
9638  * If possible, use the side that leads to a positive slack value in the summation.
9639  */
9640  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
9641  uselhs = TRUE;
9642  else
9643  uselhs = FALSE;
9644  }
9645  }
9646  else
9647  {
9648  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
9649  * If possible, use the side that leads to a positive slack value in the summation.
9650  */
9651  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
9652  uselhs = TRUE;
9653  else
9654  uselhs = FALSE;
9655  }
9656 
9657  /* add the row to the aggregation */
9658  addRowToAggregation(set, mircoef, mirrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
9659  *emptyrow = FALSE;
9660  *localrowsused = *localrowsused || row->local;
9661 
9662  SCIPdebugMessage("MIR: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
9663  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
9664  scale, weights[r], slacksign[r], *mirrhs);
9665  debugRowPrint(row);
9666 
9667  /* update the rank of the aggregation */
9668  maxrank = MAX(maxrank, row->rank);
9669 
9670  ++i; /* handle next row */
9671  }
9672  else
9673  {
9674  /* remove row from sparsity pattern, do not increase i (i-th position is filled with last entry) */
9675  rowinds[i] = rowinds[(*nrowinds)-1];
9676  (*nrowinds)--;
9677 #ifndef NDEBUG
9678  slacksign[r] = 0;
9679 #endif
9680  }
9681  }
9682 
9683  /* check if the total number of non-zeros is too large */
9684  if( *nvarinds > maxmksetcoefs )
9685  *rowtoolong = TRUE;
9686 
9687  /* set rank of the aggregated cut */
9688  if( cutrank != NULL )
9689  *cutrank = maxrank + 1;
9690 }
9691 
9692 /** removes all nearly-zero coefficients from MIR row and relaxes the right hand side correspondingly in order to
9693  * prevent numerical rounding errors
9694  */
9695 static
9697  SCIP_SET* set, /**< global SCIP settings */
9698  SCIP_PROB* prob, /**< problem data */
9699  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
9700  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9701  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
9702  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
9703  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
9704  SCIP_Bool cutislocal /**< is the cut only valid locally? */
9705  )
9706 {
9707  SCIP_Bool rhsinf;
9708  int i;
9709 
9710  assert(prob != NULL);
9711  assert(mircoef != NULL);
9712  assert(mirrhs != NULL);
9713  assert(varused != NULL);
9714  assert(varinds != NULL);
9715  assert(nvarinds != NULL);
9716 
9717  rhsinf = SCIPsetIsInfinity(set, *mirrhs);
9718  i = 0;
9719  while( i < *nvarinds )
9720  {
9721  int v;
9722 
9723  v = varinds[i];
9724  assert(0 <= v && v < prob->nvars);
9725  assert(varused[v]);
9726 
9727  if( SCIPsetIsSumZero(set, mircoef[v]) )
9728  {
9729  SCIP_Real bd;
9730 
9731  SCIPdebugMessage("coefficient of <%s> in transformed MIR row is too small: %.12f\n",
9732  SCIPvarGetName(prob->vars[v]), mircoef[v]);
9733 
9734  /* relax the constraint such that the coefficient becomes exactly 0.0 */
9735  if( SCIPsetIsPositive(set, mircoef[v]) )
9736  {
9737  bd = cutislocal ? SCIPvarGetLbLocal(prob->vars[v]) : SCIPvarGetLbGlobal(prob->vars[v]);
9738  rhsinf = SCIPsetIsInfinity(set, -bd);
9739  }
9740  else if( SCIPsetIsNegative(set, mircoef[v]) )
9741  {
9742  bd = cutislocal ? SCIPvarGetUbLocal(prob->vars[v]) : SCIPvarGetUbGlobal(prob->vars[v]);
9743  rhsinf = SCIPsetIsInfinity(set, bd);
9744  }
9745  else
9746  bd = 0.0;
9747  *mirrhs -= bd * mircoef[v];
9748  mircoef[v] = 0.0;
9749 
9750  /* remove variable from sparsity pattern, do not increase i (i-th position is filled with last entry) */
9751  varused[v] = FALSE;
9752  varinds[i] = varinds[(*nvarinds)-1];
9753  (*nvarinds)--;
9754  }
9755  else
9756  ++i;
9757  }
9758  if( rhsinf )
9759  *mirrhs = SCIPsetInfinity(set);
9760 }
9761 
9762 /** finds the best lower bound of the variable to use for MIR transformation */
9763 static
9765  SCIP_SET* set, /**< global SCIP settings */
9766  SCIP_STAT* stat, /**< problem statistics */
9767  SCIP_VAR* var, /**< problem variable */
9768  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
9769  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
9770  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
9771  SCIP_Real* bestlb, /**< pointer to store best bound value */
9772  int* bestlbtype /**< pointer to store best bound type */
9773  )
9774 {
9775  assert(bestlb != NULL);
9776  assert(bestlbtype != NULL);
9777 
9778  *bestlb = SCIPvarGetLbGlobal(var);
9779  *bestlbtype = -1;
9780 
9781  if( allowlocal )
9782  {
9783  SCIP_Real loclb;
9784 
9785  loclb = SCIPvarGetLbLocal(var);
9786  if( SCIPsetIsGT(set, loclb, *bestlb) )
9787  {
9788  *bestlb = loclb;
9789  *bestlbtype = -2;
9790  }
9791  }
9792  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
9793  {
9794  SCIP_Real bestvlb;
9795  int bestvlbidx;
9796 
9797  SCIPvarGetClosestVlb(var, sol, set, stat, &bestvlb, &bestvlbidx);
9798  if( bestvlbidx >= 0
9799  && (bestvlb > *bestlb || (*bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, *bestlb))) )
9800  {
9801  SCIP_VAR** vlbvars;
9802 
9803  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
9804  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
9805  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
9806  */
9807  vlbvars = SCIPvarGetVlbVars(var);
9808  assert(vlbvars != NULL);
9809  if( SCIPvarGetProbindex(vlbvars[bestvlbidx]) < SCIPvarGetProbindex(var) )
9810  {
9811  *bestlb = bestvlb;
9812  *bestlbtype = bestvlbidx;
9813  }
9814  }
9815  }
9816 }
9817 
9818 /** finds the best upper bound of the variable to use for MIR transformation */
9819 static
9821  SCIP_SET* set, /**< global SCIP settings */
9822  SCIP_STAT* stat, /**< problem statistics */
9823  SCIP_VAR* var, /**< problem variable */
9824  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
9825  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
9826  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
9827  SCIP_Real* bestub, /**< pointer to store best bound value */
9828  int* bestubtype /**< pointer to store best bound type */
9829  )
9830 {
9831  assert(bestub != NULL);
9832  assert(bestubtype != NULL);
9833 
9834  *bestub = SCIPvarGetUbGlobal(var);
9835  *bestubtype = -1;
9836  if( allowlocal )
9837  {
9838  SCIP_Real locub;
9839 
9840  locub = SCIPvarGetUbLocal(var);
9841  if( SCIPsetIsLT(set, locub, *bestub) )
9842  {
9843  *bestub = locub;
9844  *bestubtype = -2;
9845  }
9846  }
9847  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
9848  {
9849  SCIP_Real bestvub;
9850  int bestvubidx;
9851 
9852  SCIPvarGetClosestVub(var, sol, set, stat, &bestvub, &bestvubidx);
9853  if( bestvubidx >= 0
9854  && (bestvub < *bestub || (*bestubtype < 0 && SCIPsetIsLE(set, bestvub, *bestub))) )
9855  {
9856  SCIP_VAR** vubvars;
9857 
9858  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
9859  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
9860  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
9861  */
9862  vubvars = SCIPvarGetVubVars(var);
9863  assert(vubvars != NULL);
9864  if( SCIPvarGetProbindex(vubvars[bestvubidx]) < SCIPvarGetProbindex(var) )
9865  {
9866  *bestub = bestvub;
9867  *bestubtype = bestvubidx;
9868  }
9869  }
9870  }
9871 }
9872 
9873 /** Transform equation \f$ a \cdot x = b; lb \leq x \leq ub \f$ into standard form
9874  * \f$ a^\prime \cdot x^\prime = b,\; 0 \leq x^\prime \leq ub' \f$.
9875  *
9876  * Transform variables (lb or ub):
9877  * \f[
9878  * \begin{array}{llll}
9879  * 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}\\
9880  * 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}
9881  * \end{array}
9882  * \f]
9883  * and move the constant terms \f$ a_j\, lb_j \f$ or \f$ a_j\, ub_j \f$ to the rhs.
9884  *
9885  * Transform variables (vlb or vub):
9886  * \f[
9887  * \begin{array}{llll}
9888  * 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.} \\
9889  * 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.}
9890  * \end{array}
9891  * \f]
9892  * 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:
9893  * \f[
9894  * \begin{array}{ll}
9895  * a_{zl_j} := a_{zl_j} + a_j\, bl_j,& \mbox{or} \\
9896  * a_{zu_j} := a_{zu_j} + a_j\, bu_j &
9897  * \end{array}
9898  * \f]
9899  */
9900 static
9902  SCIP_SET* set, /**< global SCIP settings */
9903  SCIP_STAT* stat, /**< problem statistics */
9904  SCIP_PROB* prob, /**< problem data */
9905  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
9906  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
9907  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
9908  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
9909  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
9910  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
9911  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
9912  * NULL for using closest bound for all variables */
9913  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
9914  * NULL for using closest bound for all variables */
9915  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
9916  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
9917  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
9918  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
9919  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
9920  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
9921  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
9922  int* varsign, /**< stores the sign of the transformed variable in summation */
9923  int* boundtype, /**< stores the bound used for transformed variable:
9924  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
9925  SCIP_Bool* freevariable, /**< stores whether a free variable was found in MIR row -> invalid summation */
9926  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
9927  )
9928 {
9929  SCIP_Real* bestlbs;
9930  SCIP_Real* bestubs;
9931  int* bestlbtypes;
9932  int* bestubtypes;
9933  int i;
9934 
9935  assert(prob != NULL);
9936  assert(mircoef != NULL);
9937  assert(mirrhs != NULL);
9938  assert(varused != NULL);
9939  assert(varinds != NULL);
9940  assert(nvarinds != NULL);
9941  assert(varsign != NULL);
9942  assert(boundtype != NULL);
9943  assert(freevariable != NULL);
9944  assert(localbdsused != NULL);
9945 
9946  *freevariable = FALSE;
9947  *localbdsused = FALSE;
9948 
9949 #ifndef NDEBUG
9950  /* in debug mode, make sure that the whole array is initialized with invalid values */
9951  for( i = 0; i < prob->nvars; i++ )
9952  {
9953  varsign[i] = 0;
9954  boundtype[i] = -1;
9955  }
9956 #endif
9957 
9958  /* allocate temporary memory to store best bounds and bound types */
9959  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbs, prob->nvars) );
9960  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubs, prob->nvars) );
9961  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbtypes, prob->nvars) );
9962  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubtypes, prob->nvars) );
9963 
9964  /* start with continuous variables, because using variable bounds can affect the untransformed integral
9965  * variables, and these changes have to be incorporated in the transformation of the integral variables
9966  * (continuous variables have largest problem indices!)
9967  */
9968  SCIPsortDownInt(varinds, *nvarinds);
9969 
9970  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
9971  * substitute integral variables with best standard bound (lb, ub)
9972  */
9973  i = 0;
9974  while( i < *nvarinds )
9975  {
9976  SCIP_VAR* var;
9977  SCIP_Real bestlb;
9978  SCIP_Real bestub;
9979  SCIP_Bool uselb;
9980  int bestlbtype;
9981  int bestubtype;
9982  int v;
9983 
9984  v = varinds[i];
9985  assert(0 <= v && v < prob->nvars);
9986  assert(varused[v]);
9987 
9988  var = prob->vars[v];
9989  assert(v == SCIPvarGetProbindex(var));
9990 
9991  /* due to variable bound usage cancellation may occur,
9992  * do not increase i, since last element is copied to the i-th position
9993  */
9994  if( SCIPsetIsZero(set, mircoef[v]) )
9995  {
9996  varsign[v] = +1;
9997  boundtype[v] = -1;
9998  mircoef[v] = 0.0;
9999  varused[v] = FALSE;
10000  varinds[i] = varinds[(*nvarinds)-1];
10001  (*nvarinds)--;
10002  continue;
10003  }
10004 
10005  /* check if the user specified a bound to be used */
10006  if( boundsfortrans != NULL && boundsfortrans[v] > -3 )
10007  {
10008  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || ( boundsfortrans[v] == -2 || boundsfortrans[v] == -1 ));
10009 
10010  /* user has explicitly specified a bound to be used */
10011  if( boundtypesfortrans[v] == SCIP_BOUNDTYPE_LOWER )
10012  {
10013  /* user wants to use lower bound */
10014  bestlbtype = boundsfortrans[v];
10015  if( bestlbtype == -1 )
10016  bestlb = SCIPvarGetLbGlobal(var); /* use global standard lower bound */
10017  else if( bestlbtype == -2 )
10018  bestlb = SCIPvarGetLbLocal(var); /* use local standard lower bound */
10019  else
10020  {
10021  SCIP_VAR** vlbvars;
10022  SCIP_Real* vlbcoefs;
10023  SCIP_Real* vlbconsts;
10024  int k;
10025 
10026  /* use the given variable lower bound */
10027  vlbvars = SCIPvarGetVlbVars(var);
10028  vlbcoefs = SCIPvarGetVlbCoefs(var);
10029  vlbconsts = SCIPvarGetVlbConstants(var);
10030  k = boundsfortrans[v];
10031  assert(k >= 0 && k < SCIPvarGetNVlbs(var));
10032  assert(vlbvars != NULL);
10033  assert(vlbcoefs != NULL);
10034  assert(vlbconsts != NULL);
10035 
10036  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10037  if( SCIPvarGetProbindex(vlbvars[k]) < v )
10038  bestlb = vlbcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[k]) : SCIPsolGetVal(sol, set, stat, vlbvars[k])) + vlbconsts[k];
10039  else
10040  {
10041  bestlbtype = -1; /* fall back to global standard bound */
10042  bestlb = SCIPvarGetLbGlobal(var);
10043  }
10044  }
10045 
10046  assert(!SCIPsetIsInfinity(set, -bestlb));
10047  uselb = TRUE;
10048 
10049  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
10050  findBestUb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestub, &bestubtype);
10051  }
10052  else
10053  {
10054  assert(boundtypesfortrans[v] == SCIP_BOUNDTYPE_UPPER);
10055 
10056  /* user wants to use upper bound */
10057  bestubtype = boundsfortrans[v];
10058  if( bestubtype == -1 )
10059  bestub = SCIPvarGetUbGlobal(var); /* use global standard upper bound */
10060  else if( bestubtype == -2 )
10061  bestub = SCIPvarGetUbLocal(var); /* use local standard upper bound */
10062  else
10063  {
10064  SCIP_VAR** vubvars;
10065  SCIP_Real* vubcoefs;
10066  SCIP_Real* vubconsts;
10067  int k;
10068 
10069  /* use the given variable upper bound */
10070  vubvars = SCIPvarGetVubVars(var);
10071  vubcoefs = SCIPvarGetVubCoefs(var);
10072  vubconsts = SCIPvarGetVubConstants(var);
10073  k = boundsfortrans[v];
10074  assert(k >= 0 && k < SCIPvarGetNVubs(var));
10075  assert(vubvars != NULL);
10076  assert(vubcoefs != NULL);
10077  assert(vubconsts != NULL);
10078 
10079  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
10080  if( SCIPvarGetProbindex(vubvars[k]) < v )
10081  bestub = vubcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vubvars[k]) : SCIPsolGetVal(sol, set, stat, vubvars[k])) + vubconsts[k];
10082  else
10083  {
10084  bestubtype = -1; /* fall back to global standard bound */
10085  bestub = SCIPvarGetUbGlobal(var);
10086  }
10087  }
10088 
10089  assert(!SCIPsetIsInfinity(set, bestub));
10090  uselb = FALSE;
10091 
10092  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
10093  findBestLb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestlb, &bestlbtype);
10094  }
10095  }
10096  else
10097  {
10098  SCIP_Real varsol;
10099 
10100  /* bound selection should be done automatically */
10101 
10102  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
10103  findBestLb(set, stat, var, sol, usevbds, allowlocal, &bestlb, &bestlbtype);
10104 
10105  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
10106  findBestUb(set, stat, var, sol, usevbds, allowlocal, &bestub, &bestubtype);
10107 
10108  /* check, if variable is free variable */
10109  if( SCIPsetIsInfinity(set, -bestlb) && SCIPsetIsInfinity(set, bestub) )
10110  {
10111  /* we found a free variable in the row with non-zero coefficient
10112  * -> MIR row can't be transformed in standard form
10113  */
10114  *freevariable = TRUE;
10115  goto TERMINATE;
10116  }
10117 
10118  /* select transformation bound */
10119  varsol = (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var));
10120  if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
10121  uselb = TRUE;
10122  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
10123  uselb = FALSE;
10124  else if( bestlbtype == -1 ) /* prefer global standard bounds */
10125  uselb = TRUE;
10126  else if( bestubtype == -1 ) /* prefer global standard bounds */
10127  uselb = FALSE;
10128  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
10129  uselb = TRUE;
10130  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
10131  uselb = FALSE;
10132  else
10133  uselb = TRUE; /* no decision yet? just use lower bound */
10134  }
10135 
10136  /* remember given/best bounds and types */
10137  bestlbs[v] = bestlb;
10138  bestubs[v] = bestub;
10139  bestlbtypes[v] = bestlbtype;
10140  bestubtypes[v] = bestubtype;
10141 
10142  /* perform bound substitution */
10143  if( uselb )
10144  {
10145  assert(!SCIPsetIsInfinity(set, -bestlb));
10146 
10147  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
10148  boundtype[v] = bestlbtype;
10149  varsign[v] = +1;
10150 
10151  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
10152  if( bestlbtype < 0 )
10153  {
10154  (*mirrhs) -= mircoef[v] * bestlb;
10155  *localbdsused = *localbdsused || (bestlbtype == -2);
10156  }
10157  else
10158  {
10159  SCIP_VAR** vlbvars;
10160  SCIP_Real* vlbcoefs;
10161  SCIP_Real* vlbconsts;
10162  int zidx;
10163 
10164  vlbvars = SCIPvarGetVlbVars(var);
10165  vlbcoefs = SCIPvarGetVlbCoefs(var);
10166  vlbconsts = SCIPvarGetVlbConstants(var);
10167  assert(vlbvars != NULL);
10168  assert(vlbcoefs != NULL);
10169  assert(vlbconsts != NULL);
10170 
10171  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
10172  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
10173  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
10174  assert(0 <= zidx && zidx < v);
10175 
10176  (*mirrhs) -= mircoef[v] * vlbconsts[bestlbtype];
10177  mircoef[zidx] += mircoef[v] * vlbcoefs[bestlbtype];
10178 
10179  /* update sparsity pattern */
10180  if( !varused[zidx] )
10181  {
10182  assert(*nvarinds < prob->nvars);
10183  varused[zidx] = TRUE;
10184  varinds[*nvarinds] = zidx;
10185  (*nvarinds)++;
10186  }
10187  }
10188  }
10189  else
10190  {
10191  assert(!SCIPsetIsInfinity(set, bestub));
10192 
10193  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
10194  boundtype[v] = bestubtype;
10195  varsign[v] = -1;
10196 
10197  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
10198  if( bestubtype < 0 )
10199  {
10200  (*mirrhs) -= mircoef[v] * bestub;
10201  *localbdsused = *localbdsused || (bestubtype == -2);
10202  }
10203  else
10204  {
10205  SCIP_VAR** vubvars;
10206  SCIP_Real* vubcoefs;
10207  SCIP_Real* vubconsts;
10208  int zidx;
10209 
10210  vubvars = SCIPvarGetVubVars(var);
10211  vubcoefs = SCIPvarGetVubCoefs(var);
10212  vubconsts = SCIPvarGetVubConstants(var);
10213  assert(vubvars != NULL);
10214  assert(vubcoefs != NULL);
10215  assert(vubconsts != NULL);
10216 
10217  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
10218  assert(SCIPvarIsActive(vubvars[bestubtype]));
10219  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
10220  assert(zidx >= 0);
10221 
10222  (*mirrhs) -= mircoef[v] * vubconsts[bestubtype];
10223  mircoef[zidx] += mircoef[v] * vubcoefs[bestubtype];
10224 
10225  /* update sparsity pattern */
10226  if( !varused[zidx] )
10227  {
10228  assert(*nvarinds < prob->nvars);
10229  varused[zidx] = TRUE;
10230  varinds[*nvarinds] = zidx;
10231  (*nvarinds)++;
10232  }
10233  }
10234  }
10235  ++i; /* increase iterator */
10236 
10237 #ifdef SCIP_DEBUG
10238  if( bestlbtype >= 0 )
10239  {
10240  assert(bestlbtype < SCIPvarGetNVlbs(var));
10241  assert(SCIPvarGetVlbVars(var) != NULL);
10242  assert(SCIPvarGetVlbCoefs(var) != NULL);
10243  assert(SCIPvarGetVlbConstants(var) != NULL);
10244  }
10245  if( bestubtype >= 0 )
10246  {
10247  assert(bestubtype < SCIPvarGetNVubs(var));
10248  assert(SCIPvarGetVubVars(var) != NULL);
10249  assert(SCIPvarGetVubCoefs(var) != NULL);
10250  assert(SCIPvarGetVubConstants(var) != NULL);
10251  }
10252 
10253  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",
10254  SCIPvarGetName(var), varsign[v], boundtype[v], mircoef[v],
10256  (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var)), bestlb, bestub,
10257  bestlbtype >= 0 ? SCIPvarGetVlbCoefs(var)[bestlbtype] : 0.0,
10258  bestlbtype >= 0 ? SCIPvarGetName(SCIPvarGetVlbVars(var)[bestlbtype]) : "-",
10259  bestlbtype >= 0 ? SCIPvarGetVlbConstants(var)[bestlbtype] : bestlb,
10260  bestubtype >= 0 ? SCIPvarGetVubCoefs(var)[bestubtype] : 0.0,
10261  bestubtype >= 0 ? SCIPvarGetName(SCIPvarGetVubVars(var)[bestubtype]) : "-",
10262  bestubtype >= 0 ? SCIPvarGetVubConstants(var)[bestubtype] : bestub,
10263  *mirrhs);
10264 #endif
10265  }
10266 
10267  if( fixintegralrhs )
10268  {
10269  SCIP_Real f0;
10270 
10271  /* check if rhs is fractional */
10272  f0 = SCIPsetSumFrac(set, *mirrhs);
10273  if( f0 < minfrac || f0 > maxfrac )
10274  {
10275  SCIP_Real bestviolgain;
10276  SCIP_Real bestnewf0;
10277  int bestv;
10278 
10279  /* choose complementation of one variable differently such that f0 is in correct range */
10280  bestv = -1;
10281  bestviolgain = -1e+100;
10282  bestnewf0 = 1.0;
10283  for( i = 0; i < *nvarinds; i++ )
10284  {
10285  int v;
10286 
10287  v = varinds[i];
10288  assert(0 <= v && v < prob->nvars);
10289  assert(varused[v]);
10290  assert(!SCIPsetIsZero(set, mircoef[v]));
10291 
10292  if( boundtype[v] < 0
10293  && ((varsign[v] == +1 && !SCIPsetIsInfinity(set, bestubs[v]) && bestubtypes[v] < 0)
10294  || (varsign[v] == -1 && !SCIPsetIsInfinity(set, -bestlbs[v]) && bestlbtypes[v] < 0)) )
10295  {
10296  SCIP_Real fj;
10297  SCIP_Real newfj;
10298  SCIP_Real newrhs;
10299  SCIP_Real newf0;
10300  SCIP_Real solval;
10301  SCIP_Real viol;
10302  SCIP_Real newviol;
10303  SCIP_Real violgain;
10304 
10305  /* currently: a'_j = varsign * a_j -> f'_j = a'_j - floor(a'_j)
10306  * after complementation: a''_j = -varsign * a_j -> f''_j = a''_j - floor(a''_j) = 1 - f'_j
10307  * rhs'' = rhs' + varsign * a_j * (lb_j - ub_j)
10308  * cut violation from f0 and fj: f'_0 - f'_j * x'_j
10309  * after complementation: f''_0 - f''_j * x''_j
10310  *
10311  * for continuous variables, we just set f'_j = f''_j = |a'_j|
10312  */
10313  newrhs = *mirrhs + varsign[v] * mircoef[v] * (bestlbs[v] - bestubs[v]);
10314  newf0 = SCIPsetSumFrac(set, newrhs);
10315  if( newf0 < minfrac || newf0 > maxfrac )
10316  continue;
10317  if( SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10318  {
10319  fj = REALABS(mircoef[v]);
10320  newfj = fj;
10321  }
10322  else
10323  {
10324  fj = SCIPsetFrac(set, varsign[v] * mircoef[v]);
10325  newfj = SCIPsetFrac(set, -varsign[v] * mircoef[v]);
10326  }
10327 
10328  solval = (sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
10329  viol = f0 - fj * (varsign[v] == +1 ? solval - bestlbs[v] : bestubs[v] - solval);
10330  newviol = newf0 - newfj * (varsign[v] == -1 ? solval - bestlbs[v] : bestubs[v] - solval);
10331  violgain = newviol - viol;
10332 
10333  /* prefer larger violations; for equal violations, prefer smaller f0 values since then the possibility that
10334  * we f_j > f_0 is larger and we may improve some coefficients in rounding
10335  */
10336  if( SCIPsetIsGT(set, violgain, bestviolgain)
10337  || (SCIPsetIsGE(set, violgain, bestviolgain) && newf0 < bestnewf0) )
10338  {
10339  bestv = v;
10340  bestviolgain = violgain;
10341  bestnewf0 = newf0;
10342  }
10343  }
10344  }
10345 
10346  if( bestv >= 0 )
10347  {
10348  assert(bestv < prob->nvars);
10349  assert(boundtype[bestv] < 0);
10350  assert(!SCIPsetIsInfinity(set, -bestlbs[bestv]));
10351  assert(!SCIPsetIsInfinity(set, bestubs[bestv]));
10352 
10353  /* switch the complementation of this variable */
10354  (*mirrhs) += varsign[bestv] * mircoef[bestv] * (bestlbs[bestv] - bestubs[bestv]);
10355  if( varsign[bestv] == +1 )
10356  {
10357  /* switch to upper bound */
10358  assert(bestubtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
10359  boundtype[bestv] = bestubtypes[bestv];
10360  varsign[bestv] = -1;
10361  }
10362  else
10363  {
10364  /* switch to lower bound */
10365  assert(bestlbtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
10366  boundtype[bestv] = bestlbtypes[bestv];
10367  varsign[bestv] = +1;
10368  }
10369  *localbdsused = *localbdsused || (boundtype[bestv] == -2);
10370  }
10371  }
10372  }
10373 
10374  TERMINATE:
10375 
10376  /*free temporary memory */
10377  SCIPsetFreeBufferArray(set, &bestubtypes);
10378  SCIPsetFreeBufferArray(set, &bestlbtypes);
10379  SCIPsetFreeBufferArray(set, &bestubs);
10380  SCIPsetFreeBufferArray(set, &bestlbs);
10381 
10382  return SCIP_OKAY;
10383 }
10384 
10385 /** 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$
10386  * \f[
10387  * \begin{array}{rll}
10388  * integers :& \tilde{a}_j = down(a^\prime_j), & if \qquad f_j \leq f_0 \\
10389  * & \tilde{a}_j = down(a^\prime_j) + (f_j - f_0)/(1 - f_0),& if \qquad f_j > f_0 \\
10390  * continuous:& \tilde{a}_j = 0, & if \qquad a^\prime_j \geq 0 \\
10391  * & \tilde{a}_j = a^\prime_j/(1 - f_0), & if \qquad a^\prime_j < 0
10392  * \end{array}
10393  * \f]
10394  *
10395  * Transform inequality back to \f$ \hat{a} \cdot x \leq rhs \f$:
10396  *
10397  * (lb or ub):
10398  * \f[
10399  * \begin{array}{lllll}
10400  * 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} \\
10401  * 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}
10402  * \end{array}
10403  * \f]
10404  * and move the constant terms
10405  * \f[
10406  * \begin{array}{cl}
10407  * -\tilde{a}_j \cdot lb_j = -\hat{a}_j \cdot lb_j,& \mbox{or} \\
10408  * \tilde{a}_j \cdot ub_j = -\hat{a}_j \cdot ub_j &
10409  * \end{array}
10410  * \f]
10411  * to the rhs.
10412  *
10413  * (vlb or vub):
10414  * \f[
10415  * \begin{array}{lllll}
10416  * 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)} \\
10417  * 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)}
10418  * \end{array}
10419  * \f]
10420  * move the constant terms
10421  * \f[
10422  * \begin{array}{cl}
10423  * -\tilde{a}_j\, dl_j = -\hat{a}_j\, dl_j,& \mbox{or} \\
10424  * \tilde{a}_j\, du_j = -\hat{a}_j\, du_j &
10425  * \end{array}
10426  * \f]
10427  * to the rhs, and update the VB variable coefficients:
10428  * \f[
10429  * \begin{array}{ll}
10430  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j\, bl_j = \hat{a}_{zl_j} - \hat{a}_j\, bl_j,& \mbox{or} \\
10431  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j\, bu_j = \hat{a}_{zu_j} - \hat{a}_j\, bu_j &
10432  * \end{array}
10433  * \f]
10434  */
10435 static
10437  SCIP_SET* set, /**< global SCIP settings */
10438  SCIP_PROB* prob, /**< problem data */
10439  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10440  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10441  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
10442  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10443  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
10444  int* varsign, /**< stores the sign of the transformed variable in summation */
10445  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub)*/
10446  SCIP_Real f0 /**< fractional value of rhs */
10447  )
10448 {
10449  SCIP_Real onedivoneminusf0;
10450  int i;
10451 
10452  assert(prob != NULL);
10453  assert(mircoef != NULL);
10454  assert(mirrhs != NULL);
10455  assert(varused != NULL);
10456  assert(varinds != NULL);
10457  assert(nvarinds != NULL);
10458  assert(varsign != NULL);
10459  assert(0.0 < f0 && f0 < 1.0);
10460 
10461  onedivoneminusf0 = 1.0 / (1.0 - f0);
10462 
10463  /* Loop backwards to be able to delete coefficients from the sparsity pattern. Additionally, the variable bound
10464  * substitutions are only used in such a way that a variable of higher index is substituted by a variable of a
10465  * lower index. Therefore, we must loop backwards.
10466  */
10467  SCIPsortDownInt(varinds, *nvarinds);
10468 
10469  for( i = *nvarinds-1; i >= 0; i-- )
10470  {
10471  SCIP_VAR* var;
10472  SCIP_Real cutaj;
10473  int v;
10474 
10475  v = varinds[i];
10476  assert(0 <= v && v < prob->nvars);
10477  assert(varused[v]);
10478 
10479  var = prob->vars[v];
10480  assert(var != NULL);
10481  assert(SCIPvarGetProbindex(var) == v);
10482  assert(varsign[v] == +1 || varsign[v] == -1);
10483 
10484  /* calculate the coefficient in the retransformed cut */
10485  if( SCIPvarIsIntegral(var) )
10486  {
10487  SCIP_Real aj;
10488  SCIP_Real downaj;
10489  SCIP_Real fj;
10490 
10491  aj = varsign[v] * mircoef[v]; /* a'_j */
10492  downaj = SCIPsetFloor(set, aj);
10493  fj = aj - downaj;
10494 
10495  if( SCIPsetIsSumLE(set, fj, f0) )
10496  cutaj = varsign[v] * downaj; /* a^_j */
10497  else
10498  cutaj = varsign[v] * (downaj + (fj - f0) * onedivoneminusf0); /* a^_j */
10499  }
10500  else
10501  {
10502  SCIP_Real aj;
10503 
10504  aj = varsign[v] * mircoef[v]; /* a'_j */
10505  if( aj >= 0.0 )
10506  cutaj = 0.0;
10507  else
10508  cutaj = varsign[v] * aj * onedivoneminusf0; /* a^_j */
10509  }
10510 
10511  /* remove zero cut coefficients from sparsity pattern */
10512  if( SCIPsetIsZero(set, cutaj) )
10513  {
10514  mircoef[v] = 0.0;
10515  varused[v] = FALSE;
10516  varinds[i] = varinds[(*nvarinds)-1];
10517  (*nvarinds)--;
10518  continue;
10519  }
10520 
10521  mircoef[v] = cutaj;
10522 
10523  /* check for variable bound use */
10524  if( boundtype[v] < 0 )
10525  {
10526  /* standard bound */
10527 
10528  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
10529  if( varsign[v] == +1 )
10530  {
10531  /* lower bound was used */
10532  if( boundtype[v] == -1 )
10533  {
10534  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
10535  (*mirrhs) += cutaj * SCIPvarGetLbGlobal(var);
10536  }
10537  else
10538  {
10539  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
10540  (*mirrhs) += cutaj * SCIPvarGetLbLocal(var);
10541  }
10542  }
10543  else
10544  {
10545  /* upper bound was used */
10546  if( boundtype[v] == -1 )
10547  {
10548  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
10549  (*mirrhs) += cutaj * SCIPvarGetUbGlobal(var);
10550  }
10551  else
10552  {
10553  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
10554  (*mirrhs) += cutaj * SCIPvarGetUbLocal(var);
10555  }
10556  }
10557  }
10558  else
10559  {
10560  SCIP_VAR** vbz;
10561  SCIP_Real* vbb;
10562  SCIP_Real* vbd;
10563  int vbidx;
10564  int zidx;
10565 
10566  /* variable bound */
10567  vbidx = boundtype[v];
10568 
10569  /* change mirrhs and cutaj of integer variable z_j of variable bound */
10570  if( varsign[v] == +1 )
10571  {
10572  /* variable lower bound was used */
10573  assert(0 <= vbidx && vbidx < SCIPvarGetNVlbs(var));
10574  vbz = SCIPvarGetVlbVars(var);
10575  vbb = SCIPvarGetVlbCoefs(var);
10576  vbd = SCIPvarGetVlbConstants(var);
10577  }
10578  else
10579  {
10580  /* variable upper bound was used */
10581  assert(0 <= vbidx && vbidx < SCIPvarGetNVubs(var));
10582  vbz = SCIPvarGetVubVars(var);
10583  vbb = SCIPvarGetVubCoefs(var);
10584  vbd = SCIPvarGetVubConstants(var);
10585  }
10586  assert(SCIPvarIsActive(vbz[vbidx]));
10587  zidx = SCIPvarGetProbindex(vbz[vbidx]);
10588  assert(0 <= zidx && zidx < v);
10589 
10590  (*mirrhs) += cutaj * vbd[vbidx];
10591  mircoef[zidx] -= cutaj * vbb[vbidx];
10592 
10593  /* add variable to sparsity pattern */
10594  if( !varused[zidx] )
10595  {
10596  assert(*nvarinds < prob->nvars);
10597  varused[zidx] = TRUE;
10598  varinds[*nvarinds] = zidx;
10599  (*nvarinds)++;
10600  }
10601  }
10602  }
10603 }
10604 
10605 /** substitute aggregated slack variables:
10606  *
10607  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
10608  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r]. \f$
10609  *
10610  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
10611  * \f[
10612  * \begin{array}{rll}
10613  * integers : & \hat{a}_r = \tilde{a}_r = down(a^\prime_r), & \mbox{if}\qquad f_r <= f0 \\
10614  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + (f_r - f0)/(1 - f0),& \mbox{if}\qquad f_r > f0 \\
10615  * continuous:& \hat{a}_r = \tilde{a}_r = 0, & \mbox{if}\qquad a^\prime_r >= 0 \\
10616  * & \hat{a}_r = \tilde{a}_r = a^\prime_r/(1 - f0), & \mbox{if}\qquad a^\prime_r < 0
10617  * \end{array}
10618  * \f]
10619  *
10620  * Substitute \f$ \hat{a}_r \cdot s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
10621  */
10622 static
10624  SCIP_SET* set, /**< global SCIP settings */
10625  SCIP_STAT* stat, /**< problem statistics */
10626  SCIP_LP* lp, /**< LP data */
10627  SCIP_Real* weights, /**< row weights in row summation */
10628  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
10629  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10630  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10631  int* slacksign, /**< stores the sign of the row's slack variable in summation */
10632  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
10633  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10634  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
10635  int* rowinds, /**< sparsity pattern of used rows */
10636  int nrowinds, /**< number of used rows */
10637  SCIP_Real f0 /**< fractional value of rhs */
10638  )
10639 { /*lint --e{715}*/
10640  SCIP_Real onedivoneminusf0;
10641  int i;
10642 
10643  assert(lp != NULL);
10644  assert(weights != NULL);
10645  assert(!SCIPsetIsZero(set, scale));
10646  assert(mircoef != NULL);
10647  assert(mirrhs != NULL);
10648  assert(slacksign != NULL);
10649  assert(varused != NULL);
10650  assert(varinds != NULL);
10651  assert(nvarinds != NULL);
10652  assert(rowinds != NULL);
10653  assert(0.0 < f0 && f0 < 1.0);
10654 
10655  onedivoneminusf0 = 1.0 / (1.0 - f0);
10656  for( i = 0; i < nrowinds; i++ )
10657  {
10658  SCIP_ROW* row;
10659  SCIP_Real ar;
10660  SCIP_Real downar;
10661  SCIP_Real cutar;
10662  SCIP_Real fr;
10663  SCIP_Real mul;
10664  int idx;
10665  int r;
10666  int j;
10667 
10668  r = rowinds[i];
10669  assert(0 <= r && r < lp->nrows);
10670  assert(slacksign[r] == -1 || slacksign[r] == +1);
10671  assert(!SCIPsetIsZero(set, weights[r]));
10672 
10673  row = lp->rows[r];
10674  assert(row != NULL);
10675  assert(row->len == 0 || row->cols != NULL);
10676  assert(row->len == 0 || row->cols_index != NULL);
10677  assert(row->len == 0 || row->vals != NULL);
10678 
10679  /* get the slack's coefficient a'_r in the aggregated row */
10680  ar = slacksign[r] * scale * weights[r];
10681 
10682  /* calculate slack variable's coefficient a^_r in the cut */
10683  if( row->integral
10684  && ((slacksign[r] == +1 && SCIPsetIsFeasIntegral(set, row->rhs - row->constant))
10685  || (slacksign[r] == -1 && SCIPsetIsFeasIntegral(set, row->lhs - row->constant))) )
10686  {
10687  /* slack variable is always integral:
10688  * a^_r = a~_r = down(a'_r) , if f_r <= f0
10689  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
10690  */
10691  downar = SCIPsetFloor(set, ar);
10692  fr = ar - downar;
10693  if( SCIPsetIsLE(set, fr, f0) )
10694  cutar = downar;
10695  else
10696  cutar = downar + (fr - f0) * onedivoneminusf0;
10697  }
10698  else
10699  {
10700  /* slack variable is continuous:
10701  * a^_r = a~_r = 0 , if a'_r >= 0
10702  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
10703  */
10704  if( ar >= 0.0 )
10705  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
10706  else
10707  cutar = ar * onedivoneminusf0;
10708  }
10709 
10710  /* if the coefficient was reduced to zero, ignore the slack variable */
10711  if( SCIPsetIsZero(set, cutar) )
10712  continue;
10713 
10714  /* depending on the slack's sign, we have
10715  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
10716  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
10717  */
10718  mul = -slacksign[r] * cutar;
10719 
10720  /* add the slack's definition multiplied with a^_j to the cut */
10721  for( j = 0; j < row->len; ++j )
10722  {
10723  assert(row->cols[j] != NULL);
10724  assert(row->cols[j]->var != NULL);
10725  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
10726  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
10727  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
10728  idx = row->cols[j]->var_probindex;
10729  mircoef[idx] += mul * row->vals[j];
10730 
10731  /* update sparsity pattern */
10732  if( !varused[idx] )
10733  {
10734  varused[idx] = TRUE;
10735  varinds[*nvarinds] = idx;
10736  (*nvarinds)++;
10737  }
10738  }
10739 
10740  /* move slack's constant to the right hand side */
10741  if( slacksign[r] == +1 )
10742  {
10743  SCIP_Real rhs;
10744 
10745  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
10746  assert(!SCIPsetIsInfinity(set, row->rhs));
10747  rhs = row->rhs - row->constant;
10748  if( row->integral )
10749  {
10750  /* the right hand side was implicitly rounded down in row aggregation */
10751  rhs = SCIPsetFeasFloor(set, rhs);
10752  }
10753  *mirrhs -= cutar * rhs;
10754  }
10755  else
10756  {
10757  SCIP_Real lhs;
10758 
10759  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
10760  assert(!SCIPsetIsInfinity(set, -row->lhs));
10761  lhs = row->lhs - row->constant;
10762  if( row->integral )
10763  {
10764  /* the left hand side was implicitly rounded up in row aggregation */
10765  lhs = SCIPsetFeasCeil(set, lhs);
10766  }
10767  *mirrhs += cutar * lhs;
10768  }
10769  }
10770 
10771  /* set rhs to zero, if it's very close to */
10772  if( SCIPsetIsZero(set, *mirrhs) )
10773  *mirrhs = 0.0;
10774 }
10775 
10776 #ifdef SCIP_DEBUG
10777 static
10778 void printMIR(
10779  SCIP_SET* set, /**< global SCIP settings */
10780  SCIP_STAT* stat, /**< problem statistics */
10781  SCIP_PROB* prob, /**< problem data */
10782  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10783  SCIP_Real* mircoef, /**< MIR coefficients */
10784  SCIP_Real mirrhs /**< right hand side of the MIR row */
10785  )
10786 {
10787  SCIP_Real activity;
10788  int i;
10789 
10790  assert(prob != NULL);
10791 
10792  SCIPdebugMessage("MIR:");
10793  activity = 0.0;
10794  for( i = 0; i < prob->nvars; ++i )
10795  {
10796  if( mircoef[i] != 0.0 )
10797  {
10798  SCIPdebugPrintf(" %+g<%s>", mircoef[i], SCIPvarGetName(prob->vars[i]));
10799  activity += mircoef[i] * (sol == NULL ? SCIPvarGetLPSol(prob->vars[i]) : SCIPsolGetVal(sol, set, stat, prob->vars[i]));
10800  }
10801  }
10802  SCIPdebugPrintf(" <= %.6f (activity: %g)\n", mirrhs, activity);
10803 }
10804 #endif
10805 
10806 /** calculates the activity of the given MIR cut */
10807 static
10809  SCIP_SET* set, /**< global SCIP settings */
10810  SCIP_STAT* stat, /**< problem statistics */
10811  SCIP_PROB* prob, /**< problem data */
10812  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10813  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10814  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
10815  int nvarinds /**< number of non-zero MIR coefficients */
10816  )
10817 {
10818  SCIP_Real act;
10819  int i;
10820 
10821  act = 0.0;
10822  for( i = 0; i < nvarinds; i++ )
10823  {
10824  int v;
10825 
10826  v = varinds[i];
10827  assert(0 <= v && v < prob->nvars);
10828  assert(mircoef[v] != 0.0);
10829 
10830  act += mircoef[v] * ( sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
10831  }
10832 
10833  return act;
10834 }
10835 
10836 /* calculates a MIR cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because these
10837  * rows cannot participate in a MIR cut.
10838  */
10840  SCIP_LP* lp, /**< LP data */
10841  SCIP_SET* set, /**< global SCIP settings */
10842  SCIP_STAT* stat, /**< problem statistics */
10843  SCIP_PROB* prob, /**< problem data */
10844  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
10845  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
10846  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
10847  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
10848  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
10849  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
10850  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
10851  * NULL for using closest bound for all variables */
10852  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
10853  * NULL for using closest bound for all variables */
10854  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
10855  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
10856  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
10857  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
10858  SCIP_Real* weights, /**< row weights in row summation */
10859  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
10860  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
10861  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
10862  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
10863  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
10864  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
10865  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
10866  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
10867  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
10868  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
10869  )
10870 {
10871  int* slacksign;
10872  int* varsign;
10873  int* boundtype;
10874  SCIP_Bool* varused;
10875  int* varinds;
10876  int* rowinds;
10877  int nvarinds;
10878  int nrowinds;
10879  SCIP_Real rhs;
10880  SCIP_Real downrhs;
10881  SCIP_Real f0;
10882  SCIP_Bool emptyrow;
10883  SCIP_Bool freevariable;
10884  SCIP_Bool localrowsused;
10885  SCIP_Bool localbdsused;
10886  SCIP_Bool rowtoolong;
10887 
10888  assert(lp != NULL);
10889  assert(lp->solved || sol != NULL);
10890  assert(prob != NULL);
10891  assert(weights != NULL);
10892  assert(!SCIPsetIsZero(set, scale));
10893  assert(mircoef != NULL);
10894  assert(mirrhs != NULL);
10895  assert(cutactivity != NULL);
10896  assert(success != NULL);
10897  assert(cutislocal != NULL);
10898 
10899  SCIPdebugMessage("calculating MIR cut (scale: %g)\n", scale);
10900 
10901  /**@todo test, if a column based summation is faster */
10902 
10903  *success = FALSE;
10904  if( mksetcoefsvalid != NULL )
10905  *mksetcoefsvalid = FALSE;
10906 
10907  /* allocate temporary memory */
10908  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
10909  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
10910  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
10911  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
10912  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
10913  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
10914 
10915  /* calculate the row summation */
10916  sumMIRRow(set, prob, lp, weights, sidetypes, scale, allowlocal,
10917  maxmksetcoefs, maxweightrange, mircoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
10918  &emptyrow, &localrowsused, &rowtoolong, cutrank);
10919  assert(allowlocal || !localrowsused);
10920  *cutislocal = localrowsused;
10921  if( emptyrow || rowtoolong )
10922  goto TERMINATE;
10923  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
10924 
10925  /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
10926  * prevent numerical rounding errors
10927  */
10928  cleanupMIRRow(set, prob, mircoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
10929  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
10930 
10931  /* Transform equation a*x == b, lb <= x <= ub into standard form
10932  * a'*x' == b, 0 <= x' <= ub'.
10933  *
10934  * Transform variables (lb or ub):
10935  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
10936  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
10937  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
10938  *
10939  * Transform variables (vlb or vub):
10940  * 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.
10941  * 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.
10942  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
10943  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
10944  * a_{zu_j} := a_{zu_j} + a_j * bu_j
10945  */
10946  SCIP_CALL( transformMIRRow(set, stat, prob, sol, boundswitch, usevbds, allowlocal, fixintegralrhs, boundsfortrans,
10947  boundtypesfortrans, minfrac, maxfrac, mircoef, &rhs, varused, varinds, &nvarinds, varsign, boundtype,
10948  &freevariable, &localbdsused) );
10949  assert(allowlocal || !localbdsused);
10950  *cutislocal = *cutislocal || localbdsused;
10951 
10952  /* store the coefficients of the variables in the constructed mixed knapsack set */
10953  if( mksetcoefs != NULL )
10954  BMScopyMemoryArray(mksetcoefs, mircoef, prob->nvars);
10955  if( mksetcoefsvalid != NULL )
10956  *mksetcoefsvalid = TRUE;
10957 
10958  if( freevariable )
10959  goto TERMINATE;
10960  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs));
10961 
10962  /* Calculate fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j) , and derive MIR cut
10963  * a~*x' <= down(b)
10964  * integers : a~_j = down(a'_j) , if f_j <= f_0
10965  * a~_j = down(a'_j) + (f_j - f0)/(1 - f0), if f_j > f_0
10966  * continuous: a~_j = 0 , if a'_j >= 0
10967  * a~_j = a'_j/(1 - f0) , if a'_j < 0
10968  *
10969  * Transform inequality back to a^*x <= rhs:
10970  *
10971  * (lb or ub):
10972  * 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
10973  * 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
10974  * and move the constant terms
10975  * -a~_j * lb_j == -a^_j * lb_j, or
10976  * a~_j * ub_j == -a^_j * ub_j
10977  * to the rhs.
10978  *
10979  * (vlb or vub):
10980  * 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)
10981  * 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)
10982  * move the constant terms
10983  * -a~_j * dl_j == -a^_j * dl_j, or
10984  * a~_j * du_j == -a^_j * du_j
10985  * to the rhs, and update the VB variable coefficients:
10986  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
10987  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
10988  */
10989  downrhs = SCIPsetSumFloor(set, rhs);
10990  f0 = rhs - downrhs;
10991  if( f0 < minfrac || f0 > maxfrac )
10992  goto TERMINATE;
10993 
10994  /* We multiply the coefficients of the base inequality roughly by scale/(1-f0).
10995  * If this gives a scalar that is very big, we better do not generate this cut.
10996  */
10997  if( REALABS(scale)/(1.0 - f0) > MAXCMIRSCALE )
10998  goto TERMINATE;
10999 
11000  *mirrhs = downrhs;
11001  roundMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, varsign, boundtype, f0);
11002  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11003 
11004  /* substitute aggregated slack variables:
11005  *
11006  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
11007  * variable only appears in its own row:
11008  * a'_r = scale * weight[r] * slacksign[r].
11009  *
11010  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
11011  * integers : a^_r = a~_r = down(a'_r) , if f_r <= f0
11012  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
11013  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
11014  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
11015  *
11016  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
11017  */
11018  substituteMIRRow(set, stat, lp, weights, scale, mircoef, mirrhs, slacksign,
11019  varused, varinds, &nvarinds, rowinds, nrowinds, f0);
11020  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11021 
11022  /* remove again all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
11023  * prevent numerical rounding errors
11024  */
11025  cleanupMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, *cutislocal);
11026  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs));
11027 
11028  /* calculate cut activity */
11029  *cutactivity = getMIRRowActivity(set, stat, prob, sol, mircoef, varinds, nvarinds);
11030  *success = TRUE;
11031 
11032  TERMINATE:
11033  /* free temporary memory */
11034  SCIPsetFreeBufferArray(set, &rowinds);
11035  SCIPsetFreeBufferArray(set, &varinds);
11036  SCIPsetFreeBufferArray(set, &varused);
11037  SCIPsetFreeBufferArray(set, &boundtype);
11038  SCIPsetFreeBufferArray(set, &varsign);
11039  SCIPsetFreeBufferArray(set, &slacksign);
11040 
11041  /**@todo pass the sparsity pattern to the calling method in order to speed up the calling method's loops */
11042 
11043  return SCIP_OKAY;
11044 }
11045 
11046 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
11047 static
11049  SCIP_SET* set, /**< global SCIP settings */
11050  SCIP_PROB* prob, /**< problem data */
11051  SCIP_LP* lp, /**< LP data */
11052  SCIP_Real* weights, /**< row weights in row summation */
11053  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11054  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
11055  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
11056  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
11057  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size prob->nvars */
11058  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11059  int* slacksign, /**< stores the sign of the row's slack variable in summation */
11060  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
11061  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
11062  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
11063  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
11064  int* nrowinds, /**< pointer to store number of used rows */
11065  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
11066  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
11067  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
11068  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
11069  )
11070 {
11071  SCIP_Real maxweight;
11072  int rowlensum;
11073  int maxrank = 0;
11074  int i;
11075 
11076  assert(prob != NULL);
11077  assert(lp != NULL);
11078  assert(weights != NULL);
11079  assert(!SCIPsetIsZero(set, scale));
11080  assert(maxweightrange >= 1.0);
11081  assert(strongcgcoef != NULL);
11082  assert(strongcgrhs != NULL);
11083  assert(slacksign != NULL);
11084  assert(varused != NULL);
11085  assert(varinds != NULL);
11086  assert(nvarinds != NULL);
11087  assert(rowinds != NULL);
11088  assert(nrowinds != NULL);
11089  assert(emptyrow != NULL);
11090  assert(localrowsused != NULL);
11091 
11092  *nvarinds = 0;
11093  *nrowinds = 0;
11094  *localrowsused = FALSE;
11095  *strongcgrhs = 0.0;
11096  *emptyrow = TRUE;
11097  *rowtoolong = FALSE;
11098 
11099  /* initialize varused array */
11100  BMSclearMemoryArray(varused, prob->nvars);
11101 
11102  /* search the maximal absolute weight and calculate the row sparsity pattern */
11103  maxweight = getMaxAbsWeightCalcSparsity(lp, weights, rowinds, nrowinds, &rowlensum);
11104  maxweight *= ABS(scale);
11105 
11106  /* if the total number of non-zeros is way too large, we just skip this aggregation */
11107  if( rowlensum/5 > maxmksetcoefs )
11108  {
11109  *rowtoolong = TRUE;
11110  return;
11111  }
11112 
11113  /* calculate the row summation */
11114  BMSclearMemoryArray(strongcgcoef, prob->nvars);
11115  i = 0;
11116  while( i < *nrowinds )
11117  {
11118  SCIP_ROW* row;
11119  SCIP_Real weight;
11120  SCIP_Real absweight;
11121  SCIP_Bool skiprow;
11122  int r;
11123 
11124  r = rowinds[i];
11125  assert(0 <= i && i < lp->nrows);
11126  assert(weights[r] != 0.0);
11127 
11128  row = lp->rows[r];
11129  assert(row != NULL);
11130  assert(row->len == 0 || row->cols != NULL);
11131  assert(row->len == 0 || row->cols_index != NULL);
11132  assert(row->len == 0 || row->vals != NULL);
11133 
11134  /* modifiable rows cannot be part of a strong CG row summation;
11135  * local rows are only included, if the allowlocal flag is set;
11136  * close to zero weights or weights outside the maximal range are ignored
11137  */
11138  weight = scale * weights[r];
11139  absweight = ABS(weight);
11140  skiprow = FALSE;
11141  if( !row->modifiable && (allowlocal || !row->local)
11142  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
11143  {
11144  /*lint --e{644}*/
11145  SCIP_Bool uselhs;
11146 
11147  if( row->integral )
11148  {
11149  /* Row is integral:
11150  * Decide, if we want to use the left or the right hand side of the row in the summation.
11151  * If possible, use the side that leads to a positive slack value in the summation.
11152  */
11153  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
11154  uselhs = TRUE;
11155  else
11156  uselhs = FALSE;
11157  }
11158  else
11159  {
11160  /* Row is NOT integral:
11161  * Decide, if we have to use the left or the right hand side of the row in the summation,
11162  * in order to get a positive slack variable in the summation.
11163  * If not possible, ignore row in summation.
11164  */
11165  if( weight < 0.0 && !SCIPsetIsInfinity(set, -row->lhs) )
11166  uselhs = TRUE;
11167  else if( weight > 0.0 && !SCIPsetIsInfinity(set, row->rhs) )
11168  uselhs = FALSE;
11169  else
11170  skiprow = TRUE;
11171  }
11172 
11173  if( !skiprow )
11174  {
11175  /* add the row to the aggregation */
11176  addRowToAggregation(set, strongcgcoef, strongcgrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
11177  *emptyrow = FALSE;
11178  *localrowsused = *localrowsused || row->local;
11179 
11180  maxrank = MAX(maxrank, row->rank);
11181 
11182  SCIPdebugMessage("strong CG: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
11183  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
11184  scale, weights[r], slacksign[r], *strongcgrhs);
11185  debugRowPrint(row);
11186  }
11187  }
11188  else
11189  skiprow = TRUE;
11190 
11191  if( skiprow )
11192  {
11193  /* remove row from sparsity pattern, do not increase i, since the i-th position is filled with the last element */
11194  rowinds[i] = rowinds[(*nrowinds)-1];
11195  (*nrowinds)--;
11196 #ifndef NDEBUG
11197  slacksign[r] = 0;
11198 #endif
11199  }
11200  else
11201  ++i;
11202  }
11203 
11204  /* check if the total number of non-zeros is too large */
11205  if( *nrowinds > maxmksetcoefs )
11206  *rowtoolong = TRUE;
11207 
11208  /* set rank of the cut */
11209  if( cutrank != NULL )
11210  *cutrank = maxrank + 1;
11211 }
11212 
11213 /** 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$.
11214  *
11215  * Transform variables (lb or ub):
11216  * \f[
11217  * \begin{array}{llll}
11218  * 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} \\
11219  * 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}
11220  * \end{array}
11221  * \f]
11222  * and move the constant terms \f$ a_j * lb_j \f$ or \f$ a_j * ub_j \f$ to the rhs.
11223  *
11224  * Transform variables (vlb or vub):
11225  * \f[
11226  * \begin{array}{llll}
11227  * 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.} \\
11228  * 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.}
11229  * \end{array}
11230  * \f]
11231  * 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:
11232  * \f[
11233  * \begin{array}{ll}
11234  * a_{zl_j} := a_{zl_j} + a_j * bl_j,& \mbox{or} \\
11235  * a_{zu_j} := a_{zu_j} + a_j * bu_j&
11236  * \end{array}
11237  * \f]
11238  */
11239 static
11241  SCIP_SET* set, /**< global SCIP settings */
11242  SCIP_STAT* stat, /**< problem statistics */
11243  SCIP_PROB* prob, /**< problem data */
11244  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
11245  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
11246  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
11247  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11248  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11249  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11250  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11251  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11252  int* varsign, /**< stores the sign of the transformed variable in summation */
11253  int* boundtype, /**< stores the bound used for transformed variable:
11254  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
11255  SCIP_Bool* freevariable, /**< stores whether a free variable was found in strong CG row -> invalid summation */
11256  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
11257  )
11258 {
11259  int i;
11260 
11261  assert(prob != NULL);
11262  assert(strongcgcoef != NULL);
11263  assert(strongcgrhs != NULL);
11264  assert(varused != NULL);
11265  assert(varinds != NULL);
11266  assert(nvarinds != NULL);
11267  assert(varsign != NULL);
11268  assert(boundtype != NULL);
11269  assert(freevariable != NULL);
11270  assert(localbdsused != NULL);
11271 
11272  *freevariable = FALSE;
11273  *localbdsused = FALSE;
11274 
11275 #ifndef NDEBUG
11276  /* in debug mode, make sure that the whole array is initialized with invalid values */
11277  for( i = 0; i < prob->nvars; i++ )
11278  {
11279  varsign[i] = 0;
11280  boundtype[i] = -1;
11281  }
11282 #endif
11283 
11284  /* start with continuous variables, because using variable bounds can affect the untransformed integral
11285  * variables, and these changes have to be incorporated in the transformation of the integral variables
11286  * (continuous variables have largest problem indices!)
11287  */
11288  SCIPsortDownInt(varinds, *nvarinds);
11289 
11290  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
11291  * substitute integral variables with best standard bound (lb, ub)
11292  */
11293  i = 0;
11294  while( i < *nvarinds )
11295  {
11296  SCIP_VAR* var;
11297  SCIP_Real varsol;
11298  SCIP_Real bestlb;
11299  SCIP_Real bestub;
11300  SCIP_Bool uselb;
11301  int bestlbtype;
11302  int bestubtype;
11303  int v;
11304 
11305  v = varinds[i];
11306  assert(0 <= v && v < prob->nvars);
11307  assert(varused[v]);
11308 
11309  var = prob->vars[v];
11310  assert(v == SCIPvarGetProbindex(var));
11311 
11312  /* due to variable bound usage cancellation may occur;
11313  * do not increase i, since last element is copied to the i-th position
11314  */
11315  if( SCIPsetIsZero(set, strongcgcoef[v]) )
11316  {
11317  varsign[v] = +1;
11318  boundtype[v] = -1;
11319  strongcgcoef[v] = 0.0;
11320  varused[v] = FALSE;
11321  varinds[i] = varinds[(*nvarinds)-1];
11322  (*nvarinds)--;
11323  continue;
11324  }
11325 
11326  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
11327  bestlb = SCIPvarGetLbGlobal(var);
11328  bestlbtype = -1;
11329  if( allowlocal )
11330  {
11331  SCIP_Real loclb;
11332 
11333  loclb = SCIPvarGetLbLocal(var);
11334  if( SCIPsetIsGT(set, loclb, bestlb) )
11335  {
11336  bestlb = loclb;
11337  bestlbtype = -2;
11338  }
11339  }
11340  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
11341  {
11342  SCIP_Real bestvlb;
11343  int bestvlbidx;
11344 
11345  SCIPvarGetClosestVlb(var, NULL, set, stat, &bestvlb, &bestvlbidx);
11346  if( bestvlbidx >= 0
11347  && (bestvlb > bestlb || (bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, bestlb))) )
11348  {
11349  bestlb = bestvlb;
11350  bestlbtype = bestvlbidx;
11351  }
11352  }
11353 
11354  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
11355  bestub = SCIPvarGetUbGlobal(var);
11356  bestubtype = -1;
11357  if( allowlocal )
11358  {
11359  SCIP_Real locub;
11360 
11361  locub = SCIPvarGetUbLocal(var);
11362  if( SCIPsetIsLT(set, locub, bestub) )
11363  {
11364  bestub = locub;
11365  bestubtype = -2;
11366  }
11367  }
11368  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
11369  {
11370  SCIP_Real bestvub;
11371  int bestvubidx;
11372 
11373  SCIPvarGetClosestVub(var, NULL, set, stat, &bestvub, &bestvubidx);
11374  if( bestvubidx >= 0
11375  && (bestvub < bestub || (bestubtype < 0 && SCIPsetIsLE(set, bestvub, bestub))) )
11376  {
11377  bestub = bestvub;
11378  bestubtype = bestvubidx;
11379  }
11380  }
11381 
11382  /* check, if variable is free variable
11383  * (for continuous variable use bound, so that coefficient will be nonnegative)
11384  */
11386  && SCIPsetIsInfinity(set, -bestlb)
11387  && SCIPsetIsInfinity(set, bestub))
11389  && ((strongcgcoef[v] > 0.0 && SCIPsetIsInfinity(set, -bestlb))
11390  || (strongcgcoef[v] < 0.0 && SCIPsetIsInfinity(set, bestub)))) )
11391  {
11392  /* we found a free variable in the row with non-zero coefficient
11393  * -> strong CG row can't be transformed in standard form
11394  */
11395  *freevariable = TRUE;
11396  return;
11397  }
11398 
11399  /* select transformation bound
11400  * (for continuous variable use bound, so that coefficient will be nonnegative)
11401  */
11402  varsol = SCIPvarGetLPSol(var);
11404  uselb = (strongcgcoef[v] > 0.0);
11405  else if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
11406  uselb = TRUE;
11407  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
11408  uselb = FALSE;
11409  else if( bestlbtype == -1 ) /* prefer global standard bounds */
11410  uselb = TRUE;
11411  else if( bestubtype == -1 ) /* prefer global standard bounds */
11412  uselb = FALSE;
11413  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
11414  uselb = TRUE;
11415  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
11416  uselb = FALSE;
11417  else
11418  uselb = TRUE; /* no decision yet? just use lower bound */
11419 
11420  /* perform bound substitution */
11421  if( uselb )
11422  {
11423  assert(!SCIPsetIsInfinity(set, -bestlb));
11424 
11425  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
11426  boundtype[v] = bestlbtype;
11427  varsign[v] = +1;
11428 
11429  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
11430  if( bestlbtype < 0 )
11431  {
11432  (*strongcgrhs) -= strongcgcoef[v] * bestlb;
11433  *localbdsused = *localbdsused || (bestlbtype == -2);
11434  }
11435  else
11436  {
11437  SCIP_VAR** vlbvars = SCIPvarGetVlbVars(var);
11438  SCIP_Real* vlbcoefs = SCIPvarGetVlbCoefs(var);
11439  SCIP_Real* vlbconsts = SCIPvarGetVlbConstants(var);
11440  int zidx;
11441 
11442  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
11443  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
11444  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
11445  assert(0 <= zidx && zidx < v);
11446 
11447  (*strongcgrhs) -= strongcgcoef[v] * vlbconsts[bestlbtype];
11448  strongcgcoef[zidx] += strongcgcoef[v] * vlbcoefs[bestlbtype];
11449 
11450  /* update sparsity pattern */
11451  if( !varused[zidx] )
11452  {
11453  assert(*nvarinds < prob->nvars);
11454  varused[zidx] = TRUE;
11455  varinds[*nvarinds] = zidx;
11456  (*nvarinds)++;
11457  }
11458  }
11459  }
11460  else
11461  {
11462  assert(!SCIPsetIsInfinity(set, bestub));
11463 
11464  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
11465  boundtype[v] = bestubtype;
11466  varsign[v] = -1;
11467 
11468  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
11469  if( bestubtype < 0 )
11470  {
11471  (*strongcgrhs) -= strongcgcoef[v] * bestub;
11472  *localbdsused = *localbdsused || (bestubtype == -2);
11473  }
11474  else
11475  {
11476  SCIP_VAR** vubvars = SCIPvarGetVubVars(var);
11477  SCIP_Real* vubcoefs = SCIPvarGetVubCoefs(var);
11478  SCIP_Real* vubconsts = SCIPvarGetVubConstants(var);
11479  int zidx;
11480 
11481  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
11482  assert(SCIPvarIsActive(vubvars[bestubtype]));
11483  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
11484  assert(zidx >= 0);
11485 
11486  (*strongcgrhs) -= strongcgcoef[v] * vubconsts[bestubtype];
11487  strongcgcoef[zidx] += strongcgcoef[v] * vubcoefs[bestubtype];
11488 
11489  /* update sparsity pattern */
11490  if( !varused[zidx] )
11491  {
11492  assert(*nvarinds < prob->nvars);
11493  varused[zidx] = TRUE;
11494  varinds[*nvarinds] = zidx;
11495  (*nvarinds)++;
11496  }
11497  }
11498  }
11499 
11500 #ifndef NDEBUG
11502  assert(strongcgcoef[v]*varsign[v] > 0.0);
11503 #endif
11504 
11505  SCIPdebugMessage("strong CG var <%s>: varsign=%d, boundtype=%d, strongcgcoef=%g, lb=%g, ub=%g -> rhs=%g\n",
11506  SCIPvarGetName(var), varsign[v], boundtype[v], strongcgcoef[v], bestlb, bestub, *strongcgrhs);
11507 
11508  ++i; /*increase iterator */
11509  }
11510 }
11511 
11512 /** Calculate fractionalities \f$ f_0 := b - down(b) \f$, \f$ f_j := a^\prime_j - down(a^\prime_j) \f$ and
11513  * integer \f$ k >= 1 \f$ with \f$ 1/(k + 1) <= f_0 < 1/k \f$ and \f$ (=> k = up(1/f_0) + 1) \f$
11514  * 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$
11515  * and derive strong CG cut \f$ \tilde{a}*x^\prime <= down(b) \f$
11516  * \f[
11517  * \begin{array}{rll}
11518  * integers : & \tilde{a}_j = down(a^\prime_j) &, if \qquad f_j <= f_0 \\
11519  * & \tilde{a}_j = down(a^\prime_j) + p_j/(k + 1) &, if \qquad f_j > f_0 \\
11520  * continuous:& \tilde{a}_j = 0 &, if \qquad a^\prime_j >= 0 \\
11521  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_j < 0
11522  * \end{array}
11523  * \f]
11524  *
11525  * Transform inequality back to \f$ \hat{a}*x <= rhs \f$:
11526  *
11527  * (lb or ub):
11528  * \f[
11529  * \begin{array}{lllll}
11530  * 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} \\
11531  * 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}
11532  * \end{array}
11533  * \f]
11534  * and move the constant terms
11535  * \f[
11536  * \begin{array}{rl}
11537  * -\tilde{a}_j * lb_j == -\hat{a}_j * lb_j, & \mbox{or} \\
11538  * \tilde{a}_j * ub_j == -\hat{a}_j * ub_j &
11539  * \end{array}
11540  * \f]
11541  * to the rhs.
11542  *
11543  * (vlb or vub):
11544  * \f[
11545  * \begin{array}{lllll}
11546  * 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)} \\
11547  * 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)}
11548  * \end{array}
11549  * \f]
11550  * move the constant terms
11551  * \f[
11552  * \begin{array}{rl}
11553  * -\tilde{a}_j * dl_j == -\hat{a}_j * dl_j,& \mbox{or} \\
11554  * \tilde{a}_j * du_j == -\hat{a}_j * du_j &
11555  * \end{array}
11556  * \f]
11557  * to the rhs, and update the VB variable coefficients:
11558  * \f[
11559  * \begin{array}{ll}
11560  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j * bl_j == \hat{a}_{zl_j} - \hat{a}_j * bl_j,& \mbox{or} \\
11561  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j * bu_j == \hat{a}_{zu_j} - \hat{a}_j * bu_j &
11562  * \end{array}
11563  * \f]
11564  */
11565 static
11567  SCIP_SET* set, /**< global SCIP settings */
11568  SCIP_PROB* prob, /**< problem data */
11569  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11570  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11571  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11572  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11573  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11574  int* varsign, /**< stores the sign of the transformed variable in summation */
11575  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub)*/
11576  SCIP_Real f0, /**< fractional value of rhs */
11577  SCIP_Real k /**< factor to strengthen strongcg cut */
11578  )
11579 {
11580  SCIP_Real onedivoneminusf0;
11581  int nintvars;
11582  int i;
11583 
11584  assert(prob != NULL);
11585  assert(strongcgcoef != NULL);
11586  assert(strongcgrhs != NULL);
11587  assert(varused != NULL);
11588  assert(varinds != NULL);
11589  assert(nvarinds != NULL);
11590  assert(varsign != NULL);
11591  assert(0.0 < f0 && f0 < 1.0);
11592 
11593  onedivoneminusf0 = 1.0 / (1.0 - f0);
11594  nintvars = prob->nvars - prob->ncontvars;
11595 
11596  /* start with integer variables, since the variable bound substitutions can add up to the integer cut coefficients;
11597  * loop backwards to be able to delete coefficients from the sparsity pattern
11598  */
11599  SCIPsortDownInt(varinds, *nvarinds);
11600 
11601  /* integer variables */
11602  for( i = *nvarinds-1; i >= 0; i-- )
11603  {
11604  SCIP_VAR* var;
11605  SCIP_Real aj;
11606  SCIP_Real downaj;
11607  SCIP_Real cutaj;
11608  SCIP_Real fj;
11609  int v;
11610 
11611  v = varinds[i];
11612  assert(0 <= v && v < prob->nvars);
11613  assert(varused[v]);
11614 
11615  /* stop this loop if we reached the continuous variables */
11616  if( v >= nintvars )
11617  {
11618  assert(!SCIPvarIsIntegral(prob->vars[v]));
11619  assert(SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS);
11620  break;
11621  }
11622 
11623  var = prob->vars[v];
11624  assert(var != NULL);
11625  assert(SCIPvarIsIntegral(var));
11626  assert(SCIPvarGetProbindex(var) == v);
11627  assert(boundtype[v] == -1 || boundtype[v] == -2);
11628  assert(varsign[v] == +1 || varsign[v] == -1);
11629 
11630  /* calculate the coefficient in the retransformed cut */
11631  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
11632  downaj = SCIPsetFloor(set, aj);
11633  fj = aj - downaj;
11634 
11635  if( SCIPsetIsSumLE(set, fj, f0) )
11636  cutaj = varsign[v] * downaj; /* a^_j */
11637  else
11638  {
11639  SCIP_Real pj;
11640 
11641  pj = SCIPsetCeil(set, k * (fj - f0) * onedivoneminusf0);
11642  assert(pj >= 0); /* should be >= 1, but due to rounding bias can be 0 if fj almost equal to f0 */
11643  assert(pj <= k);
11644  cutaj = varsign[v] * (downaj + pj / (k + 1)); /* a^_j */
11645  }
11646 
11647 
11648  /* remove zero cut coefficients from sparsity pattern */
11649  if( SCIPsetIsZero(set, cutaj) )
11650  {
11651  strongcgcoef[v] = 0.0;
11652  varused[v] = FALSE;
11653  varinds[i] = varinds[(*nvarinds)-1];
11654  (*nvarinds)--;
11655  continue;
11656  }
11657 
11658  strongcgcoef[v] = cutaj;
11659 
11660  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
11661  if( varsign[v] == +1 )
11662  {
11663  /* lower bound was used */
11664  if( boundtype[v] == -1 )
11665  {
11666  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
11667  (*strongcgrhs) += cutaj * SCIPvarGetLbGlobal(var);
11668  }
11669  else
11670  {
11671  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
11672  (*strongcgrhs) += cutaj * SCIPvarGetLbLocal(var);
11673  }
11674  }
11675  else
11676  {
11677  /* upper bound was used */
11678  if( boundtype[v] == -1 )
11679  {
11680  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
11681  (*strongcgrhs) += cutaj * SCIPvarGetUbGlobal(var);
11682  }
11683  else
11684  {
11685  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
11686  (*strongcgrhs) += cutaj * SCIPvarGetUbLocal(var);
11687  }
11688  }
11689  }
11690 
11691  /* continuous variables */
11692  for( ; i >= 0; i-- )
11693  {
11694  int v;
11695 
11696  v = varinds[i];
11697  assert(0 <= v && v < prob->nvars);
11698  assert(varused[v]);
11699 
11700 #ifndef NDEBUG
11701  /* in a strong CG cut, cut coefficients of continuous variables are always zero; check this in debug mode */
11702  {
11703  SCIP_VAR* var;
11704  SCIP_Real aj;
11705 
11706  var = prob->vars[v];
11707  assert(var != NULL);
11708  assert(!SCIPvarIsIntegral(var));
11709  assert(SCIPvarGetProbindex(var) == v);
11710  assert(varsign[v] == +1 || varsign[v] == -1);
11711 
11712  /* calculate the coefficient in the retransformed cut */
11713  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
11714  assert(aj >= 0.0);
11715  }
11716 #endif
11717 
11718  strongcgcoef[v] = 0.0;
11719 
11720  /* remove zero cut coefficients from sparsity pattern */
11721  varused[v] = FALSE;
11722  varinds[i] = varinds[(*nvarinds)-1];
11723  (*nvarinds)--;
11724  }
11725 }
11726 
11727 /** substitute aggregated slack variables:
11728  *
11729  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
11730  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r] \f$.
11731  *
11732  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
11733  * \f[
11734  * \begin{array}{rll}
11735  * integers: & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) &, if \qquad f_r <= f0 \\
11736  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + p_r/(k + 1) &, if \qquad f_r > f0 \\
11737  * continuous:& \hat{a}_r = \tilde{a}_r = 0 &, if \qquad a^\prime_r >= 0 \\
11738  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_r < 0
11739  * \end{array}
11740  * \f]
11741  *
11742  * Substitute \f$ \hat{a}_r * s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
11743  */
11744 static
11746  SCIP_SET* set, /**< global SCIP settings */
11747  SCIP_STAT* stat, /**< problem statistics */
11748  SCIP_LP* lp, /**< LP data */
11749  SCIP_Real* weights, /**< row weights in row summation */
11750  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11751  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11752  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11753  int* slacksign, /**< stores the sign of the row's slack variable in summation */
11754  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
11755  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
11756  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
11757  int* rowinds, /**< sparsity pattern of used rows */
11758  int nrowinds, /**< number of used rows */
11759  SCIP_Real f0, /**< fractional value of rhs */
11760  SCIP_Real k /**< factor to strengthen strongcg cut */
11761  )
11762 { /*lint --e{715}*/
11763  SCIP_Real onedivoneminusf0;
11764  int i;
11765 
11766  assert(lp != NULL);
11767  assert(weights != NULL);
11768  assert(!SCIPsetIsZero(set, scale));
11769  assert(strongcgcoef != NULL);
11770  assert(strongcgrhs != NULL);
11771  assert(slacksign != NULL);
11772  assert(varused != NULL);
11773  assert(varinds != NULL);
11774  assert(nvarinds != NULL);
11775  assert(rowinds != NULL);
11776  assert(0.0 < f0 && f0 < 1.0);
11777 
11778  onedivoneminusf0 = 1.0 / (1.0 - f0);
11779 
11780  for( i = 0; i < nrowinds; i++ )
11781  {
11782  SCIP_ROW* row;
11783  SCIP_Real pr;
11784  SCIP_Real ar;
11785  SCIP_Real downar;
11786  SCIP_Real cutar;
11787  SCIP_Real fr;
11788  SCIP_Real mul;
11789  int idx;
11790  int r;
11791  int j;
11792 
11793  r = rowinds[i];
11794  assert(0 <= r && r < lp->nrows);
11795  assert(slacksign[r] == -1 || slacksign[r] == +1);
11796  assert(!SCIPsetIsZero(set, weights[r]));
11797 
11798  row = lp->rows[r];
11799  assert(row != NULL);
11800  assert(row->len == 0 || row->cols != NULL);
11801  assert(row->len == 0 || row->cols_index != NULL);
11802  assert(row->len == 0 || row->vals != NULL);
11803 
11804  /* get the slack's coefficient a'_r in the aggregated row */
11805  ar = slacksign[r] * scale * weights[r];
11806 
11807  /* calculate slack variable's coefficient a^_r in the cut */
11808  if( row->integral )
11809  {
11810  /* slack variable is always integral: */
11811  downar = SCIPsetFloor(set, ar);
11812  fr = ar - downar;
11813 
11814  if( SCIPsetIsLE(set, fr, f0) )
11815  cutar = downar;
11816  else
11817  {
11818  pr = SCIPsetCeil(set, k * (fr - f0) * onedivoneminusf0);
11819  assert(pr >= 0); /* should be >= 1, but due to rounding bias can be 0 if fr almost equal to f0 */
11820  assert(pr <= k);
11821  cutar = downar + pr / (k + 1);
11822  }
11823  }
11824  else
11825  {
11826  /* slack variable is continuous: */
11827  assert(ar >= 0.0);
11828  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
11829  }
11830 
11831  /* if the coefficient was reduced to zero, ignore the slack variable */
11832  if( SCIPsetIsZero(set, cutar) )
11833  continue;
11834 
11835  /* depending on the slack's sign, we have
11836  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
11837  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
11838  */
11839  mul = -slacksign[r] * cutar;
11840 
11841  /* add the slack's definition multiplied with a^_j to the cut */
11842  for( j = 0; j < row->len; ++j )
11843  {
11844  assert(row->cols[j] != NULL);
11845  assert(row->cols[j]->var != NULL);
11846  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
11847  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
11848  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
11849  idx = row->cols[j]->var_probindex;
11850  strongcgcoef[idx] += mul * row->vals[j];
11851 
11852  /* update sparsity pattern */
11853  if( !varused[idx] )
11854  {
11855  varused[idx] = TRUE;
11856  varinds[*nvarinds] = idx;
11857  (*nvarinds)++;
11858  }
11859  }
11860 
11861  /* move slack's constant to the right hand side */
11862  if( slacksign[r] == +1 )
11863  {
11864  SCIP_Real rhs;
11865 
11866  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
11867  assert(!SCIPsetIsInfinity(set, row->rhs));
11868  rhs = row->rhs - row->constant;
11869  if( row->integral )
11870  {
11871  /* the right hand side was implicitly rounded down in row aggregation */
11872  rhs = SCIPsetFeasFloor(set, rhs);
11873  }
11874  *strongcgrhs -= cutar * rhs;
11875  }
11876  else
11877  {
11878  SCIP_Real lhs;
11879 
11880  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
11881  assert(!SCIPsetIsInfinity(set, -row->lhs));
11882  lhs = row->lhs - row->constant;
11883  if( row->integral )
11884  {
11885  /* the left hand side was implicitly rounded up in row aggregation */
11886  lhs = SCIPsetFeasCeil(set, lhs);
11887  }
11888  *strongcgrhs += cutar * lhs;
11889  }
11890  }
11891 
11892  /* set rhs to zero, if it's very close to */
11893  if( SCIPsetIsZero(set, *strongcgrhs) )
11894  *strongcgrhs = 0.0;
11895 }
11896 
11897 /* calculates a strong CG cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because these
11898  * rows cannot participate in a strong CG cut.
11899  */
11901  SCIP_LP* lp, /**< LP data */
11902  SCIP_SET* set, /**< global SCIP settings */
11903  SCIP_STAT* stat, /**< problem statistics */
11904  SCIP_PROB* prob, /**< problem data */
11905  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
11906  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
11907  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
11908  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
11909  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
11910  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce strong CG cut for */
11911  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce strong CG cut for */
11912  SCIP_Real* weights, /**< row weights in row summation */
11913  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
11914  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
11915  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
11916  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
11917  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid strong CG cut */
11918  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
11919  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
11920  )
11921 {
11922  int* slacksign;
11923  int* varsign;
11924  int* boundtype;
11925  SCIP_Bool* varused;
11926  int* varinds;
11927  int* rowinds;
11928  int nvarinds;
11929  int nrowinds;
11930  SCIP_Real rhs;
11931  SCIP_Real downrhs;
11932  SCIP_Real f0;
11933  SCIP_Real k;
11934  SCIP_Bool emptyrow;
11935  SCIP_Bool freevariable;
11936  SCIP_Bool localrowsused;
11937  SCIP_Bool localbdsused;
11938  SCIP_Bool rowtoolong;
11939 
11940  assert(lp != NULL);
11941  assert(lp->solved);
11942  assert(prob != NULL);
11943  assert(weights != NULL);
11944  assert(!SCIPsetIsZero(set, scale));
11945  assert(strongcgcoef != NULL);
11946  assert(strongcgrhs != NULL);
11947  assert(cutactivity != NULL);
11948  assert(success != NULL);
11949  assert(cutislocal != NULL);
11950 
11951  SCIPdebugMessage("calculating strong CG cut (scale: %g)\n", scale);
11952 
11953  /**@todo test, if a column based summation is faster */
11954 
11955  *success = FALSE;
11956  *cutislocal = FALSE;
11957 
11958  /* allocate temporary memory */
11959  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
11960  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
11961  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
11962  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
11963  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
11964  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
11965 
11966  /* calculate the row summation */
11967  sumStrongCGRow(set, prob, lp, weights, scale, allowlocal,
11968  maxmksetcoefs, maxweightrange, strongcgcoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
11969  &emptyrow, &localrowsused, &rowtoolong, cutrank);
11970  assert(allowlocal || !localrowsused);
11971  *cutislocal = *cutislocal || localrowsused;
11972  if( emptyrow || rowtoolong )
11973  goto TERMINATE;
11974  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
11975 
11976  /* remove all nearly-zero coefficients from strong CG row and relaxes the right hand side correspondingly in order to
11977  * prevent numerical rounding errors
11978  */
11979  cleanupMIRRow(set, prob, strongcgcoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
11980  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
11981 
11982  /* Transform equation a*x == b, lb <= x <= ub into standard form
11983  * a'*x' == b, 0 <= x' <= ub'.
11984  *
11985  * Transform variables (lb or ub):
11986  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
11987  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
11988  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
11989  *
11990  * Transform variables (vlb or vub):
11991  * 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.
11992  * 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.
11993  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
11994  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
11995  * a_{zu_j} := a_{zu_j} + a_j * bu_j
11996  */
11997  transformStrongCGRow(set, stat, prob, boundswitch, usevbds, allowlocal,
11998  strongcgcoef, &rhs, varused, varinds, &nvarinds, varsign, boundtype, &freevariable, &localbdsused);
11999  assert(allowlocal || !localbdsused);
12000  *cutislocal = *cutislocal || localbdsused;
12001  if( freevariable )
12002  goto TERMINATE;
12003  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12004 
12005  /* Calculate
12006  * - fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j)
12007  * - integer k >= 1 with 1/(k + 1) <= f_0 < 1/k
12008  * (=> k = up(1/f_0) + 1)
12009  * - 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)
12010  * (=> p_j = up( (f_j - f_0)/((1 - f_0)/k) ))
12011  * and derive strong CG cut
12012  * a~*x' <= (k+1) * down(b)
12013  * integers : a~_j = down(a'_j) , if f_j <= f_0
12014  * a~_j = down(a'_j) + p_j/(k + 1) , if f_j > f_0
12015  * continuous: a~_j = 0 , if a'_j >= 0
12016  * no strong CG cut found , if a'_j < 0
12017  *
12018  * Transform inequality back to a^*x <= rhs:
12019  *
12020  * (lb or ub):
12021  * 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
12022  * 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
12023  * and move the constant terms
12024  * -a~_j * lb_j == -a^_j * lb_j, or
12025  * a~_j * ub_j == -a^_j * ub_j
12026  * to the rhs.
12027  *
12028  * (vlb or vub):
12029  * 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)
12030  * 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)
12031  * move the constant terms
12032  * -a~_j * dl_j == -a^_j * dl_j, or
12033  * a~_j * du_j == -a^_j * du_j
12034  * to the rhs, and update the VB variable coefficients:
12035  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
12036  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
12037  */
12038  downrhs = SCIPsetSumFloor(set, rhs);
12039  f0 = rhs - downrhs;
12040  if( f0 < minfrac || f0 > maxfrac )
12041  goto TERMINATE;
12042  k = SCIPsetCeil(set, 1.0 / f0) - 1;
12043 
12044  *strongcgrhs = downrhs;
12045  roundStrongCGRow(set, prob, strongcgcoef, strongcgrhs, varused, varinds, &nvarinds, varsign, boundtype, f0, k);
12046  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs));
12047 
12048  /* substitute aggregated slack variables:
12049  *
12050  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
12051  * variable only appears in its own row:
12052  * a'_r = scale * weight[r] * slacksign[r].
12053  *
12054  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
12055  * integers : a^_r = a~_r = (k + 1) * down(a'_r) , if f_r <= f0
12056  * a^_r = a~_r = (k + 1) * down(a'_r) + p_r , if f_r > f0
12057  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
12058  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
12059  *
12060  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
12061  */
12062  substituteStrongCGRow(set, stat, lp, weights, scale, strongcgcoef, strongcgrhs, slacksign,
12063  varused, varinds, &nvarinds, rowinds, nrowinds, f0, k);
12064  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs));
12065 
12066  /* remove again all nearly-zero coefficients from strong CG row and relax the right hand side correspondingly in order to
12067  * prevent numerical rounding errors
12068  */
12069  cleanupMIRRow(set, prob, strongcgcoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
12070  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs));
12071 
12072  /* calculate cut activity */
12073  *cutactivity = getMIRRowActivity(set, stat, prob, NULL, strongcgcoef, varinds, nvarinds);
12074  *success = TRUE;
12075 
12076  TERMINATE:
12077  /* free temporary memory */
12078  SCIPsetFreeBufferArray(set, &rowinds);
12079  SCIPsetFreeBufferArray(set, &varinds);
12080  SCIPsetFreeBufferArray(set, &varused);
12081  SCIPsetFreeBufferArray(set, &boundtype);
12082  SCIPsetFreeBufferArray(set, &varsign);
12083  SCIPsetFreeBufferArray(set, &slacksign);
12084 
12085  return SCIP_OKAY;
12086 }
12087 
12088 /** stores LP state (like basis information) into LP state object */
12090  SCIP_LP* lp, /**< LP data */
12091  BMS_BLKMEM* blkmem, /**< block memory */
12092  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
12093  )
12094 {
12095  assert(lp != NULL);
12096  assert(lp->flushed);
12097  assert(lp->solved);
12098  assert(blkmem != NULL);
12099  assert(lpistate != NULL);
12100 
12101  /* check whether there is no lp */
12102  if( lp->nlpicols == 0 && lp->nlpirows == 0 )
12103  *lpistate = NULL;
12104  else
12105  {
12106  SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
12107  }
12108 
12109  return SCIP_OKAY;
12110 }
12111 
12112 /** loads LP state (like basis information) into solver */
12114  SCIP_LP* lp, /**< LP data */
12115  BMS_BLKMEM* blkmem, /**< block memory */
12116  SCIP_SET* set, /**< global SCIP settings */
12117  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12118  SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
12119  SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
12120  SCIP_Bool wasdualfeas /**< dual feasibility when LP state information was stored */
12121  )
12122 {
12123  assert(lp != NULL);
12124  assert(blkmem != NULL);
12125 
12126  /* flush changes to the LP solver */
12127  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
12128  assert(lp->flushed);
12129 
12130  if( lp->solved && lp->solisbasic )
12131  return SCIP_OKAY;
12132 
12133  /* set LPI state in the LP solver */
12134  if( lpistate == NULL )
12135  lp->solisbasic = FALSE;
12136  else
12137  {
12138  SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
12139  lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
12140  }
12141  /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
12142  * flushed and solved, also, e.g., when we hit the iteration limit
12143  */
12144  lp->primalfeasible = wasprimfeas;
12145  lp->dualfeasible = wasdualfeas;
12146 
12147  return SCIP_OKAY;
12148 }
12149 
12150 /** frees LP state information */
12152  SCIP_LP* lp, /**< LP data */
12153  BMS_BLKMEM* blkmem, /**< block memory */
12154  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
12155  )
12156 {
12157  assert(lp != NULL);
12158 
12159  if( *lpistate != NULL )
12160  {
12161  SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
12162  }
12163 
12164  return SCIP_OKAY;
12165 }
12166 
12167 /** stores pricing norms into LP norms object */
12169  SCIP_LP* lp, /**< LP data */
12170  BMS_BLKMEM* blkmem, /**< block memory */
12171  SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
12172  )
12173 {
12174  assert(lp != NULL);
12175  assert(lp->flushed);
12176  assert(lp->solved);
12177  assert(blkmem != NULL);
12178  assert(lpinorms != NULL);
12179 
12180  /* check whether there is no lp */
12181  if( lp->nlpicols == 0 && lp->nlpirows == 0 )
12182  *lpinorms = NULL;
12183  else
12184  {
12185  SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
12186  }
12187 
12188  return SCIP_OKAY;
12189 }
12190 
12191 /** loads pricing norms from LP norms object into solver */
12193  SCIP_LP* lp, /**< LP data */
12194  BMS_BLKMEM* blkmem, /**< block memory */
12195  SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
12196  )
12197 {
12198  assert(lp != NULL);
12199  assert(blkmem != NULL);
12200  assert(lp->flushed);
12201 
12202  /* set LPI norms in the LP solver */
12203  if( lpinorms != NULL )
12204  {
12205  SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
12206  }
12207 
12208  return SCIP_OKAY;
12209 }
12210 
12211 /** frees pricing norms information */
12213  SCIP_LP* lp, /**< LP data */
12214  BMS_BLKMEM* blkmem, /**< block memory */
12215  SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
12216  )
12217 {
12218  assert(lp != NULL);
12219 
12220  SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
12221 
12222  return SCIP_OKAY;
12223 }
12224 
12225 /** sets the upper objective limit of the LP solver */
12227  SCIP_LP* lp, /**< current LP data */
12228  SCIP_SET* set, /**< global SCIP settings */
12229  SCIP_PROB* prob, /**< problem data */
12230  SCIP_Real cutoffbound /**< new upper objective limit */
12231  )
12232 {
12233  assert(lp != NULL);
12234 
12235  SCIPdebugMessage("setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
12236 
12237  /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
12238  * in SCIPendDive())
12239  */
12240  if( SCIPlpDivingObjChanged(lp) )
12241  {
12242  assert(SCIPsetIsInfinity(set, lp->cutoffbound));
12243  return SCIP_OKAY;
12244  }
12245 
12246  /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
12247  if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
12248  {
12249  /* mark the current solution invalid */
12250  lp->solved = FALSE;
12251  lp->lpobjval = SCIP_INVALID;
12253  }
12254  /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
12255  * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
12256  */
12258  && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
12259  {
12260  assert(lp->flushed);
12261  assert(lp->solved);
12263  }
12264 
12265  lp->cutoffbound = cutoffbound;
12266 
12267  return SCIP_OKAY;
12268 }
12269 
12270 /** returns the name of the given LP algorithm */
12271 static
12272 const char* lpalgoName(
12273  SCIP_LPALGO lpalgo /**< LP algorithm */
12274  )
12275 {
12276  switch( lpalgo )
12277  {
12279  return "primal simplex";
12281  return "dual simplex";
12282  case SCIP_LPALGO_BARRIER:
12283  return "barrier";
12285  return "barrier/crossover";
12286  default:
12287  SCIPerrorMessage("invalid LP algorithm\n");
12288  SCIPABORT();
12289  return "invalid"; /*lint !e527*/
12290  }
12291 }
12292 
12293 /** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
12294 static
12296  SCIP_LP* lp, /**< current LP data */
12297  SCIP_SET* set, /**< global SCIP settings */
12298  SCIP_STAT* stat, /**< problem statistics */
12299  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12300  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12301  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12302  )
12303 {
12304  SCIP_Real timedelta;
12305  SCIP_RETCODE retcode;
12306  int iterations;
12307 
12308  assert(lp != NULL);
12309  assert(lp->flushed);
12310  assert(set != NULL);
12311  assert(stat != NULL);
12312  assert(lperror != NULL);
12313 
12314  SCIPdebugMessage("solving LP %"SCIP_LONGINT_FORMAT" (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
12315  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
12316 
12317  *lperror = FALSE;
12318 
12319 #if 0
12320  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
12321  {
12322  char fname[SCIP_MAXSTRLEN];
12323  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%"SCIP_LONGINT_FORMAT"_%"SCIP_LONGINT_FORMAT".lp", stat->nnodes, stat->lpcount);
12324  SCIP_CALL( SCIPlpWrite(lp, fname) );
12325  SCIPmessagePrintInfo("wrote LP to file <%s> (primal simplex, uobjlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
12326  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol,
12327  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
12328  }
12329 #endif
12330 
12331  /* start timing */
12332  if( lp->diving || lp->probing )
12333  {
12334  if( lp->strongbranchprobing )
12335  SCIPclockStart(stat->strongbranchtime, set);
12336  else
12337  SCIPclockStart(stat->divinglptime, set);
12338 
12339  timedelta = 0.0; /* unused for diving or probing */
12340  }
12341  else
12342  {
12343  SCIPclockStart(stat->primallptime, set);
12344  timedelta = -SCIPclockGetTime(stat->primallptime);
12345  }
12346 
12347  /* call primal simplex */
12348  retcode = SCIPlpiSolvePrimal(lp->lpi);
12349  if( retcode == SCIP_LPERROR )
12350  {
12351  *lperror = TRUE;
12352  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") primal simplex solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
12353  }
12354  else
12355  {
12356  SCIP_CALL( retcode );
12357  }
12359  lp->solisbasic = TRUE;
12360 
12361  /* stop timing */
12362  if( lp->diving || lp->probing )
12363  {
12364  if( lp->strongbranchprobing )
12365  SCIPclockStop(stat->strongbranchtime, set);
12366  else
12367  SCIPclockStop(stat->divinglptime, set);
12368  }
12369  else
12370  {
12371  timedelta += SCIPclockGetTime(stat->primallptime);
12372  SCIPclockStop(stat->primallptime, set);
12373  }
12374 
12375  /* count number of iterations */
12376  stat->lpcount++;
12377  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12378  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12379  {
12380  if( !lp->strongbranchprobing )
12381  {
12382  stat->nlps++;
12383  stat->nlpiterations += iterations;
12384  }
12385  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12386  {
12387  stat->nprimalresolvelps++;
12388  stat->nprimalresolvelpiterations += iterations;
12389  }
12390  if( lp->diving || lp->probing )
12391  {
12392  if( lp->strongbranchprobing )
12393  {
12394  stat->nsbdivinglps++;
12395  stat->nsbdivinglpiterations += iterations;
12396  }
12397  else
12398  {
12399  stat->lastdivenode = stat->nnodes;
12400  stat->ndivinglps++;
12401  stat->ndivinglpiterations += iterations;
12402  }
12403  }
12404  else
12405  {
12406  stat->nprimallps++;
12407  stat->nprimallpiterations += iterations;
12408  }
12409  }
12410  else
12411  {
12412  if ( ! lp->diving && ! lp->probing )
12413  {
12414  stat->nprimalzeroitlps++;
12415  stat->primalzeroittime += timedelta;
12416  }
12417 
12418  if ( keepsol && !(*lperror) )
12419  {
12420  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
12421  if( lp->validsollp == stat->lpcount-1 )
12422  lp->validsollp = stat->lpcount;
12423  if( lp->validfarkaslp == stat->lpcount-1 )
12424  lp->validfarkaslp = stat->lpcount;
12425  }
12426  }
12427 
12428  SCIPdebugMessage("solved LP %"SCIP_LONGINT_FORMAT" with primal simplex (diving=%d, nprimallps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
12429  stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
12430 
12431  return SCIP_OKAY;
12432 }
12433 
12434 /** calls LPI to perform dual simplex, measures time and counts iterations */
12435 static
12437  SCIP_LP* lp, /**< current LP data */
12438  SCIP_SET* set, /**< global SCIP settings */
12439  SCIP_STAT* stat, /**< problem statistics */
12440  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12441  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12442  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12443  )
12444 {
12445  SCIP_Real timedelta;
12446  SCIP_RETCODE retcode;
12447  int iterations;
12448 
12449  assert(lp != NULL);
12450  assert(lp->flushed);
12451  assert(set != NULL);
12452  assert(stat != NULL);
12453  assert(lperror != NULL);
12454 
12455  SCIPdebugMessage("solving LP %"SCIP_LONGINT_FORMAT" (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
12456  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12457 
12458  *lperror = FALSE;
12459 
12460 #if 0
12461  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
12462  {
12463  char fname[SCIP_MAXSTRLEN];
12464  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%"SCIP_LONGINT_FORMAT"_%"SCIP_LONGINT_FORMAT".lp", stat->nnodes, stat->lpcount);
12465  SCIP_CALL( SCIPlpWrite(lp, fname) );
12466  SCIPmessagePrintInfo("wrote LP to file <%s> (dual simplex, uobjlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
12467  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol,
12468  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
12469  }
12470 #endif
12471 
12472  /* start timing */
12473  if( lp->diving || lp->probing )
12474  {
12475  if( lp->strongbranchprobing )
12476  SCIPclockStart(stat->strongbranchtime, set);
12477  else
12478  SCIPclockStart(stat->divinglptime, set);
12479 
12480  timedelta = 0.0; /* unused for diving or probing */
12481  }
12482  else
12483  {
12484  SCIPclockStart(stat->duallptime, set);
12485  timedelta = -SCIPclockGetTime(stat->duallptime);
12486  }
12487 
12488  /* call dual simplex */
12489  retcode = SCIPlpiSolveDual(lp->lpi);
12490  if( retcode == SCIP_LPERROR )
12491  {
12492  *lperror = TRUE;
12493  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") dual simplex solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
12494  }
12495  else
12496  {
12497  SCIP_CALL( retcode );
12498  }
12500  lp->solisbasic = TRUE;
12501 
12502  /* stop timing */
12503  if( lp->diving || lp->probing )
12504  {
12505  if( lp->strongbranchprobing )
12506  SCIPclockStop(stat->strongbranchtime, set);
12507  else
12508  SCIPclockStop(stat->divinglptime, set);
12509  }
12510  else
12511  {
12512  timedelta += SCIPclockGetTime(stat->duallptime);
12513  SCIPclockStop(stat->duallptime, set);
12514  }
12515 
12516  /* count number of iterations */
12517  stat->lpcount++;
12518  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12519  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12520  {
12521  if( !lp->strongbranchprobing )
12522  {
12523  stat->nlps++;
12524  stat->nlpiterations += iterations;
12525  }
12526  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12527  {
12528  stat->ndualresolvelps++;
12529  stat->ndualresolvelpiterations += iterations;
12530  }
12531  if( lp->diving || lp->probing )
12532  {
12533  if( lp->strongbranchprobing )
12534  {
12535  stat->nsbdivinglps++;
12536  stat->nsbdivinglpiterations += iterations;
12537  }
12538  else
12539  {
12540  stat->lastdivenode = stat->nnodes;
12541  stat->ndivinglps++;
12542  stat->ndivinglpiterations += iterations;
12543  }
12544  }
12545  else
12546  {
12547  stat->nduallps++;
12548  stat->nduallpiterations += iterations;
12549  }
12550  }
12551  else
12552  {
12553  if ( ! lp->diving && ! lp->probing )
12554  {
12555  stat->ndualzeroitlps++;
12556  stat->dualzeroittime += timedelta;
12557  }
12558 
12559  if( keepsol && !(*lperror) )
12560  {
12561  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
12562  if( lp->validsollp == stat->lpcount-1 )
12563  lp->validsollp = stat->lpcount;
12564  if( lp->validfarkaslp == stat->lpcount-1 )
12565  lp->validfarkaslp = stat->lpcount;
12566  }
12567  }
12568 
12569  SCIPdebugMessage("solved LP %"SCIP_LONGINT_FORMAT" with dual simplex (diving=%d, nduallps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
12570  stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12571 
12572  return SCIP_OKAY;
12573 }
12574 
12575 /** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
12576  *
12577  * We follow the approach of the following paper to find a lexicographically minimal optimal
12578  * solution:
12579  *
12580  * Zanette, Fischetti, Balas@n
12581  * Can pure cutting plane algorithms work?@n
12582  * IPCO 2008, Bertinoro, Italy.
12583  *
12584  * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
12585  * heuristic, i.e., we limit the number of components which are minimized.
12586  *
12587  * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
12588  * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
12589  * variables) that have nonzero reduced cost. This fixes the objective function value, because only
12590  * pivots that will not change the objective are allowed afterwards.
12591  *
12592  * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
12593  * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
12594  * candidate is found, we set the objective to minimize this variable. We run the primal simplex
12595  * algorithm (since the objective is changed the solution is not dual feasible anymore; if
12596  * variables out of the basis have been fixed to their lower bound, the basis is also not primal
12597  * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
12598  * reduced cost. We then choose the next variable and iterate.
12599  *
12600  * We stop the process once we do not find candidates or have performed a maximum number of
12601  * iterations.
12602  *
12603  * @todo Does this really produce a lexicographically minimal solution?
12604  * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
12605  * guarantee that these variables will not be changed in later stages? We can fix these variables
12606  * to their lower bound, but this destroys the basis.
12607  * @todo Should we use lexicographical minimization in diving/probing or not?
12608  */
12609 static
12611  SCIP_LP* lp, /**< current LP data */
12612  SCIP_SET* set, /**< global SCIP settings */
12613  SCIP_STAT* stat, /**< problem statistics */
12614  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12615  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12616  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12617  )
12618 {
12619  SCIP_Real timedelta;
12620  SCIP_RETCODE retcode;
12621  int totalIterations;
12622  int lexIterations;
12623  int iterations;
12624  int rounds;
12625 
12626  assert(lp != NULL);
12627  assert(lp->flushed);
12628  assert(set != NULL);
12629  assert(stat != NULL);
12630  assert(lperror != NULL);
12631 
12632  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",
12633  stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
12634 
12635  *lperror = FALSE;
12636 
12637  /* start timing */
12638  if( lp->diving || lp->probing )
12639  {
12640  if( lp->strongbranchprobing )
12641  SCIPclockStart(stat->strongbranchtime, set);
12642  else
12643  SCIPclockStart(stat->divinglptime, set);
12644 
12645  timedelta = 0.0; /* unused for diving or probing */
12646  }
12647  else
12648  {
12649  SCIPclockStart(stat->duallptime, set);
12650  timedelta = -SCIPclockGetTime(stat->duallptime);
12651  }
12652 
12653  /* call dual simplex for first lp */
12654  retcode = SCIPlpiSolveDual(lp->lpi);
12655  if( retcode == SCIP_LPERROR )
12656  {
12657  *lperror = TRUE;
12658  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") dual simplex solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
12659  }
12660  else
12661  {
12662  SCIP_CALL( retcode );
12663  }
12664  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
12665  totalIterations = iterations;
12666 
12667  /* stop timing */
12668  if( lp->diving || lp->probing )
12669  {
12670  if( lp->strongbranchprobing )
12671  SCIPclockStop(stat->strongbranchtime, set);
12672  else
12673  SCIPclockStop(stat->divinglptime, set);
12674  }
12675  else
12676  {
12677  timedelta += SCIPclockGetTime(stat->duallptime);
12678  SCIPclockStop(stat->duallptime, set);
12679  }
12680 
12681  /* count number of iterations */
12682  stat->lpcount++;
12683  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
12684  {
12685  if( lp->strongbranchprobing )
12686  {
12687  stat->nlpiterations += iterations;
12688  }
12689  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
12690  {
12691  stat->ndualresolvelps++;
12692  stat->ndualresolvelpiterations += iterations;
12693  }
12694  if( lp->diving || lp->probing )
12695  {
12696  if( lp->strongbranchprobing )
12697  {
12698  stat->nsbdivinglps++;
12699  stat->nsbdivinglpiterations += iterations;
12700  }
12701  else
12702  {
12703  stat->lastdivenode = stat->nnodes;
12704  stat->ndivinglps++;
12705  stat->ndivinglpiterations += iterations;
12706  }
12707  }
12708  else
12709  {
12710  stat->nduallps++;
12711  stat->nduallpiterations += iterations;
12712  }
12713  }
12714  else
12715  {
12716  if ( ! lp->diving && ! lp->probing )
12717  {
12718  stat->ndualzeroitlps++;
12719  stat->dualzeroittime += timedelta;
12720  }
12721  }
12722  lexIterations = 0;
12723 
12724  /* search for lexicographically minimal optimal solution */
12725  if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
12726  {
12727  SCIP_Bool chooseBasic;
12728  SCIP_Real* primsol;
12729  SCIP_Real* dualsol;
12730  SCIP_Real* redcost;
12731  int* cstat;
12732  int* rstat;
12733  SCIP_Real* newobj;
12734  SCIP_Real* newlb;
12735  SCIP_Real* newub;
12736  SCIP_Real* newlhs;
12737  SCIP_Real* newrhs;
12738  SCIP_Real* oldlb;
12739  SCIP_Real* oldub;
12740  SCIP_Real* oldlhs;
12741  SCIP_Real* oldrhs;
12742  SCIP_Real* oldobj;
12743  SCIP_Bool* fixedc;
12744  SCIP_Bool* fixedr;
12745  int* indcol;
12746  int* indrow;
12747  int* indallcol;
12748  int* indallrow;
12749  int nDualDeg;
12750  int r, c;
12751  int cntcol;
12752  int cntrow;
12753  int nruns;
12754  int pos;
12755 
12756  chooseBasic = set->lp_lexdualbasic;
12757 
12758  /* start timing */
12759  SCIPclockStart(stat->lexduallptime, set);
12760 
12761  /* get all solution information */
12762  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
12763  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
12764  if( chooseBasic )
12765  {
12766  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
12767  }
12768  else
12769  primsol = NULL;
12770 
12771  /* get basic and nonbasic information */
12772  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
12773  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
12774 
12775  /* save bounds, lhs/rhs, and objective */
12776  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldobj, lp->nlpicols) );
12777  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlb, lp->nlpicols) );
12778  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldub, lp->nlpicols) );
12779  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlhs, lp->nlpirows) );
12780  SCIP_CALL( SCIPsetAllocBufferArray(set, &oldrhs, lp->nlpirows) );
12781  SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
12782  SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
12783  SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
12784 
12785  /* get storage for several arrays */
12786  SCIP_CALL( SCIPsetAllocBufferArray(set, &newlb, lp->nlpicols) );
12787  SCIP_CALL( SCIPsetAllocBufferArray(set, &newub, lp->nlpicols) );
12788  SCIP_CALL( SCIPsetAllocBufferArray(set, &indcol, lp->nlpicols) );
12789 
12790  SCIP_CALL( SCIPsetAllocBufferArray(set, &newlhs, lp->nlpirows) );
12791  SCIP_CALL( SCIPsetAllocBufferArray(set, &newrhs, lp->nlpirows) );
12792  SCIP_CALL( SCIPsetAllocBufferArray(set, &indrow, lp->nlpirows) );
12793 
12794  SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
12795  SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
12796 
12797  SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedc, lp->nlpicols) );
12798  SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedr, lp->nlpirows) );
12799 
12800  /* initialize: set objective to 0, get fixed variables */
12801  SCIP_CALL( SCIPsetAllocBufferArray(set, &newobj, lp->nlpicols) );
12802  for( c = 0; c < lp->nlpicols; ++c )
12803  {
12804  newobj[c] = 0.0;
12805  indallcol[c] = c;
12806  if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
12807  fixedc[c] = TRUE;
12808  else
12809  fixedc[c] = FALSE;
12810  }
12811 
12812  /* initialize: get fixed slack variables */
12813  for( r = 0; r < lp->nlpirows; ++r )
12814  {
12815  indallrow[r] = r;
12816  if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
12817  fixedr[r] = TRUE;
12818  else
12819  fixedr[r] = FALSE;
12820  }
12821 
12822 #ifdef DEBUG_LEXDUAL
12823  {
12824  int j;
12825 
12826  if( !chooseBasic )
12827  {
12828  assert(primsol == NULL);
12829  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
12830  }
12831  assert(primsol != NULL);
12832  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
12833  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
12834 
12835  for( j = 0; j < lp->nlpicols; ++j )
12836  {
12837  if( fixedc[j] )
12838  {
12839  SCIPdebugMessage("%f (%d) [f] ", primsol[j], j);
12840  }
12841  else
12842  {
12843  char type;
12844  switch( (SCIP_BASESTAT) cstat[j] )
12845  {
12846  case SCIP_BASESTAT_LOWER:
12847  type = 'l';
12848  break;
12849  case SCIP_BASESTAT_UPPER:
12850  type = 'u';
12851  break;
12852  case SCIP_BASESTAT_ZERO:
12853  type = 'z';
12854  break;
12855  case SCIP_BASESTAT_BASIC:
12856  type = 'b';
12857  break;
12858  default:
12859  type = '?';
12860  SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
12861  SCIPABORT();
12862  }
12863  SCIPdebugMessage("%f (%d) [%c] ", primsol[j], j, type);
12864  }
12865  }
12866  SCIPdebugMessage("\n\n");
12867 
12868  if( !chooseBasic )
12869  {
12870  SCIPsetFreeBufferArray(set, &primsol);
12871  assert(primsol == NULL);
12872  }
12873  }
12874 #endif
12875 
12876  /* perform lexicographic rounds */
12877  pos = -1;
12878  nruns = 0;
12879  rounds = 0;
12880  /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
12881  do
12882  {
12883  int oldpos;
12884 
12885  /* get current solution */
12886  if( chooseBasic )
12887  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
12888  else
12889  {
12890  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
12891  assert(primsol == NULL);
12892  }
12893 
12894  /* get current basis */
12895  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
12896 
12897  /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
12898  nDualDeg = 0;
12899  cntcol = 0;
12900  oldpos = pos;
12901  pos = -1;
12902  for( c = 0; c < lp->nlpicols; ++c )
12903  {
12904  if( !fixedc[c] )
12905  {
12906  /* check whether variable is in basis */
12907  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
12908  {
12909  /* store first candidate */
12910  if( pos == -1 && c > oldpos )
12911  {
12912  if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
12913  pos = c;
12914  }
12915  }
12916  else
12917  {
12918  /* reduced cost == 0 -> possible candidate */
12919  if( SCIPsetIsFeasZero(set, redcost[c]) )
12920  {
12921  ++nDualDeg;
12922  /* only if we have not yet found a candidate */
12923  if( pos == -1 && c > oldpos )
12924  {
12925  /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
12926  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
12927  {
12928  newlb[cntcol] = oldlb[c];
12929  newub[cntcol] = oldlb[c];
12930  indcol[cntcol++] = c;
12931  fixedc[c] = TRUE;
12932  }
12933  else /* found a non-fixed candidate */
12934  {
12935  if( !chooseBasic )
12936  pos = c;
12937  }
12938  }
12939  }
12940  else
12941  {
12942  /* nonzero reduced cost -> variable can be fixed */
12943  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
12944  {
12945  newlb[cntcol] = oldlb[c];
12946  newub[cntcol] = oldlb[c];
12947  }
12948  else
12949  {
12950  if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
12951  {
12952  newlb[cntcol] = oldub[c];
12953  newub[cntcol] = oldub[c];
12954  }
12955  else
12956  {
12957  assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
12958  newlb[cntcol] = 0.0;
12959  newub[cntcol] = 0.0;
12960  }
12961  }
12962  indcol[cntcol++] = c;
12963  fixedc[c] = TRUE;
12964  }
12965  }
12966  }
12967  }
12968 
12969  /* check rows */
12970  cntrow = 0;
12971  for( r = 0; r < lp->nlpirows; ++r )
12972  {
12973  if( !fixedr[r] )
12974  {
12975  /* consider only nonbasic rows */
12976  if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
12977  {
12978  assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
12979  if( SCIPsetIsFeasZero(set, dualsol[r]) )
12980  ++nDualDeg;
12981  else
12982  {
12983  if( SCIPsetIsFeasPositive(set, dualsol[r]) )
12984  {
12985  assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
12986  newlhs[cntrow] = oldlhs[r];
12987  newrhs[cntrow] = oldlhs[r];
12988  }
12989  else
12990  {
12991  assert(!SCIPsetIsInfinity(set, oldrhs[r]));
12992  newlhs[cntrow] = oldrhs[r];
12993  newrhs[cntrow] = oldrhs[r];
12994  }
12995  indrow[cntrow++] = r;
12996  fixedr[r] = TRUE;
12997  }
12998  }
12999  }
13000  }
13001 
13002  if( nDualDeg > 0 && pos >= 0 )
13003  {
13004  assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
13005 
13006  /* change objective */
13007  if( nruns == 0 )
13008  {
13009  /* set objective to appropriate unit vector for first run */
13010  newobj[pos] = 1.0;
13011  SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
13012  }
13013  else
13014  {
13015  /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
13016  SCIP_Real obj = 1.0;
13017  SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
13018  }
13019 
13020  /* fix variables */
13021  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
13022  SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
13023 
13024  /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
13025  retcode = SCIPlpiSolvePrimal(lp->lpi);
13026  if( retcode == SCIP_LPERROR )
13027  {
13028  *lperror = TRUE;
13029  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") in lex-dual: primal simplex solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
13030  }
13031  else
13032  {
13033  SCIP_CALL( retcode );
13034  }
13035  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13036  lexIterations += iterations;
13037 
13038 #ifdef DEBUG_LEXDUAL
13039  if( iterations > 0 )
13040  {
13041  int j;
13042 
13043  if( !chooseBasic )
13044  {
13045  assert(primsol == NULL);
13046  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
13047  }
13048  assert(primsol != NULL);
13049  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
13050 
13051  for( j = 0; j < lp->nlpicols; ++j )
13052  {
13053  if( fixedc[j] )
13054  {
13055  SCIPdebugMessage("%f (%d) [f] ", primsol[j], j);
13056  }
13057  else
13058  {
13059  char cstart = '[';
13060  char cend = ']';
13061  char type;
13062 
13063  if(j == pos)
13064  {
13065  cstart = '*';
13066  cend = '*';
13067  }
13068 
13069  switch( (SCIP_BASESTAT) cstat[j] )
13070  {
13071  case SCIP_BASESTAT_LOWER:
13072  type = 'l';
13073  break;
13074  case SCIP_BASESTAT_UPPER:
13075  type = 'u';
13076  break;
13077  case SCIP_BASESTAT_ZERO:
13078  type = 'z';
13079  break;
13080  case SCIP_BASESTAT_BASIC:
13081  type = 'b';
13082  break;
13083  default:
13084  type = '?';
13085  SCIPerrorMessage("unknown base state %d\n", cstat[j]);
13086  SCIPABORT();
13087  }
13088  SCIPdebugMessage("%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
13089  }
13090  }
13091  SCIPdebugMessage("\n\n");
13092 
13093  if( !chooseBasic )
13094  {
13095  SCIPsetFreeBufferArray(set, &primsol);
13096  assert(primsol == NULL);
13097  }
13098  }
13099 #endif
13100 
13101  /* count only as round if iterations have been performed */
13102  if( iterations > 0 )
13103  ++rounds;
13104  ++nruns;
13105  }
13106  }
13107  while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
13108 
13109  /* reset bounds, lhs/rhs, and obj */
13110  SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
13111  SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
13112  SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
13113 
13114  /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
13115  retcode = SCIPlpiSolveDual(lp->lpi);
13116  if( retcode == SCIP_LPERROR )
13117  {
13118  *lperror = TRUE;
13119  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") dual simplex solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
13120  }
13121  else
13122  {
13123  SCIP_CALL( retcode );
13124  }
13125  assert(SCIPlpiIsOptimal(lp->lpi));
13126  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13127  lexIterations += iterations;
13128 
13129  /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
13130 
13131  /* count number of iterations */
13132  if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
13133  stat->nlps++;
13134 
13135  if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
13136  {
13137  stat->nlpiterations += lexIterations;
13138  if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
13139  {
13140  stat->nlexdualresolvelps++;
13141  stat->nlexdualresolvelpiterations += lexIterations;
13142  }
13143  stat->nlexduallps++;
13144  stat->nlexduallpiterations += lexIterations;
13145 
13146  totalIterations += lexIterations;
13147  }
13148 
13149  /* free space */
13150  SCIPsetFreeBufferArray(set, &newobj);
13151 
13152  SCIPsetFreeBufferArray(set, &fixedr);
13153  SCIPsetFreeBufferArray(set, &fixedc);
13154 
13155  SCIPsetFreeBufferArray(set, &indallrow);
13156  SCIPsetFreeBufferArray(set, &indallcol);
13157 
13158  SCIPsetFreeBufferArray(set, &indrow);
13159  SCIPsetFreeBufferArray(set, &newrhs);
13160  SCIPsetFreeBufferArray(set, &newlhs);
13161 
13162  SCIPsetFreeBufferArray(set, &indcol);
13163  SCIPsetFreeBufferArray(set, &newub);
13164  SCIPsetFreeBufferArray(set, &newlb);
13165 
13166  SCIPsetFreeBufferArray(set, &oldobj);
13167  SCIPsetFreeBufferArray(set, &oldrhs);
13168  SCIPsetFreeBufferArray(set, &oldlhs);
13169  SCIPsetFreeBufferArray(set, &oldub);
13170  SCIPsetFreeBufferArray(set, &oldlb);
13171 
13172  SCIPsetFreeBufferArray(set, &rstat);
13173  SCIPsetFreeBufferArray(set, &cstat);
13174 
13175  SCIPsetFreeBufferArray(set, &redcost);
13176  SCIPsetFreeBufferArray(set, &dualsol);
13177  if( chooseBasic )
13178  SCIPsetFreeBufferArray(set, &primsol);
13179 
13180  /* stop timing */
13181  SCIPclockStop(stat->lexduallptime, set);
13182 
13183  SCIPdebugMessage("solved LP %"SCIP_LONGINT_FORMAT" with lex dual simplex (diving=%d, nduallps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
13184  stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
13185  }
13187  lp->solisbasic = TRUE;
13188 
13189  if( totalIterations > 0 && !lp->strongbranchprobing )
13190  stat->nlps++;
13191  else
13192  {
13193  if( keepsol && !(*lperror) )
13194  {
13195  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
13196  if( lp->validsollp == stat->lpcount-1 )
13197  lp->validsollp = stat->lpcount;
13198  if( lp->validfarkaslp == stat->lpcount-1 )
13199  lp->validfarkaslp = stat->lpcount;
13200  }
13201  }
13202 
13203  return SCIP_OKAY;
13204 }
13205 
13206 /** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
13207 static
13209  SCIP_LP* lp, /**< current LP data */
13210  SCIP_SET* set, /**< global SCIP settings */
13211  SCIP_STAT* stat, /**< problem statistics */
13212  SCIP_Bool crossover, /**< should crossover be performed? */
13213  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13214  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13215  )
13216 {
13217  SCIP_Real timedelta;
13218  SCIP_RETCODE retcode;
13219  int iterations;
13220 
13221  assert(lp != NULL);
13222  assert(lp->flushed);
13223  assert(set != NULL);
13224  assert(stat != NULL);
13225  assert(lperror != NULL);
13226 
13227  SCIPdebugMessage("solving LP %"SCIP_LONGINT_FORMAT" (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%"SCIP_LONGINT_FORMAT", ndivinglps=%"SCIP_LONGINT_FORMAT")\n",
13228  stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
13229  stat->nbarrierlps, stat->ndivinglps);
13230 
13231  *lperror = FALSE;
13232 
13233 #if 0
13234  if( stat->nnodes == 1 && !lp->diving && !lp->probing )
13235  {
13236  char fname[SCIP_MAXSTRLEN];
13237  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%"SCIP_LONGINT_FORMAT"_%"SCIP_LONGINT_FORMAT".lp", stat->nnodes, stat->lpcount);
13238  SCIP_CALL( SCIPlpWrite(lp, fname) );
13239  SCIPmessagePrintInfo("wrote LP to file <%s> (barrier, uobjlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
13240  fname, lp->lpiuobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
13241  lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
13242  }
13243 #endif
13244 
13245  /* start timing */
13246  if( lp->diving || lp->probing )
13247  {
13248  if( lp->strongbranchprobing )
13249  SCIPclockStart(stat->strongbranchtime, set);
13250  else
13251  SCIPclockStart(stat->divinglptime, set);
13252 
13253  timedelta = 0.0; /* unused for diving or probing */
13254  }
13255  else
13256  {
13257  SCIPclockStart(stat->barrierlptime, set);
13258  timedelta = -SCIPclockGetTime(stat->duallptime);
13259  }
13260 
13261  /* call barrier algorithm */
13262  retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
13263  if( retcode == SCIP_LPERROR )
13264  {
13265  *lperror = TRUE;
13266  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") barrier solving error in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
13267  }
13268  else
13269  {
13270  SCIP_CALL( retcode );
13271  }
13273  lp->solisbasic = crossover;
13274 
13275  /* stop timing */
13276  if( lp->diving || lp->probing )
13277  {
13278  if( lp->strongbranchprobing )
13279  SCIPclockStop(stat->strongbranchtime, set);
13280  else
13281  SCIPclockStop(stat->divinglptime, set);
13282  }
13283  else
13284  {
13285  SCIPclockStop(stat->barrierlptime, set);
13286  timedelta = -SCIPclockGetTime(stat->duallptime);
13287  }
13288 
13289  /* count number of iterations */
13290  stat->lpcount++;
13291  SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
13292  if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
13293  {
13294  if( !lp->strongbranchprobing )
13295  {
13296  stat->nlps++;
13297  stat->nlpiterations += iterations;
13298  }
13299  if( lp->diving || lp->probing )
13300  {
13301  if( lp->strongbranchprobing )
13302  {
13303  stat->nsbdivinglps++;
13304  stat->nsbdivinglpiterations += iterations;
13305  }
13306  else
13307  {
13308  stat->lastdivenode = stat->nnodes;
13309  stat->ndivinglps++;
13310  stat->ndivinglpiterations += iterations;
13311  }
13312  }
13313  else
13314  {
13315  stat->nbarrierlps++;
13316  stat->nbarrierlpiterations += iterations;
13317  }
13318  }
13319  else
13320  {
13321  if ( ! lp->diving && ! lp->probing )
13322  {
13323  stat->nbarrierzeroitlps++;
13324  stat->barrierzeroittime += timedelta;
13325  }
13326 
13327  if( keepsol && !(*lperror) )
13328  {
13329  /* the solution didn't change: if the solution was valid before resolve, it is still valid */
13330  if( lp->validsollp == stat->lpcount-1 )
13331  lp->validsollp = stat->lpcount;
13332  if( lp->validfarkaslp == stat->lpcount-1 )
13333  lp->validfarkaslp = stat->lpcount;
13334  }
13335  }
13336 
13337  SCIPdebugMessage("solved LP %"SCIP_LONGINT_FORMAT" with barrier%s (diving=%d, nduallps=%"SCIP_LONGINT_FORMAT", nbarrierlps=%"SCIP_LONGINT_FORMAT")\n",
13338  stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
13339 
13340  return SCIP_OKAY;
13341 }
13342 
13343 /** solves the LP with the given algorithm */
13344 static
13346  SCIP_LP* lp, /**< current LP data */
13347  SCIP_SET* set, /**< global SCIP settings */
13348  SCIP_STAT* stat, /**< problem statistics */
13349  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
13350  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
13351  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13352  SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
13353  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13354  )
13355 {
13356  SCIP_Real lptimelimit;
13357  SCIP_Bool success;
13358 
13359  assert(lp != NULL);
13360  assert(lp->flushed);
13361  assert(lperror != NULL);
13362 
13363  lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
13364  success = FALSE;
13365  if( lptimelimit > 0.0 )
13366  SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
13367 
13368  if( lptimelimit <= 0.0 || !success )
13369  {
13370  SCIPdebugMessage("time limit of %f seconds could not be set\n", lptimelimit);
13371  *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
13372  *timelimit = TRUE;
13373  return SCIP_OKAY;
13374  }
13375 
13376  SCIPdebugMessage("calling LP algorithm <%s> with a time limit of %f seconds\n", lpalgoName(lpalgo), lptimelimit);
13377 
13378  /* call appropriate LP algorithm */
13379  switch( lpalgo )
13380  {
13382  SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, lperror) );
13383  break;
13384 
13386  /* run dual lexicographic simplex if required */
13387  if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
13388  {
13389  SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
13390  }
13391  else
13392  {
13393  SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
13394  }
13395  break;
13396 
13397  case SCIP_LPALGO_BARRIER:
13398  SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
13399  break;
13400 
13402  SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
13403  break;
13404 
13405  default:
13406  SCIPerrorMessage("invalid LP algorithm\n");
13407  return SCIP_INVALIDDATA;
13408  }
13409 
13410  if( !(*lperror) )
13411  {
13412  /* check for primal and dual feasibility */
13414 
13415  SCIPdebugMessage("LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
13416  }
13417 
13418  return SCIP_OKAY;
13419 }
13420 
13421 #define FEASTOLTIGHTFAC 0.001
13422 /** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
13423 static
13425  SCIP_LP* lp, /**< current LP data */
13426  SCIP_SET* set, /**< global SCIP settings */
13427  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
13428  SCIP_STAT* stat, /**< problem statistics */
13429  SCIP_PROB* prob, /**< problem data */
13430  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
13431  int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
13432  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
13433  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
13434  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
13435  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
13436  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
13437  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
13438  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13439  SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
13440  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13441  )
13442 {
13443  SCIP_Bool success;
13444  SCIP_Bool success2;
13445  SCIP_Bool success3;
13446  SCIP_Bool simplex;
13447  SCIP_Bool itlimishard;
13448 
13449  assert(lp != NULL);
13450  assert(lp->flushed);
13451  assert(set != NULL);
13452  assert(stat != NULL);
13453  assert(lperror != NULL);
13454  assert(timelimit != NULL);
13455 
13456  *lperror = FALSE;
13457 
13458  /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
13459  * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
13460  * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
13461  * SCIP_LP such that we can return a primal ray
13462  */
13463  if( lp->looseobjvalinf > 0 )
13464  {
13465  SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
13466  return SCIP_ERROR;
13467  }
13468 
13469  /* check, whether we solve with a simplex algorithm */
13470  simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
13471 
13472  /* check whether the iteration limit is a hard one */
13473  itlimishard = (itlim == harditlim);
13474 
13475  /* solve with given settings (usually fast but imprecise) */
13476  if( SCIPsetIsInfinity(set, lp->cutoffbound) )
13477  {
13478  SCIP_CALL( lpSetUobjlim(lp, set, lp->cutoffbound) );
13479  }
13480  else
13481  {
13482  SCIP_CALL( lpSetUobjlim(lp, set, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) );
13483  }
13484  SCIP_CALL( lpSetIterationLimit(lp, itlim) );
13485  SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * SCIPsetLpfeastol(set) : SCIPsetLpfeastol(set), &success) );
13486  SCIP_CALL( lpSetDualfeastol(lp, tightdualfeastol ? FEASTOLTIGHTFAC * SCIPsetDualfeastol(set) : SCIPsetDualfeastol(set),
13487  &success) );
13488  SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
13489  : SCIPsetBarrierconvtol(set), &success) );
13490  SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
13491  SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
13492  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
13493  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
13494  SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
13495  SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
13496  SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
13497  SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
13498  SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
13499  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13500  resolve = FALSE; /* only the first solve should be counted as resolving call */
13501 
13502  /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
13503  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13504  return SCIP_OKAY;
13505  else if( !set->lp_checkstability )
13506  {
13507  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13508  if( success )
13509  {
13510  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13511  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13512  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13513  return SCIP_OKAY;
13514  }
13515  }
13516 
13517  /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
13518  * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
13519  */
13520 
13521  /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
13522  * do this only if the iteration limit was not exceeded in the last LP solving call
13523  */
13524  if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
13525  {
13526  SCIP_CALL( lpSetFastmip(lp, 0, &success) );
13527  if( success )
13528  {
13529  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13530  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again with %s without FASTMIP\n",
13531  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13532  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13533 
13534  /* check for stability */
13535  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13536  return SCIP_OKAY;
13537  else if( !set->lp_checkstability )
13538  {
13539  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13540  if( success )
13541  {
13542  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13543  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13544  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13545  return SCIP_OKAY;
13546  }
13547  }
13548  }
13549  }
13550 
13551  /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
13552  * and go directly to solving the LP from scratch
13553  */
13554  if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
13555  {
13556  /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
13557  SCIP_CALL( lpSetScaling(lp, !set->lp_scaling, &success) );
13558  if( success )
13559  {
13560  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13561  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again with %s %s scaling\n",
13562  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_scaling ? "with" : "without");
13563  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13564 
13565  /* check for stability */
13566  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13567  return SCIP_OKAY;
13568  else if( !set->lp_checkstability )
13569  {
13570  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13571  if( success )
13572  {
13573  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13574  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13575  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13576  return SCIP_OKAY;
13577  }
13578  }
13579 
13580  /* reset scaling */
13581  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
13582  assert(success);
13583  }
13584  }
13585 
13586  /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
13587  * and go directly to solving the LP from scratch
13588  */
13589  if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
13590  {
13591  /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
13592  SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
13593  if( success )
13594  {
13595  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13596  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again with %s %s presolving\n",
13597  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
13598  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13599 
13600  /* check for stability */
13601  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13602  return SCIP_OKAY;
13603  else if( !set->lp_checkstability )
13604  {
13605  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13606  if( success )
13607  {
13608  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13609  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13610  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13611  return SCIP_OKAY;
13612  }
13613  }
13614 
13615  /* reset presolving */
13616  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
13617  assert(success);
13618  }
13619  }
13620 
13621  /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
13622  * do this only if the iteration limit was not exceeded in the last LP solving call
13623  */
13624  if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
13625  ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
13626  {
13627  success = FALSE;
13628  if( !tightprimfeastol )
13629  {
13630  SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * SCIPsetLpfeastol(set), &success) );
13631  }
13632 
13633  success2 = FALSE;
13634  if( !tightdualfeastol )
13635  {
13637  }
13638 
13639  success3 = FALSE;
13640  if( !simplex && !tightprimfeastol && !tightdualfeastol )
13641  {
13643  }
13644 
13645  if( success || success2 || success3 )
13646  {
13647  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13648  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again with %s with tighter primal and dual feasibility tolerance\n",
13649  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13650  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13651 
13652  /* check for stability */
13653  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
13654  return SCIP_OKAY;
13655  else if( !set->lp_checkstability )
13656  {
13657  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13658  if( success )
13659  {
13660  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13661  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13662  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13663  return SCIP_OKAY;
13664  }
13665  }
13666 
13667  /* reset feasibility tolerance */
13668  if( !tightprimfeastol )
13669  {
13670  SCIP_CALL( lpSetFeastol(lp, SCIPsetLpfeastol(set), &success) );
13671  }
13672  if( !tightdualfeastol )
13673  {
13674  SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
13675  }
13676  if( !simplex && !tightprimfeastol && !tightdualfeastol )
13677  {
13678  SCIP_CALL( lpSetBarrierconvtol(lp, SCIPsetBarrierconvtol(set), &success) );
13679  }
13680  }
13681  }
13682 
13683  /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
13684  * the given iteration limit might be a soft one to restrict resolving calls only */
13685  SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
13686 
13687  /* if not already done, solve again from scratch */
13688  if( !fromscratch && simplex )
13689  {
13690  SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
13691  if( success )
13692  {
13693  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13694  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again from scratch with %s\n",
13695  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13696  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13697 
13698  /* check for stability */
13699  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13700  return SCIP_OKAY;
13701  else if( !set->lp_checkstability )
13702  {
13703  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13704  if( success )
13705  {
13706  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13707  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13708  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13709  return SCIP_OKAY;
13710  }
13711  }
13712  }
13713  }
13714 
13715  /* solve again, use other simplex this time */
13716  if( simplex )
13717  {
13719  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13720  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again from scratch with %s\n",
13721  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13722  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13723 
13724  /* check for stability */
13725  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13726  return SCIP_OKAY;
13727  else if( !set->lp_checkstability )
13728  {
13729  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13730  if( success )
13731  {
13732  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13733  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13734  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13735  return SCIP_OKAY;
13736  }
13737  }
13738 
13739  /* solve again with opposite scaling and other simplex */
13740  SCIP_CALL( lpSetScaling(lp, !set->lp_scaling, &success) );
13741  if( success )
13742  {
13743  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13744  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again from scratch with %s %s scaling\n",
13745  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_scaling ? "with" : "without");
13746  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13747 
13748  /* check for stability */
13749  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13750  return SCIP_OKAY;
13751  else if( !set->lp_checkstability )
13752  {
13753  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13754  if( success )
13755  {
13756  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13757  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13758  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13759  return SCIP_OKAY;
13760  }
13761  }
13762 
13763  /* reset scaling */
13764  SCIP_CALL( lpSetScaling(lp, set->lp_scaling, &success) );
13765  assert(success);
13766  }
13767 
13768  /* solve again with opposite presolving and other simplex */
13769  SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
13770  if( success )
13771  {
13772  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13773  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again from scratch with %s %s presolving\n",
13774  stat->nnodes, stat->nlps, lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
13775  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13776 
13777  /* check for stability */
13778  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
13779  return SCIP_OKAY;
13780  else if( !set->lp_checkstability )
13781  {
13782  SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, &success) );
13783  if( success )
13784  {
13785  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13786  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- ignoring instability of %s\n",
13787  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13788  return SCIP_OKAY;
13789  }
13790  }
13791 
13792  /* reset presolving */
13793  SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
13794  assert(success);
13795  }
13796 
13797  /* solve again with tighter feasibility tolerance, use other simplex this time */
13798  if( !tightprimfeastol || !tightdualfeastol )
13799  {
13800  success = FALSE;
13801  if( !tightprimfeastol )
13802  {
13803  SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * SCIPsetLpfeastol(set), &success) );
13804  }
13805 
13806  success2 = FALSE;
13807  if( !tightdualfeastol )
13808  {
13810  }
13811 
13812  if( success || success2 )
13813  {
13814  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13815  "(node %"SCIP_LONGINT_FORMAT") numerical troubles in LP %"SCIP_LONGINT_FORMAT" -- solve again from scratch with %s with tighter feasibility tolerance\n",
13816  stat->nnodes, stat->nlps, lpalgoName(lpalgo));
13817  SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, timelimit, lperror) );
13818 
13819  /* check for stability */
13820  if( *timelimit || (!(*lperror) && SCIPlpiIsStable(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 feasibility tolerance */
13835  if( !tightprimfeastol )
13836  {
13837  SCIP_CALL( lpSetFeastol(lp, SCIPsetLpfeastol(set), &success) );
13838  }
13839  if( !tightdualfeastol )
13840  {
13841  SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
13842  }
13843  }
13844  }
13845  }
13846 
13847  /* nothing worked -- exit with an LPERROR */
13848  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH, "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles in LP %"SCIP_LONGINT_FORMAT"\n",
13849  stat->nnodes, stat->nlps);
13850  *lperror = TRUE;
13851 
13852  return SCIP_OKAY;
13853 }
13854 
13855 /** solves the LP with the given algorithm and evaluates return status */
13856 static
13858  SCIP_LP* lp, /**< current LP data */
13859  SCIP_SET* set, /**< global SCIP settings */
13860  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
13861  SCIP_STAT* stat, /**< problem statistics */
13862  SCIP_PROB* prob, /**< problem data */
13863  SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
13864  int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
13865  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
13866  SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
13867  SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
13868  SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
13869  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
13870  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
13871  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
13872  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
13873  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
13874  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
13875  )
13876 {
13877  SCIP_Bool solvedprimal;
13878  SCIP_Bool solveddual;
13879  SCIP_Bool timelimit;
13880  int itlim;
13881 
13882  assert(lp != NULL);
13883  assert(lp->flushed);
13884  assert(set != NULL);
13885  assert(stat != NULL);
13886  assert(lperror != NULL);
13887 
13888  checkLinks(lp);
13889 
13890  solvedprimal = FALSE;
13891  solveddual = FALSE;
13892  timelimit = FALSE;
13893 
13894  /* select the basic iteration limit depending on whether this is a resolving call or not */
13895  itlim = ( resolve ? resolveitlim : harditlim );
13896 
13897  SOLVEAGAIN:
13898  /* call simplex */
13899  SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
13900  keepsol, &timelimit, lperror) );
13901  resolve = FALSE; /* only the first solve should be counted as resolving call */
13902  solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
13903  solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
13904 
13905  /* check, if an error occurred */
13906  if( *lperror )
13907  {
13908  SCIPdebugMessage("unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
13909  lp->solved = FALSE;
13911  return SCIP_OKAY;
13912  }
13913 
13914  /* check, if a time limit was exceeded */
13915  if( timelimit )
13916  {
13917  SCIPdebugMessage("time limit exceeded before solving LP\n");
13918  lp->solved = TRUE;
13920  lp->lpobjval = -SCIPsetInfinity(set);
13921  return SCIP_OKAY;
13922  }
13923 
13924  /* only one should return true */
13925  assert(!(SCIPlpiIsOptimal(lp->lpi) && SCIPlpiIsObjlimExc(lp->lpi) && SCIPlpiIsPrimalInfeasible(lp->lpi) &&
13927 
13928  /* evaluate solution status */
13929  if( SCIPlpiIsOptimal(lp->lpi) )
13930  {
13931  assert(lp->primalfeasible);
13932  assert(lp->dualfeasible);
13934  SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
13935  if( SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) )
13936  {
13937  /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
13938  SCIPdebugMessage("optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiuobjlim);
13940  lp->lpobjval = SCIPsetInfinity(set);
13941  }
13942  /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
13943  * reached if the LP objective value is greater than the cutoff bound
13944  */
13946  || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
13947  }
13948  else if( SCIPlpiIsObjlimExc(lp->lpi) )
13949  {
13950  assert(!lpCutoffDisabled(set));
13952  lp->lpobjval = SCIPsetInfinity(set);
13953  }
13954  else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
13955  {
13956  /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
13957  if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
13958  {
13959  assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
13960  lpalgo = SCIP_LPALGO_DUALSIMPLEX;
13961  goto SOLVEAGAIN;
13962  }
13964  lp->lpobjval = SCIPsetInfinity(set);
13965  }
13966  else if( SCIPlpiExistsPrimalRay(lp->lpi) )
13967  {
13968  /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
13969  if( needprimalray && !SCIPlpiHasPrimalRay(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
13970  {
13971  assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
13972  lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
13973  goto SOLVEAGAIN;
13974  }
13976  lp->lpobjval = -SCIPsetInfinity(set);
13977  }
13978  else if( SCIPlpiIsIterlimExc(lp->lpi) )
13979  {
13980  SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
13982  }
13983  else if( SCIPlpiIsTimelimExc(lp->lpi) )
13984  {
13985  lp->lpobjval = -SCIPsetInfinity(set);
13987  }
13988  else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
13989  {
13990  assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
13991  lpalgo = SCIP_LPALGO_DUALSIMPLEX;
13992  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13993  "(node %"SCIP_LONGINT_FORMAT") solution status of LP %"SCIP_LONGINT_FORMAT" could not be proven (internal status:%d) -- solve again with %s\n",
13994  stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
13995  goto SOLVEAGAIN;
13996  }
13997  else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
13998  {
13999  assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
14000  lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
14001  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14002  "(node %"SCIP_LONGINT_FORMAT") solution status of LP %"SCIP_LONGINT_FORMAT" could not be proven (internal status:%d) -- solve again with %s\n",
14003  stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
14004  goto SOLVEAGAIN;
14005  }
14006  else
14007  {
14008  SCIPerrorMessage("(node %"SCIP_LONGINT_FORMAT") error or unknown return status of %s in LP %"SCIP_LONGINT_FORMAT" (internal status: %d)\n",
14009  stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
14011  return SCIP_LPERROR;
14012  }
14013 
14014  lp->solved = TRUE;
14015 
14016  SCIPdebugMessage("solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
14019 
14020  return SCIP_OKAY;
14021 }
14022 
14023 /** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
14024 static
14026  SCIP_LP* lp, /**< current LP data */
14027  BMS_BLKMEM* blkmem, /**< block memory */
14028  SCIP_SET* set, /**< global SCIP settings */
14029  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
14030  SCIP_STAT* stat, /**< problem statistics */
14031  SCIP_PROB* prob, /**< problem data */
14032  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14033  int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
14034  int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
14035  SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
14036  SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
14037  int fastmip, /**< which FASTMIP setting of LP solver should be used? */
14038  SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
14039  SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
14040  SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
14041  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
14042  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
14043  )
14044 {
14045  SCIP_Bool resolve;
14046  char algo;
14047 
14048  assert(lp != NULL);
14049  assert(set != NULL);
14050  assert(lperror != NULL);
14051 
14052  /* flush changes to the LP solver */
14053  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
14054  fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
14055 
14056  /* select LP algorithm to apply */
14057  resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
14058  algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
14059 
14060  switch( algo )
14061  {
14062  case 's':
14063  /* select simplex method */
14064  if( lp->dualfeasible || !lp->primalfeasible )
14065  {
14066  SCIPdebugMessage("solving dual LP\n");
14067  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
14068  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14069  }
14070  else
14071  {
14072  SCIPdebugMessage("solving primal LP\n");
14073  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
14074  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14075  }
14076  break;
14077 
14078  case 'p':
14079  SCIPdebugMessage("solving primal LP\n");
14080  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
14081  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14082  break;
14083 
14084  case 'd':
14085  SCIPdebugMessage("solving dual LP\n");
14086  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
14087  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14088  break;
14089 
14090  case 'b':
14091  SCIPdebugMessage("solving barrier LP\n");
14092  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
14093  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14094  break;
14095 
14096  case 'c':
14097  SCIPdebugMessage("solving barrier LP with crossover\n");
14098  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
14099  needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14100  break;
14101 
14102  default:
14103  SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
14104  return SCIP_PARAMETERWRONGVAL;
14105  }
14106  assert(!(*lperror) || !lp->solved);
14107 
14108  return SCIP_OKAY;
14109 }
14110 
14111 #ifndef NDEBUG
14112 /** checks if the lazy bounds are valid */
14113 static
14115  SCIP_LP* lp, /**< LP data */
14116  SCIP_SET* set /**< global SCIP settings */
14117  )
14118 {
14119  SCIP_COL* col;
14120  int c;
14121 
14122  assert(lp->flushed);
14123 
14124  for( c = 0; c < lp->nlazycols; ++c )
14125  {
14126  col = lp->lazycols[c];
14127 
14128  /* in case lazy bounds are given, check that the primal solution satisfies them */
14129  assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
14130  assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
14131  }
14132 }
14133 #else
14134 #define checkLazyBounds(lp, set) /**/
14135 #endif
14136 
14137 /** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
14138  * diving
14139  */
14140 static
14142  SCIP_LP* lp, /**< LP data */
14143  SCIP_SET* set /**< global SCIP settings */
14144  )
14145 {
14146  SCIP_COL* col;
14147  int c;
14148 
14149  assert(lp->nlazycols > 0);
14150 
14151  /* return, if we are in diving, and bounds were already applied
14152  * or if we are not in diving and bounds were not applied
14153  */
14154  if( lp->diving == lp->divinglazyapplied )
14155  return SCIP_OKAY;
14156 
14157  SCIPdebugMessage("mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
14158  lp->diving, lp->divinglazyapplied);
14159 
14160  for( c = 0; c < lp->nlazycols; ++c )
14161  {
14162  col = lp->lazycols[c];
14163 
14164  /* if the column has a lazy lower bound, mark its lower bounds as changed */
14165  if( !SCIPsetIsInfinity(set, -col->lazylb) )
14166  {
14167  assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb)); /*lint !e777*/
14168  assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
14169  || (col->flushedlb == -SCIPlpiInfinity(lp->lpi))); /*lint !e777*/
14170 
14171  /* insert column in the chgcols list (if not already there) */
14172  SCIP_CALL( insertColChgcols(col, set, lp) );
14173 
14174  /* mark bound change in the column */
14175  col->lbchanged = TRUE;
14176  }
14177 
14178  /* if the column has a lazy upper bound, mark its upper bounds as changed */
14179  if( !SCIPsetIsInfinity(set, col->lazyub) )
14180  {
14181  assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub)); /*lint !e777*/
14182  assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
14183  || (col->flushedub == SCIPlpiInfinity(lp->lpi))); /*lint !e777*/
14184 
14185  /* insert column in the chgcols list (if not already there) */
14186  SCIP_CALL( insertColChgcols(col, set, lp) );
14187 
14188  /* mark bound change in the column */
14189  col->ubchanged = TRUE;
14190  }
14191  }
14192 
14193  /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
14194  * if not, we just removed them
14195  */
14196  lp->divinglazyapplied = lp->diving;
14197 
14198  return SCIP_OKAY;
14199 }
14200 
14201 /** returns the iteration limit for an LP resolving call */
14202 static
14204  SCIP_SET* set, /**< global SCIP settings */
14205  SCIP_STAT* stat, /**< dynamic problem statistics */
14206  int itlim /**< hard iteration limit */
14207  )
14208 {
14209  /* no limit set or average not yet reliable */
14210  if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
14211  return itlim;
14212  /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
14213  if( itlim == -1 )
14214  itlim = INT_MAX;
14215  /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
14216  return (int) MIN(itlim, MAX(set->lp_resolveitermin,
14217  (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
14218 }
14219 
14220 
14221 
14222 /** solves the LP with simplex algorithm, and copy the solution into the column's data */
14224  SCIP_LP* lp, /**< LP data */
14225  SCIP_SET* set, /**< global SCIP settings */
14226  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
14227  BMS_BLKMEM* blkmem, /**< block memory buffers */
14228  SCIP_STAT* stat, /**< problem statistics */
14229  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14230  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14231  SCIP_PROB* prob, /**< problem data */
14232  SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
14233  SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
14234  * (limit is computed within the method w.r.t. the average LP iterations) */
14235  SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
14236  SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
14237  SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
14238  )
14239 {
14240  SCIP_RETCODE retcode;
14241  SCIP_Bool needprimalray;
14242  SCIP_Bool needdualray;
14243  int harditlim;
14244  int resolveitlim;
14245 
14246  assert(lp != NULL);
14247  assert(prob != NULL);
14248  assert(prob->nvars >= lp->ncols);
14249  assert(lperror != NULL);
14250 
14251  SCIPdebugMessage("solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
14252  lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
14253 
14254  retcode = SCIP_OKAY;
14255  *lperror = FALSE;
14256 
14257  /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
14258  needprimalray = TRUE;
14259  needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
14260  || (set->conf_enable && set->conf_useinflp));
14261 
14262  /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
14263  harditlim = (int) MIN(itlim, INT_MAX);
14264  resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
14265  assert(harditlim == -1 || (resolveitlim <= harditlim));
14266 
14267  /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
14268  * or removed from the LP (diving was ended)
14269  */
14270  if( lp->nlazycols > 0 )
14271  {
14272  /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
14273  * first resolve LP?
14274  */
14275  SCIP_CALL( updateLazyBounds(lp, set) );
14276  assert(lp->diving == lp->divinglazyapplied);
14277  }
14278 
14279  /* flush changes to the LP solver */
14280  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
14281  assert(lp->flushed);
14282 
14283  if( !lp->solved )
14284  {
14285  SCIP_Bool* primalfeaspointer;
14286  SCIP_Bool* dualfeaspointer;
14287  SCIP_Bool primalfeasible;
14288  SCIP_Bool dualfeasible;
14289  SCIP_Bool rayfeasible;
14290  SCIP_Bool tightprimfeastol;
14291  SCIP_Bool tightdualfeastol;
14292  SCIP_Bool fromscratch;
14293  SCIP_Bool wasfromscratch;
14294  SCIP_Longint oldnlps;
14295  int fastmip;
14296 
14297  /* set initial LP solver settings */
14298  fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
14299  tightprimfeastol = FALSE;
14300  tightdualfeastol = FALSE;
14301  fromscratch = FALSE;
14302  primalfeasible = FALSE;
14303  dualfeasible = FALSE;
14304  wasfromscratch = (stat->nlps == 0);
14305 
14306  SOLVEAGAIN:
14307  /* solve the LP */
14308  oldnlps = stat->nlps;
14309  SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
14310  needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14311  SCIPdebugMessage("lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
14312  assert(!(*lperror) || !lp->solved);
14313 
14314  /* check for error */
14315  if( *lperror )
14316  {
14317  retcode = SCIP_OKAY;
14318  goto TERMINATE;
14319  }
14320 
14321  /* evaluate solution status */
14322  switch( SCIPlpGetSolstat(lp) )
14323  {
14325  /* get LP solution and possibly check the solution's feasibility again */
14326  if( set->lp_checkprimfeas )
14327  primalfeaspointer = &primalfeasible;
14328  else
14329  {
14330  /* believe in the primal feasibility of the LP solution */
14331  primalfeasible = TRUE;
14332  primalfeaspointer = NULL;
14333  }
14334  if( set->lp_checkdualfeas )
14335  dualfeaspointer = &dualfeasible;
14336  else
14337  {
14338  /* believe in the dual feasibility of the LP solution */
14339  dualfeasible = TRUE;
14340  dualfeaspointer = NULL;
14341  }
14342 
14343  SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
14344 
14345  /* in debug mode, check that lazy bounds (if present) are not violated */
14346  checkLazyBounds(lp, set);
14347 
14348  if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
14349  {
14350  /* update ages and remove obsolete columns and rows from LP */
14351  SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
14352  if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
14353  {
14354  SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
14355  }
14356 
14357  if( !lp->solved )
14358  {
14359  /* resolve LP after removing obsolete columns and rows */
14360  SCIPdebugMessage("removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
14361  aging = FALSE; /* to prevent infinite loops */
14362  goto SOLVEAGAIN;
14363  }
14364  }
14365  if( !primalfeasible || !dualfeasible )
14366  {
14368 
14369  if( (fastmip > 0) && simplex )
14370  {
14371  /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
14372  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14373  "(node %"SCIP_LONGINT_FORMAT") solution of LP %"SCIP_LONGINT_FORMAT" not optimal (pfeas=%d, dfeas=%d) -- solving again without FASTMIP\n",
14374  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14375  fastmip = 0;
14376  goto SOLVEAGAIN;
14377  }
14378  else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
14379  {
14380  /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
14381  * tolerance
14382  */
14383  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14384  "(node %"SCIP_LONGINT_FORMAT") solution of LP %"SCIP_LONGINT_FORMAT" not optimal (pfeas=%d, dfeas=%d) -- solving again with tighter feasibility tolerance\n",
14385  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14386  tightprimfeastol = tightprimfeastol || !primalfeasible;
14387  tightdualfeastol = tightdualfeastol || !dualfeasible;
14388  goto SOLVEAGAIN;
14389  }
14390  else if( !fromscratch && !wasfromscratch && simplex )
14391  {
14392  /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
14393  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14394  "(node %"SCIP_LONGINT_FORMAT") solution of LP %"SCIP_LONGINT_FORMAT" not optimal (pfeas=%d, dfeas=%d) -- solving again from scratch\n",
14395  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
14396  fromscratch = TRUE;
14397  goto SOLVEAGAIN;
14398  }
14399  else
14400  {
14401  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14402  "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
14403  lp->solved = FALSE;
14405  *lperror = TRUE;
14406  }
14407  }
14408  SCIPdebugMessage(" -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
14409  lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
14410  lp->lpsolstat, lp->cutoffbound);
14411  break;
14412 
14414  SCIPdebugMessage(" -> LP infeasible\n");
14415  if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
14416  {
14417  if( SCIPlpiHasDualRay(lp->lpi) )
14418  {
14419  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
14420  }
14421  /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
14422  * with the primal simplex due to numerical problems) - treat this case like an LP error
14423  */
14424  else
14425  {
14426  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14427  "(node %"SCIP_LONGINT_FORMAT") infeasibility of LP %"SCIP_LONGINT_FORMAT" could not be proven by dual ray\n", stat->nnodes, stat->nlps);
14428  lp->solved = FALSE;
14430  *lperror = TRUE;
14431  }
14432  }
14433  break;
14434 
14436  if( set->lp_checkprimfeas )
14437  {
14438  /* get unbounded LP solution and check the solution's feasibility again */
14439  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
14440  }
14441  else
14442  {
14443  /* get unbounded LP solution believing in the feasibility of the LP solution */
14444  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
14445 
14446  primalfeasible = TRUE;
14447  rayfeasible = TRUE;
14448  }
14449 
14450  /* in debug mode, check that lazy bounds (if present) are not violated */
14451  checkLazyBounds(lp, set);
14452 
14453  SCIPdebugMessage(" -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
14454  primalfeasible, rayfeasible);
14455 
14456  if( !primalfeasible || !rayfeasible )
14457  {
14459 
14460  if( (fastmip > 0) && simplex )
14461  {
14462  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
14463  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14464  "(node %"SCIP_LONGINT_FORMAT") solution of unbounded LP %"SCIP_LONGINT_FORMAT" not optimal (pfeas=%d, rfeas=%d) -- solving again without FASTMIP\n",
14465  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14466  fastmip = 0;
14467  goto SOLVEAGAIN;
14468  }
14469  else if( !tightprimfeastol )
14470  {
14471  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
14472  * tolerance
14473  */
14474  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14475  "(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",
14476  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14477  tightprimfeastol = TRUE;
14478  goto SOLVEAGAIN;
14479  }
14480  else if( !fromscratch && simplex )
14481  {
14482  /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
14483  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14484  "(node %"SCIP_LONGINT_FORMAT") solution of unbounded LP %"SCIP_LONGINT_FORMAT" not optimal (pfeas=%d, rfeas=%d) -- solving again from scratch\n",
14485  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
14486  fromscratch = TRUE;
14487  goto SOLVEAGAIN;
14488  }
14489  else
14490  {
14491  /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
14492  * forget about the LP at this node and mark it to be unsolved
14493  */
14494  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14495  "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles in unbounded LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
14496  lp->solved = FALSE;
14498  *lperror = TRUE;
14499  }
14500  }
14501 
14502  break;
14503 
14505  assert(!lpCutoffDisabled(set));
14506  /* if we do branch-and-price, make sure that a dual feasible solution exists, that exceeds the objective limit;
14507  * With FASTMIP setting, CPLEX does not apply the final pivot to reach the dual solution exceeding the objective
14508  * limit. Therefore, we have to either turn off FASTMIP and resolve the problem or continue solving it without
14509  * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
14510  * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
14511  * FASTMIP and solve again.
14512  */
14513  if( !SCIPprobAllColsInLP(prob, set, lp) && fastmip )
14514  {
14515  SCIP_LPI* lpi;
14516  SCIP_Real objval;
14517 
14518  lpi = SCIPlpGetLPI(lp);
14519 
14520  assert(lpi != NULL);
14521  /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
14522  * the assert by using !SCIPsetIsFeasNegative()
14523  */
14524  assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiuobjlim));
14525 
14526  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14527 
14528  /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
14529  if( SCIPsetIsLT(set, objval, lp->lpiuobjlim) )
14530  {
14531  SCIP_Real tmpcutoff;
14532  char tmppricingchar;
14533  SCIP_LPSOLSTAT solstat;
14534 
14535  SCIPdebugMessage("objval = %f < %f = lp->lpiuobjlim, but status objlimit\n", objval, lp->lpiuobjlim);
14536 
14537  /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
14538  fromscratch = FALSE;
14539 
14540  /* temporarily disable cutoffbound, which also disables the objective limit */
14541  tmpcutoff = lp->cutoffbound;
14542  lp->cutoffbound = SCIPlpiInfinity(lpi);
14543 
14544  /* set lp pricing strategy to steepest edge */
14545  SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
14546  SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
14547 
14548  /* resolve LP with an iteration limit of 1 */
14549  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
14550  FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14551 
14552  /* reinstall old cutoff bound and lp pricing strategy */
14553  lp->cutoffbound = tmpcutoff;
14554  SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
14555 
14556  /* get objective value */
14557  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14558 
14559  /* get solution status for the lp */
14560  solstat = SCIPlpGetSolstat(lp);
14561  assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
14562 
14563  if( !(*lperror) && solstat != SCIP_LPSOLSTAT_ERROR && solstat != SCIP_LPSOLSTAT_NOTSOLVED )
14564  {
14565  SCIPdebugMessage(" ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
14566  }
14567 
14568  /* disable fastmip for subsequent LP calls (if objective limit is not yet exceeded or LP solution is infeasible) */
14569  fastmip = 0;
14570 
14571  /* the solution is still not exceeding the objective limit and the solving process
14572  * was stopped due to time or iteration limit, solve again with fastmip turned off
14573  */
14574  if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
14575  SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
14576  {
14577  assert(!(*lperror));
14578 
14579  SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
14580  FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, keepsol, lperror) );
14581 
14582  /* get objective value */
14583  SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
14584 
14585  /* get solution status for the lp */
14586  solstat = SCIPlpGetSolstat(lp);
14587 
14588  SCIPdebugMessage(" ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
14589  }
14590 
14591  /* check for lp errors */
14592  if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
14593  {
14594  SCIPdebugMessage("unresolved error while resolving LP in order to exceed the objlimit\n");
14595  lp->solved = FALSE;
14597 
14598  retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
14599  goto TERMINATE;
14600  }
14601 
14602  lp->solved = TRUE;
14603 
14604  /* optimal solution / objlimit with fastmip turned off / itlimit or timelimit, but objlimit exceeded */
14605  if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
14606  || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
14607  && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
14608  {
14609  /* get LP solution and possibly check the solution's feasibility again */
14610  if( set->lp_checkprimfeas )
14611  primalfeaspointer = &primalfeasible;
14612  else
14613  {
14614  /* believe in the primal feasibility of the LP solution */
14615  primalfeasible = TRUE;
14616  primalfeaspointer = NULL;
14617  }
14618  if( set->lp_checkdualfeas )
14619  dualfeaspointer = &dualfeasible;
14620  else
14621  {
14622  /* believe in the dual feasibility of the LP solution */
14623  dualfeasible = TRUE;
14624  dualfeaspointer = NULL;
14625  }
14626 
14627  SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
14628 
14629  /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
14630  if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
14631  {
14632  checkLazyBounds(lp, set);
14633  }
14634 
14635  /* if objective value is larger than the cutoff bound, set solution status to objective
14636  * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
14637  * this was already done in the lpSolve() method
14638  */
14639  if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
14640  {
14642  lp->lpobjval = SCIPsetInfinity(set);
14643  }
14644 
14645  /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
14646  * the cutoffbound; mark the LP to be unsolved
14647  */
14648  if( !primalfeasible || !dualfeasible
14649  || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
14650  !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
14651  {
14652  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
14653  "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles in LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
14654  lp->solved = FALSE;
14656  *lperror = TRUE;
14657  }
14658 
14659  SCIPdebugMessage(" -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
14660  lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
14661  lp->lpsolstat, lp->cutoffbound);
14662  }
14663  /* infeasible solution */
14664  else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
14665  {
14666  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
14667  SCIPdebugMessage(" -> LP infeasible\n");
14668  }
14669  /* unbounded solution */
14670  else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
14671  {
14672  if( set->lp_checkprimfeas )
14673  {
14674  /* get unbounded LP solution and check the solution's feasibility again */
14675  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
14676  }
14677  else
14678  {
14679  /* get unbounded LP solution believing in its feasibility */
14680  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
14681 
14682  primalfeasible = TRUE;
14683  rayfeasible = TRUE;
14684  }
14685 
14686  SCIPdebugMessage(" -> LP has unbounded primal ray\n");
14687 
14688  /* in debug mode, check that lazy bounds (if present) are not violated */
14689  checkLazyBounds(lp, set);
14690 
14691  if( !primalfeasible || !rayfeasible )
14692  {
14693  /* unbounded solution is infeasible (this can happen due to numerical problems):
14694  * forget about the LP at this node and mark it to be unsolved
14695 
14696  * @todo: like in the default LP solving evaluation, solve without fastmip,
14697  * with tighter feasibility tolerance and from scratch
14698  */
14699  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
14700  "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles in unbounded LP %"SCIP_LONGINT_FORMAT"\n", stat->nnodes, stat->nlps);
14701  lp->solved = FALSE;
14703  *lperror = TRUE;
14704  }
14705 
14706  }
14707 
14708  assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
14709  assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
14711  }
14712  else
14713  {
14714  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
14715  }
14716  }
14717  else if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
14718  {
14719  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
14720  }
14721  SCIPdebugMessage(" -> LP objective limit reached\n");
14722  break;
14723 
14725  SCIPdebugMessage(" -> LP iteration limit exceeded\n");
14726  break;
14727 
14729  SCIPdebugMessage(" -> LP time limit exceeded\n");
14730  break;
14731 
14732  case SCIP_LPSOLSTAT_ERROR:
14734  SCIPerrorMessage("error in LP solver\n");
14735  retcode = SCIP_LPERROR;
14736  goto TERMINATE;
14737 
14738  default:
14739  SCIPerrorMessage("unknown LP solution status\n");
14740  retcode = SCIP_ERROR;
14741  goto TERMINATE;
14742  }
14743  }
14744  assert(!(*lperror) || !lp->solved);
14745 
14746  TERMINATE:
14747  /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
14748  * may happen that we continue to solve from scratch during strong branching */
14749  if( lp->lpifromscratch )
14750  {
14751  SCIP_Bool success;
14752  (void) lpSetFromscratch(lp, FALSE, &success);
14753  SCIPdebugMessage("resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
14754  }
14755 
14756  return retcode;
14757 }
14758 
14759 /** gets solution status of current LP */
14761  SCIP_LP* lp /**< current LP data */
14762  )
14763 {
14764  assert(lp != NULL);
14765  assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
14766 
14767  return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
14768 }
14769 
14770 /** gets objective value of current LP
14771  *
14772  * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
14773  * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
14774  * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
14775  */
14777  SCIP_LP* lp, /**< current LP data */
14778  SCIP_SET* set, /**< global SCIP settings */
14779  SCIP_PROB* prob /**< problem data */
14780  )
14781 {
14782  assert(lp != NULL);
14783  assert(lp->solved);
14784  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
14785  assert(set != NULL);
14786 
14787  if( !lp->flushed )
14788  return SCIP_INVALID;
14789  else if( SCIPsetIsInfinity(set, lp->lpobjval) || SCIPsetIsInfinity(set, -lp->lpobjval))
14790  return lp->lpobjval;
14791  else if( lp->looseobjvalinf > 0 )
14792  return -SCIPsetInfinity(set);
14793  else
14794  {
14795  /* recalculate the loose objective value, if needed */
14796  if( !lp->looseobjvalid )
14797  recomputeLooseObjectiveValue(lp, set, prob);
14798 
14799  return lp->lpobjval + lp->looseobjval;
14800  }
14801 }
14802 
14803 /** gets part of objective value of current LP that results from COLUMN variables only */
14805  SCIP_LP* lp /**< current LP data */
14806  )
14807 {
14808  assert(lp != NULL);
14809  assert(lp->solved);
14810 
14811  return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
14812 }
14813 
14814 /** gets part of objective value of current LP that results from LOOSE variables only */
14816  SCIP_LP* lp, /**< current LP data */
14817  SCIP_SET* set, /**< global SCIP settings */
14818  SCIP_PROB* prob /**< problem data */
14819  )
14820 {
14821  assert(lp != NULL);
14822  assert(lp->solved);
14823  assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
14824  assert(set != NULL);
14825 
14826  if( !lp->flushed )
14827  return SCIP_INVALID;
14828  else if( lp->looseobjvalinf > 0 )
14829  return -SCIPsetInfinity(set);
14830  else
14831  return getFiniteLooseObjval(lp, set, prob);
14832 }
14833 
14834 /** remembers the current LP objective value as root solution value */
14836  SCIP_LP* lp, /**< current LP data */
14837  SCIP_SET* set, /**< global SCIP settings */
14838  SCIP_PROB* prob /**< problem data */
14839  )
14840 {
14841  assert(lp != NULL);
14842 
14844  lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
14845 }
14846 
14847 /** invalidates the root LP solution value */
14849  SCIP_LP* lp /**< current LP data */
14850  )
14851 {
14852  assert(lp != NULL);
14853 
14854  lp->rootlpobjval = SCIP_INVALID;
14856 }
14857 
14858 /** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
14859  * global bound
14860  */
14862  SCIP_LP* lp, /**< current LP data */
14863  SCIP_SET* set, /**< global SCIP settings */
14864  SCIP_PROB* prob /**< problem data */
14865  )
14866 {
14867  assert(lp != NULL);
14868  assert(lp->glbpseudoobjvalinf >= 0);
14869  assert(set != NULL);
14870 
14871  if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
14872  return -SCIPsetInfinity(set);
14873  else
14874  {
14875  /* recalculate the global pseudo solution value, if needed */
14876  if( !lp->glbpseudoobjvalid )
14877  recomputeGlbPseudoObjectiveValue(lp, set, prob);
14878 
14879  /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
14880  if( SCIPsetIsInfinity(set, -lp->glbpseudoobjval) )
14881  return -SCIPsetInfinity(set);
14882 
14883  return lp->glbpseudoobjval;
14884  }
14885 }
14886 
14887 /** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
14888  * objective function) local bound
14889  */
14891  SCIP_LP* lp, /**< current LP data */
14892  SCIP_SET* set, /**< global SCIP settings */
14893  SCIP_PROB* prob /**< problem data */
14894  )
14895 {
14896  assert(lp != NULL);
14897  assert(lp->pseudoobjvalinf >= 0);
14898  assert(set != NULL);
14899 
14900  if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
14901  return -SCIPsetInfinity(set);
14902  else
14903  {
14904  /* recalculate the pseudo solution value, if needed */
14905  if( !lp->pseudoobjvalid )
14906  recomputePseudoObjectiveValue(lp, set, prob);
14907 
14908  /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
14909  if( SCIPsetIsInfinity(set, -lp->pseudoobjval) )
14910  return -SCIPsetInfinity(set);
14911 
14912  return lp->pseudoobjval;
14913  }
14914 }
14915 
14916 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
14918  SCIP_LP* lp, /**< current LP data */
14919  SCIP_SET* set, /**< global SCIP settings */
14920  SCIP_PROB* prob, /**< problem data */
14921  SCIP_VAR* var, /**< problem variable */
14922  SCIP_Real oldbound, /**< old value for bound */
14923  SCIP_Real newbound, /**< new value for bound */
14924  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
14925  )
14926 {
14927  SCIP_Real pseudoobjval;
14928  int pseudoobjvalinf;
14929  SCIP_Real obj;
14930 
14931  pseudoobjval = getFinitePseudoObjval(lp, set, prob);
14932  pseudoobjvalinf = lp->pseudoobjvalinf;
14933  obj = SCIPvarGetObj(var);
14934  if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
14935  {
14936  if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
14937  pseudoobjvalinf--;
14938  else
14939  pseudoobjval -= oldbound * obj;
14940  assert(pseudoobjvalinf >= 0);
14941  if( SCIPsetIsInfinity(set, REALABS(newbound)) )
14942  pseudoobjvalinf++;
14943  else
14944  pseudoobjval += newbound * obj;
14945  }
14946  assert(pseudoobjvalinf >= 0);
14947 
14948  if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
14949  return -SCIPsetInfinity(set);
14950  else
14951  return pseudoobjval;
14952 }
14953 
14954 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
14955  * perform calculations with interval arithmetic to get an exact lower bound
14956  */
14958  SCIP_LP* lp, /**< current LP data */
14959  SCIP_SET* set, /**< global SCIP settings */
14960  SCIP_VAR* var, /**< problem variable */
14961  SCIP_Real oldbound, /**< old value for bound */
14962  SCIP_Real newbound, /**< new value for bound */
14963  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
14964  )
14965 {
14966  SCIP_Real pseudoobjval;
14967  int pseudoobjvalinf;
14968  SCIP_Real obj;
14969 
14970  assert(lp->pseudoobjvalid);
14971 
14972  pseudoobjval = lp->pseudoobjval;
14973  pseudoobjvalinf = lp->pseudoobjvalinf;
14974  obj = SCIPvarGetObj(var);
14975  if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
14976  {
14977  SCIP_INTERVAL objint;
14978  SCIP_INTERVAL bd;
14979  SCIP_INTERVAL prod;
14980  SCIP_INTERVAL psval;
14981 
14982  SCIPintervalSet(&psval, pseudoobjval);
14983  SCIPintervalSet(&objint, SCIPvarGetObj(var));
14984 
14985  if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
14986  pseudoobjvalinf--;
14987  else
14988  {
14989  SCIPintervalSet(&bd, oldbound);
14990  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
14991  SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
14992  }
14993  assert(pseudoobjvalinf >= 0);
14994  if( SCIPsetIsInfinity(set, REALABS(newbound)) )
14995  pseudoobjvalinf++;
14996  else
14997  {
14998  SCIPintervalSet(&bd, newbound);
14999  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
15000  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
15001  }
15002 
15003  pseudoobjval = SCIPintervalGetInf(psval);
15004  }
15005  assert(pseudoobjvalinf >= 0);
15006 
15007  if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
15008  return -SCIPsetInfinity(set);
15009  else
15010  return pseudoobjval;
15011 }
15012 
15013 /** Is the new value reliable or may we have cancellation?
15014  *
15015  * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
15016  * cancellations which can occur during increasing the oldvalue to the newvalue
15017  */
15018 static
15020  SCIP_SET* set, /**< global SCIP settings */
15021  SCIP_Real newvalue, /**< new value */
15022  SCIP_Real oldvalue /**< old reliable value */
15023  )
15024 {
15025  SCIP_Real quotient;
15026 
15027  assert(set != NULL);
15028  assert(oldvalue < SCIP_INVALID);
15029 
15030  quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
15031 
15032  return SCIPsetIsZero(set, quotient);
15033 }
15034 
15035 /** compute the objective delta due the new objective coefficient */
15036 static
15038  SCIP_SET* set, /**< global SCIP settings */
15039  SCIP_Real oldobj, /**< old objective value of variable */
15040  SCIP_Real newobj, /**< new objective value of variable */
15041  SCIP_Real lb, /**< lower bound of variable */
15042  SCIP_Real ub, /**< upper bound of variable */
15043  SCIP_Real* deltaval, /**< pointer to store the delta value */
15044  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15045  )
15046 {
15047  assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
15048  assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
15049  assert(!SCIPsetIsInfinity(set, lb));
15050  assert(!SCIPsetIsInfinity(set, -ub));
15051  assert(!SCIPsetIsEQ(set, oldobj, newobj));
15052 
15053  (*deltaval) = 0.0;
15054  (*deltainf) = 0;
15055 
15056  if( SCIPsetIsPositive(set, oldobj) )
15057  {
15058  /* sign of objective did not change */
15059  if( SCIPsetIsPositive(set, newobj) )
15060  {
15061  /* if the bound is finite, calculate the deltaval */
15062  if( !SCIPsetIsInfinity(set, -lb) )
15063  (*deltaval) = lb * (newobj - oldobj);
15064  }
15065  /* sign of objective did change, so the best bound does change */
15066  else if( SCIPsetIsNegative(set, newobj) )
15067  {
15068  if( SCIPsetIsInfinity(set, -lb) )
15069  {
15070  /* old best bound was infinite while new one is not */
15071  if( !SCIPsetIsInfinity(set, ub) )
15072  {
15073  (*deltainf) = -1;
15074  (*deltaval) = ub * newobj;
15075  }
15076  }
15077  else
15078  {
15079  /* new best bound is infinite while old one was not */
15080  if( SCIPsetIsInfinity(set, ub) )
15081  {
15082  (*deltainf) = 1;
15083  (*deltaval) = -lb * oldobj;
15084  }
15085  /* neither old nor new best bound is infinite, so just calculate the deltaval */
15086  else
15087  {
15088  (*deltaval) = (ub * newobj) - (lb * oldobj);
15089  }
15090  }
15091  }
15092  /* new objective is 0.0 */
15093  else
15094  {
15095  if( SCIPsetIsInfinity(set, -lb) )
15096  (*deltainf) = -1;
15097  else
15098  (*deltaval) = -lb * oldobj;
15099  }
15100 
15101  }
15102  else if( SCIPsetIsNegative(set, oldobj) )
15103  {
15104  /* sign of objective did not change */
15105  if( SCIPsetIsNegative(set, newobj) )
15106  {
15107  /* if the bound is finite, calculate the deltaval */
15108  if( !SCIPsetIsInfinity(set, ub) )
15109  (*deltaval) = ub * (newobj - oldobj);
15110  }
15111  /* sign of objective did change, so the best bound does change */
15112  else if( SCIPsetIsPositive(set, newobj) )
15113  {
15114  if( SCIPsetIsInfinity(set, ub) )
15115  {
15116  /* old best bound was infinite while new one is not */
15117  if( !SCIPsetIsInfinity(set, -lb) )
15118  {
15119  (*deltainf) = -1;
15120  (*deltaval) = lb * newobj;
15121  }
15122  }
15123  else
15124  {
15125  /* new best bound is infinite while old one was not */
15126  if( SCIPsetIsInfinity(set, -lb) )
15127  {
15128  (*deltainf) = 1;
15129  (*deltaval) = -ub * oldobj;
15130  }
15131  /* neither old nor new best bound is infinite, so just calculate the deltaval */
15132  else
15133  {
15134  (*deltaval) = (lb * newobj) - (ub * oldobj);
15135  }
15136  }
15137  }
15138  /* new objective is 0.0 */
15139  else
15140  {
15141  if( SCIPsetIsInfinity(set, ub) )
15142  (*deltainf) = -1;
15143  else
15144  (*deltaval) = -ub * oldobj;
15145  }
15146  }
15147  /* old objective was 0.0 */
15148  else
15149  {
15150  if( SCIPsetIsNegative(set, newobj) )
15151  {
15152  if( SCIPsetIsInfinity(set, ub) )
15153  (*deltainf) = 1;
15154  else
15155  (*deltaval) = ub * newobj;
15156  }
15157  else if( SCIPsetIsPositive(set, newobj) )
15158  {
15159  if( SCIPsetIsInfinity(set, -lb) )
15160  (*deltainf) = 1;
15161  else
15162  (*deltaval) = lb * newobj;
15163  }
15164  }
15165 }
15166 
15167 /** compute the objective delta due the new lower bound */
15168 static
15170  SCIP_SET* set, /**< global SCIP settings */
15171  SCIP_Real obj, /**< objective value of variable */
15172  SCIP_Real oldlb, /**< old lower bound of variable */
15173  SCIP_Real newlb, /**< new lower bound of variable */
15174  SCIP_Real* deltaval, /**< pointer to store the delta value */
15175  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15176  )
15177 {
15178  assert(!SCIPsetIsInfinity(set, REALABS(obj)));
15179  assert(!SCIPsetIsInfinity(set, oldlb));
15180  assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
15181  assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
15182 
15183  if( SCIPsetIsInfinity(set, -oldlb) )
15184  {
15185  if( !SCIPsetIsInfinity(set, newlb) )
15186  {
15187  (*deltainf) = -1;
15188  (*deltaval) = newlb * obj;
15189  }
15190  else
15191  {
15192  (*deltainf) = 0;
15193  (*deltaval) = 0.0;
15194  }
15195  }
15196  else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
15197  {
15198  (*deltainf) = 1;
15199  (*deltaval) = -oldlb * obj;
15200  }
15201  else
15202  {
15203  (*deltainf) = 0;
15204  (*deltaval) = obj * (newlb - oldlb);
15205  }
15206 }
15207 
15208 /** compute the objective delta due the new upper bound */
15209 static
15211  SCIP_SET* set, /**< global SCIP settings */
15212  SCIP_Real obj, /**< objective value of variable */
15213  SCIP_Real oldub, /**< old upper bound of variable */
15214  SCIP_Real newub, /**< new upper bound of variable */
15215  SCIP_Real* deltaval, /**< pointer to store the delta value */
15216  int* deltainf /**< pointer to store the number of variables with infinite best bound */
15217  )
15218 {
15219  assert(!SCIPsetIsInfinity(set, REALABS(obj)));
15220  assert(!SCIPsetIsInfinity(set, -oldub));
15221  assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
15222  assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
15223 
15224  if( SCIPsetIsInfinity(set, oldub) )
15225  {
15226  if( !SCIPsetIsInfinity(set, -newub) )
15227  {
15228  (*deltainf) = -1;
15229  (*deltaval) = newub * obj;
15230  }
15231  else
15232  {
15233  (*deltainf) = 0;
15234  (*deltaval) = 0.0;
15235  }
15236  }
15237  else if( SCIPsetIsInfinity(set, REALABS(newub)) )
15238  {
15239  (*deltainf) = 1;
15240  (*deltaval) = -oldub * obj;
15241  }
15242  else
15243  {
15244  (*deltainf) = 0;
15245  (*deltaval) = obj * (newub - oldub);
15246  }
15247 }
15248 
15249 /** update norms of objective function vector */
15250 static
15252  SCIP_LP* lp, /**< current LP data */
15253  SCIP_SET* set, /**< global SCIP settings */
15254  SCIP_Real oldobj, /**< old objective value of variable */
15255  SCIP_Real newobj /**< new objective value of variable */
15256  )
15257 {
15258  if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
15259  {
15260  if( !lp->objsqrnormunreliable )
15261  {
15262  SCIP_Real oldvalue;
15263 
15264  oldvalue = lp->objsqrnorm;
15265  lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
15266 
15267  /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
15268  if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
15269  lp->objsqrnormunreliable = TRUE;
15270  else
15271  {
15272  assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
15273 
15274  /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
15275  lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
15276 
15277  assert(lp->objsqrnorm >= 0.0);
15278  }
15279  }
15280 
15281  lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
15282  lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
15283  }
15284 }
15285 
15286 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
15287 static
15289  SCIP_LP* lp, /**< current LP data */
15290  SCIP_SET* set, /**< global SCIP settings */
15291  SCIP_VAR* var, /**< problem variable that changed */
15292  SCIP_Real deltaval, /**< delta value in the objective function */
15293  int deltainf, /**< delta value for the number of variables with infinite best bound */
15294  SCIP_Bool local, /**< should the local pseudo objective value be updated? */
15295  SCIP_Bool loose, /**< should the loose objective value be updated? */
15296  SCIP_Bool global /**< should the global pseudo objective value be updated? */
15297  )
15298 {
15299  assert(lp != NULL);
15300  assert(lp->looseobjvalinf >= 0);
15301  assert(lp->pseudoobjvalinf >= 0);
15302  assert(lp->glbpseudoobjvalinf >= 0);
15303 
15304  /* update the pseudo objective value */
15305  if( local )
15306  {
15307  lp->pseudoobjvalinf += deltainf;
15308  if( lp->pseudoobjvalid )
15309  {
15310  lp->pseudoobjval += deltaval;
15311 
15312  /* if the absolute value was increased, this is regarded as reliable,
15313  * otherwise, we check whether we can still trust the updated value
15314  */
15315  if( REALABS(lp->relpseudoobjval) < REALABS(lp->pseudoobjval) )
15316  lp->relpseudoobjval = lp->pseudoobjval;
15317  else if( SCIPsetIsUpdateUnreliable(set, lp->pseudoobjval, lp->relpseudoobjval) )
15318  lp->pseudoobjvalid = FALSE;
15319  }
15320 
15321  /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
15323  loose = TRUE;
15324  }
15325  /* update the loose objective value */
15326  if( loose )
15327  {
15328  lp->looseobjvalinf += deltainf;
15329 
15330  if( deltaval != 0.0 && lp->looseobjvalid )
15331  {
15332  lp->looseobjval += deltaval;
15333 
15334  /* if the absolute value was increased, this is regarded as reliable,
15335  * otherwise, we check whether we can still trust the updated value
15336  */
15337  if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
15338  lp->rellooseobjval = lp->looseobjval;
15339  else if( SCIPsetIsUpdateUnreliable(set, lp->looseobjval, lp->rellooseobjval) )
15340  lp->looseobjvalid = FALSE;
15341  }
15342  }
15343  /* update the root pseudo objective values */
15344  if( global )
15345  {
15346  lp->glbpseudoobjvalinf += deltainf;
15347  if( lp->glbpseudoobjvalid )
15348  {
15349  lp->glbpseudoobjval += deltaval;
15350 
15351  /* if the absolute value was increased, this is regarded as reliable,
15352  * otherwise, we check whether we can still trust the updated value
15353  */
15357  lp->glbpseudoobjvalid = FALSE;
15358  }
15359  }
15360 
15361  assert(lp->looseobjvalinf >= 0);
15362  assert(lp->pseudoobjvalinf >= 0);
15363  assert(lp->glbpseudoobjvalinf >= 0);
15364 }
15365 
15366 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
15367  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
15368  */
15369 static
15371  SCIP_LP* lp, /**< current LP data */
15372  SCIP_SET* set, /**< global SCIP settings */
15373  SCIP_VAR* var, /**< problem variable that changed */
15374  SCIP_Real oldobj, /**< old objective value of variable */
15375  SCIP_Real oldlb, /**< old objective value of variable */
15376  SCIP_Real oldub, /**< old objective value of variable */
15377  SCIP_Real newobj, /**< new objective value of variable */
15378  SCIP_Real newlb, /**< new objective value of variable */
15379  SCIP_Real newub /**< new objective value of variable */
15380  )
15381 {
15382  SCIP_INTERVAL deltaval;
15383  SCIP_INTERVAL bd;
15384  SCIP_INTERVAL obj;
15385  SCIP_INTERVAL prod;
15386  SCIP_INTERVAL psval;
15387  int deltainf;
15388 
15389  assert(lp != NULL);
15390  assert(lp->pseudoobjvalinf >= 0);
15391  assert(lp->looseobjvalinf >= 0);
15392  assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
15393  assert(!SCIPsetIsInfinity(set, oldlb));
15394  assert(!SCIPsetIsInfinity(set, -oldub));
15395  assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
15396  assert(!SCIPsetIsInfinity(set, newlb));
15397  assert(!SCIPsetIsInfinity(set, -newub));
15398  assert(var != NULL);
15399 
15401  {
15402  SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
15403  return SCIP_INVALIDDATA;
15404  }
15405 
15406  assert(SCIPvarGetProbindex(var) >= 0);
15407 
15408  SCIPintervalSet(&deltaval, 0.0);
15409  deltainf = 0;
15410 
15411  /* subtract old pseudo objective value */
15412  if( oldobj > 0.0 )
15413  {
15414  if( SCIPsetIsInfinity(set, -oldlb) )
15415  deltainf--;
15416  else
15417  {
15418  SCIPintervalSet(&bd, oldlb);
15419  SCIPintervalSet(&obj, oldobj);
15420  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15421  SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
15422  }
15423  }
15424  else if( oldobj < 0.0 )
15425  {
15426  if( SCIPsetIsInfinity(set, oldub) )
15427  deltainf--;
15428  else
15429  {
15430  SCIPintervalSet(&bd, oldub);
15431  SCIPintervalSet(&obj, oldobj);
15432  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15433  SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
15434  }
15435  }
15436 
15437  /* add new pseudo objective value */
15438  if( newobj > 0.0 )
15439  {
15440  if( SCIPsetIsInfinity(set, -newlb) )
15441  deltainf++;
15442  else
15443  {
15444  SCIPintervalSet(&bd, newlb);
15445  SCIPintervalSet(&obj, newobj);
15446  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15447  SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
15448  }
15449  }
15450  else if( newobj < 0.0 )
15451  {
15452  if( SCIPsetIsInfinity(set, newub) )
15453  deltainf++;
15454  else
15455  {
15456  SCIPintervalSet(&bd, newub);
15457  SCIPintervalSet(&obj, newobj);
15458  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
15459  SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
15460  }
15461  }
15462 
15463  /* update the pseudo and loose objective values */
15464  SCIPintervalSet(&psval, lp->pseudoobjval);
15465  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
15466  lp->pseudoobjval = SCIPintervalGetInf(psval);
15467  lp->pseudoobjvalinf += deltainf;
15469  {
15470  SCIPintervalSet(&psval, lp->looseobjval);
15471  SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
15472  lp->looseobjval = SCIPintervalGetInf(psval);
15473  lp->looseobjvalinf += deltainf;
15474  }
15475 
15476  assert(lp->pseudoobjvalinf >= 0);
15477  assert(lp->looseobjvalinf >= 0);
15478 
15479  return SCIP_OKAY;
15480 }
15481 
15482 /** updates current pseudo and loose objective value for a change in a variable's objective value */
15484  SCIP_LP* lp, /**< current LP data */
15485  SCIP_SET* set, /**< global SCIP settings */
15486  SCIP_VAR* var, /**< problem variable that changed */
15487  SCIP_Real oldobj, /**< old objective value of variable */
15488  SCIP_Real newobj /**< new objective value of variable */
15489  )
15490 {
15491  assert(set != NULL);
15492  assert(var != NULL);
15493 
15494  if( set->misc_exactsolve )
15495  {
15496  if( oldobj != newobj ) /*lint !e777*/
15497  {
15498  SCIP_CALL( lpUpdateVarProved(lp, set, var, oldobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
15499  newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
15500  }
15501  }
15502  else
15503  {
15504  if( !SCIPsetIsEQ(set, oldobj, newobj) )
15505  {
15506  SCIP_Real deltaval;
15507  int deltainf;
15508 
15510  assert(SCIPvarGetProbindex(var) >= 0);
15511 
15512  /* the objective coefficient can only be changed during presolving, that implies that the global and local
15513  * domain of the variable are the same
15514  */
15515  assert(SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
15516  assert(SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
15517 
15518  /* compute the pseudo objective delta due the new objective coefficient */
15519  getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
15520 
15521  /* update the pseudo and loose objective values */
15522  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, TRUE);
15523 
15524  /* update the objective function vector norms */
15525  lpUpdateObjNorms(lp, set, oldobj, newobj);
15526  }
15527  }
15528 
15529  return SCIP_OKAY;
15530 }
15531 
15532 /** updates current root pseudo objective value for a global change in a variable's lower bound */
15534  SCIP_LP* lp, /**< current LP data */
15535  SCIP_SET* set, /**< global SCIP settings */
15536  SCIP_VAR* var, /**< problem variable that changed */
15537  SCIP_Real oldlb, /**< old lower bound of variable */
15538  SCIP_Real newlb /**< new lower bound of variable */
15539  )
15540 {
15541  assert(set != NULL);
15542  assert(var != NULL);
15543 
15544  if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
15545  {
15546  SCIP_Real deltaval;
15547  int deltainf;
15548 
15549  /* compute the pseudo objective delta due the new lower bound */
15550  getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
15551 
15552  /* update the root pseudo objective values */
15553  lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
15554  }
15555 
15556  return SCIP_OKAY;
15557 }
15558 
15559 /** updates current pseudo and loose objective value for a change in a variable's lower bound */
15561  SCIP_LP* lp, /**< current LP data */
15562  SCIP_SET* set, /**< global SCIP settings */
15563  SCIP_VAR* var, /**< problem variable that changed */
15564  SCIP_Real oldlb, /**< old lower bound of variable */
15565  SCIP_Real newlb /**< new lower bound of variable */
15566  )
15567 {
15568  assert(set != NULL);
15569  assert(var != NULL);
15570 
15571  if( set->misc_exactsolve )
15572  {
15573  if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
15574  {
15575  SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
15576  SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
15577  }
15578  }
15579  else
15580  {
15581  if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
15582  {
15583  SCIP_Real deltaval;
15584  int deltainf;
15585 
15587  assert(SCIPvarGetProbindex(var) >= 0);
15588 
15589  /* compute the pseudo objective delta due the new lower bound */
15590  getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
15591 
15592  /* update the pseudo and loose objective values */
15593  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
15594  }
15595  }
15596 
15597  return SCIP_OKAY;
15598 }
15599 
15600 /** updates current root pseudo objective value for a global change in a variable's upper bound */
15602  SCIP_LP* lp, /**< current LP data */
15603  SCIP_SET* set, /**< global SCIP settings */
15604  SCIP_VAR* var, /**< problem variable that changed */
15605  SCIP_Real oldub, /**< old upper bound of variable */
15606  SCIP_Real newub /**< new upper bound of variable */
15607  )
15608 {
15609  assert(set != NULL);
15610  assert(var != NULL);
15611 
15612  if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
15613  {
15614  SCIP_Real deltaval;
15615  int deltainf;
15616 
15617  /* compute the pseudo objective delta due the new upper bound */
15618  getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
15619 
15620  /* update the root pseudo objective values */
15621  lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
15622  }
15623 
15624  return SCIP_OKAY;
15625 }
15626 
15627 /** updates current pseudo objective value for a change in a variable's upper bound */
15629  SCIP_LP* lp, /**< current LP data */
15630  SCIP_SET* set, /**< global SCIP settings */
15631  SCIP_VAR* var, /**< problem variable that changed */
15632  SCIP_Real oldub, /**< old upper bound of variable */
15633  SCIP_Real newub /**< new upper bound of variable */
15634  )
15635 {
15636  assert(set != NULL);
15637  assert(var != NULL);
15638 
15639  if( set->misc_exactsolve )
15640  {
15641  if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
15642  {
15643  SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
15644  SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
15645  }
15646  }
15647  else
15648  {
15649  if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
15650  {
15651  SCIP_Real deltaval;
15652  int deltainf;
15653 
15655  assert(SCIPvarGetProbindex(var) >= 0);
15656 
15657  /* compute the pseudo objective delta due the new upper bound */
15658  getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
15659 
15660  /* update the pseudo and loose objective values */
15661  lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
15662  }
15663  }
15664 
15665  return SCIP_OKAY;
15666 }
15667 
15668 /** informs LP, that given variable was added to the problem */
15670  SCIP_LP* lp, /**< current LP data */
15671  SCIP_SET* set, /**< global SCIP settings */
15672  SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
15673  )
15674 {
15675  assert(lp != NULL);
15677  assert(SCIPvarGetProbindex(var) >= 0);
15678 
15679  /* add the variable to the loose objective value sum */
15680  SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
15681 
15682  /* update the loose variables counter */
15684  lp->nloosevars++;
15685 
15686  return SCIP_OKAY;
15687 }
15688 
15689 /** informs LP, that given variable is to be deleted from the problem */
15691  SCIP_LP* lp, /**< current LP data */
15692  SCIP_SET* set, /**< global SCIP settings */
15693  SCIP_VAR* var /**< variable that will be deleted from the problem */
15694  )
15695 {
15696  assert(lp != NULL);
15698  assert(SCIPvarGetProbindex(var) >= 0);
15699 
15700  /* subtract the variable from the loose objective value sum */
15701  SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
15702 
15703  /* update the loose variables counter */
15705  {
15706  SCIPlpDecNLoosevars(lp);
15707  }
15708 
15709  return SCIP_OKAY;
15710 }
15711 
15712 /** informs LP, that given formerly loose problem variable is now a column variable */
15713 static
15715  SCIP_LP* lp, /**< current LP data */
15716  SCIP_SET* set, /**< global SCIP settings */
15717  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
15718  )
15719 {
15720  SCIP_Real obj;
15721  SCIP_Real lb;
15722  SCIP_Real ub;
15723 
15724  assert(lp != NULL);
15725  assert(lp->nloosevars > 0);
15726  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
15727  assert(SCIPvarGetProbindex(var) >= 0);
15728  assert(lp->looseobjvalinf >= 0);
15729 
15730  obj = SCIPvarGetObj(var);
15731 
15732  /* update loose objective value */
15733  if( SCIPsetIsPositive(set, obj) )
15734  {
15735  lb = SCIPvarGetLbLocal(var);
15736  if( SCIPsetIsInfinity(set, -lb) )
15737  lp->looseobjvalinf--;
15738  else
15739  lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
15740  }
15741  else if( SCIPsetIsNegative(set, obj) )
15742  {
15743  ub = SCIPvarGetUbLocal(var);
15744  if( SCIPsetIsInfinity(set, ub) )
15745  lp->looseobjvalinf--;
15746  else
15747  lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
15748  }
15749 
15750  SCIPlpDecNLoosevars(lp);
15751 
15752  assert(lp->looseobjvalinf >= 0);
15753 
15754  return SCIP_OKAY;
15755 }
15756 
15757 /** informs LP, that given formerly loose problem variable is now a column variable
15758  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
15759  */
15760 static
15762  SCIP_LP* lp, /**< current LP data */
15763  SCIP_SET* set, /**< global SCIP settings */
15764  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
15765  )
15766 {
15767  SCIP_INTERVAL bd;
15768  SCIP_INTERVAL ob;
15769  SCIP_INTERVAL prod;
15770  SCIP_INTERVAL loose;
15771  SCIP_Real obj;
15772  SCIP_Real lb;
15773  SCIP_Real ub;
15774 
15775  assert(lp != NULL);
15776  assert(lp->nloosevars > 0);
15777  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
15778  assert(SCIPvarGetProbindex(var) >= 0);
15779 
15780  obj = SCIPvarGetObj(var);
15781 
15782  SCIPintervalSet(&loose, lp->looseobjval);
15783 
15784  /* update loose objective value corresponding to the deletion of variable */
15785  if( obj > 0.0 )
15786  {
15787  lb = SCIPvarGetLbLocal(var);
15788  if( SCIPsetIsInfinity(set, -lb) )
15789  lp->looseobjvalinf--;
15790  else
15791  {
15792  SCIPintervalSet(&bd, lb);
15793  SCIPintervalSet(&ob, obj);
15794  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
15795  SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
15796  }
15797  }
15798  else if( SCIPsetIsNegative(set, obj) )
15799  {
15800  ub = SCIPvarGetUbLocal(var);
15801  if( SCIPsetIsInfinity(set, ub) )
15802  lp->looseobjvalinf--;
15803  else
15804  {
15805  SCIPintervalSet(&bd, ub);
15806  SCIPintervalSet(&ob, obj);
15807  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
15808  SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
15809  }
15810  }
15811  lp->nloosevars--;
15812 
15813  /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
15814  if( lp->nloosevars == 0 )
15815  {
15816  assert(lp->looseobjvalinf == 0);
15817  lp->looseobjval = 0.0;
15818  }
15819  else
15820  lp->looseobjval = SCIPintervalGetInf(loose);
15821 
15822  return SCIP_OKAY;
15823 }
15824 
15825 /** informs LP, that given formerly loose problem variable is now a column variable */
15827  SCIP_LP* lp, /**< current LP data */
15828  SCIP_SET* set, /**< global SCIP settings */
15829  SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
15830  )
15831 {
15832  assert(set != NULL);
15833 
15834  if( set->misc_exactsolve )
15835  {
15836  SCIP_CALL( lpUpdateVarColumnProved(lp, set, var) );
15837  }
15838  else
15839  {
15840  SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
15841  }
15842 
15843  return SCIP_OKAY;
15844 }
15845 
15846 /** informs LP, that given formerly column problem variable is now again a loose variable */
15847 static
15849  SCIP_LP* lp, /**< current LP data */
15850  SCIP_SET* set, /**< global SCIP settings */
15851  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
15852  )
15853 {
15854  SCIP_Real obj;
15855  SCIP_Real lb;
15856  SCIP_Real ub;
15857 
15858  assert(lp != NULL);
15859  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
15860  assert(SCIPvarGetProbindex(var) >= 0);
15861  assert(lp->looseobjvalinf >= 0);
15862 
15863  obj = SCIPvarGetObj(var);
15864 
15865  /* update loose objective value corresponding to the addition of variable */
15866  if( SCIPsetIsPositive(set, obj) )
15867  {
15868  lb = SCIPvarGetLbLocal(var);
15869  if( SCIPsetIsInfinity(set, -lb) )
15870  lp->looseobjvalinf++;
15871  else
15872  lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
15873  }
15874  else if( SCIPsetIsNegative(set, obj) )
15875  {
15876  ub = SCIPvarGetUbLocal(var);
15877  if( SCIPsetIsInfinity(set, ub) )
15878  lp->looseobjvalinf++;
15879  else
15880  lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
15881  }
15882  lp->nloosevars++;
15883 
15884  assert(lp->looseobjvalinf >= 0);
15885 
15886  return SCIP_OKAY;
15887 }
15888 
15889 /** informs LP, that given formerly column problem variable is now again a loose variable
15890  * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
15891  */
15892 static
15894  SCIP_LP* lp, /**< current LP data */
15895  SCIP_SET* set, /**< global SCIP settings */
15896  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
15897  )
15898 {
15899  SCIP_INTERVAL bd;
15900  SCIP_INTERVAL ob;
15901  SCIP_INTERVAL prod;
15902  SCIP_INTERVAL loose;
15903  SCIP_Real obj;
15904  SCIP_Real lb;
15905  SCIP_Real ub;
15906 
15907  assert(lp != NULL);
15908  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
15909  assert(SCIPvarGetProbindex(var) >= 0);
15910 
15911  obj = SCIPvarGetObj(var);
15912 
15913  SCIPintervalSet(&loose, lp->looseobjval);
15914 
15915  /* update loose objective value corresponding to the deletion of variable */
15916  if( obj > 0.0 )
15917  {
15918  lb = SCIPvarGetLbLocal(var);
15919  if( SCIPsetIsInfinity(set, -lb) )
15920  lp->looseobjvalinf++;
15921  else
15922  {
15923  SCIPintervalSet(&bd, lb);
15924  SCIPintervalSet(&ob, obj);
15925  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
15926  SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
15927  }
15928  }
15929  else if( SCIPsetIsNegative(set, obj) )
15930  {
15931  ub = SCIPvarGetUbLocal(var);
15932  if( SCIPsetIsInfinity(set, ub) )
15933  lp->looseobjvalinf++;
15934  else
15935  {
15936  SCIPintervalSet(&bd, ub);
15937  SCIPintervalSet(&ob, obj);
15938  SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
15939  SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
15940  }
15941  }
15942  lp->nloosevars++;
15943 
15944  lp->looseobjval = SCIPintervalGetInf(loose);
15945 
15946  return SCIP_OKAY;
15947 }
15948 
15949 /** informs LP, that given formerly column problem variable is now again a loose variable */
15951  SCIP_LP* lp, /**< current LP data */
15952  SCIP_SET* set, /**< global SCIP settings */
15953  SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
15954  )
15955 {
15956  assert(set != NULL);
15957 
15958  if( set->misc_exactsolve )
15959  {
15960  SCIP_CALL( lpUpdateVarLooseProved(lp, set, var) );
15961  }
15962  else
15963  {
15964  SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
15965  }
15966 
15967  return SCIP_OKAY;
15968 }
15969 
15970 /** decrease the number of loose variables by one */
15972  SCIP_LP* lp /**< current LP data */
15973  )
15974 {
15975  assert(lp != NULL);
15976  assert(lp->nloosevars > 0);
15977 
15978  lp->nloosevars--;
15979 
15980  /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
15981  if( lp->nloosevars == 0 )
15982  {
15983  assert(lp->looseobjvalinf == 0);
15984  lp->looseobjval = 0.0;
15985  }
15986 }
15987 
15988 /** stores the LP solution in the columns and rows */
15990  SCIP_LP* lp, /**< current LP data */
15991  SCIP_SET* set, /**< global SCIP settings */
15992  SCIP_STAT* stat, /**< problem statistics */
15993  SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
15994  SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
15995  )
15996 {
15997  SCIP_COL** lpicols;
15998  SCIP_ROW** lpirows;
15999  SCIP_Real* primsol;
16000  SCIP_Real* dualsol;
16001  SCIP_Real* activity;
16002  SCIP_Real* redcost;
16003  SCIP_Real primalbound;
16004  SCIP_Real dualbound;
16005  SCIP_Bool stillprimalfeasible;
16006  SCIP_Bool stilldualfeasible;
16007  int* cstat;
16008  int* rstat;
16009  SCIP_Longint lpcount;
16010  int nlpicols;
16011  int nlpirows;
16012  int c;
16013  int r;
16014 
16015  assert(lp != NULL);
16016  assert(lp->flushed);
16017  assert(lp->solved);
16018  assert(set != NULL);
16019  assert(stat != NULL);
16020  assert(lp->validsollp <= stat->lpcount);
16021 
16022  /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
16023  * corresponding flag immediately to FALSE to skip all checks
16024  */
16025  if( primalfeasible == NULL )
16026  stillprimalfeasible = FALSE;
16027  else
16028  {
16029  *primalfeasible = TRUE;
16030  stillprimalfeasible = TRUE;
16031  }
16032  if( dualfeasible == NULL )
16033  stilldualfeasible = FALSE;
16034  else
16035  {
16036  *dualfeasible = TRUE;
16037  stilldualfeasible = TRUE;
16038  }
16039 
16040  /* check if the values are already calculated */
16041  if( lp->validsollp == stat->lpcount )
16042  return SCIP_OKAY;
16043  lp->validsollp = stat->lpcount;
16044 
16045  SCIPdebugMessage("getting new LP solution %"SCIP_LONGINT_FORMAT" for solstat %d\n",
16046  stat->lpcount, SCIPlpGetSolstat(lp));
16047 
16048  lpicols = lp->lpicols;
16049  lpirows = lp->lpirows;
16050  nlpicols = lp->nlpicols;
16051  nlpirows = lp->nlpirows;
16052  lpcount = stat->lpcount;
16053 
16054  /* get temporary memory */
16055  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
16056  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
16057  SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
16058  SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
16059  SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
16060  SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
16061 
16062  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
16063  if( lp->solisbasic )
16064  {
16065  SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
16066  }
16067  else
16068  {
16069  BMSclearMemoryArray(cstat, nlpicols);
16070  BMSclearMemoryArray(rstat, nlpirows);
16071  }
16072 
16073  primalbound = 0.0;
16074  dualbound = 0.0;
16075 
16076  /* copy primal solution and reduced costs into columns */
16077  for( c = 0; c < nlpicols; ++c )
16078  {
16079  assert( 0 <= cstat[c] && cstat[c] < 4 );
16080  lpicols[c]->primsol = primsol[c];
16081  lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
16082  lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
16083  lpicols[c]->redcost = redcost[c];
16084  lpicols[c]->basisstatus = (unsigned int) cstat[c];
16085  lpicols[c]->validredcostlp = lpcount;
16086  if( stillprimalfeasible )
16087  {
16088  stillprimalfeasible = !SCIPsetIsFeasNegative(set, lpicols[c]->primsol - lpicols[c]->lb)
16089  && !SCIPsetIsFeasPositive(set, lpicols[c]->primsol - lpicols[c]->ub);
16090  primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
16091  }
16092  if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
16093  {
16094  double compslack;
16095 
16096  /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
16097  * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
16098  * variables, which would magnify even the tiniest violation in the dual multiplier
16099  */
16100  if( stilldualfeasible )
16101  {
16102  compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
16103  stilldualfeasible = !SCIPsetIsFeasPositive(set, compslack);
16104  }
16105  if( stilldualfeasible )
16106  {
16107  compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
16108  stilldualfeasible = !SCIPsetIsFeasNegative(set, compslack);
16109  }
16110 
16111  SCIPdebugMessage(" col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16112  SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
16113  SCIPsetIsFeasGE(set, lpicols[c]->primsol, lpicols[c]->lb),
16114  SCIPsetIsFeasLE(set, lpicols[c]->primsol, lpicols[c]->ub),
16115  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16116  !SCIPsetIsFeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
16117  !SCIPsetIsFeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
16118  dualfeasible != NULL ? stilldualfeasible : TRUE);
16119  }
16120  else
16121  {
16122  /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
16123  * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
16124  * bounds, its reduced cost must be zero
16125  */
16126  if( stilldualfeasible && SCIPsetIsFeasGT(set, lpicols[c]->primsol, lpicols[c]->lb) )
16127  stilldualfeasible = !SCIPsetIsFeasPositive(set, lpicols[c]->redcost);
16128  if( stilldualfeasible && SCIPsetIsFeasLT(set, lpicols[c]->primsol, lpicols[c]->ub) )
16129  stilldualfeasible = !SCIPsetIsFeasNegative(set, lpicols[c]->redcost);
16130 
16131  SCIPdebugMessage(" col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16132  SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
16133  SCIPsetIsFeasGE(set, lpicols[c]->primsol, lpicols[c]->lb),
16134  SCIPsetIsFeasLE(set, lpicols[c]->primsol, lpicols[c]->ub),
16135  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16136  !SCIPsetIsFeasGT(set, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsFeasPositive(set, lpicols[c]->redcost),
16137  !SCIPsetIsFeasLT(set, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsFeasNegative(set, lpicols[c]->redcost),
16138  dualfeasible != NULL ? stilldualfeasible : TRUE);
16139  }
16140 
16141  /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
16142  * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
16143  * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
16144  */
16145  if( stilldualfeasible )
16146  {
16147  if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
16148  dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
16149  else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
16150  dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
16151  }
16152  }
16153 
16154  /* copy dual solution and activities into rows */
16155  for( r = 0; r < nlpirows; ++r )
16156  {
16157  assert( 0 <= rstat[r] && rstat[r] < 4 );
16158  lpirows[r]->dualsol = dualsol[r];
16159  lpirows[r]->activity = activity[r] + lpirows[r]->constant;
16160  lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
16161  lpirows[r]->validactivitylp = lpcount;
16162  if( stillprimalfeasible )
16163  {
16164  stillprimalfeasible = SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs)
16165  && SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs);
16166  }
16167  if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
16168  {
16169  double compslack;
16170 
16171  /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
16172  * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
16173  * variables, which would magnify even the tiniest violation in the dual multiplier
16174  */
16175  if( stilldualfeasible )
16176  {
16177  compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
16178  stilldualfeasible = !SCIPsetIsFeasPositive(set, compslack);
16179  }
16180  if( stilldualfeasible )
16181  {
16182  compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
16183  stilldualfeasible = !SCIPsetIsFeasNegative(set, compslack);
16184  }
16185 
16186  SCIPdebugMessage(" row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16187  lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
16188  SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs),
16189  SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs),
16190  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16191  !SCIPsetIsFeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
16192  !SCIPsetIsFeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
16193  dualfeasible != NULL ? stilldualfeasible : TRUE);
16194  }
16195  else
16196  {
16197  /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
16198  * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
16199  * strictly within left-hand and right-hand side, its dual multiplier must be zero
16200  */
16201  if( stilldualfeasible && SCIPsetIsFeasGT(set, lpirows[r]->activity, lpirows[r]->lhs) )
16202  stilldualfeasible = !SCIPsetIsFeasPositive(set, lpirows[r]->dualsol);
16203  if( stilldualfeasible && SCIPsetIsFeasLT(set, lpirows[r]->activity, lpirows[r]->rhs) )
16204  stilldualfeasible = !SCIPsetIsFeasNegative(set, lpirows[r]->dualsol);
16205 
16206  SCIPdebugMessage(" row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
16207  lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
16208  SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs),
16209  SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs),
16210  primalfeasible != NULL ? stillprimalfeasible : TRUE,
16211  !SCIPsetIsFeasGT(set, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsFeasPositive(set, lpirows[r]->dualsol),
16212  !SCIPsetIsFeasLT(set, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsFeasNegative(set, lpirows[r]->dualsol),
16213  dualfeasible != NULL ? stilldualfeasible : TRUE);
16214  }
16215 
16216  /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
16217  * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
16218  * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
16219  */
16220  if( stilldualfeasible )
16221  {
16222  if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -(lpirows[r]->lhs - lpirows[r]->constant)) )
16223  dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
16224  else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs - lpirows[r]->constant) )
16225  dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
16226  }
16227  }
16228 
16229  /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
16230  * declare the solution primal infeasible
16231  */
16232  /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
16233  if( stillprimalfeasible )
16234  {
16235  stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
16236  SCIPdebugMessage(" primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
16237  SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
16238  }
16239 
16240  /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
16241  * the solution dual infeasible
16242  */
16243  /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
16244  if( stilldualfeasible )
16245  {
16246  stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
16247  SCIPdebugMessage(" dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
16248  SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
16249  }
16250 
16251  if( primalfeasible != NULL )
16252  *primalfeasible = stillprimalfeasible;
16253  if( dualfeasible != NULL )
16254  *dualfeasible = stilldualfeasible;
16255 
16256  /* free temporary memory */
16257  SCIPsetFreeBufferArray(set, &rstat);
16258  SCIPsetFreeBufferArray(set, &cstat);
16259  SCIPsetFreeBufferArray(set, &redcost);
16260  SCIPsetFreeBufferArray(set, &activity);
16261  SCIPsetFreeBufferArray(set, &dualsol);
16262  SCIPsetFreeBufferArray(set, &primsol);
16263 
16264  return SCIP_OKAY;
16265 }
16266 
16267 /** stores LP solution with infinite objective value in the columns and rows */
16269  SCIP_LP* lp, /**< current LP data */
16270  SCIP_SET* set, /**< global SCIP settings */
16271  SCIP_STAT* stat, /**< problem statistics */
16272  SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
16273  SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
16274  )
16275 {
16276  SCIP_COL** lpicols;
16277  SCIP_ROW** lpirows;
16278  SCIP_Real* primsol;
16279  SCIP_Real* activity;
16280  SCIP_Real* ray;
16281  SCIP_Real rayobjval;
16282  SCIP_Real rayscale;
16283  SCIP_Longint lpcount;
16284  int nlpicols;
16285  int nlpirows;
16286  int c;
16287  int r;
16288 
16289  assert(lp != NULL);
16290  assert(lp->flushed);
16291  assert(lp->solved);
16292  assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
16293  assert(SCIPsetIsInfinity(set, -lp->lpobjval));
16294  assert(set != NULL);
16295  assert(stat != NULL);
16296  assert(lp->validsollp <= stat->lpcount);
16297 
16298  if( primalfeasible != NULL )
16299  *primalfeasible = TRUE;
16300  if( rayfeasible != NULL )
16301  *rayfeasible = TRUE;
16302 
16303  /* check if the values are already calculated */
16304  if( lp->validsollp == stat->lpcount )
16305  return SCIP_OKAY;
16306 
16307  /* check if the LP solver is able to provide a primal unbounded ray */
16308  if( !SCIPlpiHasPrimalRay(lp->lpi) )
16309  {
16310  SCIPerrorMessage("LP solver has no primal ray to prove unboundedness\n");
16311  return SCIP_LPERROR;
16312  }
16313 
16314  lp->validsollp = stat->lpcount;
16315 
16316  SCIPdebugMessage("getting new unbounded LP solution %"SCIP_LONGINT_FORMAT"\n", stat->lpcount);
16317 
16318  /* get temporary memory */
16319  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
16320  SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
16321  SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, lp->nlpicols) );
16322 
16323  /* get primal feasible point */
16324  SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, activity, NULL) );
16325 
16326  /* get primal unbounded ray */
16327  SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
16328 
16329  lpicols = lp->lpicols;
16330  lpirows = lp->lpirows;
16331  nlpicols = lp->nlpicols;
16332  nlpirows = lp->nlpirows;
16333  lpcount = stat->lpcount;
16334 
16335  /* calculate the objective value decrease of the ray */
16336  rayobjval = 0.0;
16337  for( c = 0; c < nlpicols; ++c )
16338  {
16339  assert(lpicols[c] != NULL);
16340  assert(lpicols[c]->var != NULL);
16341 
16342  /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
16343  if( rayfeasible != NULL )
16344  *rayfeasible = *rayfeasible
16345  && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -lpicols[c]->lb))
16346  && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, lpicols[c]->ub));
16347 
16348  /* check primal feasibility of (finite) primal solution */
16349  if( primalfeasible != NULL )
16350  *primalfeasible = *primalfeasible
16351  && !SCIPsetIsFeasNegative(set, primsol[c] - lpicols[c]->lb)
16352  && !SCIPsetIsFeasPositive(set, primsol[c] - lpicols[c]->ub);
16353 
16354  if( !SCIPsetIsZero(set, ray[c]) )
16355  rayobjval += ray[c] * lpicols[c]->obj;
16356  }
16357 
16358  /* if the finite point is already infeasible, we do not have to add the ray */
16359  if( primalfeasible != NULL && !(*primalfeasible) )
16360  {
16361  rayscale = 0.0;
16362  }
16363  /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
16364  else if( rayfeasible != NULL && !(*rayfeasible) )
16365  {
16366  rayscale = 0.0;
16367  }
16368  /* due to numerical problems, the objective of the ray might be nonnegative,
16369  *
16370  * @todo How to check for negative objective value here?
16371  */
16372  else if( !SCIPsetIsNegative(set, rayobjval) )
16373  {
16374  if( rayfeasible != NULL )
16375  {
16376  *rayfeasible = FALSE;
16377  }
16378 
16379  rayscale = 0.0;
16380  }
16381  else
16382  {
16383  assert(rayobjval != 0.0);
16384 
16385  /* scale the ray, such that the resulting point has infinite objective value */
16386  rayscale = -2*SCIPsetInfinity(set)/rayobjval;
16387  assert(SCIPsetIsFeasPositive(set, rayscale));
16388 
16389  /* ensure that unbounded point does not violate the bounds of the variables */
16390  for( c = 0; c < nlpicols; ++c )
16391  {
16392  if( SCIPsetIsPositive(set, ray[c]) )
16393  rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c])/ray[c]);
16394  else if( SCIPsetIsNegative(set, ray[c]) )
16395  rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c])/ray[c]);
16396 
16397  assert(SCIPsetIsFeasPositive(set, rayscale));
16398  }
16399  }
16400 
16401  SCIPdebugMessage("unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
16402 
16403  /* calculate the unbounded point: x' = x + rayscale * ray */
16404  for( c = 0; c < nlpicols; ++c )
16405  {
16406  if( SCIPsetIsZero(set, ray[c]) )
16407  lpicols[c]->primsol = primsol[c];
16408  else
16409  lpicols[c]->primsol = primsol[c] + rayscale * ray[c];
16410  lpicols[c]->redcost = SCIP_INVALID;
16411  lpicols[c]->validredcostlp = -1;
16412  }
16413 
16414  for( r = 0; r < nlpirows; ++r )
16415  {
16416  lpirows[r]->dualsol = SCIP_INVALID;
16417  lpirows[r]->activity = activity[r] + lpirows[r]->constant;
16418  lpirows[r]->validactivitylp = lpcount;
16419 
16420  /* check for feasibility of the rows */
16421  if( primalfeasible != NULL )
16422  *primalfeasible = *primalfeasible
16423  && SCIPsetIsFeasGE(set, lpirows[r]->activity, lpirows[r]->lhs)
16424  && SCIPsetIsFeasLE(set, lpirows[r]->activity, lpirows[r]->rhs);
16425  }
16426 
16427  /* free temporary memory */
16428  SCIPsetFreeBufferArray(set, &ray);
16429  SCIPsetFreeBufferArray(set, &activity);
16430  SCIPsetFreeBufferArray(set, &primsol);
16431 
16432  return SCIP_OKAY;
16433 }
16434 
16435 /** returns primal ray proving the unboundedness of the current LP */
16437  SCIP_LP* lp, /**< current LP data */
16438  SCIP_SET* set, /**< global SCIP settings */
16439  SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
16440  * so the size of this array should be at least number of active variables
16441  * (all entries have to be initialized to 0 before) */
16442  )
16443 {
16444  SCIP_COL** lpicols;
16445  SCIP_Real* lpiray;
16446  SCIP_VAR* var;
16447  int nlpicols;
16448  int c;
16449 
16450  assert(lp != NULL);
16451  assert(set != NULL);
16452  assert(ray != NULL);
16453  assert(lp->flushed);
16454  assert(lp->solved);
16455  assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
16456  assert(SCIPsetIsInfinity(set, -lp->lpobjval));
16457 
16458  /* check if the LP solver is able to provide a primal unbounded ray */
16459  if( !SCIPlpiHasPrimalRay(lp->lpi) )
16460  {
16461  SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
16462  return SCIP_LPERROR;
16463  }
16464 
16465  /* get temporary memory */
16466  SCIP_CALL( SCIPsetAllocBufferArray(set, &lpiray, lp->nlpicols) );
16467 
16468  SCIPdebugMessage("getting primal ray values\n");
16469 
16470  /* get primal unbounded ray */
16471  SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
16472 
16473  lpicols = lp->lpicols;
16474  nlpicols = lp->nlpicols;
16475 
16476  /* store the ray values of active problem variables */
16477  for( c = 0; c < nlpicols; c++ )
16478  {
16479  assert(lpicols[c] != NULL);
16480 
16481  var = lpicols[c]->var;
16482  assert(var != NULL);
16483  assert(SCIPvarGetProbindex(var) != -1);
16484  ray[SCIPvarGetProbindex(var)] = lpiray[c];
16485  }
16486 
16487  SCIPsetFreeBufferArray(set, &lpiray);
16488 
16489  return SCIP_OKAY;
16490 }
16491 
16492 /** stores the dual Farkas multipliers for infeasibility proof in rows */
16494  SCIP_LP* lp, /**< current LP data */
16495  SCIP_SET* set, /**< global SCIP settings */
16496  SCIP_STAT* stat /**< problem statistics */
16497  )
16498 {
16499  SCIP_COL** lpicols;
16500  SCIP_ROW** lpirows;
16501  SCIP_Real* dualfarkas;
16502  int nlpicols;
16503  int nlpirows;
16504  int c;
16505  int r;
16506 
16507  assert(lp != NULL);
16508  assert(lp->flushed);
16509  assert(lp->solved);
16510  assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
16511  assert(set != NULL);
16512  assert(stat != NULL);
16513  assert(lp->validfarkaslp <= stat->lpcount);
16514 
16515  /* check if the values are already calculated */
16516  if( lp->validfarkaslp == stat->lpcount )
16517  return SCIP_OKAY;
16518  lp->validfarkaslp = stat->lpcount;
16519 
16520  /* get temporary memory */
16521  SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
16522 
16523  /* get dual Farkas infeasibility proof */
16524  SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
16525 
16526  lpicols = lp->lpicols;
16527  lpirows = lp->lpirows;
16528  nlpicols = lp->nlpicols;
16529  nlpirows = lp->nlpirows;
16530 
16531  /* store infeasibility proof in rows */
16532  SCIPdebugMessage("LP is infeasible:\n");
16533  for( r = 0; r < nlpirows; ++r )
16534  {
16535  SCIPdebugMessage(" row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
16536  lpirows[r]->dualfarkas = dualfarkas[r];
16537  lpirows[r]->dualsol = SCIP_INVALID;
16538  lpirows[r]->activity = 0.0;
16539  lpirows[r]->validactivitylp = -1L;
16540  lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
16541  }
16542 
16543  /* set columns as invalid */
16544  for( c = 0; c < nlpicols; ++c )
16545  {
16546  lpicols[c]->primsol = SCIP_INVALID;
16547  lpicols[c]->redcost = SCIP_INVALID;
16548  lpicols[c]->validredcostlp = -1L;
16549  lpicols[c]->validfarkaslp = -1L;
16550  }
16551 
16552  /* free temporary memory */
16553  SCIPsetFreeBufferArray(set, &dualfarkas);
16554 
16555  return SCIP_OKAY;
16556 }
16557 
16558 /** get number of iterations used in last LP solve */
16560  SCIP_LP* lp, /**< current LP data */
16561  int* iterations /**< pointer to store the iteration count */
16562  )
16563 {
16564  assert(lp != NULL);
16565 
16566  SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
16567 
16568  return SCIP_OKAY;
16569 }
16570 
16571 /** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
16572  * resets age of non-zero columns and sharp rows
16573  */
16575  SCIP_LP* lp, /**< current LP data */
16576  SCIP_STAT* stat /**< problem statistics */
16577  )
16578 {
16579  SCIP_COL** lpicols;
16580  SCIP_ROW** lpirows;
16581  int nlpicols;
16582  int nlpirows;
16583  int c;
16584  int r;
16585 
16586  assert(lp != NULL);
16587  assert(lp->flushed);
16588  assert(lp->solved);
16589  assert(lp->nlpicols == lp->ncols);
16590  assert(lp->nlpirows == lp->nrows);
16591  assert(stat != NULL);
16592  assert(lp->validsollp == stat->lpcount);
16593 
16594  SCIPdebugMessage("updating LP ages\n");
16595 
16596  lpicols = lp->lpicols;
16597  lpirows = lp->lpirows;
16598  nlpicols = lp->nlpicols;
16599  nlpirows = lp->nlpirows;
16600 
16601  for( c = 0; c < nlpicols; ++c )
16602  {
16603  assert(lpicols[c] == lp->cols[c]);
16604  if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
16605  lpicols[c]->age++;
16606  else
16607  lpicols[c]->age = 0;
16608  /*debugMessage(" -> col <%s>: primsol=%f, age=%d\n",
16609  SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
16610  }
16611 
16612  for( r = 0; r < nlpirows; ++r )
16613  {
16614  assert(lpirows[r] == lp->rows[r]);
16615  if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
16616  lpirows[r]->age++;
16617  else
16618  lpirows[r]->age = 0;
16619  /*debugMessage(" -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
16620  }
16621 
16622  return SCIP_OKAY;
16623 }
16624 
16625 /* deletes the marked columns from the LP and the LP interface */
16626 static
16628  SCIP_LP* lp, /**< current LP data */
16629  SCIP_SET* set, /**< global SCIP settings */
16630  int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
16631  )
16632 {
16633  SCIP_COL* col;
16634  int ncols;
16635  int c;
16636 
16637  assert(lp != NULL);
16638  assert(lp->flushed);
16639  assert(lp->ncols == lp->nlpicols);
16640  assert(!lp->diving);
16641  assert(coldstat != NULL);
16642  assert(lp->nlazycols <= lp->ncols);
16643 
16644  ncols = lp->ncols;
16645 
16646  /* delete columns in LP solver */
16647  SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
16648 
16649  /* update LP data respectively */
16650  for( c = 0; c < ncols; ++c )
16651  {
16652  col = lp->cols[c];
16653  assert(col != NULL);
16654  assert(col == lp->lpicols[c]);
16655  assert(coldstat[c] <= c);
16656  col->lppos = coldstat[c];
16657  if( coldstat[c] == -1 )
16658  {
16659  assert(col->removable);
16660 
16661  /* mark column to be deleted from the LPI and update column arrays of all linked rows */
16662  markColDeleted(col);
16663  colUpdateDelLP(col, set);
16664  col->lpdepth = -1;
16665 
16666  lp->cols[c] = NULL;
16667  lp->lpicols[c] = NULL;
16668  lp->ncols--;
16669  lp->nremovablecols--;
16670  lp->nlpicols--;
16671  }
16672  else if( coldstat[c] < c )
16673  {
16674  assert(lp->cols[coldstat[c]] == NULL);
16675  assert(lp->lpicols[coldstat[c]] == NULL);
16676  lp->cols[coldstat[c]] = col;
16677  lp->lpicols[coldstat[c]] = col;
16678  lp->cols[coldstat[c]]->lppos = coldstat[c];
16679  lp->cols[coldstat[c]]->lpipos = coldstat[c];
16680  lp->cols[c] = NULL;
16681  lp->lpicols[c] = NULL;
16682  }
16683  }
16684 
16685  /* remove columns which are deleted from the lazy column array */
16686  c = 0;
16687  while( c < lp->nlazycols )
16688  {
16689  if( lp->lazycols[c]->lpipos < 0 )
16690  {
16691  lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
16692  lp->nlazycols--;
16693  }
16694  else
16695  c++;
16696  }
16697 
16698  /* mark LP to be unsolved */
16699  if( lp->ncols < ncols )
16700  {
16701  assert(lp->ncols == lp->nlpicols);
16702  assert(lp->nchgcols == 0);
16703  assert(lp->flushed);
16704 
16705  lp->lpifirstchgcol = lp->nlpicols;
16706 
16707  /* mark the current solution invalid */
16708  lp->solved = FALSE;
16709  lp->primalfeasible = FALSE;
16710  lp->lpobjval = SCIP_INVALID;
16712  }
16713 
16714  checkLazyColArray(lp, set);
16715  checkLinks(lp);
16716 
16717  return SCIP_OKAY;
16718 }
16719 
16720 /* deletes the marked rows from the LP and the LP interface */
16721 static
16723  SCIP_LP* lp, /**< current LP data */
16724  BMS_BLKMEM* blkmem, /**< block memory buffers */
16725  SCIP_SET* set, /**< global SCIP settings */
16726  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16727  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16728  int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
16729  )
16730 {
16731  SCIP_ROW* row;
16732  int nrows;
16733  int r;
16734 
16735  assert(lp != NULL);
16736  assert(lp->flushed);
16737  assert(lp->nrows == lp->nlpirows);
16738  assert(!lp->diving);
16739  assert(rowdstat != NULL);
16740 
16741  nrows = lp->nrows;
16742 
16743  /* delete rows in LP solver */
16744  SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
16745 
16746  /* update LP data respectively */
16747  for( r = 0; r < nrows; ++r )
16748  {
16749  row = lp->rows[r];
16750  assert(row == lp->lpirows[r]);
16751  assert(rowdstat[r] <= r);
16752  assert(row != NULL);
16753  row->lppos = rowdstat[r];
16754  if( rowdstat[r] == -1 )
16755  {
16756  if( row->removable )
16757  lp->nremovablerows--;
16758 
16759  /* mark row to be deleted from the LPI and update row arrays of all linked columns */
16760  markRowDeleted(row);
16761  rowUpdateDelLP(row);
16762  row->lpdepth = -1;
16763 
16764  /* check, if row deletion events are tracked
16765  * if so, issue ROWDELETEDLP event
16766  */
16767  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
16768  {
16769  SCIP_EVENT* event;
16770 
16771  SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
16772  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
16773  }
16774 
16775  SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
16776  SCIProwUnlock(lp->rows[r]);
16777  SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
16778  assert(lp->lpirows[r] == NULL);
16779  assert(lp->rows[r] == NULL);
16780  lp->nrows--;
16781  lp->nlpirows--;
16782  }
16783  else if( rowdstat[r] < r )
16784  {
16785  assert(lp->rows[rowdstat[r]] == NULL);
16786  assert(lp->lpirows[rowdstat[r]] == NULL);
16787  lp->rows[rowdstat[r]] = row;
16788  lp->lpirows[rowdstat[r]] = row;
16789  lp->rows[rowdstat[r]]->lppos = rowdstat[r];
16790  lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
16791  lp->rows[r] = NULL;
16792  lp->lpirows[r] = NULL;
16793  }
16794  }
16795 
16796  /* mark LP to be unsolved */
16797  if( lp->nrows < nrows )
16798  {
16799  assert(lp->nrows == lp->nlpirows);
16800  assert(lp->nchgrows == 0);
16801  assert(lp->flushed);
16802 
16803  lp->lpifirstchgrow = lp->nlpirows;
16804 
16805  /* mark the current solution invalid */
16806  lp->solved = FALSE;
16807  lp->dualfeasible = FALSE;
16808  lp->lpobjval = SCIP_INVALID;
16810  }
16811 
16812  checkLinks(lp);
16813 
16814  return SCIP_OKAY;
16815 }
16816 
16817 /** removes all non-basic columns, that are too old, beginning with the given firstcol */
16818 static
16820  SCIP_LP* lp, /**< current LP data */
16821  SCIP_SET* set, /**< global SCIP settings */
16822  SCIP_STAT* stat, /**< problem statistics */
16823  int firstcol /**< first column to check for clean up */
16824  )
16825 {
16826  SCIP_COL** cols;
16827 #ifndef NDEBUG
16828  SCIP_COL** lpicols;
16829 #endif
16830  int* coldstat;
16831  int ncols;
16832  int ndelcols;
16833  int c;
16834 
16835  assert(lp != NULL);
16836  assert(lp->flushed);
16837  assert(lp->ncols == lp->nlpicols);
16838  assert(lp->nremovablecols <= lp->ncols);
16839  assert(!lp->diving);
16840  assert(set != NULL);
16841  assert(stat != NULL);
16842 
16843  if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
16844  return SCIP_OKAY;
16845 
16846  ncols = lp->ncols;
16847  cols = lp->cols;
16848 #ifndef NDEBUG
16849  lpicols = lp->lpicols;
16850 #endif
16851 
16852  /* get temporary memory */
16853  SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
16854 
16855  /* mark obsolete columns to be deleted */
16856  ndelcols = 0;
16857  BMSclearMemoryArray(coldstat, ncols);
16858  for( c = firstcol; c < ncols; ++c )
16859  {
16860  assert(cols[c] == lpicols[c]);
16861  assert(cols[c]->lppos == c);
16862  assert(cols[c]->lpipos == c);
16863  if( cols[c]->removable
16864  && 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 */
16865  && cols[c]->age > set->lp_colagelimit
16867  && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
16868  {
16869  assert(cols[c]->primsol == 0.0);
16870  coldstat[c] = 1;
16871  ndelcols++;
16872  cols[c]->obsoletenode = stat->nnodes;
16873  SCIPdebugMessage("removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
16874  SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
16875  }
16876  }
16877 
16878  SCIPdebugMessage("removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
16879 
16880  /* delete the marked columns in the LP solver interface, update the LP respectively */
16881  if( ndelcols > 0 )
16882  {
16883  SCIP_CALL( lpDelColset(lp, set, coldstat) );
16884  }
16885  assert(lp->ncols == ncols - ndelcols);
16886 
16887  /* release temporary memory */
16888  SCIPsetFreeBufferArray(set, &coldstat);
16889 
16890  return SCIP_OKAY;
16891 }
16892 
16893 /** removes all basic rows, that are too old, beginning with the given firstrow */
16894 static
16896  SCIP_LP* lp, /**< current LP data */
16897  BMS_BLKMEM* blkmem, /**< block memory buffers */
16898  SCIP_SET* set, /**< global SCIP settings */
16899  SCIP_STAT* stat, /**< problem statistics */
16900  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16901  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16902  int firstrow /**< first row to check for clean up */
16903  )
16904 {
16905  SCIP_ROW** rows;
16906 #ifndef NDEBUG
16907  SCIP_ROW** lpirows;
16908 #endif
16909  int* rowdstat;
16910  int nrows;
16911  int ndelrows;
16912  int r;
16913 
16914  assert(lp != NULL);
16915  assert(lp->flushed);
16916  assert(lp->nrows == lp->nlpirows);
16917  assert(lp->nremovablerows <= lp->nrows);
16918  assert(!lp->diving);
16919  assert(set != NULL);
16920  assert(stat != NULL);
16921 
16922  if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
16923  return SCIP_OKAY;
16924 
16925  nrows = lp->nrows;
16926  rows = lp->rows;
16927 #ifndef NDEBUG
16928  lpirows = lp->lpirows;
16929 #endif
16930 
16931  /* get temporary memory */
16932  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
16933 
16934  /* mark obsolete rows to be deleted */
16935  ndelrows = 0;
16936  BMSclearMemoryArray(rowdstat, nrows);
16937  for( r = firstrow; r < nrows; ++r )
16938  {
16939  assert(rows[r] == lpirows[r]);
16940  assert(rows[r]->lppos == r);
16941  assert(rows[r]->lpipos == r);
16942  if( rows[r]->removable
16943  && 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 */
16944  && rows[r]->age > set->lp_rowagelimit
16946  {
16947  rowdstat[r] = 1;
16948  ndelrows++;
16949  rows[r]->obsoletenode = stat->nnodes;
16950  SCIPdebugMessage("removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
16951  rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
16952  }
16953  }
16954 
16955  SCIPdebugMessage("removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
16956 
16957  /* delete the marked rows in the LP solver interface, update the LP respectively */
16958  if( ndelrows > 0 )
16959  {
16960  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
16961  }
16962  assert(lp->nrows == nrows - ndelrows);
16963 
16964  /* release temporary memory */
16965  SCIPsetFreeBufferArray(set, &rowdstat);
16966 
16967  return SCIP_OKAY;
16968 }
16969 
16970 /** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
16972  SCIP_LP* lp, /**< current LP data */
16973  BMS_BLKMEM* blkmem, /**< block memory buffers */
16974  SCIP_SET* set, /**< global SCIP settings */
16975  SCIP_STAT* stat, /**< problem statistics */
16976  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16977  SCIP_EVENTFILTER* eventfilter /**< global event filter */
16978  )
16979 {
16980  assert(lp != NULL);
16981  assert(lp->solved);
16982  assert(!lp->diving);
16984  assert(set != NULL);
16985 
16986  SCIPdebugMessage("removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
16987  lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
16988 
16989  if( lp->firstnewcol < lp->ncols )
16990  {
16991  SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
16992  }
16993  if( lp->firstnewrow < lp->nrows )
16994  {
16995  SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
16996  }
16997 
16998  return SCIP_OKAY;
16999 }
17000 
17001 /** removes all non-basic columns and basic rows in whole LP, that are too old */
17003  SCIP_LP* lp, /**< current LP data */
17004  BMS_BLKMEM* blkmem, /**< block memory buffers */
17005  SCIP_SET* set, /**< global SCIP settings */
17006  SCIP_STAT* stat, /**< problem statistics */
17007  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17008  SCIP_EVENTFILTER* eventfilter /**< global event filter */
17009  )
17010 {
17011  assert(lp != NULL);
17012  assert(lp->solved);
17013  assert(!lp->diving);
17015  assert(set != NULL);
17016 
17017  SCIPdebugMessage("removing all obsolete columns and rows\n");
17018 
17019  if( 0 < lp->ncols )
17020  {
17021  SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
17022  }
17023  if( 0 < lp->nrows )
17024  {
17025  SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
17026  }
17027 
17028  return SCIP_OKAY;
17029 }
17030 
17031 /** removes all non-basic columns at 0.0 beginning with the given firstcol */
17032 static
17034  SCIP_LP* lp, /**< current LP data */
17035  SCIP_SET* set, /**< global SCIP settings */
17036  SCIP_STAT* stat, /**< problem statistics */
17037  int firstcol /**< first column to check for clean up */
17038  )
17039 {
17040  SCIP_COL** cols;
17041  SCIP_COL** lpicols;
17042  int* coldstat;
17043  int ncols;
17044  int ndelcols;
17045  int c;
17046 
17047  assert(lp != NULL);
17048  assert(lp->flushed);
17049  assert(lp->ncols == lp->nlpicols);
17050  assert(!lp->diving);
17051  assert(stat != NULL);
17052  assert(lp->validsollp == stat->lpcount);
17053  assert(0 <= firstcol && firstcol < lp->ncols);
17054 
17055  if( lp->nremovablecols == 0 || !lp->solisbasic )
17056  return SCIP_OKAY;
17057 
17058  ncols = lp->ncols;
17059  cols = lp->cols;
17060  lpicols = lp->lpicols;
17061 
17062  /* get temporary memory */
17063  SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
17064 
17065  /* mark unused columns to be deleted */
17066  ndelcols = 0;
17067  BMSclearMemoryArray(coldstat, ncols);
17068  for( c = firstcol; c < ncols; ++c )
17069  {
17070  assert(cols[c] == lpicols[c]);
17071  assert(cols[c]->lppos == c);
17072  assert(cols[c]->lpipos == c);
17073  if( lpicols[c]->removable
17074  && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
17075  && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
17076  && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
17077  {
17078  coldstat[c] = 1;
17079  ndelcols++;
17080  }
17081  }
17082 
17083  SCIPdebugMessage("removing %d/%d unused columns from LP\n", ndelcols, ncols);
17084 
17085  /* delete the marked columns in the LP solver interface, update the LP respectively */
17086  if( ndelcols > 0 )
17087  {
17088  SCIP_CALL( lpDelColset(lp, set, coldstat) );
17089  }
17090  assert(lp->ncols == ncols - ndelcols);
17091 
17092  /* release temporary memory */
17093  SCIPsetFreeBufferArray(set, &coldstat);
17094 
17095  return SCIP_OKAY;
17096 }
17097 
17098 /** removes all basic rows beginning with the given firstrow */
17099 static
17101  SCIP_LP* lp, /**< current LP data */
17102  BMS_BLKMEM* blkmem, /**< block memory buffers */
17103  SCIP_SET* set, /**< global SCIP settings */
17104  SCIP_STAT* stat, /**< problem statistics */
17105  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17106  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17107  int firstrow /**< first row to check for clean up */
17108  )
17109 {
17110 #ifndef NDEBUG
17111  SCIP_ROW** rows;
17112 #endif
17113  SCIP_ROW** lpirows;
17114  int* rowdstat;
17115  int nrows;
17116  int ndelrows;
17117  int r;
17118 
17119  assert(lp != NULL);
17120  assert(lp->flushed);
17121  assert(lp->ncols == lp->nlpicols);
17122  assert(lp->nrows == lp->nlpirows);
17123  assert(!lp->diving);
17124  assert(stat != NULL);
17125  assert(lp->validsollp == stat->lpcount);
17126  assert(0 <= firstrow && firstrow < lp->nrows);
17127 
17128  if( lp->nremovablerows == 0 || !lp->solisbasic )
17129  return SCIP_OKAY;
17130 
17131 #ifndef NDEBUG
17132  rows = lp->rows;
17133 #endif
17134  nrows = lp->nrows;
17135  lpirows = lp->lpirows;
17136 
17137  /* get temporary memory */
17138  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
17139 
17140  /* mark unused rows to be deleted */
17141  ndelrows = 0;
17142  BMSclearMemoryArray(rowdstat, nrows);
17143  for( r = firstrow; r < nrows; ++r )
17144  {
17145  assert(rows[r] == lpirows[r]);
17146  assert(rows[r]->lppos == r);
17147  assert(rows[r]->lpipos == r);
17148  if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
17149  {
17150  rowdstat[r] = 1;
17151  ndelrows++;
17152  }
17153  }
17154 
17155  SCIPdebugMessage("removing %d/%d unused rows from LP\n", ndelrows, nrows);
17156 
17157  /* delete the marked rows in the LP solver interface, update the LP respectively */
17158  if( ndelrows > 0 )
17159  {
17160  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
17161  }
17162  assert(lp->nrows == nrows - ndelrows);
17163 
17164  /* release temporary memory */
17165  SCIPsetFreeBufferArray(set, &rowdstat);
17166 
17167  return SCIP_OKAY;
17168 }
17169 
17170 /** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
17172  SCIP_LP* lp, /**< current LP data */
17173  BMS_BLKMEM* blkmem, /**< block memory buffers */
17174  SCIP_SET* set, /**< global SCIP settings */
17175  SCIP_STAT* stat, /**< problem statistics */
17176  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17177  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17178  SCIP_Bool root /**< are we at the root node? */
17179  )
17180 {
17181  SCIP_Bool cleanupcols;
17182  SCIP_Bool cleanuprows;
17183 
17184  assert(lp != NULL);
17185  assert(lp->solved);
17186  assert(!lp->diving);
17188  assert(set != NULL);
17189 
17190  /* check, if we want to clean up the columns and rows */
17191  cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
17192  cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
17193 
17194  SCIPdebugMessage("removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
17195  lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
17196 
17197  if( cleanupcols && lp->firstnewcol < lp->ncols )
17198  {
17199  SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
17200  }
17201  if( cleanuprows && lp->firstnewrow < lp->nrows )
17202  {
17203  SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
17204  }
17205 
17206  return SCIP_OKAY;
17207 }
17208 
17209 /** removes all non-basic columns at 0.0 and basic rows in the whole LP */
17211  SCIP_LP* lp, /**< current LP data */
17212  BMS_BLKMEM* blkmem, /**< block memory buffers */
17213  SCIP_SET* set, /**< global SCIP settings */
17214  SCIP_STAT* stat, /**< problem statistics */
17215  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17216  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17217  SCIP_Bool root /**< are we at the root node? */
17218  )
17219 {
17220  SCIP_Bool cleanupcols;
17221  SCIP_Bool cleanuprows;
17222 
17223  assert(lp != NULL);
17224  assert(lp->solved);
17225  assert(!lp->diving);
17227  assert(set != NULL);
17228 
17229  /* check, if we want to clean up the columns and rows */
17230  cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
17231  cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
17232 
17233  SCIPdebugMessage("removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
17234  cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
17235 
17236  if( cleanupcols && 0 < lp->ncols )
17237  {
17238  SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
17239  }
17240  if( cleanuprows && 0 < lp->nrows )
17241  {
17242  SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
17243  }
17244 
17245  return SCIP_OKAY;
17246 }
17247 
17248 /** removes all redundant rows that were added at the current node */
17250  SCIP_LP* lp, /**< current LP data */
17251  BMS_BLKMEM* blkmem, /**< block memory buffers */
17252  SCIP_SET* set, /**< global SCIP settings */
17253  SCIP_STAT* stat, /**< problem statistics */
17254  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17255  SCIP_EVENTFILTER* eventfilter /**< global event filter */
17256  )
17257 {
17258 #ifndef NDEBUG
17259  SCIP_ROW** rows;
17260 #endif
17261  SCIP_ROW** lpirows;
17262  int* rowdstat;
17263  int nrows;
17264  int ndelrows;
17265  int r;
17266 
17267  assert(lp != NULL);
17268  assert(lp->flushed);
17269  assert(lp->ncols == lp->nlpicols);
17270  assert(lp->nrows == lp->nlpirows);
17271  assert(!lp->diving);
17272  assert(stat != NULL);
17273  assert(lp->validsollp == stat->lpcount);
17274  assert(lp->firstnewrow <= lp->nrows);
17275 
17276  if( lp->firstnewrow == lp->nrows )
17277  return SCIP_OKAY;
17278 
17279 #ifndef NDEBUG
17280  rows = lp->rows;
17281 #endif
17282  nrows = lp->nrows;
17283  lpirows = lp->lpirows;
17284 
17285  /* get temporary memory */
17286  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
17287 
17288  /* mark redundant rows to be deleted (only delete basic rows!) */
17289  ndelrows = 0;
17290  BMSclearMemoryArray(rowdstat, nrows);
17291  for( r = lp->firstnewrow; r < nrows; ++r )
17292  {
17293  assert(rows[r] == lpirows[r]);
17294  assert(rows[r]->lppos == r);
17295  assert(rows[r]->lpipos == r);
17296  if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
17297  && SCIProwIsRedundant(lpirows[r], set, stat) )
17298  {
17299  SCIPdebugMessage("basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
17300  SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
17301  SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
17302  rowdstat[r] = 1;
17303  ndelrows++;
17304  }
17305  }
17306 
17307  SCIPdebugMessage("removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
17308 
17309  /* delete the marked rows in the LP solver interface, update the LP respectively */
17310  if( ndelrows > 0 )
17311  {
17312  SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
17313  }
17314  assert(lp->nrows == nrows - ndelrows);
17315 
17316  /* release temporary memory */
17317  SCIPsetFreeBufferArray(set, &rowdstat);
17318 
17319  return SCIP_OKAY;
17320 }
17321 
17322 /** initiates LP diving */
17324  SCIP_LP* lp, /**< current LP data */
17325  BMS_BLKMEM* blkmem, /**< block memory */
17326  SCIP_SET* set, /**< global SCIP settings */
17327  SCIP_STAT* stat /**< problem statistics */
17328  )
17329 {
17330  int c;
17331  int r;
17332 
17333  assert(lp != NULL);
17334  assert(lp->flushed || !lp->solved);
17335  assert(!lp->diving);
17336  assert(!lp->probing);
17337  assert(lp->divelpistate == NULL);
17338  assert(lp->divelpwasprimfeas);
17339  assert(lp->divelpwasdualfeas);
17340  assert(lp->validsollp <= stat->lpcount);
17341  assert(blkmem != NULL);
17342  assert(set != NULL);
17343  assert(lp->ndivechgsides == 0);
17344 
17345  SCIPdebugMessage("diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
17346  lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
17347 
17348 #ifndef NDEBUG
17349  for( c = 0; c < lp->ncols; ++c )
17350  {
17351  assert(lp->cols[c] != NULL);
17352  assert(lp->cols[c]->var != NULL);
17353  assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
17354  assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
17355  assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
17356  assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
17357  assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
17358  }
17359 #endif
17360 
17361  /* save current LPI state (basis information) */
17362  SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
17364  lp->divelpwasdualfeas = lp->dualfeasible;
17365 
17366  /* save current LP values dependent on the solution */
17367  SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
17368  assert(lp->storedsolvals != NULL);
17369  if( !set->lp_resolverestore && lp->solved )
17370  {
17371  SCIP_Bool store = TRUE;
17372 
17373  switch ( lp->lpsolstat )
17374  {
17376  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
17377  assert(lp->validsollp == stat->lpcount);
17378  break;
17380  SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
17381  assert(lp->validsollp == stat->lpcount);
17382  break;
17386  SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
17387  assert(lp->validsollp == stat->lpcount);
17388  break;
17390  SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat) );
17391  break;
17393  case SCIP_LPSOLSTAT_ERROR:
17394  default:
17395  store = FALSE;
17396  }
17397 
17398  if ( store )
17399  {
17400  for( c = 0; c < lp->ncols; ++c )
17401  {
17402  SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
17403  }
17404  for( r = 0; r < lp->nrows; ++r )
17405  {
17407  }
17408  }
17409  }
17410 
17411  /* store LPI iteration limit */
17413 
17414  /* store current number of rows */
17415  lp->ndivingrows = lp->nrows;
17416 
17417  /* switch to diving mode */
17418  lp->diving = TRUE;
17419 
17420  return SCIP_OKAY;
17421 }
17422 
17423 /** quits LP diving and resets bounds and objective values of columns to the current node's values */
17425  SCIP_LP* lp, /**< current LP data */
17426  BMS_BLKMEM* blkmem, /**< block memory */
17427  SCIP_SET* set, /**< global SCIP settings */
17428  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17429  SCIP_STAT* stat, /**< problem statistics */
17430  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
17431  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
17432  SCIP_PROB* prob, /**< problem data */
17433  SCIP_VAR** vars, /**< array with all active variables */
17434  int nvars /**< number of active variables */
17435  )
17436 {
17437  SCIP_VAR* var;
17438  int v;
17439 
17440  assert(lp != NULL);
17441  assert(lp->diving);
17442  assert(blkmem != NULL);
17443  assert(nvars == 0 || vars != NULL);
17444 
17445  SCIPdebugMessage("diving ended (LP flushed: %u, solstat: %d)\n",
17446  lp->flushed, SCIPlpGetSolstat(lp));
17447 
17448  /* reset all columns' objective values and bounds to its original values */
17449  for( v = 0; v < nvars; ++v )
17450  {
17451  var = vars[v];
17452  assert(var != NULL);
17454  {
17455  SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, SCIPvarGetObj(var)) );
17456  SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, SCIPvarGetLbLocal(var)) );
17457  SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, SCIPvarGetUbLocal(var)) );
17458  }
17459  }
17460 
17461  /* remove rows which were added in diving mode */
17462  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
17463 
17464  /* undo changes to left hand sides and right hand sides */
17465  while( lp->ndivechgsides > 0 )
17466  {
17467  SCIP_Real oldside;
17468  SCIP_SIDETYPE sidetype;
17469  SCIP_ROW* row;
17470 
17471  lp->ndivechgsides--;
17472  oldside = lp->divechgsides[lp->ndivechgsides];
17473  sidetype = lp->divechgsidetypes[lp->ndivechgsides];
17474  row = lp->divechgrows[lp->ndivechgsides];
17475 
17476  if( sidetype == SCIP_SIDETYPE_LEFT )
17477  {
17478  SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
17479  }
17480  else
17481  {
17482  SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
17483  }
17484  }
17485 
17486  /* restore LPI iteration limit */
17488 
17489  /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
17490  * happens
17491  */
17492  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, lp->divelpistate,
17494  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
17495  lp->divelpwasprimfeas = TRUE;
17496  lp->divelpwasdualfeas = TRUE;
17497  assert(lp->divelpistate == NULL);
17498 
17499  /* switch to standard (non-diving) mode */
17500  lp->diving = FALSE;
17501  lp->divingobjchg = FALSE;
17502 
17503  /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
17504  * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
17505  * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
17506  * the parameter resolverestore to TRUE
17507  * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
17508  */
17509  assert(lp->storedsolvals != NULL);
17510  if( lp->storedsolvals->lpissolved
17511  && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL) )
17512  {
17513  SCIP_Bool lperror;
17514 
17515  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) );
17516  if( lperror )
17517  {
17518  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
17519  "(node %"SCIP_LONGINT_FORMAT") unresolved numerical troubles while resolving LP %"SCIP_LONGINT_FORMAT" after diving\n", stat->nnodes, stat->nlps);
17520  lp->resolvelperror = TRUE;
17521  }
17526  {
17527  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
17528  "LP was not resolved to a sufficient status after diving\n");
17529  lp->resolvelperror = TRUE;
17530  }
17531  }
17532  /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
17533  * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
17534  * re-solve as above can lead to a different LP status
17535  */
17536  else
17537  {
17538  int c;
17539  int r;
17540 
17541  /* if there are lazy bounds, remove them from the LP */
17542  if( lp->nlazycols > 0 )
17543  {
17544  /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
17545  * first resolve LP?
17546  */
17547  SCIP_CALL( updateLazyBounds(lp, set) );
17548  assert(lp->diving == lp->divinglazyapplied);
17549 
17550  /* flush changes to the LP solver */
17551  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
17552  }
17553 
17554  /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
17555  stat->lpcount++;
17556 
17557  /* restore LP solution values in lp data, columns and rows */
17558  if( lp->storedsolvals->lpissolved &&
17565  )
17566  {
17567  SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
17568 
17569  for( c = 0; c < lp->ncols; ++c )
17570  {
17571  SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
17572  }
17573  for( r = 0; r < lp->nrows; ++r )
17574  {
17575  SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
17576  }
17577  }
17578  else
17579  {
17580  SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
17581  }
17582  }
17583 
17584 #ifndef NDEBUG
17585  {
17586  int c;
17587  for( c = 0; c < lp->ncols; ++c )
17588  {
17589  assert(lp->cols[c] != NULL);
17590  assert(lp->cols[c]->var != NULL);
17591  assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
17592  assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
17593  assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
17594  assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
17595  assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
17596  }
17597  }
17598 #endif
17599 
17600  return SCIP_OKAY;
17601 }
17602 
17603 #define DIVESTACKGROWFACT 1.5
17604 
17605 /** records a current row side such that any change will be undone after diving */
17607  SCIP_LP* lp, /**< LP data object */
17608  SCIP_ROW* row, /**< row affected by the change */
17609  SCIP_SIDETYPE sidetype /**< side type */
17610  )
17611 {
17612  assert(lp != NULL);
17613  assert(row != NULL);
17614 
17615  if( lp->ndivechgsides == lp->divechgsidessize )
17616  {
17618  }
17619  assert(lp->ndivechgsides < lp->divechgsidessize);
17620 
17621  lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
17622  lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
17623  lp->divechgrows[lp->ndivechgsides] = row;
17624  lp->ndivechgsides++;
17625 
17626  return SCIP_OKAY;
17627 }
17628 
17629 /** informs the LP that probing mode was initiated */
17631  SCIP_LP* lp /**< current LP data */
17632  )
17633 {
17634  assert(lp != NULL);
17635  assert(!lp->probing);
17636  assert(!lp->strongbranching);
17637  assert(!lp->strongbranchprobing);
17638 
17639  lp->probing = TRUE;
17640 
17641  return SCIP_OKAY;
17642 }
17643 
17644 /** informs the LP that probing mode was finished */
17646  SCIP_LP* lp /**< current LP data */
17647  )
17648 {
17649  assert(lp != NULL);
17650  assert(lp->probing);
17651  assert(!lp->strongbranching);
17652  assert(!lp->strongbranchprobing);
17653 
17654  lp->probing = FALSE;
17655 
17656  return SCIP_OKAY;
17657 }
17658 
17659 /** informs the LP that the probing mode is now used for strongbranching */
17661  SCIP_LP* lp /**< current LP data */
17662  )
17663 {
17664  assert(lp != NULL);
17665  assert(lp->probing);
17666  assert(!lp->strongbranching);
17667  assert(!lp->strongbranchprobing);
17668 
17669  lp->strongbranchprobing = TRUE;
17670 }
17671 
17672 /** informs the LP that the probing mode is not used for strongbranching anymore */
17674  SCIP_LP* lp /**< current LP data */
17675  )
17676 {
17677  assert(lp != NULL);
17678  assert(lp->probing);
17679  assert(!lp->strongbranching);
17680  assert(lp->strongbranchprobing);
17681 
17682  lp->strongbranchprobing = FALSE;
17683 }
17684 
17685 /** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
17686  * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
17687  * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
17688  * we have only left hand sides):
17689  * min{cx | b <= Ax, lb <= x <= ub}
17690  * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
17691  * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
17692  * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
17693  * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
17694  */
17695 static
17697  SCIP_LP* lp, /**< current LP data */
17698  SCIP_SET* set, /**< global SCIP settings */
17699  SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
17700  SCIP_Real* bound /**< result of interval arithmetic minimization */
17701  )
17702 {
17703  SCIP_INTERVAL* yinter;
17704  SCIP_INTERVAL b;
17705  SCIP_INTERVAL ytb;
17706  SCIP_INTERVAL prod;
17707  SCIP_INTERVAL diff;
17708  SCIP_INTERVAL x;
17709  SCIP_INTERVAL minprod;
17710  SCIP_INTERVAL a;
17711  SCIP_ROW* row;
17712  SCIP_COL* col;
17713  SCIP_Real y;
17714  SCIP_Real c;
17715  int i;
17716  int j;
17717 
17718  assert(lp != NULL);
17719  assert(lp->solved);
17720  assert(set != NULL);
17721  assert(bound != NULL);
17722 
17723  /* allocate buffer for storing y in interval arithmetic */
17724  SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
17725 
17726  /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
17727  SCIPintervalSet(&ytb, 0.0);
17728  for( j = 0; j < lp->nrows; ++j )
17729  {
17730  row = lp->rows[j];
17731  assert(row != NULL);
17732 
17733  y = (usefarkas ? row->dualfarkas : row->dualsol);
17734 
17735  if( SCIPsetIsFeasPositive(set, y) )
17736  {
17737  SCIPintervalSet(&yinter[j], y);
17738  SCIPintervalSet(&b, row->lhs - row->constant);
17739  }
17740  else if( SCIPsetIsFeasNegative(set, y) )
17741  {
17742  SCIPintervalSet(&yinter[j], y);
17743  SCIPintervalSet(&b, row->rhs - row->constant);
17744  }
17745  else
17746  {
17747  SCIPintervalSet(&yinter[j], 0.0);
17748  SCIPintervalSet(&b, 0.0);
17749  }
17750 
17751  SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
17752  SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
17753  }
17754 
17755  /* calculate min{(c^T - y^TA)x} */
17756  SCIPintervalSet(&minprod, 0.0);
17757  for( j = 0; j < lp->ncols; ++j )
17758  {
17759  col = lp->cols[j];
17760  assert(col != NULL);
17761  assert(col->nunlinked == 0);
17762 
17764 
17765  c = usefarkas ? 0.0 : col->obj;
17766  SCIPintervalSet(&diff, c);
17767 
17768  for( i = 0; i < col->nlprows; ++i )
17769  {
17770  assert(col->rows[i] != NULL);
17771  assert(col->rows[i]->lppos >= 0);
17772  assert(col->linkpos[i] >= 0);
17773  SCIPintervalSet(&a, col->vals[i]);
17774  SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
17775  SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
17776  }
17777 
17778 #ifndef NDEBUG
17779  for( i = col->nlprows; i < col->len; ++i )
17780  {
17781  assert(col->rows[i] != NULL);
17782  assert(col->rows[i]->lppos == -1);
17783  assert(col->rows[i]->dualsol == 0.0);
17784  assert(col->rows[i]->dualfarkas == 0.0);
17785  assert(col->linkpos[i] >= 0);
17786  }
17787 #endif
17788 
17789  SCIPintervalSetBounds(&x, col->lb, col->ub);
17790  SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
17791  SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
17792  }
17793 
17794  /* add y^Tb */
17795  SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
17796 
17797  /* free buffer for storing y in interval arithmetic */
17798  SCIPsetFreeBufferArray(set, &yinter);
17799 
17800  *bound = SCIPintervalGetInf(minprod);
17801 
17802  return SCIP_OKAY;
17803 }
17804 
17805 /** gets proven lower (dual) bound of last LP solution */
17807  SCIP_LP* lp, /**< current LP data */
17808  SCIP_SET* set, /**< global SCIP settings */
17809  SCIP_Real* bound /**< pointer to store proven dual bound */
17810  )
17811 {
17812  SCIP_CALL( provedBound(lp, set, FALSE, bound) );
17813 
17814  SCIPdebugMessage("proved lower bound of LP: %.15g\n", *bound);
17815 
17816  return SCIP_OKAY;
17817 }
17818 
17819 /** gets proven dual bound of last LP solution */
17821  SCIP_LP* lp, /**< current LP data */
17822  SCIP_SET* set, /**< global SCIP settings */
17823  SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
17824  )
17825 {
17826  SCIP_Real bound;
17827 
17828  assert(proved != NULL);
17829 
17830  SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
17831 
17832  *proved = (bound > 0.0);
17833 
17834  SCIPdebugMessage("proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
17835 
17836  return SCIP_OKAY;
17837 }
17838 
17839 
17840 
17841 /** writes LP to a file */
17843  SCIP_LP* lp, /**< current LP data */
17844  const char* fname /**< file name */
17845  )
17846 {
17847  assert(lp != NULL);
17848  assert(lp->flushed);
17849  assert(fname != NULL);
17850 
17851  SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
17852 
17853  return SCIP_OKAY;
17854 }
17855 
17856 /** writes MIP relaxation of the current B&B node to a file */
17858  SCIP_LP* lp, /**< current LP data */
17859  SCIP_SET* set, /**< global SCIP settings */
17860  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17861  const char* fname, /**< file name */
17862  SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
17863  * troubles with reserved symbols? */
17864  SCIP_Bool origobj, /**< should the original objective function be used? */
17865  SCIP_OBJSENSE objsense, /**< objective sense */
17866  SCIP_Real objscale, /**< objective scaling factor */
17867  SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
17868  SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
17869  )
17870 {
17871  FILE* file;
17872  int i;
17873  int j;
17874  char rowname[SCIP_MAXSTRLEN];
17875  SCIP_Real coeff;
17876 
17877  assert(lp != NULL);
17878  assert(lp->flushed);
17879  assert(fname != NULL);
17880 
17881  SCIPdebugMessage("Start to write MIP to file <%s>\n", fname);
17882  file = fopen(fname, "w");
17883  if( file == NULL )
17884  {
17885  SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
17886  SCIPprintSysError(fname);
17887  return SCIP_FILECREATEERROR;
17888  }
17889 
17890  /* print comments */
17891  if( genericnames )
17892  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
17893  else
17894  {
17895  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
17896  SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
17897  }
17898 
17899  if( origobj && objoffset != 0.0 )
17900  {
17901  SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
17902  SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
17903  }
17904 
17905  /* print objective function */
17906  /**@note the transformed problem in SCIP is always a minimization problem */
17907  if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
17908  SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
17909  else
17910  SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
17911 
17912  /* print objective */
17913  SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
17914  j = 0;
17915  for( i = 0; i < lp->ncols; ++i )
17916  {
17917  if( lp->cols[i]->obj != 0.0 )
17918  {
17919  coeff = lp->cols[i]->obj;
17920  if( origobj )
17921  {
17922  coeff *= (SCIP_Real) objsense;
17923  coeff *= objscale;
17924  }
17925 
17926  if( genericnames )
17927  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
17928  else
17929  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
17930 
17931  ++j;
17932  if( j % 10 == 0 )
17933  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
17934  }
17935  }
17936  /* add artificial variable 'objoffset' to transfer objective offset */
17937  if( origobj && objoffset != 0.0 )
17938  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
17939 
17940  /* print constraint section */
17941  SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
17942  for( i = 0; i < lp->nrows; i++ )
17943  {
17944  char type = 'i';
17945 
17946  /* skip removable rows if we want to write them as lazy constraints */
17947  if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
17948  continue;
17949 
17950  /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
17951  * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
17952  * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
17953  * type 'i' means: lhs and rhs are both infinite */
17954  if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
17955  type = 'r';
17956  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
17957  type = 'l';
17958  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
17959  type = 'e';
17960  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
17961  type = 'b';
17962 
17963  /* print name of row */
17964  if( genericnames )
17965  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
17966  else
17967  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
17968 
17969  WRITEROW:
17970  switch( type )
17971  {
17972  case 'r':
17973  case 'l':
17974  case 'e':
17975  if( strlen(rowname) > 0 )
17976  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
17977  break;
17978  case 'i':
17979  SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
17980  SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
17981  SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
17982  type = 'b';
17983  /*lint -fallthrough*/
17984  case 'b':
17985  SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
17986  break;
17987  case 'B':
17988  SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
17989  break;
17990  default:
17991  SCIPerrorMessage("Undefined row type!\n");
17992  return SCIP_ERROR;
17993  }
17994 
17995  /* print coefficients and variables */
17996  for( j = 0; j < lp->rows[i]->nlpcols; ++j )
17997  {
17998  if( genericnames )
17999  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
18000  else
18001  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
18002 
18003  if( (j+1) % 10 == 0 )
18004  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
18005  }
18006 
18007  /* print right hand side */
18008  switch( type )
18009  {
18010  case 'b':
18011  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18012  type = 'B';
18013  goto WRITEROW;
18014  case 'l':
18015  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18016  break;
18017  case 'B':
18018  case 'r':
18019  SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
18020  break;
18021  case 'e':
18022  SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18023  break;
18024  default:
18025  SCIPerrorMessage("Undefined row type!\n");
18026  return SCIP_ERROR;
18027  }
18028  }
18029 
18030  if ( lazyconss )
18031  {
18032  /* print lazy constraint section */
18033  SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
18034  for( i = 0; i < lp->nrows; i++ )
18035  {
18036  char type = 'i';
18037 
18038  /* skip non-removable rows if we want to write lazy constraints */
18039  if ( ! SCIProwIsRemovable(lp->rows[i]) )
18040  continue;
18041 
18042  /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
18043  * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
18044  * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
18045  * type 'i' means: lhs and rhs are both infinite */
18046  if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18047  type = 'r';
18048  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18049  type = 'l';
18050  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
18051  type = 'e';
18052  else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
18053  type = 'b';
18054 
18055  /* print name of row */
18056  if( genericnames )
18057  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
18058  else
18059  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
18060 
18061  WRITELAZYROW:
18062  switch( type )
18063  {
18064  case 'r':
18065  case 'l':
18066  case 'e':
18067  if( strlen(rowname) > 0 )
18068  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
18069  break;
18070  case 'i':
18071  SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
18072  SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
18073  SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
18074  type = 'b';
18075  /*lint -fallthrough*/
18076  case 'b':
18077  SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
18078  break;
18079  case 'B':
18080  SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
18081  break;
18082  default:
18083  SCIPerrorMessage("Undefined row type!\n");
18084  return SCIP_ERROR;
18085  }
18086 
18087  /* print coefficients and variables */
18088  for( j = 0; j < lp->rows[i]->nlpcols; ++j )
18089  {
18090  if( genericnames )
18091  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
18092  else
18093  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
18094 
18095  if( (j+1) % 10 == 0 )
18096  SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
18097  }
18098 
18099  /* print right hand side */
18100  switch( type )
18101  {
18102  case 'b':
18103  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18104  type = 'B';
18105  goto WRITELAZYROW;
18106  case 'l':
18107  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18108  break;
18109  case 'B':
18110  case 'r':
18111  SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
18112  break;
18113  case 'e':
18114  SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
18115  break;
18116  default:
18117  SCIPerrorMessage("Undefined row type!\n");
18118  return SCIP_ERROR;
18119  }
18120  }
18121  }
18122 
18123  /* print variable bounds */
18124  SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
18125  for( i = 0; i < lp->ncols; ++i )
18126  {
18127  if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
18128  {
18129  /* print lower bound as far this one is not infinity */
18130  if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
18131  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
18132 
18133  /* print variable name */
18134  if( genericnames )
18135  SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
18136  else
18137  SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
18138 
18139  /* print upper bound as far this one is not infinity */
18140  if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
18141  SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
18142  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
18143  }
18144  }
18145  if( origobj && objoffset != 0.0 )
18146  SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
18147 
18148  /* print integer variables */
18149  SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
18150  j = 0;
18151  for( i = 0; i < lp->ncols; ++i )
18152  {
18153  if( SCIPvarIsIntegral(lp->cols[i]->var) )
18154  {
18155  /* print variable name */
18156  if( genericnames )
18157  SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
18158  else
18159  SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
18160 
18161  j++;
18162  if( j % 10 == 0 )
18163  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
18164  }
18165  }
18166 
18167  SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
18168  fclose(file);
18169 
18170  return SCIP_OKAY;
18171 }
18172 
18173 /*
18174  * simple functions implemented as defines
18175  */
18176 
18177 /* In debug mode, the following methods are implemented as function calls to ensure
18178  * type validity.
18179  * In optimized mode, the methods are implemented as defines to improve performance.
18180  * However, we want to have them in the library anyways, so we have to undef the defines.
18181  */
18182 
18183 #undef SCIPcolGetObj
18184 #undef SCIPcolGetLb
18185 #undef SCIPcolGetUb
18186 #undef SCIPcolGetBestBound
18187 #undef SCIPcolGetPrimsol
18188 #undef SCIPcolGetMinPrimsol
18189 #undef SCIPcolGetMaxPrimsol
18190 #undef SCIPcolGetBasisStatus
18191 #undef SCIPcolGetVar
18192 #undef SCIPcolGetIndex
18193 #undef SCIPcolIsIntegral
18194 #undef SCIPcolIsRemovable
18195 #undef SCIPcolGetLPPos
18196 #undef SCIPcolGetLPDepth
18197 #undef SCIPcolIsInLP
18198 #undef SCIPcolGetNNonz
18199 #undef SCIPcolGetNLPNonz
18200 #undef SCIPcolGetRows
18201 #undef SCIPcolGetVals
18202 #undef SCIPcolGetStrongbranchNode
18203 #undef SCIPcolGetNStrongbranchs
18204 #undef SCIPboundtypeOpposite
18205 #undef SCIProwGetNNonz
18206 #undef SCIProwGetNLPNonz
18207 #undef SCIProwGetCols
18208 #undef SCIProwGetVals
18209 #undef SCIProwGetConstant
18210 #undef SCIProwGetNorm
18211 #undef SCIProwGetSumNorm
18212 #undef SCIProwGetLhs
18213 #undef SCIProwGetRhs
18214 #undef SCIProwGetDualsol
18215 #undef SCIProwGetDualfarkas
18216 #undef SCIProwGetBasisStatus
18217 #undef SCIProwGetName
18218 #undef SCIProwGetIndex
18219 #undef SCIProwGetAge
18220 #undef SCIProwGetRank
18221 #undef SCIProwIsIntegral
18222 #undef SCIProwIsLocal
18223 #undef SCIProwIsModifiable
18224 #undef SCIProwIsRemovable
18225 #undef SCIProwGetOrigintype
18226 #undef SCIProwGetOriginCons
18227 #undef SCIProwGetOriginSepa
18228 #undef SCIProwIsInGlobalCutpool
18229 #undef SCIProwGetLPPos
18230 #undef SCIProwGetLPDepth
18231 #undef SCIProwIsInLP
18232 #undef SCIProwChgRank
18233 #undef SCIPlpGetCols
18234 #undef SCIPlpGetNCols
18235 #undef SCIPlpGetRows
18236 #undef SCIPlpGetNRows
18237 #undef SCIPlpGetNewcols
18238 #undef SCIPlpGetNNewcols
18239 #undef SCIPlpGetNewrows
18240 #undef SCIPlpGetNNewrows
18241 #undef SCIPlpGetObjNorm
18242 #undef SCIPlpGetRootObjval
18243 #undef SCIPlpGetRootColumnObjval
18244 #undef SCIPlpGetRootLooseObjval
18245 #undef SCIPlpGetLPI
18246 #undef SCIPlpSetIsRelax
18247 #undef SCIPlpIsRelax
18248 #undef SCIPlpIsSolved
18249 #undef SCIPlpIsSolBasic
18250 #undef SCIPlpDiving
18251 #undef SCIPlpDivingObjChanged
18252 #undef SCIPlpMarkDivingObjChanged
18253 
18254 /** gets objective value of column */
18256  SCIP_COL* col /**< LP column */
18257  )
18258 {
18259  assert(col != NULL);
18260 
18261  return col->obj;
18262 }
18263 
18264 /** gets lower bound of column */
18266  SCIP_COL* col /**< LP column */
18267  )
18268 {
18269  assert(col != NULL);
18270 
18271  return col->lb;
18272 }
18273 
18274 /** gets upper bound of column */
18276  SCIP_COL* col /**< LP column */
18277  )
18278 {
18279  assert(col != NULL);
18280 
18281  return col->ub;
18282 }
18283 
18284 /** gets best bound of column with respect to the objective function */
18286  SCIP_COL* col /**< LP column */
18287  )
18288 {
18289  assert(col != NULL);
18290 
18291  if( col->obj >= 0.0 )
18292  return col->lb;
18293  else
18294  return col->ub;
18295 }
18296 
18297 /** gets the primal LP solution of a column */
18299  SCIP_COL* col /**< LP column */
18300  )
18301 {
18302  assert(col != NULL);
18303 
18304  if( col->lppos >= 0 )
18305  return col->primsol;
18306  else
18307  return 0.0;
18308 }
18309 
18310 /** gets the minimal LP solution value, this column ever assumed */
18312  SCIP_COL* col /**< LP column */
18313  )
18314 {
18315  assert(col != NULL);
18316 
18317  return col->minprimsol;
18318 }
18319 
18320 /** gets the maximal LP solution value, this column ever assumed */
18322  SCIP_COL* col /**< LP column */
18323  )
18324 {
18325  assert(col != NULL);
18326 
18327  return col->maxprimsol;
18328 }
18329 
18330 /** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
18331  * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
18332  */
18334  SCIP_COL* col /**< LP column */
18335  )
18336 {
18337  assert(col != NULL);
18338  assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
18339 
18340  return (SCIP_BASESTAT)col->basisstatus;
18341 }
18342 
18343 /** gets variable this column represents */
18345  SCIP_COL* col /**< LP column */
18346  )
18347 {
18348  assert(col != NULL);
18349 
18350  return col->var;
18351 }
18352 
18353 /** gets unique index of col */
18355  SCIP_COL* col /**< LP col */
18356  )
18357 {
18358  assert(col != NULL);
18359 
18360  return col->index;
18361 }
18362 
18363 /** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
18365  SCIP_COL* col /**< LP column */
18366  )
18367 {
18368  assert(col != NULL);
18369  assert(SCIPvarIsIntegral(col->var) == col->integral);
18370 
18371  return col->integral;
18372 }
18373 
18374 /** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
18376  SCIP_COL* col /**< LP column */
18377  )
18378 {
18379  assert(col != NULL);
18380 
18381  return col->removable;
18382 }
18383 
18384 /** gets position of column in current LP, or -1 if it is not in LP */
18386  SCIP_COL* col /**< LP column */
18387  )
18388 {
18389  assert(col != NULL);
18390  assert((col->lppos == -1) == (col->lpdepth == -1));
18391 
18392  return col->lppos;
18393 }
18394 
18395 /** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
18397  SCIP_COL* col /**< LP column */
18398  )
18399 {
18400  assert(col != NULL);
18401  assert((col->lppos == -1) == (col->lpdepth == -1));
18402 
18403  return col->lpdepth;
18404 }
18405 
18406 /** returns TRUE iff column is member of current LP */
18408  SCIP_COL* col /**< LP column */
18409  )
18410 {
18411  assert(col != NULL);
18412  assert((col->lppos == -1) == (col->lpdepth == -1));
18413 
18414  return (col->lppos >= 0);
18415 }
18416 
18417 /** get number of nonzero entries in column vector */
18419  SCIP_COL* col /**< LP column */
18420  )
18421 {
18422  assert(col != NULL);
18423 
18424  return col->len;
18425 }
18426 
18427 /** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
18428  *
18429  * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
18430  * 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
18431  */
18433  SCIP_COL* col /**< LP column */
18434  )
18435 {
18436  assert(col != NULL);
18437  assert(col->nunlinked == 0);
18438 
18439  return col->nlprows;
18440 }
18441 
18442 /** gets array with rows of nonzero entries */
18444  SCIP_COL* col /**< LP column */
18445  )
18446 {
18447  assert(col != NULL);
18448 
18449  return col->rows;
18450 }
18451 
18452 /** gets array with coefficients of nonzero entries */
18454  SCIP_COL* col /**< LP column */
18455  )
18456 {
18457  assert(col != NULL);
18458 
18459  return col->vals;
18460 }
18461 
18462 /** gets node number of the last node in current branch and bound run, where strong branching was used on the
18463  * given column, or -1 if strong branching was never applied to the column in current run
18464  */
18466  SCIP_COL* col /**< LP column */
18467  )
18468 {
18469  assert(col != NULL);
18470 
18471  return col->sbnode;
18472 }
18473 
18474 /** gets number of times, strong branching was applied in current run on the given column */
18476  SCIP_COL* col /**< LP column */
18477  )
18478 {
18479  assert(col != NULL);
18480 
18481  return col->nsbcalls;
18482 }
18483 
18484 /** gets opposite bound type of given bound type */
18486  SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
18487  )
18488 {
18489  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
18490 
18492 }
18493 
18494 /** get number of nonzero entries in row vector */
18496  SCIP_ROW* row /**< LP row */
18497  )
18498 {
18499  assert(row != NULL);
18500 
18501  return row->len;
18502 }
18503 
18504 /** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
18505  *
18506  * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
18507  * 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
18508  */
18510  SCIP_ROW* row /**< LP row */
18511  )
18512 {
18513  assert(row != NULL);
18514  assert(row->nunlinked == 0);
18515 
18516  return row->nlpcols;
18517 }
18518 
18519 /** gets array with columns of nonzero entries */
18521  SCIP_ROW* row /**< LP row */
18522  )
18523 {
18524  assert(row != NULL);
18525 
18526  return row->cols;
18527 }
18528 
18529 /** gets array with coefficients of nonzero entries */
18531  SCIP_ROW* row /**< LP row */
18532  )
18533 {
18534  assert(row != NULL);
18535 
18536  return row->vals;
18537 }
18538 
18539 /** gets constant shift of row */
18541  SCIP_ROW* row /**< LP row */
18542  )
18543 {
18544  assert(row != NULL);
18545 
18546  return row->constant;
18547 }
18548 
18549 /** gets Euclidean norm of row vector */
18551  SCIP_ROW* row /**< LP row */
18552  )
18553 {
18554  assert(row != NULL);
18555 
18556  checkRowSqrnorm(row);
18557 
18558  return sqrt(row->sqrnorm);
18559 }
18560 
18561 /** gets sum norm of row vector (sum of absolute values of coefficients) */
18563  SCIP_ROW* row /**< LP row */
18564  )
18565 {
18566  assert(row != NULL);
18567 
18568  checkRowSumnorm(row);
18569 
18570  return row->sumnorm;
18571 }
18572 
18573 /** returns the left hand side of the row */
18575  SCIP_ROW* row /**< LP row */
18576  )
18577 {
18578  assert(row != NULL);
18579 
18580  return row->lhs;
18581 }
18582 
18583 /** returns the right hand side of the row */
18585  SCIP_ROW* row /**< LP row */
18586  )
18587 {
18588  assert(row != NULL);
18589 
18590  return row->rhs;
18591 }
18592 
18593 /** gets the dual LP solution of a row */
18595  SCIP_ROW* row /**< LP row */
18596  )
18597 {
18598  assert(row != NULL);
18599 
18600  if( row->lppos >= 0 )
18601  return row->dualsol;
18602  else
18603  return 0.0;
18604 }
18605 
18606 /** gets the dual Farkas coefficient of a row in an infeasible LP */
18608  SCIP_ROW* row /**< LP row */
18609  )
18610 {
18611  assert(row != NULL);
18612 
18613  if( row->lppos >= 0 )
18614  return row->dualfarkas;
18615  else
18616  return 0.0;
18617 }
18618 
18619 /** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
18620  * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
18621  */
18623  SCIP_ROW* row /**< LP row */
18624  )
18625 {
18626  assert(row != NULL);
18627  assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
18628 
18629  return (SCIP_BASESTAT)row->basisstatus;
18630 }
18631 
18632 /** returns the name of the row */
18633 const char* SCIProwGetName(
18634  SCIP_ROW* row /**< LP row */
18635  )
18636 {
18637  assert(row != NULL);
18638 
18639  return row->name;
18640 }
18641 
18642 /** gets unique index of row */
18644  SCIP_ROW* row /**< LP row */
18645  )
18646 {
18647  assert(row != NULL);
18648 
18649  return row->index;
18650 }
18651 
18652 /** gets age of row */
18654  SCIP_ROW* row /**< LP row */
18655  )
18656 {
18657  assert(row != NULL);
18658 
18659  return row->age;
18660 }
18661 
18662 /** gets rank of row */
18664  SCIP_ROW* row /**< LP row */
18665  )
18666 {
18667  assert(row != NULL);
18668 
18669  return row->rank;
18670 }
18671 
18672 /** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
18674  SCIP_ROW* row /**< LP row */
18675  )
18676 {
18677  assert(row != NULL);
18678 
18679  return row->integral;
18680 }
18681 
18682 /** returns TRUE iff row is only valid locally */
18684  SCIP_ROW* row /**< LP row */
18685  )
18686 {
18687  assert(row != NULL);
18688 
18689  return row->local;
18690 }
18691 
18692 /** returns TRUE iff row is modifiable during node processing (subject to column generation) */
18694  SCIP_ROW* row /**< LP row */
18695  )
18696 {
18697  assert(row != NULL);
18698 
18699  return row->modifiable;
18700 }
18701 
18702 /** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
18704  SCIP_ROW* row /**< LP row */
18705  )
18706 {
18707  assert(row != NULL);
18708 
18709  return row->removable;
18710 }
18711 
18712 /** returns type of origin that created the row */
18714  SCIP_ROW* row /**< LP row */
18715  )
18716 {
18717  assert( row != NULL );
18718 
18719  return (SCIP_ROWORIGINTYPE) row->origintype;
18720 }
18721 
18722 /** returns origin constraint handler that created the row (NULL if not available) */
18724  SCIP_ROW* row /**< LP row */
18725  )
18726 {
18727  assert( row != NULL );
18728 
18730  {
18731  assert( row->origin != NULL );
18732  return (SCIP_CONSHDLR*) row->origin;
18733  }
18734  return NULL;
18735 }
18736 
18737 /** returns origin separator that created the row (NULL if not available) */
18739  SCIP_ROW* row /**< LP row */
18740  )
18741 {
18742  assert( row != NULL );
18743 
18745  {
18746  assert( row->origin != NULL );
18747  return (SCIP_SEPA*) row->origin;
18748  }
18749  return NULL;
18750 }
18751 
18752 /** returns TRUE iff row is member of the global cut pool */
18754  SCIP_ROW* row /**< LP row */
18755  )
18756 {
18757  assert(row != NULL);
18758 
18759  return row->inglobalcutpool;
18760 }
18761 
18762 /** gets position of row in current LP, or -1 if it is not in LP */
18764  SCIP_ROW* row /**< LP row */
18765  )
18766 {
18767  assert(row != NULL);
18768  assert((row->lppos == -1) == (row->lpdepth == -1));
18769 
18770  return row->lppos;
18771 }
18772 
18773 /** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
18775  SCIP_ROW* row /**< LP row */
18776  )
18777 {
18778  assert(row != NULL);
18779  assert((row->lppos == -1) == (row->lpdepth == -1));
18780 
18781  return row->lpdepth;
18782 }
18783 
18784 /** returns TRUE iff row is member of current LP */
18786  SCIP_ROW* row /**< LP row */
18787  )
18788 {
18789  assert(row != NULL);
18790  assert((row->lppos == -1) == (row->lpdepth == -1));
18791 
18792  return (row->lppos >= 0);
18793 }
18794 
18795 /** changes the rank of LP row */
18797  SCIP_ROW* row, /**< LP row */
18798  int rank /**< new value for rank */
18799  )
18800 {
18801  assert(row != NULL);
18802 
18803  row->rank = rank;
18804 }
18805 
18806 /** gets array with columns of the LP */
18808  SCIP_LP* lp /**< current LP data */
18809  )
18810 {
18811  assert(lp != NULL);
18812 
18813  return lp->cols;
18814 }
18815 
18816 /** gets current number of columns in LP */
18818  SCIP_LP* lp /**< current LP data */
18819  )
18820 {
18821  assert(lp != NULL);
18822 
18823  return lp->ncols;
18824 }
18825 
18826 /** gets array with rows of the LP */
18828  SCIP_LP* lp /**< current LP data */
18829  )
18830 {
18831  assert(lp != NULL);
18832 
18833  return lp->rows;
18834 }
18835 
18836 /** gets current number of rows in LP */
18838  SCIP_LP* lp /**< current LP data */
18839  )
18840 {
18841  assert(lp != NULL);
18842 
18843  return lp->nrows;
18844 }
18845 
18846 /** gets array with newly added columns after the last mark */
18848  SCIP_LP* lp /**< current LP data */
18849  )
18850 {
18851  assert(lp != NULL);
18852  assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
18853 
18854  return &(lp->cols[lp->firstnewcol]);
18855 }
18856 
18857 /** gets number of newly added columns after the last mark */
18859  SCIP_LP* lp /**< current LP data */
18860  )
18861 {
18862  assert(lp != NULL);
18863  assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
18864 
18865  return lp->ncols - lp->firstnewcol;
18866 }
18867 
18868 /** gets array with newly added rows after the last mark */
18870  SCIP_LP* lp /**< current LP data */
18871  )
18872 {
18873  assert(lp != NULL);
18874  assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
18875 
18876  return &(lp->rows[lp->firstnewrow]);
18877 }
18878 
18879 /** gets number of newly added rows after the last mark */
18881  SCIP_LP* lp /**< current LP data */
18882  )
18883 {
18884  assert(lp != NULL);
18885  assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
18886 
18887  return lp->nrows - lp->firstnewrow;
18888 }
18889 
18890 /** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
18892  SCIP_SET* set, /**< global SCIP settings */
18893  SCIP_LP* lp /**< LP data */
18894  )
18895 {
18896  if( lp->objsqrnormunreliable )
18897  {
18898  SCIP_COL** cols;
18899  int c;
18900 
18901  cols = lp->cols;
18902  assert(cols != NULL || lp->ncols == 0);
18903 
18904  lp->objsqrnorm = 0.0;
18905 
18906  for( c = lp->ncols - 1; c >= 0; --c )
18907  {
18908  lp->objsqrnorm += SQR(cols[c]->obj); /*lint !e613*/
18909  }
18910  assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
18911 
18912  /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
18913  lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
18914 
18916  }
18917  return;
18918 }
18919 
18920 /** gets Euclidean norm of objective function vector of column variables, only use this method if
18921  * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
18923  SCIP_LP* lp /**< LP data */
18924  )
18925 {
18926  assert(lp != NULL);
18927  assert(!lp->objsqrnormunreliable);
18928  assert(lp->objsqrnorm >= 0.0);
18929 
18930  return SQRT(lp->objsqrnorm);
18931 }
18932 
18933 /** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
18935  SCIP_LP* lp, /**< LP data */
18936  SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
18937  )
18938 {
18939  assert(lp != NULL);
18940 
18941  lp->rootlpisrelax = isrelax;
18942 }
18943 
18944 /** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
18946  SCIP_LP* lp /**< LP data */
18947  )
18948 {
18949  assert(lp != NULL);
18950 
18951  return lp->rootlpisrelax;
18952 }
18953 
18954 /** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
18956  SCIP_LP* lp /**< LP data */
18957  )
18958 {
18959  assert(lp != NULL);
18960 
18961  return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
18962 }
18963 
18964 /** gets part of the objective value of the root node LP that results from COLUMN variables only;
18965  * returns SCIP_INVALID if the root node LP was not (yet) solved
18966  */
18968  SCIP_LP* lp /**< LP data */
18969  )
18970 {
18971  assert(lp != NULL);
18972 
18973  return lp->rootlpobjval;
18974 }
18975 
18976 /** gets part of the objective value of the root node LP that results from LOOSE variables only;
18977  * returns SCIP_INVALID if the root node LP was not (yet) solved
18978  */
18980  SCIP_LP* lp /**< LP data */
18981  )
18982 {
18983  assert(lp != NULL);
18984 
18985  return lp->rootlooseobjval;
18986 }
18987 
18988 /** gets the LP solver interface */
18990  SCIP_LP* lp /**< current LP data */
18991  )
18992 {
18993  assert(lp != NULL);
18994 
18995  return lp->lpi;
18996 }
18997 
18998 /** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
19000  SCIP_LP* lp, /**< LP data */
19001  SCIP_Bool relax /**< is the current lp a relaxation? */
19002  )
19003 {
19004  assert(lp != NULL);
19005 
19006  lp->isrelax = relax;
19007 }
19008 
19009 /** returns whether the current LP is a relaxation of the problem for which it has been solved and its
19010  * solution value a valid local lower bound?
19011  */
19013  SCIP_LP* lp /**< LP data */
19014  )
19015 {
19016  assert(lp != NULL);
19017 
19018  return lp->isrelax;
19019 }
19020 
19021 /** returns whether the current LP is flushed and solved */
19023  SCIP_LP* lp /**< current LP data */
19024  )
19025 {
19026  assert(lp != NULL);
19027 
19028  return lp->flushed && lp->solved;
19029 }
19030 
19031 /** returns whether the current LP solution is a basic solution */
19033  SCIP_LP* lp /**< current LP data */
19034  )
19035 {
19036  assert(lp != NULL);
19037 
19038  return lp->solisbasic;
19039 }
19040 
19041 /** returns whether the LP is in diving mode */
19043  SCIP_LP* lp /**< current LP data */
19044  )
19045 {
19046  assert(lp != NULL);
19047 
19048  return lp->diving;
19049 }
19050 
19051 /** returns whether the LP is in diving mode and the objective value of at least one column was changed */
19053  SCIP_LP* lp /**< current LP data */
19054  )
19055 {
19056  assert(lp != NULL);
19057 
19058  return lp->divingobjchg;
19059 }
19060 
19061 /** marks the diving LP to have a changed objective function */
19063  SCIP_LP* lp /**< current LP data */
19064  )
19065 {
19066  assert(lp != NULL);
19067  assert(lp->diving);
19068 
19069  lp->divingobjchg = TRUE;
19070 }
19071 
19072 /** compute relative interior point
19073  *
19074  * We use the approach of@par
19075  * R. Freund, R. Roundy, M. J. Todd@par
19076  * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
19077  * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
19078  *
19079  * to compute a relative interior point for the current LP.
19080  *
19081  * Assume the original LP looks as follows:
19082  * \f[
19083  * \begin{array}{rrl}
19084  * \min & c^T x &\\
19085  * & A x & \geq a\\
19086  * & B x & \leq b\\
19087  * & D x & = d.
19088  * \end{array}
19089  * \f]
19090  * Note that bounds should be included in the system.
19091  *
19092  * To find an interior point the following LP does the job:
19093  * \f[
19094  * \begin{array}{rrl}
19095  * \max & 1^T y &\\
19096  * & A x - y - \alpha a & \geq 0\\
19097  * & B x + y - \alpha b & \leq 0\\
19098  * & D x - \alpha d & = 0\\
19099  * & 0 \leq y & \leq 1\\
19100  * & \alpha & \geq 1.
19101  * \end{array}
19102  * \f]
19103  * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
19104  * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
19105  * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
19106  */
19108  SCIP_SET* set, /**< global SCIP settings */
19109  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
19110  SCIP_LP* lp, /**< LP data */
19111  SCIP_PROB* prob, /**< problem data */
19112  SCIP_Bool relaxrows, /**< should the rows be relaxed */
19113  SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
19114  SCIP_Real timelimit, /**< time limit for LP solver */
19115  int iterlimit, /**< iteration limit for LP solver */
19116  SCIP_Real* point, /**< array to store relative interior point on exit */
19117  SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
19118  )
19119 {
19120  SCIP_LPI* lpi;
19121  SCIP_Real* obj;
19122  SCIP_Real* lb;
19123  SCIP_Real* ub;
19124  SCIP_Real* primal;
19125  SCIP_Real* colvals;
19126  SCIP_Real zero;
19127  SCIP_Real minusinf;
19128  SCIP_Real plusinf;
19129  SCIP_Real objval;
19130  SCIP_Real alpha;
19131  SCIP_RETCODE retcode;
19132  int* colinds;
19133  int nnewcols;
19134 #ifndef NDEBUG
19135  int nslacks;
19136 #endif
19137  int beg;
19138  int cnt;
19139  int i;
19140  int j;
19141 
19142  assert(set != NULL);
19143  assert(lp != NULL);
19144  assert(point != NULL);
19145  assert(success != NULL);
19146 
19147  *success = FALSE;
19148 
19149  /* check time and iteration limits */
19150  if ( timelimit <= 0.0 || iterlimit <= 0 )
19151  return SCIP_OKAY;
19152 
19153  /* exit if there are no columns */
19154  assert(lp->nrows >= 0);
19155  assert(lp->ncols >= 0);
19156  if( lp->ncols == 0 )
19157  return SCIP_OKAY;
19158 
19159  /* disable objective cutoff if we have none */
19160  if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
19161  inclobjcutoff = FALSE;
19162 
19163  SCIPdebugMessage("Computing relative interior point to current LP.\n");
19164 
19165  /* if there are no rows, we return the zero point */
19166  if( lp->nrows == 0 && !inclobjcutoff )
19167  {
19168  /* create zero point */
19169  BMSclearMemoryArray(point, lp->ncols);
19170  *success = TRUE;
19171 
19172  return SCIP_OKAY;
19173  }
19174 
19175  /* create auxiliary LP */
19176  SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
19177 
19179  if( retcode != SCIP_OKAY && retcode != SCIP_PARAMETERUNKNOWN )
19180  {
19181  SCIP_CALL( retcode );
19182  }
19183 
19185  if( retcode != SCIP_OKAY && retcode != SCIP_PARAMETERUNKNOWN )
19186  {
19187  SCIP_CALL( retcode );
19188  }
19189 
19190  /* get storage */
19191  nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
19192  SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
19193  SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
19194  SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
19195 
19196  /* create original columns (bounds are relaxed below, unless the variable is fixed) */
19197  for( j = 0; j < lp->ncols; ++j )
19198  {
19199  /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
19200  obj[j] = 0.0;
19201  lb[j] = -SCIPlpiInfinity(lpi);
19202  ub[j] = SCIPlpiInfinity(lpi);
19203 #if 0
19204  /* note: we could also use the original bounds - free variables seem to be faster. */
19205  lb[j] = lp->cols[j]->lb;
19206  ub[j] = lp->cols[j]->ub;
19207 #endif
19208  }
19209 
19210  /* add artificial alpha variable */
19211  nnewcols = lp->ncols;
19212  obj[nnewcols] = 0.0;
19213  lb[nnewcols] = 1.0;
19214  ub[nnewcols] = SCIPlpiInfinity(lpi);
19215  ++nnewcols;
19216 
19217  /* create slacks for rows */
19218  for( i = 0; i < lp->nrows; ++i )
19219  {
19220  SCIP_ROW* row;
19221 
19222  row = lp->rows[i];
19223  assert( row != NULL );
19224 
19225  if( SCIProwIsModifiable(row) )
19226  continue;
19227 
19228  /* make sure row is sorted */
19229  rowSortLP(row);
19230  assert( row->lpcolssorted );
19231 
19232  /* check whether we have an equation */
19233  if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
19234  {
19235  assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
19236  assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
19237  }
19238  else if( relaxrows )
19239  {
19240  /* otherwise add slacks for each side if necessary */
19241  if( !SCIPsetIsInfinity(set, REALABS(row->lhs)) )
19242  {
19243  obj[nnewcols] = 1.0;
19244  lb[nnewcols] = 0.0;
19245  ub[nnewcols] = 1.0;
19246  ++nnewcols;
19247  }
19248  if( !SCIPsetIsInfinity(set, REALABS(row->rhs)) )
19249  {
19250  obj[nnewcols] = 1.0;
19251  lb[nnewcols] = 0.0;
19252  ub[nnewcols] = 1.0;
19253  ++nnewcols;
19254  }
19255  }
19256  }
19257 
19258  /* create slacks for objective cutoff row */
19259  if( inclobjcutoff && relaxrows )
19260  {
19261  /* add slacks for right hand side */
19262  obj[nnewcols] = 1.0;
19263  lb[nnewcols] = 0.0;
19264  ub[nnewcols] = 1.0;
19265  ++nnewcols;
19266  }
19267 
19268  /* create slacks for bounds */
19269  for( j = 0; j < lp->ncols; ++j )
19270  {
19271  SCIP_COL* col;
19272 
19273  col = lp->cols[j];
19274  assert( col != NULL );
19275 
19276  /* no slacks for fixed variables */
19277  if( SCIPsetIsEQ(set, col->lb, col->ub) )
19278  continue;
19279 
19280  /* add slacks for each bound if necessary */
19281  if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
19282  {
19283  obj[nnewcols] = 1.0;
19284  lb[nnewcols] = 0.0;
19285  ub[nnewcols] = 1.0;
19286  ++nnewcols;
19287  }
19288  if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
19289  {
19290  obj[nnewcols] = 1.0;
19291  lb[nnewcols] = 0.0;
19292  ub[nnewcols] = 1.0;
19293  ++nnewcols;
19294  }
19295  }
19296 #ifndef NDEBUG
19297  nslacks = nnewcols - lp->ncols - 1;
19298  assert( nslacks >= 0 );
19299  assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
19300 #endif
19301 
19302  /* add columns */
19303  SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
19304 
19305  /* free storage */
19306  SCIPsetFreeBufferArray(set, &obj);
19307  SCIPsetFreeBufferArray(set, &ub);
19308  SCIPsetFreeBufferArray(set, &lb);
19309 
19310  /* prepare storage for rows */
19311  SCIP_CALL( SCIPsetAllocBufferArray(set, &colinds, lp->ncols+2) );
19312  SCIP_CALL( SCIPsetAllocBufferArray(set, &colvals, lp->ncols+2) );
19313 
19314  /* create rows arising from original rows */
19315  cnt = 0;
19316  beg = 0;
19317  zero = 0.0;
19318  minusinf = -SCIPlpiInfinity(lpi);
19319  plusinf = SCIPlpiInfinity(lpi);
19320  for( i = 0; i < lp->nrows; ++i )
19321  {
19322  SCIP_ROW* row;
19323  SCIP_COL** rowcols;
19324  SCIP_Real* rowvals;
19325  SCIP_Real lhs;
19326  SCIP_Real rhs;
19327  int nnonz;
19328 
19329  row = lp->rows[i];
19330  assert( row != NULL );
19331 
19332  if( SCIProwIsModifiable(row) )
19333  continue;
19334  assert( row->lpcolssorted );
19335 
19336  /* get row data */
19337  lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
19338  rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
19339  nnonz = row->nlpcols;
19340  assert( nnonz <= lp->ncols );
19341  rowcols = row->cols;
19342  rowvals = row->vals;
19343 
19344  /* set up indices */
19345  for( j = 0; j < nnonz; ++j )
19346  {
19347  assert( rowcols[j] != NULL );
19348  assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
19349  assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
19350  colinds[j] = rowcols[j]->lppos;
19351  colvals[j] = rowvals[j];
19352  }
19353 
19354  /* if we have an equation */
19355  if( SCIPsetIsEQ(set, lhs, rhs) )
19356  {
19357  /* add artificial variable */
19358  colinds[nnonz] = lp->ncols;
19359  colvals[nnonz] = -rhs;
19360 
19361  /* add row */
19362  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &zero, NULL, nnonz+1, &beg, colinds, colvals) );
19363  }
19364  else
19365  {
19366  SCIP_Real abslhs = REALABS(lhs);
19367  SCIP_Real absrhs = REALABS(rhs);
19368 
19369  /* treat lhs */
19370  if( !SCIPsetIsInfinity(set, abslhs) )
19371  {
19372  assert(!SCIPsetIsEQ(set, lhs, rhs));
19373 
19374  /* add artificial variable */
19375  colinds[nnonz] = lp->ncols;
19376  colvals[nnonz] = -lhs;
19377 
19378  if( relaxrows )
19379  {
19380  /* add slack variable */
19381  colinds[nnonz+1] = lp->ncols + 1 + cnt;
19382  colvals[nnonz+1] = -MAX(1.0, lhs);
19383  ++cnt;
19384  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, nnonz+2, &beg, colinds, colvals) );
19385  }
19386  else
19387  {
19388  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, nnonz+1, &beg, colinds, colvals) );
19389  }
19390  }
19391 
19392  /* treat rhs */
19393  if( !SCIPsetIsInfinity(set, absrhs) )
19394  {
19395  assert(!SCIPsetIsEQ(set, lhs, rhs));
19396 
19397  /* add artificial variable */
19398  colinds[nnonz] = lp->ncols;
19399  colvals[nnonz] = -rhs;
19400 
19401  if( relaxrows )
19402  {
19403  /* add slack variable */
19404  colinds[nnonz+1] = lp->ncols + 1 + cnt;
19405  colvals[nnonz+1] = MAX(1.0, absrhs);
19406  ++cnt;
19407  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz+2, &beg, colinds, colvals) );
19408  }
19409  else
19410  {
19411  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz+1, &beg, colinds, colvals) );
19412  }
19413  }
19414  }
19415  }
19416 
19417  /* create row arising from objective cutoff */
19418  if( inclobjcutoff )
19419  {
19420  SCIP_Real rhs;
19421  int nnonz;
19422 
19423  /* get row data */
19424  assert(lp->looseobjvalinf == 0);
19425  rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
19426 
19427  /* set up indices and coefficients */
19428  nnonz = 0;
19429  for( j = 0; j < lp->ncols; ++j )
19430  {
19431  assert( lp->cols[j] != NULL );
19432  assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
19433  assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
19434  if( lp->cols[j]->obj == 0.0 )
19435  continue;
19436  colinds[nnonz] = lp->cols[j]->lppos;
19437  colvals[nnonz] = lp->cols[j]->obj;
19438  ++nnonz;
19439  }
19440 
19441  /* treat rhs */
19442  /* add artificial variable */
19443  colinds[nnonz] = lp->ncols;
19444  colvals[nnonz] = -rhs;
19445  ++nnonz;
19446 
19447  if( relaxrows )
19448  {
19449  SCIP_Real absrhs = REALABS(rhs);
19450 
19451  /* add slack variable */
19452  colinds[nnonz] = lp->ncols + 1 + cnt;
19453  colvals[nnonz] = MAX(1.0, absrhs);
19454  ++cnt;
19455  ++nnonz;
19456  }
19457  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, nnonz, &beg, colinds, colvals) );
19458  }
19459 
19460  /* create rows arising from bounds */
19461  for( j = 0; j < lp->ncols; ++j )
19462  {
19463  SCIP_COL* col;
19464  SCIP_Real abscollb;
19465  SCIP_Real abscolub;
19466 
19467  col = lp->cols[j];
19468  assert( col != NULL );
19469  assert( col->lppos == j );
19470 
19471  /* set up index of column */
19472  colinds[0] = j;
19473  colvals[0] = 1.0;
19474 
19475  /* fixed variable */
19476  if( SCIPsetIsEQ(set, col->lb, col->ub) )
19477  {
19478  /* add artificial variable */
19479  colinds[1] = lp->ncols;
19480  colvals[1] = -col->lb;
19481 
19482  /* add row */
19483  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &zero, NULL, 2, &beg, colinds, colvals) );
19484 
19485  continue;
19486  }
19487 
19488  abscollb = REALABS(col->lb);
19489  abscolub = REALABS(col->ub);
19490 
19491  /* lower bound */
19492  if( !SCIPsetIsInfinity(set, abscollb) )
19493  {
19494  /* add artificial variable */
19495  colinds[1] = lp->ncols;
19496  colvals[1] = -col->lb;
19497 
19498  /* add slack variable */
19499  colinds[2] = lp->ncols + 1 + cnt;
19500  colvals[2] = -MAX(1.0, abscollb);
19501  ++cnt;
19502  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &zero, &plusinf, NULL, 3, &beg, colinds, colvals) );
19503  }
19504 
19505  /* upper bound */
19506  if( !SCIPsetIsInfinity(set, abscolub) )
19507  {
19508  /* add artificial variable */
19509  colinds[1] = lp->ncols;
19510  colvals[1] = -col->ub;
19511 
19512  /* add slack variable */
19513  colinds[2] = lp->ncols + 1 + cnt;
19514  colvals[2] = MAX(1.0, abscolub);
19515  ++cnt;
19516  SCIP_CALL( SCIPlpiAddRows(lpi, 1, &minusinf, &zero, NULL, 3, &beg, colinds, colvals) );
19517  }
19518  }
19519  assert( cnt == nslacks );
19520 
19521  SCIPsetFreeBufferArray(set, &colvals);
19522  SCIPsetFreeBufferArray(set, &colinds);
19523 
19524 #ifdef SCIP_OUTPUT
19525  SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
19526 #endif
19527 
19528 #ifndef NDEBUG
19529  {
19530  int ncols;
19531  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
19532  assert( ncols == nnewcols );
19533  }
19534 #endif
19535 
19536  /* set time limit */
19537  retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
19538 
19539  /* check, if parameter is unknown */
19540  if ( retcode == SCIP_PARAMETERUNKNOWN )
19541  SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
19542 
19543  /* set iteration limit */
19544  retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
19545 
19546  /* check, if parameter is unknown */
19547  if ( retcode == SCIP_PARAMETERUNKNOWN )
19548  SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
19549 
19550  /* solve and store point */
19551  /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
19552  retcode = SCIPlpiSolveDual(lpi); /* dual is usually faster */
19553 
19554  /* detect possible error in LP solver */
19555  if ( retcode != SCIP_OKAY )
19556  {
19557  SCIP_CALL( SCIPlpiFree(&lpi) );
19558  return SCIP_OKAY;
19559  }
19560 
19561 #ifndef NDEBUG
19562  if ( SCIPlpiIsIterlimExc(lpi) )
19563  SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
19564  if ( SCIPlpiIsTimelimExc(lpi) )
19565  SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
19566 #endif
19567 
19568  if( SCIPlpiIsOptimal(lpi) )
19569  {
19570  /* get primal solution */
19571  SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
19572  SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
19573  alpha = primal[lp->ncols];
19574  assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
19575 
19576  SCIPdebugMessage("Solved relative interior lp with objective %g.\n", objval);
19577 
19578  /* construct relative interior point */
19579  for( j = 0; j < lp->ncols; ++j )
19580  point[j] = primal[j]/alpha;
19581 
19582 #ifdef SCIP_DEBUG
19583  /* check whether the point is a relative interior point */
19584  cnt = 0;
19585  if( relaxrows )
19586  {
19587  for( i = 0; i < lp->nrows; ++i )
19588  {
19589  SCIP_ROW* row;
19590  SCIP_COL** rowcols;
19591  SCIP_Real* rowvals;
19592  SCIP_Real lhs;
19593  SCIP_Real rhs;
19594  SCIP_Real sum;
19595  int nnonz;
19596 
19597  row = lp->rows[i];
19598  assert( row != NULL );
19599 
19600  /* get row data */
19601  lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
19602  rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
19603  nnonz = row->nlpcols;
19604  assert( nnonz <= lp->ncols );
19605  rowcols = row->cols;
19606  rowvals = row->vals;
19607 
19608  sum = 0.0;
19609  for( j = 0; j < nnonz; ++j )
19610  sum += rowvals[j] * primal[rowcols[j]->lppos];
19611  sum /= alpha;
19612 
19613  /* if we have an equation */
19614  if( SCIPsetIsEQ(set, lhs, rhs) )
19615  {
19616  assert( SCIPsetIsFeasEQ(set, sum, lhs) );
19617  }
19618  else
19619  {
19620  /* treat lhs */
19621  if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
19622  {
19623  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
19624  ++cnt;
19625  }
19626  /* treat rhs */
19627  if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
19628  {
19629  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
19630  ++cnt;
19631  }
19632  }
19633  }
19634  if( inclobjcutoff )
19635  {
19636  SCIP_Real sum;
19637 #ifndef NDEBUG
19638  SCIP_Real rhs;
19639 
19640  rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
19641 #endif
19642  sum = 0.0;
19643  for( j = 0; j < lp->ncols; ++j )
19644  sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
19645  sum /= alpha;
19646 
19647  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
19648  ++cnt;
19649  }
19650  }
19651  /* check bounds */
19652  for( j = 0; j < lp->ncols; ++j )
19653  {
19654  SCIP_COL* col;
19655 #ifndef NDEBUG
19656  SCIP_Real val;
19657 #endif
19658 
19659  col = lp->cols[j];
19660  assert( col != NULL );
19661 #ifndef NDEBUG
19662  val = primal[col->lppos] / alpha;
19663 #endif
19664  /* if the variable is not fixed */
19665  if( !SCIPsetIsEQ(set, col->lb, col->ub) )
19666  {
19667  /* treat lb */
19668  if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
19669  {
19670  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
19671  ++cnt;
19672  }
19673  /* treat rhs */
19674  if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
19675  {
19676  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
19677  ++cnt;
19678  }
19679  }
19680  }
19681 #endif
19682 
19683  /* free */
19684  SCIPsetFreeBufferArray(set, &primal);
19685 
19686  *success = TRUE;
19687  }
19688  SCIP_CALL( SCIPlpiFree(&lpi) );
19689 
19690  return SCIP_OKAY;
19691 }
19692