1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   lp.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  LP management methods and data structures
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 * @author Marc Pfetsch
31   	 * @author Kati Wolter
32   	 * @author Gerald Gamrath
33   	 *
34   	 *  In LP management, we have to differ between the current LP and the SCIP_LP
35   	 *  stored in the LP solver. All LP methods affect the current LP only.
36   	 *  Before solving the current LP with the LP solver or setting an LP state,
37   	 *  the LP solvers data has to be updated to the current LP with a call to
38   	 *  lpFlush().
39   	 */
40   	
41   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42   	
43   	
44   	#include "lpi/lpi.h"
45   	#include "scip/clock.h"
46   	#include "scip/cons.h"
47   	#include "scip/event.h"
48   	#include "scip/intervalarith.h"
49   	#include "scip/lp.h"
50   	#include "scip/misc.h"
51   	#include "scip/prob.h"
52   	#include "scip/pub_lp.h"
53   	#include "scip/pub_message.h"
54   	#include "scip/pub_misc.h"
55   	#include "scip/pub_misc_sort.h"
56   	#include "scip/pub_var.h"
57   	#include "scip/set.h"
58   	#include "scip/sol.h"
59   	#include "scip/solve.h"
60   	#include "scip/stat.h"
61   	#include "scip/struct_event.h"
62   	#include "scip/struct_lp.h"
63   	#include "scip/struct_prob.h"
64   	#include "scip/struct_set.h"
65   	#include "scip/struct_stat.h"
66   	#include "scip/struct_var.h"
67   	#include "scip/var.h"
68   	#include <string.h>
69   	
70   	
71   	/* activate this to use the row activities as given by the LPI instead of recalculating
72   	 * using the LP solver activity is potentially faster, but may not be consistent with the SCIP_ROW calculations
73   	 * see also #2594 for more details on possible trouble
74   	 */
75   	/* #define SCIP_USE_LPSOLVER_ACTIVITY */
76   	
77   	/*
78   	 * debug messages
79   	 */
80   	
81   	#ifdef SCIP_DEBUG
82   	/** method is to print in row in case SCIP_DEBUG is defined */
83   	static
84   	void debugRowPrint(
85   	   SCIP_SET*             set,                /**< global SCIP settings */
86   	   SCIP_ROW*             row                 /**< LP row */
87   	   )
88   	{
89   	   int i;
90   	
91   	   assert(row != NULL);
92   	
93   	   /* print row name */
94   	   if( row->name != NULL && row->name[0] != '\0' )
95   	   {
96   	      SCIPsetDebugMsgPrint(set, "%s: ", row->name);
97   	   }
98   	
99   	   /* print left hand side */
100  	   SCIPsetDebugMsgPrint(set, "%.15g <= ", row->lhs);
101  	
102  	   /* print coefficients */
103  	   if( row->len == 0 )
104  	   {
105  	      SCIPsetDebugMsgPrint(set, "0 ");
106  	   }
107  	   for( i = 0; i < row->len; ++i )
108  	   {
109  	      assert(row->cols[i] != NULL);
110  	      assert(row->cols[i]->var != NULL);
111  	      assert(SCIPvarGetName(row->cols[i]->var) != NULL);
112  	      assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
113  	      SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
114  	   }
115  	
116  	   /* print constant */
117  	   if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
118  	   {
119  	      SCIPsetDebugMsgPrint(set, "%+.15g ", row->constant);
120  	   }
121  	
122  	   /* print right hand side */
123  	   SCIPsetDebugMsgPrint(set, "<= %.15g\n", row->rhs);
124  	}
125  	#else
126  	#define debugRowPrint(x,y) /**/
127  	#endif
128  	
129  	#ifdef SCIP_DEBUG
130  	/** method to output column if SCIP_DEBUG is define */
131  	static
132  	void debugColPrint(
133  	   SCIP_SET*             set,                /**< global SCIP settings */
134  	   SCIP_COL*             col                 /**< LP column */
135  	   )
136  	{
137  	   int r;
138  	
139  	   assert(col != NULL);
140  	   assert(col->var != NULL);
141  	
142  	   /* print bounds */
143  	   SCIPsetDebugMsgPrint(set, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
144  	
145  	   /* print coefficients */
146  	   if( col->len == 0 )
147  	   {
148  	      SCIPsetDebugMsgPrint(set, "<empty>");
149  	   }
150  	   for( r = 0; r < col->len; ++r )
151  	   {
152  	      assert(col->rows[r] != NULL);
153  	      assert(col->rows[r]->name != NULL);
154  	      SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
155  	   }
156  	   SCIPsetDebugMsgPrint(set, "\n");
157  	}
158  	#else
159  	#define debugColPrint(x,y) /**/
160  	#endif
161  	
162  	/*
163  	 * memory growing methods for dynamically allocated arrays
164  	 */
165  	
166  	/** ensures, that chgcols array can store at least num entries */
167  	static
168  	SCIP_RETCODE ensureChgcolsSize(
169  	   SCIP_LP*              lp,                 /**< current LP data */
170  	   SCIP_SET*             set,                /**< global SCIP settings */
171  	   int                   num                 /**< minimum number of entries to store */
172  	   )
173  	{
174  	   assert(lp->nchgcols <= lp->chgcolssize);
175  	
176  	   if( num > lp->chgcolssize )
177  	   {
178  	      int newsize;
179  	
180  	      newsize = SCIPsetCalcMemGrowSize(set, num);
181  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
182  	      lp->chgcolssize = newsize;
183  	   }
184  	   assert(num <= lp->chgcolssize);
185  	
186  	   return SCIP_OKAY;
187  	}
188  	
189  	/** ensures, that chgrows array can store at least num entries */
190  	static
191  	SCIP_RETCODE ensureChgrowsSize(
192  	   SCIP_LP*              lp,                 /**< current LP data */
193  	   SCIP_SET*             set,                /**< global SCIP settings */
194  	   int                   num                 /**< minimum number of entries to store */
195  	   )
196  	{
197  	   assert(lp->nchgrows <= lp->chgrowssize);
198  	
199  	   if( num > lp->chgrowssize )
200  	   {
201  	      int newsize;
202  	
203  	      newsize = SCIPsetCalcMemGrowSize(set, num);
204  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
205  	      lp->chgrowssize = newsize;
206  	   }
207  	   assert(num <= lp->chgrowssize);
208  	
209  	   return SCIP_OKAY;
210  	}
211  	
212  	/** ensures, that lpicols array can store at least num entries */
213  	static
214  	SCIP_RETCODE ensureLpicolsSize(
215  	   SCIP_LP*              lp,                 /**< current LP data */
216  	   SCIP_SET*             set,                /**< global SCIP settings */
217  	   int                   num                 /**< minimum number of entries to store */
218  	   )
219  	{
220  	   assert(lp->nlpicols <= lp->lpicolssize);
221  	
222  	   if( num > lp->lpicolssize )
223  	   {
224  	      int newsize;
225  	
226  	      newsize = SCIPsetCalcMemGrowSize(set, num);
227  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
228  	      lp->lpicolssize = newsize;
229  	   }
230  	   assert(num <= lp->lpicolssize);
231  	
232  	   return SCIP_OKAY;
233  	}
234  	
235  	/** ensures, that lpirows array can store at least num entries */
236  	static
237  	SCIP_RETCODE ensureLpirowsSize(
238  	   SCIP_LP*              lp,                 /**< current LP data */
239  	   SCIP_SET*             set,                /**< global SCIP settings */
240  	   int                   num                 /**< minimum number of entries to store */
241  	   )
242  	{
243  	   assert(lp->nlpirows <= lp->lpirowssize);
244  	
245  	   if( num > lp->lpirowssize )
246  	   {
247  	      int newsize;
248  	
249  	      newsize = SCIPsetCalcMemGrowSize(set, num);
250  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
251  	      lp->lpirowssize = newsize;
252  	   }
253  	   assert(num <= lp->lpirowssize);
254  	
255  	   return SCIP_OKAY;
256  	}
257  	
258  	/** ensures, that cols array can store at least num entries */
259  	static
260  	SCIP_RETCODE ensureColsSize(
261  	   SCIP_LP*              lp,                 /**< current LP data */
262  	   SCIP_SET*             set,                /**< global SCIP settings */
263  	   int                   num                 /**< minimum number of entries to store */
264  	   )
265  	{
266  	   assert(lp->ncols <= lp->colssize);
267  	
268  	   if( num > lp->colssize )
269  	   {
270  	      int newsize;
271  	
272  	      newsize = SCIPsetCalcMemGrowSize(set, num);
273  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
274  	      lp->colssize = newsize;
275  	   }
276  	   assert(num <= lp->colssize);
277  	
278  	   return SCIP_OKAY;
279  	}
280  	
281  	/** ensures, that soldirection array can store at least num entries */
282  	static
283  	SCIP_RETCODE ensureSoldirectionSize(
284  	   SCIP_LP*              lp,                 /**< current LP data */
285  	   int                   num                 /**< minimum number of entries to store */
286  	   )
287  	{
288  	   if( num > lp->soldirectionsize )
289  	   {
290  	      BMSfreeMemoryArrayNull(&lp->soldirection);
291  	      SCIP_ALLOC( BMSallocMemoryArray(&lp->soldirection, num) );
292  	
293  	      lp->soldirectionsize = num;
294  	   }
295  	
296  	   assert(num <= lp->soldirectionsize);
297  	
298  	   return SCIP_OKAY;
299  	}
300  	
301  	/** ensures, that lazy cols array can store at least num entries */
302  	static
303  	SCIP_RETCODE ensureLazycolsSize(
304  	   SCIP_LP*              lp,                 /**< current LP data */
305  	   SCIP_SET*             set,                /**< global SCIP settings */
306  	   int                   num                 /**< minimum number of entries to store */
307  	   )
308  	{
309  	   assert(lp->nlazycols <= lp->lazycolssize);
310  	
311  	   if( num > lp->lazycolssize )
312  	   {
313  	      int newsize;
314  	
315  	      newsize = SCIPsetCalcMemGrowSize(set, num);
316  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
317  	      lp->lazycolssize = newsize;
318  	   }
319  	   assert(num <= lp->lazycolssize);
320  	
321  	   return SCIP_OKAY;
322  	}
323  	
324  	/** ensures, that rows array can store at least num entries */
325  	static
326  	SCIP_RETCODE ensureRowsSize(
327  	   SCIP_LP*              lp,                 /**< current LP data */
328  	   SCIP_SET*             set,                /**< global SCIP settings */
329  	   int                   num                 /**< minimum number of entries to store */
330  	   )
331  	{
332  	   assert(lp->nrows <= lp->rowssize);
333  	
334  	   if( num > lp->rowssize )
335  	   {
336  	      int newsize;
337  	
338  	      newsize = SCIPsetCalcMemGrowSize(set, num);
339  	      SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
340  	      lp->rowssize = newsize;
341  	   }
342  	   assert(num <= lp->rowssize);
343  	
344  	   return SCIP_OKAY;
345  	}
346  	
347  	/** ensures, that row array of column can store at least num entries */
348  	static
349  	SCIP_RETCODE colEnsureSize(
350  	   SCIP_COL*             col,                /**< LP column */
351  	   BMS_BLKMEM*           blkmem,             /**< block memory */
352  	   SCIP_SET*             set,                /**< global SCIP settings */
353  	   int                   num                 /**< minimum number of entries to store */
354  	   )
355  	{
356  	   assert(col != NULL);
357  	   assert(col->len <= col->size);
358  	
359  	   if( num > col->size )
360  	   {
361  	      int newsize;
362  	
363  	      newsize = SCIPsetCalcMemGrowSize(set, num);
364  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
365  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
366  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
367  	      col->size = newsize;
368  	   }
369  	   assert(num <= col->size);
370  	
371  	   return SCIP_OKAY;
372  	}
373  	
374  	/** save current LP values dependent on the solution */
375  	static
376  	SCIP_RETCODE lpStoreSolVals(
377  	   SCIP_LP*              lp,                 /**< LP data */
378  	   SCIP_STAT*            stat,               /**< problem statistics */
379  	   BMS_BLKMEM*           blkmem              /**< block memory */
380  	   )
381  	{
382  	   SCIP_LPSOLVALS* storedsolvals;
383  	
384  	   assert(lp != NULL);
385  	   assert(stat != NULL);
386  	   assert(blkmem != NULL);
387  	
388  	   /* allocate memory for storage */
389  	   if( lp->storedsolvals == NULL )
390  	   {
391  	      SCIP_ALLOC( BMSallocMemory(&lp->storedsolvals) );
392  	   }
393  	   storedsolvals = lp->storedsolvals;
394  	
395  	   /* store values */
396  	   storedsolvals->lpsolstat = lp->lpsolstat;
397  	   storedsolvals->lpobjval = lp->lpobjval;
398  	   storedsolvals->primalfeasible = lp->primalfeasible;
399  	   storedsolvals->primalchecked = lp->primalchecked;
400  	   storedsolvals->dualfeasible = lp->dualfeasible;
401  	   storedsolvals->dualchecked = lp->dualchecked;
402  	   storedsolvals->solisbasic = lp->solisbasic;
403  	   storedsolvals->lpissolved = lp->solved;
404  	
405  	   return SCIP_OKAY;
406  	}
407  	
408  	/** restore LP solution values in column */
409  	static
410  	SCIP_RETCODE lpRestoreSolVals(
411  	   SCIP_LP*              lp,                 /**< LP data */
412  	   BMS_BLKMEM*           blkmem,             /**< block memory */
413  	   SCIP_Longint          validlp             /**< number of lp for which restored values are valid */
414  	   )
415  	{
416  	   SCIP_LPSOLVALS* storedsolvals;
417  	
418  	   assert(lp != NULL);
419  	   assert(blkmem != NULL);
420  	
421  	   /* if stored values are available, restore them */
422  	   storedsolvals = lp->storedsolvals;
423  	   if( storedsolvals != NULL )
424  	   {
425  	      lp->solved = storedsolvals->lpissolved;
426  	      lp->validsollp = validlp;
427  	
428  	      lp->lpsolstat = storedsolvals->lpsolstat;
429  	      lp->lpobjval = storedsolvals->lpobjval;
430  	      lp->primalfeasible = storedsolvals->primalfeasible;
431  	      lp->primalchecked = storedsolvals->primalchecked;
432  	      lp->dualfeasible = storedsolvals->dualfeasible;
433  	      lp->dualchecked = storedsolvals->dualchecked;
434  	      lp->solisbasic = storedsolvals->solisbasic;
435  	
436  	      /* solution values are stored only for LPs solved to optimality or unboundedness */
437  	      assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
438  	         lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY ||
439  	         lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
440  	         lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT ||
441  	         lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT ||
442  	         lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE ||
443  	         lp->validsollp == -1);
444  	   }
445  	   /* no values available, mark LP as unsolved */
446  	   else
447  	   {
448  	      lp->solved = FALSE;
449  	      lp->validsollp = -1;
450  	
451  	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
452  	      lp->lpobjval = SCIP_INVALID;
453  	      lp->primalfeasible = FALSE;
454  	      lp->primalchecked = FALSE;
455  	      lp->dualfeasible = FALSE;
456  	      lp->dualchecked = FALSE;
457  	      lp->solisbasic = FALSE;
458  	      lp->validfarkaslp = -1;
459  	   }
460  	
461  	   lp->validdegeneracylp = -1;
462  	
463  	   /* intentionally keep storage space allocated */
464  	
465  	   return SCIP_OKAY;
466  	}
467  	
468  	/** save current LP solution values stored in each column */
469  	static
470  	SCIP_RETCODE colStoreSolVals(
471  	   SCIP_COL*             col,                /**< LP column */
472  	   BMS_BLKMEM*           blkmem              /**< block memory */
473  	   )
474  	{
475  	   SCIP_COLSOLVALS* storedsolvals;
476  	
477  	   assert(col != NULL);
478  	   assert(blkmem != NULL);
479  	
480  	   /* allocate memory for storage */
481  	   if( col->storedsolvals == NULL )
482  	   {
483  	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &col->storedsolvals) );
484  	   }
485  	   storedsolvals = col->storedsolvals;
486  	
487  	   /* store values */
488  	   storedsolvals->primsol = col->primsol;
489  	   storedsolvals->redcost = col->redcost;
490  	   storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
491  	
492  	   return SCIP_OKAY;
493  	}
494  	
495  	/** restore LP solution values in column */
496  	static
497  	SCIP_RETCODE colRestoreSolVals(
498  	   SCIP_COL*             col,                /**< LP column */
499  	   BMS_BLKMEM*           blkmem,             /**< block memory */
500  	   SCIP_Longint          validlp,            /**< number of lp for which restored values are valid */
501  	   SCIP_Bool             freebuffer          /**< should buffer for LP solution values be freed? */
502  	   )
503  	{
504  	   SCIP_COLSOLVALS* storedsolvals;
505  	
506  	   assert(col != NULL);
507  	   assert(blkmem != NULL);
508  	
509  	   /* if stored values are available, restore them */
510  	   storedsolvals = col->storedsolvals;
511  	   if( storedsolvals != NULL )
512  	   {
513  	      col->primsol = storedsolvals->primsol;
514  	      col->redcost = storedsolvals->redcost;
515  	      col->validredcostlp = validlp;
516  	      col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
517  	
518  	      /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
519  	      col->validfarkaslp = -1;
520  	   }
521  	   /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
522  	    * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
523  	    */
524  	   else
525  	   {
526  	      col->primsol = 0.0;
527  	      col->validredcostlp = -1;
528  	      col->validfarkaslp = -1;
529  	      col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
530  	   }
531  	
532  	   /* free memory */
533  	   if( freebuffer )
534  	   {
535  	      BMSfreeBlockMemoryNull(blkmem, &col->storedsolvals);
536  	      assert(col->storedsolvals == NULL);
537  	   }
538  	
539  	   return SCIP_OKAY;
540  	}
541  	
542  	/** save current LP solution values stored in each column */
543  	static
544  	SCIP_RETCODE rowStoreSolVals(
545  	   SCIP_ROW*             row,                /**< LP row */
546  	   BMS_BLKMEM*           blkmem,             /**< block memory */
547  	   SCIP_Bool             infeasible          /**< is the solution infeasible? */
548  	   )
549  	{
550  	   SCIP_ROWSOLVALS* storedsolvals;
551  	
552  	   assert(row != NULL);
553  	   assert(blkmem != NULL);
554  	
555  	   /* allocate memory for storage */
556  	   if( row->storedsolvals == NULL )
557  	   {
558  	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &row->storedsolvals) );
559  	   }
560  	   storedsolvals = row->storedsolvals;
561  	
562  	   /* store values */
563  	   if ( infeasible )
564  	   {
565  	      storedsolvals->dualsol = row->dualfarkas;
566  	      storedsolvals->activity = SCIP_INVALID;
567  	      storedsolvals->basisstatus = SCIP_BASESTAT_BASIC;  /*lint !e641*/
568  	   }
569  	   else
570  	   {
571  	      storedsolvals->dualsol = row->dualsol;
572  	      storedsolvals->activity = row->activity;
573  	      storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
574  	   }
575  	
576  	   return SCIP_OKAY;
577  	}
578  	
579  	/** restore LP solution values in row */
580  	static
581  	SCIP_RETCODE rowRestoreSolVals(
582  	   SCIP_ROW*             row,                /**< LP column */
583  	   BMS_BLKMEM*           blkmem,             /**< block memory */
584  	   SCIP_Longint          validlp,            /**< number of lp for which restored values are valid */
585  	   SCIP_Bool             freebuffer,         /**< should buffer for LP solution values be freed? */
586  	   SCIP_Bool             infeasible          /**< is the solution infeasible? */
587  	   )
588  	{
589  	   SCIP_ROWSOLVALS* storedsolvals;
590  	
591  	   assert(row != NULL);
592  	   assert(blkmem != NULL);
593  	
594  	   /* if stored values are available, restore them */
595  	   storedsolvals = row->storedsolvals;
596  	   if( storedsolvals != NULL )
597  	   {
598  	      if ( infeasible )
599  	         row->dualfarkas = storedsolvals->dualsol;
600  	      else
601  	         row->dualsol = storedsolvals->dualsol;
602  	      row->activity = storedsolvals->activity;
603  	      row->validactivitylp = validlp;
604  	      row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
605  	   }
606  	   /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
607  	    * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
608  	    */
609  	   else
610  	   {
611  	      row->dualsol = 0.0;
612  	      row->dualfarkas = 0.0;
613  	      row->activity = SCIP_INVALID;
614  	      row->validactivitylp = -1;
615  	      row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
616  	   }
617  	
618  	   /* free memory */
619  	   if( freebuffer )
620  	   {
621  	      BMSfreeBlockMemoryNull(blkmem, &row->storedsolvals);
622  	      assert(row->storedsolvals == NULL);
623  	   }
624  	
625  	   return SCIP_OKAY;
626  	}
627  	
628  	/** ensures, that column array of row can store at least num entries */
629  	SCIP_RETCODE SCIProwEnsureSize(
630  	   SCIP_ROW*             row,                /**< LP row */
631  	   BMS_BLKMEM*           blkmem,             /**< block memory */
632  	   SCIP_SET*             set,                /**< global SCIP settings */
633  	   int                   num                 /**< minimum number of entries to store */
634  	   )
635  	{
636  	   assert(row != NULL);
637  	   assert(row->len <= row->size);
638  	
639  	   if( num > row->size )
640  	   {
641  	      int newsize;
642  	
643  	      newsize = SCIPsetCalcMemGrowSize(set, num);
644  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
645  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
646  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
647  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
648  	      row->size = newsize;
649  	   }
650  	   assert(num <= row->size);
651  	
652  	   return SCIP_OKAY;
653  	}
654  	
655  	
656  	#ifdef SCIP_MORE_DEBUG /* enable this to check the sortings within rows (for debugging, very slow!) */
657  	static SCIP_Bool msgdisp_checkrow = FALSE;
658  	
659  	static
660  	void checkRow(
661  	   SCIP_ROW*             row
662  	   )
663  	{
664  	   int i;
665  	
666  	   if( !msgdisp_checkrow )
667  	   {
668  	      printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
669  	      msgdisp_checkrow = TRUE;
670  	   }
671  	
672  	   /* validate sorting of LP part of row */
673  	   if( row->lpcolssorted && row->nlpcols > 0)
674  	   {
675  	      assert(row->cols_index[0] == row->cols[0]->index);
676  	      for( i = 1; i < row->nlpcols; ++i )
677  	      {
678  	         assert(row->cols_index[i] == row->cols[i]->index);
679  	         assert(row->cols_index[i] >= row->cols_index[i-1]);
680  	      }
681  	   }
682  	
683  	   /* validate sorting of non-LP part of row */
684  	   if( row->nonlpcolssorted && row->len > row->nlpcols )
685  	   {
686  	      assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
687  	      for( i = row->nlpcols + 1; i < row->len; ++i )
688  	      {
689  	         assert(row->cols_index[i] == row->cols[i]->index);
690  	         assert(row->cols_index[i] >= row->cols_index[i-1]);
691  	      }
692  	   }
693  	}
694  	#else
695  	#define checkRow(row) /**/
696  	#endif
697  	
698  	#ifdef SCIP_MORE_DEBUG /* enable this to check norms of rows (for debugging, very slow!) */
699  	static
700  	void checkRowSqrnorm(
701  	   SCIP_ROW*             row
702  	   )
703  	{
704  	   SCIP_COL** cols;
705  	   SCIP_Real sqrnorm;
706  	   int c;
707  	
708  	   cols = row->cols;
709  	   assert(cols != NULL || row->len == 0);
710  	
711  	   sqrnorm = 0.0;
712  	
713  	   for( c = row->len - 1; c >= 0; --c )
714  	   {
715  	      if( cols[c]->lppos >= 0 )
716  	         sqrnorm += SQR(row->vals[c]);
717  	   }
718  	
719  	   assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
720  	}
721  	
722  	static
723  	void checkRowSumnorm(
724  	   SCIP_ROW*             row
725  	   )
726  	{
727  	   SCIP_COL** cols;
728  	   SCIP_Real sumnorm;
729  	   int c;
730  	
731  	   cols = row->cols;
732  	   assert(cols != NULL || row->len == 0);
733  	
734  	   sumnorm = 0.0;
735  	
736  	   for( c = row->len - 1; c >= 0; --c )
737  	   {
738  	      if( cols[c]->lppos >= 0 )
739  	         sumnorm += REALABS(row->vals[c]);
740  	   }
741  	
742  	   assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
743  	}
744  	
745  	static
746  	void checkRowObjprod(
747  	   SCIP_ROW*             row
748  	   )
749  	{
750  	   SCIP_COL** cols;
751  	   SCIP_Real objprod;
752  	   int c;
753  	
754  	   cols = row->cols;
755  	   assert(cols != NULL || row->len == 0);
756  	
757  	   objprod = 0.0;
758  	
759  	   for( c = row->len - 1; c >= 0; --c )
760  	   {
761  	      if( cols[c]->lppos >= 0 )
762  	         objprod += row->vals[c] * cols[c]->unchangedobj;
763  	   }
764  	
765  	   assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
766  	}
767  	#else
768  	#define checkRowSqrnorm(row) /**/
769  	#define checkRowSumnorm(row) /**/
770  	#define checkRowObjprod(row) /**/
771  	#endif
772  	
773  	/*
774  	 * Local methods for pseudo and loose objective values
775  	 */
776  	
777  	/* recompute the loose objective value from scratch, if it was marked to be unreliable before */
778  	static
779  	void recomputeLooseObjectiveValue(
780  	   SCIP_LP*              lp,                 /**< current LP data */
781  	   SCIP_SET*             set,                /**< global SCIP settings */
782  	   SCIP_PROB*            prob                /**< problem data */
783  	   )
784  	{
785  	   SCIP_VAR** vars;
786  	   SCIP_Real obj;
787  	   int nvars;
788  	   int v;
789  	
790  	   assert(lp != NULL);
791  	   assert(set != NULL);
792  	   assert(prob != NULL);
793  	   assert(!lp->looseobjvalid);
794  	
795  	   vars = prob->vars;
796  	   nvars = prob->nvars;
797  	   lp->looseobjval = 0.0;
798  	
799  	   /* iterate over all variables in the problem */
800  	   for( v = 0; v < nvars; ++v )
801  	   {
802  	      if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
803  	      {
804  	         obj = SCIPvarGetObj(vars[v]);
805  	
806  	         /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
807  	         if( SCIPsetIsPositive(set, obj) && !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
808  	            lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
809  	         else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
810  	            lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
811  	      }
812  	   }
813  	
814  	   /* the recomputed value is reliable */
815  	   lp->rellooseobjval = lp->looseobjval;
816  	   lp->looseobjvalid = TRUE;
817  	}
818  	
819  	/* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
820  	static
821  	void recomputePseudoObjectiveValue(
822  	   SCIP_LP*              lp,                 /**< current LP data */
823  	   SCIP_SET*             set,                /**< global SCIP settings */
824  	   SCIP_PROB*            prob                /**< problem data */
825  	   )
826  	{
827  	   SCIP_VAR** vars;
828  	   int nvars;
829  	   int v;
830  	
831  	   assert(lp != NULL);
832  	   assert(set != NULL);
833  	   assert(prob != NULL);
834  	   assert(!lp->pseudoobjvalid);
835  	
836  	   vars = prob->vars;
837  	   nvars = prob->nvars;
838  	   lp->pseudoobjval = 0.0;
839  	
840  	   /* iterate over all variables in the problem */
841  	   for( v = 0; v < nvars; ++v )
842  	   {
843  	      /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
844  	      if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
845  	         !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
846  	      {
847  	         lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
848  	      }
849  	      else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
850  	         !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
851  	      {
852  	         lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
853  	      }
854  	   }
855  	
856  	   /* the recomputed value is reliable */
857  	   lp->relpseudoobjval = lp->pseudoobjval;
858  	   lp->pseudoobjvalid = TRUE;
859  	}
860  	
861  	/* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
862  	static
863  	void recomputeGlbPseudoObjectiveValue(
864  	   SCIP_LP*              lp,                 /**< current LP data */
865  	   SCIP_SET*             set,                /**< global SCIP settings */
866  	   SCIP_PROB*            prob                /**< problem data */
867  	   )
868  	{
869  	   SCIP_VAR** vars;
870  	   int nvars;
871  	   int v;
872  	
873  	   assert(lp != NULL);
874  	   assert(set != NULL);
875  	   assert(prob != NULL);
876  	   assert(!lp->glbpseudoobjvalid);
877  	
878  	   vars = prob->vars;
879  	   nvars = prob->nvars;
880  	   lp->glbpseudoobjval = 0.0;
881  	
882  	   /* iterate over all variables in the problem */
883  	   for( v = 0; v < nvars; ++v )
884  	   {
885  	      /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
886  	      if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
887  	         !SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
888  	      {
889  	         lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
890  	      }
891  	      else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
892  	         !SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
893  	      {
894  	         lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
895  	      }
896  	   }
897  	
898  	   /* the recomputed value is reliable */
899  	   lp->relglbpseudoobjval = lp->glbpseudoobjval;
900  	   lp->glbpseudoobjvalid = TRUE;
901  	}
902  	
903  	/** gets finite part of objective value of current LP that results from LOOSE variables only */
904  	static
905  	SCIP_Real getFiniteLooseObjval(
906  	   SCIP_LP*              lp,                 /**< current LP data */
907  	   SCIP_SET*             set,                /**< global SCIP settings */
908  	   SCIP_PROB*            prob                /**< problem data */
909  	   )
910  	{
911  	   assert(lp != NULL);
912  	   assert(set != NULL);
913  	   assert(prob != NULL);
914  	   assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
915  	   assert(lp->flushed);
916  	   assert(lp->looseobjvalinf == 0);
917  	
918  	   /* recalculate the loose objective value, if needed */
919  	   if( !lp->looseobjvalid )
920  	      recomputeLooseObjectiveValue(lp, set, prob);
921  	
922  	   return lp->looseobjval;
923  	}
924  	
925  	/** gets finite part of pseudo objective value of current LP */
926  	static
927  	SCIP_Real getFinitePseudoObjval(
928  	   SCIP_LP*              lp,                 /**< current LP data */
929  	   SCIP_SET*             set,                /**< global SCIP settings */
930  	   SCIP_PROB*            prob                /**< problem data */
931  	   )
932  	{
933  	   assert(lp != NULL);
934  	   assert(set != NULL);
935  	   assert(prob != NULL);
936  	
937  	   /* recalculate the pseudo objective value, if needed */
938  	   if( !lp->pseudoobjvalid )
939  	      recomputePseudoObjectiveValue(lp, set, prob);
940  	
941  	   return lp->pseudoobjval;
942  	}
943  	
944  	/*
945  	 * Sorting and searching rows and columns
946  	 */
947  	
948  	
949  	/** comparison method for sorting rows by non-decreasing index */
950  	SCIP_DECL_SORTPTRCOMP(SCIProwComp)
951  	{
952  	   assert(elem1 != NULL);
953  	   assert(elem2 != NULL);
954  	
955  	   if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
956  	      return -1;
957  	   else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
958  	      return +1;
959  	   else
960  	   {
961  	      assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
962  	      return 0;
963  	   }
964  	}
965  	
966  	
967  	/** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
968  	static
969  	void colSortLP(
970  	   SCIP_COL*             col                 /**< column to be sorted */
971  	   )
972  	{
973  	   int i;
974  	
975  	   assert(col != NULL);
976  	
977  	   /* check, if column is already sorted in the LP part */
978  	   if( col->lprowssorted )
979  	      return;
980  	
981  	   /* sort coefficients */
982  	   SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
983  	
984  	   /* update links */
985  	   for( i = 0; i < col->nlprows; ++i )
986  	   {
987  	      if( col->linkpos[i] >= 0 )
988  	      {
989  	         assert(col->rows[i]->cols[col->linkpos[i]] == col);
990  	         assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
991  	         col->rows[i]->linkpos[col->linkpos[i]] = i;
992  	      }
993  	   }
994  	
995  	   col->lprowssorted = TRUE;
996  	}
997  	
998  	/** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
999  	 *  ones
1000 	 */
1001 	static
1002 	void colSortNonLP(
1003 	   SCIP_COL*             col                 /**< column to be sorted */
1004 	   )
1005 	{
1006 	   int i;
1007 	
1008 	   assert(col != NULL);
1009 	
1010 	   /* check, if column is already sorted in the non-LP part */
1011 	   if( col->nonlprowssorted )
1012 	      return;
1013 	
1014 	   /* sort coefficients */
1015 	   SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
1016 	
1017 	   /* update links */
1018 	   for( i = col->nlprows; i < col->len; ++i )
1019 	   {
1020 	      if( col->linkpos[i] >= 0 )
1021 	      {
1022 	         assert(col->rows[i]->cols[col->linkpos[i]] == col);
1023 	         assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
1024 	         col->rows[i]->linkpos[col->linkpos[i]] = i;
1025 	      }
1026 	   }
1027 	
1028 	   col->nonlprowssorted = TRUE;
1029 	}
1030 	
1031 	/** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
1032 	static
1033 	void rowSortLP(
1034 	   SCIP_ROW*             row                 /**< row to be sorted */
1035 	   )
1036 	{
1037 	   int i;
1038 	
1039 	   assert(row != NULL);
1040 	
1041 	   /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
1042 	   if( row->lpcolssorted || row->delaysort )
1043 	      return;
1044 	
1045 	   /* sort coefficients */
1046 	   SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
1047 	
1048 	   /* update links */
1049 	   for( i = 0; i < row->nlpcols; ++i )
1050 	   {
1051 	      if( row->linkpos[i] >= 0 )
1052 	      {
1053 	         assert(row->cols[i]->rows[row->linkpos[i]] == row);
1054 	         assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1055 	         row->cols[i]->linkpos[row->linkpos[i]] = i;
1056 	      }
1057 	   }
1058 	
1059 	   row->lpcolssorted = TRUE;
1060 	}
1061 	
1062 	/** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1063 	 *  higher ones
1064 	 */
1065 	static
1066 	void rowSortNonLP(
1067 	   SCIP_ROW*             row                 /**< row to be sorted */
1068 	   )
1069 	{
1070 	   int i;
1071 	
1072 	   assert(row != NULL);
1073 	
1074 	   checkRow(row);
1075 	
1076 	   /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1077 	   if( row->nonlpcolssorted || row->delaysort )
1078 	      return;
1079 	
1080 	   /* sort coefficients */
1081 	   SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1082 	
1083 	   /* update links */
1084 	   for( i = row->nlpcols; i < row->len; ++i )
1085 	   {
1086 	      if( row->linkpos[i] >= 0 )
1087 	      {
1088 	         assert(row->cols[i]->rows[row->linkpos[i]] == row);
1089 	         assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1090 	         row->cols[i]->linkpos[row->linkpos[i]] = i;
1091 	      }
1092 	   }
1093 	
1094 	   checkRow(row);
1095 	
1096 	   row->nonlpcolssorted = TRUE;
1097 	}
1098 	
1099 	/** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1100 	static
1101 	int colSearchCoefPart(
1102 	   SCIP_COL*             col,                /**< column to be searched in */
1103 	   const SCIP_ROW*       row,                /**< coefficient to be searched for */
1104 	   int                   minpos,             /**< first position of search range */
1105 	   int                   maxpos              /**< last position of search range */
1106 	   )
1107 	{
1108 	   int pos;
1109 	   int idx;
1110 	   int searchidx;
1111 	
1112 	   assert(col != NULL);
1113 	   assert(row != NULL);
1114 	
1115 	   /* binary search */
1116 	   searchidx = row->index;
1117 	   while(minpos <= maxpos)
1118 	   {
1119 	      pos = (minpos + maxpos)/2;
1120 	      assert(0 <= pos && pos < col->len);
1121 	      assert(col->rows[pos] != NULL);
1122 	      assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1123 	      idx = col->rows[pos]->index;
1124 	      if( searchidx == idx )
1125 	         return pos;
1126 	      else if( searchidx < idx )
1127 	         maxpos = pos-1;
1128 	      else
1129 	         minpos = pos+1;
1130 	   }
1131 	
1132 	   return -1;
1133 	}
1134 	
1135 	/** searches coefficient in column, returns position in col vector or -1 if not found */
1136 	static
1137 	int colSearchCoef(
1138 	   SCIP_COL*             col,                /**< column to be searched in */
1139 	   const SCIP_ROW*       row                 /**< coefficient to be searched for */
1140 	   )
1141 	{
1142 	   int pos;
1143 	
1144 	   assert(col != NULL);
1145 	   assert(row != NULL);
1146 	
1147 	   pos = -1;
1148 	
1149 	   /* search in the linked LP rows */
1150 	   if( row->lppos >= 0 )
1151 	   {
1152 	      /* column has to be sorted, such that binary search works */
1153 	      colSortLP(col);
1154 	      assert(col->lprowssorted);
1155 	
1156 	      pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1157 	      if( pos >= 0 )
1158 	         return pos;
1159 	   }
1160 	
1161 	   /* search in the non-LP/unlinked rows */
1162 	   if( row->lppos == -1 || col->nunlinked > 0 )
1163 	   {
1164 	      /* column has to be sorted, such that binary search works */
1165 	      colSortNonLP(col);
1166 	      assert(col->nonlprowssorted);
1167 	
1168 	      pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1169 	   }
1170 	
1171 	   return pos;
1172 	}
1173 	
1174 	/** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1175 	static
1176 	int rowSearchCoefPart(
1177 	   SCIP_ROW*             row,                /**< row to be searched in */
1178 	   const SCIP_COL*       col,                /**< coefficient to be searched for */
1179 	   int                   minpos,             /**< first position of search range */
1180 	   int                   maxpos              /**< last position of search range */
1181 	   )
1182 	{
1183 	   int pos;
1184 	   int idx;
1185 	   int searchidx;
1186 	
1187 	   assert(row != NULL);
1188 	   assert(col != NULL);
1189 	
1190 	   /* binary search */
1191 	   searchidx = col->index;
1192 	   while(minpos <= maxpos)
1193 	   {
1194 	      pos = (minpos + maxpos)/2;
1195 	      assert(0 <= pos && pos < row->len);
1196 	      assert(row->cols[pos] != NULL);
1197 	      assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1198 	      assert(row->cols_index[pos] == row->cols[pos]->index);
1199 	      idx = row->cols_index[pos];
1200 	      if( searchidx == idx )
1201 	         return pos;
1202 	      else if( searchidx < idx )
1203 	         maxpos = pos-1;
1204 	      else
1205 	         minpos = pos+1;
1206 	   }
1207 	
1208 	   return -1;
1209 	}
1210 	
1211 	/** searches coefficient in row, returns position in row vector or -1 if not found;
1212 	 *  if the sorting of the row is delayed, returns -1
1213 	 */
1214 	static
1215 	int rowSearchCoef(
1216 	   SCIP_ROW*             row,                /**< row to be searched in */
1217 	   const SCIP_COL*       col                 /**< coefficient to be searched for */
1218 	   )
1219 	{
1220 	   int pos;
1221 	
1222 	   assert(row != NULL);
1223 	   assert(col != NULL);
1224 	
1225 	   if( row->delaysort )
1226 	      return -1;
1227 	
1228 	   pos = -1;
1229 	
1230 	   /* search in the linked LP columns */
1231 	   if( col->lppos >= 0 )
1232 	   {
1233 	      /* row has to be sorted, such that binary search works */
1234 	      rowSortLP(row);
1235 	      assert(row->lpcolssorted);
1236 	
1237 	      pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1238 	   }
1239 	
1240 	   /* search in the non-LP/unlinked columns */
1241 	   if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1242 	   {
1243 	      /* row has to be sorted, such that binary search works */
1244 	      rowSortNonLP(row);
1245 	      assert(row->nonlpcolssorted);
1246 	
1247 	      pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1248 	   }
1249 	
1250 	#ifndef NDEBUG
1251 	   /* validate result */
1252 	   assert(-1 <= pos && pos < row->len);
1253 	   if( pos >= 0 )
1254 	      assert(row->cols[pos] == col);
1255 	   else
1256 	   {
1257 	      int i;
1258 	      for( i = 0; i < row->len; ++i )
1259 	         assert(row->cols[i] != col);
1260 	   }
1261 	#endif
1262 	
1263 	   return pos;
1264 	}
1265 	
1266 	/** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1267 	static
1268 	void colMoveCoef(
1269 	   SCIP_COL*             col,                /**< LP column */
1270 	   int                   oldpos,             /**< old position of coefficient */
1271 	   int                   newpos              /**< new position of coefficient */
1272 	   )
1273 	{
1274 	   assert(col != NULL);
1275 	   assert(0 <= oldpos && oldpos < col->len);
1276 	   assert(0 <= newpos && newpos < col->len);
1277 	   assert(col->rows[oldpos] != NULL);
1278 	
1279 	   if( oldpos == newpos )
1280 	      return;
1281 	
1282 	   col->rows[newpos] = col->rows[oldpos];
1283 	   col->vals[newpos] = col->vals[oldpos];
1284 	   col->linkpos[newpos] = col->linkpos[oldpos];
1285 	
1286 	   /* update link position in row */
1287 	   if( col->linkpos[newpos] >= 0 )
1288 	   {
1289 	      assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1290 	      assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1291 	
1292 	      col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1293 	   }
1294 	
1295 	   /* update sorted flags */
1296 	   if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1297 	      col->lprowssorted = FALSE;
1298 	   else
1299 	      col->nonlprowssorted = FALSE;
1300 	}
1301 	
1302 	/** swaps two coefficients in a column, and updates all corresponding data structures */
1303 	static
1304 	void colSwapCoefs(
1305 	   SCIP_COL*             col,                /**< LP column */
1306 	   int                   pos1,               /**< position of first coefficient */
1307 	   int                   pos2                /**< position of second coefficient */
1308 	   )
1309 	{
1310 	   SCIP_ROW* tmprow;
1311 	   SCIP_Real tmpval;
1312 	   int tmplinkpos;
1313 	
1314 	   assert(col != NULL);
1315 	   assert(0 <= pos1 && pos1 < col->len);
1316 	   assert(0 <= pos2 && pos2 < col->len);
1317 	   assert(col->rows[pos1] != NULL);
1318 	
1319 	   if( pos1 == pos2 )
1320 	      return;
1321 	
1322 	   /* swap coefficients */
1323 	   tmprow = col->rows[pos2];
1324 	   tmpval = col->vals[pos2];
1325 	   tmplinkpos = col->linkpos[pos2];
1326 	
1327 	   col->rows[pos2] = col->rows[pos1];
1328 	   col->vals[pos2] = col->vals[pos1];
1329 	   col->linkpos[pos2] = col->linkpos[pos1];
1330 	
1331 	   col->rows[pos1] = tmprow;
1332 	   col->vals[pos1] = tmpval;
1333 	   col->linkpos[pos1] = tmplinkpos;
1334 	
1335 	   /* update link position in rows */
1336 	   if( col->linkpos[pos1] >= 0 )
1337 	   {
1338 	      assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1339 	      assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1340 	
1341 	      col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1342 	   }
1343 	   if( col->linkpos[pos2] >= 0 )
1344 	   {
1345 	      assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1346 	      assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1347 	
1348 	      col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1349 	   }
1350 	
1351 	   /* update sorted flags */
1352 	   if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1353 	      col->lprowssorted = FALSE;
1354 	   else
1355 	      col->nonlprowssorted = FALSE;
1356 	   if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1357 	      col->lprowssorted = FALSE;
1358 	   else
1359 	      col->nonlprowssorted = FALSE;
1360 	}
1361 	
1362 	/** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1363 	static
1364 	void rowMoveCoef(
1365 	   SCIP_ROW*             row,                /**< LP row */
1366 	   int                   oldpos,             /**< old position of coefficient */
1367 	   int                   newpos              /**< new position of coefficient */
1368 	   )
1369 	{
1370 	   assert(row != NULL);
1371 	   assert(0 <= oldpos && oldpos < row->len);
1372 	   assert(0 <= newpos && newpos < row->len);
1373 	   assert(row->cols[oldpos] != NULL);
1374 	
1375 	   if( oldpos == newpos )
1376 	      return;
1377 	
1378 	   row->cols[newpos] = row->cols[oldpos];
1379 	   row->cols_index[newpos] = row->cols_index[oldpos];
1380 	   row->vals[newpos] = row->vals[oldpos];
1381 	   row->linkpos[newpos] = row->linkpos[oldpos];
1382 	
1383 	   /* update link position in column */
1384 	   if( row->linkpos[newpos] >= 0 )
1385 	   {
1386 	      assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1387 	      assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1388 	
1389 	      row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1390 	   }
1391 	
1392 	   /* update sorted flags */
1393 	   if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1394 	      row->lpcolssorted = FALSE;
1395 	   else
1396 	      row->nonlpcolssorted = FALSE;
1397 	}
1398 	
1399 	/** swaps two coefficients in a row, and updates all corresponding data structures */
1400 	static
1401 	void rowSwapCoefs(
1402 	   SCIP_ROW*             row,                /**< LP row */
1403 	   int                   pos1,               /**< position of first coefficient */
1404 	   int                   pos2                /**< position of second coefficient */
1405 	   )
1406 	{
1407 	   SCIP_COL* tmpcol;
1408 	   SCIP_Real tmpval;
1409 	   int tmpindex;
1410 	   int tmplinkpos;
1411 	
1412 	   assert(row != NULL);
1413 	   assert(0 <= pos1 && pos1 < row->len);
1414 	   assert(0 <= pos2 && pos2 < row->len);
1415 	   assert(row->cols[pos1] != NULL);
1416 	   assert(row->cols[pos1]->index == row->cols_index[pos1]);
1417 	
1418 	   if( pos1 == pos2 )
1419 	      return;
1420 	
1421 	   /* swap coefficients */
1422 	   tmpcol = row->cols[pos2];
1423 	   tmpindex = row->cols_index[pos2];
1424 	   tmpval = row->vals[pos2];
1425 	   tmplinkpos = row->linkpos[pos2];
1426 	
1427 	   row->cols[pos2] = row->cols[pos1];
1428 	   row->cols_index[pos2] = row->cols_index[pos1];
1429 	   row->vals[pos2] = row->vals[pos1];
1430 	   row->linkpos[pos2] = row->linkpos[pos1];
1431 	
1432 	   row->cols[pos1] = tmpcol;
1433 	   row->cols_index[pos1] = tmpindex;
1434 	   row->vals[pos1] = tmpval;
1435 	   row->linkpos[pos1] = tmplinkpos;
1436 	
1437 	   /* update link position in columns */
1438 	   if( row->linkpos[pos1] >= 0 )
1439 	   {
1440 	      assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1441 	      assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1442 	
1443 	      row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1444 	   }
1445 	   if( row->linkpos[pos2] >= 0 )
1446 	   {
1447 	      assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1448 	      assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1449 	
1450 	      row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1451 	   }
1452 	
1453 	   /* update sorted flags */
1454 	   if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1455 	      row->lpcolssorted = FALSE;
1456 	   else
1457 	      row->nonlpcolssorted = FALSE;
1458 	   if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1459 	      row->lpcolssorted = FALSE;
1460 	   else
1461 	      row->nonlpcolssorted = FALSE;
1462 	}
1463 	
1464 	/** issues a ROWCOEFCHANGED event on the given row */
1465 	static
1466 	SCIP_RETCODE rowEventCoefChanged(
1467 	   SCIP_ROW*             row,                /**< row which coefficient has changed */
1468 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1469 	   SCIP_SET*             set,                /**< global SCIP settings */
1470 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1471 	   SCIP_COL*             col,                /**< the column which coefficient has changed */
1472 	   SCIP_Real             oldval,             /**< old value of the coefficient */
1473 	   SCIP_Real             newval              /**< new value of the coefficient */
1474 	   )
1475 	{
1476 	   assert(row != NULL);
1477 	   assert(row->eventfilter != NULL);
1478 	   assert(col != NULL);
1479 	
1480 	   /* check, if the row is being tracked for coefficient changes
1481 	    * if so, issue ROWCOEFCHANGED event
1482 	    */
1483 	   if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1484 	   {
1485 	      SCIP_EVENT* event;
1486 	
1487 	      SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1488 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1489 	   }
1490 	
1491 	   return SCIP_OKAY;
1492 	}
1493 	
1494 	/** issues a ROWCONSTCHANGED event on the given row */
1495 	static
1496 	SCIP_RETCODE rowEventConstantChanged(
1497 	   SCIP_ROW*             row,                /**< row which coefficient has changed */
1498 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1499 	   SCIP_SET*             set,                /**< global SCIP settings */
1500 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1501 	   SCIP_Real             oldval,             /**< old value of the constant */
1502 	   SCIP_Real             newval              /**< new value of the constant */
1503 	   )
1504 	{
1505 	   assert(row != NULL);
1506 	   assert(row->eventfilter != NULL);
1507 	
1508 	   /* check, if the row is being tracked for coefficient changes
1509 	    * if so, issue ROWCONSTCHANGED event
1510 	    */
1511 	   if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCONSTCHANGED)) )
1512 	   {
1513 	      SCIP_EVENT* event;
1514 	
1515 	      SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1516 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1517 	   }
1518 	
1519 	   return SCIP_OKAY;
1520 	}
1521 	
1522 	/** issues a ROWSIDECHANGED event on the given row */
1523 	static
1524 	SCIP_RETCODE rowEventSideChanged(
1525 	   SCIP_ROW*             row,                /**< row which coefficient has changed */
1526 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1527 	   SCIP_SET*             set,                /**< global SCIP settings */
1528 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1529 	   SCIP_SIDETYPE         side,               /**< the side that has changed */
1530 	   SCIP_Real             oldval,             /**< old value of side */
1531 	   SCIP_Real             newval              /**< new value of side */
1532 	   )
1533 	{
1534 	   assert(row != NULL);
1535 	   assert(row->eventfilter != NULL);
1536 	
1537 	   /* check, if the row is being tracked for coefficient changes
1538 	    * if so, issue ROWSIDECHANGED event
1539 	    */
1540 	   if( (row->eventfilter->len > 0 && !(row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED)) )
1541 	   {
1542 	      SCIP_EVENT* event;
1543 	
1544 	      SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1545 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1546 	   }
1547 	
1548 	   return SCIP_OKAY;
1549 	}
1550 	
1551 	#ifdef SCIP_MORE_DEBUG /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */
1552 	
1553 	#ifdef NDEBUG
1554 	#define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1555 	#else
1556 	#define ASSERT(x) assert(x)
1557 	#endif
1558 	
1559 	static SCIP_Bool msgdisp_checklinks = FALSE;
1560 	
1561 	
1562 	static
1563 	void checkLinks(
1564 	   SCIP_LP*              lp                  /**< current LP data */
1565 	   )
1566 	{
1567 	   SCIP_COL* col;
1568 	   SCIP_ROW* row;
1569 	   int i;
1570 	   int j;
1571 	
1572 	   ASSERT(lp != NULL);
1573 	
1574 	   if( !msgdisp_checklinks )
1575 	   {
1576 	      printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1577 	      msgdisp_checklinks = TRUE;
1578 	   }
1579 	
1580 	   for( i = 0; i < lp->ncols; ++i )
1581 	   {
1582 	      col = lp->cols[i];
1583 	      ASSERT(col != NULL);
1584 	      ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1585 	      ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1586 	      ASSERT(col->nlprows <= col->len);
1587 	      ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1588 	
1589 	      for( j = 0; j < col->len; ++j )
1590 	      {
1591 	         row = col->rows[j];
1592 	         ASSERT(row != NULL);
1593 	         ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1594 	         ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1595 	         ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1596 	         ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1597 	      }
1598 	   }
1599 	
1600 	   for( i = 0; i < lp->nrows; ++i )
1601 	   {
1602 	      row = lp->rows[i];
1603 	      ASSERT(row != NULL);
1604 	      ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1605 	      ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1606 	      ASSERT(row->nlpcols <= row->len);
1607 	      ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1608 	
1609 	      for( j = 0; j < row->len; ++j )
1610 	      {
1611 	         col = row->cols[j];
1612 	         ASSERT(col != NULL);
1613 	         ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1614 	         ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1615 	         ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1616 	         ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1617 	      }
1618 	   }
1619 	}
1620 	
1621 	#undef ASSERT
1622 	
1623 	#else
1624 	#define checkLinks(lp) /**/
1625 	#endif
1626 	
1627 	/*
1628 	 * Changing announcements
1629 	 */
1630 	
1631 	/** announces, that the given coefficient in the constraint matrix changed */
1632 	static
1633 	void coefChanged(
1634 	   SCIP_ROW*             row,                /**< LP row */
1635 	   SCIP_COL*             col,                /**< LP col */
1636 	   SCIP_LP*              lp                  /**< current LP data */
1637 	   )
1638 	{
1639 	   assert(row != NULL);
1640 	   assert(col != NULL);
1641 	   assert(lp != NULL);
1642 	
1643 	   if( row->lpipos >= 0 && col->lpipos >= 0 )
1644 	   {
1645 	      assert(row->lpipos < lp->nlpirows);
1646 	      assert(col->lpipos < lp->nlpicols);
1647 	
1648 	      /* we have to remember the change only in the row or in the column,
1649 	       * because the readdition of one vector would change the other automatically.
1650 	       */
1651 	      if( row->lpipos >= lp->lpifirstchgrow )
1652 	         row->coefchanged = TRUE;
1653 	      else if( col->lpipos >= lp->lpifirstchgcol )
1654 	         col->coefchanged = TRUE;
1655 	      else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1656 	      {
1657 	         row->coefchanged = TRUE;
1658 	         lp->lpifirstchgrow = row->lpipos;
1659 	      }
1660 	      else
1661 	      {
1662 	         col->coefchanged = TRUE;
1663 	         lp->lpifirstchgcol = col->lpipos;
1664 	      }
1665 	
1666 	      /* mark the current LP unflushed */
1667 	      lp->flushed = FALSE;
1668 	   }
1669 	
1670 	   row->pseudoactivity = SCIP_INVALID;
1671 	   row->minactivity = SCIP_INVALID;
1672 	   row->maxactivity = SCIP_INVALID;
1673 	   row->validpsactivitydomchg = -1;
1674 	   row->validactivitybdsdomchg = -1;
1675 	}
1676 	
1677 	
1678 	
1679 	/*
1680 	 * local column changing methods
1681 	 */
1682 	
1683 	/* forward declaration for colAddCoef() */
1684 	static
1685 	SCIP_RETCODE rowAddCoef(
1686 	   SCIP_ROW*             row,                /**< LP row */
1687 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1688 	   SCIP_SET*             set,                /**< global SCIP settings */
1689 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1690 	   SCIP_LP*              lp,                 /**< current LP data */
1691 	   SCIP_COL*             col,                /**< LP column */
1692 	   SCIP_Real             val,                /**< value of coefficient */
1693 	   int                   linkpos             /**< position of row in the column's row array, or -1 */
1694 	   );
1695 	
1696 	/** adds a previously non existing coefficient to an LP column */
1697 	static
1698 	SCIP_RETCODE colAddCoef(
1699 	   SCIP_COL*             col,                /**< LP column */
1700 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1701 	   SCIP_SET*             set,                /**< global SCIP settings */
1702 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1703 	   SCIP_LP*              lp,                 /**< current LP data */
1704 	   SCIP_ROW*             row,                /**< LP row */
1705 	   SCIP_Real             val,                /**< value of coefficient */
1706 	   int                   linkpos             /**< position of column in the row's col array, or -1 */
1707 	   )
1708 	{
1709 	   int pos;
1710 	
1711 	   assert(blkmem != NULL);
1712 	   assert(col != NULL);
1713 	   assert(col->nlprows <= col->len);
1714 	   assert(col->var != NULL);
1715 	   assert(row != NULL);
1716 	   assert(!SCIPsetIsZero(set, val));
1717 	   /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1718 	
1719 	   SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1720 	   assert(col->rows != NULL);
1721 	   assert(col->vals != NULL);
1722 	   assert(col->linkpos != NULL);
1723 	
1724 	   pos = col->len;
1725 	   col->len++;
1726 	
1727 	   /* if the row is in current LP and is linked to the column, we have to insert it at the end of the linked LP rows
1728 	    * part of the column's arrays
1729 	    */
1730 	   if( row->lppos >= 0 && linkpos >= 0 )
1731 	   {
1732 	      /* move the first non-LP/not linked row to the end */
1733 	      if( col->nlprows < pos )
1734 	      {
1735 	         colMoveCoef(col, col->nlprows, pos);
1736 	         pos = col->nlprows;
1737 	      }
1738 	      col->nlprows++;
1739 	   }
1740 	
1741 	   /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1742 	   val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1743 	
1744 	   /* insert the row at the correct position and update the links */
1745 	   col->rows[pos] = row;
1746 	   col->vals[pos] = val;
1747 	   col->linkpos[pos] = linkpos;
1748 	   if( linkpos == -1 )
1749 	   {
1750 	      col->nunlinked++;
1751 	
1752 	      /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1753 	       * of the row is not complete
1754 	       */
1755 	      if( col->lppos >= 0 )
1756 	      {
1757 	         /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1758 	          * has to be updated
1759 	          */
1760 	         SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1761 	         if( row->lppos >= 0 )
1762 	            pos = col->nlprows-1;
1763 	         linkpos = col->linkpos[pos];
1764 	
1765 	         assert(0 <= linkpos && linkpos < row->len);
1766 	         assert(row->cols[linkpos] == col);
1767 	         assert(col->rows[pos] == row);
1768 	         assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1769 	         assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1770 	      }
1771 	   }
1772 	   else
1773 	   {
1774 	      assert(row->linkpos[linkpos] == -1);
1775 	      assert(row->nunlinked > 0);
1776 	      row->linkpos[linkpos] = pos;
1777 	      row->nunlinked--;
1778 	
1779 	      /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1780 	       * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1781 	       */
1782 	      if( col->lppos >= 0 )
1783 	      {
1784 	         row->nlpcols++;
1785 	         rowSwapCoefs(row, linkpos, row->nlpcols-1);
1786 	
1787 	         /* if no swap was necessary, mark nonlpcols to be unsorted */
1788 	         if( linkpos == row->nlpcols-1 )
1789 	            row->lpcolssorted = FALSE;
1790 	      }
1791 	   }
1792 	
1793 	   /* update the sorted flags */
1794 	   if( row->lppos >= 0 && linkpos >= 0 )
1795 	   {
1796 	      assert(col->nlprows >= 1);
1797 	      assert(col->rows[col->nlprows-1] == row);
1798 	      if( col->nlprows > 1 )
1799 	         col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1800 	   }
1801 	   else
1802 	   {
1803 	      assert(col->len - col->nlprows >= 1);
1804 	      assert(col->rows[col->len-1] == row);
1805 	      if( col->len - col->nlprows > 1 )
1806 	         col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1807 	   }
1808 	
1809 	   coefChanged(row, col, lp);
1810 	
1811 	   SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1812 	      val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1813 	
1814 	   return SCIP_OKAY;
1815 	}
1816 	
1817 	/** deletes coefficient at given position from column */
1818 	static
1819 	SCIP_RETCODE colDelCoefPos(
1820 	   SCIP_COL*             col,                /**< column to be changed */
1821 	   SCIP_SET*             set,                /**< global SCIP settings */
1822 	   SCIP_LP*              lp,                 /**< current LP data */
1823 	   int                   pos                 /**< position in column vector to delete */
1824 	   )
1825 	{
1826 	   SCIP_ROW* row;
1827 	
1828 	   assert(col != NULL);
1829 	   assert(col->var != NULL);
1830 	   assert(set != NULL);
1831 	   assert(0 <= pos && pos < col->len);
1832 	   assert(col->rows[pos] != NULL);
1833 	   assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1834 	   assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1835 	
1836 	   row = col->rows[pos];
1837 	   assert((row->lppos >= 0) == (pos < col->nlprows));
1838 	
1839 	   /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from column <%s>\n",
1840 	     col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1841 	
1842 	   if( col->linkpos[pos] == -1 )
1843 	      col->nunlinked--;
1844 	
1845 	   /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1846 	   if( pos < col->nlprows )
1847 	   {
1848 	      colMoveCoef(col, col->nlprows-1, pos);
1849 	      col->nlprows--;
1850 	      pos = col->nlprows;
1851 	   }
1852 	
1853 	   /* move last coefficient to position of empty slot */
1854 	   colMoveCoef(col, col->len-1, pos);
1855 	   col->len--;
1856 	
1857 	   coefChanged(row, col, lp);
1858 	
1859 	   return SCIP_OKAY;
1860 	}
1861 	
1862 	/** changes a coefficient at given position of an LP column */
1863 	static
1864 	SCIP_RETCODE colChgCoefPos(
1865 	   SCIP_COL*             col,                /**< LP column */
1866 	   SCIP_SET*             set,                /**< global SCIP settings */
1867 	   SCIP_LP*              lp,                 /**< current LP data */
1868 	   int                   pos,                /**< position in column vector to change */
1869 	   SCIP_Real             val                 /**< value of coefficient */
1870 	   )
1871 	{
1872 	   assert(col != NULL);
1873 	   assert(col->var != NULL);
1874 	   assert(0 <= pos && pos < col->len);
1875 	   assert(col->rows[pos] != NULL);
1876 	   assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1877 	
1878 	   /*debugMsg(scip, "changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1879 	     col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1880 	
1881 	   /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1882 	   val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1883 	
1884 	   if( SCIPsetIsZero(set, val) )
1885 	   {
1886 	      /* delete existing coefficient */
1887 	      SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1888 	   }
1889 	   else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1890 	   {
1891 	      /* change existing coefficient */
1892 	      col->vals[pos] = val;
1893 	      coefChanged(col->rows[pos], col, lp);
1894 	   }
1895 	
1896 	   return SCIP_OKAY;
1897 	}
1898 	
1899 	
1900 	
1901 	
1902 	/*
1903 	 * local row changing methods
1904 	 */
1905 	
1906 	/** update row norms after addition of coefficient */
1907 	static
1908 	void rowAddNorms(
1909 	   SCIP_ROW*             row,                /**< LP row */
1910 	   SCIP_SET*             set,                /**< global SCIP settings */
1911 	   SCIP_COL*             col,                /**< column of added coefficient */
1912 	   SCIP_Real             val,                /**< value of added coefficient */
1913 	   SCIP_Bool             updateidxvals       /**< update min/max idx and min/max val? */
1914 	   )
1915 	{
1916 	   SCIP_Real absval;
1917 	
1918 	   assert(row != NULL);
1919 	   assert(row->nummaxval >= 0);
1920 	   assert(row->numminval >= 0);
1921 	   assert(set != NULL);
1922 	   assert(col != NULL);
1923 	
1924 	   absval = REALABS(val);
1925 	   assert(!SCIPsetIsZero(set, absval));
1926 	
1927 	   /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
1928 	   if( col->lppos >= 0 )
1929 	   {
1930 	      /* update squared Euclidean norm and sum norm */
1931 	      row->sqrnorm += SQR(absval);
1932 	      row->sumnorm += absval;
1933 	
1934 	      /* update objective function scalar product */
1935 	      row->objprod += val * col->unchangedobj;
1936 	   }
1937 	
1938 	   if( updateidxvals )
1939 	   {
1940 	      /* update min/maxidx */
1941 	      row->minidx = MIN(row->minidx, col->index);
1942 	      row->maxidx = MAX(row->maxidx, col->index);
1943 	
1944 	      /* update maximal and minimal non-zero value */
1945 	      if( row->nummaxval > 0 )
1946 	      {
1947 	         if( SCIPsetIsGT(set, absval, row->maxval) )
1948 	         {
1949 	            row->maxval = absval;
1950 	            row->nummaxval = 1;
1951 	         }
1952 	         else if( SCIPsetIsGE(set, absval, row->maxval) )
1953 	         {
1954 	            /* make sure the maxval is always exactly the same */
1955 	            row->maxval = MAX(absval, row->maxval);
1956 	            row->nummaxval++;
1957 	         }
1958 	      }
1959 	      if( row->numminval > 0 )
1960 	      {
1961 	         if( SCIPsetIsLT(set, absval, row->minval) )
1962 	         {
1963 	            row->minval = absval;
1964 	            row->numminval = 1;
1965 	         }
1966 	         else if( SCIPsetIsLE(set, absval, row->minval) )
1967 	         {
1968 	            /* make sure the minval is always exactly the same */
1969 	            row->minval = MIN(absval, row->minval);
1970 	            row->numminval++;
1971 	         }
1972 	      }
1973 	   }
1974 	   else
1975 	   {
1976 	      assert(row->minidx <= col->index);
1977 	      assert(row->maxidx >= col->index);
1978 	      assert(row->numminval <= 0 || absval >= row->minval);
1979 	      assert(row->nummaxval <= 0 || absval <= row->maxval);
1980 	   }
1981 	}
1982 	
1983 	/** update row norms after deletion of coefficient */
1984 	static
1985 	void rowDelNorms(
1986 	   SCIP_ROW*             row,                /**< LP row */
1987 	   SCIP_SET*             set,                /**< global SCIP settings */
1988 	   SCIP_COL*             col,                /**< column of deleted coefficient */
1989 	   SCIP_Real             val,                /**< value of deleted coefficient */
1990 	   SCIP_Bool             forcenormupdate,    /**< should the norms be updated even if lppos of column is -1? */
1991 	   SCIP_Bool             updateindex,        /**< should the minimal/maximal column index of row be updated? */
1992 	   SCIP_Bool             updateval           /**< should the minimal/maximal value of row be updated? */
1993 	   )
1994 	{
1995 	   SCIP_Real absval;
1996 	
1997 	   assert(row != NULL);
1998 	   assert(row->nummaxval >= 0);
1999 	   assert(row->numminval >= 0);
2000 	   assert(set != NULL);
2001 	   assert(col != NULL);
2002 	
2003 	   absval = REALABS(val);
2004 	   assert(!SCIPsetIsZero(set, absval));
2005 	   assert(row->nummaxval == 0 || row->maxval >= absval);
2006 	   assert(row->numminval == 0 || row->minval <= absval);
2007 	
2008 	   /* update min/maxidx validity */
2009 	   if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
2010 	      row->validminmaxidx = FALSE;
2011 	
2012 	   /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
2013 	   if( forcenormupdate || col->lppos >= 0 )
2014 	   {
2015 	      /* update squared Euclidean norm and sum norm */
2016 	      row->sqrnorm -= SQR(absval);
2017 	      row->sqrnorm = MAX(row->sqrnorm, 0.0);
2018 	      row->sumnorm -= absval;
2019 	      row->sumnorm = MAX(row->sumnorm, 0.0);
2020 	
2021 	      /* update objective function scalar product */
2022 	      row->objprod -= val * col->unchangedobj;
2023 	   }
2024 	
2025 	   if( updateval )
2026 	   {
2027 	      /* update maximal and minimal non-zero value */
2028 	      if( row->nummaxval > 0 )
2029 	      {
2030 	         if( SCIPsetIsGE(set, absval, row->maxval) )
2031 	            row->nummaxval--;
2032 	      }
2033 	      if( row->numminval > 0 )
2034 	      {
2035 	         if( SCIPsetIsLE(set, absval, row->minval) )
2036 	            row->numminval--;
2037 	      }
2038 	   }
2039 	}
2040 	
2041 	/** adds a previously non existing coefficient to an LP row */
2042 	static
2043 	SCIP_RETCODE rowAddCoef(
2044 	   SCIP_ROW*             row,                /**< LP row */
2045 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2046 	   SCIP_SET*             set,                /**< global SCIP settings */
2047 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2048 	   SCIP_LP*              lp,                 /**< current LP data */
2049 	   SCIP_COL*             col,                /**< LP column */
2050 	   SCIP_Real             val,                /**< value of coefficient */
2051 	   int                   linkpos             /**< position of row in the column's row array, or -1 */
2052 	   )
2053 	{
2054 	   int pos;
2055 	
2056 	   assert(row != NULL);
2057 	   assert(row->nlpcols <= row->len);
2058 	   assert(blkmem != NULL);
2059 	   assert(col != NULL);
2060 	   assert(col->var != NULL);
2061 	   assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2062 	   assert(!SCIPsetIsZero(set, val));
2063 	   /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2064 	
2065 	   if( row->nlocks > 0 )
2066 	   {
2067 	      SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2068 	      return SCIP_INVALIDDATA;
2069 	   }
2070 	
2071 	   SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2072 	   assert(row->cols != NULL);
2073 	   assert(row->vals != NULL);
2074 	
2075 	   pos = row->len;
2076 	   row->len++;
2077 	
2078 	   /* if the column is in current LP and is linked to the row, we have to insert it at the end of the linked LP columns
2079 	    * part of the row's arrays
2080 	    */
2081 	   if( col->lppos >= 0 && linkpos >= 0 )
2082 	   {
2083 	      /* move the first non-LP/not linked column to the end */
2084 	      if( row->nlpcols < pos )
2085 	      {
2086 	         rowMoveCoef(row, row->nlpcols, pos);
2087 	         pos = row->nlpcols;
2088 	      }
2089 	      row->nlpcols++;
2090 	   }
2091 	
2092 	   /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2093 	   val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2094 	
2095 	   /* insert the column at the correct position and update the links */
2096 	   row->cols[pos] = col;
2097 	   row->cols_index[pos] = col->index;
2098 	   row->vals[pos] = val;
2099 	   row->linkpos[pos] = linkpos;
2100 	   row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2101 	   if( linkpos == -1 )
2102 	   {
2103 	      row->nunlinked++;
2104 	
2105 	      /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2106 	       * of the column is not complete
2107 	       */
2108 	      if( row->lppos >= 0 )
2109 	      {
2110 	         /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2111 	          * has to be updated
2112 	          */
2113 	         SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2114 	         if( col->lppos >= 0 )
2115 	            pos = row->nlpcols-1;
2116 	         linkpos = row->linkpos[pos];
2117 	
2118 	         assert(0 <= linkpos && linkpos < col->len);
2119 	         assert(col->rows[linkpos] == row);
2120 	         assert(row->cols[pos] == col);
2121 	         assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2122 	         assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2123 	      }
2124 	   }
2125 	   else
2126 	   {
2127 	      assert(col->linkpos[linkpos] == -1);
2128 	      assert(col->nunlinked > 0);
2129 	      col->linkpos[linkpos] = pos;
2130 	      col->nunlinked--;
2131 	
2132 	      /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2133 	       * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2134 	       */
2135 	      if( row->lppos >= 0 )
2136 	      {
2137 	         col->nlprows++;
2138 	         colSwapCoefs(col, linkpos, col->nlprows-1);
2139 	
2140 	         /* if no swap was necessary, mark lprows to be unsorted */
2141 	         if( linkpos == col->nlprows-1 )
2142 	            col->lprowssorted = FALSE;
2143 	      }
2144 	   }
2145 	
2146 	   /* update the sorted flags */
2147 	   if( col->lppos >= 0 && linkpos >= 0 )
2148 	   {
2149 	      assert(row->nlpcols >= 1);
2150 	      assert(row->cols[row->nlpcols-1] == col);
2151 	      if( row->nlpcols > 1 )
2152 	      {
2153 	         assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2154 	         row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2155 	      }
2156 	   }
2157 	   else
2158 	   {
2159 	      assert(row->len - row->nlpcols >= 1);
2160 	      assert(row->cols[row->len-1] == col);
2161 	      if( row->len - row->nlpcols > 1 )
2162 	      {
2163 	         assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2164 	         row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2165 	      }
2166 	   }
2167 	
2168 	   /* update row norm */
2169 	   rowAddNorms(row, set, col, val, TRUE);
2170 	
2171 	   coefChanged(row, col, lp);
2172 	
2173 	   SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2174 	      val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2175 	
2176 	   /* issue row coefficient changed event */
2177 	   SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2178 	
2179 	   return SCIP_OKAY;
2180 	}
2181 	
2182 	/** deletes coefficient at given position from row */
2183 	static
2184 	SCIP_RETCODE rowDelCoefPos(
2185 	   SCIP_ROW*             row,                /**< row to be changed */
2186 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2187 	   SCIP_SET*             set,                /**< global SCIP settings */
2188 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2189 	   SCIP_LP*              lp,                 /**< current LP data */
2190 	   int                   pos                 /**< position in row vector to delete */
2191 	   )
2192 	{
2193 	   SCIP_COL* col;
2194 	   SCIP_Real val;
2195 	
2196 	   assert(row != NULL);
2197 	   assert(set != NULL);
2198 	   assert(0 <= pos && pos < row->len);
2199 	   assert(row->cols[pos] != NULL);
2200 	   assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2201 	
2202 	   col = row->cols[pos];
2203 	   val = row->vals[pos];
2204 	   assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2205 	
2206 	   /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from row <%s>\n",
2207 	     val, SCIPvarGetName(col->var), pos, row->name);*/
2208 	
2209 	   if( row->nlocks > 0 )
2210 	   {
2211 	      SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2212 	      return SCIP_INVALIDDATA;
2213 	   }
2214 	
2215 	   if( row->linkpos[pos] == -1 )
2216 	      row->nunlinked--;
2217 	
2218 	   /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2219 	   if( pos < row->nlpcols )
2220 	   {
2221 	      rowMoveCoef(row, row->nlpcols-1, pos);
2222 	      assert(!row->lpcolssorted);
2223 	      row->nlpcols--;
2224 	      pos = row->nlpcols;
2225 	   }
2226 	
2227 	   /* move last coefficient to position of empty slot */
2228 	   rowMoveCoef(row, row->len-1, pos);
2229 	   row->len--;
2230 	
2231 	   /* update norms */
2232 	   rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2233 	
2234 	   coefChanged(row, col, lp);
2235 	
2236 	   /* issue row coefficient changed event */
2237 	   SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2238 	
2239 	   return SCIP_OKAY;
2240 	}
2241 	
2242 	/** changes a coefficient at given position of an LP row */
2243 	static
2244 	SCIP_RETCODE rowChgCoefPos(
2245 	   SCIP_ROW*             row,                /**< LP row */
2246 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2247 	   SCIP_SET*             set,                /**< global SCIP settings */
2248 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2249 	   SCIP_LP*              lp,                 /**< current LP data */
2250 	   int                   pos,                /**< position in row vector to change */
2251 	   SCIP_Real             val                 /**< value of coefficient */
2252 	   )
2253 	{
2254 	   SCIP_COL* col;
2255 	
2256 	   assert(row != NULL);
2257 	   assert(0 <= pos && pos < row->len);
2258 	
2259 	   /*SCIPsetDebugMsg(set, "changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2260 	     row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2261 	
2262 	   if( row->nlocks > 0 )
2263 	   {
2264 	      SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2265 	      return SCIP_INVALIDDATA;
2266 	   }
2267 	
2268 	   /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2269 	   val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2270 	   col = row->cols[pos];
2271 	   assert(row->cols[pos] != NULL);
2272 	
2273 	   if( SCIPsetIsZero(set, val) )
2274 	   {
2275 	      /* delete existing coefficient */
2276 	      SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2277 	   }
2278 	   else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2279 	   {
2280 	      SCIP_Real oldval;
2281 	
2282 	      oldval = row->vals[pos];
2283 	
2284 	      /* change existing coefficient */
2285 	      rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2286 	      row->vals[pos] = val;
2287 	      row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2288 	      rowAddNorms(row, set, col, row->vals[pos], TRUE);
2289 	      coefChanged(row, col, lp);
2290 	
2291 	      /* issue row coefficient changed event */
2292 	      SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2293 	   }
2294 	
2295 	   return SCIP_OKAY;
2296 	}
2297 	
2298 	/** notifies LP row, that its sides were changed */
2299 	static
2300 	SCIP_RETCODE rowSideChanged(
2301 	   SCIP_ROW*             row,                /**< LP row */
2302 	   SCIP_SET*             set,                /**< global SCIP settings */
2303 	   SCIP_LP*              lp,                 /**< current LP data */
2304 	   SCIP_SIDETYPE         sidetype            /**< type of side: left or right hand side */
2305 	   )
2306 	{
2307 	   assert(row != NULL);
2308 	   assert(lp != NULL);
2309 	
2310 	   if( row->lpipos >= 0 )
2311 	   {
2312 	      /* insert row in the chgrows list (if not already there) */
2313 	      if( !row->lhschanged && !row->rhschanged )
2314 	      {
2315 	         SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2316 	         lp->chgrows[lp->nchgrows] = row;
2317 	         lp->nchgrows++;
2318 	      }
2319 	
2320 	      /* mark side change in the row */
2321 	      switch( sidetype )
2322 	      {
2323 	      case SCIP_SIDETYPE_LEFT:
2324 	         row->lhschanged = TRUE;
2325 	         break;
2326 	      case SCIP_SIDETYPE_RIGHT:
2327 	         row->rhschanged = TRUE;
2328 	         break;
2329 	      default:
2330 	         SCIPerrorMessage("unknown row side type\n");
2331 	         SCIPABORT();
2332 	         return SCIP_INVALIDDATA;  /*lint !e527*/
2333 	      }
2334 	
2335 	      /* mark the current LP unflushed */
2336 	      lp->flushed = FALSE;
2337 	
2338 	      assert(lp->nchgrows > 0);
2339 	   }
2340 	
2341 	   return SCIP_OKAY;
2342 	}
2343 	
2344 	
2345 	
2346 	
2347 	/*
2348 	 * double linked coefficient matrix methods
2349 	 */
2350 	
2351 	/** insert column coefficients in corresponding rows */
2352 	SCIP_RETCODE colLink(
2353 	   SCIP_COL*             col,                /**< column data */
2354 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2355 	   SCIP_SET*             set,                /**< global SCIP settings */
2356 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2357 	   SCIP_LP*              lp                  /**< current LP data */
2358 	   )
2359 	{
2360 	   int i;
2361 	
2362 	   assert(col != NULL);
2363 	   assert(col->var != NULL);
2364 	   assert(blkmem != NULL);
2365 	   assert(set != NULL);
2366 	   assert(lp != NULL);
2367 	
2368 	   if( col->nunlinked > 0 )
2369 	   {
2370 	      SCIPsetDebugMsg(set, "linking column <%s>\n", SCIPvarGetName(col->var));
2371 	
2372 	      /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2373 	      for( i = col->nlprows; i < col->len; ++i )
2374 	      {
2375 	         assert(!SCIPsetIsZero(set, col->vals[i]));
2376 	         if( col->linkpos[i] == -1 )
2377 	         {
2378 	            /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2379 	            SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2380 	         }
2381 	         assert(col->rows[i]->cols[col->linkpos[i]] == col);
2382 	         assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2383 	         assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2384 	         assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2385 	      }
2386 	   }
2387 	   assert(col->nunlinked == 0);
2388 	
2389 	   checkLinks(lp);
2390 	
2391 	   return SCIP_OKAY;
2392 	}
2393 	
2394 	/** removes column coefficients from corresponding rows */
2395 	SCIP_RETCODE colUnlink(
2396 	   SCIP_COL*             col,                /**< column data */
2397 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2398 	   SCIP_SET*             set,                /**< global SCIP settings */
2399 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2400 	   SCIP_LP*              lp                  /**< current LP data */
2401 	   )
2402 	{
2403 	   int i;
2404 	
2405 	   assert(col != NULL);
2406 	   assert(col->var != NULL);
2407 	   assert(blkmem != NULL);
2408 	   assert(set != NULL);
2409 	   assert(lp != NULL);
2410 	
2411 	   if( col->nunlinked < col->len )
2412 	   {
2413 	      SCIPsetDebugMsg(set, "unlinking column <%s>\n", SCIPvarGetName(col->var));
2414 	      for( i = 0; i < col->len; ++i )
2415 	      {
2416 	         if( col->linkpos[i] >= 0 )
2417 	         {
2418 	            assert(col->rows[i]->cols[col->linkpos[i]] == col);
2419 	            SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2420 	            col->linkpos[i] = -1;
2421 	            col->nunlinked++;
2422 	         }
2423 	      }
2424 	   }
2425 	   assert(col->nunlinked == col->len);
2426 	
2427 	   checkLinks(lp);
2428 	
2429 	   return SCIP_OKAY;
2430 	}
2431 	
2432 	/** insert row coefficients in corresponding columns */
2433 	SCIP_RETCODE rowLink(
2434 	   SCIP_ROW*             row,                /**< row data */
2435 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2436 	   SCIP_SET*             set,                /**< global SCIP settings */
2437 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2438 	   SCIP_LP*              lp                  /**< current LP data */
2439 	   )
2440 	{
2441 	   int i;
2442 	
2443 	   assert(row != NULL);
2444 	   assert(blkmem != NULL);
2445 	   assert(set != NULL);
2446 	   assert(lp != NULL);
2447 	
2448 	   if( row->nunlinked > 0 )
2449 	   {
2450 	      SCIPsetDebugMsg(set, "linking row <%s>\n", row->name);
2451 	
2452 	      /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2453 	      for( i = row->nlpcols; i < row->len; ++i )
2454 	      {
2455 	         assert(!SCIPsetIsZero(set, row->vals[i]));
2456 	         if( row->linkpos[i] == -1 )
2457 	         {
2458 	            /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2459 	            SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2460 	         }
2461 	         assert(row->cols[i]->rows[row->linkpos[i]] == row);
2462 	         assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2463 	         assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2464 	         assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2465 	      }
2466 	   }
2467 	   assert(row->nunlinked == 0);
2468 	
2469 	   checkLinks(lp);
2470 	
2471 	   return SCIP_OKAY;
2472 	}
2473 	
2474 	/** removes row coefficients from corresponding columns */
2475 	SCIP_RETCODE rowUnlink(
2476 	   SCIP_ROW*             row,                /**< row data */
2477 	   SCIP_SET*             set,                /**< global SCIP settings */
2478 	   SCIP_LP*              lp                  /**< current LP data */
2479 	   )
2480 	{
2481 	   int i;
2482 	
2483 	   assert(row != NULL);
2484 	   assert(set != NULL);
2485 	   assert(lp != NULL);
2486 	
2487 	   if( row->nunlinked < row->len )
2488 	   {
2489 	      SCIPsetDebugMsg(set, "unlinking row <%s>\n", row->name);
2490 	      for( i = 0; i < row->len; ++i )
2491 	      {
2492 	         if( row->linkpos[i] >= 0 )
2493 	         {
2494 	            assert(row->cols[i]->rows[row->linkpos[i]] == row);
2495 	            SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2496 	            row->nunlinked++;
2497 	         }
2498 	      }
2499 	   }
2500 	   assert(row->nunlinked == row->len);
2501 	
2502 	   return SCIP_OKAY;
2503 	}
2504 	
2505 	
2506 	
2507 	
2508 	/*
2509 	 * local LP parameter methods
2510 	 */
2511 	
2512 	/** sets parameter of type int in LP solver, ignoring unknown parameters */
2513 	static
2514 	SCIP_RETCODE lpSetIntpar(
2515 	   SCIP_LP*              lp,                 /**< current LP data */
2516 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2517 	   int                   value,              /**< value to set parameter to */
2518 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2519 	   )
2520 	{
2521 	   SCIP_RETCODE retcode;
2522 	
2523 	   assert(lp != NULL);
2524 	   assert(success != NULL);
2525 	
2526 	   retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2527 	
2528 	   /* check, if parameter is unknown */
2529 	   if( retcode == SCIP_PARAMETERUNKNOWN )
2530 	   {
2531 	      *success = FALSE;
2532 	      return SCIP_OKAY;
2533 	   }
2534 	   *success = TRUE;
2535 	
2536 	   return retcode;
2537 	}
2538 	
2539 	/** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2540 	static
2541 	SCIP_RETCODE lpSetBoolpar(
2542 	   SCIP_LP*              lp,                 /**< current LP data */
2543 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2544 	   SCIP_Bool             value,              /**< value to set parameter to */
2545 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2546 	   )
2547 	{
2548 	   return lpSetIntpar(lp, lpparam, (int)value, success);
2549 	}
2550 	
2551 	/** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2552 	static
2553 	SCIP_RETCODE lpSetRealpar(
2554 	   SCIP_LP*              lp,                 /**< current LP data */
2555 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2556 	   SCIP_Real             value,              /**< value to set parameter to */
2557 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2558 	   )
2559 	{
2560 	   SCIP_RETCODE retcode;
2561 	
2562 	   assert(lp != NULL);
2563 	   assert(success != NULL);
2564 	
2565 	   retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2566 	
2567 	   /* check, if parameter is unknown */
2568 	   if( retcode == SCIP_PARAMETERUNKNOWN )
2569 	   {
2570 	      *success = FALSE;
2571 	      return SCIP_OKAY;
2572 	   }
2573 	   *success = TRUE;
2574 	
2575 	   return retcode;
2576 	}
2577 	
2578 	#ifndef NDEBUG
2579 	/** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2580 	static
2581 	SCIP_RETCODE lpCheckIntpar(
2582 	   SCIP_LP*              lp,                 /**< current LP data */
2583 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2584 	   int                   value               /**< value parameter should have */
2585 	   )
2586 	{
2587 	   SCIP_RETCODE retcode;
2588 	   int lpivalue;
2589 	
2590 	   assert(lp != NULL);
2591 	
2592 	   retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2593 	
2594 	   /* ignore unknown parameter error */
2595 	   if( retcode == SCIP_PARAMETERUNKNOWN )
2596 	      return SCIP_OKAY;
2597 	
2598 	   /* check value */
2599 	   assert(lpivalue == value);
2600 	
2601 	   return retcode;
2602 	}
2603 	
2604 	/** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2605 	static
2606 	SCIP_RETCODE lpCheckBoolpar(
2607 	   SCIP_LP*              lp,                 /**< current LP data */
2608 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2609 	   SCIP_Bool             value               /**< value parameter should have */
2610 	   )
2611 	{
2612 	   return lpCheckIntpar(lp, lpparam, (int)value);
2613 	}
2614 	
2615 	/** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2616 	static
2617 	SCIP_RETCODE lpCheckRealpar(
2618 	   SCIP_LP*              lp,                 /**< current LP data */
2619 	   SCIP_LPPARAM          lpparam,            /**< LP parameter */
2620 	   SCIP_Real             value               /**< value parameter should have */
2621 	   )
2622 	{
2623 	   SCIP_RETCODE retcode;
2624 	   SCIP_Real lpivalue;
2625 	
2626 	   assert(lp != NULL);
2627 	
2628 	   retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2629 	
2630 	   /* ignore unknown parameter error */
2631 	   if( retcode == SCIP_PARAMETERUNKNOWN )
2632 	      return SCIP_OKAY;
2633 	
2634 	   /* check value */
2635 	   assert(lpivalue == value); /*lint !e777*/
2636 	
2637 	   return retcode;
2638 	}
2639 	#else
2640 	#define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2641 	#define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2642 	#define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2643 	#endif
2644 	
2645 	/** should the objective limit of the LP solver be disabled */
2646 	#define lpCutoffDisabled(set,prob) (set->lp_disablecutoff == 1 || ((set->nactivepricers > 0 || !SCIPprobAllColsInLP(prob, set, lp)) && set->lp_disablecutoff == 2))
2647 	
2648 	/** sets the objective limit of the LP solver
2649 	 *
2650 	 *  Note that we are always minimizing.
2651 	 */
2652 	static
2653 	SCIP_RETCODE lpSetObjlim(
2654 	   SCIP_LP*              lp,                 /**< current LP data */
2655 	   SCIP_SET*             set,                /**< global SCIP settings */
2656 	   SCIP_PROB*            prob,               /**< problem data */
2657 	   SCIP_Real             objlim,             /**< new objective limit */
2658 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was actually changed */
2659 	   )
2660 	{
2661 	   assert(lp != NULL);
2662 	   assert(set != NULL);
2663 	   assert(success != NULL);
2664 	
2665 	   *success = FALSE;
2666 	
2667 	   /* We disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP
2668 	    * solver's objective limit handling, so we make sure that the objective limit is inactive (infinity). */
2669 	   if( lpCutoffDisabled(set, prob) || set->misc_exactsolve )
2670 	      objlim = SCIPlpiInfinity(lp->lpi);
2671 	
2672 	   /* convert SCIP infinity value to lp-solver infinity value if necessary */
2673 	   if( SCIPsetIsInfinity(set, objlim) )
2674 	      objlim = SCIPlpiInfinity(lp->lpi);
2675 	
2676 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_OBJLIM, lp->lpiobjlim) );
2677 	
2678 	   if( objlim != lp->lpiobjlim ) /*lint !e777*/
2679 	   {
2680 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) );
2681 	      if( *success )
2682 	      {
2683 	         SCIP_Real actualobjlim;
2684 	
2685 	         /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2686 	         SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) );
2687 	         if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/
2688 	         {
2689 	            /* mark the current solution invalid */
2690 	            lp->solved = FALSE;
2691 	            lp->primalfeasible = FALSE;
2692 	            lp->primalchecked = FALSE;
2693 	            lp->lpobjval = SCIP_INVALID;
2694 	            lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2695 	         }
2696 	         lp->lpiobjlim = actualobjlim;
2697 	      }
2698 	   }
2699 	
2700 	   return SCIP_OKAY;
2701 	}
2702 	
2703 	/** sets the feasibility tolerance of the LP solver */
2704 	static
2705 	SCIP_RETCODE lpSetFeastol(
2706 	   SCIP_LP*              lp,                 /**< current LP data */
2707 	   SCIP_Real             feastol,            /**< new feasibility tolerance */
2708 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was actually changed */
2709 	   )
2710 	{
2711 	   assert(lp != NULL);
2712 	   assert(feastol >= 0.0);
2713 	   assert(success != NULL);
2714 	
2715 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_FEASTOL, lp->lpifeastol) );
2716 	
2717 	   if( feastol != lp->lpifeastol ) /*lint !e777*/
2718 	   {
2719 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2720 	      if( *success )
2721 	      {
2722 	         SCIP_Real actualfeastol;
2723 	
2724 	         /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2725 	         SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) );
2726 	         if( lp->nrows > 0 && actualfeastol < lp->lpifeastol )
2727 	         {
2728 	            /* mark the current solution invalid */
2729 	            lp->solved = FALSE;
2730 	            lp->primalfeasible = FALSE;
2731 	            lp->primalchecked = FALSE;
2732 	            lp->lpobjval = SCIP_INVALID;
2733 	            lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2734 	         }
2735 	         else
2736 	            *success = FALSE;
2737 	         lp->lpifeastol = actualfeastol;
2738 	      }
2739 	   }
2740 	   else
2741 	      *success = FALSE;
2742 	
2743 	   return SCIP_OKAY;
2744 	}
2745 	
2746 	/** sets the reduced costs feasibility tolerance of the LP solver */
2747 	static
2748 	SCIP_RETCODE lpSetDualfeastol(
2749 	   SCIP_LP*              lp,                 /**< current LP data */
2750 	   SCIP_Real             dualfeastol,        /**< new reduced costs feasibility tolerance */
2751 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was actually changed */
2752 	   )
2753 	{
2754 	   assert(lp != NULL);
2755 	   assert(dualfeastol >= 0.0);
2756 	   assert(success != NULL);
2757 	
2758 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_DUALFEASTOL, lp->lpidualfeastol) );
2759 	
2760 	   if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2761 	   {
2762 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2763 	      if( *success )
2764 	      {
2765 	         SCIP_Real actualdualfeastol;
2766 	
2767 	         /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2768 	         SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) );
2769 	         if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol )
2770 	         {
2771 	            /* mark the current solution invalid */
2772 	            lp->solved = FALSE;
2773 	            lp->dualfeasible = FALSE;
2774 	            lp->dualchecked = FALSE;
2775 	            lp->lpobjval = SCIP_INVALID;
2776 	            lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2777 	         }
2778 	         else
2779 	            *success = FALSE;
2780 	         lp->lpidualfeastol = actualdualfeastol;
2781 	      }
2782 	   }
2783 	   else
2784 	      *success = FALSE;
2785 	
2786 	   return SCIP_OKAY;
2787 	}
2788 	
2789 	/** sets the convergence tolerance used in barrier algorithm of the LP solver */
2790 	static
2791 	SCIP_RETCODE lpSetBarrierconvtol(
2792 	   SCIP_LP*              lp,                 /**< current LP data */
2793 	   SCIP_Real             barrierconvtol,     /**< new convergence tolerance used in barrier algorithm */
2794 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was actually changed */
2795 	   )
2796 	{
2797 	   assert(lp != NULL);
2798 	   assert(barrierconvtol >= 0.0);
2799 	   assert(success != NULL);
2800 	
2801 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, lp->lpibarrierconvtol) );
2802 	
2803 	   if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2804 	   {
2805 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2806 	      if( *success )
2807 	      {
2808 	         SCIP_Real actualbarrierconvtol;
2809 	
2810 	         /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2811 	         SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) );
2812 	         if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol
2813 	            && (lp->lastlpalgo == SCIP_LPALGO_BARRIER || lp->lastlpalgo == SCIP_LPALGO_BARRIERCROSSOVER) )
2814 	         {
2815 	            /* mark the current solution invalid */
2816 	            lp->solved = FALSE;
2817 	            lp->dualfeasible = FALSE;
2818 	            lp->dualchecked = FALSE;
2819 	            lp->lpobjval = SCIP_INVALID;
2820 	            lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2821 	         }
2822 	         else
2823 	            *success = FALSE;
2824 	         lp->lpibarrierconvtol = actualbarrierconvtol;
2825 	      }
2826 	   }
2827 	   else
2828 	      *success = FALSE;
2829 	
2830 	   return SCIP_OKAY;
2831 	}
2832 	
2833 	/** sets the FROMSCRATCH setting of the LP solver */
2834 	static
2835 	SCIP_RETCODE lpSetFromscratch(
2836 	   SCIP_LP*              lp,                 /**< current LP data */
2837 	   SCIP_Bool             fromscratch,        /**< new FROMSCRATCH setting */
2838 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2839 	   )
2840 	{
2841 	   assert(lp != NULL);
2842 	   assert(success != NULL);
2843 	
2844 	   SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, lp->lpifromscratch) );
2845 	
2846 	   if( fromscratch != lp->lpifromscratch )
2847 	   {
2848 	      SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2849 	      if( *success )
2850 	         lp->lpifromscratch = fromscratch;
2851 	   }
2852 	   else
2853 	      *success = FALSE;
2854 	
2855 	   return SCIP_OKAY;
2856 	}
2857 	
2858 	/** sets the FASTMIP setting of the LP solver */
2859 	static
2860 	SCIP_RETCODE lpSetFastmip(
2861 	   SCIP_LP*              lp,                 /**< current LP data */
2862 	   int                   fastmip,            /**< new FASTMIP setting */
2863 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2864 	   )
2865 	{
2866 	   assert(lp != NULL);
2867 	   assert(success != NULL);
2868 	   assert(0 <= fastmip && fastmip <= 1);
2869 	
2870 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_FASTMIP, lp->lpifastmip) );
2871 	
2872 	   if( fastmip != lp->lpifastmip )
2873 	   {
2874 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2875 	      if( *success )
2876 	      {
2877 	         lp->lpifastmip = fastmip;
2878 	         lp->solved = FALSE;
2879 	         /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more
2880 	          * demanding setting; however, in the current code, this should have not effect. */
2881 	      }
2882 	   }
2883 	   else
2884 	      *success = FALSE;
2885 	
2886 	   return SCIP_OKAY;
2887 	}
2888 	
2889 	/** sets the SCALING setting of the LP solver */
2890 	static
2891 	SCIP_RETCODE lpSetScaling(
2892 	   SCIP_LP*              lp,                 /**< current LP data */
2893 	   int                   scaling,            /**< new SCALING setting */
2894 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2895 	   )
2896 	{
2897 	   assert(lp != NULL);
2898 	   assert(success != NULL);
2899 	
2900 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_SCALING, lp->lpiscaling) );
2901 	
2902 	   if( scaling != lp->lpiscaling )
2903 	   {
2904 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2905 	      if( *success )
2906 	         lp->lpiscaling = scaling;
2907 	   }
2908 	   else
2909 	      *success = FALSE;
2910 	
2911 	   return SCIP_OKAY;
2912 	}
2913 	
2914 	/** sets the number of THREADS  of the LP solver */
2915 	static
2916 	SCIP_RETCODE lpSetThreads(
2917 	   SCIP_LP*              lp,                 /**< current LP data */
2918 	   int                   threads,            /**< new number of threads used to solve the LP */
2919 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2920 	   )
2921 	{
2922 	   assert(lp != NULL);
2923 	   assert(success != NULL);
2924 	
2925 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_THREADS, lp->lpithreads) );
2926 	
2927 	   if( threads != lp->lpithreads )
2928 	   {
2929 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2930 	      if( *success )
2931 	         lp->lpithreads = threads;
2932 	   }
2933 	   else
2934 	      *success = FALSE;
2935 	
2936 	   return SCIP_OKAY;
2937 	}
2938 	
2939 	/** sets the PRESOLVING setting of the LP solver */
2940 	static
2941 	SCIP_RETCODE lpSetPresolving(
2942 	   SCIP_LP*              lp,                 /**< current LP data */
2943 	   SCIP_Bool             presolving,         /**< new PRESOLVING setting */
2944 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2945 	   )
2946 	{
2947 	   assert(lp != NULL);
2948 	   assert(success != NULL);
2949 	
2950 	   SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_PRESOLVING, lp->lpipresolving) );
2951 	
2952 	   if( presolving != lp->lpipresolving )
2953 	   {
2954 	      SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2955 	      if( *success )
2956 	         lp->lpipresolving = presolving;
2957 	   }
2958 	   else
2959 	      *success = FALSE;
2960 	
2961 	   return SCIP_OKAY;
2962 	}
2963 	
2964 	/** sets the ROWREPSWITCH setting of the LP solver */
2965 	static
2966 	SCIP_RETCODE lpSetRowrepswitch(
2967 	   SCIP_LP*              lp,                 /**< current LP data */
2968 	   SCIP_Real             rowrepswitch,       /**< new ROWREPSWITCH value */
2969 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
2970 	   )
2971 	{
2972 	   assert(lp != NULL);
2973 	   assert(success != NULL);
2974 	
2975 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, lp->lpirowrepswitch) );
2976 	
2977 	   if( rowrepswitch != lp->lpirowrepswitch )  /*lint !e777*/
2978 	   {
2979 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2980 	      if( *success )
2981 	         lp->lpirowrepswitch = rowrepswitch;
2982 	   }
2983 	   else
2984 	      *success = FALSE;
2985 	
2986 	   return SCIP_OKAY;
2987 	}
2988 	
2989 	/** sets the iteration limit of the LP solver */
2990 	static
2991 	SCIP_RETCODE lpSetIterationLimit(
2992 	   SCIP_LP*              lp,                 /**< current LP data */
2993 	   int                   itlim               /**< maximal number of LP iterations to perform, or -1 for no limit */
2994 	   )
2995 	{
2996 	   SCIP_Bool success;
2997 	
2998 	   assert(lp != NULL);
2999 	   assert(itlim >= -1);
3000 	
3001 	   if( itlim == -1 )
3002 	      itlim = INT_MAX;
3003 	
3004 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_LPITLIM, lp->lpiitlim) );
3005 	
3006 	   if( itlim != lp->lpiitlim )
3007 	   {
3008 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
3009 	      if( success )
3010 	      {
3011 	         if( itlim > lp->lpiitlim )
3012 	         {
3013 	            /* mark the current solution invalid */
3014 	            lp->solved = FALSE;
3015 	            lp->lpobjval = SCIP_INVALID;
3016 	            lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
3017 	         }
3018 	         lp->lpiitlim = itlim;
3019 	      }
3020 	   }
3021 	
3022 	   return SCIP_OKAY;
3023 	}
3024 	
3025 	/** sets the pricing strategy of the LP solver */
3026 	static
3027 	SCIP_RETCODE lpSetPricing(
3028 	   SCIP_LP*              lp,                 /**< current LP data */
3029 	   SCIP_PRICING          pricing             /**< pricing strategy */
3030 	   )
3031 	{
3032 	   SCIP_Bool success;
3033 	
3034 	   assert(lp != NULL);
3035 	
3036 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_PRICING, (int)lp->lpipricing) );
3037 	
3038 	   if( pricing != lp->lpipricing )
3039 	   {
3040 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
3041 	      if( success )
3042 	         lp->lpipricing = pricing;
3043 	   }
3044 	
3045 	   return SCIP_OKAY;
3046 	}
3047 	
3048 	/** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
3049 	static
3050 	SCIP_RETCODE lpSetPricingChar(
3051 	   SCIP_LP*              lp,                 /**< current LP data */
3052 	   char                  pricingchar         /**< character representing the pricing strategy */
3053 	   )
3054 	{
3055 	   SCIP_PRICING pricing;
3056 	
3057 	   switch( pricingchar )
3058 	   {
3059 	   case 'l':
3060 	      pricing = SCIP_PRICING_LPIDEFAULT;
3061 	      break;
3062 	   case 'a':
3063 	      pricing = SCIP_PRICING_AUTO;
3064 	      break;
3065 	   case 'f':
3066 	      pricing = SCIP_PRICING_FULL;
3067 	      break;
3068 	   case 'p':
3069 	      pricing = SCIP_PRICING_PARTIAL;
3070 	      break;
3071 	   case 's':
3072 	      pricing = SCIP_PRICING_STEEP;
3073 	      break;
3074 	   case 'q':
3075 	      pricing = SCIP_PRICING_STEEPQSTART;
3076 	      break;
3077 	   case 'd':
3078 	      pricing = SCIP_PRICING_DEVEX;
3079 	      break;
3080 	   default:
3081 	      SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
3082 	      return SCIP_INVALIDDATA;
3083 	   }
3084 	
3085 	   SCIP_CALL( lpSetPricing(lp, pricing) );
3086 	
3087 	   return SCIP_OKAY;
3088 	}
3089 	
3090 	/** sets the verbosity of the LP solver */
3091 	static
3092 	SCIP_RETCODE lpSetLPInfo(
3093 	   SCIP_LP*              lp,                 /**< current LP data */
3094 	   SCIP_Bool             lpinfo              /**< should the LP solver display status messages? */
3095 	   )
3096 	{
3097 	   SCIP_Bool success;
3098 	
3099 	   assert(lp != NULL);
3100 	
3101 	   SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_LPINFO, lp->lpilpinfo) );
3102 	
3103 	   if( lpinfo != lp->lpilpinfo )
3104 	   {
3105 	      SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3106 	      if( success )
3107 	         lp->lpilpinfo = lpinfo;
3108 	   }
3109 	
3110 	   return SCIP_OKAY;
3111 	}
3112 	
3113 	/** sets the CONDITIONLIMIT setting of the LP solver */
3114 	static
3115 	SCIP_RETCODE lpSetConditionLimit(
3116 	   SCIP_LP*              lp,                 /**< current LP data */
3117 	   SCIP_Real             condlimit,          /**< new CONDITIONLIMIT value */
3118 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3119 	   )
3120 	{
3121 	   assert(lp != NULL);
3122 	   assert(success != NULL);
3123 	
3124 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, lp->lpiconditionlimit) );
3125 	
3126 	   if( condlimit != lp->lpiconditionlimit )  /*lint !e777*/
3127 	   {
3128 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3129 	      if( *success )
3130 	         lp->lpiconditionlimit = condlimit;
3131 	   }
3132 	   else
3133 	      *success = FALSE;
3134 	
3135 	   return SCIP_OKAY;
3136 	}
3137 	
3138 	/** sets the MARKOWITZ setting of the LP solver */
3139 	static
3140 	SCIP_RETCODE lpSetMarkowitz(
3141 	   SCIP_LP*              lp,                 /**< current LP data */
3142 	   SCIP_Real             threshhold,         /**< new MARKOWITZ value */
3143 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3144 	   )
3145 	{
3146 	   assert(lp != NULL);
3147 	   assert(success != NULL);
3148 	
3149 	   SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_MARKOWITZ, lp->lpimarkowitz) );
3150 	
3151 	   if( threshhold != lp->lpimarkowitz )  /*lint !e777*/
3152 	   {
3153 	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) );
3154 	      if( *success )
3155 	         lp->lpimarkowitz = threshhold;
3156 	   }
3157 	   else
3158 	      *success = FALSE;
3159 	
3160 	   return SCIP_OKAY;
3161 	}
3162 	
3163 	/** sets the type of timer of the LP solver */
3164 	static
3165 	SCIP_RETCODE lpSetTiming(
3166 	   SCIP_LP*              lp,                 /**< current LP data */
3167 	   SCIP_CLOCKTYPE        timing,             /**< new timing value */
3168 	   SCIP_Bool             enabled,            /**< is timing enabled? */
3169 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3170 	   )
3171 	{
3172 	   int lptiming;
3173 	
3174 	   assert(lp != NULL);
3175 	   assert(success != NULL);
3176 	   assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/
3177 	
3178 	   SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_TIMING, lp->lpitiming) );
3179 	
3180 	   if( !enabled )
3181 	      lptiming = 0;
3182 	   else
3183 	      lptiming = (int) timing;
3184 	
3185 	   if( lptiming != lp->lpitiming )  /*lint !e777*/
3186 	   {
3187 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3188 	      if( *success )
3189 	         lp->lpitiming = lptiming;
3190 	   }
3191 	   else
3192 	      *success = FALSE;
3193 	
3194 	   return SCIP_OKAY;
3195 	}
3196 	
3197 	/** sets the initial random seed of the LP solver */
3198 	static
3199 	SCIP_RETCODE lpSetRandomseed(
3200 	   SCIP_LP*              lp,                 /**< current LP data */
3201 	   int                   randomseed,         /**< new initial random seed */
3202 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3203 	   )
3204 	{
3205 	   assert(lp != NULL);
3206 	   assert(success != NULL);
3207 	
3208 	   /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */
3209 	
3210 	   if( randomseed == 0 )
3211 	   {
3212 	      lp->lpirandomseed = randomseed;
3213 	      *success = TRUE;
3214 	   }
3215 	   else if( randomseed != lp->lpirandomseed )  /*lint !e777*/
3216 	   {
3217 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) );
3218 	      if( *success )
3219 	         lp->lpirandomseed = randomseed;
3220 	   }
3221 	   else
3222 	      *success = FALSE;
3223 	
3224 	   return SCIP_OKAY;
3225 	}
3226 	
3227 	/** sets the LP solution polishing method */
3228 	static
3229 	SCIP_RETCODE lpSetSolutionPolishing(
3230 	   SCIP_LP*              lp,                 /**< current LP data */
3231 	   SCIP_Bool             polishing,          /**< LP solution polishing activated (0: disabled, 1: enabled) */
3232 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3233 	   )
3234 	{
3235 	   assert(lp != NULL);
3236 	   assert(success != NULL);
3237 	
3238 	   if( polishing != lp->lpisolutionpolishing )
3239 	   {
3240 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) );
3241 	      if( *success )
3242 	         lp->lpisolutionpolishing = polishing;
3243 	   }
3244 	   else
3245 	      *success = FALSE;
3246 	
3247 	   return SCIP_OKAY;
3248 	}
3249 	
3250 	/** sets the LP refactorization interval */
3251 	static
3252 	SCIP_RETCODE lpSetRefactorInterval(
3253 	   SCIP_LP*              lp,                 /**< current LP data */
3254 	   int                   refactor,           /**< LP refactorization interval (0: automatic) */
3255 	   SCIP_Bool*            success             /**< pointer to store whether the parameter was successfully changed */
3256 	   )
3257 	{
3258 	   assert(lp != NULL);
3259 	   assert(success != NULL);
3260 	
3261 	   if( refactor != lp->lpirefactorinterval )
3262 	   {
3263 	      SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) );
3264 	      if( *success )
3265 	         lp->lpirefactorinterval = refactor;
3266 	   }
3267 	   else
3268 	      *success = FALSE;
3269 	
3270 	   return SCIP_OKAY;
3271 	}
3272 	
3273 	
3274 	/*
3275 	 * Column methods
3276 	 */
3277 	
3278 	/** creates an LP column */
3279 	SCIP_RETCODE SCIPcolCreate(
3280 	   SCIP_COL**            col,                /**< pointer to column data */
3281 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3282 	   SCIP_SET*             set,                /**< global SCIP settings */
3283 	   SCIP_STAT*            stat,               /**< problem statistics */
3284 	   SCIP_VAR*             var,                /**< variable, this column represents */
3285 	   int                   len,                /**< number of nonzeros in the column */
3286 	   SCIP_ROW**            rows,               /**< array with rows of column entries */
3287 	   SCIP_Real*            vals,               /**< array with coefficients of column entries */
3288 	   SCIP_Bool             removable           /**< should the column be removed from the LP due to aging or cleanup? */
3289 	   )
3290 	{
3291 	   int i;
3292 	
3293 	   assert(col != NULL);
3294 	   assert(blkmem != NULL);
3295 	   assert(set != NULL);
3296 	   assert(stat != NULL);
3297 	   assert(var != NULL);
3298 	   assert(len >= 0);
3299 	   assert(len == 0 || (rows != NULL && vals != NULL));
3300 	
3301 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3302 	
3303 	   if( len > 0 )
3304 	   {
3305 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3306 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3307 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3308 	
3309 	      for( i = 0; i < len; ++i )
3310 	      {
3311 	         assert(rows[i] != NULL);
3312 	         assert(!SCIPsetIsZero(set, vals[i]));
3313 	         (*col)->linkpos[i] = -1;
3314 	      }
3315 	   }
3316 	   else
3317 	   {
3318 	      (*col)->rows = NULL;
3319 	      (*col)->vals = NULL;
3320 	      (*col)->linkpos = NULL;
3321 	   }
3322 	
3323 	   (*col)->var = var;
3324 	   (*col)->obj = SCIPvarGetObj(var);
3325 	   (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3326 	   (*col)->lb = SCIPvarGetLbLocal(var);
3327 	   (*col)->ub = SCIPvarGetUbLocal(var);
3328 	   (*col)->flushedobj = 0.0;
3329 	   (*col)->flushedlb = 0.0;
3330 	   (*col)->flushedub = 0.0;
3331 	   (*col)->index = stat->ncolidx;
3332 	   SCIPstatIncrement(stat, set, ncolidx);
3333 	   (*col)->size = len;
3334 	   (*col)->len = len;
3335 	   (*col)->nlprows = 0;
3336 	   (*col)->nunlinked = len;
3337 	   (*col)->lppos = -1;
3338 	   (*col)->lpipos = -1;
3339 	   (*col)->lpdepth = -1;
3340 	   (*col)->primsol = 0.0;
3341 	   (*col)->redcost = SCIP_INVALID;
3342 	   (*col)->farkascoef = SCIP_INVALID;
3343 	   (*col)->minprimsol = (*col)->ub;
3344 	   (*col)->maxprimsol = (*col)->lb;
3345 	   (*col)->sbdown = SCIP_INVALID;
3346 	   (*col)->sbup = SCIP_INVALID;
3347 	   (*col)->sbsolval  = SCIP_INVALID;
3348 	   (*col)->sblpobjval = SCIP_INVALID;
3349 	   (*col)->sbnode = -1;
3350 	   (*col)->validredcostlp = -1;
3351 	   (*col)->validfarkaslp = -1;
3352 	   (*col)->validsblp = -1;
3353 	   (*col)->sbitlim = -1;
3354 	   (*col)->nsbcalls = 0;
3355 	   (*col)->age = 0;
3356 	   (*col)->obsoletenode = -1;
3357 	   (*col)->var_probindex = SCIPvarGetProbindex(var);
3358 	   (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3359 	   (*col)->lprowssorted = TRUE;
3360 	   (*col)->nonlprowssorted = (len <= 1);
3361 	   (*col)->objchanged = FALSE;
3362 	   (*col)->lbchanged = FALSE;
3363 	   (*col)->ubchanged = FALSE;
3364 	   (*col)->coefchanged = FALSE;
3365 	   (*col)->integral = SCIPvarIsIntegral(var);
3366 	   (*col)->removable = removable;
3367 	   (*col)->sbdownvalid = FALSE;
3368 	   (*col)->sbupvalid = FALSE;
3369 	   (*col)->lazylb = SCIPvarGetLbLazy(var);
3370 	   (*col)->lazyub = SCIPvarGetUbLazy(var);
3371 	   (*col)->storedsolvals = NULL;
3372 	
3373 	   return SCIP_OKAY;
3374 	}
3375 	
3376 	/** frees an LP column */
3377 	SCIP_RETCODE SCIPcolFree(
3378 	   SCIP_COL**            col,                /**< pointer to LP column */
3379 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3380 	   SCIP_SET*             set,                /**< global SCIP settings */
3381 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3382 	   SCIP_LP*              lp                  /**< current LP data */
3383 	   )
3384 	{
3385 	   assert(blkmem != NULL);
3386 	   assert(col != NULL);
3387 	   assert(*col != NULL);
3388 	   assert((*col)->var != NULL);
3389 	   assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3390 	   assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3391 	   assert((*col)->lppos == -1);
3392 	   assert((*col)->lpipos == -1);
3393 	
3394 	   /* remove column indices from corresponding rows */
3395 	   SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3396 	
3397 	   BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3398 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3399 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3400 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3401 	   BMSfreeBlockMemory(blkmem, col);
3402 	
3403 	   return SCIP_OKAY;
3404 	}
3405 	
3406 	/** output column to file stream */
3407 	void SCIPcolPrint(
3408 	   SCIP_COL*             col,                /**< LP column */
3409 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
3410 	   FILE*                 file                /**< output file (or NULL for standard output) */
3411 	   )
3412 	{
3413 	   int r;
3414 	
3415 	   assert(col != NULL);
3416 	   assert(col->var != NULL);
3417 	
3418 	   /* print bounds */
3419 	   SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3420 	
3421 	   /* print coefficients */
3422 	   if( col->len == 0 )
3423 	      SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3424 	   for( r = 0; r < col->len; ++r )
3425 	   {
3426 	      assert(col->rows[r] != NULL);
3427 	      assert(col->rows[r]->name != NULL);
3428 	      SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3429 	   }
3430 	   SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3431 	}
3432 	
3433 	/** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3434 	 */
3435 	void SCIPcolSort(
3436 	   SCIP_COL*             col                 /**< column to be sorted */
3437 	   )
3438 	{
3439 	   /* sort LP rows */
3440 	   colSortLP(col);
3441 	
3442 	   /* sort non-LP rows */
3443 	   colSortNonLP(col);
3444 	}
3445 	
3446 	/** adds a previously non existing coefficient to an LP column */
3447 	SCIP_RETCODE SCIPcolAddCoef(
3448 	   SCIP_COL*             col,                /**< LP column */
3449 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3450 	   SCIP_SET*             set,                /**< global SCIP settings */
3451 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3452 	   SCIP_LP*              lp,                 /**< current LP data */
3453 	   SCIP_ROW*             row,                /**< LP row */
3454 	   SCIP_Real             val                 /**< value of coefficient */
3455 	   )
3456 	{
3457 	   assert(lp != NULL);
3458 	   assert(!lp->diving);
3459 	
3460 	   SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3461 	
3462 	   checkLinks(lp);
3463 	
3464 	   return SCIP_OKAY;
3465 	}
3466 	
3467 	/** deletes existing coefficient from column */
3468 	SCIP_RETCODE SCIPcolDelCoef(
3469 	   SCIP_COL*             col,                /**< column to be changed */
3470 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3471 	   SCIP_SET*             set,                /**< global SCIP settings */
3472 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3473 	   SCIP_LP*              lp,                 /**< current LP data */
3474 	   SCIP_ROW*             row                 /**< coefficient to be deleted */
3475 	   )
3476 	{
3477 	   int pos;
3478 	
3479 	   assert(col != NULL);
3480 	   assert(col->var != NULL);
3481 	   assert(lp != NULL);
3482 	   assert(!lp->diving);
3483 	   assert(row != NULL);
3484 	
3485 	   /* search the position of the row in the column's row vector */
3486 	   pos = colSearchCoef(col, row);
3487 	   if( pos == -1 )
3488 	   {
3489 	      SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3490 	      return SCIP_INVALIDDATA;
3491 	   }
3492 	   assert(0 <= pos && pos < col->len);
3493 	   assert(col->rows[pos] == row);
3494 	
3495 	   /* if row knows of the column, remove the column from the row's col vector */
3496 	   if( col->linkpos[pos] >= 0 )
3497 	   {
3498 	      assert(row->cols[col->linkpos[pos]] == col);
3499 	      assert(row->cols_index[col->linkpos[pos]] == col->index);
3500 	      assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3501 	      SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3502 	   }
3503 	
3504 	   /* delete the row from the column's row vector */
3505 	   SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3506 	
3507 	   checkLinks(lp);
3508 	
3509 	   return SCIP_OKAY;
3510 	}
3511 	
3512 	/** changes or adds a coefficient to an LP column */
3513 	SCIP_RETCODE SCIPcolChgCoef(
3514 	   SCIP_COL*             col,                /**< LP column */
3515 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3516 	   SCIP_SET*             set,                /**< global SCIP settings */
3517 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3518 	   SCIP_LP*              lp,                 /**< current LP data */
3519 	   SCIP_ROW*             row,                /**< LP row */
3520 	   SCIP_Real             val                 /**< value of coefficient */
3521 	   )
3522 	{
3523 	   int pos;
3524 	
3525 	   assert(col != NULL);
3526 	   assert(lp != NULL);
3527 	   assert(!lp->diving);
3528 	   assert(row != NULL);
3529 	
3530 	   /* search the position of the row in the column's row vector */
3531 	   pos = colSearchCoef(col, row);
3532 	
3533 	   /* check, if row already exists in the column's row vector */
3534 	   if( pos == -1 )
3535 	   {
3536 	      /* add previously not existing coefficient */
3537 	      SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3538 	   }
3539 	   else
3540 	   {
3541 	      /* modify already existing coefficient */
3542 	      assert(0 <= pos && pos < col->len);
3543 	      assert(col->rows[pos] == row);
3544 	
3545 	      /* if row knows of the column, change the corresponding coefficient in the row */
3546 	      if( col->linkpos[pos] >= 0 )
3547 	      {
3548 	         assert(row->cols[col->linkpos[pos]] == col);
3549 	         assert(row->cols_index[col->linkpos[pos]] == col->index);
3550 	         assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3551 	         SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3552 	      }
3553 	
3554 	      /* change the coefficient in the column */
3555 	      SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3556 	   }
3557 	
3558 	   checkLinks(lp);
3559 	
3560 	   return SCIP_OKAY;
3561 	}
3562 	
3563 	/** increases value of an existing or non-existing coefficient in an LP column */
3564 	SCIP_RETCODE SCIPcolIncCoef(
3565 	   SCIP_COL*             col,                /**< LP column */
3566 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3567 	   SCIP_SET*             set,                /**< global SCIP settings */
3568 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3569 	   SCIP_LP*              lp,                 /**< current LP data */
3570 	   SCIP_ROW*             row,                /**< LP row */
3571 	   SCIP_Real             incval              /**< value to add to the coefficient */
3572 	   )
3573 	{
3574 	   int pos;
3575 	
3576 	   assert(col != NULL);
3577 	   assert(lp != NULL);
3578 	   assert(!lp->diving);
3579 	   assert(row != NULL);
3580 	
3581 	   if( SCIPsetIsZero(set, incval) )
3582 	      return SCIP_OKAY;
3583 	
3584 	   /* search the position of the row in the column's row vector */
3585 	   pos = colSearchCoef(col, row);
3586 	
3587 	   /* check, if row already exists in the column's row vector */
3588 	   if( pos == -1 )
3589 	   {
3590 	      /* add previously not existing coefficient */
3591 	      SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3592 	   }
3593 	   else
3594 	   {
3595 	      /* modify already existing coefficient */
3596 	      assert(0 <= pos && pos < col->len);
3597 	      assert(col->rows[pos] == row);
3598 	
3599 	      /* if row knows of the column, change the corresponding coefficient in the row */
3600 	      if( col->linkpos[pos] >= 0 )
3601 	      {
3602 	         assert(row->cols[col->linkpos[pos]] == col);
3603 	         assert(row->cols_index[col->linkpos[pos]] == col->index);
3604 	         assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3605 	         SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3606 	      }
3607 	
3608 	      /* change the coefficient in the column */
3609 	      SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3610 	   }
3611 	
3612 	   checkLinks(lp);
3613 	
3614 	   return SCIP_OKAY;
3615 	}
3616 	
3617 	/** insert column in the chgcols list (if not already there) */
3618 	static
3619 	SCIP_RETCODE insertColChgcols(
3620 	   SCIP_COL*             col,                /**< LP column to change */
3621 	   SCIP_SET*             set,                /**< global SCIP settings */
3622 	   SCIP_LP*              lp                  /**< current LP data */
3623 	   )
3624 	{
3625 	   if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3626 	   {
3627 	      SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3628 	      lp->chgcols[lp->nchgcols] = col;
3629 	      lp->nchgcols++;
3630 	   }
3631 	
3632 	   /* mark the current LP unflushed */
3633 	   lp->flushed = FALSE;
3634 	
3635 	   return SCIP_OKAY;
3636 	}
3637 	
3638 	/** Is the new value reliable or may we have cancellation?
3639 	 *
3640 	 *  @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3641 	 *  cancellations which can occur during increasing the oldvalue to the newvalue
3642 	 */
3643 	static
3644 	SCIP_Bool isNewValueUnreliable(
3645 	   SCIP_SET*             set,                /**< global SCIP settings */
3646 	   SCIP_Real             newvalue,           /**< new value */
3647 	   SCIP_Real             oldvalue            /**< old reliable value */
3648 	   )
3649 	{
3650 	   SCIP_Real quotient;
3651 	
3652 	   assert(set != NULL);
3653 	   assert(oldvalue != SCIP_INVALID);  /*lint !e777*/
3654 	
3655 	   quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3656 	
3657 	   return SCIPsetIsZero(set, quotient);
3658 	}
3659 	
3660 	/** update norms of objective function vector */
3661 	static
3662 	void lpUpdateObjNorms(
3663 	   SCIP_LP*              lp,                 /**< current LP data */
3664 	   SCIP_SET*             set,                /**< global SCIP settings */
3665 	   SCIP_Real             oldobj,             /**< old objective value of variable */
3666 	   SCIP_Real             newobj              /**< new objective value of variable */
3667 	   )
3668 	{
3669 	   if( REALABS(newobj) != REALABS(oldobj) )   /*lint !e777*/
3670 	   {
3671 	      if( !lp->objsqrnormunreliable )
3672 	      {
3673 	         SCIP_Real oldvalue;
3674 	
3675 	         oldvalue = lp->objsqrnorm;
3676 	         lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3677 	
3678 	         /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3679 	         if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3680 	            lp->objsqrnormunreliable = TRUE;
3681 	         else
3682 	         {
3683 	            assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3684 	
3685 	            /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3686 	            lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3687 	
3688 	            assert(lp->objsqrnorm >= 0.0);
3689 	         }
3690 	      }
3691 	
3692 	      lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3693 	      lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3694 	   }
3695 	}
3696 	
3697 	/** changes objective value of column */
3698 	SCIP_RETCODE SCIPcolChgObj(
3699 	   SCIP_COL*             col,                /**< LP column to change */
3700 	   SCIP_SET*             set,                /**< global SCIP settings */
3701 	   SCIP_LP*              lp,                 /**< current LP data */
3702 	   SCIP_Real             newobj              /**< new objective value */
3703 	   )
3704 	{
3705 	   assert(col != NULL);
3706 	   assert(col->var != NULL);
3707 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3708 	   assert(SCIPvarGetCol(col->var) == col);
3709 	   assert(lp != NULL);
3710 	
3711 	   SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3712 	
3713 	   /* only add actual changes */
3714 	   if( !SCIPsetIsEQ(set, col->obj, newobj) )
3715 	   {
3716 	      /* only variables with a real position in the LPI can be inserted */
3717 	      if( col->lpipos >= 0 )
3718 	      {
3719 	         /* insert column in the chgcols list (if not already there) */
3720 	         SCIP_CALL( insertColChgcols(col, set, lp) );
3721 	
3722 	         /* mark objective value change in the column */
3723 	         col->objchanged = TRUE;
3724 	
3725 	         assert(lp->nchgcols > 0);
3726 	      }
3727 	      /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3728 	       * LP and the LP has to be flushed
3729 	       */
3730 	      else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3731 	         || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3732 	      {
3733 	         /* mark the LP unflushed */
3734 	         lp->flushed = FALSE;
3735 	      }
3736 	   }
3737 	
3738 	   /* store new objective function value */
3739 	   col->obj = newobj;
3740 	
3741 	   /* update original objective value, as long as we are not in diving or probing and changed objective values */
3742 	   if( !lp->divingobjchg )
3743 	   {
3744 	      SCIP_Real oldobj = col->unchangedobj;
3745 	
3746 	      assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3747 	      col->unchangedobj = newobj;
3748 	
3749 	      /* update the objective function vector norms */
3750 	      lpUpdateObjNorms(lp, set, oldobj, newobj);
3751 	   }
3752 	
3753 	   return SCIP_OKAY;
3754 	}
3755 	
3756 	/** changes lower bound of column */
3757 	SCIP_RETCODE SCIPcolChgLb(
3758 	   SCIP_COL*             col,                /**< LP column to change */
3759 	   SCIP_SET*             set,                /**< global SCIP settings */
3760 	   SCIP_LP*              lp,                 /**< current LP data */
3761 	   SCIP_Real             newlb               /**< new lower bound value */
3762 	   )
3763 	{
3764 	   assert(col != NULL);
3765 	   assert(col->var != NULL);
3766 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3767 	   assert(SCIPvarGetCol(col->var) == col);
3768 	   assert(lp != NULL);
3769 	
3770 	   SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3771 	
3772 	   /* only add actual changes */
3773 	   if( !SCIPsetIsEQ(set, col->lb, newlb) )
3774 	   {
3775 	      /* only variables with a real position in the LPI can be inserted */
3776 	      if( col->lpipos >= 0 )
3777 	      {
3778 	         /* insert column in the chgcols list (if not already there) */
3779 	         SCIP_CALL( insertColChgcols(col, set, lp) );
3780 	
3781 	         /* mark bound change in the column */
3782 	         col->lbchanged = TRUE;
3783 	
3784 	         assert(lp->nchgcols > 0);
3785 	      }
3786 	      /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3787 	       * flushed
3788 	       */
3789 	      else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3790 	      {
3791 	         /* mark the LP unflushed */
3792 	         lp->flushed = FALSE;
3793 	      }
3794 	   }
3795 	
3796 	   col->lb = newlb;
3797 	
3798 	   return SCIP_OKAY;
3799 	}
3800 	
3801 	/** changes upper bound of column */
3802 	SCIP_RETCODE SCIPcolChgUb(
3803 	   SCIP_COL*             col,                /**< LP column to change */
3804 	   SCIP_SET*             set,                /**< global SCIP settings */
3805 	   SCIP_LP*              lp,                 /**< current LP data */
3806 	   SCIP_Real             newub               /**< new upper bound value */
3807 	   )
3808 	{
3809 	   assert(col != NULL);
3810 	   assert(col->var != NULL);
3811 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3812 	   assert(SCIPvarGetCol(col->var) == col);
3813 	   assert(lp != NULL);
3814 	
3815 	   SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3816 	
3817 	   /* only add actual changes */
3818 	   if( !SCIPsetIsEQ(set, col->ub, newub) )
3819 	   {
3820 	      /* only variables with a real position in the LPI can be inserted */
3821 	      if( col->lpipos >= 0 )
3822 	      {
3823 	         /* insert column in the chgcols list (if not already there) */
3824 	         SCIP_CALL( insertColChgcols(col, set, lp) );
3825 	
3826 	         /* mark bound change in the column */
3827 	         col->ubchanged = TRUE;
3828 	
3829 	         assert(lp->nchgcols > 0);
3830 	      }
3831 	      /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3832 	       * flushed
3833 	       */
3834 	      else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3835 	      {
3836 	         /* mark the LP unflushed */
3837 	         lp->flushed = FALSE;
3838 	      }
3839 	   }
3840 	
3841 	   col->ub = newub;
3842 	
3843 	   return SCIP_OKAY;
3844 	}
3845 	
3846 	/** calculates the reduced costs of a column using the given dual solution vector */
3847 	SCIP_Real SCIPcolCalcRedcost(
3848 	   SCIP_COL*             col,                /**< LP column */
3849 	   SCIP_Real*            dualsol             /**< dual solution vector for current LP rows */
3850 	   )
3851 	{
3852 	   SCIP_ROW* row;
3853 	   SCIP_Real redcost;
3854 	   int i;
3855 	
3856 	   assert(col != NULL);
3857 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3858 	   assert(SCIPvarGetCol(col->var) == col);
3859 	   assert(dualsol != NULL);
3860 	
3861 	   redcost = col->obj;
3862 	   for( i = 0; i < col->nlprows; ++i )
3863 	   {
3864 	      row = col->rows[i];
3865 	      assert(row != NULL);
3866 	      assert(row->lppos >= 0);
3867 	      redcost -= col->vals[i] * dualsol[row->lppos];
3868 	   }
3869 	
3870 	   if( col->nunlinked > 0 )
3871 	   {
3872 	      for( i = col->nlprows; i < col->len; ++i )
3873 	      {
3874 	         row = col->rows[i];
3875 	         assert(row != NULL);
3876 	         assert(row->lppos == -1 || col->linkpos[i] == -1);
3877 	         if( row->lppos >= 0 )
3878 	            redcost -= col->vals[i] * dualsol[row->lppos];
3879 	      }
3880 	   }
3881 	#ifndef NDEBUG
3882 	   else
3883 	   {
3884 	      for( i = col->nlprows; i < col->len; ++i )
3885 	      {
3886 	         row = col->rows[i];
3887 	         assert(row != NULL);
3888 	         assert(row->lppos == -1);
3889 	         assert(col->linkpos[i] >= 0);
3890 	      }
3891 	   }
3892 	#endif
3893 	
3894 	   return redcost;
3895 	}
3896 	
3897 	/** calculates the reduced costs of a column using the dual solution stored in the rows */
3898 	static
3899 	SCIP_Real colCalcInternalRedcost(
3900 	   SCIP_COL*             col                 /**< LP column */
3901 	   )
3902 	{
3903 	   SCIP_ROW* row;
3904 	   SCIP_Real redcost;
3905 	   int i;
3906 	
3907 	   assert(col != NULL);
3908 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
3909 	   assert(SCIPvarGetCol(col->var) == col);
3910 	
3911 	   redcost = col->obj;
3912 	   for( i = 0; i < col->nlprows; ++i )
3913 	   {
3914 	      row = col->rows[i];
3915 	      assert(row != NULL);
3916 	      assert(row->dualsol != SCIP_INVALID);  /*lint !e777*/
3917 	      assert(row->lppos >= 0);
3918 	      assert(col->linkpos[i] >= 0);
3919 	      redcost -= col->vals[i] * row->dualsol;
3920 	   }
3921 	
3922 	   if( col->nunlinked > 0 )
3923 	   {
3924 	      for( i = col->nlprows; i < col->len; ++i )
3925 	      {
3926 	         row = col->rows[i];
3927 	         assert(row != NULL);
3928 	         assert(row->lppos >= 0 || row->dualsol == 0.0);
3929 	         assert(row->lppos == -1 || col->linkpos[i] == -1);
3930 	         if( row->lppos >= 0 )
3931 	            redcost -= col->vals[i] * row->dualsol;
3932 	      }
3933 	   }
3934 	#ifndef NDEBUG
3935 	   else
3936 	   {
3937 	      for( i = col->nlprows; i < col->len; ++i )
3938 	      {
3939 	         row = col->rows[i];
3940 	         assert(row != NULL);
3941 	         assert(row->dualsol == 0.0);
3942 	         assert(row->lppos == -1);
3943 	         assert(col->linkpos[i] >= 0);
3944 	      }
3945 	   }
3946 	#endif
3947 	
3948 	   return redcost;
3949 	}
3950 	
3951 	/** gets the reduced costs of a column in last LP or after recalculation */
3952 	SCIP_Real SCIPcolGetRedcost(
3953 	   SCIP_COL*             col,                /**< LP column */
3954 	   SCIP_STAT*            stat,               /**< problem statistics */
3955 	   SCIP_LP*              lp                  /**< current LP data */
3956 	   )
3957 	{
3958 	   assert(col != NULL);
3959 	   assert(stat != NULL);
3960 	   assert(lp != NULL);
3961 	   assert(col->validredcostlp <= stat->lpcount);
3962 	   assert(lp->validsollp == stat->lpcount);
3963 	
3964 	   if( col->validredcostlp < stat->lpcount )
3965 	   {
3966 	      col->redcost = colCalcInternalRedcost(col);
3967 	      col->validredcostlp = stat->lpcount;
3968 	   }
3969 	   assert(col->validredcostlp == stat->lpcount);
3970 	   assert(col->redcost != SCIP_INVALID);  /*lint !e777*/
3971 	
3972 	   return col->redcost;
3973 	}
3974 	
3975 	/** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3976 	SCIP_Real SCIPcolGetFeasibility(
3977 	   SCIP_COL*             col,                /**< LP column */
3978 	   SCIP_SET*             set,                /**< global SCIP settings */
3979 	   SCIP_STAT*            stat,               /**< problem statistics */
3980 	   SCIP_LP*              lp                  /**< current LP data */
3981 	   )
3982 	{
3983 	   assert(col != NULL);
3984 	   assert(set != NULL);
3985 	   assert(stat != NULL);
3986 	   assert(lp != NULL);
3987 	   assert(lp->validsollp == stat->lpcount);
3988 	
3989 	   /* A column's reduced cost is defined as
3990 	    *   redcost  = obj - activity,  activity = y^T * col.   (activity = obj - redcost)
3991 	    * The activity is equal to the activity of the corresponding row in the dual LP.
3992 	    * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3993 	    * The sides of the dual row depend on the bounds of the column:
3994 	    *  - lb == ub      :  dual row is a free row with infinite sides
3995 	    *  -  0 <= lb <  ub:         activity <= obj  =>  0 <= redcost
3996 	    *  - lb <   0 <  ub:  obj <= activity <= obj  =>  0 <= redcost <= 0
3997 	    *  - lb <  ub <=  0:  obj <= activity         =>       redcost <= 0
3998 	    */
3999 	   if( SCIPsetIsEQ(set, col->lb, col->ub) )
4000 	   {
4001 	      /* dual row is free */
4002 	      return SCIPsetInfinity(set);
4003 	   }
4004 	   else
4005 	   {
4006 	      SCIP_Real redcost;
4007 	
4008 	      /* calculate reduced costs */
4009 	      redcost = SCIPcolGetRedcost(col, stat, lp);
4010 	
4011 	      if( !SCIPsetIsNegative(set, col->lb) )
4012 	      {
4013 	         /* dual row is  activity <= obj  <=>  redcost >= 0 */
4014 	         return redcost;
4015 	      }
4016 	      else if( SCIPsetIsPositive(set, col->ub) )
4017 	      {
4018 	         /* dual row is  activity == obj  <=>  redcost == 0 */
4019 	         return -REALABS(redcost);
4020 	      }
4021 	      else
4022 	      {
4023 	         /* dual row is  activity >= obj  <=>  redcost <= 0 */
4024 	         return -redcost;
4025 	      }
4026 	   }
4027 	}
4028 	
4029 	/** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
4030 	SCIP_Real SCIPcolCalcFarkasCoef(
4031 	   SCIP_COL*             col,                /**< LP column */
4032 	   SCIP_Real*            dualfarkas          /**< dense dual Farkas vector for current LP rows */
4033 	   )
4034 	{
4035 	   SCIP_ROW* row;
4036 	   SCIP_Real farkas;
4037 	   int i;
4038 	
4039 	   assert(col != NULL);
4040 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4041 	   assert(SCIPvarGetCol(col->var) == col);
4042 	   assert(dualfarkas != NULL);
4043 	
4044 	   farkas = 0.0;
4045 	   for( i = 0; i < col->nlprows; ++i )
4046 	   {
4047 	      row = col->rows[i];
4048 	      assert(row != NULL);
4049 	      assert(row->lppos >= 0);
4050 	      farkas += col->vals[i] * dualfarkas[row->lppos];
4051 	   }
4052 	
4053 	   if( col->nunlinked > 0 )
4054 	   {
4055 	      for( i = col->nlprows; i < col->len; ++i )
4056 	      {
4057 	         row = col->rows[i];
4058 	         assert(row != NULL);
4059 	         assert(row->lppos == -1 || col->linkpos[i] == -1);
4060 	         if( row->lppos >= 0 )
4061 	            farkas += col->vals[i] * dualfarkas[row->lppos];
4062 	      }
4063 	   }
4064 	#ifndef NDEBUG
4065 	   else
4066 	   {
4067 	      for( i = col->nlprows; i < col->len; ++i )
4068 	      {
4069 	         row = col->rows[i];
4070 	         assert(row != NULL);
4071 	         assert(row->lppos == -1);
4072 	         assert(col->linkpos[i] >= 0);
4073 	      }
4074 	   }
4075 	#endif
4076 	
4077 	   return farkas;
4078 	}
4079 	
4080 	/** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
4081 	static
4082 	SCIP_Real colCalcInternalFarkasCoef(
4083 	   SCIP_COL*             col                 /**< LP column */
4084 	   )
4085 	{
4086 	   SCIP_ROW* row;
4087 	   SCIP_Real farkas;
4088 	   int i;
4089 	
4090 	   assert(col != NULL);
4091 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4092 	   assert(SCIPvarGetCol(col->var) == col);
4093 	
4094 	   farkas = 0.0;
4095 	   for( i = 0; i < col->nlprows; ++i )
4096 	   {
4097 	      row = col->rows[i];
4098 	      assert(row != NULL);
4099 	      assert(row->dualfarkas != SCIP_INVALID);  /*lint !e777*/
4100 	      assert(row->lppos >= 0);
4101 	      assert(col->linkpos[i] >= 0);
4102 	      farkas += col->vals[i] * row->dualfarkas;
4103 	   }
4104 	
4105 	   if( col->nunlinked > 0 )
4106 	   {
4107 	      for( i = col->nlprows; i < col->len; ++i )
4108 	      {
4109 	         row = col->rows[i];
4110 	         assert(row != NULL);
4111 	         assert(row->lppos >= 0 || row->dualfarkas == 0.0);
4112 	         assert(row->lppos == -1 || col->linkpos[i] == -1);
4113 	         if( row->lppos >= 0 )
4114 	            farkas += col->vals[i] * row->dualfarkas;
4115 	      }
4116 	   }
4117 	#ifndef NDEBUG
4118 	   else
4119 	   {
4120 	      for( i = col->nlprows; i < col->len; ++i )
4121 	      {
4122 	         row = col->rows[i];
4123 	         assert(row != NULL);
4124 	         assert(row->dualfarkas == 0.0);
4125 	         assert(row->lppos == -1);
4126 	         assert(col->linkpos[i] >= 0);
4127 	      }
4128 	   }
4129 	#endif
4130 	
4131 	   return farkas;
4132 	}
4133 	
4134 	/** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
4135 	SCIP_Real SCIPcolGetFarkasCoef(
4136 	   SCIP_COL*             col,                /**< LP column */
4137 	   SCIP_STAT*            stat,               /**< problem statistics */
4138 	   SCIP_LP*              lp                  /**< current LP data */
4139 	   )
4140 	{
4141 	   assert(col != NULL);
4142 	   assert(stat != NULL);
4143 	   assert(lp != NULL);
4144 	   assert(col->validfarkaslp <= stat->lpcount);
4145 	   assert(lp->validfarkaslp == stat->lpcount);
4146 	
4147 	   if( col->validfarkaslp < stat->lpcount )
4148 	   {
4149 	      col->farkascoef = colCalcInternalFarkasCoef(col);
4150 	      col->validfarkaslp = stat->lpcount;
4151 	   }
4152 	   assert(col->validfarkaslp == stat->lpcount);
4153 	   assert(col->farkascoef != SCIP_INVALID);  /*lint !e777*/
4154 	
4155 	   return col->farkascoef;
4156 	}
4157 	
4158 	/** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
4159 	 *  the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
4160 	 */
4161 	SCIP_Real SCIPcolGetFarkasValue(
4162 	   SCIP_COL*             col,                /**< LP column */
4163 	   SCIP_STAT*            stat,               /**< problem statistics */
4164 	   SCIP_LP*              lp                  /**< current LP data */
4165 	   )
4166 	{
4167 	   SCIP_Real farkascoef;
4168 	
4169 	   assert(col != NULL);
4170 	
4171 	   farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
4172 	
4173 	   if( farkascoef > 0.0 )
4174 	      return col->ub * farkascoef;
4175 	   else
4176 	      return col->lb * farkascoef;
4177 	}
4178 	
4179 	/** start strong branching - call before any strong branching */
4180 	SCIP_RETCODE SCIPlpStartStrongbranch(
4181 	   SCIP_LP*              lp                  /**< LP data */
4182 	   )
4183 	{
4184 	   assert(lp != NULL);
4185 	   assert(!lp->strongbranching);
4186 	
4187 	   lp->strongbranching = TRUE;
4188 	   SCIPdebugMessage("starting strong branching ...\n");
4189 	   SCIP_CALL( SCIPlpiStartStrongbranch(lp->lpi) );
4190 	
4191 	   return SCIP_OKAY;
4192 	}
4193 	
4194 	/** end strong branching - call after any strong branching */
4195 	SCIP_RETCODE SCIPlpEndStrongbranch(
4196 	   SCIP_LP*              lp                  /**< LP data */
4197 	   )
4198 	{
4199 	   assert(lp != NULL);
4200 	   assert(lp->strongbranching);
4201 	
4202 	   lp->strongbranching = FALSE;
4203 	   SCIPdebugMessage("ending strong branching ...\n");
4204 	   SCIP_CALL( SCIPlpiEndStrongbranch(lp->lpi) );
4205 	
4206 	   return SCIP_OKAY;
4207 	}
4208 	
4209 	/** sets strong branching information for a column variable */
4210 	void SCIPcolSetStrongbranchData(
4211 	   SCIP_COL*             col,                /**< LP column */
4212 	   SCIP_SET*             set,                /**< global SCIP settings */
4213 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4214 	   SCIP_LP*              lp,                 /**< LP data */
4215 	   SCIP_Real             lpobjval,           /**< objective value of the current LP */
4216 	   SCIP_Real             primsol,            /**< primal solution value of the column in the current LP */
4217 	   SCIP_Real             sbdown,             /**< dual bound after branching column down */
4218 	   SCIP_Real             sbup,               /**< dual bound after branching column up */
4219 	   SCIP_Bool             sbdownvalid,        /**< is the returned down value a valid dual bound? */
4220 	   SCIP_Bool             sbupvalid,          /**< is the returned up value a valid dual bound? */
4221 	   SCIP_Longint          iter,               /**< total number of strong branching iterations */
4222 	   int                   itlim               /**< iteration limit applied to the strong branching call */
4223 	   )
4224 	{
4225 	   assert(col != NULL);
4226 	   assert(col->var != NULL);
4227 	   assert(SCIPcolIsIntegral(col));
4228 	   assert(SCIPvarIsIntegral(col->var));
4229 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4230 	   assert(SCIPvarGetCol(col->var) == col);
4231 	   assert(col->lpipos >= 0);
4232 	   assert(col->lppos >= 0);
4233 	   assert(set != NULL);
4234 	   assert(stat != NULL);
4235 	   assert(lp != NULL);
4236 	   assert(lp->strongbranchprobing);
4237 	   assert(col->lppos < lp->ncols);
4238 	   assert(lp->cols[col->lppos] == col);
4239 	   assert(itlim >= 1);
4240 	
4241 	   col->sblpobjval = lpobjval;
4242 	   col->sbsolval = primsol;
4243 	   col->validsblp = stat->nlps;
4244 	   col->sbnode = stat->nnodes;
4245 	
4246 	   col->sbitlim = itlim;
4247 	   col->nsbcalls++;
4248 	
4249 	   col->sbdown = MIN(sbdown, lp->cutoffbound);
4250 	   col->sbup = MIN(sbup, lp->cutoffbound);
4251 	   col->sbdownvalid = sbdownvalid;
4252 	   col->sbupvalid = sbupvalid;
4253 	
4254 	   SCIPstatIncrement(stat, set, nstrongbranchs);
4255 	   SCIPstatAdd(stat, set, nsblpiterations, iter);
4256 	   if( stat->nnodes == 1 )
4257 	   {
4258 	      SCIPstatIncrement(stat, set, nrootstrongbranchs);
4259 	      SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4260 	   }
4261 	}
4262 	
4263 	/** invalidates strong branching information for a column variable */
4264 	void SCIPcolInvalidateStrongbranchData(
4265 	   SCIP_COL*             col,                /**< LP column */
4266 	   SCIP_SET*             set,                /**< global SCIP settings */
4267 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4268 	   SCIP_LP*              lp                  /**< LP data */
4269 	   )
4270 	{
4271 	   assert(col != NULL);
4272 	   assert(col->var != NULL);
4273 	   assert(SCIPcolIsIntegral(col));
4274 	   assert(SCIPvarIsIntegral(col->var));
4275 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4276 	   assert(SCIPvarGetCol(col->var) == col);
4277 	   assert(col->lpipos >= 0);
4278 	   assert(col->lppos >= 0);
4279 	   assert(set != NULL);
4280 	   assert(stat != NULL);
4281 	   assert(lp != NULL);
4282 	   assert(lp->strongbranchprobing);
4283 	   assert(col->lppos < lp->ncols);
4284 	   assert(lp->cols[col->lppos] == col);
4285 	
4286 	   col->sbdown = SCIP_INVALID;
4287 	   col->sbup = SCIP_INVALID;
4288 	   col->sbdownvalid = FALSE;
4289 	   col->sbupvalid = FALSE;
4290 	   col->validsblp = -1;
4291 	   col->sbsolval = SCIP_INVALID;
4292 	   col->sblpobjval = SCIP_INVALID;
4293 	   col->sbnode = -1;
4294 	   col->sbitlim = -1;
4295 	}
4296 	
4297 	
4298 	/** gets strong branching information on a column variable */
4299 	SCIP_RETCODE SCIPcolGetStrongbranch(
4300 	   SCIP_COL*             col,                /**< LP column */
4301 	   SCIP_Bool             integral,           /**< should integral strong branching be performed? */
4302 	   SCIP_SET*             set,                /**< global SCIP settings */
4303 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4304 	   SCIP_PROB*            prob,               /**< problem data */
4305 	   SCIP_LP*              lp,                 /**< LP data */
4306 	   int                   itlim,              /**< iteration limit for strong branchings */
4307 	   SCIP_Bool             updatecol,          /**< should col be updated, or should it stay in its current state ? */
4308 	   SCIP_Bool             updatestat,         /**< should stat be updated, or should it stay in its current state ? */
4309 	   SCIP_Real*            down,               /**< stores dual bound after branching column down */
4310 	   SCIP_Real*            up,                 /**< stores dual bound after branching column up */
4311 	   SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
4312 	                                              *   otherwise, it can only be used as an estimate value */
4313 	   SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
4314 	                                              *   otherwise, it can only be used as an estimate value */
4315 	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
4316 	   )
4317 	{
4318 	   SCIP_Real sbdown;
4319 	   SCIP_Real sbup;
4320 	   SCIP_Bool sbdownvalid;
4321 	   SCIP_Bool sbupvalid;
4322 	   SCIP_Longint validsblp;
4323 	   SCIP_Real sbsolval;
4324 	   SCIP_Real sblpobjval;
4325 	   SCIP_Longint sbnode;
4326 	   int sbitlim;
4327 	   int nsbcalls;
4328 	
4329 	   assert(col != NULL);
4330 	   assert(col->var != NULL);
4331 	   assert(SCIPcolIsIntegral(col));
4332 	   assert(SCIPvarIsIntegral(col->var));
4333 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4334 	   assert(SCIPvarGetCol(col->var) == col);
4335 	   assert(col->primsol != SCIP_INVALID);  /*lint !e777*/
4336 	   assert(col->lpipos >= 0);
4337 	   assert(col->lppos >= 0);
4338 	   assert(set != NULL);
4339 	   assert(stat != NULL);
4340 	   assert(lp != NULL);
4341 	   assert(lp->flushed);
4342 	   assert(lp->solved);
4343 	   assert(lp->strongbranching);
4344 	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4345 	   assert(lp->validsollp == stat->lpcount);
4346 	   assert(col->lppos < lp->ncols);
4347 	   assert(lp->cols[col->lppos] == col);
4348 	   assert(itlim >= 1);
4349 	   /*   assert(down != NULL);
4350 	    *  assert(up != NULL); temporary hack for cloud branching
4351 	    */
4352 	   assert(lperror != NULL);
4353 	
4354 	   *lperror = FALSE;
4355 	
4356 	   sbdown = col->sbdown;
4357 	   sbup = col->sbup;
4358 	   sbdownvalid = col->sbdownvalid;
4359 	   sbupvalid = col->sbupvalid;
4360 	   sbitlim = col->sbitlim;
4361 	   nsbcalls = col->nsbcalls;
4362 	
4363 	   validsblp = stat->nlps;
4364 	   sbsolval = col->primsol;
4365 	   sblpobjval = SCIPlpGetObjval(lp, set, prob);
4366 	   sbnode = stat->nnodes;
4367 	   assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4368 	
4369 	   /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4370 	   if( lp->looseobjvalinf > 0 )
4371 	   {
4372 	      sbdown = -SCIPsetInfinity(set);
4373 	      sbup = -SCIPsetInfinity(set);
4374 	      sbdownvalid = FALSE;
4375 	      sbupvalid = FALSE;
4376 	   }
4377 	   else
4378 	   {
4379 	      SCIP_RETCODE retcode;
4380 	      int iter;
4381 	
4382 	      SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4383 	         SCIPvarGetName(col->var), col->primsol, itlim);
4384 	
4385 	      /* start timing */
4386 	      SCIPclockStart(stat->strongbranchtime, set);
4387 	
4388 	      /* call LPI strong branching */
4389 	      sbitlim = itlim;
4390 	      nsbcalls++;
4391 	
4392 	      sbdown = lp->lpobjval;
4393 	      sbup = lp->lpobjval;
4394 	
4395 	      if( integral )
4396 	         retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down  == NULL ? NULL : &sbdown, up  == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4397 	      else
4398 	      {
4399 	         assert( ! SCIPsetIsIntegral(set, col->primsol) );
4400 	         retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL :  &sbup, &sbdownvalid, &sbupvalid, &iter);
4401 	      }
4402 	
4403 	      /* check return code for errors */
4404 	      if( retcode == SCIP_LPERROR )
4405 	      {
4406 	         *lperror = TRUE;
4407 	         sbdown = SCIP_INVALID;
4408 	         sbup = SCIP_INVALID;
4409 	         sbdownvalid = FALSE;
4410 	         sbupvalid = FALSE;
4411 	         validsblp = -1;
4412 	         sbsolval = SCIP_INVALID;
4413 	         sblpobjval = SCIP_INVALID;
4414 	         sbnode = -1;
4415 	      }
4416 	      else
4417 	      {
4418 	         SCIP_Real looseobjval;
4419 	
4420 	         *lperror = FALSE;
4421 	         SCIP_CALL( retcode );
4422 	
4423 	         looseobjval = getFiniteLooseObjval(lp, set, prob);
4424 	         sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4425 	         sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4426 	
4427 	         /* update strong branching statistics */
4428 	         if( updatestat )
4429 	         {
4430 	            if( iter == -1 )
4431 	            {
4432 	               /* calculate average iteration number */
4433 	               iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4434 	                  : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4435 	                  : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4436 	                  : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4437 	                  : 0;
4438 	               if( iter/2 >= itlim )
4439 	                  iter = 2*itlim;
4440 	            }
4441 	            SCIPstatIncrement(stat, set, nstrongbranchs);
4442 	            SCIPstatAdd(stat, set, nsblpiterations, iter);
4443 	            if( stat->nnodes == 1 )
4444 	            {
4445 	               SCIPstatIncrement(stat, set, nrootstrongbranchs);
4446 	               SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4447 	            }
4448 	         }
4449 	      }
4450 	
4451 	      /* stop timing */
4452 	      SCIPclockStop(stat->strongbranchtime, set);
4453 	   }
4454 	   assert(*lperror || sbdown != SCIP_INVALID);  /*lint !e777*/
4455 	   assert(*lperror || sbup != SCIP_INVALID);  /*lint !e777*/
4456 	
4457 	   if( down != NULL)
4458 	      *down = sbdown;
4459 	   if( up != NULL )
4460 	      *up = sbup;
4461 	   if( downvalid != NULL )
4462 	      *downvalid = sbdownvalid;
4463 	   if( upvalid != NULL )
4464 	      *upvalid = sbupvalid;
4465 	
4466 	   if( updatecol )
4467 	   {
4468 	      col->sbdown = sbdown;
4469 	      col->sbup = sbup;
4470 	      col->sbdownvalid = sbdownvalid;
4471 	      col->sbupvalid = sbupvalid;
4472 	      col->validsblp = validsblp;
4473 	      col->sbsolval = sbsolval;
4474 	      col->sblpobjval = sblpobjval;
4475 	      col->sbnode = sbnode;
4476 	      col->sbitlim = sbitlim;
4477 	      col->nsbcalls = nsbcalls;
4478 	   }
4479 	
4480 	   return SCIP_OKAY;
4481 	}
4482 	
4483 	/** gets strong branching information on column variables */
4484 	SCIP_RETCODE SCIPcolGetStrongbranches(
4485 	   SCIP_COL**            cols,               /**< LP columns */
4486 	   int                   ncols,              /**< number of columns */
4487 	   SCIP_Bool             integral,           /**< should integral strong branching be performed? */
4488 	   SCIP_SET*             set,                /**< global SCIP settings */
4489 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4490 	   SCIP_PROB*            prob,               /**< problem data */
4491 	   SCIP_LP*              lp,                 /**< LP data */
4492 	   int                   itlim,              /**< iteration limit for strong branchings */
4493 	   SCIP_Real*            down,               /**< stores dual bounds after branching columns down */
4494 	   SCIP_Real*            up,                 /**< stores dual bounds after branching columns up */
4495 	   SCIP_Bool*            downvalid,          /**< stores whether the returned down values are valid dual bounds, or NULL;
4496 	                                              *   otherwise, they can only be used as an estimate value */
4497 	   SCIP_Bool*            upvalid,            /**< stores whether the returned up values are valid dual bounds, or NULL;
4498 	                                              *   otherwise, they can only be used as an estimate value */
4499 	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
4500 	   )
4501 	{
4502 	   SCIP_RETCODE retcode;
4503 	   SCIP_Real* sbdown;
4504 	   SCIP_Real* sbup;
4505 	   SCIP_Bool* sbdownvalid;
4506 	   SCIP_Bool* sbupvalid;
4507 	   SCIP_Real* primsols;
4508 	   SCIP_COL** subcols;
4509 	   int* lpipos;
4510 	   int* subidx;
4511 	   int nsubcols;
4512 	   int iter;
4513 	   int j;
4514 	
4515 	   assert(cols != NULL);
4516 	   assert(set != NULL);
4517 	   assert(stat != NULL);
4518 	   assert(lp != NULL);
4519 	   assert(lp->flushed);
4520 	   assert(lp->solved);
4521 	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4522 	   assert(lp->validsollp == stat->lpcount);
4523 	   assert(itlim >= 1);
4524 	   assert(down != NULL);
4525 	   assert(up != NULL);
4526 	   assert(lperror != NULL);
4527 	
4528 	   *lperror = FALSE;
4529 	
4530 	   if ( ncols <= 0 )
4531 	      return SCIP_OKAY;
4532 	
4533 	   /* start timing */
4534 	   SCIPclockStart(stat->strongbranchtime, set);
4535 	
4536 	   /* initialize storage */
4537 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4538 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4539 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4540 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4541 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4542 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4543 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4544 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4545 	
4546 	   nsubcols = 0;
4547 	   for( j = 0; j < ncols; ++j )
4548 	   {
4549 	      SCIP_COL* col;
4550 	      col = cols[j];
4551 	
4552 	      assert(col->lppos < lp->ncols);
4553 	      assert(lp->cols[col->lppos] == col);
4554 	      assert(SCIPcolIsIntegral(col));
4555 	      assert(SCIPvarIsIntegral(col->var));
4556 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
4557 	      assert(SCIPvarGetCol(col->var) == col);
4558 	      assert(col->primsol != SCIP_INVALID);  /*lint !e777*/
4559 	      assert(col->lpipos >= 0);
4560 	      assert(col->lppos >= 0);
4561 	
4562 	      col->validsblp = stat->nlps;
4563 	      col->sbsolval = col->primsol;
4564 	      col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4565 	      col->sbnode = stat->nnodes;
4566 	      assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4567 	
4568 	      /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4569 	      if( lp->looseobjvalinf > 0 )
4570 	      {
4571 	         /* directly set up column and result vectors*/
4572 	         col->sbdown = -SCIPsetInfinity(set);
4573 	         col->sbup = -SCIPsetInfinity(set);
4574 	         col->sbdownvalid = FALSE;
4575 	         col->sbupvalid = FALSE;
4576 	         down[j] = col->sbdown;
4577 	         up[j] = col->sbup;
4578 	         if( downvalid != NULL )
4579 	            downvalid[j] = col->sbdownvalid;
4580 	         if( upvalid != NULL )
4581 	            upvalid[j] = col->sbupvalid;
4582 	      }
4583 	      else
4584 	      {
4585 	         col->sbitlim = itlim;
4586 	         col->nsbcalls++;
4587 	
4588 	         lpipos[nsubcols] = col->lpipos;
4589 	         primsols[nsubcols] = col->primsol;
4590 	         assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4591 	         subidx[nsubcols] = j;
4592 	         subcols[nsubcols++] = col;
4593 	      }
4594 	   }
4595 	
4596 	   SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4597 	
4598 	   /* call LPI strong branching */
4599 	   if ( integral )
4600 	      retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4601 	   else
4602 	      retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4603 	
4604 	   /* check return code for errors */
4605 	   if( retcode == SCIP_LPERROR )
4606 	   {
4607 	      *lperror = TRUE;
4608 	
4609 	      for( j = 0; j < nsubcols; ++j )
4610 	      {
4611 	         SCIP_COL* col;
4612 	         int idx;
4613 	
4614 	         col = subcols[j];
4615 	         idx = subidx[j];
4616 	
4617 	         col->sbdown = SCIP_INVALID;
4618 	         col->sbup = SCIP_INVALID;
4619 	         col->sbdownvalid = FALSE;
4620 	         col->sbupvalid = FALSE;
4621 	         col->validsblp = -1;
4622 	         col->sbsolval = SCIP_INVALID;
4623 	         col->sblpobjval = SCIP_INVALID;
4624 	         col->sbnode = -1;
4625 	
4626 	         down[idx] = col->sbdown;
4627 	         up[idx] = col->sbup;
4628 	         if( downvalid != NULL )
4629 	            downvalid[idx] = col->sbdownvalid;
4630 	         if( upvalid != NULL )
4631 	            upvalid[idx] = col->sbupvalid;
4632 	      }
4633 	   }
4634 	   else
4635 	   {
4636 	      SCIP_Real looseobjval;
4637 	
4638 	      *lperror = FALSE;
4639 	      SCIP_CALL( retcode );
4640 	
4641 	      looseobjval = getFiniteLooseObjval(lp, set, prob);
4642 	
4643 	      for( j = 0; j < nsubcols; ++j )
4644 	      {
4645 	         SCIP_COL* col;
4646 	         int idx;
4647 	
4648 	         col = subcols[j];
4649 	         idx = subidx[j];
4650 	
4651 	         assert( col->sbdown != SCIP_INVALID);  /*lint !e777*/
4652 	         assert( col->sbup != SCIP_INVALID);  /*lint !e777*/
4653 	
4654 	         col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4655 	         col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4656 	         col->sbdownvalid = sbdownvalid[j];
4657 	         col->sbupvalid = sbupvalid[j];
4658 	
4659 	         down[idx] = col->sbdown;
4660 	         up[idx] = col->sbup;
4661 	         if( downvalid != NULL )
4662 	            downvalid[idx] = col->sbdownvalid;
4663 	         if( upvalid != NULL )
4664 	            upvalid[idx] = col->sbupvalid;
4665 	      }
4666 	
4667 	      /* update strong branching statistics */
4668 	      if( iter == -1 )
4669 	      {
4670 	         /* calculate average iteration number */
4671 	         iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4672 	            : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4673 	            : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4674 	            : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4675 	            : 0;
4676 	         if( iter/2 >= itlim )
4677 	            iter = 2*itlim;
4678 	      }
4679 	      SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4680 	      SCIPstatAdd(stat, set, nsblpiterations, iter);
4681 	      if( stat->nnodes == 1 )
4682 	      {
4683 	         SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4684 	         SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4685 	      }
4686 	   }
4687 	
4688 	   SCIPsetFreeBufferArray(set, &sbupvalid);
4689 	   SCIPsetFreeBufferArray(set, &sbdownvalid);
4690 	   SCIPsetFreeBufferArray(set, &sbup);
4691 	   SCIPsetFreeBufferArray(set, &sbdown);
4692 	   SCIPsetFreeBufferArray(set, &primsols);
4693 	   SCIPsetFreeBufferArray(set, &lpipos);
4694 	   SCIPsetFreeBufferArray(set, &subidx);
4695 	   SCIPsetFreeBufferArray(set, &subcols);
4696 	
4697 	   /* stop timing */
4698 	   SCIPclockStop(stat->strongbranchtime, set);
4699 	
4700 	   return SCIP_OKAY;
4701 	}
4702 	
4703 	/** gets last strong branching information available for a column variable;
4704 	 *  returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4705 	 *  keep in mind, that the returned old values may have nothing to do with the current LP solution
4706 	 */
4707 	void SCIPcolGetStrongbranchLast(
4708 	   SCIP_COL*             col,                /**< LP column */
4709 	   SCIP_Real*            down,               /**< stores dual bound after branching column down, or NULL */
4710 	   SCIP_Real*            up,                 /**< stores dual bound after branching column up, or NULL */
4711 	   SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
4712 	                                              *   otherwise, it can only be used as an estimate value */
4713 	   SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
4714 	                                              *   otherwise, it can only be used as an estimate value */
4715 	   SCIP_Real*            solval,             /**< stores LP solution value of column at last strong branching call, or NULL */
4716 	   SCIP_Real*            lpobjval            /**< stores LP objective value at last strong branching call, or NULL */
4717 	   )
4718 	{
4719 	   assert(col != NULL);
4720 	
4721 	   if( down != NULL )
4722 	      *down = col->sbdown;
4723 	   if( up != NULL )
4724 	      *up = col->sbup;
4725 	   if( downvalid != NULL )
4726 	      *downvalid = col->sbdownvalid;
4727 	   if( upvalid != NULL )
4728 	      *upvalid = col->sbupvalid;
4729 	   if( solval != NULL )
4730 	      *solval = col->sbsolval;
4731 	   if( lpobjval != NULL )
4732 	      *lpobjval = col->sblpobjval;
4733 	}
4734 	
4735 	/** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4736 	 *  the LP where the strong branching on this column was applied;
4737 	 *  if strong branching was not yet applied on the column at the current node, returns INT_MAX
4738 	 */
4739 	SCIP_Longint SCIPcolGetStrongbranchLPAge(
4740 	   SCIP_COL*             col,                /**< LP column */
4741 	   SCIP_STAT*            stat                /**< dynamic problem statistics */
4742 	   )
4743 	{
4744 	   assert(col != NULL);
4745 	   assert(stat != NULL);
4746 	
4747 	   return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4748 	}
4749 	
4750 	/** marks a column to be not removable from the LP in the current node because it became obsolete */
4751 	void SCIPcolMarkNotRemovableLocal(
4752 	   SCIP_COL*             col,                /**< LP column */
4753 	   SCIP_STAT*            stat                /**< problem statistics */
4754 	   )
4755 	{
4756 	   assert(col  != NULL);
4757 	   assert(stat != NULL);
4758 	   assert(stat->nnodes > 0);
4759 	
4760 	   /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4761 	   col->obsoletenode = stat->nnodes;
4762 	}
4763 	
4764 	
4765 	/*
4766 	 * Row methods
4767 	 */
4768 	
4769 	/** calculates row norms and min/maxidx from scratch, and checks for sorting */
4770 	static
4771 	void rowCalcNorms(
4772 	   SCIP_ROW*             row,                /**< LP row */
4773 	   SCIP_SET*             set                 /**< global SCIP settings */
4774 	   )
4775 	{
4776 	   int i;
4777 	
4778 	   assert(row != NULL);
4779 	   assert(set != NULL);
4780 	
4781 	   row->sqrnorm = 0.0;
4782 	   row->sumnorm = 0.0;
4783 	   row->objprod = 0.0;
4784 	   row->maxval = 0.0;
4785 	   row->nummaxval = 1;
4786 	   row->minval = SCIPsetInfinity(set);
4787 	   row->numminval = 1;
4788 	   row->minidx = INT_MAX;
4789 	   row->maxidx = INT_MIN;
4790 	   row->validminmaxidx = TRUE;
4791 	   row->lpcolssorted = TRUE;
4792 	   row->nonlpcolssorted = TRUE;
4793 	
4794 	   /* check, if row is sorted
4795 	    * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4796 	    */
4797 	   for( i = 0; i < row->nlpcols; ++i )
4798 	   {
4799 	      assert(row->cols[i] != NULL);
4800 	      assert(!SCIPsetIsZero(set, row->vals[i]));
4801 	      assert(row->cols[i]->lppos >= 0);
4802 	      assert(row->linkpos[i] >= 0);
4803 	      assert(row->cols[i]->index == row->cols_index[i]);
4804 	
4805 	      rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4806 	      if( i > 0 )
4807 	      {
4808 	         assert(row->cols[i-1]->index == row->cols_index[i-1]);
4809 	         row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4810 	      }
4811 	   }
4812 	   for( i = row->nlpcols; i < row->len; ++i )
4813 	   {
4814 	      assert(row->cols[i] != NULL);
4815 	      assert(!SCIPsetIsZero(set, row->vals[i]));
4816 	      assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4817 	      assert(row->cols[i]->index == row->cols_index[i]);
4818 	
4819 	      rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4820 	      if( i > row->nlpcols )
4821 	      {
4822 	         assert(row->cols[i-1]->index == row->cols_index[i-1]);
4823 	         row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4824 	      }
4825 	   }
4826 	}
4827 	
4828 	/** calculates min/maxval and min/maxidx from scratch */
4829 	static
4830 	void rowCalcIdxsAndVals(
4831 	   SCIP_ROW*             row,                /**< LP row */
4832 	   SCIP_SET*             set                 /**< global SCIP settings */
4833 	   )
4834 	{
4835 	   SCIP_COL* col;
4836 	   SCIP_Real absval;
4837 	   int i;
4838 	
4839 	   assert(row != NULL);
4840 	   assert(set != NULL);
4841 	
4842 	   row->maxval = 0.0;
4843 	   row->nummaxval = 1;
4844 	   row->numintcols = 0;
4845 	   row->minval = SCIPsetInfinity(set);
4846 	   row->numminval = 1;
4847 	   row->minidx = INT_MAX;
4848 	   row->maxidx = INT_MIN;
4849 	   row->validminmaxidx = TRUE;
4850 	
4851 	   /* calculate maxval, minval, minidx, and maxidx */
4852 	   for( i = 0; i < row->len; ++i )
4853 	   {
4854 	      col = row->cols[i];
4855 	      assert(col != NULL);
4856 	      assert(!SCIPsetIsZero(set, row->vals[i]));
4857 	
4858 	      absval = REALABS(row->vals[i]);
4859 	      assert(!SCIPsetIsZero(set, absval));
4860 	
4861 	      /* update min/maxidx */
4862 	      row->minidx = MIN(row->minidx, col->index);
4863 	      row->maxidx = MAX(row->maxidx, col->index);
4864 	      row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4865 	
4866 	      /* update maximal and minimal non-zero value */
4867 	      if( row->nummaxval > 0 )
4868 	      {
4869 	         if( SCIPsetIsGT(set, absval, row->maxval) )
4870 	         {
4871 	            row->maxval = absval;
4872 	            row->nummaxval = 1;
4873 	         }
4874 	         else if( SCIPsetIsGE(set, absval, row->maxval) )
4875 	         {
4876 	            /* make sure the maxval is always exactly the same */
4877 	            row->maxval = MAX(absval, row->maxval);
4878 	            row->nummaxval++;
4879 	         }
4880 	      }
4881 	      if( row->numminval > 0 )
4882 	      {
4883 	         if( SCIPsetIsLT(set, absval, row->minval) )
4884 	         {
4885 	            row->minval = absval;
4886 	            row->numminval = 1;
4887 	         }
4888 	         else if( SCIPsetIsLE(set, absval, row->minval) )
4889 	         {
4890 	            /* make sure the minval is always exactly the same */
4891 	            row->minval = MIN(absval, row->minval);
4892 	            row->numminval++;
4893 	         }
4894 	      }
4895 	   }
4896 	}
4897 	
4898 	/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4899 	static
4900 	SCIP_Bool isIntegralScalar(
4901 	   SCIP_Real             val,                /**< value that should be scaled to an integral value */
4902 	   SCIP_Real             scalar,             /**< scalar that should be tried */
4903 	   SCIP_Real             mindelta,           /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4904 	   SCIP_Real             maxdelta,           /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4905 	   SCIP_Real*            intval              /**< pointer to store the scaled integral value, or NULL */
4906 	   )
4907 	{
4908 	   SCIP_Real sval;
4909 	   SCIP_Real downval;
4910 	   SCIP_Real upval;
4911 	
4912 	   assert(mindelta <= 0.0);
4913 	   assert(maxdelta >= 0.0);
4914 	
4915 	   sval = val * scalar;
4916 	   downval = floor(sval);
4917 	   upval = ceil(sval);
4918 	
4919 	   if( SCIPrelDiff(sval, downval) <= maxdelta )
4920 	   {
4921 	      if( intval != NULL )
4922 	         *intval = downval;
4923 	      return TRUE;
4924 	   }
4925 	   else if( SCIPrelDiff(sval, upval) >= mindelta )
4926 	   {
4927 	      if( intval != NULL )
4928 	         *intval = upval;
4929 	      return TRUE;
4930 	   }
4931 	
4932 	   return FALSE;
4933 	}
4934 	
4935 	/** scales row with given factor, and rounds coefficients to integers if close enough;
4936 	 *  the constant is automatically moved to the sides;
4937 	 *  if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4938 	 */
4939 	static
4940 	SCIP_RETCODE rowScale(
4941 	   SCIP_ROW*             row,                /**< LP row */
4942 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4943 	   SCIP_SET*             set,                /**< global SCIP settings */
4944 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4945 	   SCIP_STAT*            stat,               /**< problem statistics */
4946 	   SCIP_LP*              lp,                 /**< current LP data */
4947 	   SCIP_Real             scaleval,           /**< value to scale row with */
4948 	   SCIP_Bool             integralcontvars,   /**< should the coefficients of the continuous variables also be made integral,
4949 	                                              *   if they are close to integral values? */
4950 	   SCIP_Real             minrounddelta,      /**< minimal relative difference of scaled coefficient s*c and integral i,
4951 	                                              *   upto which the integral is used instead of the scaled real coefficient */
4952 	   SCIP_Real             maxrounddelta       /**< maximal relative difference of scaled coefficient s*c and integral i
4953 	                                              *   upto which the integral is used instead of the scaled real coefficient */
4954 	   )
4955 	{
4956 	   SCIP_COL* col;
4957 	   SCIP_Real val;
4958 	   SCIP_Real newval;
4959 	   SCIP_Real intval;
4960 	   SCIP_Real mindelta;
4961 	   SCIP_Real maxdelta;
4962 	   SCIP_Real lb;
4963 	   SCIP_Real ub;
4964 	   SCIP_Bool mindeltainf;
4965 	   SCIP_Bool maxdeltainf;
4966 	   int oldlen;
4967 	   int c;
4968 	
4969 	   assert(row != NULL);
4970 	   assert(row->len == 0 || row->cols != NULL);
4971 	   assert(row->len == 0 || row->vals != NULL);
4972 	   assert(SCIPsetIsPositive(set, scaleval));
4973 	   assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4974 	   assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4975 	
4976 	   SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4977 	
4978 	   mindelta = 0.0;
4979 	   maxdelta = 0.0;
4980 	   mindeltainf = FALSE;
4981 	   maxdeltainf = FALSE;
4982 	   oldlen = row->len;
4983 	
4984 	   /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4985 	    * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4986 	    * this rounding can lead to
4987 	    */
4988 	   row->integral = TRUE;
4989 	
4990 	   c = 0;
4991 	   while( c < row->len )
4992 	   {
4993 	      col = row->cols[c];
4994 	      val = row->vals[c];
4995 	      assert(!SCIPsetIsZero(set, val));
4996 	
4997 	      /* get local or global bounds for column, depending on the local or global feasibility of the row */
4998 	      if( row->local )
4999 	      {
5000 	         lb = col->lb;
5001 	         ub = col->ub;
5002 	      }
5003 	      else
5004 	      {
5005 	         lb = SCIPvarGetLbGlobal(col->var);
5006 	         ub = SCIPvarGetUbGlobal(col->var);
5007 	      }
5008 	
5009 	      /* calculate scaled coefficient */
5010 	      newval = val * scaleval;
5011 	      if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5012 	         && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5013 	      {
5014 	         if( !SCIPsetIsEQ(set, intval, newval) )
5015 	         {
5016 	            if( intval < newval )
5017 	            {
5018 	               mindelta += (intval - newval)*ub;
5019 	               maxdelta += (intval - newval)*lb;
5020 	               mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5021 	               maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5022 	            }
5023 	            else
5024 	            {
5025 	               mindelta += (intval - newval)*lb;
5026 	               maxdelta += (intval - newval)*ub;
5027 	               mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5028 	               maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5029 	            }
5030 	         }
5031 	         newval = intval;
5032 	      }
5033 	
5034 	      if( !SCIPsetIsEQ(set, val, newval) )
5035 	      {
5036 	         /* if column knows of the row, change the corresponding coefficient in the column */
5037 	         if( row->linkpos[c] >= 0 )
5038 	         {
5039 	            assert(col->rows[row->linkpos[c]] == row);
5040 	            assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5041 	            SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5042 	         }
5043 	
5044 	         /* change the coefficient in the row, and update the norms and integrality status */
5045 	         SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5046 	
5047 	         /* current coefficient has been deleted from the row because it was almost zero */
5048 	         if( oldlen != row->len )
5049 	         {
5050 	            assert(row->len == oldlen - 1);
5051 	            c--;
5052 	            oldlen = row->len;
5053 	         }
5054 	      }
5055 	      else
5056 	         row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5057 	
5058 	      ++c;
5059 	   }
5060 	
5061 	   /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5062 	    * to not destroy feasibility due to rounding
5063 	    */
5064 	   /**@todo ensure that returned cut does not have infinite lhs and rhs */
5065 	   if( !SCIPsetIsInfinity(set, -row->lhs) )
5066 	   {
5067 	      if( mindeltainf )
5068 	         newval = -SCIPsetInfinity(set);
5069 	      else
5070 	      {
5071 	         newval = (row->lhs - row->constant) * scaleval + mindelta;
5072 	         if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5073 	            newval = SCIPsetSumCeil(set, newval);
5074 	      }
5075 	      SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5076 	   }
5077 	   if( !SCIPsetIsInfinity(set, row->rhs) )
5078 	   {
5079 	      if( maxdeltainf )
5080 	         newval = SCIPsetInfinity(set);
5081 	      else
5082 	      {
5083 	         newval = (row->rhs - row->constant) * scaleval + maxdelta;
5084 	         if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5085 	            newval = SCIPsetSumFloor(set, newval);
5086 	      }
5087 	      SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5088 	   }
5089 	
5090 	   /* clear the row constant */
5091 	   SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5092 	
5093 	   SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5094 	   debugRowPrint(set, row);
5095 	
5096 	#ifdef SCIP_DEBUG
5097 	   /* check integrality status of row */
5098 	   for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5099 	   {}
5100 	   assert(row->integral == (c == row->len));
5101 	#endif
5102 	
5103 	   /* invalid the activity */
5104 	   row->validactivitylp = -1;
5105 	
5106 	   return SCIP_OKAY;
5107 	}
5108 	
5109 	/** creates and captures an LP row */
5110 	SCIP_RETCODE SCIProwCreate(
5111 	   SCIP_ROW**            row,                /**< pointer to LP row data */
5112 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5113 	   SCIP_SET*             set,                /**< global SCIP settings */
5114 	   SCIP_STAT*            stat,               /**< problem statistics */
5115 	   const char*           name,               /**< name of row */
5116 	   int                   len,                /**< number of nonzeros in the row */
5117 	   SCIP_COL**            cols,               /**< array with columns of row entries */
5118 	   SCIP_Real*            vals,               /**< array with coefficients of row entries */
5119 	   SCIP_Real             lhs,                /**< left hand side of row */
5120 	   SCIP_Real             rhs,                /**< right hand side of row */
5121 	   SCIP_ROWORIGINTYPE    origintype,         /**< type of origin of row */
5122 	   void*                 origin,             /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5123 	   SCIP_Bool             local,              /**< is row only valid locally? */
5124 	   SCIP_Bool             modifiable,         /**< is row modifiable during node processing (subject to column generation)? */
5125 	   SCIP_Bool             removable           /**< should the row be removed from the LP due to aging or cleanup? */
5126 	   )
5127 	{
5128 	   assert(row != NULL);
5129 	   assert(blkmem != NULL);
5130 	   assert(stat != NULL);
5131 	   assert(len >= 0);
5132 	   assert(len == 0 || (cols != NULL && vals != NULL));
5133 	   /* note, that the assert tries to avoid numerical troubles in the LP solver.
5134 	    * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5135 	    * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5136 	    */
5137 	   assert(lhs <= rhs);
5138 	
5139 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5140 	
5141 	   (*row)->integral = TRUE;
5142 	   if( len > 0 )
5143 	   {
5144 	      SCIP_VAR* var;
5145 	      int i;
5146 	
5147 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5148 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5149 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5150 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5151 	
5152 	      for( i = 0; i < len; ++i )
5153 	      {
5154 	         assert(cols[i] != NULL);
5155 	         assert(!SCIPsetIsZero(set, vals[i]));
5156 	
5157 	         var = cols[i]->var;
5158 	         (*row)->cols_index[i] = cols[i]->index;
5159 	         (*row)->linkpos[i] = -1;
5160 	         if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5161 	         {
5162 	            (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5163 	            (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5164 	         }
5165 	         else
5166 	         {
5167 	            (*row)->integral = FALSE;
5168 	         }
5169 	      }
5170 	   }
5171 	   else
5172 	   {
5173 	      (*row)->cols = NULL;
5174 	      (*row)->cols_index = NULL;
5175 	      (*row)->vals = NULL;
5176 	      (*row)->linkpos = NULL;
5177 	   }
5178 	
5179 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5180 	   (*row)->constant = 0.0;
5181 	   (*row)->lhs = lhs;
5182 	   (*row)->rhs = rhs;
5183 	   (*row)->flushedlhs = -SCIPsetInfinity(set);
5184 	   (*row)->flushedrhs = SCIPsetInfinity(set);
5185 	   (*row)->sqrnorm = 0.0;
5186 	   (*row)->sumnorm = 0.0;
5187 	   (*row)->objprod = 0.0;
5188 	   (*row)->maxval = 0.0;
5189 	   (*row)->minval = SCIPsetInfinity(set);
5190 	   (*row)->dualsol = 0.0;
5191 	   (*row)->activity = SCIP_INVALID;
5192 	   (*row)->dualfarkas = 0.0;
5193 	   (*row)->pseudoactivity = SCIP_INVALID;
5194 	   (*row)->minactivity = SCIP_INVALID;
5195 	   (*row)->maxactivity = SCIP_INVALID;
5196 	   (*row)->origin = origin;
5197 	   (*row)->eventfilter = NULL;
5198 	   (*row)->index = stat->nrowidx;
5199 	   SCIPstatIncrement(stat, set, nrowidx);
5200 	   (*row)->size = len;
5201 	   (*row)->len = len;
5202 	   (*row)->nlpcols = 0;
5203 	   (*row)->nunlinked = len;
5204 	   (*row)->nuses = 0;
5205 	   (*row)->lppos = -1;
5206 	   (*row)->lpipos = -1;
5207 	   (*row)->lpdepth = -1;
5208 	   (*row)->minidx = INT_MAX;
5209 	   (*row)->maxidx = INT_MIN;
5210 	   (*row)->nummaxval = 0;
5211 	   (*row)->numminval = 0;
5212 	   (*row)->numintcols = -1;
5213 	   (*row)->validactivitylp = -1;
5214 	   (*row)->validpsactivitydomchg = -1;
5215 	   (*row)->validactivitybdsdomchg = -1;
5216 	   (*row)->nlpsaftercreation = 0L;
5217 	   (*row)->activeinlpcounter = 0L;
5218 	   (*row)->age = 0;
5219 	   (*row)->rank = 0;
5220 	   (*row)->obsoletenode = -1;
5221 	   (*row)->fromcutpool = FALSE;
5222 	   (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5223 	   (*row)->lpcolssorted = TRUE;
5224 	   (*row)->nonlpcolssorted = (len <= 1);
5225 	   (*row)->delaysort = FALSE;
5226 	   (*row)->validminmaxidx = FALSE;
5227 	   (*row)->lhschanged = FALSE;
5228 	   (*row)->rhschanged = FALSE;
5229 	   (*row)->coefchanged = FALSE;
5230 	   (*row)->local = local;
5231 	   (*row)->modifiable = modifiable;
5232 	   (*row)->nlocks = 0;
5233 	   (*row)->origintype = origintype; /*lint !e641*/
5234 	   (*row)->removable = removable;
5235 	   (*row)->inglobalcutpool = FALSE;
5236 	   (*row)->storedsolvals = NULL;
5237 	
5238 	   /* calculate row norms and min/maxidx, and check if row is sorted */
5239 	   rowCalcNorms(*row, set);
5240 	
5241 	   /* capture the row */
5242 	   SCIProwCapture(*row);
5243 	
5244 	   /* create event filter */
5245 	   SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5246 	
5247 	   /* capture origin constraint if available */
5248 	   if( origintype == SCIP_ROWORIGINTYPE_CONS )
5249 	   {
5250 	      SCIP_CONS* cons = (SCIP_CONS*) origin;
5251 	      assert(cons != NULL);
5252 	      SCIPconsCapture(cons);
5253 	   }
5254 	
5255 	   return SCIP_OKAY;
5256 	} /*lint !e715*/
5257 	
5258 	/** frees an LP row */
5259 	SCIP_RETCODE SCIProwFree(
5260 	   SCIP_ROW**            row,                /**< pointer to LP row */
5261 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5262 	   SCIP_SET*             set,                /**< global SCIP settings */
5263 	   SCIP_LP*              lp                  /**< current LP data */
5264 	   )
5265 	{
5266 	   assert(blkmem != NULL);
5267 	   assert(row != NULL);
5268 	   assert(*row != NULL);
5269 	   assert((*row)->nuses == 0);
5270 	   assert((*row)->lppos == -1);
5271 	   assert((*row)->eventfilter != NULL);
5272 	
5273 	   /* release constraint that has been used for creating the row */
5274 	   if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5275 	   {
5276 	      SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5277 	      assert(cons != NULL);
5278 	      SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5279 	   }
5280 	
5281 	   /* remove column indices from corresponding rows */
5282 	   SCIP_CALL( rowUnlink(*row, set, lp) );
5283 	
5284 	   /* free event filter */
5285 	   SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5286 	
5287 	   BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5288 	   BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5289 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5290 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5291 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5292 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5293 	   BMSfreeBlockMemory(blkmem, row);
5294 	
5295 	   return SCIP_OKAY;
5296 	}
5297 	
5298 	/** output row to file stream */
5299 	void SCIProwPrint(
5300 	   SCIP_ROW*             row,                /**< LP row */
5301 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
5302 	   FILE*                 file                /**< output file (or NULL for standard output) */
5303 	   )
5304 	{
5305 	   int i;
5306 	
5307 	   assert(row != NULL);
5308 	
5309 	   /* print row name */
5310 	   if( row->name != NULL && row->name[0] != '\0' )
5311 	   {
5312 	      SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5313 	   }
5314 	
5315 	   /* print left hand side */
5316 	   SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5317 	
5318 	   /* print coefficients */
5319 	   if( row->len == 0 )
5320 	      SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5321 	   for( i = 0; i < row->len; ++i )
5322 	   {
5323 	      assert(row->cols[i] != NULL);
5324 	      assert(row->cols[i]->var != NULL);
5325 	      assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5326 	      assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5327 	      SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5328 	   }
5329 	
5330 	   /* print constant */
5331 	   if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON )
5332 	      SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5333 	
5334 	   /* print right hand side */
5335 	   SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5336 	}
5337 	
5338 	/** increases usage counter of LP row */
5339 	void SCIProwCapture(
5340 	   SCIP_ROW*             row                 /**< LP row */
5341 	   )
5342 	{
5343 	   assert(row != NULL);
5344 	   assert(row->nuses >= 0);
5345 	   assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5346 	
5347 	   SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5348 	   row->nuses++;
5349 	}
5350 	
5351 	/** decreases usage counter of LP row, and frees memory if necessary */
5352 	SCIP_RETCODE SCIProwRelease(
5353 	   SCIP_ROW**            row,                /**< pointer to LP row */
5354 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5355 	   SCIP_SET*             set,                /**< global SCIP settings */
5356 	   SCIP_LP*              lp                  /**< current LP data */
5357 	   )
5358 	{
5359 	   assert(blkmem != NULL);
5360 	   assert(row != NULL);
5361 	   assert(*row != NULL);
5362 	   assert((*row)->nuses >= 1);
5363 	   assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5364 	
5365 	   SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5366 	   (*row)->nuses--;
5367 	   if( (*row)->nuses == 0 )
5368 	   {
5369 	      SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5370 	   }
5371 	
5372 	   *row = NULL;
5373 	
5374 	   return SCIP_OKAY;
5375 	}
5376 	
5377 	/** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5378 	void SCIProwLock(
5379 	   SCIP_ROW*             row                 /**< LP row */
5380 	   )
5381 	{
5382 	   assert(row != NULL);
5383 	
5384 	   /* check, if row is modifiable */
5385 	   if( !row->modifiable )
5386 	   {
5387 	      SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5388 	      row->nlocks++;
5389 	   }
5390 	}
5391 	
5392 	/** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5393 	void SCIProwUnlock(
5394 	   SCIP_ROW*             row                 /**< LP row */
5395 	   )
5396 	{
5397 	   assert(row != NULL);
5398 	
5399 	   /* check, if row is modifiable */
5400 	   if( !row->modifiable )
5401 	   {
5402 	      SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5403 	      assert(row->nlocks > 0);
5404 	      row->nlocks--;
5405 	   }
5406 	}
5407 	
5408 	/** adds a previously non existing coefficient to an LP row */
5409 	SCIP_RETCODE SCIProwAddCoef(
5410 	   SCIP_ROW*             row,                /**< LP row */
5411 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5412 	   SCIP_SET*             set,                /**< global SCIP settings */
5413 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5414 	   SCIP_LP*              lp,                 /**< current LP data */
5415 	   SCIP_COL*             col,                /**< LP column */
5416 	   SCIP_Real             val                 /**< value of coefficient */
5417 	   )
5418 	{
5419 	   assert(lp != NULL);
5420 	   assert(!lp->diving || row->lppos == -1);
5421 	
5422 	   SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5423 	
5424 	   checkLinks(lp);
5425 	
5426 	   return SCIP_OKAY;
5427 	}
5428 	
5429 	/** deletes coefficient from row */
5430 	SCIP_RETCODE SCIProwDelCoef(
5431 	   SCIP_ROW*             row,                /**< row to be changed */
5432 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5433 	   SCIP_SET*             set,                /**< global SCIP settings */
5434 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5435 	   SCIP_LP*              lp,                 /**< current LP data */
5436 	   SCIP_COL*             col                 /**< coefficient to be deleted */
5437 	   )
5438 	{
5439 	   int pos;
5440 	
5441 	   assert(row != NULL);
5442 	   assert(!row->delaysort);
5443 	   assert(lp != NULL);
5444 	   assert(!lp->diving || row->lppos == -1);
5445 	   assert(col != NULL);
5446 	   assert(col->var != NULL);
5447 	
5448 	   /* search the position of the column in the row's col vector */
5449 	   pos = rowSearchCoef(row, col);
5450 	   if( pos == -1 )
5451 	   {
5452 	      SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5453 	      return SCIP_INVALIDDATA;
5454 	   }
5455 	   assert(0 <= pos && pos < row->len);
5456 	   assert(row->cols[pos] == col);
5457 	   assert(row->cols_index[pos] == col->index);
5458 	
5459 	   /* if column knows of the row, remove the row from the column's row vector */
5460 	   if( row->linkpos[pos] >= 0 )
5461 	   {
5462 	      assert(col->rows[row->linkpos[pos]] == row);
5463 	      assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5464 	      SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5465 	   }
5466 	
5467 	   /* delete the column from the row's col vector */
5468 	   SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5469 	
5470 	   checkLinks(lp);
5471 	
5472 	   return SCIP_OKAY;
5473 	}
5474 	
5475 	/** changes or adds a coefficient to an LP row */
5476 	SCIP_RETCODE SCIProwChgCoef(
5477 	   SCIP_ROW*             row,                /**< LP row */
5478 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5479 	   SCIP_SET*             set,                /**< global SCIP settings */
5480 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5481 	   SCIP_LP*              lp,                 /**< current LP data */
5482 	   SCIP_COL*             col,                /**< LP column */
5483 	   SCIP_Real             val                 /**< value of coefficient */
5484 	   )
5485 	{
5486 	   int pos;
5487 	
5488 	   assert(row != NULL);
5489 	   assert(!row->delaysort);
5490 	   assert(lp != NULL);
5491 	   assert(!lp->diving || row->lppos == -1);
5492 	   assert(col != NULL);
5493 	
5494 	   /* search the position of the column in the row's col vector */
5495 	   pos = rowSearchCoef(row, col);
5496 	
5497 	   /* check, if column already exists in the row's col vector */
5498 	   if( pos == -1 )
5499 	   {
5500 	      /* add previously not existing coefficient */
5501 	      SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5502 	   }
5503 	   else
5504 	   {
5505 	      /* modify already existing coefficient */
5506 	      assert(0 <= pos && pos < row->len);
5507 	      assert(row->cols[pos] == col);
5508 	      assert(row->cols_index[pos] == col->index);
5509 	
5510 	      /* if column knows of the row, change the corresponding coefficient in the column */
5511 	      if( row->linkpos[pos] >= 0 )
5512 	      {
5513 	         assert(col->rows[row->linkpos[pos]] == row);
5514 	         assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5515 	         SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5516 	      }
5517 	
5518 	      /* change the coefficient in the row */
5519 	      SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5520 	   }
5521 	
5522 	   checkLinks(lp);
5523 	
5524 	   return SCIP_OKAY;
5525 	}
5526 	
5527 	/** increases value of an existing or non-existing coefficient in an LP row */
5528 	SCIP_RETCODE SCIProwIncCoef(
5529 	   SCIP_ROW*             row,                /**< LP row */
5530 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5531 	   SCIP_SET*             set,                /**< global SCIP settings */
5532 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5533 	   SCIP_LP*              lp,                 /**< current LP data */
5534 	   SCIP_COL*             col,                /**< LP column */
5535 	   SCIP_Real             incval              /**< value to add to the coefficient */
5536 	   )
5537 	{
5538 	   int pos;
5539 	
5540 	   assert(row != NULL);
5541 	   assert(lp != NULL);
5542 	   assert(!lp->diving || row->lppos == -1);
5543 	   assert(col != NULL);
5544 	
5545 	   if( SCIPsetIsZero(set, incval) )
5546 	      return SCIP_OKAY;
5547 	
5548 	   /* search the position of the column in the row's col vector */
5549 	   pos = rowSearchCoef(row, col);
5550 	
5551 	   /* check, if column already exists in the row's col vector */
5552 	   if( pos == -1 )
5553 	   {
5554 	      /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5555 	      SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5556 	   }
5557 	   else
5558 	   {
5559 	      /* modify already existing coefficient */
5560 	      assert(0 <= pos && pos < row->len);
5561 	      assert(row->cols[pos] == col);
5562 	      assert(row->cols_index[pos] == col->index);
5563 	
5564 	      /* if column knows of the row, change the corresponding coefficient in the column */
5565 	      if( row->linkpos[pos] >= 0 )
5566 	      {
5567 	         assert(col->rows[row->linkpos[pos]] == row);
5568 	         assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5569 	         SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5570 	      }
5571 	
5572 	      /* change the coefficient in the row */
5573 	      SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5574 	   }
5575 	
5576 	   checkLinks(lp);
5577 	
5578 	   /* invalid the activity */
5579 	   row->validactivitylp = -1;
5580 	
5581 	   return SCIP_OKAY;
5582 	}
5583 	
5584 	/** changes constant value of a row */
5585 	SCIP_RETCODE SCIProwChgConstant(
5586 	   SCIP_ROW*             row,                /**< LP row */
5587 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5588 	   SCIP_SET*             set,                /**< global SCIP settings */
5589 	   SCIP_STAT*            stat,               /**< problem statistics */
5590 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5591 	   SCIP_LP*              lp,                 /**< current LP data */
5592 	   SCIP_Real             constant            /**< new constant value */
5593 	   )
5594 	{
5595 	   assert(row != NULL);
5596 	   assert(row->lhs <= row->rhs);
5597 	   assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5598 	   assert(stat != NULL);
5599 	   assert(lp != NULL);
5600 	   assert(!lp->diving || row->lppos == -1);
5601 	
5602 	   if( !SCIPsetIsEQ(set, constant, row->constant) )
5603 	   {
5604 	      SCIP_Real oldconstant;
5605 	
5606 	      if( row->validpsactivitydomchg == stat->domchgcount )
5607 	      {
5608 	         assert(row->pseudoactivity != SCIP_INVALID);  /*lint !e777*/
5609 	         row->pseudoactivity += constant - row->constant;
5610 	      }
5611 	      if( row->validactivitybdsdomchg == stat->domchgcount )
5612 	      {
5613 	         assert(row->minactivity != SCIP_INVALID);  /*lint !e777*/
5614 	         assert(row->maxactivity != SCIP_INVALID);  /*lint !e777*/
5615 	         row->minactivity += constant - row->constant;
5616 	         row->maxactivity += constant - row->constant;
5617 	      }
5618 	
5619 	      if( !SCIPsetIsInfinity(set, -row->lhs) )
5620 	      {
5621 	         SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5622 	      }
5623 	      if( !SCIPsetIsInfinity(set, row->rhs) )
5624 	      {
5625 	         SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5626 	      }
5627 	
5628 	      oldconstant = row->constant;
5629 	
5630 	      row->constant = constant;
5631 	
5632 	      /* issue row constant changed event */
5633 	      SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5634 	   }
5635 	
5636 	   return SCIP_OKAY;
5637 	}
5638 	
5639 	/** add constant value to a row */
5640 	SCIP_RETCODE SCIProwAddConstant(
5641 	   SCIP_ROW*             row,                /**< LP row */
5642 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5643 	   SCIP_SET*             set,                /**< global SCIP settings */
5644 	   SCIP_STAT*            stat,               /**< problem statistics */
5645 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5646 	   SCIP_LP*              lp,                 /**< current LP data */
5647 	   SCIP_Real             addval              /**< constant value to add to the row */
5648 	   )
5649 	{
5650 	   assert(row != NULL);
5651 	   assert(row->lhs <= row->rhs);
5652 	   assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5653 	   assert(stat != NULL);
5654 	   assert(lp != NULL);
5655 	   assert(!lp->diving || row->lppos == -1);
5656 	
5657 	   if( !SCIPsetIsZero(set, addval) )
5658 	   {
5659 	      SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5660 	   }
5661 	
5662 	   return SCIP_OKAY;
5663 	}
5664 	
5665 	/** changes left hand side of LP row */
5666 	SCIP_RETCODE SCIProwChgLhs(
5667 	   SCIP_ROW*             row,                /**< LP row */
5668 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5669 	   SCIP_SET*             set,                /**< global SCIP settings */
5670 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5671 	   SCIP_LP*              lp,                 /**< current LP data */
5672 	   SCIP_Real             lhs                 /**< new left hand side */
5673 	   )
5674 	{
5675 	   assert(row != NULL);
5676 	   assert(lp != NULL);
5677 	
5678 	   if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5679 	   {
5680 	      SCIP_Real oldlhs;
5681 	
5682 	      oldlhs = row->lhs;
5683 	
5684 	      row->lhs = lhs;
5685 	      SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) );
5686 	
5687 	      if( !lp->diving )
5688 	      {
5689 	         /* issue row side changed event */
5690 	         SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5691 	      }
5692 	   }
5693 	
5694 	   return SCIP_OKAY;
5695 	}
5696 	
5697 	/** changes right hand side of LP row */
5698 	SCIP_RETCODE SCIProwChgRhs(
5699 	   SCIP_ROW*             row,                /**< LP row */
5700 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5701 	   SCIP_SET*             set,                /**< global SCIP settings */
5702 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5703 	   SCIP_LP*              lp,                 /**< current LP data */
5704 	   SCIP_Real             rhs                 /**< new right hand side */
5705 	   )
5706 	{
5707 	   assert(row != NULL);
5708 	   assert(lp != NULL);
5709 	
5710 	   if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5711 	   {
5712 	      SCIP_Real oldrhs;
5713 	
5714 	      oldrhs = row->rhs;
5715 	
5716 	      row->rhs = rhs;
5717 	      SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) );
5718 	
5719 	      if( !lp->diving )
5720 	      {
5721 	         /* issue row side changed event */
5722 	         SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5723 	      }
5724 	   }
5725 	
5726 	   return SCIP_OKAY;
5727 	}
5728 	
5729 	/** changes the local flag of LP row */
5730 	SCIP_RETCODE SCIProwChgLocal(
5731 	   SCIP_ROW*             row,                /**< LP row */
5732 	   SCIP_Bool             local               /**< new value for local flag */
5733 	   )
5734 	{
5735 	   assert(row != NULL);
5736 	
5737 	   row->local = local;
5738 	
5739 	   return SCIP_OKAY;
5740 	}
5741 	
5742 	/** additional scalars that are tried in integrality scaling */
5743 	static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5744 	static const int nscalars = 9;
5745 	
5746 	/** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5747 	SCIP_RETCODE SCIProwCalcIntegralScalar(
5748 	   SCIP_ROW*             row,                /**< LP row */
5749 	   SCIP_SET*             set,                /**< global SCIP settings */
5750 	   SCIP_Real             mindelta,           /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5751 	   SCIP_Real             maxdelta,           /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5752 	   SCIP_Longint          maxdnom,            /**< maximal denominator allowed in rational numbers */
5753 	   SCIP_Real             maxscale,           /**< maximal allowed scalar */
5754 	   SCIP_Bool             usecontvars,        /**< should the coefficients of the continuous variables also be made integral? */
5755 	   SCIP_Real*            intscalar,          /**< pointer to store scalar that would make the coefficients integral, or NULL */
5756 	   SCIP_Bool*            success             /**< stores whether returned value is valid */
5757 	   )
5758 	{
5759 	#ifndef NDEBUG
5760 	   SCIP_COL* col;
5761 	#endif
5762 	   SCIP_Longint gcd;
5763 	   SCIP_Longint scm;
5764 	   SCIP_Longint nominator;
5765 	   SCIP_Longint denominator;
5766 	   SCIP_Real val;
5767 	   SCIP_Real absval;
5768 	   SCIP_Real minval;
5769 	   SCIP_Real scaleval;
5770 	   SCIP_Real twomultval;
5771 	   SCIP_Bool scalable;
5772 	   SCIP_Bool twomult;
5773 	   SCIP_Bool rational;
5774 	   int c;
5775 	   int s;
5776 	
5777 	   /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5778 	   assert(row != NULL);
5779 	   assert(row->len == 0 || row->cols != NULL);
5780 	   assert(row->len == 0 || row->cols_index != NULL);
5781 	   assert(row->len == 0 || row->vals != NULL);
5782 	   assert(maxdnom >= 1);
5783 	   assert(mindelta < 0.0);
5784 	   assert(maxdelta > 0.0);
5785 	   assert(success != NULL);
5786 	
5787 	   SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5788 	   SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5789 	
5790 	   if( intscalar != NULL )
5791 	      *intscalar = SCIP_INVALID;
5792 	   *success = FALSE;
5793 	
5794 	   /* get minimal absolute non-zero value */
5795 	   minval = SCIP_REAL_MAX;
5796 	   for( c = 0; c < row->len; ++c )
5797 	   {
5798 	#ifndef NDEBUG
5799 	      col = row->cols[c];
5800 	      assert(col != NULL);
5801 	      assert(col->var != NULL);
5802 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
5803 	      assert(SCIPvarGetCol(col->var) == col);
5804 	#endif
5805 	      val = row->vals[c];
5806 	      assert(!SCIPsetIsZero(set, val));
5807 	
5808 	      if( val < mindelta || val > maxdelta )
5809 	      {
5810 	         absval = REALABS(val);
5811 	         minval = MIN(minval, absval);
5812 	      }
5813 	   }
5814 	   if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5815 	   {
5816 	      /* all coefficients are zero (inside tolerances) */
5817 	      if( intscalar != NULL )
5818 	         *intscalar = 1.0;
5819 	      *success = TRUE;
5820 	      SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5821 	
5822 	      return SCIP_OKAY;
5823 	   }
5824 	   assert(minval > MIN(-mindelta, maxdelta));
5825 	   assert(SCIPsetIsPositive(set, minval));
5826 	   assert(!SCIPsetIsInfinity(set, minval));
5827 	
5828 	   /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5829 	    * and a power of 2
5830 	    */
5831 	   scaleval = 1.0/minval;
5832 	   scalable = (scaleval <= maxscale);
5833 	   for( c = 0; c < row->len && scalable; ++c )
5834 	   {
5835 	      /* don't look at continuous variables, if we don't have to */
5836 	      if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5837 	         continue;
5838 	
5839 	      /* check, if the coefficient can be scaled with a simple scalar */
5840 	      val = row->vals[c];
5841 	      absval = REALABS(val);
5842 	      while( scaleval <= maxscale
5843 	         && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5844 	      {
5845 	         for( s = 0; s < nscalars; ++s )
5846 	         {
5847 	            if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5848 	            {
5849 	               scaleval *= scalars[s];
5850 	               break;
5851 	            }
5852 	         }
5853 	         if( s >= nscalars )
5854 	            scaleval *= 2.0;
5855 	      }
5856 	      scalable = (scaleval <= maxscale);
5857 	      SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5858 	   }
5859 	   if( scalable )
5860 	   {
5861 	      /* make row coefficients integral by dividing them by the smallest coefficient
5862 	       * (and multiplying them with a power of 2)
5863 	       */
5864 	      assert(scaleval <= maxscale);
5865 	      if( intscalar != NULL )
5866 	         *intscalar = scaleval;
5867 	      *success = TRUE;
5868 	      SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5869 	
5870 	      return SCIP_OKAY;
5871 	   }
5872 	
5873 	   /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5874 	   twomultval = 1.0;
5875 	   twomult = (twomultval <= maxscale);
5876 	   for( c = 0; c < row->len && twomult; ++c )
5877 	   {
5878 	      /* don't look at continuous variables, if we don't have to */
5879 	      if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5880 	         continue;
5881 	
5882 	      /* check, if the coefficient can be scaled with a simple scalar */
5883 	      val = row->vals[c];
5884 	      absval = REALABS(val);
5885 	      while( twomultval <= maxscale
5886 	         && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5887 	      {
5888 	         for( s = 0; s < nscalars; ++s )
5889 	         {
5890 	            if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5891 	            {
5892 	               twomultval *= scalars[s];
5893 	               break;
5894 	            }
5895 	         }
5896 	         if( s >= nscalars )
5897 	            twomultval *= 2.0;
5898 	      }
5899 	      twomult = (twomultval <= maxscale);
5900 	      SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5901 	         val, twomultval, val*twomultval, twomult);
5902 	   }
5903 	   if( twomult )
5904 	   {
5905 	      /* make row coefficients integral by multiplying them with a power of 2 */
5906 	      assert(twomultval <= maxscale);
5907 	      if( intscalar != NULL )
5908 	         *intscalar = twomultval;
5909 	      *success = TRUE;
5910 	      SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5911 	
5912 	      return SCIP_OKAY;
5913 	   }
5914 	
5915 	   /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5916 	    * and the smallest common multiple of the denominators
5917 	    */
5918 	   gcd = 1;
5919 	   scm = 1;
5920 	   rational = (maxdnom > 1);
5921 	
5922 	   /* first coefficient (to initialize gcd) */
5923 	   for( c = 0; c < row->len && rational; ++c )
5924 	   {
5925 	      if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5926 	      {
5927 	         val = row->vals[c];
5928 	         rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5929 	         if( rational && nominator != 0 )
5930 	         {
5931 	            assert(denominator > 0);
5932 	            gcd = ABS(nominator);
5933 	            scm = denominator;
5934 	            rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5935 	            SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5936 	               val, nominator, denominator, gcd, scm, rational);
5937 	            break;
5938 	         }
5939 	      }
5940 	   }
5941 	
5942 	   /* remaining coefficients */
5943 	   for( ++c; c < row->len && rational; ++c )
5944 	   {
5945 	      if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5946 	      {
5947 	         val = row->vals[c];
5948 	         rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5949 	         if( rational && nominator != 0 )
5950 	         {
5951 	            assert(denominator > 0);
5952 	            gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5953 	            scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5954 	            rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5955 	            SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5956 	               val, nominator, denominator, gcd, scm, rational);
5957 	         }
5958 	      }
5959 	   }
5960 	
5961 	   if( rational )
5962 	   {
5963 	      /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5964 	      assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5965 	      if( intscalar != NULL )
5966 	         *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5967 	      *success = TRUE;
5968 	      SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5969 	         (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5970 	   }
5971 	   else
5972 	   {
5973 	      assert(!(*success));
5974 	      SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5975 	   }
5976 	
5977 	   return SCIP_OKAY;
5978 	}
5979 	
5980 	/** tries to scale row, s.t. all coefficients become integral */
5981 	SCIP_RETCODE SCIProwMakeIntegral(
5982 	   SCIP_ROW*             row,                /**< LP row */
5983 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5984 	   SCIP_SET*             set,                /**< global SCIP settings */
5985 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
5986 	   SCIP_STAT*            stat,               /**< problem statistics */
5987 	   SCIP_LP*              lp,                 /**< current LP data */
5988 	   SCIP_Real             mindelta,           /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5989 	   SCIP_Real             maxdelta,           /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5990 	   SCIP_Longint          maxdnom,            /**< maximal denominator allowed in rational numbers */
5991 	   SCIP_Real             maxscale,           /**< maximal value to scale row with */
5992 	   SCIP_Bool             usecontvars,        /**< should the coefficients of the continuous variables also be made integral? */
5993 	   SCIP_Bool*            success             /**< stores whether row could be made rational */
5994 	   )
5995 	{
5996 	   SCIP_Real intscalar;
5997 	
5998 	   assert(success != NULL);
5999 	
6000 	   /* calculate scalar to make coefficients integral */
6001 	   SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
6002 	         &intscalar, success) );
6003 	
6004 	   if( *success )
6005 	   {
6006 	      /* scale the row */
6007 	      SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6008 	   }
6009 	
6010 	   return SCIP_OKAY;
6011 	}
6012 	
6013 	/** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6014 	 *  higher ones
6015 	 */
6016 	void SCIProwSort(
6017 	   SCIP_ROW*             row                 /**< row to be sorted */
6018 	   )
6019 	{
6020 	   assert(row != NULL);
6021 	
6022 	   /* sort LP columns */
6023 	   rowSortLP(row);
6024 	
6025 	   /* sort non-LP columns */
6026 	   rowSortNonLP(row);
6027 	
6028 	#ifdef SCIP_MORE_DEBUG
6029 	   /* check the sorting */
6030 	   {
6031 	      int c;
6032 	      if( !row->delaysort )
6033 	      {
6034 	         for( c = 1; c < row->nlpcols; ++c )
6035 	            assert(row->cols[c]->index >= row->cols[c-1]->index);
6036 	         for( c = row->nlpcols + 1; c < row->len; ++c )
6037 	            assert(row->cols[c]->index >= row->cols[c-1]->index);
6038 	      }
6039 	   }
6040 	#endif
6041 	}
6042 	
6043 	/** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6044 	 *  zero entries from row
6045 	 *  the row must not be linked to the columns; otherwise, we would need to update the columns as
6046 	 *  well, which is too expensive
6047 	 */
6048 	static
6049 	void rowMerge(
6050 	   SCIP_ROW*             row,                /**< row to be sorted */
6051 	   SCIP_SET*             set                 /**< global SCIP settings */
6052 	   )
6053 	{
6054 	   assert(row != NULL);
6055 	   assert(!row->delaysort);
6056 	   assert(row->nunlinked == row->len);
6057 	   assert(row->nlpcols == 0);
6058 	
6059 	   SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6060 	
6061 	   /* do nothing on empty rows; if row is sorted, nothing has to be done */
6062 	   if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6063 	   {
6064 	      SCIP_COL** cols;
6065 	      int* cols_index;
6066 	      SCIP_Real* vals;
6067 	      int s;
6068 	      int t;
6069 	
6070 	      /* make sure, the row is sorted */
6071 	      SCIProwSort(row);
6072 	      assert(row->lpcolssorted);
6073 	      assert(row->nonlpcolssorted);
6074 	
6075 	      /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6076 	      cols = row->cols;
6077 	      cols_index = row->cols_index;
6078 	      vals = row->vals;
6079 	      assert(cols != NULL);
6080 	      assert(cols_index != NULL);
6081 	      assert(vals != NULL);
6082 	
6083 	      t = 0;
6084 	      row->integral = TRUE;
6085 	      assert(!SCIPsetIsZero(set, vals[0]));
6086 	      assert(row->linkpos[0] == -1);
6087 	
6088 	      for( s = 1; s < row->len; ++s )
6089 	      {
6090 	         assert(!SCIPsetIsZero(set, vals[s]));
6091 	         assert(row->linkpos[s] == -1);
6092 	
6093 	         if( cols[s] == cols[t] )
6094 	         {
6095 	            /* merge entries with equal column */
6096 	            vals[t] += vals[s];
6097 	         }
6098 	         else
6099 	         {
6100 	            /* go to the next entry, overwriting current entry if coefficient is zero */
6101 	            if( !SCIPsetIsZero(set, vals[t]) )
6102 	            {
6103 	               /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6104 	               vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6105 	
6106 	               row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6107 	               t++;
6108 	            }
6109 	            cols[t] = cols[s];
6110 	            cols_index[t] = cols_index[s];
6111 	            vals[t] = vals[s];
6112 	         }
6113 	      }
6114 	      if( !SCIPsetIsZero(set, vals[t]) )
6115 	      {
6116 	         row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6117 	         t++;
6118 	      }
6119 	      assert(s == row->len);
6120 	      assert(t <= row->len);
6121 	
6122 	      row->len = t;
6123 	      row->nunlinked = t;
6124 	
6125 	      /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6126 	      if( t < s )
6127 	         rowCalcNorms(row, set);
6128 	   }
6129 	
6130 	#ifndef NDEBUG
6131 	   /* check for double entries */
6132 	   {
6133 	      int i;
6134 	      int j;
6135 	
6136 	      for( i = 0; i < row->len; ++i )
6137 	      {
6138 	         assert(row->cols[i] != NULL);
6139 	         assert(row->cols[i]->index == row->cols_index[i]);
6140 	         for( j = i+1; j < row->len; ++j )
6141 	            assert(row->cols[i] != row->cols[j]);
6142 	      }
6143 	   }
6144 	#endif
6145 	}
6146 	
6147 	/** enables delaying of row sorting */
6148 	void SCIProwDelaySort(
6149 	   SCIP_ROW*             row                 /**< LP row */
6150 	   )
6151 	{
6152 	   assert(row != NULL);
6153 	   assert(!row->delaysort);
6154 	
6155 	   row->delaysort = TRUE;
6156 	}
6157 	
6158 	/** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6159 	void SCIProwForceSort(
6160 	   SCIP_ROW*             row,                /**< LP row */
6161 	   SCIP_SET*             set                 /**< global SCIP settings */
6162 	   )
6163 	{
6164 	   assert(row != NULL);
6165 	   assert(row->delaysort);
6166 	
6167 	   row->delaysort = FALSE;
6168 	   rowMerge(row, set);
6169 	}
6170 	
6171 	/** recalculates the current activity of a row */
6172 	void SCIProwRecalcLPActivity(
6173 	   SCIP_ROW*             row,                /**< LP row */
6174 	   SCIP_STAT*            stat                /**< problem statistics */
6175 	   )
6176 	{
6177 	   SCIP_COL* col;
6178 	   int c;
6179 	
6180 	   assert(row != NULL);
6181 	   assert(stat != NULL);
6182 	
6183 	   row->activity = row->constant;
6184 	   for( c = 0; c < row->nlpcols; ++c )
6185 	   {
6186 	      col = row->cols[c];
6187 	      assert(col != NULL);
6188 	      assert(col->primsol != SCIP_INVALID);  /*lint !e777*/
6189 	      assert(col->lppos >= 0);
6190 	      assert(row->linkpos[c] >= 0);
6191 	      row->activity += row->vals[c] * col->primsol;
6192 	   }
6193 	
6194 	   if( row->nunlinked > 0 )
6195 	   {
6196 	      for( c = row->nlpcols; c < row->len; ++c )
6197 	      {
6198 	         col = row->cols[c];
6199 	         assert(col != NULL);
6200 	         assert(col->lppos >= 0 || col->primsol == 0.0);
6201 	         assert(col->lppos == -1 || row->linkpos[c] == -1);
6202 	         if( col->lppos >= 0 )
6203 	            row->activity += row->vals[c] * col->primsol;
6204 	      }
6205 	   }
6206 	#ifndef NDEBUG
6207 	   else
6208 	   {
6209 	      for( c = row->nlpcols; c < row->len; ++c )
6210 	      {
6211 	         col = row->cols[c];
6212 	         assert(col != NULL);
6213 	         assert(col->primsol == 0.0);
6214 	         assert(col->lppos == -1);
6215 	         assert(row->linkpos[c] >= 0);
6216 	      }
6217 	   }
6218 	#endif
6219 	
6220 	   row->validactivitylp = stat->lpcount;
6221 	}
6222 	
6223 	/** returns the activity of a row in the current LP solution */
6224 	SCIP_Real SCIProwGetLPActivity(
6225 	   SCIP_ROW*             row,                /**< LP row */
6226 	   SCIP_SET*             set,                /**< global SCIP settings */
6227 	   SCIP_STAT*            stat,               /**< problem statistics */
6228 	   SCIP_LP*              lp                  /**< current LP data */
6229 	   )
6230 	{
6231 	   SCIP_Real inf;
6232 	   SCIP_Real activity;
6233 	
6234 	   assert(row != NULL);
6235 	   assert(stat != NULL);
6236 	   assert(lp != NULL);
6237 	   assert(row->validactivitylp <= stat->lpcount);
6238 	   assert(lp->validsollp == stat->lpcount);
6239 	
6240 	   if( row->validactivitylp != stat->lpcount )
6241 	      SCIProwRecalcLPActivity(row, stat);
6242 	   assert(row->validactivitylp == stat->lpcount);
6243 	   assert(row->activity != SCIP_INVALID);  /*lint !e777*/
6244 	
6245 	   activity = row->activity;
6246 	   inf = SCIPsetInfinity(set);
6247 	   activity = MAX(activity, -inf);
6248 	   activity = MIN(activity, +inf);
6249 	
6250 	   return activity;
6251 	}
6252 	
6253 	/** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6254 	SCIP_Real SCIProwGetLPFeasibility(
6255 	   SCIP_ROW*             row,                /**< LP row */
6256 	   SCIP_SET*             set,                /**< global SCIP settings */
6257 	   SCIP_STAT*            stat,               /**< problem statistics */
6258 	   SCIP_LP*              lp                  /**< current LP data */
6259 	   )
6260 	{
6261 	   SCIP_Real activity;
6262 	
6263 	   assert(row != NULL);
6264 	
6265 	   activity = SCIProwGetLPActivity(row, set, stat, lp);
6266 	
6267 	   return MIN(row->rhs - activity, activity - row->lhs);
6268 	}
6269 	
6270 	/** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6271 	 *
6272 	 *  @todo Implement calculation of activities similar to LPs.
6273 	 */
6274 	SCIP_Real SCIProwGetRelaxFeasibility(
6275 	   SCIP_ROW*             row,                /**< LP row */
6276 	   SCIP_SET*             set,                /**< global SCIP settings */
6277 	   SCIP_STAT*            stat                /**< problem statistics */
6278 	   )
6279 	{
6280 	   SCIP_Real inf;
6281 	   SCIP_Real activity;
6282 	   SCIP_COL* col;
6283 	   int c;
6284 	
6285 	   assert( row != NULL );
6286 	   assert( stat != NULL );
6287 	
6288 	   activity = row->constant;
6289 	   for (c = 0; c < row->nlpcols; ++c)
6290 	   {
6291 	      col = row->cols[c];
6292 	      assert( col != NULL );
6293 	      assert( col->lppos >= 0 );
6294 	      assert( col->var != NULL );
6295 	      assert( row->linkpos[c] >= 0 );
6296 	      activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6297 	   }
6298 	
6299 	   if ( row->nunlinked > 0 )
6300 	   {
6301 	      for (c = row->nlpcols; c < row->len; ++c)
6302 	      {
6303 	         col = row->cols[c];
6304 	         assert( col != NULL );
6305 	         assert( col->lppos == -1 || row->linkpos[c] == -1 );
6306 	         if ( col->lppos >= 0 )
6307 	         {
6308 	            assert( col->var != NULL );
6309 	            activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6310 	         }
6311 	      }
6312 	   }
6313 	#ifndef NDEBUG
6314 	   else
6315 	   {
6316 	      for (c = row->nlpcols; c < row->len; ++c)
6317 	      {
6318 	         col = row->cols[c];
6319 	         assert( col != NULL );
6320 	         assert( col->lppos == -1 );
6321 	         assert( row->linkpos[c] >= 0 );
6322 	      }
6323 	   }
6324 	#endif
6325 	   inf = SCIPsetInfinity(set);
6326 	   activity = MAX(activity, -inf);
6327 	   activity = MIN(activity, +inf);
6328 	
6329 	   return MIN(row->rhs - activity, activity - row->lhs);
6330 	}
6331 	
6332 	/** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6333 	 *
6334 	 *  @todo Implement calculation of activities similar to LPs.
6335 	 */
6336 	SCIP_Real SCIProwGetNLPFeasibility(
6337 	   SCIP_ROW*             row,                /**< LP row */
6338 	   SCIP_SET*             set,                /**< global SCIP settings */
6339 	   SCIP_STAT*            stat                /**< problem statistics */
6340 	   )
6341 	{
6342 	   SCIP_Real inf;
6343 	   SCIP_Real activity;
6344 	   SCIP_COL* col;
6345 	   int c;
6346 	
6347 	   assert( row != NULL );
6348 	   assert( stat != NULL );
6349 	
6350 	   activity = row->constant;
6351 	   for (c = 0; c < row->nlpcols; ++c)
6352 	   {
6353 	      col = row->cols[c];
6354 	      assert( col != NULL );
6355 	      assert( col->lppos >= 0 );
6356 	      assert( col->var != NULL );
6357 	      assert( row->linkpos[c] >= 0 );
6358 	      activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6359 	   }
6360 	
6361 	   if ( row->nunlinked > 0 )
6362 	   {
6363 	      for (c = row->nlpcols; c < row->len; ++c)
6364 	      {
6365 	         col = row->cols[c];
6366 	         assert( col != NULL );
6367 	         assert( col->lppos == -1 || row->linkpos[c] == -1 );
6368 	         if ( col->lppos >= 0 )
6369 	         {
6370 	            assert( col->var != NULL );
6371 	            activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6372 	         }
6373 	      }
6374 	   }
6375 	#ifndef NDEBUG
6376 	   else
6377 	   {
6378 	      for (c = row->nlpcols; c < row->len; ++c)
6379 	      {
6380 	         col = row->cols[c];
6381 	         assert( col != NULL );
6382 	         assert( col->lppos == -1 );
6383 	         assert( row->linkpos[c] >= 0 );
6384 	      }
6385 	   }
6386 	#endif
6387 	   inf = SCIPsetInfinity(set);
6388 	   activity = MAX(activity, -inf);
6389 	   activity = MIN(activity, +inf);
6390 	
6391 	   return MIN(row->rhs - activity, activity - row->lhs);
6392 	}
6393 	
6394 	/** calculates the current pseudo activity of a row */
6395 	void SCIProwRecalcPseudoActivity(
6396 	   SCIP_ROW*             row,                /**< row data */
6397 	   SCIP_STAT*            stat                /**< problem statistics */
6398 	   )
6399 	{
6400 	   SCIP_COL* col;
6401 	   int i;
6402 	
6403 	   assert(row != NULL);
6404 	   assert(stat != NULL);
6405 	
6406 	   row->pseudoactivity = row->constant;
6407 	   for( i = 0; i < row->len; ++i )
6408 	   {
6409 	      col = row->cols[i];
6410 	      assert(col != NULL);
6411 	      assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6412 	      assert(col->var != NULL);
6413 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
6414 	
6415 	      row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6416 	   }
6417 	   row->validpsactivitydomchg = stat->domchgcount;
6418 	   assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6419 	}
6420 	
6421 	/** returns the pseudo activity of a row in the current pseudo solution */
6422 	SCIP_Real SCIProwGetPseudoActivity(
6423 	   SCIP_ROW*             row,                /**< LP row */
6424 	   SCIP_SET*             set,                /**< global SCIP settings */
6425 	   SCIP_STAT*            stat                /**< problem statistics */
6426 	   )
6427 	{
6428 	   SCIP_Real inf;
6429 	   SCIP_Real activity;
6430 	
6431 	   assert(row != NULL);
6432 	   assert(stat != NULL);
6433 	   assert(row->validpsactivitydomchg <= stat->domchgcount);
6434 	
6435 	   /* check, if pseudo activity has to be calculated */
6436 	   if( row->validpsactivitydomchg != stat->domchgcount )
6437 	      SCIProwRecalcPseudoActivity(row, stat);
6438 	   assert(row->validpsactivitydomchg == stat->domchgcount);
6439 	   assert(row->pseudoactivity != SCIP_INVALID);  /*lint !e777*/
6440 	
6441 	   activity = row->pseudoactivity;
6442 	   inf = SCIPsetInfinity(set);
6443 	   activity = MAX(activity, -inf);
6444 	   activity = MIN(activity, +inf);
6445 	
6446 	   return activity;
6447 	}
6448 	
6449 	/** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6450 	SCIP_Real SCIProwGetPseudoFeasibility(
6451 	   SCIP_ROW*             row,                /**< LP row */
6452 	   SCIP_SET*             set,                /**< global SCIP settings */
6453 	   SCIP_STAT*            stat                /**< problem statistics */
6454 	   )
6455 	{
6456 	   SCIP_Real pseudoactivity;
6457 	
6458 	   assert(row != NULL);
6459 	
6460 	   pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6461 	
6462 	   return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6463 	}
6464 	
6465 	/** returns the activity of a row for a given solution */
6466 	SCIP_Real SCIProwGetSolActivity(
6467 	   SCIP_ROW*             row,                /**< LP row */
6468 	   SCIP_SET*             set,                /**< global SCIP settings */
6469 	   SCIP_STAT*            stat,               /**< problem statistics data */
6470 	   SCIP_SOL*             sol                 /**< primal CIP solution */
6471 	   )
6472 	{
6473 	   SCIP_COL* col;
6474 	   SCIP_Real inf;
6475 	   SCIP_Real activity;
6476 	   SCIP_Real solval;
6477 	   int i;
6478 	
6479 	   assert(row != NULL);
6480 	
6481 	   activity = row->constant;
6482 	   for( i = 0; i < row->len; ++i )
6483 	   {
6484 	      col = row->cols[i];
6485 	      assert(col != NULL);
6486 	      assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6487 	      solval = SCIPsolGetVal(sol, set, stat, col->var);
6488 	      if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6489 	      {
6490 	         if( SCIPsetIsInfinity(set, -row->lhs) )
6491 	            solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6492 	         else if( SCIPsetIsInfinity(set, row->rhs) )
6493 	            solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6494 	         else
6495 	            solval = (col->lb + col->ub)/2.0;
6496 	      }
6497 	      activity += row->vals[i] * solval;
6498 	   }
6499 	
6500 	   inf = SCIPsetInfinity(set);
6501 	   activity = MAX(activity, -inf);
6502 	   activity = MIN(activity, +inf);
6503 	
6504 	   return activity;
6505 	}
6506 	
6507 	/** returns the feasibility of a row for the given solution */
6508 	SCIP_Real SCIProwGetSolFeasibility(
6509 	   SCIP_ROW*             row,                /**< LP row */
6510 	   SCIP_SET*             set,                /**< global SCIP settings */
6511 	   SCIP_STAT*            stat,               /**< problem statistics data */
6512 	   SCIP_SOL*             sol                 /**< primal CIP solution */
6513 	   )
6514 	{
6515 	   SCIP_Real activity;
6516 	
6517 	   assert(row != NULL);
6518 	
6519 	   activity = SCIProwGetSolActivity(row, set, stat, sol);
6520 	
6521 	   return MIN(row->rhs - activity, activity - row->lhs);
6522 	}
6523 	
6524 	/** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6525 	static
6526 	void rowCalcActivityBounds(
6527 	   SCIP_ROW*             row,                /**< row data */
6528 	   SCIP_SET*             set,                /**< global SCIP settings */
6529 	   SCIP_STAT*            stat                /**< problem statistics data */
6530 	   )
6531 	{
6532 	   SCIP_COL* col;
6533 	   SCIP_Real val;
6534 	   SCIP_Bool mininfinite;
6535 	   SCIP_Bool maxinfinite;
6536 	   int i;
6537 	
6538 	   assert(row != NULL);
6539 	   assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6540 	   assert(stat != NULL);
6541 	
6542 	   /* calculate activity bounds */
6543 	   mininfinite = FALSE;
6544 	   maxinfinite = FALSE;
6545 	   row->minactivity = row->constant;
6546 	   row->maxactivity = row->constant;
6547 	   for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6548 	   {
6549 	      col = row->cols[i];
6550 	      assert(col != NULL);
6551 	      assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6552 	      val = row->vals[i];
6553 	      if( val >= 0.0 )
6554 	      {
6555 	         mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6556 	         maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6557 	         if( !mininfinite )
6558 	            row->minactivity += val * col->lb;
6559 	         if( !maxinfinite )
6560 	            row->maxactivity += val * col->ub;
6561 	      }
6562 	      else
6563 	      {
6564 	         mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6565 	         maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6566 	         if( !mininfinite )
6567 	            row->minactivity += val * col->ub;
6568 	         if( !maxinfinite )
6569 	            row->maxactivity += val * col->lb;
6570 	      }
6571 	   }
6572 	
6573 	   if( mininfinite )
6574 	      row->minactivity = -SCIPsetInfinity(set);
6575 	   if( maxinfinite )
6576 	      row->maxactivity = SCIPsetInfinity(set);
6577 	   row->validactivitybdsdomchg = stat->domchgcount;
6578 	
6579 	#ifndef NDEBUG
6580 	   {
6581 	      SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6582 	
6583 	      /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6584 	       * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6585 	       * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6586 	       * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6587 	       * tolerance as a proxy to account for the accumulation effect
6588 	       */
6589 	      assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6590 	         || EPSISINT(row->minactivity - row->constant, inttol));
6591 	      assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6592 	         || EPSISINT(row->maxactivity - row->constant, inttol));
6593 	   }
6594 	#endif
6595 	}
6596 	
6597 	/** returns the minimal activity of a row w.r.t. the columns' bounds */
6598 	SCIP_Real SCIProwGetMinActivity(
6599 	   SCIP_ROW*             row,                /**< LP row */
6600 	   SCIP_SET*             set,                /**< global SCIP settings */
6601 	   SCIP_STAT*            stat                /**< problem statistics data */
6602 	   )
6603 	{
6604 	   assert(row != NULL);
6605 	   assert(stat != NULL);
6606 	   assert(row->validactivitybdsdomchg <= stat->domchgcount);
6607 	
6608 	   /* check, if activity bounds has to be calculated */
6609 	   if( row->validactivitybdsdomchg != stat->domchgcount )
6610 	      rowCalcActivityBounds(row, set, stat);
6611 	   assert(row->validactivitybdsdomchg == stat->domchgcount);
6612 	   assert(row->minactivity != SCIP_INVALID);  /*lint !e777*/
6613 	   assert(row->maxactivity != SCIP_INVALID);  /*lint !e777*/
6614 	
6615 	   return row->minactivity;
6616 	}
6617 	
6618 	/** returns the maximal activity of a row w.r.t. the columns' bounds */
6619 	SCIP_Real SCIProwGetMaxActivity(
6620 	   SCIP_ROW*             row,                /**< LP row */
6621 	   SCIP_SET*             set,                /**< global SCIP settings */
6622 	   SCIP_STAT*            stat                /**< problem statistics data */
6623 	   )
6624 	{
6625 	   assert(row != NULL);
6626 	   assert(stat != NULL);
6627 	   assert(row->validactivitybdsdomchg <= stat->domchgcount);
6628 	
6629 	   /* check, if activity bounds has to be calculated */
6630 	   if( row->validactivitybdsdomchg != stat->domchgcount )
6631 	      rowCalcActivityBounds(row, set, stat);
6632 	   assert(row->validactivitybdsdomchg == stat->domchgcount);
6633 	   assert(row->minactivity != SCIP_INVALID);  /*lint !e777*/
6634 	   assert(row->maxactivity != SCIP_INVALID);  /*lint !e777*/
6635 	
6636 	   return row->maxactivity;
6637 	}
6638 	
6639 	/** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6640 	SCIP_Bool SCIProwIsRedundant(
6641 	   SCIP_ROW*             row,                /**< LP row */
6642 	   SCIP_SET*             set,                /**< global SCIP settings */
6643 	   SCIP_STAT*            stat                /**< problem statistics data */
6644 	   )
6645 	{
6646 	   assert(row != NULL);
6647 	
6648 	   if( row->modifiable )
6649 	      return FALSE;
6650 	   if( !SCIPsetIsInfinity(set, -row->lhs) )
6651 	   {
6652 	      SCIP_Real minactivity;
6653 	
6654 	      minactivity = SCIProwGetMinActivity(row, set, stat);
6655 	      if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6656 	         return FALSE;
6657 	   }
6658 	   if( !SCIPsetIsInfinity(set, row->rhs) )
6659 	   {
6660 	      SCIP_Real maxactivity;
6661 	
6662 	      maxactivity = SCIProwGetMaxActivity(row, set, stat);
6663 	      if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6664 	         return FALSE;
6665 	   }
6666 	
6667 	   return TRUE;
6668 	}
6669 	
6670 	/** gets maximal absolute value of row vector coefficients */
6671 	SCIP_Real SCIProwGetMaxval(
6672 	   SCIP_ROW*             row,                /**< LP row */
6673 	   SCIP_SET*             set                 /**< global SCIP settings */
6674 	   )
6675 	{
6676 	   assert(row != NULL);
6677 	
6678 	   if( row->nummaxval == 0 )
6679 	      rowCalcIdxsAndVals(row, set);
6680 	   assert(row->nummaxval > 0);
6681 	   assert(row->maxval >= 0.0 || row->len == 0);
6682 	
6683 	   return row->maxval;
6684 	}
6685 	
6686 	/** gets minimal absolute value of row vector's non-zero coefficients */
6687 	SCIP_Real SCIProwGetMinval(
6688 	   SCIP_ROW*             row,                /**< LP row */
6689 	   SCIP_SET*             set                 /**< global SCIP settings */
6690 	   )
6691 	{
6692 	   assert(row != NULL);
6693 	
6694 	   if( row->numminval == 0 )
6695 	      rowCalcIdxsAndVals(row, set);
6696 	   assert(row->numminval > 0);
6697 	   assert(row->minval >= 0.0 || row->len == 0);
6698 	
6699 	   return row->minval;
6700 	}
6701 	
6702 	/** gets maximal column index of row entries */
6703 	int SCIProwGetMaxidx(
6704 	   SCIP_ROW*             row,                /**< LP row */
6705 	   SCIP_SET*             set                 /**< global SCIP settings */
6706 	   )
6707 	{
6708 	   assert(row != NULL);
6709 	
6710 	   if( row->validminmaxidx == 0 )
6711 	      rowCalcIdxsAndVals(row, set);
6712 	   assert(row->maxidx >= 0 || row->len == 0);
6713 	   assert(row->validminmaxidx);
6714 	
6715 	   return row->maxidx;
6716 	}
6717 	
6718 	/** gets minimal column index of row entries */
6719 	int SCIProwGetMinidx(
6720 	   SCIP_ROW*             row,                /**< LP row */
6721 	   SCIP_SET*             set                 /**< global SCIP settings */
6722 	   )
6723 	{
6724 	   assert(row != NULL);
6725 	
6726 	   if( row->validminmaxidx == 0 )
6727 	      rowCalcIdxsAndVals(row, set);
6728 	   assert(row->minidx >= 0 || row->len == 0);
6729 	   assert(row->validminmaxidx);
6730 	
6731 	   return row->minidx;
6732 	}
6733 	
6734 	/** gets number of integral columns in row */
6735 	int SCIProwGetNumIntCols(
6736 	   SCIP_ROW*             row,                /**< LP row */
6737 	   SCIP_SET*             set                 /**< global SCIP settings */
6738 	   )
6739 	{
6740 	   assert(row != NULL);
6741 	
6742 	   if( row->numintcols == -1 )
6743 	      rowCalcIdxsAndVals(row, set);
6744 	
6745 	   assert(row->numintcols <= row->len && row->numintcols >= 0);
6746 	
6747 	   return row->numintcols;
6748 	}
6749 	
6750 	/** returns row's cutoff distance in the direction of the given primal solution */
6751 	SCIP_Real SCIProwGetLPSolCutoffDistance(
6752 	   SCIP_ROW*             row,                /**< LP row */
6753 	   SCIP_SET*             set,                /**< global SCIP settings */
6754 	   SCIP_STAT*            stat,               /**< problem statistics data */
6755 	   SCIP_SOL*             sol,                /**< solution to compute direction for cutoff distance; must not be NULL */
6756 	   SCIP_LP*              lp                  /**< current LP data */
6757 	   )
6758 	{
6759 	   SCIP_Real solcutoffdist;
6760 	   int k;
6761 	
6762 	   assert(sol != NULL);
6763 	
6764 	   if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6765 	   {
6766 	      SCIP_Real scale = 0.0;
6767 	
6768 	      lp->validsoldirlp = stat->lpcount;
6769 	      lp->validsoldirsol = sol;
6770 	
6771 	      SCIP_CALL_ABORT( ensureSoldirectionSize(lp, lp->ncols) );
6772 	
6773 	      for( k = 0; k < lp->ncols; ++k )
6774 	      {
6775 	         assert(lp->cols[k]->lppos == k);
6776 	         lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6777 	         scale += SQR(lp->soldirection[k]);
6778 	      }
6779 	
6780 	      if( scale > 0.0 )
6781 	      {
6782 	         scale = 1.0 / SQRT(scale);
6783 	
6784 	         for( k = 0; k < lp->ncols; ++k )
6785 	            lp->soldirection[k] *= scale;
6786 	      }
6787 	   }
6788 	
6789 	   solcutoffdist = 0.0;
6790 	   for( k = 0; k < row->nlpcols; ++k )
6791 	      solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6792 	
6793 	   for( k = row->nlpcols; k < row->len; ++k )
6794 	   {
6795 	      if( row->cols[k]->lppos >= 0 )
6796 	         solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6797 	   }
6798 	
6799 	   if( SCIPsetIsSumZero(set, solcutoffdist) )
6800 	      solcutoffdist = set->num_sumepsilon;
6801 	
6802 	   solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6803 	
6804 	   return solcutoffdist;
6805 	}
6806 	
6807 	/** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6808 	SCIP_Real SCIProwGetLPEfficacy(
6809 	   SCIP_ROW*             row,                /**< LP row */
6810 	   SCIP_SET*             set,                /**< global SCIP settings */
6811 	   SCIP_STAT*            stat,               /**< problem statistics data */
6812 	   SCIP_LP*              lp                  /**< current LP data */
6813 	   )
6814 	{
6815 	   SCIP_Real norm;
6816 	   SCIP_Real feasibility;
6817 	   SCIP_Real eps;
6818 	
6819 	   assert(set != NULL);
6820 	
6821 	   switch( set->sepa_efficacynorm )
6822 	   {
6823 	   case 'e':
6824 	      norm = SCIProwGetNorm(row);
6825 	      break;
6826 	   case 'm':
6827 	      norm = SCIProwGetMaxval(row, set);
6828 	      break;
6829 	   case 's':
6830 	      norm = SCIProwGetSumNorm(row);
6831 	      break;
6832 	   case 'd':
6833 	      norm = (row->len == 0 ? 0.0 : 1.0);
6834 	      break;
6835 	   default:
6836 	      SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6837 	      SCIPABORT();
6838 	      norm = 0.0; /*lint !e527*/
6839 	   }
6840 	
6841 	   eps = SCIPsetSumepsilon(set);
6842 	   norm = MAX(norm, eps);
6843 	   feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6844 	
6845 	   return -feasibility / norm;
6846 	}
6847 	
6848 	/** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6849 	SCIP_Bool SCIProwIsLPEfficacious(
6850 	   SCIP_ROW*             row,                /**< LP row */
6851 	   SCIP_SET*             set,                /**< global SCIP settings */
6852 	   SCIP_STAT*            stat,               /**< problem statistics data */
6853 	   SCIP_LP*              lp,                 /**< current LP data */
6854 	   SCIP_Bool             root                /**< should the root's minimal cut efficacy be used? */
6855 	   )
6856 	{
6857 	   SCIP_Real efficacy;
6858 	
6859 	   efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6860 	
6861 	   return SCIPsetIsEfficacious(set, root, efficacy);
6862 	}
6863 	
6864 	/** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6865 	SCIP_Real SCIProwGetSolEfficacy(
6866 	   SCIP_ROW*             row,                /**< LP row */
6867 	   SCIP_SET*             set,                /**< global SCIP settings */
6868 	   SCIP_STAT*            stat,               /**< problem statistics data */
6869 	   SCIP_SOL*             sol                 /**< primal CIP solution */
6870 	   )
6871 	{
6872 	   SCIP_Real norm;
6873 	   SCIP_Real feasibility;
6874 	   SCIP_Real eps;
6875 	
6876 	   assert(set != NULL);
6877 	
6878 	   switch( set->sepa_efficacynorm )
6879 	   {
6880 	   case 'e':
6881 	      norm = SCIProwGetNorm(row);
6882 	      break;
6883 	   case 'm':
6884 	      norm = SCIProwGetMaxval(row, set);
6885 	      break;
6886 	   case 's':
6887 	      norm = SCIProwGetSumNorm(row);
6888 	      break;
6889 	   case 'd':
6890 	      norm = (row->len == 0 ? 0.0 : 1.0);
6891 	      break;
6892 	   default:
6893 	      SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6894 	      SCIPABORT();
6895 	      norm = 0.0; /*lint !e527*/
6896 	   }
6897 	
6898 	   eps = SCIPsetSumepsilon(set);
6899 	   norm = MAX(norm, eps);
6900 	   feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6901 	
6902 	   return -feasibility / norm;
6903 	}
6904 	
6905 	/** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6906 	 *  efficacy
6907 	 */
6908 	SCIP_Bool SCIProwIsSolEfficacious(
6909 	   SCIP_ROW*             row,                /**< LP row */
6910 	   SCIP_SET*             set,                /**< global SCIP settings */
6911 	   SCIP_STAT*            stat,               /**< problem statistics data */
6912 	   SCIP_SOL*             sol,                /**< primal CIP solution */
6913 	   SCIP_Bool             root                /**< should the root's minimal cut efficacy be used? */
6914 	   )
6915 	{
6916 	   SCIP_Real efficacy;
6917 	
6918 	   efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6919 	
6920 	   return SCIPsetIsEfficacious(set, root, efficacy);
6921 	}
6922 	
6923 	/** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6924 	SCIP_Real SCIProwGetRelaxEfficacy(
6925 	   SCIP_ROW*             row,                /**< LP row */
6926 	   SCIP_SET*             set,                /**< global SCIP settings */
6927 	   SCIP_STAT*            stat                /**< problem statistics data */
6928 	   )
6929 	{
6930 	   SCIP_Real norm;
6931 	   SCIP_Real feasibility;
6932 	   SCIP_Real eps;
6933 	
6934 	   assert(set != NULL);
6935 	
6936 	   switch( set->sepa_efficacynorm )
6937 	   {
6938 	   case 'e':
6939 	      norm = SCIProwGetNorm(row);
6940 	      break;
6941 	   case 'm':
6942 	      norm = SCIProwGetMaxval(row, set);
6943 	      break;
6944 	   case 's':
6945 	      norm = SCIProwGetSumNorm(row);
6946 	      break;
6947 	   case 'd':
6948 	      norm = (row->len == 0 ? 0.0 : 1.0);
6949 	      break;
6950 	   default:
6951 	      SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6952 	      SCIPABORT();
6953 	      norm = 0.0; /*lint !e527*/
6954 	   }
6955 	
6956 	   eps = SCIPsetSumepsilon(set);
6957 	   norm = MAX(norm, eps);
6958 	   feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6959 	
6960 	   return -feasibility / norm;
6961 	}
6962 	
6963 	/** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6964 	SCIP_Real SCIProwGetNLPEfficacy(
6965 	   SCIP_ROW*             row,                /**< LP row */
6966 	   SCIP_SET*             set,                /**< global SCIP settings */
6967 	   SCIP_STAT*            stat                /**< problem statistics data */
6968 	   )
6969 	{
6970 	   SCIP_Real norm;
6971 	   SCIP_Real feasibility;
6972 	   SCIP_Real eps;
6973 	
6974 	   assert(set != NULL);
6975 	
6976 	   switch( set->sepa_efficacynorm )
6977 	   {
6978 	   case 'e':
6979 	      norm = SCIProwGetNorm(row);
6980 	      break;
6981 	   case 'm':
6982 	      norm = SCIProwGetMaxval(row, set);
6983 	      break;
6984 	   case 's':
6985 	      norm = SCIProwGetSumNorm(row);
6986 	      break;
6987 	   case 'd':
6988 	      norm = (row->len == 0 ? 0.0 : 1.0);
6989 	      break;
6990 	   default:
6991 	      SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6992 	      SCIPABORT();
6993 	      norm = 0.0; /*lint !e527*/
6994 	   }
6995 	
6996 	   eps = SCIPsetSumepsilon(set);
6997 	   norm = MAX(norm, eps);
6998 	   feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6999 	
7000 	   return -feasibility / norm;
7001 	}
7002 	
7003 	/** returns the scalar product of the coefficient vectors of the two given rows
7004 	 *
7005 	 *  @note the scalar product is computed w.r.t. the current LP columns only
7006 	 *  @todo also consider non-LP columns for the computation?
7007 	 */
7008 	SCIP_Real SCIProwGetScalarProduct(
7009 	   SCIP_ROW*             row1,               /**< first LP row */
7010 	   SCIP_ROW*             row2                /**< second LP row */
7011 	   )
7012 	{
7013 	   SCIP_Real scalarprod;
7014 	   int* row1colsidx;
7015 	   int* row2colsidx;
7016 	   int i1;
7017 	   int i2;
7018 	
7019 	   assert(row1 != NULL);
7020 	   assert(row2 != NULL);
7021 	
7022 	   /* Sort the column indices of both rows.
7023 	    *
7024 	    * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7025 	    * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7026 	    * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7027 	    * for both or one of the non-LP columns for both.
7028 	    * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7029 	    * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7030 	    * columns can be added later and remain unlinked while all previously added columns might already be linked.
7031 	    * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7032 	    *
7033 	    * We distinguish the following cases:
7034 	    *
7035 	    * 1) both rows have no unlinked columns
7036 	    *    -> we just check the LP partitions
7037 	    *
7038 	    * 2) exactly one row is completely unlinked, the other one is completely linked
7039 	    *    -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7040 	    *       (thus all common LP columns are regarded)
7041 	    *
7042 	    * 3) we have unlinked and LP columns in both rows
7043 	    *    -> we need to compare four partitions at once
7044 	    *
7045 	    * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7046 	    *     -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7047 	    *        other row
7048 	    *
7049 	    * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7050 	    *     -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7051 	    *
7052 	    * 5) both rows are completely unlinked
7053 	    *    -> we need to compare two partitions: both complete rows
7054 	    */
7055 	   SCIProwSort(row1);
7056 	   assert(row1->lpcolssorted);
7057 	   assert(row1->nonlpcolssorted);
7058 	   SCIProwSort(row2);
7059 	   assert(row2->lpcolssorted);
7060 	   assert(row2->nonlpcolssorted);
7061 	
7062 	   assert(row1->nunlinked <= row1->len - row1->nlpcols);
7063 	   assert(row2->nunlinked <= row2->len - row2->nlpcols);
7064 	
7065 	   row1colsidx = row1->cols_index;
7066 	   row2colsidx = row2->cols_index;
7067 	
7068 	#ifndef NDEBUG
7069 	   /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7070 	   if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7071 	   {
7072 	      i1 = 0;
7073 	      i2 = row2->nlpcols;
7074 	      while( i1 < row1->nlpcols && i2 < row2->len )
7075 	      {
7076 	         assert(row1->cols[i1] != row2->cols[i2]);
7077 	         if( row1->cols[i1]->index < row2->cols[i2]->index )
7078 	            ++i1;
7079 	         else
7080 	         {
7081 	            assert(row1->cols[i1]->index > row2->cols[i2]->index);
7082 	            ++i2;
7083 	         }
7084 	      }
7085 	      assert(i1 == row1->nlpcols || i2 == row2->len);
7086 	
7087 	      i1 = row1->nlpcols;
7088 	      i2 = 0;
7089 	      while( i1 < row1->len && i2 < row2->nlpcols )
7090 	      {
7091 	         assert(row1->cols[i1] != row2->cols[i2]);
7092 	         if( row1->cols[i1]->index < row2->cols[i2]->index )
7093 	            ++i1;
7094 	         else
7095 	         {
7096 	            assert(row1->cols[i1]->index > row2->cols[i2]->index);
7097 	            ++i2;
7098 	         }
7099 	      }
7100 	      assert(i1 == row1->len || i2 == row2->nlpcols);
7101 	   }
7102 	#endif
7103 	
7104 	   /* The "easy" cases 1) and 2) */
7105 	   if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7106 	      ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7107 	         && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7108 	         && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7109 	   {
7110 	      assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7111 	      assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7112 	
7113 	      /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7114 	       * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7115 	       */
7116 	      i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7117 	      i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7118 	      scalarprod = 0.0;
7119 	
7120 	      /* calculate the scalar product */
7121 	      while( i1 >= 0 && i2 >= 0 )
7122 	      {
7123 	         assert(row1->cols[i1]->index == row1colsidx[i1]);
7124 	         assert(row2->cols[i2]->index == row2colsidx[i2]);
7125 	         assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7126 	         if( row1colsidx[i1] < row2colsidx[i2] )
7127 	            --i2;
7128 	         else if( row1colsidx[i1] > row2colsidx[i2] )
7129 	            --i1;
7130 	         else
7131 	         {
7132 	            scalarprod += row1->vals[i1] * row2->vals[i2];
7133 	            --i1;
7134 	            --i2;
7135 	         }
7136 	      }
7137 	   }
7138 	   /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7139 	   else
7140 	   {
7141 	      SCIP_Bool lpcols;
7142 	      int ilp1;
7143 	      int inlp1;
7144 	      int ilp2;
7145 	      int inlp2;
7146 	      int end1;
7147 	      int end2;
7148 	
7149 	      scalarprod = 0;
7150 	      ilp1 = 0;
7151 	      ilp2 = 0;
7152 	
7153 	      /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7154 	      inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7155 	      inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7156 	
7157 	      /* handle the case of four partitions (case 3) until one partition is finished;
7158 	       * cases 4a), 4b), and 5) will fail the while-condition
7159 	       */
7160 	      while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7161 	      {
7162 	         assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7163 	         assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7164 	         assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7165 	         assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7166 	         assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7167 	         assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7168 	         assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7169 	         assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7170 	
7171 	         /* rows have the same linked LP columns */
7172 	         if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7173 	         {
7174 	            scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7175 	            ++ilp1;
7176 	            ++ilp2;
7177 	         }
7178 	         /* LP column of row1 is the same as unlinked column of row2 */
7179 	         else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7180 	         {
7181 	            scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7182 	            ++ilp1;
7183 	            ++inlp2;
7184 	         }
7185 	         /* unlinked column of row1 is the same as LP column of row2 */
7186 	         else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7187 	         {
7188 	            scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7189 	            ++inlp1;
7190 	            ++ilp2;
7191 	         }
7192 	         /* two unlinked LP columns are the same */
7193 	         else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7194 	         {
7195 	            scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7196 	            ++inlp1;
7197 	            ++inlp2;
7198 	         }
7199 	         /* increase smallest counter */
7200 	         else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7201 	         {
7202 	            if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7203 	            {
7204 	               if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7205 	                  ++ilp1;
7206 	               else
7207 	                  ++ilp2;
7208 	            }
7209 	            else
7210 	            {
7211 	               if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7212 	                  ++ilp1;
7213 	               else
7214 	                  ++inlp2;
7215 	            }
7216 	         }
7217 	         else
7218 	         {
7219 	            if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7220 	            {
7221 	               if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7222 	                  ++inlp1;
7223 	               else
7224 	                  ++ilp2;
7225 	            }
7226 	            else
7227 	            {
7228 	               if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7229 	                  ++inlp1;
7230 	               else
7231 	                  ++inlp2;
7232 	            }
7233 	         }
7234 	      }
7235 	
7236 	      /* One partition was completely handled, we just have to handle the three remaining partitions:
7237 	       * the remaining partition of this row and the two partitions of the other row.
7238 	       * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7239 	       */
7240 	      if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7241 	      {
7242 	         int tmpilp;
7243 	         int tmpinlp;
7244 	
7245 	         assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7246 	
7247 	         SCIPswapPointers((void**) &row1, (void**) &row2);
7248 	         SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7249 	         tmpilp = ilp1;
7250 	         tmpinlp = inlp1;
7251 	         ilp1 = ilp2;
7252 	         inlp1 = inlp2;
7253 	         ilp2 = tmpilp;
7254 	         inlp2 = tmpinlp;
7255 	      }
7256 	
7257 	      /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7258 	       * -> this merges cases 4a) and 4b)
7259 	       */
7260 	      if( ilp1 == row1->nlpcols )
7261 	      {
7262 	         i1 = inlp1;
7263 	         end1 = row1->len;
7264 	         lpcols = FALSE;
7265 	      }
7266 	      else
7267 	      {
7268 	         assert(inlp1 == row1->len);
7269 	
7270 	         i1 = ilp1;
7271 	         end1 = row1->nlpcols;
7272 	         lpcols = TRUE;
7273 	      }
7274 	
7275 	      /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7276 	       * case 5) will fail the while-condition
7277 	       */
7278 	      while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7279 	      {
7280 	         assert(row1->cols[i1]->index == row1colsidx[i1]);
7281 	         assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7282 	         assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7283 	         assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7284 	         assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7285 	
7286 	         /* current column in row 1 is the same as the current LP column in row 2 */
7287 	         if( row1colsidx[i1] == row2colsidx[ilp2] )
7288 	         {
7289 	            scalarprod += row1->vals[i1] * row2->vals[ilp2];
7290 	            ++i1;
7291 	            ++ilp2;
7292 	         }
7293 	         /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7294 	         else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7295 	         {
7296 	            scalarprod += row1->vals[i1] * row2->vals[inlp2];
7297 	            ++i1;
7298 	            ++inlp2;
7299 	         }
7300 	         /* increase smallest counter */
7301 	         else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7302 	         {
7303 	            if( row1colsidx[i1] < row2colsidx[ilp2] )
7304 	               ++i1;
7305 	            else
7306 	               ++ilp2;
7307 	         }
7308 	         else
7309 	         {
7310 	            if( row1colsidx[i1] < row2colsidx[inlp2] )
7311 	               ++i1;
7312 	            else
7313 	               ++inlp2;
7314 	         }
7315 	      }
7316 	
7317 	      /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7318 	       * the two rows
7319 	       */
7320 	      if( i1 < end1 )
7321 	      {
7322 	         /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7323 	         if( ilp2 == row2->nlpcols )
7324 	         {
7325 	            i2 = inlp2;
7326 	            end2 = row2->len;
7327 	            lpcols = FALSE;
7328 	         }
7329 	         else
7330 	         {
7331 	            assert(inlp2 == row2->len);
7332 	
7333 	            i2 = ilp2;
7334 	            end2 = row2->nlpcols;
7335 	         }
7336 	
7337 	         /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7338 	         while( i1 < end1 && i2 < end2 )
7339 	         {
7340 	            assert(row1->cols[i1]->index == row1colsidx[i1]);
7341 	            assert(row2->cols[i2]->index == row2colsidx[i2]);
7342 	            assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7343 	
7344 	            /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7345 	            if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7346 	            {
7347 	               scalarprod += row1->vals[i1] * row2->vals[i2];
7348 	               ++i1;
7349 	               ++i2;
7350 	            }
7351 	            /* increase smallest counter */
7352 	            else if( row1colsidx[i1] < row2colsidx[i2] )
7353 	               ++i1;
7354 	            else
7355 	               ++i2;
7356 	         }
7357 	      }
7358 	   }
7359 	
7360 	   return scalarprod;
7361 	}
7362 	
7363 	/** returns the discrete scalar product of the coefficient vectors of the two given rows */
7364 	static
7365 	int SCIProwGetDiscreteScalarProduct(
7366 	   SCIP_ROW*             row1,               /**< first LP row */
7367 	   SCIP_ROW*             row2                /**< second LP row */
7368 	   )
7369 	{
7370 	   int prod;
7371 	   int* row1colsidx;
7372 	   int* row2colsidx;
7373 	   int i1;
7374 	   int i2;
7375 	
7376 	   assert(row1 != NULL);
7377 	   assert(row2 != NULL);
7378 	
7379 	   /* Sort the column indices of both rows.
7380 	    *
7381 	    * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7382 	    * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7383 	    * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7384 	    * for both or one of the non-LP columns for both.
7385 	    * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7386 	    * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7387 	    * columns can be added later and remain unlinked while all previously added columns might already be linked.
7388 	    * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7389 	    *
7390 	    * We distinguish the following cases:
7391 	    *
7392 	    * 1) both rows have no unlinked columns
7393 	    *    -> we just check the LP partitions
7394 	    *
7395 	    * 2) exactly one row is completely unlinked, the other one is completely linked
7396 	    *    -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7397 	    *       (thus all common LP columns are regarded)
7398 	    *
7399 	    * 3) we have unlinked and LP columns in both rows
7400 	    *    -> we need to compare four partitions at once
7401 	    *
7402 	    * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7403 	    *     -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7404 	    *        other row
7405 	    *
7406 	    * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7407 	    *     -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7408 	    *
7409 	    * 5) both rows are completely unlinked
7410 	    *    -> we need to compare two partitions: both complete rows
7411 	    */
7412 	   SCIProwSort(row1);
7413 	   assert(row1->lpcolssorted);
7414 	   assert(row1->nonlpcolssorted);
7415 	   SCIProwSort(row2);
7416 	   assert(row2->lpcolssorted);
7417 	   assert(row2->nonlpcolssorted);
7418 	
7419 	   assert(row1->nunlinked <= row1->len - row1->nlpcols);
7420 	   assert(row2->nunlinked <= row2->len - row2->nlpcols);
7421 	
7422 	   row1colsidx = row1->cols_index;
7423 	   row2colsidx = row2->cols_index;
7424 	
7425 	#ifndef NDEBUG
7426 	   /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7427 	   if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7428 	   {
7429 	      i1 = 0;
7430 	      i2 = row2->nlpcols;
7431 	      while( i1 < row1->nlpcols && i2 < row2->len )
7432 	      {
7433 	         assert(row1->cols[i1] != row2->cols[i2]);
7434 	         if( row1->cols[i1]->index < row2->cols[i2]->index )
7435 	            ++i1;
7436 	         else
7437 	         {
7438 	            assert(row1->cols[i1]->index > row2->cols[i2]->index);
7439 	            ++i2;
7440 	         }
7441 	      }
7442 	      assert(i1 == row1->nlpcols || i2 == row2->len);
7443 	
7444 	      i1 = row1->nlpcols;
7445 	      i2 = 0;
7446 	      while( i1 < row1->len && i2 < row2->nlpcols )
7447 	      {
7448 	         assert(row1->cols[i1] != row2->cols[i2]);
7449 	         if( row1->cols[i1]->index < row2->cols[i2]->index )
7450 	            ++i1;
7451 	         else
7452 	         {
7453 	            assert(row1->cols[i1]->index > row2->cols[i2]->index);
7454 	            ++i2;
7455 	         }
7456 	      }
7457 	      assert(i1 == row1->len || i2 == row2->nlpcols);
7458 	   }
7459 	#endif
7460 	
7461 	   /* The "easy" cases 1) and 2) */
7462 	   if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7463 	      ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7464 	         && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7465 	         && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7466 	   {
7467 	      assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7468 	      assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7469 	
7470 	      /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7471 	       * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7472 	       */
7473 	      i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7474 	      i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7475 	      prod = 0;
7476 	
7477 	      /* calculate the scalar product */
7478 	      while( i1 >= 0 && i2 >= 0 )
7479 	      {
7480 	         assert(row1->cols[i1]->index == row1colsidx[i1]);
7481 	         assert(row2->cols[i2]->index == row2colsidx[i2]);
7482 	         assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7483 	         if( row1colsidx[i1] < row2colsidx[i2] )
7484 	            --i2;
7485 	         else if( row1colsidx[i1] > row2colsidx[i2] )
7486 	            --i1;
7487 	         else
7488 	         {
7489 	            ++prod;
7490 	            --i1;
7491 	            --i2;
7492 	         }
7493 	      }
7494 	   }
7495 	   /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7496 	   else
7497 	   {
7498 	      SCIP_Bool lpcols;
7499 	      int ilp1;
7500 	      int inlp1;
7501 	      int ilp2;
7502 	      int inlp2;
7503 	      int end1;
7504 	      int end2;
7505 	
7506 	      prod = 0;
7507 	      ilp1 = 0;
7508 	      ilp2 = 0;
7509 	
7510 	      /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7511 	      inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7512 	      inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7513 	
7514 	      /* handle the case of four partitions (case 3) until one partition is finished;
7515 	       * cases 4a), 4b), and 5) will fail the while-condition
7516 	       */
7517 	      while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7518 	      {
7519 	         assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7520 	         assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7521 	         assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7522 	         assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7523 	         assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7524 	         assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7525 	         assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7526 	         assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7527 	
7528 	         /* rows have the same linked LP columns */
7529 	         if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7530 	         {
7531 	            ++prod;
7532 	            ++ilp1;
7533 	            ++ilp2;
7534 	         }
7535 	         /* LP column of row1 is the same as unlinked column of row2 */
7536 	         else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7537 	         {
7538 	            ++prod;
7539 	            ++ilp1;
7540 	            ++inlp2;
7541 	         }
7542 	         /* unlinked column of row1 is the same as LP column of row2 */
7543 	         else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7544 	         {
7545 	            ++prod;
7546 	            ++inlp1;
7547 	            ++ilp2;
7548 	         }
7549 	         /* two unlinked LP columns are the same */
7550 	         else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7551 	         {
7552 	            ++prod;
7553 	            ++inlp1;
7554 	            ++inlp2;
7555 	         }
7556 	         /* increase smallest counter */
7557 	         else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7558 	         {
7559 	            if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7560 	            {
7561 	               if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7562 	                  ++ilp1;
7563 	               else
7564 	                  ++ilp2;
7565 	            }
7566 	            else
7567 	            {
7568 	               if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7569 	                  ++ilp1;
7570 	               else
7571 	                  ++inlp2;
7572 	            }
7573 	         }
7574 	         else
7575 	         {
7576 	            if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7577 	            {
7578 	               if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7579 	                  ++inlp1;
7580 	               else
7581 	                  ++ilp2;
7582 	            }
7583 	            else
7584 	            {
7585 	               if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7586 	                  ++inlp1;
7587 	               else
7588 	                  ++inlp2;
7589 	            }
7590 	         }
7591 	      }
7592 	
7593 	      /* One partition was completely handled, we just have to handle the three remaining partitions:
7594 	       * the remaining partition of this row and the two partitions of the other row.
7595 	       * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7596 	       */
7597 	      if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7598 	      {
7599 	         int tmpilp;
7600 	         int tmpinlp;
7601 	
7602 	         assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7603 	
7604 	         SCIPswapPointers((void**) &row1, (void**) &row2);
7605 	         SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7606 	         tmpilp = ilp1;
7607 	         tmpinlp = inlp1;
7608 	         ilp1 = ilp2;
7609 	         inlp1 = inlp2;
7610 	         ilp2 = tmpilp;
7611 	         inlp2 = tmpinlp;
7612 	      }
7613 	
7614 	      /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7615 	       * -> this merges cases 4a) and 4b)
7616 	       */
7617 	      if( ilp1 == row1->nlpcols )
7618 	      {
7619 	         i1 = inlp1;
7620 	         end1 = row1->len;
7621 	         lpcols = FALSE;
7622 	      }
7623 	      else
7624 	      {
7625 	         assert(inlp1 == row1->len);
7626 	
7627 	         i1 = ilp1;
7628 	         end1 = row1->nlpcols;
7629 	         lpcols = TRUE;
7630 	      }
7631 	
7632 	      /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7633 	       * case 5) will fail the while-condition
7634 	       */
7635 	      while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7636 	      {
7637 	         assert(row1->cols[i1]->index == row1colsidx[i1]);
7638 	         assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7639 	         assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7640 	         assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7641 	         assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7642 	
7643 	         /* current column in row 1 is the same as the current LP column in row 2 */
7644 	         if( row1colsidx[i1] == row2colsidx[ilp2] )
7645 	         {
7646 	            ++prod;
7647 	            ++i1;
7648 	            ++ilp2;
7649 	         }
7650 	         /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7651 	         else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7652 	         {
7653 	            ++prod;
7654 	            ++i1;
7655 	            ++inlp2;
7656 	         }
7657 	         /* increase smallest counter */
7658 	         else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7659 	         {
7660 	            if( row1colsidx[i1] < row2colsidx[ilp2] )
7661 	               ++i1;
7662 	            else
7663 	               ++ilp2;
7664 	         }
7665 	         else
7666 	         {
7667 	            if( row1colsidx[i1] < row2colsidx[inlp2] )
7668 	               ++i1;
7669 	            else
7670 	               ++inlp2;
7671 	         }
7672 	      }
7673 	
7674 	      /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7675 	       * the two rows
7676 	       */
7677 	      if( i1 < end1 )
7678 	      {
7679 	         /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7680 	         if( ilp2 == row2->nlpcols )
7681 	         {
7682 	            i2 = inlp2;
7683 	            end2 = row2->len;
7684 	            lpcols = FALSE;
7685 	         }
7686 	         else
7687 	         {
7688 	            assert(inlp2 == row2->len);
7689 	
7690 	            i2 = ilp2;
7691 	            end2 = row2->nlpcols;
7692 	         }
7693 	
7694 	         /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7695 	         while( i1 < end1 && i2 < end2 )
7696 	         {
7697 	            assert(row1->cols[i1]->index == row1colsidx[i1]);
7698 	            assert(row2->cols[i2]->index == row2colsidx[i2]);
7699 	            assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7700 	
7701 	            /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7702 	            if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7703 	            {
7704 	               ++prod;
7705 	               ++i1;
7706 	               ++i2;
7707 	            }
7708 	            /* increase smallest counter */
7709 	            else if( row1colsidx[i1] < row2colsidx[i2] )
7710 	               ++i1;
7711 	            else
7712 	               ++i2;
7713 	         }
7714 	      }
7715 	   }
7716 	
7717 	   return prod;
7718 	}
7719 	
7720 	/** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7721 	 *  p = |v*w|/(|v|*|w|);
7722 	 *  the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7723 	 */
7724 	SCIP_Real SCIProwGetParallelism(
7725 	   SCIP_ROW*             row1,               /**< first LP row */
7726 	   SCIP_ROW*             row2,               /**< second LP row */
7727 	   char                  orthofunc           /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7728 	   )
7729 	{
7730 	   SCIP_Real parallelism;
7731 	   SCIP_Real scalarprod;
7732 	
7733 	   switch( orthofunc )
7734 	   {
7735 	   case 'e':
7736 	      scalarprod = SCIProwGetScalarProduct(row1, row2);
7737 	      if( scalarprod == 0.0 )
7738 	      {
7739 	         parallelism = 0.0;
7740 	         break;
7741 	      }
7742 	
7743 	      if( SCIProwGetNorm(row1) == 0.0 )
7744 	      {
7745 	         /* In theory, this should not happen if the scalarproduct is not zero
7746 	          * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7747 	          * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7748 	          * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7749 	          */
7750 	         int i;
7751 	         for( i = 0; i < row1->len; ++i )
7752 	            if( row1->cols[i]->lppos >= 0 )
7753 	               row1->sqrnorm += SQR(row1->vals[i]);
7754 	         assert(SCIProwGetNorm(row1) != 0.0);
7755 	      }
7756 	
7757 	      if( SCIProwGetNorm(row2) == 0.0 )
7758 	      {
7759 	         /* same as for row1 above: reeval norms if it is 0, which is wrong */
7760 	         int i;
7761 	         for( i = 0; i < row2->len; ++i )
7762 	            if( row2->cols[i]->lppos >= 0 )
7763 	               row2->sqrnorm += SQR(row2->vals[i]);
7764 	         assert(SCIProwGetNorm(row2) != 0.0);
7765 	      }
7766 	
7767 	      parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7768 	      break;
7769 	
7770 	   case 'd':
7771 	      scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7772 	      parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7773 	      break;
7774 	
7775 	   default:
7776 	      SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7777 	      SCIPABORT();
7778 	      parallelism = 0.0; /*lint !e527*/
7779 	   }
7780 	
7781 	   return parallelism;
7782 	}
7783 	
7784 	/** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7785 	 *  o = 1 - |v*w|/(|v|*|w|);
7786 	 *  the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7787 	 */
7788 	SCIP_Real SCIProwGetOrthogonality(
7789 	   SCIP_ROW*             row1,               /**< first LP row */
7790 	   SCIP_ROW*             row2,               /**< second LP row */
7791 	   char                  orthofunc           /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7792 	   )
7793 	{
7794 	   return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7795 	}
7796 	
7797 	/** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7798 	 *  function, if the value is 0, it is orthogonal to the objective function
7799 	 */
7800 	SCIP_Real SCIProwGetObjParallelism(
7801 	   SCIP_ROW*             row,                /**< LP row */
7802 	   SCIP_SET*             set,                /**< global SCIP settings */
7803 	   SCIP_LP*              lp                  /**< current LP data */
7804 	   )
7805 	{
7806 	   SCIP_Real prod;
7807 	   SCIP_Real parallelism;
7808 	
7809 	   assert(row != NULL);
7810 	   assert(lp != NULL);
7811 	
7812 	   if( lp->objsqrnormunreliable )
7813 	      SCIPlpRecalculateObjSqrNorm(set, lp);
7814 	
7815 	   assert(!lp->objsqrnormunreliable);
7816 	   assert(lp->objsqrnorm >= 0.0);
7817 	
7818 	   checkRowSqrnorm(row);
7819 	   checkRowObjprod(row);
7820 	
7821 	   prod = row->sqrnorm * lp->objsqrnorm;
7822 	
7823 	   parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / SQRT(prod) : 0.0;
7824 	   assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7825 	   assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7826 	   parallelism = MIN(parallelism, 1.0);
7827 	   parallelism = MAX(parallelism, 0.0);
7828 	
7829 	   return parallelism;
7830 	}
7831 	
7832 	/** includes event handler with given data in row's event filter */
7833 	SCIP_RETCODE SCIProwCatchEvent(
7834 	   SCIP_ROW*             row,                /**< row */
7835 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7836 	   SCIP_SET*             set,                /**< global SCIP settings */
7837 	   SCIP_EVENTTYPE        eventtype,          /**< event type to catch */
7838 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
7839 	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
7840 	   int*                  filterpos           /**< pointer to store position of event filter entry, or NULL */
7841 	   )
7842 	{
7843 	   assert(row != NULL);
7844 	   assert(row->eventfilter != NULL);
7845 	   assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7846 	   assert((eventtype &  SCIP_EVENTTYPE_ROWCHANGED) != 0);
7847 	
7848 	   SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7849 	      eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7850 	
7851 	   SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7852 	
7853 	   return SCIP_OKAY;
7854 	}
7855 	
7856 	/** deletes event handler with given data from row's event filter */
7857 	SCIP_RETCODE SCIProwDropEvent(
7858 	   SCIP_ROW*             row,                /**< row */
7859 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7860 	   SCIP_SET*             set,                /**< global SCIP settings */
7861 	   SCIP_EVENTTYPE        eventtype,          /**< event type mask of dropped event */
7862 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
7863 	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
7864 	   int                   filterpos           /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7865 	   )
7866 	{
7867 	   assert(row != NULL);
7868 	   assert(row->eventfilter != NULL);
7869 	
7870 	   SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7871 	
7872 	   SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7873 	
7874 	   return SCIP_OKAY;
7875 	}
7876 	
7877 	/** marks a row to be not removable from the LP in the current node because it became obsolete */
7878 	void SCIProwMarkNotRemovableLocal(
7879 	   SCIP_ROW*             row,                /**< LP row */
7880 	   SCIP_STAT*            stat                /**< problem statistics */
7881 	   )
7882 	{
7883 	   assert(row  != NULL);
7884 	   assert(stat != NULL);
7885 	   assert(stat->nnodes > 0);
7886 	
7887 	   /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7888 	   row->obsoletenode = stat->nnodes;
7889 	}
7890 	
7891 	/*
7892 	 * LP solver data update
7893 	 */
7894 	
7895 	/** resets column data to represent a column not in the LP solver */
7896 	static
7897 	void markColDeleted(
7898 	   SCIP_COL*             col                 /**< column to be marked deleted */
7899 	   )
7900 	{
7901 	   assert(col != NULL);
7902 	
7903 	   col->lpipos = -1;
7904 	   col->primsol = 0.0;
7905 	   col->redcost = SCIP_INVALID;
7906 	   col->farkascoef = SCIP_INVALID;
7907 	   col->sbdown = SCIP_INVALID;
7908 	   col->sbup = SCIP_INVALID;
7909 	   col->sbdownvalid = FALSE;
7910 	   col->sbupvalid = FALSE;
7911 	   col->validredcostlp = -1;
7912 	   col->validfarkaslp = -1;
7913 	   col->sbitlim = -1;
7914 	   col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7915 	}
7916 	
7917 	/** applies all cached column removals to the LP solver */
7918 	static
7919 	SCIP_RETCODE lpFlushDelCols(
7920 	   SCIP_LP*              lp                  /**< current LP data */
7921 	   )
7922 	{
7923 	   assert(lp != NULL);
7924 	   assert(lp->lpifirstchgcol <= lp->nlpicols);
7925 	   assert(lp->lpifirstchgcol <= lp->ncols);
7926 	
7927 	   /* find the first column to change */
7928 	   while( lp->lpifirstchgcol < lp->nlpicols
7929 	      && lp->lpifirstchgcol < lp->ncols
7930 	      && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7931 	      && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7932 	   {
7933 	      assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7934 	      lp->lpifirstchgcol++;
7935 	   }
7936 	
7937 	   /* shrink LP to the part which didn't change */
7938 	   if( lp->lpifirstchgcol < lp->nlpicols )
7939 	   {
7940 	      int i;
7941 	
7942 	      assert(!lp->diving);
7943 	      SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7944 	      SCIP_CALL( SCIPlpiDelCols(lp->lpi, lp->lpifirstchgcol, lp->nlpicols-1) );
7945 	      for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7946 	      {
7947 	         markColDeleted(lp->lpicols[i]);
7948 	      }
7949 	      lp->nlpicols = lp->lpifirstchgcol;
7950 	      lp->flushdeletedcols = TRUE;
7951 	      lp->updateintegrality = TRUE;
7952 	
7953 	      /* mark the LP unsolved */
7954 	      lp->solved = FALSE;
7955 	      lp->primalfeasible = FALSE;
7956 	      lp->primalchecked = FALSE;
7957 	      lp->lpobjval = SCIP_INVALID;
7958 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
7959 	   }
7960 	   assert(lp->nlpicols == lp->lpifirstchgcol);
7961 	
7962 	   return SCIP_OKAY;
7963 	}
7964 	
7965 	/** computes for the given column the lower and upper bound that should be flushed into the LP
7966 	 *  depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7967 	 *  the bounds are explicitly added to the LP in any case
7968 	 */
7969 	static
7970 	void computeLPBounds(
7971 	   SCIP_LP*              lp,                 /**< current LP data */
7972 	   SCIP_SET*             set,                /**< global SCIP settings */
7973 	   SCIP_COL*             col,                /**< column to compute bounds for */
7974 	   SCIP_Real             lpiinf,             /**< infinity value if the LP solver */
7975 	   SCIP_Real*            lb,                 /**< pointer to store the new lower bound */
7976 	   SCIP_Real*            ub                  /**< pointer to store the new upper bound */
7977 	   )
7978 	{
7979 	   assert(lp != NULL);
7980 	   assert(set != NULL);
7981 	   assert(col != NULL);
7982 	   assert(lb != NULL);
7983 	   assert(ub != NULL);
7984 	
7985 	   /* get the correct new lower bound:
7986 	    * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7987 	    * if we are in diving mode, ignore lazy bounds and always take the lower bound
7988 	    */
7989 	   if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7990 	      (*lb) = -lpiinf;
7991 	   else
7992 	      (*lb) = col->lb;
7993 	   /* get the correct new upper bound:
7994 	    * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7995 	    * if we are in diving mode, ignore lazy bounds and always take the upper bound
7996 	    */
7997 	   if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7998 	      (*ub) = lpiinf;
7999 	   else
8000 	      (*ub) = col->ub;
8001 	}
8002 	
8003 	/** applies all cached column additions to the LP solver */
8004 	static
8005 	SCIP_RETCODE lpFlushAddCols(
8006 	   SCIP_LP*              lp,                 /**< current LP data */
8007 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8008 	   SCIP_SET*             set,                /**< global SCIP settings */
8009 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
8010 	   )
8011 	{
8012 	   SCIP_Real* obj;
8013 	   SCIP_Real* lb;
8014 	   SCIP_Real* ub;
8015 	   int* beg;
8016 	   int* ind;
8017 	   SCIP_Real* val;
8018 	   char** name;
8019 	   SCIP_COL* col;
8020 	   SCIP_Real lpiinf;
8021 	   int c;
8022 	   int pos;
8023 	   int nnonz;
8024 	   int naddcols;
8025 	   int naddcoefs;
8026 	   int i;
8027 	   int lpipos;
8028 	
8029 	   assert(lp != NULL);
8030 	   assert(lp->lpifirstchgcol == lp->nlpicols);
8031 	   assert(blkmem != NULL);
8032 	   assert(set != NULL);
8033 	
8034 	   /* if there are no columns to add, we are ready */
8035 	   if( lp->ncols == lp->nlpicols )
8036 	      return SCIP_OKAY;
8037 	
8038 	   /* add the additional columns */
8039 	   assert(!lp->diving);
8040 	   assert(lp->ncols > lp->nlpicols);
8041 	   SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8042 	
8043 	   /* get the solver's infinity value */
8044 	   lpiinf = SCIPlpiInfinity(lp->lpi);
8045 	
8046 	   /* count the (maximal) number of added coefficients, calculate the number of added columns */
8047 	   naddcols = lp->ncols - lp->nlpicols;
8048 	   naddcoefs = 0;
8049 	   for( c = lp->nlpicols; c < lp->ncols; ++c )
8050 	      naddcoefs += lp->cols[c]->len;
8051 	   assert(naddcols > 0);
8052 	
8053 	   /* get temporary memory for changes */
8054 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8055 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8056 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8057 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8058 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8059 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8060 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8061 	
8062 	   /* fill temporary memory with column data */
8063 	   nnonz = 0;
8064 	   for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8065 	   {
8066 	      col = lp->cols[c];
8067 	      assert(col != NULL);
8068 	      assert(col->var != NULL);
8069 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8070 	      assert(SCIPvarGetCol(col->var) == col);
8071 	      assert(col->lppos == c);
8072 	      assert(nnonz + col->nlprows <= naddcoefs);
8073 	
8074 	      SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8075 	      debugColPrint(set, col);
8076 	
8077 	      /* Because the column becomes a member of the LP solver, it now can take values
8078 	       * different from zero. That means, we have to include the column in the corresponding
8079 	       * row vectors.
8080 	       */
8081 	      SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8082 	
8083 	      lp->lpicols[c] = col;
8084 	      col->lpipos = c;
8085 	      col->primsol = SCIP_INVALID;
8086 	      col->redcost = SCIP_INVALID;
8087 	      col->farkascoef = SCIP_INVALID;
8088 	      col->sbdown = SCIP_INVALID;
8089 	      col->sbup = SCIP_INVALID;
8090 	      col->sbdownvalid = FALSE;
8091 	      col->sbupvalid = FALSE;
8092 	      col->validredcostlp = -1;
8093 	      col->validfarkaslp = -1;
8094 	      col->sbitlim = -1;
8095 	      col->objchanged = FALSE;
8096 	      col->lbchanged = FALSE;
8097 	      col->ubchanged = FALSE;
8098 	      col->coefchanged = FALSE;
8099 	      obj[pos] = col->obj;
8100 	
8101 	      /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8102 	      computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8103 	
8104 	      beg[pos] = nnonz;
8105 	      name[pos] = (char*)SCIPvarGetName(col->var);
8106 	
8107 	      col->flushedobj = obj[pos];
8108 	      col->flushedlb = lb[pos];
8109 	      col->flushedub = ub[pos];
8110 	
8111 	      for( i = 0; i < col->nlprows; ++i )
8112 	      {
8113 	         assert(col->rows[i] != NULL);
8114 	         lpipos = col->rows[i]->lpipos;
8115 	         if( lpipos >= 0 )
8116 	         {
8117 	            assert(lpipos < lp->nrows);
8118 	            assert(nnonz < naddcoefs);
8119 	            ind[nnonz] = lpipos;
8120 	            val[nnonz] = col->vals[i];
8121 	            nnonz++;
8122 	         }
8123 	      }
8124 	#ifndef NDEBUG
8125 	      for( i = col->nlprows; i < col->len; ++i )
8126 	      {
8127 	         assert(col->rows[i] != NULL);
8128 	         assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8129 	      }
8130 	#endif
8131 	   }
8132 	
8133 	   /* call LP interface */
8134 	   SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8135 	   SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8136 	   lp->nlpicols = lp->ncols;
8137 	   lp->lpifirstchgcol = lp->nlpicols;
8138 	
8139 	   /* free temporary memory */
8140 	   SCIPsetFreeBufferArray(set, &name);
8141 	   SCIPsetFreeBufferArray(set, &val);
8142 	   SCIPsetFreeBufferArray(set, &ind);
8143 	   SCIPsetFreeBufferArray(set, &beg);
8144 	   SCIPsetFreeBufferArray(set, &ub);
8145 	   SCIPsetFreeBufferArray(set, &lb);
8146 	   SCIPsetFreeBufferArray(set, &obj);
8147 	
8148 	   lp->flushaddedcols = TRUE;
8149 	   lp->updateintegrality = TRUE;
8150 	
8151 	   /* mark the LP unsolved */
8152 	   lp->solved = FALSE;
8153 	   lp->dualfeasible = FALSE;
8154 	   lp->dualchecked = FALSE;
8155 	   lp->lpobjval = SCIP_INVALID;
8156 	   lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8157 	
8158 	   return SCIP_OKAY;
8159 	}
8160 	
8161 	/** resets row data to represent a row not in the LP solver */
8162 	static
8163 	void markRowDeleted(
8164 	   SCIP_ROW*             row                 /**< row to be marked deleted */
8165 	   )
8166 	{
8167 	   assert(row != NULL);
8168 	
8169 	   row->lpipos = -1;
8170 	   row->dualsol = 0.0;
8171 	   row->activity = SCIP_INVALID;
8172 	   row->dualfarkas = 0.0;
8173 	   row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8174 	   row->validactivitylp = -1;
8175 	}
8176 	
8177 	/** applies all cached row removals to the LP solver */
8178 	static
8179 	SCIP_RETCODE lpFlushDelRows(
8180 	   SCIP_LP*              lp,                 /**< current LP data */
8181 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8182 	   SCIP_SET*             set                 /**< global SCIP settings */
8183 	   )
8184 	{
8185 	   assert(lp != NULL);
8186 	   assert(lp->lpifirstchgrow <= lp->nlpirows);
8187 	   assert(lp->lpifirstchgrow <= lp->nrows);
8188 	
8189 	   /* find the first row to change */
8190 	   while( lp->lpifirstchgrow < lp->nlpirows
8191 	      && lp->lpifirstchgrow < lp->nrows
8192 	      && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8193 	      && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8194 	   {
8195 	      assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8196 	      lp->lpifirstchgrow++;
8197 	   }
8198 	
8199 	   /* shrink LP to the part which didn't change */
8200 	   if( lp->lpifirstchgrow < lp->nlpirows )
8201 	   {
8202 	      int i;
8203 	
8204 	      SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8205 	      SCIP_CALL( SCIPlpiDelRows(lp->lpi, lp->lpifirstchgrow, lp->nlpirows-1) );
8206 	      for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8207 	      {
8208 	         markRowDeleted(lp->lpirows[i]);
8209 	         SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8210 	      }
8211 	      lp->nlpirows = lp->lpifirstchgrow;
8212 	      lp->flushdeletedrows = TRUE;
8213 	
8214 	      /* mark the LP unsolved */
8215 	      lp->solved = FALSE;
8216 	      lp->dualfeasible = FALSE;
8217 	      lp->dualchecked = FALSE;
8218 	      lp->lpobjval = SCIP_INVALID;
8219 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8220 	   }
8221 	   assert(lp->nlpirows == lp->lpifirstchgrow);
8222 	
8223 	   return SCIP_OKAY;
8224 	}
8225 	
8226 	/** applies all cached row additions and removals to the LP solver */
8227 	static
8228 	SCIP_RETCODE lpFlushAddRows(
8229 	   SCIP_LP*              lp,                 /**< current LP data */
8230 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8231 	   SCIP_SET*             set,                /**< global SCIP settings */
8232 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
8233 	   )
8234 	{
8235 	   SCIP_Real* lhs;
8236 	   SCIP_Real* rhs;
8237 	   int* beg;
8238 	   int* ind;
8239 	   SCIP_Real* val;
8240 	   char** name;
8241 	   SCIP_ROW* row;
8242 	   SCIP_Real lpiinf;
8243 	   int r;
8244 	   int pos;
8245 	   int nnonz;
8246 	   int naddrows;
8247 	   int naddcoefs;
8248 	   int i;
8249 	   int lpipos;
8250 	
8251 	   assert(lp != NULL);
8252 	   assert(lp->lpifirstchgrow == lp->nlpirows);
8253 	   assert(blkmem != NULL);
8254 	
8255 	   /* if there are no rows to add, we are ready */
8256 	   if( lp->nrows == lp->nlpirows )
8257 	      return SCIP_OKAY;
8258 	
8259 	   /* add the additional rows */
8260 	   assert(lp->nrows > lp->nlpirows);
8261 	   SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8262 	
8263 	   /* get the solver's infinity value */
8264 	   lpiinf = SCIPlpiInfinity(lp->lpi);
8265 	
8266 	   /* count the (maximal) number of added coefficients, calculate the number of added rows */
8267 	   naddrows = lp->nrows - lp->nlpirows;
8268 	   naddcoefs = 0;
8269 	   for( r = lp->nlpirows; r < lp->nrows; ++r )
8270 	      naddcoefs += lp->rows[r]->len;
8271 	   assert(naddrows > 0);
8272 	
8273 	   /* get temporary memory for changes */
8274 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8275 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8276 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8277 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8278 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8279 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8280 	
8281 	   /* fill temporary memory with row data */
8282 	   nnonz = 0;
8283 	   for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8284 	   {
8285 	      row = lp->rows[r];
8286 	      assert(row != NULL);
8287 	      assert(row->lppos == r);
8288 	      assert(nnonz + row->nlpcols <= naddcoefs);
8289 	
8290 	      SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8291 	      debugRowPrint(set, row);
8292 	
8293 	      /* Because the row becomes a member of the LP solver, its dual variable now can take values
8294 	       * different from zero. That means, we have to include the row in the corresponding
8295 	       * column vectors.
8296 	       */
8297 	      SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8298 	
8299 	      SCIProwCapture(row);
8300 	      lp->lpirows[r] = row;
8301 	      row->lpipos = r;
8302 	      row->dualsol = SCIP_INVALID;
8303 	      row->activity = SCIP_INVALID;
8304 	      row->dualfarkas = SCIP_INVALID;
8305 	      row->validactivitylp = -1;
8306 	      row->lhschanged = FALSE;
8307 	      row->rhschanged = FALSE;
8308 	      row->coefchanged = FALSE;
8309 	      if( SCIPsetIsInfinity(set, -row->lhs) )
8310 	         lhs[pos] = -lpiinf;
8311 	      else
8312 	         lhs[pos] = row->lhs - row->constant;
8313 	      if( SCIPsetIsInfinity(set, row->rhs) )
8314 	         rhs[pos] = lpiinf;
8315 	      else
8316 	         rhs[pos] = row->rhs - row->constant;
8317 	      beg[pos] = nnonz;
8318 	      name[pos] = row->name;
8319 	
8320 	      row->flushedlhs = lhs[pos];
8321 	      row->flushedrhs = rhs[pos];
8322 	
8323 	      SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8324 	      for( i = 0; i < row->nlpcols; ++i )
8325 	      {
8326 	         assert(row->cols[i] != NULL);
8327 	         lpipos = row->cols[i]->lpipos;
8328 	         if( lpipos >= 0 )
8329 	         {
8330 	            assert(lpipos < lp->ncols);
8331 	            assert(nnonz < naddcoefs);
8332 	            SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8333 	            ind[nnonz] = lpipos;
8334 	            val[nnonz] = row->vals[i];
8335 	            nnonz++;
8336 	         }
8337 	      }
8338 	      SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8339 	#ifndef NDEBUG
8340 	      for( i = row->nlpcols; i < row->len; ++i )
8341 	      {
8342 	         assert(row->cols[i] != NULL);
8343 	         assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8344 	      }
8345 	#endif
8346 	   }
8347 	
8348 	   /* call LP interface */
8349 	   SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8350 	   SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8351 	   lp->nlpirows = lp->nrows;
8352 	   lp->lpifirstchgrow = lp->nlpirows;
8353 	
8354 	   /* free temporary memory */
8355 	   SCIPsetFreeBufferArray(set, &name);
8356 	   SCIPsetFreeBufferArray(set, &val);
8357 	   SCIPsetFreeBufferArray(set, &ind);
8358 	   SCIPsetFreeBufferArray(set, &beg);
8359 	   SCIPsetFreeBufferArray(set, &rhs);
8360 	   SCIPsetFreeBufferArray(set, &lhs);
8361 	
8362 	   lp->flushaddedrows = TRUE;
8363 	
8364 	   /* mark the LP unsolved */
8365 	   lp->solved = FALSE;
8366 	   lp->primalfeasible = FALSE;
8367 	   lp->primalchecked = FALSE;
8368 	   lp->lpobjval = SCIP_INVALID;
8369 	   lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8370 	
8371 	   return SCIP_OKAY;
8372 	}
8373 	
8374 	/** applies all cached column bound and objective changes to the LP */
8375 	static
8376 	SCIP_RETCODE lpFlushChgCols(
8377 	   SCIP_LP*              lp,                 /**< current LP data */
8378 	   SCIP_SET*             set                 /**< global SCIP settings */
8379 	   )
8380 	{
8381 	#ifndef NDEBUG
8382 	   SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8383 	#endif
8384 	   SCIP_COL* col;
8385 	   int* objind;
8386 	   int* bdind;
8387 	   SCIP_Real* obj;
8388 	   SCIP_Real* lb;
8389 	   SCIP_Real* ub;
8390 	   SCIP_Real lpiinf;
8391 	   int nobjchg;
8392 	   int nbdchg;
8393 	   int i;
8394 	
8395 	   assert(lp != NULL);
8396 	
8397 	   if( lp->nchgcols == 0 )
8398 	      return SCIP_OKAY;
8399 	
8400 	   /* get the solver's infinity value */
8401 	   lpiinf = SCIPlpiInfinity(lp->lpi);
8402 	
8403 	   /* get temporary memory for changes */
8404 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8405 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, lp->ncols) );
8406 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8407 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, lp->ncols) );
8408 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, lp->ncols) );
8409 	
8410 	   /* collect all cached bound and objective changes */
8411 	   nobjchg = 0;
8412 	   nbdchg = 0;
8413 	   for( i = 0; i < lp->nchgcols; ++i )
8414 	   {
8415 	      col = lp->chgcols[i];
8416 	      assert(col != NULL);
8417 	      assert(col->var != NULL);
8418 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8419 	      assert(SCIPvarGetCol(col->var) == col);
8420 	
8421 	      if( col->lpipos >= 0 )
8422 	      {
8423 	#ifndef NDEBUG
8424 	         /* do not check consistency of data with LPI in case of LPI=none */
8425 	         if( !lpinone )
8426 	         {
8427 	            SCIP_Real lpiobj;
8428 	            SCIP_Real lpilb;
8429 	            SCIP_Real lpiub;
8430 	
8431 	            SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8432 	            SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8433 	            assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8434 	            assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb))
8435 	                  || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8436 	            assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub))
8437 	                  || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8438 	         }
8439 	#endif
8440 	
8441 	         if( col->objchanged )
8442 	         {
8443 	            SCIP_Real newobj;
8444 	
8445 	            newobj = col->obj;
8446 	            if( col->flushedobj != newobj ) /*lint !e777*/
8447 	            {
8448 	               assert(nobjchg < lp->ncols);
8449 	               objind[nobjchg] = col->lpipos;
8450 	               obj[nobjchg] = newobj;
8451 	               nobjchg++;
8452 	               col->flushedobj = newobj;
8453 	            }
8454 	            col->objchanged = FALSE;
8455 	         }
8456 	
8457 	         if( col->lbchanged || col->ubchanged )
8458 	         {
8459 	            SCIP_Real newlb;
8460 	            SCIP_Real newub;
8461 	
8462 	            /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8463 	            computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8464 	
8465 	            if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8466 	            {
8467 	               assert(nbdchg < lp->ncols);
8468 	               bdind[nbdchg] = col->lpipos;
8469 	               lb[nbdchg] = newlb;
8470 	               ub[nbdchg] = newub;
8471 	               nbdchg++;
8472 	               col->flushedlb = newlb;
8473 	               col->flushedub = newub;
8474 	            }
8475 	            col->lbchanged = FALSE;
8476 	            col->ubchanged = FALSE;
8477 	         }
8478 	      }
8479 	      /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8480 	   }
8481 	
8482 	   /* change objective values in LP */
8483 	   if( nobjchg > 0 )
8484 	   {
8485 	      SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8486 	      SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8487 	
8488 	      /* mark the LP unsolved */
8489 	      lp->solved = FALSE;
8490 	      lp->dualfeasible = FALSE;
8491 	      lp->dualchecked = FALSE;
8492 	      lp->lpobjval = SCIP_INVALID;
8493 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8494 	   }
8495 	
8496 	   /* change bounds in LP */
8497 	   if( nbdchg > 0 )
8498 	   {
8499 	      SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8500 	      SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8501 	
8502 	      /* mark the LP unsolved */
8503 	      lp->solved = FALSE;
8504 	      lp->primalfeasible = FALSE;
8505 	      lp->primalchecked = FALSE;
8506 	      lp->lpobjval = SCIP_INVALID;
8507 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8508 	   }
8509 	
8510 	   lp->nchgcols = 0;
8511 	
8512 	   /* free temporary memory */
8513 	   SCIPsetFreeBufferArray(set, &ub);
8514 	   SCIPsetFreeBufferArray(set, &lb);
8515 	   SCIPsetFreeBufferArray(set, &bdind);
8516 	   SCIPsetFreeBufferArray(set, &obj);
8517 	   SCIPsetFreeBufferArray(set, &objind);
8518 	
8519 	   return SCIP_OKAY;
8520 	}
8521 	
8522 	/** applies all cached row side changes to the LP */
8523 	static
8524 	SCIP_RETCODE lpFlushChgRows(
8525 	   SCIP_LP*              lp,                 /**< current LP data */
8526 	   SCIP_SET*             set                 /**< global SCIP settings */
8527 	   )
8528 	{
8529 	#ifndef NDEBUG
8530 	   SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8531 	#endif
8532 	   SCIP_ROW* row;
8533 	   int* ind;
8534 	   SCIP_Real* lhs;
8535 	   SCIP_Real* rhs;
8536 	   SCIP_Real lpiinf;
8537 	   int i;
8538 	   int nchg;
8539 	
8540 	   assert(lp != NULL);
8541 	
8542 	   if( lp->nchgrows == 0 )
8543 	      return SCIP_OKAY;
8544 	
8545 	   /* get the solver's infinity value */
8546 	   lpiinf = SCIPlpiInfinity(lp->lpi);
8547 	
8548 	   /* get temporary memory for changes */
8549 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, lp->nrows) );
8550 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, lp->nrows) );
8551 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, lp->nrows) );
8552 	
8553 	   /* collect all cached left and right hand side changes */
8554 	   nchg = 0;
8555 	   for( i = 0; i < lp->nchgrows; ++i )
8556 	   {
8557 	      row = lp->chgrows[i];
8558 	      assert(row != NULL);
8559 	
8560 	      if( row->lpipos >= 0 )
8561 	      {
8562 	#ifndef NDEBUG
8563 	         /* do not check consistency of data with LPI in case of LPI=none */
8564 	         if( !lpinone )
8565 	         {
8566 	            SCIP_Real lpilhs;
8567 	            SCIP_Real lpirhs;
8568 	
8569 	            SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8570 	            assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8571 	            assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8572 	         }
8573 	#endif
8574 	         if( row->lhschanged || row->rhschanged )
8575 	         {
8576 	            SCIP_Real newlhs;
8577 	            SCIP_Real newrhs;
8578 	
8579 	            newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8580 	            newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8581 	            if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8582 	            {
8583 	               assert(nchg < lp->nrows);
8584 	               ind[nchg] = row->lpipos;
8585 	               lhs[nchg] = newlhs;
8586 	               rhs[nchg] = newrhs;
8587 	               nchg++;
8588 	               row->flushedlhs = newlhs;
8589 	               row->flushedrhs = newrhs;
8590 	            }
8591 	            row->lhschanged = FALSE;
8592 	            row->rhschanged = FALSE;
8593 	         }
8594 	      }
8595 	   }
8596 	
8597 	   /* change left and right hand sides in LP */
8598 	   if( nchg > 0 )
8599 	   {
8600 	      SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8601 	      SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8602 	
8603 	      /* mark the LP unsolved */
8604 	      lp->solved = FALSE;
8605 	      lp->primalfeasible = FALSE;
8606 	      lp->primalchecked = FALSE;
8607 	      lp->lpobjval = SCIP_INVALID;
8608 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8609 	   }
8610 	
8611 	   lp->nchgrows = 0;
8612 	
8613 	   /* free temporary memory */
8614 	   SCIPsetFreeBufferArray(set, &rhs);
8615 	   SCIPsetFreeBufferArray(set, &lhs);
8616 	   SCIPsetFreeBufferArray(set, &ind);
8617 	
8618 	   return SCIP_OKAY;
8619 	}
8620 	
8621 	/** copy integrality information to the LP */
8622 	static
8623 	SCIP_RETCODE lpCopyIntegrality(
8624 	   SCIP_LP*              lp,                 /**< current LP data */
8625 	   SCIP_SET*             set                 /**< global SCIP settings */
8626 	   )
8627 	{
8628 	   int i;
8629 	   int nintegers;
8630 	   int* integerInfo;
8631 	   SCIP_VAR* var;
8632 	
8633 	   assert(lp != NULL);
8634 	
8635 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8636 	
8637 	   /* count total number of integralities */
8638 	   nintegers = 0;
8639 	
8640 	   for( i = 0; i < lp->ncols; ++i )
8641 	   {
8642 	      var = SCIPcolGetVar(lp->cols[i]);
8643 	      if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) )
8644 	      {
8645 	         integerInfo[i] = 1;
8646 	         ++nintegers;
8647 	      }
8648 	      else
8649 	         integerInfo[i] = 0;
8650 	   }
8651 	
8652 	   /* only pass integrality information if integer variables are present */
8653 	   if( nintegers > 0 )
8654 	   {
8655 	      SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8656 	   }
8657 	   else
8658 	   {
8659 	      SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, 0, NULL) );
8660 	   }
8661 	
8662 	   SCIPsetFreeBufferArray(set, &integerInfo);
8663 	
8664 	   /* mark integralities to be updated */
8665 	   lp->updateintegrality = FALSE;
8666 	
8667 	   return SCIP_OKAY;
8668 	}
8669 	
8670 	/** applies all cached changes to the LP solver */
8671 	SCIP_RETCODE SCIPlpFlush(
8672 	   SCIP_LP*              lp,                 /**< current LP data */
8673 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8674 	   SCIP_SET*             set,                /**< global SCIP settings */
8675 	   SCIP_PROB*            prob,               /**< problem data */
8676 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
8677 	   )
8678 	{
8679 	   assert(lp != NULL);
8680 	   assert(blkmem != NULL);
8681 	
8682 	   SCIPsetDebugMsg(set, "flushing LP changes: old (%d cols, %d rows), nchgcols=%d, nchgrows=%d, firstchgcol=%d, firstchgrow=%d, new (%d cols, %d rows), flushed=%u\n",
8683 	      lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8684 	
8685 	   if( !lp->flushed )
8686 	   {
8687 	      lp->flushdeletedcols = FALSE;
8688 	      lp->flushaddedcols = FALSE;
8689 	      lp->flushdeletedrows = FALSE;
8690 	      lp->flushaddedrows = FALSE;
8691 	
8692 	      SCIP_CALL( lpFlushDelCols(lp) );
8693 	      SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8694 	      SCIP_CALL( lpFlushChgCols(lp, set) );
8695 	      SCIP_CALL( lpFlushChgRows(lp, set) );
8696 	      SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8697 	      SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8698 	
8699 	      lp->flushed = TRUE;
8700 	
8701 	      checkLinks(lp);
8702 	   }
8703 	
8704 	   /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8705 	    * we want to re-optimize the LP even if nothing else has changed */
8706 	   if( lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 && ! lpCutoffDisabled(set, prob) ) /*lint !e777*/
8707 	   {
8708 	      lp->solved = FALSE;
8709 	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
8710 	   }
8711 	
8712 	   assert(lp->nlpicols == lp->ncols);
8713 	   assert(lp->lpifirstchgcol == lp->nlpicols);
8714 	   assert(lp->nlpirows == lp->nrows);
8715 	   assert(lp->lpifirstchgrow == lp->nlpirows);
8716 	   assert(lp->nchgcols == 0);
8717 	   assert(lp->nchgrows == 0);
8718 	#ifndef NDEBUG
8719 	   {
8720 	      int ncols;
8721 	      int nrows;
8722 	
8723 	      SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8724 	      SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8725 	      assert(ncols == lp->ncols);
8726 	      assert(nrows == lp->nrows);
8727 	   }
8728 	#endif
8729 	
8730 	   return SCIP_OKAY;
8731 	}
8732 	
8733 	/** marks the LP to be flushed, even if the LP thinks it is not flushed */
8734 	SCIP_RETCODE SCIPlpMarkFlushed(
8735 	   SCIP_LP*              lp,                 /**< current LP data */
8736 	   SCIP_SET*             set                 /**< global SCIP settings */
8737 	   )
8738 	{
8739 	#ifndef NDEBUG
8740 	   SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8741 	#endif
8742 	   int i;
8743 	
8744 	   assert(lp != NULL);
8745 	
8746 	#ifndef NDEBUG
8747 	   /* check, if there are really no column or row deletions or coefficient changes left */
8748 	   while( lp->lpifirstchgcol < lp->nlpicols
8749 	      && lp->lpifirstchgcol < lp->ncols
8750 	      && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8751 	      && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8752 	   {
8753 	      assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8754 	      lp->lpifirstchgcol++;
8755 	   }
8756 	   assert(lp->nlpicols == lp->lpifirstchgcol);
8757 	
8758 	   while( lp->lpifirstchgrow < lp->nlpirows
8759 	      && lp->lpifirstchgrow < lp->nrows
8760 	      && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8761 	      && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8762 	   {
8763 	      assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8764 	      lp->lpifirstchgrow++;
8765 	   }
8766 	   assert(lp->nlpirows == lp->lpifirstchgrow);
8767 	#endif
8768 	
8769 	   lp->lpifirstchgcol = lp->nlpicols;
8770 	   lp->lpifirstchgrow = lp->nlpirows;
8771 	
8772 	   /* check, if there are really no column or row additions left */
8773 	   assert(lp->ncols == lp->nlpicols);
8774 	   assert(lp->nrows == lp->nlpirows);
8775 	
8776 	   /* mark the changed columns to be unchanged, and check, if this is really correct */
8777 	   for( i = 0; i < lp->nchgcols; ++i )
8778 	   {
8779 	      SCIP_COL* col;
8780 	
8781 	      col = lp->chgcols[i];
8782 	      assert(col != NULL);
8783 	      assert(col->var != NULL);
8784 	      assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
8785 	      assert(SCIPvarGetCol(col->var) == col);
8786 	
8787 	      if( col->lpipos >= 0 )
8788 	      {
8789 	#ifndef NDEBUG
8790 	         /* do not check consistency of data with LPI in case of LPI=none */
8791 	         if( !lpinone )
8792 	         {
8793 	            SCIP_Real lpiobj;
8794 	            SCIP_Real lpilb;
8795 	            SCIP_Real lpiub;
8796 	
8797 	            SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8798 	            SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8799 	            assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8800 	            assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8801 	            assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8802 	            assert(col->flushedobj == col->obj); /*lint !e777*/
8803 	            assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8804 	            assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8805 	         }
8806 	#endif
8807 	         col->objchanged = FALSE;
8808 	         col->lbchanged = FALSE;
8809 	         col->ubchanged = FALSE;
8810 	      }
8811 	      /* maybe lb/ub/objchanged should  be set to false also when lpipos is -1 */
8812 	   }
8813 	   lp->nchgcols = 0;
8814 	
8815 	   /* mark the changed rows to be unchanged, and check, if this is really correct */
8816 	   for( i = 0; i < lp->nchgrows; ++i )
8817 	   {
8818 	      SCIP_ROW* row;
8819 	
8820 	      row = lp->chgrows[i];
8821 	      assert(row != NULL);
8822 	
8823 	      if( row->lpipos >= 0 )
8824 	      {
8825 	#ifndef NDEBUG
8826 	         /* do not check consistency of data with LPI in case of LPI=none */
8827 	         if( !lpinone )
8828 	         {
8829 	            SCIP_Real lpilhs;
8830 	            SCIP_Real lpirhs;
8831 	
8832 	            SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8833 	            assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8834 	            assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8835 	            assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8836 	            assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8837 	         }
8838 	#endif
8839 	         row->lhschanged = FALSE;
8840 	         row->rhschanged = FALSE;
8841 	      }
8842 	   }
8843 	   lp->nchgrows = 0;
8844 	
8845 	   /* mark the LP to be flushed */
8846 	   lp->flushed = TRUE;
8847 	
8848 	   checkLinks(lp);
8849 	
8850 	   return SCIP_OKAY;
8851 	}
8852 	
8853 	
8854 	
8855 	
8856 	/*
8857 	 * LP methods
8858 	 */
8859 	
8860 	/** updates link data after addition of column */
8861 	static
8862 	void colUpdateAddLP(
8863 	   SCIP_COL*             col,                /**< LP column */
8864 	   SCIP_SET*             set                 /**< global SCIP settings */
8865 	   )
8866 	{
8867 	   SCIP_ROW* row;
8868 	   int i;
8869 	   int pos;
8870 	
8871 	   assert(col != NULL);
8872 	   assert(col->lppos >= 0);
8873 	
8874 	   /* update column arrays of all linked rows */
8875 	   for( i = 0; i < col->len; ++i )
8876 	   {
8877 	      pos = col->linkpos[i];
8878 	      if( pos >= 0 )
8879 	      {
8880 	         row = col->rows[i];
8881 	         assert(row != NULL);
8882 	         assert(row->linkpos[pos] == i);
8883 	         assert(row->cols[pos] == col);
8884 	         assert(row->nlpcols <= pos && pos < row->len);
8885 	
8886 	         row->nlpcols++;
8887 	         rowSwapCoefs(row, pos, row->nlpcols-1);
8888 	         assert(row->cols[row->nlpcols-1] == col);
8889 	
8890 	         /* if no swap was necessary, mark lpcols to be unsorted */
8891 	         if( pos == row->nlpcols-1 )
8892 	            row->lpcolssorted = FALSE;
8893 	
8894 	         /* update norms */
8895 	         rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8896 	      }
8897 	   }
8898 	}
8899 	
8900 	/** updates link data after addition of row */
8901 	static
8902 	void rowUpdateAddLP(
8903 	   SCIP_ROW*             row                 /**< LP row */
8904 	   )
8905 	{
8906 	   SCIP_COL* col;
8907 	   int i;
8908 	   int pos;
8909 	
8910 	   assert(row != NULL);
8911 	   assert(row->lppos >= 0);
8912 	
8913 	   /* update row arrays of all linked columns */
8914 	   for( i = 0; i < row->len; ++i )
8915 	   {
8916 	      pos = row->linkpos[i];
8917 	      if( pos >= 0 )
8918 	      {
8919 	         col = row->cols[i];
8920 	         assert(col != NULL);
8921 	         assert(col->linkpos[pos] == i);
8922 	         assert(col->rows[pos] == row);
8923 	         assert(col->nlprows <= pos && pos < col->len);
8924 	
8925 	         col->nlprows++;
8926 	         colSwapCoefs(col, pos, col->nlprows-1);
8927 	
8928 	         /* if no swap was necessary, mark lprows to be unsorted */
8929 	         if( pos == col->nlprows-1 )
8930 	            col->lprowssorted = FALSE;
8931 	      }
8932 	   }
8933 	}
8934 	
8935 	/** updates link data after removal of column */
8936 	static
8937 	void colUpdateDelLP(
8938 	   SCIP_COL*             col,                /**< LP column */
8939 	   SCIP_SET*             set                 /**< global SCIP settings */
8940 	   )
8941 	{
8942 	   SCIP_ROW* row;
8943 	   int i;
8944 	   int pos;
8945 	
8946 	   assert(col != NULL);
8947 	   assert(col->lppos == -1);
8948 	
8949 	   /* update column arrays of all linked rows */
8950 	   for( i = 0; i < col->len; ++i )
8951 	   {
8952 	      pos = col->linkpos[i];
8953 	      if( pos >= 0 )
8954 	      {
8955 	         row = col->rows[i];
8956 	         assert(row != NULL);
8957 	         assert(row->linkpos[pos] == i);
8958 	         assert(row->cols[pos] == col);
8959 	         assert(0 <= pos && pos < row->nlpcols);
8960 	
8961 	         /* update norms */
8962 	         rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8963 	
8964 	         row->nlpcols--;
8965 	         rowSwapCoefs(row, pos, row->nlpcols);
8966 	
8967 	         /* if no swap was necessary, mark nonlpcols to be unsorted */
8968 	         if( pos == row->nlpcols )
8969 	            row->nonlpcolssorted = FALSE;
8970 	      }
8971 	   }
8972 	}
8973 	
8974 	/** updates link data after removal of row */
8975 	static
8976 	void rowUpdateDelLP(
8977 	   SCIP_ROW*             row                 /**< LP row */
8978 	   )
8979 	{
8980 	   SCIP_COL* col;
8981 	   int i;
8982 	   int pos;
8983 	
8984 	   assert(row != NULL);
8985 	   assert(row->lppos == -1);
8986 	
8987 	   /* update row arrays of all linked columns */
8988 	   for( i = 0; i < row->len; ++i )
8989 	   {
8990 	      pos = row->linkpos[i];
8991 	      if( pos >= 0 )
8992 	      {
8993 	         col = row->cols[i];
8994 	         assert(col != NULL);
8995 	         assert(0 <= pos && pos < col->nlprows);
8996 	         assert(col->linkpos[pos] == i);
8997 	         assert(col->rows[pos] == row);
8998 	
8999 	         col->nlprows--;
9000 	         colSwapCoefs(col, pos, col->nlprows);
9001 	
9002 	         /* if no swap was necessary, mark lprows to be unsorted */
9003 	         if( pos == col->nlprows )
9004 	            col->nonlprowssorted = FALSE;
9005 	      }
9006 	   }
9007 	}
9008 	
9009 	static
9010 	SCIP_RETCODE allocDiveChgSideArrays(
9011 	   SCIP_LP*              lp,                 /**< LP data object */
9012 	   int                   initsize            /**< initial size of the arrays */
9013 	   )
9014 	{
9015 	   assert(lp != NULL);
9016 	   assert(lp->divechgsides == NULL);
9017 	   assert(lp->divechgsidetypes == NULL);
9018 	   assert(lp->divechgrows == NULL);
9019 	   assert(lp->ndivechgsides == 0);
9020 	   assert(lp->divechgsidessize == 0);
9021 	   assert(initsize > 0);
9022 	
9023 	   lp->divechgsidessize = initsize;
9024 	   SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) );
9025 	   SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) );
9026 	   SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) );
9027 	
9028 	   return SCIP_OKAY;
9029 	}
9030 	
9031 	static
9032 	SCIP_RETCODE reallocDiveChgSideArrays(
9033 	   SCIP_LP*              lp,                 /**< LP data object */
9034 	   int                   minsize,            /**< minimal number of elements */
9035 	   SCIP_Real             growfact            /**< growing factor */
9036 	   )
9037 	{
9038 	   assert(lp != NULL);
9039 	   assert(lp->divechgsides != NULL);
9040 	   assert(lp->divechgsidetypes != NULL);
9041 	   assert(lp->divechgrows != NULL);
9042 	   assert(lp->ndivechgsides > 0);
9043 	   assert(lp->divechgsidessize > 0);
9044 	   assert(minsize > 0);
9045 	
9046 	   if( minsize <= lp->divechgsidessize )
9047 	      return SCIP_OKAY;
9048 	
9049 	   lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9050 	   SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) );
9051 	   SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) );
9052 	   SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) );
9053 	
9054 	   return SCIP_OKAY;
9055 	}
9056 	
9057 	static
9058 	void freeDiveChgSideArrays(
9059 	   SCIP_LP*              lp                  /**< LP data object */
9060 	   )
9061 	{
9062 	   assert(lp != NULL);
9063 	   assert(lp->divechgsides != NULL);
9064 	   assert(lp->divechgsidetypes != NULL);
9065 	   assert(lp->divechgrows != NULL);
9066 	   assert(lp->ndivechgsides == 0);
9067 	   assert(lp->divechgsidessize > 0);
9068 	
9069 	   BMSfreeMemoryArrayNull(&lp->divechgsides);
9070 	   BMSfreeMemoryArrayNull(&lp->divechgsidetypes);
9071 	   BMSfreeMemoryArrayNull(&lp->divechgrows);
9072 	   lp->divechgsidessize = 0;
9073 	}
9074 	
9075 	#define DIVESTACKINITSIZE 100
9076 	
9077 	/** creates empty LP data object */
9078 	SCIP_RETCODE SCIPlpCreate(
9079 	   SCIP_LP**             lp,                 /**< pointer to LP data object */
9080 	   SCIP_SET*             set,                /**< global SCIP settings */
9081 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
9082 	   SCIP_STAT*            stat,               /**< problem statistics */
9083 	   const char*           name                /**< problem name */
9084 	   )
9085 	{
9086 	   SCIP_Bool success;
9087 	
9088 	   assert(lp != NULL);
9089 	   assert(set != NULL);
9090 	   assert(stat != NULL);
9091 	   assert(name != NULL);
9092 	
9093 	   SCIP_ALLOC( BMSallocMemory(lp) );
9094 	
9095 	   /* open LP Solver interface */
9096 	   SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9097 	
9098 	   (*lp)->lpicols = NULL;
9099 	   (*lp)->lpirows = NULL;
9100 	   (*lp)->chgcols = NULL;
9101 	   (*lp)->chgrows = NULL;
9102 	   (*lp)->cols = NULL;
9103 	   (*lp)->soldirection = NULL;
9104 	   (*lp)->lazycols = NULL;
9105 	   (*lp)->rows = NULL;
9106 	   (*lp)->lpobjval = 0.0;
9107 	   (*lp)->glbpseudoobjval = 0.0;
9108 	   (*lp)->relglbpseudoobjval = 0.0;
9109 	   (*lp)->glbpseudoobjvalid = TRUE;
9110 	   (*lp)->glbpseudoobjvalinf = 0;
9111 	   (*lp)->pseudoobjval = 0.0;
9112 	   (*lp)->relpseudoobjval = 0.0;
9113 	   (*lp)->pseudoobjvalid = TRUE;
9114 	   (*lp)->pseudoobjvalinf = 0;
9115 	   (*lp)->looseobjval = 0.0;
9116 	   (*lp)->rellooseobjval = 0.0;
9117 	   (*lp)->looseobjvalid = TRUE;
9118 	   (*lp)->looseobjvalinf = 0;
9119 	   (*lp)->nloosevars = 0;
9120 	   (*lp)->rootlpobjval = SCIP_INVALID;
9121 	   (*lp)->rootlooseobjval = SCIP_INVALID;
9122 	   (*lp)->cutoffbound = SCIPsetInfinity(set);
9123 	   (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9124 	   SCIPlpResetFeastol(*lp, set);
9125 	   (*lp)->validdegeneracylp = -1;
9126 	   (*lp)->objsqrnorm = 0.0;
9127 	   (*lp)->objsumnorm = 0.0;
9128 	   (*lp)->lpicolssize = 0;
9129 	   (*lp)->nlpicols = 0;
9130 	   (*lp)->lpirowssize = 0;
9131 	   (*lp)->nlpirows = 0;
9132 	   (*lp)->lpifirstchgcol = 0;
9133 	   (*lp)->lpifirstchgrow = 0;
9134 	   (*lp)->colssize = 0;
9135 	   (*lp)->soldirectionsize = 0;
9136 	   (*lp)->ncols = 0;
9137 	   (*lp)->lazycolssize = 0;
9138 	   (*lp)->nlazycols = 0;
9139 	   (*lp)->rowssize = 0;
9140 	   (*lp)->nrows = 0;
9141 	   (*lp)->chgcolssize = 0;
9142 	   (*lp)->nchgcols = 0;
9143 	   (*lp)->chgrowssize = 0;
9144 	   (*lp)->nchgrows = 0;
9145 	   (*lp)->firstnewcol = 0;
9146 	   (*lp)->firstnewrow = 0;
9147 	   (*lp)->nremovablecols = 0;
9148 	   (*lp)->nremovablerows = 0;
9149 	   (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9150 	   (*lp)->validfarkaslp = -1;
9151 	   (*lp)->validsoldirlp = -1;
9152 	   (*lp)->validsoldirsol = NULL;
9153 	   (*lp)->objsqrnormunreliable = FALSE;
9154 	   (*lp)->flushdeletedcols = FALSE;
9155 	   (*lp)->flushaddedcols = FALSE;
9156 	   (*lp)->flushdeletedrows = FALSE;
9157 	   (*lp)->flushaddedrows = FALSE;
9158 	   (*lp)->updateintegrality = TRUE;
9159 	   (*lp)->flushed = TRUE;
9160 	   (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9161 	   (*lp)->solved = TRUE;
9162 	   (*lp)->primalfeasible = TRUE;
9163 	   (*lp)->primalchecked = TRUE;
9164 	   (*lp)->dualfeasible = TRUE;
9165 	   (*lp)->dualchecked = TRUE;
9166 	   (*lp)->solisbasic = FALSE;
9167 	   (*lp)->rootlpisrelax = TRUE;
9168 	   (*lp)->isrelax = TRUE;
9169 	   (*lp)->installing = FALSE;
9170 	   (*lp)->strongbranching = FALSE;
9171 	   (*lp)->strongbranchprobing = FALSE;
9172 	   (*lp)->probing = FALSE;
9173 	   (*lp)->diving = FALSE;
9174 	   (*lp)->divingobjchg = FALSE;
9175 	   (*lp)->divinglazyapplied = FALSE;
9176 	   (*lp)->divelpistate = NULL;
9177 	   (*lp)->divelpwasprimfeas = TRUE;
9178 	   (*lp)->divelpwasprimchecked = TRUE;
9179 	   (*lp)->divelpwasdualfeas = TRUE;
9180 	   (*lp)->divelpwasdualchecked = TRUE;
9181 	   (*lp)->divechgsides = NULL;
9182 	   (*lp)->divechgsidetypes = NULL;
9183 	   (*lp)->divechgrows = NULL;
9184 	   (*lp)->ndivechgsides = 0;
9185 	   (*lp)->divechgsidessize = 0;
9186 	   (*lp)->ndivingrows = 0;
9187 	   (*lp)->divinglpiitlim = INT_MAX;
9188 	   (*lp)->resolvelperror = FALSE;
9189 	   (*lp)->divenolddomchgs = 0;
9190 	   (*lp)->adjustlpval = FALSE;
9191 	   (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9192 	   (*lp)->lpifeastol = (*lp)->feastol;
9193 	   (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9194 	   (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9195 	   (*lp)->lpifromscratch = FALSE;
9196 	   (*lp)->lpifastmip = set->lp_fastmip;
9197 	   (*lp)->lpiscaling = set->lp_scaling;
9198 	   (*lp)->lpipresolving = set->lp_presolving;
9199 	   (*lp)->lpilpinfo = set->disp_lpinfo;
9200 	   (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9201 	   (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9202 	   (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9203 	   (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9204 	   (*lp)->lpimarkowitz = set->lp_markowitz;
9205 	   (*lp)->lpiitlim = INT_MAX;
9206 	   (*lp)->lpipricing = SCIP_PRICING_AUTO;
9207 	   (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9208 	   (*lp)->lpithreads = set->lp_threads;
9209 	   (*lp)->lpitiming = (int) set->time_clocktype;
9210 	   (*lp)->lpirandomseed = set->random_randomseed;
9211 	   (*lp)->storedsolvals = NULL;
9212 	
9213 	   /* allocate arrays for diving */
9214 	   SCIP_CALL( allocDiveChgSideArrays(*lp, DIVESTACKINITSIZE) );
9215 	
9216 	   /* set default parameters in LP solver */
9217 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9218 	   if( !success )
9219 	   {
9220 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9221 	         "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9222 	         SCIPlpiGetSolverName());
9223 	   }
9224 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9225 	   (*lp)->lpihasfeastol = success;
9226 	   if( !success )
9227 	   {
9228 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9229 	         "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9230 	         SCIPlpiGetSolverName());
9231 	   }
9232 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9233 	   (*lp)->lpihasdualfeastol = success;
9234 	   if( !success )
9235 	   {
9236 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9237 	         "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9238 	         SCIPlpiGetSolverName());
9239 	   }
9240 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9241 	   (*lp)->lpihasbarrierconvtol = success;
9242 	   if( !success )
9243 	   {
9244 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9245 	         "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9246 	         SCIPlpiGetSolverName());
9247 	   }
9248 	   SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9249 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9250 	   (*lp)->lpihasfastmip = success;
9251 	   if( !success )
9252 	   {
9253 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9254 	         "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9255 	         SCIPlpiGetSolverName());
9256 	   }
9257 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9258 	   (*lp)->lpihasscaling = success;
9259 	   if( !success )
9260 	   {
9261 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9262 	         "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9263 	         SCIPlpiGetSolverName());
9264 	   }
9265 	   SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9266 	   (*lp)->lpihaspresolving = success;
9267 	   if( !success )
9268 	   {
9269 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9270 	         "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9271 	         SCIPlpiGetSolverName());
9272 	   }
9273 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9274 	   if( !success )
9275 	   {
9276 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9277 	         "LP Solver <%s>: clock type cannot be set\n",
9278 	         SCIPlpiGetSolverName());
9279 	   }
9280 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9281 	   if( !success )
9282 	   {
9283 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9284 	         "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9285 	         SCIPlpiGetSolverName());
9286 	   }
9287 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9288 	   if( !success )
9289 	   {
9290 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9291 	         "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9292 	         SCIPlpiGetSolverName());
9293 	   }
9294 	   SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9295 	   if( !success )
9296 	   {
9297 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9298 	         "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9299 	         SCIPlpiGetSolverName());
9300 	   }
9301 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9302 	   (*lp)->lpihasrowrep = success;
9303 	   if( !success )
9304 	   {
9305 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9306 	         "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9307 	         SCIPlpiGetSolverName());
9308 	   }
9309 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9310 	   (*lp)->lpihaspolishing = success;
9311 	   if( !success )
9312 	   {
9313 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9314 	         "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9315 	         SCIPlpiGetSolverName());
9316 	   }
9317 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9318 	   (*lp)->lpihasrefactor = success;
9319 	   if( !success )
9320 	   {
9321 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9322 	         "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9323 	         SCIPlpiGetSolverName());
9324 	   }
9325 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9326 	   if( !success )
9327 	   {
9328 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9329 	         "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9330 	         SCIPlpiGetSolverName());
9331 	   }
9332 	   SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9333 	   if( !success )
9334 	   {
9335 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9336 	         "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9337 	         SCIPlpiGetSolverName());
9338 	   }
9339 	   SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9340 	   if( !success )
9341 	   {
9342 	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9343 	         "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9344 	         SCIPlpiGetSolverName());
9345 	   }
9346 	   /* keep the default LP random seed if this parameter is set to 0 (current default) */
9347 	   if( (*lp)->lpirandomseed != 0 )
9348 	   {
9349 	      SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9350 	      if( !success )
9351 	      {
9352 	         SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9353 	            "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9354 	            SCIPlpiGetSolverName());
9355 	      }
9356 	   }
9357 	
9358 	   /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9359 	    * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9360 	   if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9361 	   {
9362 	      SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9363 	      return SCIP_PARAMETERWRONGVAL;
9364 	   }
9365 	
9366 	   return SCIP_OKAY;
9367 	}
9368 	
9369 	/** frees LP data object */
9370 	SCIP_RETCODE SCIPlpFree(
9371 	   SCIP_LP**             lp,                 /**< pointer to LP data object */
9372 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9373 	   SCIP_SET*             set,                /**< global SCIP settings */
9374 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9375 	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
9376 	   )
9377 	{
9378 	   int i;
9379 	
9380 	   assert(lp != NULL);
9381 	   assert(*lp != NULL);
9382 	
9383 	   SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9384 	
9385 	   freeDiveChgSideArrays(*lp);
9386 	
9387 	   /* release LPI rows */
9388 	   for( i = 0; i < (*lp)->nlpirows; ++i )
9389 	   {
9390 	      SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9391 	   }
9392 	
9393 	   if( (*lp)->lpi != NULL )
9394 	   {
9395 	      SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9396 	   }
9397 	
9398 	   BMSfreeMemoryNull(&(*lp)->storedsolvals);
9399 	   BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9400 	   BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9401 	   BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9402 	   BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9403 	   BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9404 	   BMSfreeMemoryArrayNull(&(*lp)->cols);
9405 	   BMSfreeMemoryArrayNull(&(*lp)->rows);
9406 	   BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9407 	   BMSfreeMemory(lp);
9408 	
9409 	   return SCIP_OKAY;
9410 	}
9411 	
9412 	/** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9413 	 *  changes to the LP solver
9414 	 */
9415 	SCIP_RETCODE SCIPlpReset(
9416 	   SCIP_LP*              lp,                 /**< LP data */
9417 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9418 	   SCIP_SET*             set,                /**< global SCIP settings */
9419 	   SCIP_PROB*            prob,               /**< problem data */
9420 	   SCIP_STAT*            stat,               /**< problem statistics */
9421 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9422 	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
9423 	   )
9424 	{
9425 	   assert(stat != NULL);
9426 	
9427 	   SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9428 	   SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9429 	
9430 	   /* mark the empty LP to be solved */
9431 	   lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9432 	   lp->lpobjval = 0.0;
9433 	   lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9434 	   lp->validfarkaslp = -1;
9435 	   lp->validdegeneracylp = -1;
9436 	   lp->validsoldirlp = -1;
9437 	   lp->validsoldirsol = NULL;
9438 	   lp->solved = TRUE;
9439 	   lp->primalfeasible = TRUE;
9440 	   lp->primalchecked = TRUE;
9441 	   lp->dualfeasible = TRUE;
9442 	   lp->dualchecked = TRUE;
9443 	   lp->solisbasic = FALSE;
9444 	   lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9445 	
9446 	   return SCIP_OKAY;
9447 	}
9448 	
9449 	/** adds a column to the LP */
9450 	SCIP_RETCODE SCIPlpAddCol(
9451 	   SCIP_LP*              lp,                 /**< LP data */
9452 	   SCIP_SET*             set,                /**< global SCIP settings */
9453 	   SCIP_COL*             col,                /**< LP column */
9454 	   int                   depth               /**< depth in the tree where the column addition is performed */
9455 	   )
9456 	{
9457 	   assert(lp != NULL);
9458 	   assert(!lp->diving);
9459 	   assert(col != NULL);
9460 	   assert(col->len == 0 || col->rows != NULL);
9461 	   assert(col->lppos == -1);
9462 	   assert(col->var != NULL);
9463 	   assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9464 	   assert(SCIPvarGetCol(col->var) == col);
9465 	   assert(SCIPvarIsIntegral(col->var) == col->integral);
9466 	
9467 	   SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9468 	#ifdef SCIP_DEBUG
9469 	   {
9470 	      int i;
9471 	      SCIPsetDebugMsgPrint(set, "  (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9472 	      for( i = 0; i < col->len; ++i )
9473 	         SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9474 	      SCIPsetDebugMsgPrint(set, "\n");
9475 	   }
9476 	#endif
9477 	
9478 	   SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9479 	   lp->cols[lp->ncols] = col;
9480 	   col->lppos = lp->ncols;
9481 	   col->lpdepth = depth;
9482 	   col->age = 0;
9483 	   lp->ncols++;
9484 	   if( col->removable )
9485 	      lp->nremovablecols++;
9486 	
9487 	   if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9488 	   {
9489 	      SCIP_CALL( ensureLazycolsSize(lp, set, lp->nlazycols+1) );
9490 	      lp->lazycols[lp->nlazycols] = col;
9491 	      lp->nlazycols++;
9492 	   }
9493 	
9494 	   /* mark the current LP unflushed */
9495 	   lp->flushed = FALSE;
9496 	
9497 	   /* update column arrays of all linked rows */
9498 	   colUpdateAddLP(col, set);
9499 	
9500 	   /* update the objective function vector norms */
9501 	   lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9502 	
9503 	   checkLinks(lp);
9504 	
9505 	   return SCIP_OKAY;
9506 	}
9507 	
9508 	/** adds a row to the LP and captures it */
9509 	SCIP_RETCODE SCIPlpAddRow(
9510 	   SCIP_LP*              lp,                 /**< LP data */
9511 	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
9512 	   SCIP_SET*             set,                /**< global SCIP settings */
9513 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9514 	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
9515 	   SCIP_ROW*             row,                /**< LP row */
9516 	   int                   depth               /**< depth in the tree where the row addition is performed */
9517 	   )
9518 	{
9519 	   assert(lp != NULL);
9520 	   assert(row != NULL);
9521 	   assert(row->len == 0 || row->cols != NULL);
9522 	   assert(row->lppos == -1);
9523 	
9524 	   SCIProwCapture(row);
9525 	   SCIProwLock(row);
9526 	
9527 	   SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9528 	#ifdef SCIP_DEBUG
9529 	   {
9530 	      int i;
9531 	      SCIPsetDebugMsgPrint(set, "  %g <=", row->lhs);
9532 	      for( i = 0; i < row->len; ++i )
9533 	         SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9534 	      if( !SCIPsetIsZero(set, row->constant) )
9535 	         SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9536 	      SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9537 	   }
9538 	#endif
9539 	
9540 	   SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9541 	   lp->rows[lp->nrows] = row;
9542 	   row->lppos = lp->nrows;
9543 	   row->lpdepth = depth;
9544 	   row->age = 0;
9545 	   lp->nrows++;
9546 	   if( row->removable )
9547 	      lp->nremovablerows++;
9548 	
9549 	   /* mark the current LP unflushed */
9550 	   lp->flushed = FALSE;
9551 	
9552 	   /* update row arrays of all linked columns */
9553 	   rowUpdateAddLP(row);
9554 	
9555 	   checkLinks(lp);
9556 	
9557 	   rowCalcNorms(row, set);
9558 	
9559 	   /* check, if row addition to LP events are tracked
9560 	    * if so, issue ROWADDEDLP event
9561 	    */
9562 	   if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9563 	   {
9564 	      SCIP_EVENT* event;
9565 	
9566 	      SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9567 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9568 	   }
9569 	
9570 	   return SCIP_OKAY;
9571 	}
9572 	
9573 	
9574 	#ifndef NDEBUG
9575 	/** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9576 	 *  cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9577 	 *  the lazycols array
9578 	 */
9579 	static
9580 	void checkLazyColArray(
9581 	   SCIP_LP*              lp,                 /**< LP data */
9582 	   SCIP_SET*             set                 /**< global SCIP settings */
9583 	   )
9584 	{
9585 	   SCIP_Bool contained;
9586 	   int c;
9587 	   int i;
9588 	
9589 	   assert(lp != NULL);
9590 	
9591 	   /* check if each column in the lazy column array has a counter part in the column array */
9592 	   for( i = 0; i < lp->nlazycols; ++i )
9593 	   {
9594 	      /* check if each lazy column has at least on lazy bound */
9595 	      assert(lp->lazycols[i] != NULL);
9596 	      assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9597 	
9598 	      contained = FALSE;
9599 	      for( c = 0; c < lp->ncols; ++c )
9600 	      {
9601 	         if( lp->lazycols[i] == lp->cols[c] )
9602 	         {
9603 	            assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9604 	            contained = TRUE;
9605 	         }
9606 	      }
9607 	      assert(contained);
9608 	   }
9609 	
9610 	   /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9611 	    * array */
9612 	   for( c = 0; c < lp->ncols; ++c )
9613 	   {
9614 	      contained = FALSE;
9615 	      assert(lp->cols[c] != NULL);
9616 	
9617 	      for( i = 0; i < lp->nlazycols; ++i )
9618 	      {
9619 	         if( lp->lazycols[i] == lp->cols[c] )
9620 	         {
9621 	            contained = TRUE;
9622 	         }
9623 	      }
9624 	
9625 	      assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9626 	   }
9627 	}
9628 	#else
9629 	#define checkLazyColArray(lp, set) /**/
9630 	#endif
9631 	
9632 	/** removes all columns after the given number of cols from the LP */
9633 	SCIP_RETCODE SCIPlpShrinkCols(
9634 	   SCIP_LP*              lp,                 /**< LP data */
9635 	   SCIP_SET*             set,                /**< global SCIP settings */
9636 	   int                   newncols            /**< new number of columns in the LP */
9637 	   )
9638 	{
9639 	   SCIP_COL* col;
9640 	   int c;
9641 	
9642 	   assert(lp != NULL);
9643 	
9644 	   SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9645 	   assert(0 <= newncols);
9646 	   assert(newncols <= lp->ncols);
9647 	
9648 	   if( newncols < lp->ncols )
9649 	   {
9650 	      assert(!lp->diving);
9651 	
9652 	      for( c = lp->ncols-1; c >= newncols; --c )
9653 	      {
9654 	         col = lp->cols[c];
9655 	         assert(col != NULL);
9656 	         assert(col->len == 0 || col->rows != NULL);
9657 	         assert(col->var != NULL);
9658 	         assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN);
9659 	         assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9660 	         assert(col->lppos == c);
9661 	
9662 	         /* mark column to be removed from the LP */
9663 	         col->lppos = -1;
9664 	         col->lpdepth = -1;
9665 	         lp->ncols--;
9666 	
9667 	         /* count removable columns */
9668 	         if( col->removable )
9669 	            lp->nremovablecols--;
9670 	
9671 	         /* update column arrays of all linked rows */
9672 	         colUpdateDelLP(col, set);
9673 	
9674 	         /* update the objective function vector norms */
9675 	         lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9676 	      }
9677 	      assert(lp->ncols == newncols);
9678 	      lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9679 	
9680 	      /* remove columns which are deleted from the lazy column array */
9681 	      c = 0;
9682 	      while( c < lp->nlazycols )
9683 	      {
9684 	         if( lp->lazycols[c]->lppos < 0 )
9685 	         {
9686 	            lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9687 	            lp->nlazycols--;
9688 	         }
9689 	         else
9690 	            c++;
9691 	      }
9692 	
9693 	      /* mark the current LP unflushed */
9694 	      lp->flushed = FALSE;
9695 	
9696 	      checkLazyColArray(lp, set);
9697 	      checkLinks(lp);
9698 	   }
9699 	   assert(lp->nremovablecols <= lp->ncols);
9700 	
9701 	   return SCIP_OKAY;
9702 	}
9703 	
9704 	/** removes and releases all rows after the given number of rows from the LP */
9705 	SCIP_RETCODE SCIPlpShrinkRows(
9706 	   SCIP_LP*              lp,                 /**< LP data */
9707 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9708 	   SCIP_SET*             set,                /**< global SCIP settings */
9709 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9710 	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
9711 	   int                   newnrows            /**< new number of rows in the LP */
9712 	   )
9713 	{
9714 	   SCIP_ROW* row;
9715 	   int r;
9716 	
9717 	   assert(lp != NULL);
9718 	   assert(0 <= newnrows && newnrows <= lp->nrows);
9719 	
9720 	   SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9721 	   if( newnrows < lp->nrows )
9722 	   {
9723 	      for( r = lp->nrows-1; r >= newnrows; --r )
9724 	      {
9725 	         row = lp->rows[r];
9726 	         assert(row != NULL);
9727 	         assert(row->len == 0 || row->cols != NULL);
9728 	         assert(row->lppos == r);
9729 	
9730 	         /* mark row to be removed from the LP */
9731 	         row->lppos = -1;
9732 	         row->lpdepth = -1;
9733 	         lp->nrows--;
9734 	
9735 	         /* count removable rows */
9736 	         if( row->removable )
9737 	            lp->nremovablerows--;
9738 	
9739 	         /* update row arrays of all linked columns */
9740 	         rowUpdateDelLP(row);
9741 	
9742 	         SCIProwUnlock(lp->rows[r]);
9743 	
9744 	         /* check, if row deletion events are tracked
9745 	          * if so, issue ROWDELETEDLP event
9746 	          */
9747 	         if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9748 	         {
9749 	            SCIP_EVENT* event;
9750 	
9751 	            SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9752 	            SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9753 	         }
9754 	
9755 	         SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9756 	      }
9757 	      assert(lp->nrows == newnrows);
9758 	      lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9759 	
9760 	      /* mark the current LP unflushed */
9761 	      lp->flushed = FALSE;
9762 	
9763 	      checkLinks(lp);
9764 	   }
9765 	   assert(lp->nremovablerows <= lp->nrows);
9766 	
9767 	   return SCIP_OKAY;
9768 	}
9769 	
9770 	/** removes all columns and rows from LP, releases all rows */
9771 	SCIP_RETCODE SCIPlpClear(
9772 	   SCIP_LP*              lp,                 /**< LP data */
9773 	   BMS_BLKMEM*           blkmem,             /**< block memory */
9774 	   SCIP_SET*             set,                /**< global SCIP settings */
9775 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
9776 	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
9777 	   )
9778 	{
9779 	   assert(lp != NULL);
9780 	   assert(!lp->diving);
9781 	
9782 	   SCIPsetDebugMsg(set, "clearing LP\n");
9783 	   SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9784 	   SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9785 	
9786 	   return SCIP_OKAY;
9787 	}
9788 	
9789 	/** remembers number of columns and rows to track the newly added ones */
9790 	void SCIPlpMarkSize(
9791 	   SCIP_LP*              lp                  /**< current LP data */
9792 	   )
9793 	{
9794 	   assert(lp != NULL);
9795 	   assert(!lp->diving);
9796 	
9797 	   lp->firstnewrow = lp->nrows;
9798 	   lp->firstnewcol = lp->ncols;
9799 	}
9800 	
9801 	/** sets the remembered number of columns and rows to the given values */
9802 	void SCIPlpSetSizeMark(
9803 	   SCIP_LP*              lp,                 /**< current LP data */
9804 	   int                   nrows,              /**< number of rows to set the size marker to */
9805 	   int                   ncols               /**< number of columns to set the size marker to */
9806 	   )
9807 	{
9808 	   assert(lp != NULL);
9809 	   assert(!lp->diving);
9810 	
9811 	   lp->firstnewrow = nrows;
9812 	   lp->firstnewcol = ncols;
9813 	}
9814 	
9815 	/** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9816 	SCIP_RETCODE SCIPlpGetBasisInd(
9817 	   SCIP_LP*              lp,                 /**< LP data */
9818 	   int*                  basisind            /**< pointer to store basis indices ready to keep number of rows entries */
9819 	   )
9820 	{
9821 	   assert(lp != NULL);
9822 	   assert(lp->flushed);
9823 	   assert(lp->solved);
9824 	   assert(lp->solisbasic);
9825 	   assert(basisind != NULL);
9826 	
9827 	   SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9828 	
9829 	   return SCIP_OKAY;
9830 	}
9831 	
9832 	/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9833 	SCIP_RETCODE SCIPlpGetBase(
9834 	   SCIP_LP*              lp,                 /**< LP data */
9835 	   int*                  cstat,              /**< array to store column basis status, or NULL */
9836 	   int*                  rstat               /**< array to store row basis status, or NULL */
9837 	   )
9838 	{
9839 	   assert(lp != NULL);
9840 	   assert(lp->flushed);
9841 	   assert(lp->solved);
9842 	   assert(lp->solisbasic);
9843 	
9844 	   SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9845 	
9846 	   return SCIP_OKAY;
9847 	}
9848 	
9849 	/** gets a row from the inverse basis matrix B^-1 */
9850 	SCIP_RETCODE SCIPlpGetBInvRow(
9851 	   SCIP_LP*              lp,                 /**< LP data */
9852 	   int                   r,                  /**< row number */
9853 	   SCIP_Real*            coef,               /**< pointer to store the coefficients of the row */
9854 	   int*                  inds,               /**< array to store the non-zero indices, or NULL */
9855 	   int*                  ninds               /**< pointer to store the number of non-zero indices, or NULL
9856 	                                              *   (-1: if we do not store sparsity informations) */
9857 	   )
9858 	{
9859 	   assert(lp != NULL);
9860 	   assert(lp->flushed);
9861 	   assert(lp->solved);
9862 	   assert(lp->solisbasic);
9863 	   assert(0 <= r && r < lp->nrows);  /* the basis matrix is nrows x nrows */
9864 	   assert(coef != NULL);
9865 	
9866 	   SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9867 	
9868 	   return SCIP_OKAY;
9869 	}
9870 	
9871 	/** gets a column from the inverse basis matrix B^-1 */
9872 	SCIP_RETCODE SCIPlpGetBInvCol(
9873 	   SCIP_LP*              lp,                 /**< LP data */
9874 	   int                   c,                  /**< column number of B^-1; this is NOT the number of the column in the LP
9875 	                                              *   returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9876 	                                              *   to get the array which links the B^-1 column numbers to the row and
9877 	                                              *   column numbers of the LP! c must be between 0 and nrows-1, since the
9878 	                                              *   basis has the size nrows * nrows */
9879 	   SCIP_Real*            coef,               /**< pointer to store the coefficients of the column */
9880 	   int*                  inds,               /**< array to store the non-zero indices, or NULL */
9881 	   int*                  ninds               /**< pointer to store the number of non-zero indices, or NULL
9882 	                                              *   (-1: if we do not store sparsity informations) */
9883 	   )
9884 	{
9885 	   assert(lp != NULL);
9886 	   assert(lp->flushed);
9887 	   assert(lp->solved);
9888 	   assert(lp->solisbasic);
9889 	   assert(0 <= c && c < lp->nrows);  /* the basis matrix is nrows x nrows */
9890 	   assert(coef != NULL);
9891 	
9892 	   SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9893 	
9894 	   return SCIP_OKAY;
9895 	}
9896 	
9897 	/** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9898 	SCIP_RETCODE SCIPlpGetBInvARow(
9899 	   SCIP_LP*              lp,                 /**< LP data */
9900 	   int                   r,                  /**< row number */
9901 	   SCIP_Real*            binvrow,            /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9902 	   SCIP_Real*            coef,               /**< pointer to store the coefficients of the row */
9903 	   int*                  inds,               /**< array to store the non-zero indices, or NULL */
9904 	   int*                  ninds               /**< pointer to store the number of non-zero indices, or NULL
9905 	                                              *  (-1: if we do not store sparsity informations) */
9906 	   )
9907 	{
9908 	   assert(lp != NULL);
9909 	   assert(lp->flushed);
9910 	   assert(lp->solved);
9911 	   assert(lp->solisbasic);
9912 	   assert(0 <= r && r < lp->nrows);  /* the basis matrix is nrows x nrows */
9913 	   assert(coef != NULL);
9914 	
9915 	   SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9916 	
9917 	   return SCIP_OKAY;
9918 	}
9919 	
9920 	/** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9921 	 *  i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9922 	 */
9923 	SCIP_RETCODE SCIPlpGetBInvACol(
9924 	   SCIP_LP*              lp,                 /**< LP data */
9925 	   int                   c,                  /**< column number which can be accessed by SCIPcolGetLPPos() */
9926 	   SCIP_Real*            coef,               /**< pointer to store the coefficients of the column */
9927 	   int*                  inds,               /**< array to store the non-zero indices, or NULL */
9928 	   int*                  ninds               /**< pointer to store the number of non-zero indices, or NULL
9929 	                                              *  (-1: if we do not store sparsity informations) */
9930 	   )
9931 	{
9932 	   assert(lp != NULL);
9933 	   assert(lp->flushed);
9934 	   assert(lp->solved);
9935 	   assert(lp->solisbasic);
9936 	   assert(0 <= c && c < lp->ncols);
9937 	   assert(coef != NULL);
9938 	
9939 	   SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9940 	
9941 	   return SCIP_OKAY;
9942 	}
9943 	
9944 	/** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9945 	 *  LP row are swapped in the summation
9946 	 */
9947 	SCIP_RETCODE SCIPlpSumRows(
9948 	   SCIP_LP*              lp,                 /**< LP data */
9949 	   SCIP_SET*             set,                /**< global SCIP settings */
9950 	   SCIP_PROB*            prob,               /**< problem data */
9951 	   SCIP_Real*            weights,            /**< row weights in row summation */
9952 	   SCIP_REALARRAY*       sumcoef,            /**< array to store sum coefficients indexed by variables' probindex */
9953 	   SCIP_Real*            sumlhs,             /**< pointer to store the left hand side of the row summation */
9954 	   SCIP_Real*            sumrhs              /**< pointer to store the right hand side of the row summation */
9955 	   )
9956 	{
9957 	   SCIP_ROW* row;
9958 	   int r;
9959 	   int i;
9960 	   int idx;
9961 	   SCIP_Bool lhsinfinite;
9962 	   SCIP_Bool rhsinfinite;
9963 	
9964 	   assert(lp != NULL);
9965 	   assert(prob != NULL);
9966 	   assert(weights != NULL);
9967 	   assert(sumcoef != NULL);
9968 	   assert(sumlhs != NULL);
9969 	   assert(sumrhs != NULL);
9970 	
9971 	   /**@todo test, if a column based summation is faster */
9972 	
9973 	   SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9974 	   SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9975 	   *sumlhs = 0.0;
9976 	   *sumrhs = 0.0;
9977 	   lhsinfinite = FALSE;
9978 	   rhsinfinite = FALSE;
9979 	   for( r = 0; r < lp->nrows; ++r )
9980 	   {
9981 	      if( !SCIPsetIsZero(set, weights[r]) )
9982 	      {
9983 	         row = lp->rows[r];
9984 	         assert(row != NULL);
9985 	         assert(row->len == 0 || row->cols != NULL);
9986 	         assert(row->len == 0 || row->cols_index != NULL);
9987 	         assert(row->len == 0 || row->vals != NULL);
9988 	
9989 	         /* add the row coefficients to the sum */
9990 	         for( i = 0; i < row->len; ++i )
9991 	         {
9992 	            assert(row->cols[i] != NULL);
9993 	            assert(row->cols[i]->var != NULL);
9994 	            assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9995 	            assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9996 	            assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9997 	            idx = row->cols[i]->var_probindex;
9998 	            assert(0 <= idx && idx < prob->nvars);
9999 	            SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
10000	         }
10001	
10002	         /* add the row sides to the sum, depending on the sign of the weight */
10003	         if( weights[r] > 0.0 )
10004	         {
10005	            lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10006	            if( !lhsinfinite )
10007	               (*sumlhs) += weights[r] * (row->lhs - row->constant);
10008	            rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10009	            if( !rhsinfinite )
10010	               (*sumrhs) += weights[r] * (row->rhs - row->constant);
10011	         }
10012	         else
10013	         {
10014	            lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10015	            if( !lhsinfinite )
10016	               (*sumlhs) += weights[r] * (row->rhs - row->constant);
10017	            rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10018	            if( !rhsinfinite )
10019	               (*sumrhs) += weights[r] * (row->lhs - row->constant);
10020	         }
10021	      }
10022	   }
10023	
10024	   if( lhsinfinite )
10025	      *sumlhs = -SCIPsetInfinity(set);
10026	   if( rhsinfinite )
10027	      *sumrhs = SCIPsetInfinity(set);
10028	
10029	   return SCIP_OKAY;
10030	}
10031	
10032	/** stores LP state (like basis information) into LP state object */
10033	SCIP_RETCODE SCIPlpGetState(
10034	   SCIP_LP*              lp,                 /**< LP data */
10035	   BMS_BLKMEM*           blkmem,             /**< block memory */
10036	   SCIP_LPISTATE**       lpistate            /**< pointer to LP state information (like basis information) */
10037	   )
10038	{
10039	   assert(lp != NULL);
10040	   assert(lp->flushed);
10041	   assert(lp->solved);
10042	   assert(blkmem != NULL);
10043	   assert(lpistate != NULL);
10044	
10045	   /* check whether there is no lp */
10046	   if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10047	      *lpistate = NULL;
10048	   else
10049	   {
10050	      SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10051	   }
10052	
10053	   return SCIP_OKAY;
10054	}
10055	
10056	/** loads LP state (like basis information) into solver */
10057	SCIP_RETCODE SCIPlpSetState(
10058	   SCIP_LP*              lp,                 /**< LP data */
10059	   BMS_BLKMEM*           blkmem,             /**< block memory */
10060	   SCIP_SET*             set,                /**< global SCIP settings */
10061	   SCIP_PROB*            prob,               /**< problem data */
10062	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
10063	   SCIP_LPISTATE*        lpistate,           /**< LP state information (like basis information) */
10064	   SCIP_Bool             wasprimfeas,        /**< primal feasibility when LP state information was stored */
10065	   SCIP_Bool             wasprimchecked,     /**< true if the LP solution has passed the primal feasibility check */
10066	   SCIP_Bool             wasdualfeas,        /**< dual feasibility when LP state information was stored */
10067	   SCIP_Bool             wasdualchecked      /**< true if the LP solution has passed the dual feasibility check */
10068	   )
10069	{
10070	   assert(lp != NULL);
10071	   assert(blkmem != NULL);
10072	
10073	   /* flush changes to the LP solver */
10074	   SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10075	   assert(lp->flushed);
10076	
10077	   if( lp->solved && lp->solisbasic )
10078	      return SCIP_OKAY;
10079	
10080	   /* set LPI state in the LP solver */
10081	   if( lpistate == NULL )
10082	      lp->solisbasic = FALSE;
10083	   else
10084	   {
10085	      SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10086	      lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10087	   }
10088	   /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10089	    *        flushed and solved, also, e.g., when we hit the iteration limit
10090	    */
10091	   lp->primalfeasible = wasprimfeas;
10092	   lp->primalchecked = wasprimchecked;
10093	   lp->dualfeasible = wasdualfeas;
10094	   lp->dualchecked = wasdualchecked;
10095	
10096	   return SCIP_OKAY;
10097	}
10098	
10099	/** frees LP state information */
10100	SCIP_RETCODE SCIPlpFreeState(
10101	   SCIP_LP*              lp,                 /**< LP data */
10102	   BMS_BLKMEM*           blkmem,             /**< block memory */
10103	   SCIP_LPISTATE**       lpistate            /**< pointer to LP state information (like basis information) */
10104	   )
10105	{
10106	   assert(lp != NULL);
10107	
10108	   if( *lpistate != NULL )
10109	   {
10110	      SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10111	   }
10112	
10113	   return SCIP_OKAY;
10114	}
10115	
10116	/** interrupts the currently ongoing lp solve, or disables the interrupt */
10117	SCIP_RETCODE SCIPlpInterrupt(
10118	   SCIP_LP*              lp,                 /**< LP data */
10119	   SCIP_Bool             interrupt           /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10120	   )
10121	{
10122	   assert(lp != NULL);
10123	
10124	   if( lp->lpi == NULL )
10125	      return SCIP_OKAY;
10126	
10127	   SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10128	
10129	   return SCIP_OKAY;
10130	}
10131	
10132	/** stores pricing norms into LP norms object */
10133	SCIP_RETCODE SCIPlpGetNorms(
10134	   SCIP_LP*              lp,                 /**< LP data */
10135	   BMS_BLKMEM*           blkmem,             /**< block memory */
10136	   SCIP_LPINORMS**       lpinorms            /**< pointer to LP pricing norms information */
10137	   )
10138	{
10139	   assert(lp != NULL);
10140	   assert(lp->flushed);
10141	   assert(lp->solved);
10142	   assert(blkmem != NULL);
10143	   assert(lpinorms != NULL);
10144	
10145	   /* check whether there is no lp */
10146	   if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10147	      *lpinorms = NULL;
10148	   else
10149	   {
10150	      SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10151	   }
10152	
10153	   return SCIP_OKAY;
10154	}
10155	
10156	/** loads pricing norms from LP norms object into solver */
10157	SCIP_RETCODE SCIPlpSetNorms(
10158	   SCIP_LP*              lp,                 /**< LP data */
10159	   BMS_BLKMEM*           blkmem,             /**< block memory */
10160	   SCIP_LPINORMS*        lpinorms            /**< LP pricing norms information */
10161	   )
10162	{
10163	   assert(lp != NULL);
10164	   assert(blkmem != NULL);
10165	   assert(lp->flushed);
10166	
10167	   /* set LPI norms in the LP solver */
10168	   if( lpinorms != NULL )
10169	   {
10170	      SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10171	   }
10172	
10173	   return SCIP_OKAY;
10174	}
10175	
10176	/** frees pricing norms information */
10177	SCIP_RETCODE SCIPlpFreeNorms(
10178	   SCIP_LP*              lp,                 /**< LP data */
10179	   BMS_BLKMEM*           blkmem,             /**< block memory */
10180	   SCIP_LPINORMS**       lpinorms            /**< pointer to LP pricing norms information */
10181	   )
10182	{
10183	   assert(lp != NULL);
10184	
10185	   SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10186	
10187	   return SCIP_OKAY;
10188	}
10189	
10190	/** return the current cutoff bound of the lp */
10191	SCIP_Real SCIPlpGetCutoffbound(
10192	   SCIP_LP*              lp                  /**< current LP data */
10193	   )
10194	{
10195	   assert(lp != NULL);
10196	
10197	   return lp->cutoffbound;
10198	}
10199	
10200	/** sets the upper objective limit of the LP solver */
10201	SCIP_RETCODE SCIPlpSetCutoffbound(
10202	   SCIP_LP*              lp,                 /**< current LP data */
10203	   SCIP_SET*             set,                /**< global SCIP settings */
10204	   SCIP_PROB*            prob,               /**< problem data */
10205	   SCIP_Real             cutoffbound         /**< new upper objective limit */
10206	   )
10207	{
10208	   assert(lp != NULL);
10209	
10210	   SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10211	
10212	   /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10213	    * in SCIPendDive())
10214	    */
10215	   if( SCIPlpDivingObjChanged(lp) )
10216	   {
10217	      assert(SCIPsetIsInfinity(set, lp->cutoffbound));
10218	      return SCIP_OKAY;
10219	   }
10220	
10221	   /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10222	   if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10223	   {
10224	      /* mark the current solution invalid */
10225	      lp->solved = FALSE;
10226	      lp->lpobjval = SCIP_INVALID;
10227	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
10228	   }
10229	   /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10230	    * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10231	    */
10232	   else if( !lpCutoffDisabled(set, prob) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
10233	      && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10234	   {
10235	      assert(lp->flushed);
10236	      assert(lp->solved);
10237	      lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
10238	   }
10239	
10240	   lp->cutoffbound = cutoffbound;
10241	
10242	   return SCIP_OKAY;
10243	}
10244	
10245	/** gets current primal feasibility tolerance of LP solver */
10246	SCIP_Real SCIPlpGetFeastol(
10247	   SCIP_LP*              lp                  /**< current LP data */
10248	   )
10249	{
10250	   assert(lp != NULL);
10251	
10252	   return lp->feastol;
10253	}
10254	
10255	/** sets primal feasibility tolerance of LP solver */
10256	void SCIPlpSetFeastol(
10257	   SCIP_LP*              lp,                 /**< current LP data */
10258	   SCIP_SET*             set,                /**< global SCIP settings */
10259	   SCIP_Real             newfeastol          /**< new primal feasibility tolerance for LP */
10260	   )
10261	{
10262	   assert(lp != NULL);
10263	   assert(newfeastol > 0.0);
10264	
10265	   SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10266	
10267	   /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10268	   if( newfeastol < lp->feastol )
10269	   {
10270	      lp->solved = FALSE;
10271	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
10272	   }
10273	
10274	   lp->feastol = newfeastol;
10275	}
10276	
10277	/** resets primal feasibility tolerance of LP solver
10278	 *
10279	 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10280	 */
10281	void SCIPlpResetFeastol(
10282	   SCIP_LP*              lp,                 /**< current LP data */
10283	   SCIP_SET*             set                 /**< global SCIP settings */
10284	   )
10285	{
10286	   assert(lp != NULL);
10287	
10288	   SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10289	
10290	   if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10291	      SCIPlpSetFeastol(lp, set, MIN(SCIPsetRelaxfeastol(set), SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set))); /*lint !e666*/
10292	   else
10293	      SCIPlpSetFeastol(lp, set, SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set));
10294	}
10295	
10296	/** returns the name of the given LP algorithm */
10297	static
10298	const char* lpalgoName(
10299	   SCIP_LPALGO           lpalgo              /**< LP algorithm */
10300	   )
10301	{
10302	   switch( lpalgo )
10303	   {
10304	   case SCIP_LPALGO_PRIMALSIMPLEX:
10305	      return "primal simplex";
10306	   case SCIP_LPALGO_DUALSIMPLEX:
10307	      return "dual simplex";
10308	   case SCIP_LPALGO_BARRIER:
10309	      return "barrier";
10310	   case SCIP_LPALGO_BARRIERCROSSOVER:
10311	      return "barrier/crossover";
10312	   default:
10313	      SCIPerrorMessage("invalid LP algorithm\n");
10314	      SCIPABORT();
10315	      return "invalid"; /*lint !e527*/
10316	   }
10317	}
10318	
10319	/** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10320	static
10321	SCIP_RETCODE lpPrimalSimplex(
10322	   SCIP_LP*              lp,                 /**< current LP data */
10323	   SCIP_SET*             set,                /**< global SCIP settings */
10324	   SCIP_STAT*            stat,               /**< problem statistics */
10325	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
10326	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
10327	   SCIP_Bool             instable,           /**< is this a resolving call to avoid instable LPs? */
10328	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
10329	   )
10330	{
10331	   SCIP_Real timedelta;
10332	   SCIP_RETCODE retcode;
10333	   int iterations;
10334	
10335	   assert(lp != NULL);
10336	   assert(lp->flushed);
10337	   assert(set != NULL);
10338	   assert(stat != NULL);
10339	   assert(lperror != NULL);
10340	
10341	   SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10342	      stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10343	
10344	   *lperror = FALSE;
10345	
10346	#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10347	   if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10348	   {
10349	      char fname[SCIP_MAXSTRLEN];
10350	      (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10351	      SCIP_CALL( SCIPlpWrite(lp, fname) );
10352	      SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10353	         fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10354	         lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
10355	   }
10356	#endif
10357	
10358	   /* start timing */
10359	   if( lp->diving || lp->probing )
10360	   {
10361	      if( lp->strongbranchprobing )
10362	         SCIPclockStart(stat->strongbranchtime, set);
10363	      else
10364	         SCIPclockStart(stat->divinglptime, set);
10365	
10366	      timedelta = 0.0;   /* unused for diving or probing */
10367	   }
10368	   else
10369	   {
10370	      SCIPclockStart(stat->primallptime, set);
10371	      timedelta = -SCIPclockGetTime(stat->primallptime);
10372	   }
10373	
10374	   /* if this is a call to resolve an instable LP, collect time */
10375	   if( instable )
10376	   {
10377	      SCIPclockStart(stat->resolveinstablelptime, set);
10378	   }
10379	
10380	   /* call primal simplex */
(16) Event example_assign: Example 5: Assigning: "retcode" = return value from "SCIPlpiSolvePrimal(lp->lpi)".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_checked]
10381	   retcode = SCIPlpiSolvePrimal(lp->lpi);
(17) Event example_checked: Example 5 (cont.): "retcode" has its value checked in "retcode == SCIP_LPERROR".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign]
10382	   if( retcode == SCIP_LPERROR )
10383	   {
10384	      *lperror = TRUE;
10385	      SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10386	   }
10387	   else
10388	   {
10389	      SCIP_CALL( retcode );
10390	   }
10391	   lp->lastlpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
10392	   lp->solisbasic = TRUE;
10393	
10394	   /* stop timing */
10395	   if( lp->diving || lp->probing )
10396	   {
10397	      if( lp->strongbranchprobing )
10398	         SCIPclockStop(stat->strongbranchtime, set);
10399	      else
10400	         SCIPclockStop(stat->divinglptime, set);
10401	   }
10402	   else
10403	   {
10404	      timedelta += SCIPclockGetTime(stat->primallptime);
10405	      SCIPclockStop(stat->primallptime, set);
10406	   }
10407	
10408	   if ( instable )
10409	   {
10410	      SCIPclockStop(stat->resolveinstablelptime, set);
10411	   }
10412	
10413	   /* count number of iterations */
10414	   SCIPstatIncrement(stat, set, lpcount);
10415	   SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10416	   if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10417	   {
10418	      if( !lp->strongbranchprobing )
10419	      {
10420	         SCIPstatIncrement(stat, set, nlps);
10421	         SCIPstatAdd( stat, set, nlpiterations, iterations );
10422	      }
10423	      if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10424	      {
10425	         SCIPstatIncrement(stat, set, nprimalresolvelps );
10426	         SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10427	      }
10428	      if ( instable )
10429	      {
10430	         SCIPstatIncrement(stat, set, nresolveinstablelps);
10431	         SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10432	      }
10433	      if( lp->diving || lp->probing )
10434	      {
10435	         if( lp->strongbranchprobing )
10436	         {
10437	            SCIPstatIncrement(stat, set, nsbdivinglps);
10438	            SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10439	         }
10440	         else
10441	         {
10442	            SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10443	            SCIPstatIncrement(stat, set, ndivinglps);
10444	            SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10445	         }
10446	      }
10447	      else
10448	      {
10449	         SCIPstatIncrement(stat, set, nprimallps);
10450	         SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10451	      }
10452	   }
10453	   else
10454	   {
10455	      if ( ! lp->diving && ! lp->probing )
10456	      {
10457	         SCIPstatIncrement(stat, set, nprimalzeroitlps);
10458	         SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10459	      }
10460	
10461	      if ( keepsol && !(*lperror) )
10462	      {
10463	         /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10464	         if( lp->validsollp == stat->lpcount-1 )
10465	            lp->validsollp = stat->lpcount;
10466	         if( lp->validfarkaslp == stat->lpcount-1 )
10467	            lp->validfarkaslp = stat->lpcount;
10468	      }
10469	   }
10470	
10471	   SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10472	      stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10473	
10474	   return SCIP_OKAY;
10475	}
10476	
10477	/** calls LPI to perform dual simplex, measures time and counts iterations */
10478	static
10479	SCIP_RETCODE lpDualSimplex(
10480	   SCIP_LP*              lp,                 /**< current LP data */
10481	   SCIP_SET*             set,                /**< global SCIP settings */
10482	   SCIP_STAT*            stat,               /**< problem statistics */
10483	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
10484	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
10485	   SCIP_Bool             instable,           /**< is this a resolving call to avoid instable LPs? */
10486	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
10487	   )
10488	{
10489	   SCIP_Real timedelta;
10490	   SCIP_RETCODE retcode;
10491	   int iterations;
10492	
10493	   assert(lp != NULL);
10494	   assert(lp->flushed);
10495	   assert(set != NULL);
10496	   assert(stat != NULL);
10497	   assert(lperror != NULL);
10498	
10499	   SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10500	      stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10501	
10502	   *lperror = FALSE;
10503	
10504	#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10505	   if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10506	   {
10507	      char fname[SCIP_MAXSTRLEN];
10508	      (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10509	      SCIP_CALL( SCIPlpWrite(lp, fname) );
10510	      SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10511	         fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10512	         lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
10513	   }
10514	#endif
10515	
10516	   /* start timing */
10517	   if( lp->diving || lp->probing )
10518	   {
10519	      if( lp->strongbranchprobing )
10520	         SCIPclockStart(stat->strongbranchtime, set);
10521	      else
10522	         SCIPclockStart(stat->divinglptime, set);
10523	
10524	      timedelta = 0.0;   /* unused for diving or probing */
10525	   }
10526	   else
10527	   {
10528	      SCIPclockStart(stat->duallptime, set);
10529	      timedelta = -SCIPclockGetTime(stat->duallptime);
10530	   }
10531	
10532	   /* if this is a call to resolve an instable LP, collect time */
10533	   if ( instable )
10534	   {
10535	      SCIPclockStart(stat->resolveinstablelptime, set);
10536	   }
10537	
10538	   /* call dual simplex */
10539	   retcode = SCIPlpiSolveDual(lp->lpi);
10540	   if( retcode == SCIP_LPERROR )
10541	   {
10542	      *lperror = TRUE;
10543	      SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10544	   }
10545	   else
10546	   {
10547	      SCIP_CALL( retcode );
10548	   }
10549	   lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
10550	   lp->solisbasic = TRUE;
10551	
10552	   /* stop timing */
10553	   if( lp->diving || lp->probing )
10554	   {
10555	      if( lp->strongbranchprobing )
10556	         SCIPclockStop(stat->strongbranchtime, set);
10557	      else
10558	         SCIPclockStop(stat->divinglptime, set);
10559	   }
10560	   else
10561	   {
10562	      timedelta += SCIPclockGetTime(stat->duallptime);
10563	      SCIPclockStop(stat->duallptime, set);
10564	   }
10565	
10566	   if ( instable )
10567	   {
10568	      SCIPclockStop(stat->resolveinstablelptime, set);
10569	   }
10570	
10571	   /* count number of iterations */
10572	   SCIPstatIncrement(stat, set, lpcount);
10573	   SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10574	   if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10575	   {
10576	      if( !lp->strongbranchprobing )
10577	      {
10578	         SCIPstatIncrement(stat, set, nlps);
10579	         SCIPstatAdd(stat, set, nlpiterations, iterations);
10580	      }
10581	      if( resolve && !lp->lpifromscratch && stat->nlps > 1  )
10582	      {
10583	         SCIPstatIncrement(stat, set, ndualresolvelps);
10584	         SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10585	      }
10586	      if ( instable )
10587	      {
10588	         SCIPstatIncrement(stat, set, nresolveinstablelps);
10589	         SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10590	      }
10591	      if( lp->diving || lp->probing )
10592	      {
10593	         if( lp->strongbranchprobing )
10594	         {
10595	            SCIPstatIncrement(stat, set, nsbdivinglps);
10596	            SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10597	         }
10598	         else
10599	         {
10600	            SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10601	            SCIPstatIncrement(stat, set, ndivinglps);
10602	            SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10603	         }
10604	      }
10605	      else
10606	      {
10607	         SCIPstatIncrement(stat, set, nduallps);
10608	         SCIPstatAdd(stat, set, nduallpiterations, iterations);
10609	      }
10610	   }
10611	   else
10612	   {
10613	      if ( ! lp->diving && ! lp->probing )
10614	      {
10615	         SCIPstatIncrement(stat, set, ndualzeroitlps);
10616	         SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10617	      }
10618	
10619	      if( keepsol && !(*lperror) )
10620	      {
10621	         /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10622	         if( lp->validsollp == stat->lpcount-1 )
10623	            lp->validsollp = stat->lpcount;
10624	         if( lp->validfarkaslp == stat->lpcount-1 )
10625	            lp->validfarkaslp = stat->lpcount;
10626	      }
10627	   }
10628	
10629	   SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10630	      stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10631	
10632	   return SCIP_OKAY;
10633	}
10634	
10635	/** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10636	 *
10637	 *  We follow the approach of the following paper to find a lexicographically minimal optimal
10638	 *  solution:
10639	 *
10640	 *  Zanette, Fischetti, Balas@n
10641	 *  Can pure cutting plane algorithms work?@n
10642	 *  IPCO 2008, Bertinoro, Italy.
10643	 *
10644	 *  We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10645	 *  heuristic, i.e., we limit the number of components which are minimized.
10646	 *
10647	 *  More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10648	 *  nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10649	 *  variables) that have nonzero reduced cost. This fixes the objective function value, because only
10650	 *  pivots that will not change the objective are allowed afterwards.
10651	 *
10652	 *  Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10653	 *  nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10654	 *  candidate is found, we set the objective to minimize this variable. We run the primal simplex
10655	 *  algorithm (since the objective is changed the solution is not dual feasible anymore; if
10656	 *  variables out of the basis have been fixed to their lower bound, the basis is also not primal
10657	 *  feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10658	 *  reduced cost. We then choose the next variable and iterate.
10659	 *
10660	 *  We stop the process once we do not find candidates or have performed a maximum number of
10661	 *  iterations.
10662	 *
10663	 *  @todo Does this really produce a lexicographically minimal solution?
10664	 *  @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10665	 *    guarantee that these variables will not be changed in later stages? We can fix these variables
10666	 *    to their lower bound, but this destroys the basis.
10667	 *  @todo Should we use lexicographical minimization in diving/probing or not?
10668	 */
10669	static
10670	SCIP_RETCODE lpLexDualSimplex(
10671	   SCIP_LP*              lp,                 /**< current LP data */
10672	   SCIP_SET*             set,                /**< global SCIP settings */
10673	   SCIP_STAT*            stat,               /**< problem statistics */
10674	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
10675	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
10676	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
10677	   )
10678	{
10679	   SCIP_Real timedelta;
10680	   SCIP_RETCODE retcode;
10681	   int totalIterations;
10682	   int lexIterations;
10683	   int iterations;
10684	   int rounds;
10685	
10686	   assert(lp != NULL);
10687	   assert(lp->flushed);
10688	   assert(set != NULL);
10689	   assert(stat != NULL);
10690	   assert(lperror != NULL);
10691	
10692	   SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10693	      stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10694	
10695	   *lperror = FALSE;
10696	
10697	   /* start timing */
10698	   if( lp->diving || lp->probing )
10699	   {
10700	      if( lp->strongbranchprobing )
10701	         SCIPclockStart(stat->strongbranchtime, set);
10702	      else
10703	         SCIPclockStart(stat->divinglptime, set);
10704	
10705	      timedelta = 0.0;   /* unused for diving or probing */
10706	   }
10707	   else
10708	   {
10709	      SCIPclockStart(stat->duallptime, set);
10710	      timedelta = -SCIPclockGetTime(stat->duallptime);
10711	   }
10712	
10713	   /* call dual simplex for first lp */
10714	   retcode = SCIPlpiSolveDual(lp->lpi);
10715	   if( retcode == SCIP_LPERROR )
10716	   {
10717	      *lperror = TRUE;
10718	      SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10719	   }
10720	   else
10721	   {
10722	      SCIP_CALL( retcode );
10723	   }
10724	   SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10725	   totalIterations = iterations;
10726	
10727	   /* stop timing */
10728	   if( lp->diving || lp->probing )
10729	   {
10730	      if( lp->strongbranchprobing )
10731	         SCIPclockStop(stat->strongbranchtime, set);
10732	      else
10733	         SCIPclockStop(stat->divinglptime, set);
10734	   }
10735	   else
10736	   {
10737	      timedelta += SCIPclockGetTime(stat->duallptime);
10738	      SCIPclockStop(stat->duallptime, set);
10739	   }
10740	
10741	   /* count number of iterations */
10742	   SCIPstatIncrement(stat, set, lpcount);
10743	   if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10744	   {
10745	      if( lp->strongbranchprobing )
10746	      {
10747	         SCIPstatAdd(stat, set, nlpiterations, iterations);
10748	      }
10749	      if( resolve && !lp->lpifromscratch && stat->nlps > 1  )
10750	      {
10751	         SCIPstatIncrement(stat, set, ndualresolvelps);
10752	         SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10753	      }
10754	      if( lp->diving || lp->probing )
10755	      {
10756	         if( lp->strongbranchprobing )
10757	         {
10758	            SCIPstatIncrement(stat, set, nsbdivinglps);
10759	            SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10760	         }
10761	         else
10762	         {
10763	            SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10764	            SCIPstatIncrement(stat, set, ndivinglps);
10765	            SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10766	         }
10767	      }
10768	      else
10769	      {
10770	         SCIPstatIncrement(stat, set, nduallps);
10771	         SCIPstatAdd(stat, set, nduallpiterations, iterations);
10772	      }
10773	   }
10774	   else
10775	   {
10776	      if ( ! lp->diving && ! lp->probing )
10777	      {
10778	         SCIPstatIncrement(stat, set, ndualzeroitlps);
10779	         SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10780	      }
10781	   }
10782	   lexIterations = 0;
10783	
10784	   /* search for lexicographically minimal optimal solution */
10785	   if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10786	   {
10787	      SCIP_Bool chooseBasic;
10788	      SCIP_Real* primsol;
10789	      SCIP_Real* dualsol;
10790	      SCIP_Real* redcost;
10791	      int* cstat;
10792	      int* rstat;
10793	      SCIP_Real* newobj;
10794	      SCIP_Real* newlb;
10795	      SCIP_Real* newub;
10796	      SCIP_Real* newlhs;
10797	      SCIP_Real* newrhs;
10798	      SCIP_Real* oldlb;
10799	      SCIP_Real* oldub;
10800	      SCIP_Real* oldlhs;
10801	      SCIP_Real* oldrhs;
10802	      SCIP_Real* oldobj;
10803	      SCIP_Bool* fixedc;
10804	      SCIP_Bool* fixedr;
10805	      int* indcol;
10806	      int* indrow;
10807	      int* indallcol;
10808	      int* indallrow;
10809	      int nDualDeg;
10810	      int r, c;
10811	      int cntcol;
10812	      int cntrow;
10813	      int nruns;
10814	      int pos;
10815	
10816	      chooseBasic = set->lp_lexdualbasic;
10817	
10818	      /* start timing */
10819	      SCIPclockStart(stat->lexduallptime, set);
10820	
10821	      /* get all solution information */
10822	      SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10823	      SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10824	      if( chooseBasic )
10825	      {
10826	         SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10827	      }
10828	      else
10829	         primsol = NULL;
10830	
10831	      /* get basic and nonbasic information */
10832	      SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) );
10833	      SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) );
10834	
10835	      /* save bounds, lhs/rhs, and objective */
10836	      SCIP_CALL( SCIPsetAllocBufferArray(set, &oldobj, lp->nlpicols) );
10837	      SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlb, lp->nlpicols) );
10838	      SCIP_CALL( SCIPsetAllocBufferArray(set, &oldub, lp->nlpicols) );
10839	      SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlhs, lp->nlpirows) );
10840	      SCIP_CALL( SCIPsetAllocBufferArray(set, &oldrhs, lp->nlpirows) );
10841	      SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10842	      SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10843	      SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10844	
10845	      /* get storage for several arrays */
10846	      SCIP_CALL( SCIPsetAllocBufferArray(set, &newlb, lp->nlpicols) );
10847	      SCIP_CALL( SCIPsetAllocBufferArray(set, &newub, lp->nlpicols) );
10848	      SCIP_CALL( SCIPsetAllocBufferArray(set, &indcol, lp->nlpicols) );
10849	
10850	      SCIP_CALL( SCIPsetAllocBufferArray(set, &newlhs, lp->nlpirows) );
10851	      SCIP_CALL( SCIPsetAllocBufferArray(set, &newrhs, lp->nlpirows) );
10852	      SCIP_CALL( SCIPsetAllocBufferArray(set, &indrow, lp->nlpirows) );
10853	
10854	      SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10855	      SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10856	
10857	      SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedc, lp->nlpicols) );
10858	      SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedr, lp->nlpirows) );
10859	
10860	      /* initialize: set objective to 0, get fixed variables */
10861	      SCIP_CALL( SCIPsetAllocBufferArray(set, &newobj, lp->nlpicols) );
10862	      for( c = 0; c < lp->nlpicols; ++c )
10863	      {
10864	         newobj[c] = 0.0;
10865	         indallcol[c] = c;
10866	         if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10867	            fixedc[c] = TRUE;
10868	         else
10869	            fixedc[c] = FALSE;
10870	      }
10871	
10872	      /* initialize: get fixed slack variables */
10873	      for( r = 0; r < lp->nlpirows; ++r )
10874	      {
10875	         indallrow[r] = r;
10876	         if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10877	            fixedr[r] = TRUE;
10878	         else
10879	            fixedr[r] = FALSE;
10880	      }
10881	
10882	#ifdef DEBUG_LEXDUAL
10883	      {
10884	         int j;
10885	
10886	         if( !chooseBasic )
10887	         {
10888	            assert(primsol == NULL);
10889	            SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10890	         }
10891	         assert(primsol != NULL);
10892	         SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10893	         SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10894	
10895	         for( j = 0; j < lp->nlpicols; ++j )
10896	         {
10897	            if( fixedc[j] )
10898	            {
10899	               SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10900	            }
10901	            else
10902	            {
10903	               char type;
10904	               switch( (SCIP_BASESTAT) cstat[j] )
10905	               {
10906	               case SCIP_BASESTAT_LOWER:
10907	                  type = 'l';
10908	                  break;
10909	               case SCIP_BASESTAT_UPPER:
10910	                  type = 'u';
10911	                  break;
10912	               case SCIP_BASESTAT_ZERO:
10913	                  type = 'z';
10914	                  break;
10915	               case SCIP_BASESTAT_BASIC:
10916	                  type = 'b';
10917	                  break;
10918	               default:
10919	                  type = '?';
10920	                  SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10921	                  SCIPABORT();
10922	               }
10923	               SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10924	            }
10925	         }
10926	         SCIPsetDebugMsg(set, "\n\n");
10927	
10928	         if( !chooseBasic )
10929	         {
10930	            SCIPsetFreeBufferArray(set, &primsol);
10931	            assert(primsol == NULL);
10932	         }
10933	      }
10934	#endif
10935	
10936	      /* perform lexicographic rounds */
10937	      pos = -1;
10938	      nruns = 0;
10939	      rounds = 0;
10940	      /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10941	      do
10942	      {
10943	         int oldpos;
10944	
10945	         /* get current solution */
10946	         if( chooseBasic )
10947	            SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10948	         else
10949	         {
10950	            SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10951	            assert(primsol == NULL);
10952	         }
10953	
10954	         /* get current basis */
10955	         SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10956	
10957	         /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10958	         nDualDeg = 0;
10959	         cntcol = 0;
10960	         oldpos = pos;
10961	         pos = -1;
10962	         for( c = 0; c < lp->nlpicols; ++c )
10963	         {
10964	            if( !fixedc[c] )
10965	            {
10966	               /* check whether variable is in basis */
10967	               if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10968	               {
10969	                  /* store first candidate */
10970	                  if( pos == -1 && c > oldpos )
10971	                  {
10972	                     if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10973	                        pos = c;
10974	                  }
10975	               }
10976	               else
10977	               {
10978	                  /* reduced cost == 0 -> possible candidate */
10979	                  if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10980	                  {
10981	                     ++nDualDeg;
10982	                     /* only if we have not yet found a candidate */
10983	                     if( pos == -1 && c > oldpos )
10984	                     {
10985	                        /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10986	                        if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10987	                        {
10988	                           newlb[cntcol] = oldlb[c];
10989	                           newub[cntcol] = oldlb[c];
10990	                           indcol[cntcol++] = c;
10991	                           fixedc[c] = TRUE;
10992	                        }
10993	                        else /* found a non-fixed candidate */
10994	                        {
10995	                           if( !chooseBasic )
10996	                              pos = c;
10997	                        }
10998	                     }
10999	                  }
11000	                  else
11001	                  {
11002	                     /* nonzero reduced cost -> variable can be fixed */
11003	                     if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11004	                     {
11005	                        newlb[cntcol] = oldlb[c];
11006	                        newub[cntcol] = oldlb[c];
11007	                     }
11008	                     else
11009	                     {
11010	                        if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11011	                        {
11012	                           newlb[cntcol] = oldub[c];
11013	                           newub[cntcol] = oldub[c];
11014	                        }
11015	                        else
11016	                        {
11017	                           assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11018	                           newlb[cntcol] = 0.0;
11019	                           newub[cntcol] = 0.0;
11020	                        }
11021	                     }
11022	                     indcol[cntcol++] = c;
11023	                     fixedc[c] = TRUE;
11024	                  }
11025	               }
11026	            }
11027	         }
11028	
11029	         /* check rows */
11030	         cntrow = 0;
11031	         for( r = 0; r < lp->nlpirows; ++r )
11032	         {
11033	            if( !fixedr[r] )
11034	            {
11035	               /* consider only nonbasic rows */
11036	               if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11037	               {
11038	                  assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11039	                  if( SCIPsetIsFeasZero(set, dualsol[r]) )
11040	                     ++nDualDeg;
11041	                  else
11042	                  {
11043	                     if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11044	                     {
11045	                        assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11046	                        newlhs[cntrow] = oldlhs[r];
11047	                        newrhs[cntrow] = oldlhs[r];
11048	                     }
11049	                     else
11050	                     {
11051	                        assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11052	                        newlhs[cntrow] = oldrhs[r];
11053	                        newrhs[cntrow] = oldrhs[r];
11054	                     }
11055	                     indrow[cntrow++] = r;
11056	                     fixedr[r] = TRUE;
11057	                  }
11058	               }
11059	            }
11060	         }
11061	
11062	         if( nDualDeg > 0 && pos >= 0 )
11063	         {
11064	            assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11065	
11066	            /* change objective */
11067	            if( nruns == 0 )
11068	            {
11069	               /* set objective to appropriate unit vector for first run */
11070	               newobj[pos] = 1.0;
11071	               SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11072	            }
11073	            else
11074	            {
11075	               /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11076	               SCIP_Real obj = 1.0;
11077	               SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11078	            }
11079	
11080	            /* fix variables */
11081	            SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11082	            SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11083	
11084	            /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
(14) Event example_assign: Example 4: Assigning: "retcode" = return value from "SCIPlpiSolvePrimal(lp->lpi)".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_checked][example_assign][example_checked]
11085	            retcode = SCIPlpiSolvePrimal(lp->lpi);
(15) Event example_checked: Example 4 (cont.): "retcode" has its value checked in "retcode == SCIP_LPERROR".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_assign][example_checked]
11086	            if( retcode == SCIP_LPERROR )
11087	            {
11088	               *lperror = TRUE;
11089	               SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11090	            }
11091	            else
11092	            {
11093	               SCIP_CALL( retcode );
11094	            }
11095	            SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11096	            lexIterations += iterations;
11097	
11098	#ifdef DEBUG_LEXDUAL
11099	            if( iterations > 0 )
11100	            {
11101	               int j;
11102	
11103	               if( !chooseBasic )
11104	               {
11105	                  assert(primsol == NULL);
11106	                  SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11107	               }
11108	               assert(primsol != NULL);
11109	               SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11110	
11111	               for( j = 0; j < lp->nlpicols; ++j )
11112	               {
11113	                  if( fixedc[j] )
11114	                  {
11115	                     SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11116	                  }
11117	                  else
11118	                  {
11119	                     char cstart = '[';
11120	                     char cend = ']';
11121	                     char type;
11122	
11123	                     if(j == pos)
11124	                     {
11125	                        cstart = '*';
11126	                        cend = '*';
11127	                     }
11128	
11129	                     switch( (SCIP_BASESTAT) cstat[j] )
11130	                     {
11131	                     case SCIP_BASESTAT_LOWER:
11132	                        type = 'l';
11133	                        break;
11134	                     case SCIP_BASESTAT_UPPER:
11135	                        type = 'u';
11136	                        break;
11137	                     case SCIP_BASESTAT_ZERO:
11138	                        type = 'z';
11139	                        break;
11140	                     case SCIP_BASESTAT_BASIC:
11141	                        type = 'b';
11142	                        break;
11143	                     default:
11144	                        type = '?';
11145	                        SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11146	                        SCIPABORT();
11147	                     }
11148	                     SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11149	                  }
11150	               }
11151	               SCIPsetDebugMsg(set, "\n\n");
11152	
11153	               if( !chooseBasic )
11154	               {
11155	                  SCIPsetFreeBufferArray(set, &primsol);
11156	                  assert(primsol == NULL);
11157	               }
11158	            }
11159	#endif
11160	
11161	            /* count only as round if iterations have been performed */
11162	            if( iterations > 0 )
11163	               ++rounds;
11164	            ++nruns;
11165	         }
11166	      }
11167	      while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11168	
11169	      /* reset bounds, lhs/rhs, and obj */
11170	      SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11171	      SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11172	      SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11173	
11174	      /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
11175	      retcode = SCIPlpiSolveDual(lp->lpi);
11176	      if( retcode == SCIP_LPERROR )
11177	      {
11178	         *lperror = TRUE;
11179	         SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11180	      }
11181	      else
11182	      {
11183	         SCIP_CALL( retcode );
11184	      }
11185	      assert(SCIPlpiIsOptimal(lp->lpi));
11186	      SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11187	      lexIterations += iterations;
11188	
11189	      /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11190	
11191	      /* count number of iterations */
11192	      if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11193	         SCIPstatIncrement(stat, set, nlps);
11194	
11195	      if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11196	      {
11197	         SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11198	         if( resolve && !lp->lpifromscratch && stat->nlps > 1  )
11199	         {
11200	            SCIPstatIncrement(stat, set, nlexdualresolvelps);
11201	            SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11202	         }
11203	         SCIPstatIncrement(stat, set, nlexduallps);
11204	         SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11205	
11206	         totalIterations += lexIterations;
11207	      }
11208	
11209	      /* free space */
11210	      SCIPsetFreeBufferArray(set, &newobj);
11211	
11212	      SCIPsetFreeBufferArray(set, &fixedr);
11213	      SCIPsetFreeBufferArray(set, &fixedc);
11214	
11215	      SCIPsetFreeBufferArray(set, &indallrow);
11216	      SCIPsetFreeBufferArray(set, &indallcol);
11217	
11218	      SCIPsetFreeBufferArray(set, &indrow);
11219	      SCIPsetFreeBufferArray(set, &newrhs);
11220	      SCIPsetFreeBufferArray(set, &newlhs);
11221	
11222	      SCIPsetFreeBufferArray(set, &indcol);
11223	      SCIPsetFreeBufferArray(set, &newub);
11224	      SCIPsetFreeBufferArray(set, &newlb);
11225	
11226	      SCIPsetFreeBufferArray(set, &oldobj);
11227	      SCIPsetFreeBufferArray(set, &oldrhs);
11228	      SCIPsetFreeBufferArray(set, &oldlhs);
11229	      SCIPsetFreeBufferArray(set, &oldub);
11230	      SCIPsetFreeBufferArray(set, &oldlb);
11231	
11232	      SCIPsetFreeBufferArray(set, &rstat);
11233	      SCIPsetFreeBufferArray(set, &cstat);
11234	
11235	      SCIPsetFreeBufferArray(set, &redcost);
11236	      SCIPsetFreeBufferArray(set, &dualsol);
11237	      if( chooseBasic )
11238	         SCIPsetFreeBufferArray(set, &primsol);
11239	
11240	      /* stop timing */
11241	      SCIPclockStop(stat->lexduallptime, set);
11242	
11243	      SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11244	         stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11245	   }
11246	   lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
11247	   lp->solisbasic = TRUE;
11248	
11249	   if( totalIterations > 0 && !lp->strongbranchprobing )
11250	      SCIPstatIncrement(stat, set, nlps);
11251	   else
11252	   {
11253	      if( keepsol && !(*lperror) )
11254	      {
11255	         /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11256	         if( lp->validsollp == stat->lpcount-1 )
11257	            lp->validsollp = stat->lpcount;
11258	         if( lp->validfarkaslp == stat->lpcount-1 )
11259	            lp->validfarkaslp = stat->lpcount;
11260	      }
11261	   }
11262	
11263	   return SCIP_OKAY;
11264	}
11265	
11266	/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11267	static
11268	SCIP_RETCODE lpBarrier(
11269	   SCIP_LP*              lp,                 /**< current LP data */
11270	   SCIP_SET*             set,                /**< global SCIP settings */
11271	   SCIP_STAT*            stat,               /**< problem statistics */
11272	   SCIP_Bool             crossover,          /**< should crossover be performed? */
11273	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
11274	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
11275	   )
11276	{
11277	   SCIP_Real timedelta;
11278	   SCIP_RETCODE retcode;
11279	   int iterations;
11280	
11281	   assert(lp != NULL);
11282	   assert(lp->flushed);
11283	   assert(set != NULL);
11284	   assert(stat != NULL);
11285	   assert(lperror != NULL);
11286	
11287	   SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11288	      stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11289	      stat->nbarrierlps, stat->ndivinglps);
11290	
11291	   *lperror = FALSE;
11292	
11293	#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11294	   if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11295	   {
11296	      char fname[SCIP_MAXSTRLEN];
11297	      (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11298	      SCIP_CALL( SCIPlpWrite(lp, fname) );
11299	      SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11300	         fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11301	         lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving);
11302	   }
11303	#endif
11304	
11305	   /* start timing */
11306	   if( lp->diving || lp->probing )
11307	   {
11308	      if( lp->strongbranchprobing )
11309	         SCIPclockStart(stat->strongbranchtime, set);
11310	      else
11311	         SCIPclockStart(stat->divinglptime, set);
11312	
11313	      timedelta = 0.0;   /* unused for diving or probing */
11314	   }
11315	   else
11316	   {
11317	      SCIPclockStart(stat->barrierlptime, set);
11318	      timedelta = -SCIPclockGetTime(stat->barrierlptime);
11319	   }
11320	
11321	   /* call barrier algorithm */
11322	   retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11323	   if( retcode == SCIP_LPERROR )
11324	   {
11325	      *lperror = TRUE;
11326	      SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11327	   }
11328	   else
11329	   {
11330	      SCIP_CALL( retcode );
11331	   }
11332	   lp->lastlpalgo = (crossover ? SCIP_LPALGO_BARRIERCROSSOVER : SCIP_LPALGO_BARRIER);
11333	   lp->solisbasic = crossover;
11334	
11335	   /* stop timing */
11336	   if( lp->diving || lp->probing )
11337	   {
11338	      if( lp->strongbranchprobing )
11339	         SCIPclockStop(stat->strongbranchtime, set);
11340	      else
11341	         SCIPclockStop(stat->divinglptime, set);
11342	   }
11343	   else
11344	   {
11345	      SCIPclockStop(stat->barrierlptime, set);
11346	      timedelta += SCIPclockGetTime(stat->barrierlptime);
11347	   }
11348	
11349	   /* count number of iterations */
11350	   SCIPstatIncrement(stat, set, lpcount);
11351	   SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11352	   if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11353	   {
11354	      if( !lp->strongbranchprobing )
11355	      {
11356	         SCIPstatIncrement(stat, set, nlps);
11357	         SCIPstatAdd(stat, set, nlpiterations, iterations);
11358	      }
11359	      if( lp->diving || lp->probing )
11360	      {
11361	         if( lp->strongbranchprobing )
11362	         {
11363	            SCIPstatIncrement(stat, set, nsbdivinglps);
11364	            SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11365	         }
11366	         else
11367	         {
11368	            SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11369	            SCIPstatIncrement(stat, set, ndivinglps);
11370	            SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11371	         }
11372	      }
11373	      else
11374	      {
11375	         SCIPstatIncrement(stat, set, nbarrierlps);
11376	         SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11377	      }
11378	   }
11379	   else
11380	   {
11381	      if ( ! lp->diving && ! lp->probing )
11382	      {
11383	         SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11384	         SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11385	      }
11386	
11387	      if( keepsol && !(*lperror) )
11388	      {
11389	         /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11390	         if( lp->validsollp == stat->lpcount-1 )
11391	            lp->validsollp = stat->lpcount;
11392	         if( lp->validfarkaslp == stat->lpcount-1 )
11393	            lp->validfarkaslp = stat->lpcount;
11394	      }
11395	   }
11396	
11397	   SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11398	      stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11399	
11400	   return SCIP_OKAY;
11401	}
11402	
11403	/** solves the LP with the given algorithm */
11404	static
11405	SCIP_RETCODE lpAlgorithm(
11406	   SCIP_LP*              lp,                 /**< current LP data */
11407	   SCIP_SET*             set,                /**< global SCIP settings */
11408	   SCIP_STAT*            stat,               /**< problem statistics */
11409	   SCIP_LPALGO           lpalgo,             /**< LP algorithm that should be applied */
11410	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
11411	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
11412	   SCIP_Bool             instable,           /**< is this a resolving call to avoid instable LPs? */
11413	   SCIP_Bool*            timelimit,          /**< pointer to store whether the time limit was hit */
11414	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
11415	   )
11416	{
11417	   SCIP_Real lptimelimit;
11418	   SCIP_Bool success;
11419	
11420	   assert(lp != NULL);
11421	   assert(lp->flushed);
11422	   assert(lperror != NULL);
11423	
11424	   /* check if a time limit is set, and set time limit for LP solver accordingly */
11425	   lptimelimit = SCIPlpiInfinity(lp->lpi);
11426	   if( set->istimelimitfinite )
11427	      lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11428	
11429	   success = FALSE;
11430	   if( lptimelimit > 0.0 )
11431	      SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11432	
11433	   if( lptimelimit <= 0.0 || !success )
11434	   {
11435	      SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11436	      *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11437	      *timelimit = TRUE;
11438	      return SCIP_OKAY;
11439	   }
11440	   SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11441	
11442	   /* call appropriate LP algorithm */
11443	   switch( lpalgo )
11444	   {
11445	   case SCIP_LPALGO_PRIMALSIMPLEX:
11446	      SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11447	      break;
11448	
11449	   case SCIP_LPALGO_DUALSIMPLEX:
11450	      /* run dual lexicographic simplex if required */
11451	      if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11452	      {
11453	         SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11454	      }
11455	      else
11456	      {
11457	         SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11458	      }
11459	      break;
11460	
11461	   case SCIP_LPALGO_BARRIER:
11462	      SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11463	      break;
11464	
11465	   case SCIP_LPALGO_BARRIERCROSSOVER:
11466	      SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11467	      break;
11468	
11469	   default:
11470	      SCIPerrorMessage("invalid LP algorithm\n");
11471	      return SCIP_INVALIDDATA;
11472	   }
11473	
11474	   if( !(*lperror) )
11475	   {
11476	      /* check for primal and dual feasibility */
11477	      SCIP_CALL( SCIPlpiGetSolFeasibility(lp->lpi, &lp->primalfeasible, &lp->dualfeasible) );
11478	
11479	      SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11480	   }
11481	
11482	   return SCIP_OKAY;
11483	}
11484	
11485	/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11486	 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11487	 */
11488	#define MAXNUMTROUBLELPMSGS 10
11489	
11490	/** prints message about numerical trouble
11491	 *
11492	 * If message has verblevel at most high and display/verblevel is not full,
11493	 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11494	 * were printed before in the current run.
11495	 */
11496	static
11497	void lpNumericalTroubleMessage(
11498	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
11499	   SCIP_SET*             set,                /**< global SCIP settings */
11500	   SCIP_STAT*            stat,               /**< problem statistics */
11501	   SCIP_VERBLEVEL        verblevel,          /**< verbosity level of message */
11502	   const char*           formatstr,          /**< message format string */
11503	   ...                                       /**< arguments to format string */
11504	   )
11505	{
11506	   va_list ap;
11507	
11508	   assert(verblevel > SCIP_VERBLEVEL_NONE);
11509	   assert(verblevel <= SCIP_VERBLEVEL_FULL);
11510	   assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11511	
11512	   if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11513	   {
11514	      if( verblevel <= SCIP_VERBLEVEL_HIGH )
11515	      {
11516	         /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11517	         if( stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11518	            return;
11519	
11520	         /* increase count on messages with verblevel high */
11521	         ++stat->nnumtroublelpmsgs ;
11522	      }
11523	
11524	      /* if messages wouldn't be printed, then return already */
11525	      if( verblevel > set->disp_verblevel )
11526	         return;
11527	   }
11528	
11529	   /* print common begin of message */
11530	   SCIPmessagePrintInfo(messagehdlr,
11531	      "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11532	      stat->nnodes, stat->nlps);
11533	
11534	   /* print individual part of message */
11535	   va_start(ap, formatstr); /*lint !e838*/
11536	   SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11537	   va_end(ap);
11538	
11539	   /* warn that further messages will be suppressed */
11540	   if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11541	   {
11542	      SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11543	   }
11544	
11545	   /* print closing new-line */
11546	   SCIPmessagePrintInfo(messagehdlr, "\n");
11547	}
11548	
11549	static
11550	SCIP_RETCODE ignoreInstability(
11551	   SCIP_LP*              lp,                 /**< current LP data */
11552	   SCIP_SET*             set,                /**< global SCIP settings */
11553	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
11554	   SCIP_STAT*            stat,               /**< problem statistics */
11555	   SCIP_LPALGO           lpalgo,             /**< LP algorithm that should be applied */
11556	   SCIP_Bool*            success             /**< was instability successfully ignored */
11557	   )
11558	{
11559	   assert(lp != NULL);
11560	   assert(set != NULL);
11561	
11562	   SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11563	
11564	   if( *success )
11565	   {
11566	      lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11567	      if( !set->lp_checkdualfeas )
11568	         lp->dualfeasible = TRUE;
11569	      if( !set->lp_checkprimfeas )
11570	         lp->primalchecked = TRUE;
11571	   }
11572	
11573	   return SCIP_OKAY;
11574	}
11575	
11576	#define FEASTOLTIGHTFAC 0.001
11577	/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11578	static
11579	SCIP_RETCODE lpSolveStable(
11580	   SCIP_LP*              lp,                 /**< current LP data */
11581	   SCIP_SET*             set,                /**< global SCIP settings */
11582	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
11583	   SCIP_STAT*            stat,               /**< problem statistics */
11584	   SCIP_PROB*            prob,               /**< problem data */
11585	   SCIP_LPALGO           lpalgo,             /**< LP algorithm that should be applied */
11586	   int                   itlim,              /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11587	   int                   harditlim,          /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11588	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
11589	   int                   fastmip,            /**< which FASTMIP setting of LP solver should be used? */
11590	   SCIP_Bool             tightprimfeastol,   /**< should a tighter primal feasibility tolerance be used? */
11591	   SCIP_Bool             tightdualfeastol,   /**< should a tighter dual feasibility tolerance be used? */
11592	   SCIP_Bool             fromscratch,        /**< should the LP be solved from scratch without using current basis? */
11593	   int                   scaling,            /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11594	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
11595	   SCIP_Bool*            timelimit,          /**< pointer to store whether the time limit was hit */
11596	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
11597	   )
11598	{
11599	   SCIP_Bool success;
11600	   SCIP_Bool success2;
11601	   SCIP_Bool success3;
11602	   SCIP_Bool simplex;
11603	   SCIP_Bool itlimishard;
11604	   SCIP_Bool usepolishing;
11605	
11606	   assert(lp != NULL);
11607	   assert(lp->flushed);
11608	   assert(set != NULL);
11609	   assert(stat != NULL);
11610	   assert(lperror != NULL);
11611	   assert(timelimit != NULL);
11612	
11613	   *lperror = FALSE;
11614	
11615	   /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11616	    *       solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11617	    *       and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11618	    *       SCIP_LP such that we can return a primal ray
11619	    */
11620	   if( lp->looseobjvalinf > 0 )
11621	   {
11622	      SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11623	      return SCIP_ERROR;
11624	   }
11625	
11626	   /* check, whether we solve with a simplex algorithm */
11627	   simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11628	
11629	   /* check whether the iteration limit is a hard one */
11630	   itlimishard = (itlim == harditlim);
11631	
11632	   /* check whether solution polishing should be used */
11633	   if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11634	         || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11635	   {
11636	      usepolishing = TRUE;
11637	      if( lp->updateintegrality )
11638	      {
11639	         SCIP_CALL( lpCopyIntegrality(lp, set) );
11640	      }
11641	   }
11642	   else
11643	      usepolishing = FALSE;
11644	
11645	   /* solve with given settings (usually fast but imprecise) */
11646	   if( SCIPsetIsInfinity(set, lp->cutoffbound) )
11647	   {
11648	      SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11649	   }
11650	   else
11651	   {
11652	      SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11653	   }
11654	   SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11655	   SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11656	   SCIP_CALL( lpSetDualfeastol(lp, tightdualfeastol ? FEASTOLTIGHTFAC * SCIPsetDualfeastol(set) : SCIPsetDualfeastol(set),
11657	         &success) );
11658	   SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11659	         : SCIPsetBarrierconvtol(set), &success) );
11660	   SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11661	   SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11662	   SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11663	   SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11664	   SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11665	   SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11666	   SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11667	   SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11668	   SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11669	   SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11670	   SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11671	   SCIP_CALL( lpSetRandomseed(lp, (int) SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed), &success) );
11672	   SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11673	   SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11674	
11675	   SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11676	
11677	   /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11678	    * optimal without preforming scaling/change tolerances/presolving */
11679	   resolve = FALSE;
11680	
11681	   /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11682	   if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11683	      return SCIP_OKAY;
11684	
11685	   if( !set->lp_checkstability )
11686	   {
11687	      SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11688	
11689	      if( success )
11690	         return SCIP_OKAY;
11691	   }
11692	
11693	   /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11694	    * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11695	    */
11696	
11697	   /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11698	    * do this only if the iteration limit was not exceeded in the last LP solving call
11699	    */
11700	   if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11701	   {
11702	      SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11703	      if( success )
11704	      {
11705	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11706	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11707	
11708	         /* check for stability */
11709	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11710	            return SCIP_OKAY;
11711	
11712	         if( !set->lp_checkstability )
11713	         {
11714	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11715	
11716	            if( success )
11717	               return SCIP_OKAY;
11718	         }
11719	      }
11720	   }
11721	
11722	   /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11723	    * and go directly to solving the LP from scratch
11724	    */
11725	   if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11726	   {
11727	      /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11728	      SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11729	      if( success )
11730	      {
11731	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11732	            lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11733	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11734	
11735	         /* check for stability */
11736	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11737	            return SCIP_OKAY;
11738	
11739	         if( !set->lp_checkstability )
11740	         {
11741	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11742	
11743	            if( success )
11744	               return SCIP_OKAY;
11745	         }
11746	
11747	         /* reset scaling */
11748	         SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11749	         assert(success);
11750	      }
11751	   }
11752	
11753	   /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11754	    * and go directly to solving the LP from scratch */
11755	   if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11756	   {
11757	      /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11758	      SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11759	      if( success )
11760	      {
11761	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11762	            lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11763	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11764	
11765	         /* check for stability */
11766	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11767	            return SCIP_OKAY;
11768	
11769	         if( !set->lp_checkstability )
11770	         {
11771	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11772	
11773	            if( success )
11774	               return SCIP_OKAY;
11775	         }
11776	
11777	         /* reset presolving */
11778	         SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11779	         assert(success);
11780	      }
11781	   }
11782	
11783	   /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11784	    * do this only if the iteration limit was not exceeded in the last LP solving call
11785	    */
11786	   if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11787	      ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11788	   {
11789	      success = FALSE;
11790	      if( !tightprimfeastol )
11791	      {
11792	         SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11793	      }
11794	
11795	      success2 = FALSE;
11796	      if( !tightdualfeastol )
11797	      {
11798	         SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) );
11799	      }
11800	
11801	      success3 = FALSE;
11802	      if( !simplex && !tightprimfeastol && !tightdualfeastol )
11803	      {
11804	         SCIP_CALL( lpSetBarrierconvtol(lp, FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set), &success3) );
11805	      }
11806	
11807	      /* only resolve if at least one of the parameters was actually changed in the LP solver */
11808	      if( success || success2 || success3 )
11809	      {
11810	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11811	            lpalgoName(lpalgo));
11812	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11813	
11814	         /* check for stability */
11815	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11816	            return SCIP_OKAY;
11817	
11818	         if( !set->lp_checkstability )
11819	         {
11820	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11821	
11822	            if( success )
11823	               return SCIP_OKAY;
11824	         }
11825	
11826	         /* reset feasibility tolerance */
11827	         if( !tightprimfeastol )
11828	         {
11829	            SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11830	         }
11831	         if( !tightdualfeastol )
11832	         {
11833	            SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
11834	         }
11835	         if( !simplex && !tightprimfeastol && !tightdualfeastol )
11836	         {
11837	            SCIP_CALL( lpSetBarrierconvtol(lp, SCIPsetBarrierconvtol(set), &success) );
11838	         }
11839	      }
11840	   }
11841	
11842	   /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11843	    * the given iteration limit might be a soft one to restrict resolving calls only */
11844	   SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11845	
11846	   /* if not already done, solve again from scratch */
11847	   if( !fromscratch && simplex )
11848	   {
11849	      SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11850	      if( success )
11851	      {
11852	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11853	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11854	
11855	         /* check for stability */
11856	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11857	            return SCIP_OKAY;
11858	
11859	         if( !set->lp_checkstability )
11860	         {
11861	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11862	
11863	            if( success )
11864	               return SCIP_OKAY;
11865	         }
11866	      }
11867	   }
11868	
11869	   /* solve again, use other simplex this time */
11870	   if( simplex )
11871	   {
11872	      lpalgo = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX ? SCIP_LPALGO_DUALSIMPLEX : SCIP_LPALGO_PRIMALSIMPLEX);
11873	      lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11874	      SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11875	
11876	      /* check for stability */
11877	      if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11878	         return SCIP_OKAY;
11879	
11880	      if( !set->lp_checkstability )
11881	      {
11882	         SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11883	
11884	         if( success )
11885	            return SCIP_OKAY;
11886	      }
11887	
11888	      /* solve again with opposite scaling and other simplex */
11889	      SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11890	      if( success )
11891	      {
11892	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11893	            lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11894	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11895	
11896	         /* check for stability */
11897	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11898	            return SCIP_OKAY;
11899	
11900	         if( !set->lp_checkstability )
11901	         {
11902	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11903	
11904	            if( success )
11905	               return SCIP_OKAY;
11906	         }
11907	
11908	         /* reset scaling */
11909	         SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11910	         assert(success);
11911	      }
11912	
11913	      /* solve again with opposite presolving and other simplex */
11914	      SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11915	      if( success )
11916	      {
11917	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11918	            lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11919	         SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11920	
11921	         /* check for stability */
11922	         if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11923	            return SCIP_OKAY;
11924	
11925	         if( !set->lp_checkstability )
11926	         {
11927	            SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11928	
11929	            if( success )
11930	               return SCIP_OKAY;
11931	         }
11932	
11933	         /* reset presolving */
11934	         SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11935	         assert(success);
11936	      }
11937	
11938	      /* solve again with tighter feasibility tolerance, use other simplex this time */
11939	      if( !tightprimfeastol || !tightdualfeastol )
11940	      {
11941	         success = FALSE;
11942	         if( !tightprimfeastol )
11943	         {
11944	            SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11945	         }
11946	
11947	         success2 = FALSE;
11948	         if( !tightdualfeastol )
11949	         {
11950	            SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) );
11951	         }
11952	
11953	         /* only resolve if at least one of the parameters was actually changed in the LP solver */
11954	         if( success || success2 )
11955	         {
11956	            lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11957	               lpalgoName(lpalgo));
11958	            SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11959	
11960	            /* check for stability */
11961	            if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11962	               return SCIP_OKAY;
11963	
11964	            if( !set->lp_checkstability )
11965	            {
11966	               SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11967	
11968	               if( success )
11969	                  return SCIP_OKAY;
11970	            }
11971	
11972	            /* reset feasibility tolerance */
11973	            if( !tightprimfeastol )
11974	            {
11975	               SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11976	            }
11977	            if( !tightdualfeastol )
11978	            {
11979	               SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) );
11980	            }
11981	            SCIP_UNUSED(success);
11982	         }
11983	      }
11984	   }
11985	
11986	   /* nothing worked -- exit with an LPERROR */
11987	   lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11988	   *lperror = TRUE;
11989	
11990	   return SCIP_OKAY;
11991	}
11992	
11993	/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
11994	static
11995	void adjustLPobjval(
11996	   SCIP_LP*              lp,                 /**< current LP data */
11997	   SCIP_SET*             set,                /**< global SCIP settings */
11998	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
11999	   )
12000	{
12001	   assert(lp != NULL);
12002	   assert(set != NULL);
12003	
12004	   if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12005	   {
12006	      if( !lp->adjustlpval && messagehdlr != NULL )
12007	      {
12008	         SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12009	         lp->adjustlpval = TRUE;
12010	      }
12011	      lp->lpobjval = SCIPsetInfinity(set);
12012	   }
12013	   else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12014	   {
12015	      if( !lp->adjustlpval && messagehdlr != NULL )
12016	      {
12017	         SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12018	         lp->adjustlpval = TRUE;
12019	      }
12020	      lp->lpobjval = -SCIPsetInfinity(set);
12021	   }
12022	}
12023	
12024	/** solves the LP with the given algorithm and evaluates return status */
12025	static
12026	SCIP_RETCODE lpSolve(
12027	   SCIP_LP*              lp,                 /**< current LP data */
12028	   SCIP_SET*             set,                /**< global SCIP settings */
12029	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
12030	   SCIP_STAT*            stat,               /**< problem statistics */
12031	   SCIP_PROB*            prob,               /**< problem data */
12032	   SCIP_LPALGO           lpalgo,             /**< LP algorithm that should be applied */
12033	   int                   resolveitlim,       /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12034	   int                   harditlim,          /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12035	   SCIP_Bool             needprimalray,      /**< if the LP is unbounded, do we need a primal ray? */
12036	   SCIP_Bool             needdualray,        /**< if the LP is infeasible, do we need a dual ray? */
12037	   SCIP_Bool             resolve,            /**< is this a resolving call (starting with feasible basis)? */
12038	   int                   fastmip,            /**< which FASTMIP setting of LP solver should be used? */
12039	   SCIP_Bool             tightprimfeastol,   /**< should a tighter primal feasibility tolerance be used? */
12040	   SCIP_Bool             tightdualfeastol,   /**< should a tighter dual feasibility tolerance be used? */
12041	   SCIP_Bool             fromscratch,        /**< should the LP be solved from scratch without using current basis? */
12042	   int                   scaling,            /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12043	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
12044	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
12045	   )
12046	{
12047	   SCIP_Bool solvedprimal;
12048	   SCIP_Bool solveddual;
12049	   SCIP_Bool timelimit;
12050	   int itlim;
12051	
12052	   assert(lp != NULL);
12053	   assert(lp->flushed);
12054	   assert(set != NULL);
12055	   assert(stat != NULL);
12056	   assert(lperror != NULL);
12057	
12058	   checkLinks(lp);
12059	
12060	   solvedprimal = FALSE;
12061	   solveddual = FALSE;
12062	   timelimit = FALSE;
12063	
12064	   /* select the basic iteration limit depending on whether this is a resolving call or not */
12065	   itlim = ( resolve ? resolveitlim : harditlim );
12066	
12067	 SOLVEAGAIN:
12068	   /* call simplex */
12069	   SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12070	         scaling, keepsol, &timelimit, lperror) );
12071	   resolve = FALSE; /* only the first solve should be counted as resolving call */
12072	   solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12073	   solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12074	
12075	   /* check, if an error occurred */
12076	   if( *lperror )
12077	   {
12078	      SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12079	      lp->solved = FALSE;
12080	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12081	      return SCIP_OKAY;
12082	   }
12083	
12084	   /* check, if a time limit was exceeded */
12085	   if( timelimit )
12086	   {
12087	      SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12088	      lp->solved = TRUE;
12089	      lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT;
12090	      lp->lpobjval = -SCIPsetInfinity(set);
12091	      return SCIP_OKAY;
12092	   }
12093	
12094	   /* only one should return true */
12095	   assert(!(SCIPlpiIsOptimal(lp->lpi) && SCIPlpiIsObjlimExc(lp->lpi) && SCIPlpiIsPrimalInfeasible(lp->lpi) &&
12096	         SCIPlpiExistsPrimalRay(lp->lpi) && SCIPlpiIsIterlimExc(lp->lpi) && SCIPlpiIsTimelimExc(lp->lpi)));
12097	
12098	   /* evaluate solution status */
12099	   if( SCIPlpiIsOptimal(lp->lpi) )
12100	   {
12101	      assert(lp->primalfeasible);
12102	      assert(lp->dualfeasible);
12103	      lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
12104	      SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12105	      adjustLPobjval(lp, set, messagehdlr);
12106	
12107	      if( !SCIPsetIsInfinity(set, lp->lpiobjlim) && SCIPsetIsGE(set, lp->lpobjval, lp->lpiobjlim) )
12108	      {
12109	         /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12110	         SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12111	         lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12112	         lp->lpobjval = SCIPsetInfinity(set);
12113	      }
12114	      /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12115	       * reached if the LP objective value is greater than the cutoff bound
12116	       */
12117	      assert(lpCutoffDisabled(set, prob) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || SCIPsetIsInfinity(set, lp->cutoffbound)
12118	         || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12119	   }
12120	   else if( SCIPlpiIsObjlimExc(lp->lpi) )
12121	   {
12122	      assert(!lpCutoffDisabled(set, prob));
12123	
12124	#ifndef NDEBUG
12125	      /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12126	       * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12127	      SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12128	      assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12129	#endif
12130	
12131	      lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12132	      lp->lpobjval = SCIPsetInfinity(set);
12133	   }
12134	   else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12135	   {
12136	      /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12137	      if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12138	      {
12139	         assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12140	         lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12141	         goto SOLVEAGAIN;
12142	      }
12143	      lp->lpsolstat = SCIP_LPSOLSTAT_INFEASIBLE;
12144	      lp->lpobjval = SCIPsetInfinity(set);
12145	   }
12146	   else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12147	   {
12148	      /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12149	      if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12150	      {
12151	         /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12152	         assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
12153	         lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
12154	         goto SOLVEAGAIN;
12155	      }
12156	      lp->lpsolstat = SCIP_LPSOLSTAT_UNBOUNDEDRAY;
12157	      lp->lpobjval = -SCIPsetInfinity(set);
12158	   }
12159	   else if( SCIPlpiIsIterlimExc(lp->lpi) )
12160	   {
12161	      SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12162	
12163	      /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12164	         iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12165	      if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12166	         adjustLPobjval(lp, set, NULL);
12167	      else
12168	         adjustLPobjval(lp, set, messagehdlr);
12169	
12170	      lp->lpsolstat = SCIP_LPSOLSTAT_ITERLIMIT;
12171	   }
12172	   else if( SCIPlpiIsTimelimExc(lp->lpi) )
12173	   {
12174	      lp->lpobjval = -SCIPsetInfinity(set);
12175	      lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT;
12176	   }
12177	   else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12178	   {
12179	      assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12180	      lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12181	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12182	         "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12183	         stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12184	      goto SOLVEAGAIN;
12185	   }
12186	   else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12187	   {
12188	      assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX);
12189	      lpalgo = SCIP_LPALGO_PRIMALSIMPLEX;
12190	      SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12191	         "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12192	         stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12193	      goto SOLVEAGAIN;
12194	   }
12195	   else
12196	   {
12197	      SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12198	         stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12199	      lp->lpsolstat = SCIP_LPSOLSTAT_ERROR;
12200	      return SCIP_LPERROR;
12201	   }
12202	
12203	   lp->solved = TRUE;
12204	
12205	   SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12206	      lpalgoName(lp->lastlpalgo), lp->lpsolstat, SCIPlpiGetInternalStatus(lp->lpi),
12207	      SCIPlpiIsPrimalFeasible(lp->lpi), SCIPlpiIsDualFeasible(lp->lpi));
12208	
12209	   return SCIP_OKAY;
12210	}
12211	
12212	/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12213	static
12214	SCIP_RETCODE lpFlushAndSolve(
12215	   SCIP_LP*              lp,                 /**< current LP data */
12216	   BMS_BLKMEM*           blkmem,             /**< block memory */
12217	   SCIP_SET*             set,                /**< global SCIP settings */
12218	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
12219	   SCIP_STAT*            stat,               /**< problem statistics */
12220	   SCIP_PROB*            prob,               /**< problem data */
12221	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
12222	   int                   resolveitlim,       /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12223	   int                   harditlim,          /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12224	   SCIP_Bool             needprimalray,      /**< if the LP is unbounded, do we need a primal ray? */
12225	   SCIP_Bool             needdualray,        /**< if the LP is infeasible, do we need a dual ray? */
12226	   int                   fastmip,            /**< which FASTMIP setting of LP solver should be used? */
12227	   SCIP_Bool             tightprimfeastol,   /**< should a tighter primal feasibility tolerance be used? */
12228	   SCIP_Bool             tightdualfeastol,   /**< should a tighter dual feasibility tolerance be used? */
12229	   SCIP_Bool             fromscratch,        /**< should the LP be solved from scratch without using current basis? */
12230	   int                   scaling,            /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12231	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
12232	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
12233	   )
12234	{
12235	   SCIP_Bool resolve;
12236	   char algo;
12237	
12238	   assert(lp != NULL);
12239	   assert(set != NULL);
12240	   assert(lperror != NULL);
12241	
12242	   /* flush changes to the LP solver */
12243	   SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12244	   fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12245	
12246	   /* select LP algorithm to apply */
12247	   resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12248	   algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12249	
12250	   switch( algo )
12251	   {
12252	   case 's':
12253	      /* select simplex method */
12254	      if( lp->dualfeasible || !lp->primalfeasible )
12255	      {
12256	         SCIPsetDebugMsg(set, "solving dual LP\n");
12257	         SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12258	               needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12259	      }
12260	      else
12261	      {
12262	         SCIPsetDebugMsg(set, "solving primal LP\n");
12263	         SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12264	               needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12265	      }
12266	      break;
12267	
12268	   case 'p':
12269	      SCIPsetDebugMsg(set, "solving primal LP\n");
12270	      SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12271	            needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12272	      break;
12273	
12274	   case 'd':
12275	      SCIPsetDebugMsg(set, "solving dual LP\n");
12276	      SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12277	            needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12278	      break;
12279	
12280	   case 'b':
12281	      SCIPsetDebugMsg(set, "solving barrier LP\n");
12282	      SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12283	            needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12284	      break;
12285	
12286	   case 'c':
12287	      SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12288	      SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12289	            needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12290	      break;
12291	
12292	   default:
12293	      SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12294	      return SCIP_PARAMETERWRONGVAL;
12295	   }
12296	   assert(!(*lperror) || !lp->solved);
12297	
12298	   return SCIP_OKAY;
12299	}
12300	
12301	#ifndef NDEBUG
12302	/** checks if the lazy bounds are valid */
12303	static
12304	void checkLazyBounds(
12305	   SCIP_LP*              lp,                 /**< LP data */
12306	   SCIP_SET*             set                 /**< global SCIP settings */
12307	   )
12308	{
12309	   SCIP_COL* col;
12310	   int c;
12311	
12312	   assert(lp->flushed);
12313	
12314	   for( c = 0; c < lp->nlazycols; ++c )
12315	   {
12316	      col = lp->lazycols[c];
12317	
12318	      /* in case lazy bounds are given, check that the primal solution satisfies them */
12319	      assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12320	      assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12321	   }
12322	}
12323	#else
12324	#define checkLazyBounds(lp, set) /**/
12325	#endif
12326	
12327	/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12328	 *  diving
12329	 */
12330	static
12331	SCIP_RETCODE updateLazyBounds(
12332	   SCIP_LP*              lp,                 /**< LP data */
12333	   SCIP_SET*             set                 /**< global SCIP settings */
12334	   )
12335	{
12336	   SCIP_COL* col;
12337	   int c;
12338	
12339	   assert(lp->nlazycols > 0);
12340	
12341	   /* return, if we are in diving, and bounds were already applied
12342	    * or if we are not in diving and bounds were not applied
12343	    */
12344	   if( lp->diving == lp->divinglazyapplied )
12345	      return SCIP_OKAY;
12346	
12347	   SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12348	      lp->diving, lp->divinglazyapplied);
12349	
12350	   for( c = 0; c < lp->nlazycols; ++c )
12351	   {
12352	      col = lp->lazycols[c];
12353	
12354	      /* if the column has a lazy lower bound, mark its lower bounds as changed */
12355	      if( !SCIPsetIsInfinity(set, -col->lazylb) )
12356	      {
12357	         assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12358	         assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12359	            || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12360	
12361	         /* insert column in the chgcols list (if not already there) */
12362	         SCIP_CALL( insertColChgcols(col, set, lp) );
12363	
12364	         /* mark bound change in the column */
12365	         col->lbchanged = TRUE;
12366	      }
12367	
12368	      /* if the column has a lazy upper bound, mark its upper bounds as changed */
12369	      if( !SCIPsetIsInfinity(set, col->lazyub) )
12370	      {
12371	         assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12372	         assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12373	            || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12374	
12375	         /* insert column in the chgcols list (if not already there) */
12376	         SCIP_CALL( insertColChgcols(col, set, lp) );
12377	
12378	         /* mark bound change in the column */
12379	         col->ubchanged = TRUE;
12380	      }
12381	   }
12382	
12383	   /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12384	    * if not, we just removed them
12385	    */
12386	   lp->divinglazyapplied = lp->diving;
12387	
12388	   return SCIP_OKAY;
12389	}
12390	
12391	/** returns the iteration limit for an LP resolving call */
12392	static
12393	int lpGetResolveItlim(
12394	   SCIP_SET*             set,                /**< global SCIP settings */
12395	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
12396	   int                   itlim               /**< hard iteration limit */
12397	   )
12398	{
12399	   /* no limit set or average not yet reliable */
12400	   if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12401	      return itlim;
12402	   /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12403	   if( itlim == -1 )
12404	      itlim = INT_MAX;
12405	   /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12406	   return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12407	         (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12408	}
12409	
12410	
12411	
12412	/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12413	SCIP_RETCODE SCIPlpSolveAndEval(
12414	   SCIP_LP*              lp,                 /**< LP data */
12415	   SCIP_SET*             set,                /**< global SCIP settings */
12416	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
12417	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
12418	   SCIP_STAT*            stat,               /**< problem statistics */
12419	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
12420	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
12421	   SCIP_PROB*            prob,               /**< problem data */
12422	   SCIP_Longint          itlim,              /**< maximal number of LP iterations to perform, or -1 for no limit */
12423	   SCIP_Bool             limitresolveiters,  /**< should LP iterations for resolving calls be limited?
12424	                                              *   (limit is computed within the method w.r.t. the average LP iterations) */
12425	   SCIP_Bool             aging,              /**< should aging and removal of obsolete cols/rows be applied? */
12426	   SCIP_Bool             keepsol,            /**< should the old LP solution be kept if no iterations were performed? */
12427	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred */
12428	   )
12429	{
12430	   SCIP_RETCODE retcode;
12431	   SCIP_Bool needprimalray;
12432	   SCIP_Bool needdualray;
12433	   int harditlim;
12434	   int resolveitlim;
12435	
12436	   assert(lp != NULL);
12437	   assert(prob != NULL);
12438	   assert(prob->nvars >= lp->ncols);
12439	   assert(lperror != NULL);
12440	
12441	   retcode = SCIP_OKAY;
12442	   *lperror = FALSE;
12443	
12444	   if( lp->flushed && lp->solved )
12445	   {
12446	      SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12447	      return SCIP_OKAY;
12448	   }
12449	
12450	   SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12451	      lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12452	
12453	   /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12454	   needprimalray = TRUE;
12455	   needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12456	      || (set->conf_enable && set->conf_useinflp != 'o'));
12457	
12458	   /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12459	   harditlim = (int) MIN(itlim, INT_MAX);
12460	   resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12461	   assert(harditlim == -1 || (resolveitlim <= harditlim));
12462	
12463	   /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12464	    * or removed from the LP (diving was ended)
12465	    */
12466	   if( lp->nlazycols > 0 )
12467	   {
12468	      /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12469	       * first resolve LP?
12470	       */
12471	      SCIP_CALL( updateLazyBounds(lp, set) );
12472	      assert(lp->diving == lp->divinglazyapplied);
12473	   }
12474	
12475	   /* flush changes to the LP solver */
12476	   SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12477	   assert(lp->flushed);
12478	
12479	   /* if the time limit was reached in the last call and the LP did not change, lp->solved is set to TRUE, but we want
12480	    * to run again anyway, since there seems to be some time left / the time limit was increased
12481	    */
12482	   if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12483	   {
12484	      SCIP_Bool* primalfeaspointer;
12485	      SCIP_Bool* dualfeaspointer;
12486	      SCIP_Bool primalfeasible;
12487	      SCIP_Bool dualfeasible;
12488	      SCIP_Bool farkasvalid;
12489	      SCIP_Bool rayfeasible;
12490	      SCIP_Bool tightprimfeastol;
12491	      SCIP_Bool tightdualfeastol;
12492	      SCIP_Bool fromscratch;
12493	      SCIP_Bool wasfromscratch;
12494	      int scaling;
12495	      SCIP_Longint oldnlps;
12496	      int fastmip;
12497	
12498	      /* set initial LP solver settings */
12499	      fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12500	      tightprimfeastol = FALSE;
12501	      tightdualfeastol = FALSE;
12502	      fromscratch = FALSE;
12503	      primalfeasible = FALSE;
12504	      dualfeasible = FALSE;
12505	      wasfromscratch = (stat->nlps == 0);
12506	      scaling = set->lp_scaling;
12507	
12508	   SOLVEAGAIN:
12509	      /* solve the LP */
12510	      oldnlps = stat->nlps;
12511	      SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12512	            needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12513	      SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12514	      assert(!(*lperror) || !lp->solved);
12515	
12516	      /* check for error */
12517	      if( *lperror )
12518	      {
12519	         retcode = SCIP_OKAY;
12520	         goto TERMINATE;
12521	      }
12522	
12523	      /* evaluate solution status */
12524	      switch( SCIPlpGetSolstat(lp) )
12525	      {
12526	      case SCIP_LPSOLSTAT_OPTIMAL:
12527	         /* get LP solution and possibly check the solution's feasibility again */
12528	         if( set->lp_checkprimfeas )
12529	         {
12530	            primalfeaspointer = &primalfeasible;
12531	            lp->primalchecked = TRUE;
12532	         }
12533	         else
12534	         {
12535	            /* believe in the primal feasibility of the LP solution */
12536	            primalfeasible = TRUE;
12537	            primalfeaspointer = NULL;
12538	            lp->primalchecked = FALSE;
12539	         }
12540	         if( set->lp_checkdualfeas )
12541	         {
12542	            dualfeaspointer = &dualfeasible;
12543	            lp->dualchecked = TRUE;
12544	         }
12545	         else
12546	         {
12547	            /* believe in the dual feasibility of the LP solution */
12548	            dualfeasible = TRUE;
12549	            dualfeaspointer = NULL;
12550	            lp->dualchecked = FALSE;
12551	         }
12552	
12553	         SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12554	
12555	         /* in debug mode, check that lazy bounds (if present) are not violated */
12556	         checkLazyBounds(lp, set);
12557	
12558	         if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12559	         {
12560	            /* update ages and remove obsolete columns and rows from LP */
12561	            SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12562	            if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12563	            {
12564	               SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12565	            }
12566	
12567	            if( !lp->solved )
12568	            {
12569	               /* resolve LP after removing obsolete columns and rows */
12570	               SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12571	               aging = FALSE; /* to prevent infinite loops */
12572	               goto SOLVEAGAIN;
12573	            }
12574	         }
12575	         if( !primalfeasible || !dualfeasible )
12576	         {
12577	            SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12578	
12579	            if( (fastmip > 0) && simplex )
12580	            {
12581	               /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12582	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12583	                  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12584	                  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12585	               fastmip = 0;
12586	               goto SOLVEAGAIN;
12587	            }
12588	            else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12589	            {
12590	               /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12591	                * tolerance
12592	                */
12593	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12594	                  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12595	                  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12596	               tightprimfeastol = tightprimfeastol || !primalfeasible;
12597	               tightdualfeastol = tightdualfeastol || !dualfeasible;
12598	               goto SOLVEAGAIN;
12599	            }
12600	            else if( !fromscratch && !wasfromscratch && simplex )
12601	            {
12602	               /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12603	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12604	                  "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12605	                  stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12606	               fromscratch = TRUE;
12607	               goto SOLVEAGAIN;
12608	            }
12609	            else
12610	            {
12611	               lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12612	               lp->solved = FALSE;
12613	               lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12614	               *lperror = TRUE;
12615	            }
12616	         }
12617	         SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12618	            lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12619	            lp->lpsolstat, lp->cutoffbound);
12620	         break;
12621	
12622	      case SCIP_LPSOLSTAT_INFEASIBLE:
12623	         SCIPsetDebugMsg(set, " -> LP infeasible\n");
12624	         if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve || set->lp_alwaysgetduals )
12625	         {
12626	            if( SCIPlpiHasDualRay(lp->lpi) )
12627	            {
12628	               SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12629	            }
12630	            /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12631	             * with the primal simplex due to numerical problems) - treat this case like an LP error
12632	             */
12633	            else
12634	            {
12635	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12636	                  "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12637	               lp->solved = FALSE;
12638	               lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12639	               farkasvalid = FALSE;
12640	               *lperror = TRUE;
12641	            }
12642	         }
12643	         else
12644	            farkasvalid = TRUE;
12645	
12646	         /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12647	         if( !farkasvalid && !(*lperror) )
12648	         {
12649	            SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12650	
12651	            if( (fastmip > 0) && simplex )
12652	            {
12653	               /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12654	                * without FASTMIP
12655	                */
12656	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12657	                  "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12658	                  stat->nnodes, stat->nlps);
12659	               fastmip = 0;
12660	               goto SOLVEAGAIN;
12661	            }
12662	            else if( !tightdualfeastol )
12663	            {
12664	               /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12665	                * solve again with tighter feasibility tolerance
12666	                */
12667	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12668	                  "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12669	                  stat->nnodes, stat->nlps);
12670	               tightdualfeastol = TRUE;
12671	               goto SOLVEAGAIN;
12672	            }
12673	            else if( !fromscratch && simplex )
12674	            {
12675	               /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12676	                * from scratch
12677	                */
12678	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12679	                  "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12680	                  stat->nnodes, stat->nlps);
12681	               fromscratch = TRUE;
12682	               goto SOLVEAGAIN;
12683	            }
12684	            else
12685	            {
12686	               /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12687	                * helped forget about the LP at this node and mark it to be unsolved
12688	                */
12689	               lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12690	               lp->solved = FALSE;
12691	               lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12692	               *lperror = TRUE;
12693	            }
12694	         }
12695	
12696	         break;
12697	
12698	      case SCIP_LPSOLSTAT_UNBOUNDEDRAY:
12699	         if( set->lp_checkprimfeas )
12700	         {
12701	            /* get unbounded LP solution and check the solution's feasibility again */
12702	            SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12703	
12704	            lp->primalchecked = TRUE;
12705	         }
12706	         else
12707	         {
12708	            /* get unbounded LP solution believing in the feasibility of the LP solution */
12709	            SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
12710	
12711	            primalfeasible = TRUE;
12712	            rayfeasible = TRUE;
12713	            lp->primalchecked = FALSE;
12714	         }
12715	
12716	         /* in debug mode, check that lazy bounds (if present) are not violated */
12717	         checkLazyBounds(lp, set);
12718	
12719	         SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12720	            primalfeasible, rayfeasible);
12721	
12722	         if( !primalfeasible || !rayfeasible )
12723	         {
12724	            SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12725	
12726	            if( (fastmip > 0) && simplex )
12727	            {
12728	               /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12729	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12730	                  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12731	                  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12732	               fastmip = 0;
12733	               goto SOLVEAGAIN;
12734	            }
12735	            else if( !tightprimfeastol )
12736	            {
12737	               /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12738	                * tolerance
12739	                */
12740	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12741	                  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again with tighter primal feasibility tolerance\n",
12742	                  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12743	               tightprimfeastol = TRUE;
12744	               goto SOLVEAGAIN;
12745	            }
12746	            else if( !fromscratch && simplex )
12747	            {
12748	               /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12749	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12750	                  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12751	                  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12752	               fromscratch = TRUE;
12753	               goto SOLVEAGAIN;
12754	            }
12755	            else if( scaling > 0 )
12756	            {
12757	               /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12758	               SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12759	                  "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12760	                  stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12761	               scaling = 0;
12762	               goto SOLVEAGAIN;
12763	            }
12764	            else
12765	            {
12766	               /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12767	                * forget about the LP at this node and mark it to be unsolved
12768	                */
12769	               lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12770	               lp->solved = FALSE;
12771	               lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12772	               *lperror = TRUE;
12773	            }
12774	         }
12775	
12776	         break;
12777	
12778	      case SCIP_LPSOLSTAT_OBJLIMIT:
12779	         assert(!lpCutoffDisabled(set, prob));
12780	         /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12781	          * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12782	          * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12783	          * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12784	          * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12785	          * FASTMIP and solve again. */
12786	         if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
12787	         {
12788	            SCIP_LPI* lpi;
12789	            SCIP_Real objval;
12790	
12791	            lpi = SCIPlpGetLPI(lp);
12792	
12793	            assert(lpi != NULL);
12794	            /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12795	             * the assert by using !SCIPsetIsFeasNegative()
12796	             */
12797	            assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim));
12798	
12799	            SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12800	
12801	            /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12802	            if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12803	            {
12804	               SCIP_Real tmpcutoff;
12805	               char tmppricingchar;
12806	               SCIP_LPSOLSTAT solstat;
12807	
12808	               SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12809	
12810	               /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12811	               fromscratch = FALSE;
12812	
12813	               /* temporarily disable cutoffbound, which also disables the objective limit */
12814	               tmpcutoff = lp->cutoffbound;
12815	               lp->cutoffbound = SCIPlpiInfinity(lpi);
12816	
12817	               /* set lp pricing strategy to steepest edge */
12818	               SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12819	               SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12820	
12821	               /* resolve LP with an iteration limit of 1 */
12822	               SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12823	                     FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12824	
12825	               /* reinstall old cutoff bound and lp pricing strategy */
12826	               lp->cutoffbound = tmpcutoff;
12827	               SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12828	
12829	               /* get objective value */
12830	               SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12831	
12832	               /* get solution status for the lp */
12833	               solstat = SCIPlpGetSolstat(lp);
12834	               assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12835	
12836	               SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12837	
12838	               /* the solution is still not exceeding the objective limit and the solving process
12839	                * was stopped due to time or iteration limit, solve again with fastmip turned off
12840	                */
12841	               if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12842	                  SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12843	               {
12844	                  SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12845	                  if( !(lperror) && (fastmip > 0) && simplex )
12846	                  {
12847	                     fastmip = 0;
12848	                     SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12849	                           FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12850	
12851	                     /* get objective value */
12852	                     SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12853	
12854	                     /* get solution status for the lp */
12855	                     solstat = SCIPlpGetSolstat(lp);
12856	
12857	                     SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12858	                  }
12859	               }/*lint !e438*/
12860	
12861	               /* check for lp errors */
12862	               if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12863	               {
12864	                  SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12865	                  lp->solved = FALSE;
12866	                  lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12867	
12868	                  retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12869	                  goto TERMINATE;
12870	               }
12871	
12872	               lp->solved = TRUE;
12873	
12874	               /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12875	               if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12876	                  || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12877	                     && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12878	               {
12879	                  /* get LP solution and possibly check the solution's feasibility again */
12880	                  if( set->lp_checkprimfeas )
12881	                  {
12882	                     primalfeaspointer = &primalfeasible;
12883	                     lp->primalchecked = TRUE;
12884	                  }
12885	                  else
12886	                  {
12887	                     /* believe in the primal feasibility of the LP solution */
12888	                     primalfeasible = TRUE;
12889	                     primalfeaspointer = NULL;
12890	                     lp->primalchecked = FALSE;
12891	                  }
12892	                  if( set->lp_checkdualfeas )
12893	                  {
12894	                     dualfeaspointer = &dualfeasible;
12895	                     lp->dualchecked = TRUE;
12896	                  }
12897	                  else
12898	                  {
12899	                     /* believe in the dual feasibility of the LP solution */
12900	                     dualfeasible = TRUE;
12901	                     dualfeaspointer = NULL;
12902	                     lp->dualchecked = FALSE;
12903	                  }
12904	
12905	                  SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12906	
12907	                  /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12908	                  if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12909	                  {
12910	                     checkLazyBounds(lp, set);
12911	                  }
12912	
12913	                  /* if objective value is larger than the cutoff bound, set solution status to objective
12914	                   * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12915	                   * this was already done in the lpSolve() method
12916	                   */
12917	                  if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12918	                  {
12919	                     lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT;
12920	                     lp->lpobjval = SCIPsetInfinity(set);
12921	                  }
12922	
12923	                  /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12924	                   * the cutoffbound; mark the LP to be unsolved
12925	                   */
12926	                  if( !primalfeasible || !dualfeasible
12927	                     || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12928	                        !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
12929	                  {
12930	                     lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12931	                     lp->solved = FALSE;
12932	                     lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12933	                     *lperror = TRUE;
12934	                  }
12935	
12936	                  SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12937	                     lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12938	                     lp->lpsolstat, lp->cutoffbound);
12939	               }
12940	               /* infeasible solution */
12941	               else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12942	               {
12943	                  SCIPsetDebugMsg(set, " -> LP infeasible\n");
12944	
12945	                  if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve )
12946	                  {
12947	                     if( SCIPlpiHasDualRay(lp->lpi) )
12948	                     {
12949	                        SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12950	                     }
12951	                     /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12952	                      * with the primal simplex due to numerical problems) - treat this case like an LP error
12953	                      */
12954	                     else
12955	                     {
12956	                        SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12957	                           "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12958	                        lp->solved = FALSE;
12959	                        lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
12960	                        farkasvalid = FALSE;
12961	                        *lperror = TRUE;
12962	                     }
12963	                  }
12964	                  else
12965	                     farkasvalid = TRUE;
12966	
12967	                  if( !farkasvalid )
12968	                  {
12969	                     SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12970	
12971	                     if( !tightprimfeastol )
12972	                     {
12973	                        /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12974	                         * solve again with tighter feasibility tolerance
12975	                         */
12976	                        SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12977	                              "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12978	                              stat->nnodes, stat->nlps);
12979	                        tightprimfeastol = TRUE;
12980	                        goto SOLVEAGAIN;
12981	                     }
12982	                     else if( simplex )
12983	                     {
12984	                        /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12985	                         * from scratch
12986	                         */
12987	                        SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12988	                              "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12989	                              stat->nnodes, stat->nlps);
12990	                        fromscratch = TRUE;
12991	                        goto SOLVEAGAIN;
12992	                     }
12993	                     else
12994	                     {
12995	                        /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12996	                         * helped forget about the LP at this node and mark it to be unsolved
12997	                         */
12998	                        lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12999	                        lp->solved = FALSE;
13000	                        lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
13001	                        *lperror = TRUE;
13002	                     }
13003	                  }
13004	               }
13005	               /* unbounded solution */
13006	               else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13007	               {
13008	                  if( set->lp_checkprimfeas )
13009	                  {
13010	                     /* get unbounded LP solution and check the solution's feasibility again */
13011	                     SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13012	
13013	                     lp->primalchecked = TRUE;
13014	                  }
13015	                  else
13016	                  {
13017	                     /* get unbounded LP solution believing in its feasibility */
13018	                     SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
13019	
13020	                     primalfeasible = TRUE;
13021	                     rayfeasible = TRUE;
13022	                     lp->primalchecked = FALSE;
13023	                  }
13024	
13025	                  SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13026	
13027	                  /* in debug mode, check that lazy bounds (if present) are not violated */
13028	                  checkLazyBounds(lp, set);
13029	
13030	                  if( !primalfeasible || !rayfeasible )
13031	                  {
13032	                     /* unbounded solution is infeasible (this can happen due to numerical problems):
13033	                      * forget about the LP at this node and mark it to be unsolved
13034	                      *
13035	                      * @todo: like in the default LP solving evaluation, solve without fastmip,
13036	                      * with tighter feasibility tolerance and from scratch
13037	                      */
13038	                     lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13039	                     lp->solved = FALSE;
13040	                     lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
13041	                     *lperror = TRUE;
13042	                  }
13043	               }
13044	
13045	               assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
13046	               assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
13047	                  || lp->lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT);
13048	            }
13049	            else
13050	            {
13051	               SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13052	            }
13053	         }
13054	         SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13055	         break;
13056	
13057	      case SCIP_LPSOLSTAT_ITERLIMIT:
13058	         SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13059	         break;
13060	
13061	      case SCIP_LPSOLSTAT_TIMELIMIT:
13062	         SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13063	
13064	         /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13065	         stat->nclockskipsleft = 0;
13066	         if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13067	         {
13068	            SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13069	               "you might consider switching the clock type of SCIP\n");
13070	            stat->status = SCIP_STATUS_TIMELIMIT;
13071	         }
13072	         break;
13073	
13074	      case SCIP_LPSOLSTAT_ERROR:
13075	      case SCIP_LPSOLSTAT_NOTSOLVED:
13076	         SCIPerrorMessage("error in LP solver\n");
13077	         retcode = SCIP_LPERROR;
13078	         goto TERMINATE;
13079	
13080	      default:
13081	         SCIPerrorMessage("unknown LP solution status\n");
13082	         retcode = SCIP_ERROR;
13083	         goto TERMINATE;
13084	      }
13085	   }
13086	   assert(!(*lperror) || !lp->solved);
13087	
13088	 TERMINATE:
13089	   /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13090	    * may happen that we continue to solve from scratch during strong branching */
13091	   if( lp->lpifromscratch )
13092	   {
13093	      SCIP_Bool success;
13094	      (void) lpSetFromscratch(lp, FALSE, &success);
13095	      SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13096	      SCIP_UNUSED(success);
13097	   }
13098	
13099	   return retcode;
13100	}
13101	
13102	/** gets solution status of current LP */
13103	SCIP_LPSOLSTAT SCIPlpGetSolstat(
13104	   SCIP_LP*              lp                  /**< current LP data */
13105	   )
13106	{
13107	   assert(lp != NULL);
13108	   assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
13109	
13110	   return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13111	}
13112	
13113	/** gets objective value of current LP
13114	 *
13115	 *  @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13116	 *        if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13117	 *        SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13118	 */
13119	SCIP_Real SCIPlpGetObjval(
13120	   SCIP_LP*              lp,                 /**< current LP data */
13121	   SCIP_SET*             set,                /**< global SCIP settings */
13122	   SCIP_PROB*            prob                /**< problem data */
13123	   )
13124	{
13125	   assert(lp != NULL);
13126	   assert(lp->solved);
13127	   assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13128	   assert(set != NULL);
13129	
13130	   if( !lp->flushed )
13131	      return SCIP_INVALID;
13132	   else if( SCIPsetIsInfinity(set, lp->lpobjval) || SCIPsetIsInfinity(set, -lp->lpobjval))
13133	      return lp->lpobjval;
13134	   else if( lp->looseobjvalinf > 0 )
13135	      return -SCIPsetInfinity(set);
13136	   else
13137	   {
13138	      /* recalculate the loose objective value, if needed */
13139	      if( !lp->looseobjvalid )
13140	         recomputeLooseObjectiveValue(lp, set, prob);
13141	
13142	      return lp->lpobjval + lp->looseobjval;
13143	   }
13144	}
13145	
13146	/** gets part of objective value of current LP that results from COLUMN variables only */
13147	SCIP_Real SCIPlpGetColumnObjval(
13148	   SCIP_LP*              lp                  /**< current LP data */
13149	   )
13150	{
13151	   assert(lp != NULL);
13152	   assert(lp->solved);
13153	
13154	   return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13155	}
13156	
13157	/** gets part of objective value of current LP that results from LOOSE variables only */
13158	SCIP_Real SCIPlpGetLooseObjval(
13159	   SCIP_LP*              lp,                 /**< current LP data */
13160	   SCIP_SET*             set,                /**< global SCIP settings */
13161	   SCIP_PROB*            prob                /**< problem data */
13162	   )
13163	{
13164	   assert(lp != NULL);
13165	   assert(lp->solved);
13166	   assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13167	   assert(set != NULL);
13168	
13169	   if( !lp->flushed )
13170	      return SCIP_INVALID;
13171	   else if( lp->looseobjvalinf > 0 )
13172	      return -SCIPsetInfinity(set);
13173	   else
13174	      return getFiniteLooseObjval(lp, set, prob);
13175	}
13176	
13177	/** remembers the current LP objective value as root solution value */
13178	void SCIPlpStoreRootObjval(
13179	   SCIP_LP*              lp,                 /**< current LP data */
13180	   SCIP_SET*             set,                /**< global SCIP settings */
13181	   SCIP_PROB*            prob                /**< problem data */
13182	   )
13183	{
13184	   assert(lp != NULL);
13185	
13186	   lp->rootlpobjval = SCIPlpGetColumnObjval(lp);
13187	   lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13188	}
13189	
13190	/** invalidates the root LP solution value */
13191	void SCIPlpInvalidateRootObjval(
13192	   SCIP_LP*              lp                  /**< current LP data */
13193	   )
13194	{
13195	   assert(lp != NULL);
13196	
13197	   lp->rootlpobjval = SCIP_INVALID;
13198	   lp->rootlooseobjval = SCIP_INVALID;
13199	}
13200	
13201	/** recomputes local and global pseudo objective values */
13202	void SCIPlpRecomputeLocalAndGlobalPseudoObjval(
13203	   SCIP_LP*              lp,                 /**< current LP data */
13204	   SCIP_SET*             set,                /**< global SCIP settings */
13205	   SCIP_PROB*            prob                /**< problem data */
13206	   )
13207	{
13208	   SCIP_VAR** vars;
13209	   int nvars;
13210	   int v;
13211	
13212	   assert(lp != NULL);
13213	   assert(set != NULL);
13214	   assert(prob != NULL);
13215	
13216	   vars = prob->vars;
13217	   nvars = prob->nvars;
13218	
13219	   lp->glbpseudoobjvalinf = 0;
13220	   lp->glbpseudoobjval = 0.0;
13221	
13222	   lp->pseudoobjvalinf = 0;
13223	   lp->pseudoobjval = 0.0;
13224	
13225	   for( v = 0; v < nvars; ++v )
13226	   {
13227	      SCIP_Real obj = SCIPvarGetObj(vars[v]);
13228	
13229	      if( SCIPsetIsPositive(set, obj) )
13230	      {
13231	         /* update the global pseudo objective value */
13232	         if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
13233	            ++(lp->glbpseudoobjvalinf);
13234	         else
13235	            lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
13236	
13237	         /* update the local pseudo objective value */
13238	         if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
13239	            ++(lp->pseudoobjvalinf);
13240	         else
13241	            lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
13242	      }
13243	
13244	      if( SCIPsetIsNegative(set, obj) )
13245	      {
13246	         /* update the global pseudo objective value */
13247	         if( SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) )
13248	            ++(lp->glbpseudoobjvalinf);
13249	         else
13250	            lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
13251	
13252	         /* update the local pseudo objective value */
13253	         if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
13254	            ++(lp->pseudoobjvalinf);
13255	         else
13256	            lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
13257	      }
13258	   }
13259	
13260	   /* the recomputed values are reliable */
13261	   lp->relglbpseudoobjval = lp->glbpseudoobjval;
13262	   lp->glbpseudoobjvalid = TRUE;
13263	   lp->relpseudoobjval = lp->pseudoobjval;
13264	   lp->pseudoobjvalid = TRUE;
13265	}
13266	
13267	/** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13268	 *  global bound
13269	 */
13270	SCIP_Real SCIPlpGetGlobalPseudoObjval(
13271	   SCIP_LP*              lp,                 /**< current LP data */
13272	   SCIP_SET*             set,                /**< global SCIP settings */
13273	   SCIP_PROB*            prob                /**< problem data */
13274	   )
13275	{
13276	   assert(lp != NULL);
13277	   assert(lp->glbpseudoobjvalinf >= 0);
13278	   assert(set != NULL);
13279	
13280	   if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13281	      return -SCIPsetInfinity(set);
13282	   else
13283	   {
13284	      /* recalculate the global pseudo solution value, if needed */
13285	      if( !lp->glbpseudoobjvalid )
13286	         recomputeGlbPseudoObjectiveValue(lp, set, prob);
13287	
13288	      /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13289	      if( SCIPsetIsInfinity(set, -lp->glbpseudoobjval) )
13290	         return -SCIPsetInfinity(set);
13291	
13292	      if( SCIPsetIsInfinity(set, lp->glbpseudoobjval) )
13293	         return SCIPsetInfinity(set);
13294	
13295	      return lp->glbpseudoobjval;
13296	   }
13297	}
13298	
13299	/** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13300	 *  objective function) local bound
13301	 */
13302	SCIP_Real SCIPlpGetPseudoObjval(
13303	   SCIP_LP*              lp,                 /**< current LP data */
13304	   SCIP_SET*             set,                /**< global SCIP settings */
13305	   SCIP_PROB*            prob                /**< problem data */
13306	   )
13307	{
13308	   assert(lp != NULL);
13309	   assert(lp->pseudoobjvalinf >= 0);
13310	   assert(set != NULL);
13311	
13312	   if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13313	      return -SCIPsetInfinity(set);
13314	   else
13315	   {
13316	      /* recalculate the pseudo solution value, if needed */
13317	      if( !lp->pseudoobjvalid )
13318	         recomputePseudoObjectiveValue(lp, set, prob);
13319	
13320	      /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13321	      if( SCIPsetIsInfinity(set, -lp->pseudoobjval) )
13322	         return -SCIPsetInfinity(set);
13323	
13324	      if( SCIPsetIsInfinity(set, lp->pseudoobjval) )
13325	         return SCIPsetInfinity(set);
13326	
13327	      return lp->pseudoobjval;
13328	   }
13329	}
13330	
13331	/** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13332	SCIP_Real SCIPlpGetModifiedPseudoObjval(
13333	   SCIP_LP*              lp,                 /**< current LP data */
13334	   SCIP_SET*             set,                /**< global SCIP settings */
13335	   SCIP_PROB*            prob,               /**< problem data */
13336	   SCIP_VAR*             var,                /**< problem variable */
13337	   SCIP_Real             oldbound,           /**< old value for bound */
13338	   SCIP_Real             newbound,           /**< new value for bound */
13339	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
13340	   )
13341	{
13342	   SCIP_Real pseudoobjval;
13343	   int pseudoobjvalinf;
13344	   SCIP_Real obj;
13345	
13346	   pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13347	   pseudoobjvalinf = lp->pseudoobjvalinf;
13348	   obj = SCIPvarGetObj(var);
13349	   if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13350	   {
13351	      if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13352	         pseudoobjvalinf--;
13353	      else
13354	         pseudoobjval -= oldbound * obj;
13355	      assert(pseudoobjvalinf >= 0);
13356	      if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13357	         pseudoobjvalinf++;
13358	      else
13359	         pseudoobjval += newbound * obj;
13360	   }
13361	   assert(pseudoobjvalinf >= 0);
13362	
13363	   if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13364	      return -SCIPsetInfinity(set);
13365	   else
13366	      return pseudoobjval;
13367	}
13368	
13369	/** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13370	 *  perform calculations with interval arithmetic to get an exact lower bound
13371	 */
13372	SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(
13373	   SCIP_LP*              lp,                 /**< current LP data */
13374	   SCIP_SET*             set,                /**< global SCIP settings */
13375	   SCIP_VAR*             var,                /**< problem variable */
13376	   SCIP_Real             oldbound,           /**< old value for bound */
13377	   SCIP_Real             newbound,           /**< new value for bound */
13378	   SCIP_BOUNDTYPE        boundtype           /**< type of bound: lower or upper bound */
13379	   )
13380	{
13381	   SCIP_Real pseudoobjval;
13382	   int pseudoobjvalinf;
13383	   SCIP_Real obj;
13384	
13385	   assert(lp->pseudoobjvalid);
13386	
13387	   pseudoobjval = lp->pseudoobjval;
13388	   pseudoobjvalinf = lp->pseudoobjvalinf;
13389	   obj = SCIPvarGetObj(var);
13390	   if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13391	   {
13392	      SCIP_INTERVAL objint;
13393	      SCIP_INTERVAL bd;
13394	      SCIP_INTERVAL prod;
13395	      SCIP_INTERVAL psval;
13396	
13397	      SCIPintervalSet(&psval, pseudoobjval);
13398	      SCIPintervalSet(&objint, SCIPvarGetObj(var));
13399	
13400	      if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13401	         pseudoobjvalinf--;
13402	      else
13403	      {
13404	         SCIPintervalSet(&bd, oldbound);
13405	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13406	         SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13407	      }
13408	      assert(pseudoobjvalinf >= 0);
13409	      if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13410	         pseudoobjvalinf++;
13411	      else
13412	      {
13413	         SCIPintervalSet(&bd, newbound);
13414	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13415	         SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13416	      }
13417	
13418	      pseudoobjval = SCIPintervalGetInf(psval);
13419	   }
13420	   assert(pseudoobjvalinf >= 0);
13421	
13422	   if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13423	      return -SCIPsetInfinity(set);
13424	   else
13425	      return pseudoobjval;
13426	}
13427	
13428	/** compute the objective delta due the new objective coefficient */
13429	static
13430	void getObjvalDeltaObj(
13431	   SCIP_SET*             set,                /**< global SCIP settings */
13432	   SCIP_Real             oldobj,             /**< old objective value of variable */
13433	   SCIP_Real             newobj,             /**< new objective value of variable */
13434	   SCIP_Real             lb,                 /**< lower bound of variable */
13435	   SCIP_Real             ub,                 /**< upper bound of variable */
13436	   SCIP_Real*            deltaval,           /**< pointer to store the delta value */
13437	   int*                  deltainf            /**< pointer to store the number of variables with infinite best bound */
13438	   )
13439	{
13440	   assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13441	   assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13442	   assert(!SCIPsetIsInfinity(set, lb));
13443	   assert(!SCIPsetIsInfinity(set, -ub));
13444	   assert(!SCIPsetIsEQ(set, oldobj, newobj));
13445	
13446	   (*deltaval) = 0.0;
13447	   (*deltainf) = 0;
13448	
13449	   if( SCIPsetIsPositive(set, oldobj) )
13450	   {
13451	      /* sign of objective did not change */
13452	      if( SCIPsetIsPositive(set, newobj) )
13453	      {
13454	         /* if the bound is finite, calculate the deltaval */
13455	         if( !SCIPsetIsInfinity(set, -lb) )
13456	            (*deltaval) = lb * (newobj - oldobj);
13457	      }
13458	      /* sign of objective did change, so the best bound does change */
13459	      else if( SCIPsetIsNegative(set, newobj) )
13460	      {
13461	         if( SCIPsetIsInfinity(set, -lb) )
13462	         {
13463	            /* old best bound was infinite while new one is not */
13464	            if( !SCIPsetIsInfinity(set, ub) )
13465	            {
13466	               (*deltainf) = -1;
13467	               (*deltaval) = ub * newobj;
13468	            }
13469	         }
13470	         else
13471	         {
13472	            /* new best bound is infinite while old one was not */
13473	            if( SCIPsetIsInfinity(set, ub) )
13474	            {
13475	               (*deltainf) = 1;
13476	               (*deltaval) = -lb * oldobj;
13477	            }
13478	            /* neither old nor new best bound is infinite, so just calculate the deltaval */
13479	            else
13480	            {
13481	               (*deltaval) = (ub * newobj) - (lb * oldobj);
13482	            }
13483	         }
13484	      }
13485	      /* new objective is 0.0 */
13486	      else
13487	      {
13488	         if( SCIPsetIsInfinity(set, -lb) )
13489	            (*deltainf) = -1;
13490	         else
13491	            (*deltaval) = -lb * oldobj;
13492	      }
13493	   }
13494	   else if( SCIPsetIsNegative(set, oldobj) )
13495	   {
13496	      /* sign of objective did not change */
13497	      if( SCIPsetIsNegative(set, newobj) )
13498	      {
13499	         /* if the bound is finite, calculate the deltaval */
13500	         if( !SCIPsetIsInfinity(set, ub) )
13501	            (*deltaval) = ub * (newobj - oldobj);
13502	      }
13503	      /* sign of objective did change, so the best bound does change */
13504	      else if( SCIPsetIsPositive(set, newobj) )
13505	      {
13506	         if( SCIPsetIsInfinity(set, ub) )
13507	         {
13508	            /* old best bound was infinite while new one is not */
13509	            if( !SCIPsetIsInfinity(set, -lb) )
13510	            {
13511	               (*deltainf) = -1;
13512	               (*deltaval) = lb * newobj;
13513	            }
13514	         }
13515	         else
13516	         {
13517	            /* new best bound is infinite while old one was not */
13518	            if( SCIPsetIsInfinity(set, -lb) )
13519	            {
13520	               (*deltainf) = 1;
13521	               (*deltaval) = -ub * oldobj;
13522	            }
13523	            /* neither old nor new best bound is infinite, so just calculate the deltaval */
13524	            else
13525	            {
13526	               (*deltaval) = (lb * newobj) - (ub * oldobj);
13527	            }
13528	         }
13529	      }
13530	      /* new objective is 0.0 */
13531	      else
13532	      {
13533	         if( SCIPsetIsInfinity(set, ub) )
13534	            (*deltainf) = -1;
13535	         else
13536	            (*deltaval) = -ub * oldobj;
13537	      }
13538	   }
13539	   /* old objective was 0.0 */
13540	   else
13541	   {
13542	      if( SCIPsetIsNegative(set, newobj) )
13543	      {
13544	         if( SCIPsetIsInfinity(set, ub) )
13545	            (*deltainf) = 1;
13546	         else
13547	            (*deltaval) = ub * newobj;
13548	      }
13549	      else if( SCIPsetIsPositive(set, newobj) )
13550	      {
13551	         if( SCIPsetIsInfinity(set, -lb) )
13552	            (*deltainf) = 1;
13553	         else
13554	            (*deltaval) = lb * newobj;
13555	      }
13556	   }
13557	}
13558	
13559	/** compute the objective delta due the new lower bound */
13560	static
13561	void getObjvalDeltaLb(
13562	   SCIP_SET*             set,                /**< global SCIP settings */
13563	   SCIP_Real             obj,                /**< objective value of variable */
13564	   SCIP_Real             oldlb,              /**< old lower bound of variable */
13565	   SCIP_Real             newlb,              /**< new lower bound of variable */
13566	   SCIP_Real*            deltaval,           /**< pointer to store the delta value */
13567	   int*                  deltainf            /**< pointer to store the number of variables with infinite best bound */
13568	   )
13569	{
13570	   assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13571	   assert(!SCIPsetIsInfinity(set, oldlb));
13572	   assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
13573	   assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
13574	
13575	   if( SCIPsetIsInfinity(set, -oldlb) )
13576	   {
13577	      if( !SCIPsetIsInfinity(set, newlb) )
13578	      {
13579	         (*deltainf) = -1;
13580	         (*deltaval) = newlb * obj;
13581	      }
13582	      else
13583	      {
13584	         (*deltainf) = 0;
13585	         (*deltaval) = 0.0;
13586	      }
13587	   }
13588	   else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
13589	   {
13590	      (*deltainf) = 1;
13591	      (*deltaval) = -oldlb * obj;
13592	   }
13593	   else
13594	   {
13595	      (*deltainf) = 0;
13596	      (*deltaval) = obj * (newlb - oldlb);
13597	   }
13598	}
13599	
13600	/** compute the objective delta due the new upper bound */
13601	static
13602	void getObjvalDeltaUb(
13603	   SCIP_SET*             set,                /**< global SCIP settings */
13604	   SCIP_Real             obj,                /**< objective value of variable */
13605	   SCIP_Real             oldub,              /**< old upper bound of variable */
13606	   SCIP_Real             newub,              /**< new upper bound of variable */
13607	   SCIP_Real*            deltaval,           /**< pointer to store the delta value */
13608	   int*                  deltainf            /**< pointer to store the number of variables with infinite best bound */
13609	   )
13610	{
13611	   assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13612	   assert(!SCIPsetIsInfinity(set, -oldub));
13613	   assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
13614	   assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
13615	
13616	   if( SCIPsetIsInfinity(set, oldub) )
13617	   {
13618	      if( !SCIPsetIsInfinity(set, -newub) )
13619	      {
13620	         (*deltainf) = -1;
13621	         (*deltaval) = newub * obj;
13622	      }
13623	      else
13624	      {
13625	         (*deltainf) = 0;
13626	         (*deltaval) = 0.0;
13627	      }
13628	   }
13629	   else if( SCIPsetIsInfinity(set, REALABS(newub)) )
13630	   {
13631	      (*deltainf) = 1;
13632	      (*deltaval) = -oldub * obj;
13633	   }
13634	   else
13635	   {
13636	      (*deltainf) = 0;
13637	      (*deltaval) = obj * (newub - oldub);
13638	   }
13639	}
13640	
13641	/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13642	static
13643	void lpUpdateObjval(
13644	   SCIP_LP*              lp,                 /**< current LP data */
13645	   SCIP_SET*             set,                /**< global SCIP settings */
13646	   SCIP_VAR*             var,                /**< problem variable that changed */
13647	   SCIP_Real             deltaval,           /**< delta value in the objective function */
13648	   int                   deltainf,           /**< delta value for the number of variables with infinite best bound */
13649	   SCIP_Bool             local,              /**< should the local pseudo objective value be updated? */
13650	   SCIP_Bool             loose,              /**< should the loose objective value be updated? */
13651	   SCIP_Bool             global              /**< should the global pseudo objective value be updated? */
13652	   )
13653	{
13654	   assert(lp != NULL);
13655	   assert(lp->looseobjvalinf >= 0);
13656	   assert(lp->pseudoobjvalinf >= 0);
13657	   assert(lp->glbpseudoobjvalinf >= 0);
13658	
13659	   /* update the pseudo objective value */
13660	   if( local )
13661	   {
13662	      lp->pseudoobjvalinf += deltainf;
13663	      if( lp->pseudoobjvalid )
13664	      {
13665	         lp->pseudoobjval += deltaval;
13666	
13667	         /* if the absolute value was increased, this is regarded as reliable,
13668	          * otherwise, we check whether we can still trust the updated value
13669	          */
13670	         if( REALABS(lp->relpseudoobjval) < REALABS(lp->pseudoobjval) )
13671	            lp->relpseudoobjval = lp->pseudoobjval;
13672	         else if( SCIPsetIsUpdateUnreliable(set, lp->pseudoobjval, lp->relpseudoobjval) )
13673	            lp->pseudoobjvalid = FALSE;
13674	      }
13675	
13676	      /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13677	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
13678	         loose = TRUE;
13679	   }
13680	   /* update the loose objective value */
13681	   if( loose )
13682	   {
13683	      lp->looseobjvalinf += deltainf;
13684	
13685	      if( deltaval != 0.0 && lp->looseobjvalid )
13686	      {
13687	         lp->looseobjval += deltaval;
13688	
13689	         /* if the absolute value was increased, this is regarded as reliable,
13690	          * otherwise, we check whether we can still trust the updated value
13691	          */
13692	         if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13693	            lp->rellooseobjval = lp->looseobjval;
13694	         else if( SCIPsetIsUpdateUnreliable(set, lp->looseobjval, lp->rellooseobjval) )
13695	            lp->looseobjvalid = FALSE;
13696	      }
13697	   }
13698	   /* update the root pseudo objective values */
13699	   if( global )
13700	   {
13701	      lp->glbpseudoobjvalinf += deltainf;
13702	      if( lp->glbpseudoobjvalid )
13703	      {
13704	         lp->glbpseudoobjval += deltaval;
13705	
13706	         /* if the absolute value was increased, this is regarded as reliable,
13707	          * otherwise, we check whether we can still trust the updated value
13708	          */
13709	         if( REALABS(lp->relglbpseudoobjval) < REALABS(lp->glbpseudoobjval) )
13710	            lp->relglbpseudoobjval = lp->glbpseudoobjval;
13711	         else if( SCIPsetIsUpdateUnreliable(set, lp->glbpseudoobjval, lp->relglbpseudoobjval) )
13712	            lp->glbpseudoobjvalid = FALSE;
13713	      }
13714	   }
13715	
13716	   assert(lp->looseobjvalinf >= 0);
13717	   assert(lp->pseudoobjvalinf >= 0);
13718	   assert(lp->glbpseudoobjvalinf >= 0);
13719	}
13720	
13721	/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13722	 *  pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13723	 */
13724	static
13725	SCIP_RETCODE lpUpdateVarProved(
13726	   SCIP_LP*              lp,                 /**< current LP data */
13727	   SCIP_SET*             set,                /**< global SCIP settings */
13728	   SCIP_VAR*             var,                /**< problem variable that changed */
13729	   SCIP_Real             oldobj,             /**< old objective value of variable */
13730	   SCIP_Real             oldlb,              /**< old objective value of variable */
13731	   SCIP_Real             oldub,              /**< old objective value of variable */
13732	   SCIP_Real             newobj,             /**< new objective value of variable */
13733	   SCIP_Real             newlb,              /**< new objective value of variable */
13734	   SCIP_Real             newub               /**< new objective value of variable */
13735	   )
13736	{
13737	   SCIP_INTERVAL deltaval;
13738	   SCIP_INTERVAL bd;
13739	   SCIP_INTERVAL obj;
13740	   SCIP_INTERVAL prod;
13741	   SCIP_INTERVAL psval;
13742	   int deltainf;
13743	
13744	   assert(lp != NULL);
13745	   assert(lp->pseudoobjvalinf >= 0);
13746	   assert(lp->looseobjvalinf >= 0);
13747	   assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13748	   assert(!SCIPsetIsInfinity(set, oldlb));
13749	   assert(!SCIPsetIsInfinity(set, -oldub));
13750	   assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13751	   assert(!SCIPsetIsInfinity(set, newlb));
13752	   assert(!SCIPsetIsInfinity(set, -newub));
13753	   assert(var != NULL);
13754	
13755	   if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
13756	   {
13757	      SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13758	      return SCIP_INVALIDDATA;
13759	   }
13760	
13761	   assert(SCIPvarGetProbindex(var) >= 0);
13762	
13763	   SCIPintervalSet(&deltaval, 0.0);
13764	   deltainf = 0;
13765	
13766	   /* subtract old pseudo objective value */
13767	   if( oldobj > 0.0 )
13768	   {
13769	      if( SCIPsetIsInfinity(set, -oldlb) )
13770	         deltainf--;
13771	      else
13772	      {
13773	         SCIPintervalSet(&bd, oldlb);
13774	         SCIPintervalSet(&obj, oldobj);
13775	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13776	         SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod);  /* deltaval -= oldlb * oldobj; */
13777	      }
13778	   }
13779	   else if( oldobj < 0.0 )
13780	   {
13781	      if( SCIPsetIsInfinity(set, oldub) )
13782	         deltainf--;
13783	      else
13784	      {
13785	         SCIPintervalSet(&bd, oldub);
13786	         SCIPintervalSet(&obj, oldobj);
13787	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13788	         SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod);  /* deltaval -= oldub * oldobj; */
13789	      }
13790	   }
13791	
13792	   /* add new pseudo objective value */
13793	   if( newobj > 0.0 )
13794	   {
13795	      if( SCIPsetIsInfinity(set, -newlb) )
13796	         deltainf++;
13797	      else
13798	      {
13799	         SCIPintervalSet(&bd, newlb);
13800	         SCIPintervalSet(&obj, newobj);
13801	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13802	         SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod);  /* deltaval += newlb * newobj; */
13803	      }
13804	   }
13805	   else if( newobj < 0.0 )
13806	   {
13807	      if( SCIPsetIsInfinity(set, newub) )
13808	         deltainf++;
13809	      else
13810	      {
13811	         SCIPintervalSet(&bd, newub);
13812	         SCIPintervalSet(&obj, newobj);
13813	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13814	         SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod);  /* deltaval += newub * newobj; */
13815	      }
13816	   }
13817	
13818	   /* update the pseudo and loose objective values */
13819	   SCIPintervalSet(&psval, lp->pseudoobjval);
13820	   SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13821	   lp->pseudoobjval = SCIPintervalGetInf(psval);
13822	   lp->pseudoobjvalinf += deltainf;
13823	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
13824	   {
13825	      SCIPintervalSet(&psval, lp->looseobjval);
13826	      SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13827	      lp->looseobjval = SCIPintervalGetInf(psval);
13828	      lp->looseobjvalinf += deltainf;
13829	   }
13830	
13831	   assert(lp->pseudoobjvalinf >= 0);
13832	   assert(lp->looseobjvalinf >= 0);
13833	
13834	   return SCIP_OKAY;
13835	}
13836	
13837	/** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13838	SCIP_RETCODE SCIPlpUpdateVarObj(
13839	   SCIP_LP*              lp,                 /**< current LP data */
13840	   SCIP_SET*             set,                /**< global SCIP settings */
13841	   SCIP_VAR*             var,                /**< problem variable that changed */
13842	   SCIP_Real             oldobj,             /**< old objective coefficient of variable */
13843	   SCIP_Real             newobj              /**< new objective coefficient of variable */
13844	   )
13845	{
13846	   assert(set != NULL);
13847	   assert(var != NULL);
13848	
13849	   if( set->misc_exactsolve )
13850	   {
13851	      if( oldobj != newobj ) /*lint !e777*/
13852	      {
13853	         SCIP_CALL( lpUpdateVarProved(lp, set, var, oldobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
13854	               newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
13855	      }
13856	   }
13857	   else
13858	   {
13859	      if( !SCIPsetIsEQ(set, oldobj, newobj) )
13860	      {
13861	         SCIP_Real deltaval;
13862	         int deltainf;
13863	
13864	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13865	         assert(SCIPvarGetProbindex(var) >= 0);
13866	
13867	         /* the objective coefficient can only be changed during presolving, that implies that the global and local
13868	          * domain of the variable are the same
13869	          */
13870	         assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
13871	         assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
13872	
13873	         /* compute the pseudo objective delta due the new objective coefficient */
13874	         getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
13875	
13876	         /* update the local pseudo objective value */
13877	         lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13878	
13879	         /* compute the pseudo objective delta due the new objective coefficient */
13880	         getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
13881	
13882	         /* update the global pseudo objective value */
13883	         lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13884	      }
13885	   }
13886	
13887	   return SCIP_OKAY;
13888	}
13889	
13890	
13891	/** updates current root pseudo objective value for a global change in a variable's lower bound */
13892	SCIP_RETCODE SCIPlpUpdateVarLbGlobal(
13893	   SCIP_LP*              lp,                 /**< current LP data */
13894	   SCIP_SET*             set,                /**< global SCIP settings */
13895	   SCIP_VAR*             var,                /**< problem variable that changed */
13896	   SCIP_Real             oldlb,              /**< old lower bound of variable */
13897	   SCIP_Real             newlb               /**< new lower bound of variable */
13898	   )
13899	{
13900	   assert(set != NULL);
13901	   assert(var != NULL);
13902	
13903	   if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13904	   {
13905	      SCIP_Real deltaval;
13906	      int deltainf;
13907	
13908	      /* compute the pseudo objective delta due the new lower bound */
13909	      getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13910	
13911	      /* update the root pseudo objective values */
13912	      lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13913	   }
13914	
13915	   return SCIP_OKAY;
13916	}
13917	
13918	/** updates current pseudo and loose objective value for a change in a variable's lower bound */
13919	SCIP_RETCODE SCIPlpUpdateVarLb(
13920	   SCIP_LP*              lp,                 /**< current LP data */
13921	   SCIP_SET*             set,                /**< global SCIP settings */
13922	   SCIP_VAR*             var,                /**< problem variable that changed */
13923	   SCIP_Real             oldlb,              /**< old lower bound of variable */
13924	   SCIP_Real             newlb               /**< new lower bound of variable */
13925	   )
13926	{
13927	   assert(set != NULL);
13928	   assert(var != NULL);
13929	
13930	   if( set->misc_exactsolve )
13931	   {
13932	      if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13933	      {
13934	         SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
13935	               SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
13936	      }
13937	   }
13938	   else
13939	   {
13940	      if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13941	      {
13942	         SCIP_Real deltaval;
13943	         int deltainf;
13944	
13945	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13946	         assert(SCIPvarGetProbindex(var) >= 0);
13947	
13948	         /* compute the pseudo objective delta due the new lower bound */
13949	         getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13950	
13951	         /* update the pseudo and loose objective values */
13952	         lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13953	      }
13954	   }
13955	
13956	   return SCIP_OKAY;
13957	}
13958	
13959	/** updates current root pseudo objective value for a global change in a variable's upper bound */
13960	SCIP_RETCODE SCIPlpUpdateVarUbGlobal(
13961	   SCIP_LP*              lp,                 /**< current LP data */
13962	   SCIP_SET*             set,                /**< global SCIP settings */
13963	   SCIP_VAR*             var,                /**< problem variable that changed */
13964	   SCIP_Real             oldub,              /**< old upper bound of variable */
13965	   SCIP_Real             newub               /**< new upper bound of variable */
13966	   )
13967	{
13968	   assert(set != NULL);
13969	   assert(var != NULL);
13970	
13971	   if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13972	   {
13973	      SCIP_Real deltaval;
13974	      int deltainf;
13975	
13976	      /* compute the pseudo objective delta due the new upper bound */
13977	      getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13978	
13979	      /* update the root pseudo objective values */
13980	      lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13981	   }
13982	
13983	   return SCIP_OKAY;
13984	}
13985	
13986	/** updates current pseudo objective value for a change in a variable's upper bound */
13987	SCIP_RETCODE SCIPlpUpdateVarUb(
13988	   SCIP_LP*              lp,                 /**< current LP data */
13989	   SCIP_SET*             set,                /**< global SCIP settings */
13990	   SCIP_VAR*             var,                /**< problem variable that changed */
13991	   SCIP_Real             oldub,              /**< old upper bound of variable */
13992	   SCIP_Real             newub               /**< new upper bound of variable */
13993	   )
13994	{
13995	   assert(set != NULL);
13996	   assert(var != NULL);
13997	
13998	   if( set->misc_exactsolve )
13999	   {
14000	      if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14001	      {
14002	         SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
14003	               SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
14004	      }
14005	   }
14006	   else
14007	   {
14008	      if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14009	      {
14010	         SCIP_Real deltaval;
14011	         int deltainf;
14012	
14013	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14014	         assert(SCIPvarGetProbindex(var) >= 0);
14015	
14016	         /* compute the pseudo objective delta due the new upper bound */
14017	         getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14018	
14019	         /* update the pseudo and loose objective values */
14020	         lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14021	      }
14022	   }
14023	
14024	   return SCIP_OKAY;
14025	}
14026	
14027	/** informs LP, that given variable was added to the problem */
14028	SCIP_RETCODE SCIPlpUpdateAddVar(
14029	   SCIP_LP*              lp,                 /**< current LP data */
14030	   SCIP_SET*             set,                /**< global SCIP settings */
14031	   SCIP_VAR*             var                 /**< variable that is now a LOOSE problem variable */
14032	   )
14033	{
14034	   assert(lp != NULL);
14035	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14036	   assert(SCIPvarGetProbindex(var) >= 0);
14037	
14038	   /* add the variable to the loose objective value sum */
14039	   SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
14040	
14041	   /* update the loose variables counter */
14042	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
14043	      lp->nloosevars++;
14044	
14045	   return SCIP_OKAY;
14046	}
14047	
14048	/** informs LP, that given variable is to be deleted from the problem */
14049	SCIP_RETCODE SCIPlpUpdateDelVar(
14050	   SCIP_LP*              lp,                 /**< current LP data */
14051	   SCIP_SET*             set,                /**< global SCIP settings */
14052	   SCIP_VAR*             var                 /**< variable that will be deleted from the problem */
14053	   )
14054	{
14055	   assert(lp != NULL);
14056	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14057	   assert(SCIPvarGetProbindex(var) >= 0);
14058	
14059	   /* subtract the variable from the loose objective value sum */
14060	   SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
14061	
14062	   /* update the loose variables counter */
14063	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
14064	   {
14065	      SCIPlpDecNLoosevars(lp);
14066	   }
14067	
14068	   return SCIP_OKAY;
14069	}
14070	
14071	/** informs LP, that given formerly loose problem variable is now a column variable */
14072	static
14073	SCIP_RETCODE lpUpdateVarColumn(
14074	   SCIP_LP*              lp,                 /**< current LP data */
14075	   SCIP_SET*             set,                /**< global SCIP settings */
14076	   SCIP_VAR*             var                 /**< problem variable that changed from LOOSE to COLUMN */
14077	   )
14078	{
14079	   SCIP_Real obj;
14080	   SCIP_Real lb;
14081	   SCIP_Real ub;
14082	
14083	   assert(lp != NULL);
14084	   assert(lp->nloosevars > 0);
14085	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14086	   assert(SCIPvarGetProbindex(var) >= 0);
14087	   assert(lp->looseobjvalinf >= 0);
14088	
14089	   obj = SCIPvarGetObj(var);
14090	
14091	   /* update loose objective value */
14092	   if( SCIPsetIsPositive(set, obj) )
14093	   {
14094	      lb = SCIPvarGetLbLocal(var);
14095	      if( SCIPsetIsInfinity(set, -lb) )
14096	         lp->looseobjvalinf--;
14097	      else
14098	         lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14099	   }
14100	   else if( SCIPsetIsNegative(set, obj) )
14101	   {
14102	      ub = SCIPvarGetUbLocal(var);
14103	      if( SCIPsetIsInfinity(set, ub) )
14104	         lp->looseobjvalinf--;
14105	      else
14106	         lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14107	   }
14108	
14109	   SCIPlpDecNLoosevars(lp);
14110	
14111	   assert(lp->looseobjvalinf >= 0);
14112	
14113	   return SCIP_OKAY;
14114	}
14115	
14116	/** informs LP, that given formerly loose problem variable is now a column variable
14117	 *  pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14118	 */
14119	static
14120	SCIP_RETCODE lpUpdateVarColumnProved(
14121	   SCIP_LP*              lp,                 /**< current LP data */
14122	   SCIP_SET*             set,                /**< global SCIP settings */
14123	   SCIP_VAR*             var                 /**< problem variable that changed from LOOSE to COLUMN */
14124	   )
14125	{
14126	   SCIP_INTERVAL bd;
14127	   SCIP_INTERVAL ob;
14128	   SCIP_INTERVAL prod;
14129	   SCIP_INTERVAL loose;
14130	   SCIP_Real obj;
14131	   SCIP_Real lb;
14132	   SCIP_Real ub;
14133	
14134	   assert(lp != NULL);
14135	   assert(lp->nloosevars > 0);
14136	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14137	   assert(SCIPvarGetProbindex(var) >= 0);
14138	
14139	   obj = SCIPvarGetObj(var);
14140	
14141	   SCIPintervalSet(&loose, lp->looseobjval);
14142	
14143	   /* update loose objective value corresponding to the deletion of variable */
14144	   if( obj > 0.0 )
14145	   {
14146	      lb = SCIPvarGetLbLocal(var);
14147	      if( SCIPsetIsInfinity(set, -lb) )
14148	         lp->looseobjvalinf--;
14149	      else
14150	      {
14151	         SCIPintervalSet(&bd, lb);
14152	         SCIPintervalSet(&ob, obj);
14153	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14154	         SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod);  /* lp->looseobjval -= lb * obj; */
14155	      }
14156	   }
14157	   else if( SCIPsetIsNegative(set, obj) )
14158	   {
14159	      ub = SCIPvarGetUbLocal(var);
14160	      if( SCIPsetIsInfinity(set, ub) )
14161	         lp->looseobjvalinf--;
14162	      else
14163	      {
14164	         SCIPintervalSet(&bd, ub);
14165	         SCIPintervalSet(&ob, obj);
14166	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14167	         SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod);  /* lp->looseobjval -= ub * obj; */
14168	      }
14169	   }
14170	   lp->nloosevars--;
14171	
14172	   /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14173	   if( lp->nloosevars == 0 )
14174	   {
14175	      assert(lp->looseobjvalinf == 0);
14176	      lp->looseobjval = 0.0;
14177	   }
14178	   else
14179	      lp->looseobjval = SCIPintervalGetInf(loose);
14180	
14181	   return SCIP_OKAY;
14182	}
14183	
14184	/** informs LP, that given formerly loose problem variable is now a column variable */
14185	SCIP_RETCODE SCIPlpUpdateVarColumn(
14186	   SCIP_LP*              lp,                 /**< current LP data */
14187	   SCIP_SET*             set,                /**< global SCIP settings */
14188	   SCIP_VAR*             var                 /**< problem variable that changed from LOOSE to COLUMN */
14189	   )
14190	{
14191	   assert(set != NULL);
14192	
14193	   if( set->misc_exactsolve )
14194	   {
14195	      SCIP_CALL( lpUpdateVarColumnProved(lp, set, var) );
14196	   }
14197	   else
14198	   {
14199	      SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
14200	   }
14201	
14202	   return SCIP_OKAY;
14203	}
14204	
14205	/** informs LP, that given formerly column problem variable is now again a loose variable */
14206	static
14207	SCIP_RETCODE lpUpdateVarLoose(
14208	   SCIP_LP*              lp,                 /**< current LP data */
14209	   SCIP_SET*             set,                /**< global SCIP settings */
14210	   SCIP_VAR*             var                 /**< problem variable that changed from COLUMN to LOOSE */
14211	   )
14212	{
14213	   SCIP_Real obj;
14214	   SCIP_Real lb;
14215	   SCIP_Real ub;
14216	
14217	   assert(lp != NULL);
14218	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14219	   assert(SCIPvarGetProbindex(var) >= 0);
14220	   assert(lp->looseobjvalinf >= 0);
14221	
14222	   obj = SCIPvarGetObj(var);
14223	
14224	   /* update loose objective value corresponding to the addition of variable */
14225	   if( SCIPsetIsPositive(set, obj) )
14226	   {
14227	      lb = SCIPvarGetLbLocal(var);
14228	      if( SCIPsetIsInfinity(set, -lb) )
14229	         lp->looseobjvalinf++;
14230	      else
14231	         lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14232	   }
14233	   else if( SCIPsetIsNegative(set, obj) )
14234	   {
14235	      ub = SCIPvarGetUbLocal(var);
14236	      if( SCIPsetIsInfinity(set, ub) )
14237	         lp->looseobjvalinf++;
14238	      else
14239	         lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14240	   }
14241	   lp->nloosevars++;
14242	
14243	   assert(lp->looseobjvalinf >= 0);
14244	
14245	   return SCIP_OKAY;
14246	}
14247	
14248	/** informs LP, that given formerly column problem variable is now again a loose variable
14249	 *  pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14250	 */
14251	static
14252	SCIP_RETCODE lpUpdateVarLooseProved(
14253	   SCIP_LP*              lp,                 /**< current LP data */
14254	   SCIP_SET*             set,                /**< global SCIP settings */
14255	   SCIP_VAR*             var                 /**< problem variable that changed from COLUMN to LOOSE */
14256	   )
14257	{
14258	   SCIP_INTERVAL bd;
14259	   SCIP_INTERVAL ob;
14260	   SCIP_INTERVAL prod;
14261	   SCIP_INTERVAL loose;
14262	   SCIP_Real obj;
14263	   SCIP_Real lb;
14264	   SCIP_Real ub;
14265	
14266	   assert(lp != NULL);
14267	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14268	   assert(SCIPvarGetProbindex(var) >= 0);
14269	
14270	   obj = SCIPvarGetObj(var);
14271	
14272	   SCIPintervalSet(&loose, lp->looseobjval);
14273	
14274	   /* update loose objective value corresponding to the deletion of variable */
14275	   if( obj > 0.0 )
14276	   {
14277	      lb = SCIPvarGetLbLocal(var);
14278	      if( SCIPsetIsInfinity(set, -lb) )
14279	         lp->looseobjvalinf++;
14280	      else
14281	      {
14282	         SCIPintervalSet(&bd, lb);
14283	         SCIPintervalSet(&ob, obj);
14284	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14285	         SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod);  /* lp->looseobjval += lb * obj; */
14286	      }
14287	   }
14288	   else if( SCIPsetIsNegative(set, obj) )
14289	   {
14290	      ub = SCIPvarGetUbLocal(var);
14291	      if( SCIPsetIsInfinity(set, ub) )
14292	         lp->looseobjvalinf++;
14293	      else
14294	      {
14295	         SCIPintervalSet(&bd, ub);
14296	         SCIPintervalSet(&ob, obj);
14297	         SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14298	         SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod);  /* lp->looseobjval += ub * obj; */
14299	      }
14300	   }
14301	   lp->nloosevars++;
14302	
14303	   lp->looseobjval = SCIPintervalGetInf(loose);
14304	
14305	   return SCIP_OKAY;
14306	}
14307	
14308	/** informs LP, that given formerly column problem variable is now again a loose variable */
14309	SCIP_RETCODE SCIPlpUpdateVarLoose(
14310	   SCIP_LP*              lp,                 /**< current LP data */
14311	   SCIP_SET*             set,                /**< global SCIP settings */
14312	   SCIP_VAR*             var                 /**< problem variable that changed from COLUMN to LOOSE */
14313	   )
14314	{
14315	   assert(set != NULL);
14316	
14317	   if( set->misc_exactsolve )
14318	   {
14319	      SCIP_CALL( lpUpdateVarLooseProved(lp, set, var) );
14320	   }
14321	   else
14322	   {
14323	      SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
14324	   }
14325	
14326	   return SCIP_OKAY;
14327	}
14328	
14329	/** decrease the number of loose variables by one */
14330	void SCIPlpDecNLoosevars(
14331	   SCIP_LP*              lp                  /**< current LP data */
14332	   )
14333	{
14334	   assert(lp != NULL);
14335	   assert(lp->nloosevars > 0);
14336	
14337	   lp->nloosevars--;
14338	
14339	   /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14340	   if( lp->nloosevars == 0 )
14341	   {
14342	      assert(lp->looseobjvalinf == 0);
14343	      lp->looseobjval = 0.0;
14344	   }
14345	}
14346	
14347	/** stores the LP solution in the columns and rows */
14348	SCIP_RETCODE SCIPlpGetSol(
14349	   SCIP_LP*              lp,                 /**< current LP data */
14350	   SCIP_SET*             set,                /**< global SCIP settings */
14351	   SCIP_STAT*            stat,               /**< problem statistics */
14352	   SCIP_Bool*            primalfeasible,     /**< pointer to store whether the solution is primal feasible, or NULL */
14353	   SCIP_Bool*            dualfeasible        /**< pointer to store whether the solution is dual feasible, or NULL */
14354	   )
14355	{
14356	   SCIP_COL** lpicols;
14357	   SCIP_ROW** lpirows;
14358	   SCIP_Real* primsol;
14359	   SCIP_Real* dualsol;
14360	   SCIP_Real* activity = NULL;
14361	   SCIP_Real* redcost;
14362	   SCIP_Real primalbound;
14363	   SCIP_Real dualbound;
14364	   SCIP_Bool stillprimalfeasible;
14365	   SCIP_Bool stilldualfeasible;
14366	   int* cstat;
14367	   int* rstat;
14368	   SCIP_Longint lpcount;
14369	   int nlpicols;
14370	   int nlpirows;
14371	   int c;
14372	   int r;
14373	
14374	   assert(lp != NULL);
14375	   assert(lp->flushed);
14376	   assert(lp->solved);
14377	   assert(set != NULL);
14378	   assert(stat != NULL);
14379	   assert(lp->validsollp <= stat->lpcount);
14380	
14381	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
14382	
14383	   /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14384	    * corresponding flag immediately to FALSE to skip all checks
14385	    */
14386	   if( primalfeasible == NULL )
14387	      stillprimalfeasible = FALSE;
14388	   else
14389	   {
14390	      *primalfeasible = TRUE;
14391	      stillprimalfeasible = TRUE;
14392	   }
14393	   if( dualfeasible == NULL )
14394	      stilldualfeasible = FALSE;
14395	   else
14396	   {
14397	      *dualfeasible = TRUE;
14398	      stilldualfeasible = TRUE;
14399	   }
14400	
14401	   /* check if the values are already calculated */
14402	   if( lp->validsollp == stat->lpcount )
14403	      return SCIP_OKAY;
14404	   lp->validsollp = stat->lpcount;
14405	
14406	   SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14407	      stat->lpcount, SCIPlpGetSolstat(lp));
14408	
14409	   lpicols = lp->lpicols;
14410	   lpirows = lp->lpirows;
14411	   nlpicols = lp->nlpicols;
14412	   nlpirows = lp->nlpirows;
14413	   lpcount = stat->lpcount;
14414	
14415	   /* get temporary memory */
14416	   SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
14417	   SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14418	#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14419	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14420	#endif
14421	   SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14422	   SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14423	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14424	
14425	   SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14426	   if( lp->solisbasic )
14427	   {
14428	      SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14429	   }
14430	   else
14431	   {
14432	      BMSclearMemoryArray(cstat, nlpicols);
14433	      BMSclearMemoryArray(rstat, nlpirows);
14434	   }
14435	
14436	   primalbound = 0.0;
14437	   dualbound = 0.0;
14438	
14439	   /* copy primal solution and reduced costs into columns */
14440	   for( c = 0; c < nlpicols; ++c )
14441	   {
14442	      assert( 0 <= cstat[c] && cstat[c] < 4 );
14443	      lpicols[c]->primsol = primsol[c];
14444	      if( !SCIPisFinite(lpicols[c]->primsol) )
14445	      {
14446	         /* calculating with nan or +/-inf can have many unexpected effects
14447	          * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14448	          * this should trigger a resolve of the LP, or a stop with an LP error
14449	          */
14450	         stillprimalfeasible = FALSE;
14451	         stilldualfeasible = FALSE;
14452	         lpicols[c]->primsol = 0.0;
14453	         SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14454	      }
14455	      lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14456	      lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14457	      lpicols[c]->redcost = redcost[c];
14458	      lpicols[c]->basisstatus = (unsigned int) cstat[c];
14459	      lpicols[c]->validredcostlp = lpcount;
14460	      if( stillprimalfeasible )
14461	      {
14462	         stillprimalfeasible =
14463	            (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14464	            && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14465	         primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14466	      }
14467	      if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14468	      {
14469	         double compslack;
14470	
14471	         /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14472	          * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14473	          * variables, which would magnify even the tiniest violation in the dual multiplier
14474	          */
14475	         if( stilldualfeasible )
14476	         {
14477	            compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14478	            stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14479	         }
14480	         if( stilldualfeasible )
14481	         {
14482	            compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14483	            stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14484	         }
14485	
14486	         SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14487	            SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14488	            SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14489	            SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14490	            primalfeasible != NULL ? stillprimalfeasible : TRUE,
14491	            !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14492	            !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14493	            dualfeasible != NULL ? stilldualfeasible : TRUE);
14494	      }
14495	      else
14496	      {
14497	         /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14498	         if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14499	         {
14500	            lpicols[c]->redcost = 0.0;
14501	         }
14502	
14503	         /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14504	          * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14505	          * bounds, its reduced cost must be zero
14506	          */
14507	         if( stilldualfeasible
14508	            && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14509	            stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14510	         if( stilldualfeasible
14511	            && (SCIPsetIsInfinity(set,  lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14512	            stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14513	
14514	         SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14515	            SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14516	            SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14517	            SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14518	            primalfeasible != NULL ? stillprimalfeasible : TRUE,
14519	            !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14520	            !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14521	            dualfeasible != NULL ? stilldualfeasible : TRUE);
14522	      }
14523	
14524	      /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14525	       * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14526	       * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14527	       */
14528	      if( stilldualfeasible )
14529	      {
14530	         if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14531	            dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14532	         else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14533	            dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14534	      }
14535	   }
14536	
14537	   /* copy dual solution and activities into rows */
14538	   for( r = 0; r < nlpirows; ++r )
14539	   {
14540	      assert( 0 <= rstat[r] && rstat[r] < 4 );
14541	      lpirows[r]->dualsol = dualsol[r];
14542	#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14543	      lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14544	#else
14545	      /* calculate row activity if invalid */
14546	      if( lpirows[r]->validactivitylp != stat->lpcount )
14547	         SCIProwRecalcLPActivity(lpirows[r], stat);
14548	#endif
14549	      lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14550	      lpirows[r]->validactivitylp = lpcount;
14551	      if( stillprimalfeasible )
14552	      {
14553	         stillprimalfeasible =
14554	            (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14555	            && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14556	      }
14557	      if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14558	      {
14559	         double compslack;
14560	
14561	         /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14562	          * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14563	          * variables, which would magnify even the tiniest violation in the dual multiplier
14564	          */
14565	         if( stilldualfeasible )
14566	         {
14567	            compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14568	            stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14569	         }
14570	         if( stilldualfeasible )
14571	         {
14572	            compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14573	            stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14574	         }
14575	
14576	         SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14577	            lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14578	            SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14579	            SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14580	            primalfeasible != NULL ? stillprimalfeasible : TRUE,
14581	            !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14582	            !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14583	            dualfeasible != NULL ? stilldualfeasible : TRUE);
14584	      }
14585	      else
14586	      {
14587	         /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14588	          * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14589	          * strictly within left-hand and right-hand side, its dual multiplier must be zero
14590	          */
14591	         if( stilldualfeasible &&
14592	               (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14593	            stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14594	         if( stilldualfeasible &&
14595	               (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14596	            stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14597	
14598	         SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14599	            lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14600	            SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14601	            SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14602	            primalfeasible != NULL ? stillprimalfeasible : TRUE,
14603	            !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14604	            !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14605	            dualfeasible != NULL ? stilldualfeasible : TRUE);
14606	      }
14607	
14608	      /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14609	       * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14610	       * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14611	       */
14612	      if( stilldualfeasible )
14613	      {
14614	         if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14615	            dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14616	         else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14617	            dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14618	      }
14619	   }
14620	
14621	   /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14622	    * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14623	    * infinity
14624	    */
14625	   /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14626	   if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14627	      && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14628	   {
14629	      stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14630	      SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14631	         SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14632	   }
14633	
14634	   /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14635	    * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14636	    */
14637	   /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14638	   if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14639	      && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14640	   {
14641	      stilldualfeasible =  SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14642	      SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14643	         SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14644	   }
14645	
14646	   if( primalfeasible != NULL )
14647	      *primalfeasible = stillprimalfeasible;
14648	   if( dualfeasible != NULL )
14649	      *dualfeasible = stilldualfeasible;
14650	
14651	   /* free temporary memory */
14652	   SCIPsetFreeBufferArray(set, &rstat);
14653	   SCIPsetFreeBufferArray(set, &cstat);
14654	   SCIPsetFreeBufferArray(set, &redcost);
14655	#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14656	   SCIPsetFreeBufferArray(set, &activity);
14657	#endif
14658	   SCIPsetFreeBufferArray(set, &dualsol);
14659	   SCIPsetFreeBufferArray(set, &primsol);
14660	
14661	   return SCIP_OKAY;
14662	}
14663	
14664	/** stores LP solution with infinite objective value in the columns and rows */
14665	SCIP_RETCODE SCIPlpGetUnboundedSol(
14666	   SCIP_LP*              lp,                 /**< current LP data */
14667	   SCIP_SET*             set,                /**< global SCIP settings */
14668	   SCIP_STAT*            stat,               /**< problem statistics */
14669	   SCIP_Bool*            primalfeasible,     /**< pointer to store whether the solution is primal feasible, or NULL */
14670	   SCIP_Bool*            rayfeasible         /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14671	   )
14672	{
14673	   SCIP_COL** lpicols;
14674	   SCIP_ROW** lpirows;
14675	   SCIP_Real* primsol;
14676	   SCIP_Real* activity;
14677	   SCIP_Real* ray;
14678	   SCIP_Real rayobjval;
14679	   SCIP_Real rayscale;
14680	   SCIP_Longint lpcount;
14681	   SCIP_COL* col;
14682	   int nlpicols;
14683	   int nlpirows;
14684	   int c;
14685	   int r;
14686	
14687	   assert(lp != NULL);
14688	   assert(lp->flushed);
14689	   assert(lp->solved);
14690	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
14691	   assert(SCIPsetIsInfinity(set, -lp->lpobjval));
14692	   assert(set != NULL);
14693	   assert(stat != NULL);
14694	   assert(lp->validsollp <= stat->lpcount);
14695	
14696	   if( primalfeasible != NULL )
14697	      *primalfeasible = TRUE;
14698	   if( rayfeasible != NULL )
14699	      *rayfeasible = TRUE;
14700	
14701	   /* check if the values are already calculated */
14702	   if( lp->validsollp == stat->lpcount )
14703	      return SCIP_OKAY;
14704	   lp->validsollp = stat->lpcount;
14705	
14706	   /* check if the LP solver is able to provide a primal unbounded ray */
14707	   if( !SCIPlpiHasPrimalRay(lp->lpi) )
14708	   {
14709	      SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14710	      return SCIP_LPERROR;
14711	   }
14712	
14713	   SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14714	
14715	   /* get temporary memory */
14716	   SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
14717	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14718	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, lp->nlpicols) );
14719	
14720	   /* get primal unbounded ray */
14721	   SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14722	
14723	   lpicols = lp->lpicols;
14724	   lpirows = lp->lpirows;
14725	   nlpicols = lp->nlpicols;
14726	   nlpirows = lp->nlpirows;
14727	   lpcount = stat->lpcount;
14728	
14729	   /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14730	   rayobjval = 0.0;
14731	   for( c = 0; c < nlpicols; ++c )
14732	   {
14733	      assert(lpicols[c] != NULL);
14734	      assert(lpicols[c]->var != NULL);
14735	
14736	      col = lpicols[c];
14737	
14738	      /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14739	      if( rayfeasible != NULL )
14740	      {
14741	         *rayfeasible = *rayfeasible
14742	            && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14743	            && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set,  col->ub));
14744	      }
14745	
14746	      if( ! SCIPsetIsZero(set, ray[c]) )
14747	         rayobjval += ray[c] * col->obj;
14748	
14749	      /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14750	       * heuristically try to construct a primal solution.
14751	       */
14752	      primsol[c] = 0.0;
14753	      if( SCIPsetIsFeasZero(set, ray[c]) )
14754	      {
14755	         /* if the ray component is 0, we try to satisfy as many rows as possible */
14756	         if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14757	            primsol[c] = col->lb;
14758	         else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14759	            primsol[c] = col->ub;
14760	      }
14761	
14762	      /* make sure we respect the bounds */
14763	      primsol[c] = MAX(primsol[c], col->lb);
14764	      primsol[c] = MIN(primsol[c], col->ub);
14765	
14766	      assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14767	   }
14768	
14769	   /* check feasibility of heuristic primal solution */
14770	   for( r = 0; r < nlpirows; ++r )
14771	   {
14772	      SCIP_Real act;
14773	      SCIP_ROW* row;
14774	
14775	      row = lpirows[r];
14776	      assert( row != NULL );
14777	      act = row->constant;
14778	
14779	      for( c = 0; c < row->nlpcols; ++c )
14780	      {
14781	         col = row->cols[c];
14782	
14783	         assert( col != NULL );
14784	         assert( col->lppos >= 0 );
14785	         assert( row->linkpos[c] >= 0 );
14786	         assert( primsol[col->lppos] != SCIP_INVALID );  /*lint !e777*/
14787	
14788	         act += row->vals[c] * primsol[col->lppos];
14789	      }
14790	
14791	      if( row->nunlinked > 0 )
14792	      {
14793	         for( c = row->nlpcols; c < row->len; ++c )
14794	         {
14795	            col = row->cols[c];
14796	            assert( col != NULL );
14797	
14798	            if( col->lppos >= 0 )
14799	               act += row->vals[c] * primsol[col->lppos];
14800	         }
14801	      }
14802	
14803	      /* check feasibility */
14804	      if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14805	          (! SCIPsetIsInfinity(set,  row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14806	         break;
14807	   }
14808	
14809	   /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14810	   if( r < nlpirows )
14811	   {
14812	      /* get primal feasible point */
14813	      SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
14814	
14815	      /* check bounds of primal solution */
14816	      if( primalfeasible != NULL )
14817	      {
14818	         assert( *primalfeasible );
14819	         for( c = 0; c < nlpicols; ++c )
14820	         {
14821	            assert( lpicols[c] != NULL );
14822	            assert( lpicols[c]->var != NULL );
14823	
14824	            /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14825	             * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14826	            if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14827	               SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14828	            {
14829	               *primalfeasible = FALSE;
14830	               break;
14831	            }
14832	         }
14833	      }
14834	   }
14835	
14836	   /* compute activity and check feasibility of primal solution and ray */
14837	   for( r = 0; r < nlpirows; ++r )
14838	   {
14839	      SCIP_Real primact;
14840	      SCIP_Real rayact = 0.0;
14841	      SCIP_ROW* row;
14842	
14843	      row = lpirows[r];
14844	      assert( row != NULL );
14845	
14846	      primact = row->constant;
14847	
14848	      for( c = 0; c < row->nlpcols; ++c )
14849	      {
14850	         col = row->cols[c];
14851	
14852	         assert( col != NULL );
14853	         assert( col->lppos >= 0 );
14854	         assert( row->linkpos[c] >= 0 );
14855	         assert( primsol[col->lppos] != SCIP_INVALID );  /*lint !e777*/
14856	
14857	         primact += row->vals[c] * primsol[col->lppos];
14858	         rayact += row->vals[c] * ray[col->lppos];
14859	      }
14860	
14861	      if( row->nunlinked > 0 )
14862	      {
14863	         for( c = row->nlpcols; c < row->len; ++c )
14864	         {
14865	            col = row->cols[c];
14866	            assert( col != NULL );
14867	
14868	            if( col->lppos >= 0 )
14869	            {
14870	               primact += row->vals[c] * primsol[col->lppos];
14871	               rayact += row->vals[c] * ray[col->lppos];
14872	            }
14873	         }
14874	      }
14875	
14876	      /* check feasibility of primal solution */
14877	      if( primalfeasible != NULL && *primalfeasible )
14878	      {
14879	         if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14880	            ( ! SCIPsetIsInfinity(set,  row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14881	            *primalfeasible = FALSE;
14882	      }
14883	
14884	      /* check feasibility of ray */
14885	      if( rayfeasible != NULL && *rayfeasible )
14886	      {
14887	         if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14888	            ( ! SCIPsetIsInfinity(set,  row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14889	            *rayfeasible = FALSE;
14890	      }
14891	
14892	      /* store activity of primal solution */
14893	      activity[r] = primact;
14894	   }
14895	
14896	   if( primalfeasible != NULL && !(*primalfeasible) )
14897	   {
14898	      /* if the finite point is already infeasible, we do not have to add the ray */
14899	      rayscale = 0.0;
14900	   }
14901	   else if( rayfeasible != NULL && !(*rayfeasible) )
14902	   {
14903	      /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14904	      rayscale = 0.0;
14905	   }
14906	   else if( !SCIPsetIsNegative(set, rayobjval) )
14907	   {
14908	      /* due to numerical problems, the objective of the ray might be nonnegative
14909	       *
14910	       * @todo How to check for negative objective value here?
14911	       */
14912	      if( rayfeasible != NULL )
14913	         *rayfeasible = FALSE;
14914	
14915	      rayscale = 0.0;
14916	   }
14917	   else
14918	   {
14919	      assert(rayobjval != 0.0);
14920	
14921	      /* scale the ray, such that the resulting point has infinite objective value */
14922	      rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14923	      assert(SCIPsetIsFeasPositive(set, rayscale));
14924	
14925	      /* ensure that unbounded point does not violate the bounds of the variables */
14926	      for( c = 0; c < nlpicols; ++c )
14927	      {
14928	         if( SCIPsetIsPositive(set, ray[c]) )
14929	         {
14930	            if( !SCIPsetIsInfinity(set, primsol[c]) )
14931	               rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14932	            /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14933	            else
14934	            {
14935	               assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14936	               rayscale = MIN(rayscale, 1.0 / ray[c]);
14937	            }
14938	         }
14939	         else if( SCIPsetIsNegative(set, ray[c]) )
14940	         {
14941	            if( !SCIPsetIsInfinity(set, -primsol[c]) )
14942	               rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14943	            /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14944	            else
14945	            {
14946	               assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14947	               rayscale = MIN(rayscale, -1.0 / ray[c]);
14948	            }
14949	         }
14950	
14951	         assert(SCIPsetIsFeasPositive(set, rayscale));
14952	      }
14953	   }
14954	
14955	   SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14956	
14957	   /* calculate the unbounded point: x' = x + rayscale * ray */
14958	   /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14959	    * typically large values in scaling. */
14960	   for( c = 0; c < nlpicols; ++c )
14961	   {
14962	      if( SCIPsetIsZero(set, ray[c]) )
14963	         lpicols[c]->primsol = primsol[c];
14964	      else
14965	      {
14966	         SCIP_Real primsolval;
14967	         primsolval = primsol[c] + rayscale * ray[c];
14968	         lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14969	      }
14970	      lpicols[c]->redcost = SCIP_INVALID;
14971	      lpicols[c]->validredcostlp = -1;
14972	   }
14973	
14974	   /* transfer solution */
14975	   for( r = 0; r < nlpirows; ++r )
14976	   {
14977	      lpirows[r]->dualsol = SCIP_INVALID;
14978	      lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14979	      lpirows[r]->validactivitylp = lpcount;
14980	   }
14981	
14982	   /* free temporary memory */
14983	   SCIPsetFreeBufferArray(set, &ray);
14984	   SCIPsetFreeBufferArray(set, &activity);
14985	   SCIPsetFreeBufferArray(set, &primsol);
14986	
14987	   return SCIP_OKAY;
14988	}
14989	
14990	/** returns primal ray proving the unboundedness of the current LP */
14991	SCIP_RETCODE SCIPlpGetPrimalRay(
14992	   SCIP_LP*              lp,                 /**< current LP data */
14993	   SCIP_SET*             set,                /**< global SCIP settings */
14994	   SCIP_Real*            ray                 /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
14995	                                              *   so the size of this array should be at least number of active variables
14996	                                              *   (all entries have to be initialized to 0 before) */
14997	   )
14998	{
14999	   SCIP_COL** lpicols;
15000	   SCIP_Real* lpiray;
15001	   SCIP_VAR* var;
15002	   int nlpicols;
15003	   int c;
15004	
15005	   assert(lp != NULL);
15006	   assert(set != NULL);
15007	   assert(ray != NULL);
15008	   assert(lp->flushed);
15009	   assert(lp->solved);
15010	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
15011	   assert(SCIPsetIsInfinity(set, -lp->lpobjval));
15012	
15013	   /* check if the LP solver is able to provide a primal unbounded ray */
15014	   if( !SCIPlpiHasPrimalRay(lp->lpi) )
15015	   {
15016	      SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15017	      return SCIP_LPERROR;
15018	   }
15019	
15020	   /* get temporary memory */
15021	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lpiray, lp->nlpicols) );
15022	
15023	   SCIPsetDebugMsg(set, "getting primal ray values\n");
15024	
15025	   /* get primal unbounded ray */
15026	   SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15027	
15028	   lpicols = lp->lpicols;
15029	   nlpicols = lp->nlpicols;
15030	
15031	   /* store the ray values of active problem variables */
15032	   for( c = 0; c < nlpicols; c++ )
15033	   {
15034	      assert(lpicols[c] != NULL);
15035	
15036	      var = lpicols[c]->var;
15037	      assert(var != NULL);
15038	      assert(SCIPvarGetProbindex(var) != -1);
15039	      ray[SCIPvarGetProbindex(var)] = lpiray[c];
15040	   }
15041	
15042	   SCIPsetFreeBufferArray(set, &lpiray);
15043	
15044	   return SCIP_OKAY;
15045	}
15046	
15047	/** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15048	 *  lp/checkfarkas = TRUE.
15049	 *
15050	 *  @note the check will not be performed if @p valid is NULL.
15051	 */
15052	SCIP_RETCODE SCIPlpGetDualfarkas(
15053	   SCIP_LP*              lp,                 /**< current LP data */
15054	   SCIP_SET*             set,                /**< global SCIP settings */
15055	   SCIP_STAT*            stat,               /**< problem statistics */
15056	   SCIP_Bool*            valid               /**< pointer to store whether the Farkas proof is valid or NULL */
15057	   )
15058	{
15059	   SCIP_COL** lpicols;
15060	   SCIP_ROW** lpirows;
15061	   SCIP_Real* dualfarkas;
15062	   SCIP_Real* farkascoefs;
15063	   SCIP_Real farkaslhs;
15064	   SCIP_Real maxactivity;
15065	   SCIP_Bool checkfarkas;
15066	   int nlpicols;
15067	   int nlpirows;
15068	   int c;
15069	   int r;
15070	
15071	   assert(lp != NULL);
15072	   assert(lp->flushed);
15073	   assert(lp->solved);
15074	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
15075	   assert(set != NULL);
15076	   assert(stat != NULL);
15077	   assert(lp->validfarkaslp <= stat->lpcount);
15078	
15079	   if( valid != NULL )
15080	      *valid = TRUE;
15081	
15082	   /* check if the values are already calculated */
15083	   if( lp->validfarkaslp == stat->lpcount )
15084	      return SCIP_OKAY;
15085	   lp->validfarkaslp = stat->lpcount;
15086	
15087	   farkascoefs = NULL;
15088	   maxactivity = 0.0;
15089	   farkaslhs = 0.0;
15090	
15091	   checkfarkas = (set->lp_checkfarkas && valid != NULL);
15092	
15093	   /* get temporary memory */
15094	   SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15095	
15096	   if( checkfarkas )
15097	   {
15098	      SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15099	      BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15100	   }
15101	
15102	   /* get dual Farkas infeasibility proof */
15103	   SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15104	
15105	   lpicols = lp->lpicols;
15106	   lpirows = lp->lpirows;
15107	   nlpicols = lp->nlpicols;
15108	   nlpirows = lp->nlpirows;
15109	
15110	   /* store infeasibility proof in rows */
15111	   SCIPsetDebugMsg(set, "LP is infeasible:\n");
15112	   for( r = 0; r < nlpirows; ++r )
15113	   {
15114	      SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15115	      lpirows[r]->dualfarkas = dualfarkas[r];
15116	      lpirows[r]->dualsol = SCIP_INVALID;
15117	      lpirows[r]->activity = 0.0;
15118	      lpirows[r]->validactivitylp = -1L;
15119	      lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15120	
15121	      if( checkfarkas )
15122	      {
15123	         assert(farkascoefs != NULL);
15124	
15125	         /* the infeasibility proof would be invalid if
15126	          *   (i)  dualfarkas[r] > 0 and lhs = -inf
15127	          *   (ii) dualfarkas[r] < 0 and rhs = inf
15128	          * however, due to numerics we accept slightly negative / positive values
15129	          */
15130	         if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15131	            || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15132	         {
15133	            SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15134	               SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15135	
15136	            if( valid != NULL )
15137	               *valid = FALSE;
15138	
15139	            goto TERMINATE;
15140	         }
15141	
15142	         /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15143	          * within tolerances (see above) but slighty positive / negative
15144	          */
15145	         if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15146	            || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15147	            continue;
15148	
15149	         /* iterate over all columns and scale with dual solution */
15150	         for( c = 0; c < lpirows[r]->len; c++ )
15151	         {
15152	            int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15153	
15154	            if( pos == -1 )
15155	               continue;
15156	
15157	            assert(pos >= 0 && pos < nlpicols);
15158	
15159	            farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15160	         }
15161	
15162	         /* the row contributes with its left-hand side to the proof */
15163	         if( dualfarkas[r] > 0.0 )
15164	         {
15165	            assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15166	
15167	            farkaslhs += dualfarkas[r] * (lpirows[r]->lhs - lpirows[r]->constant);
15168	         }
15169	         /* the row contributes with its right-hand side to the proof */
15170	         else if( dualfarkas[r] < 0.0 )
15171	         {
15172	            assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15173	
15174	            farkaslhs += dualfarkas[r] * (lpirows[r]->rhs - lpirows[r]->constant);
15175	         }
15176	      }
15177	   }
15178	
15179	   /* set columns as invalid */
15180	   for( c = 0; c < nlpicols; ++c )
15181	   {
15182	      lpicols[c]->primsol = SCIP_INVALID;
15183	      lpicols[c]->redcost = SCIP_INVALID;
15184	      lpicols[c]->validredcostlp = -1L;
15185	      lpicols[c]->validfarkaslp = -1L;
15186	
15187	      if( checkfarkas )
15188	      {
15189	         assert(farkascoefs != NULL);
15190	         assert(SCIPcolGetLPPos(lpicols[c]) == c);
15191	
15192	         /* skip coefficients that are too close to zero */
15193	         if( SCIPsetIsFeasZero(set, farkascoefs[c]) )
15194	            continue;
15195	
15196	         /* calculate the maximal activity */
15197	         if( farkascoefs[c] > 0.0 )
15198	            maxactivity += farkascoefs[c] * SCIPcolGetUb(lpicols[c]);
15199	         else
15200	            maxactivity += farkascoefs[c] * SCIPcolGetLb(lpicols[c]);
15201	      }
15202	   }
15203	
15204	   /* check whether the farkasproof is valid
15205	    * due to numerics, it might happen that the left-hand side of the aggregation is larger/smaller or equal than +/- infinity.
15206	    * in that case, we declare the Farkas proof to be invalid.
15207	    */
15208	   if( checkfarkas && (SCIPsetIsInfinity(set, REALABS(farkaslhs)) || SCIPsetIsGE(set, maxactivity, farkaslhs)) )
15209	   {
15210	      SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15211	
15212	      if( valid != NULL )
15213	         *valid = FALSE;
15214	   }
15215	
15216	  TERMINATE:
15217	   /* free temporary memory */
15218	   if( checkfarkas )
15219	      SCIPsetFreeBufferArray(set, &farkascoefs);
15220	
15221	   SCIPsetFreeBufferArray(set, &dualfarkas);
15222	
15223	   return SCIP_OKAY;
15224	}
15225	
15226	/** get number of iterations used in last LP solve */
15227	SCIP_RETCODE SCIPlpGetIterations(
15228	   SCIP_LP*              lp,                 /**< current LP data */
15229	   int*                  iterations          /**< pointer to store the iteration count */
15230	   )
15231	{
15232	   assert(lp != NULL);
15233	
15234	   SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15235	
15236	   return SCIP_OKAY;
15237	}
15238	
15239	/** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15240	 *  resets age of non-zero columns and sharp rows
15241	 */
15242	SCIP_RETCODE SCIPlpUpdateAges(
15243	   SCIP_LP*              lp,                 /**< current LP data */
15244	   SCIP_STAT*            stat                /**< problem statistics */
15245	   )
15246	{
15247	   SCIP_COL** lpicols;
15248	   SCIP_ROW** lpirows;
15249	   int nlpicols;
15250	   int nlpirows;
15251	   int c;
15252	   int r;
15253	
15254	   assert(lp != NULL);
15255	   assert(lp->flushed);
15256	   assert(lp->solved);
15257	   assert(lp->nlpicols == lp->ncols);
15258	   assert(lp->nlpirows == lp->nrows);
15259	   assert(stat != NULL);
15260	   assert(lp->validsollp == stat->lpcount);
15261	
15262	   SCIPdebugMessage("updating LP ages\n");
15263	
15264	   lpicols = lp->lpicols;
15265	   lpirows = lp->lpirows;
15266	   nlpicols = lp->nlpicols;
15267	   nlpirows = lp->nlpirows;
15268	
15269	   for( c = 0; c < nlpicols; ++c )
15270	   {
15271	      assert(lpicols[c] == lp->cols[c]);
15272	      if( lpicols[c]->primsol == 0.0 )  /* non-basic columns to remove are exactly at 0.0 */
15273	         lpicols[c]->age++;
15274	      else
15275	         lpicols[c]->age = 0;
15276	      /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15277	        SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15278	   }
15279	
15280	   for( r = 0; r < nlpirows; ++r )
15281	   {
15282	      lpirows[r]->nlpsaftercreation++;
15283	      assert(lpirows[r] == lp->rows[r]);
15284	
15285	      if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15286	      {
15287	         lpirows[r]->age++;
15288	      }
15289	      else
15290	      {
15291	         lpirows[r]->activeinlpcounter++;
15292	         lpirows[r]->age = 0;
15293	      }
15294	      /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15295	   }
15296	
15297	   return SCIP_OKAY;
15298	}
15299	
15300	/* deletes the marked columns from the LP and the LP interface */
15301	static
15302	SCIP_RETCODE lpDelColset(
15303	   SCIP_LP*              lp,                 /**< current LP data */
15304	   SCIP_SET*             set,                /**< global SCIP settings */
15305	   int*                  coldstat            /**< deletion status of columns:  1 if column should be deleted, 0 if not */
15306	   )
15307	{
15308	   SCIP_COL* col;
15309	   int ncols;
15310	   int c;
15311	
15312	   assert(lp != NULL);
15313	   assert(lp->flushed);
15314	   assert(lp->ncols == lp->nlpicols);
15315	   assert(!lp->diving);
15316	   assert(coldstat != NULL);
15317	   assert(lp->nlazycols <= lp->ncols);
15318	
15319	   ncols = lp->ncols;
15320	
15321	   /* delete columns in LP solver */
15322	   SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15323	
15324	   /* update LP data respectively */
15325	   for( c = 0; c < ncols; ++c )
15326	   {
15327	      col = lp->cols[c];
15328	      assert(col != NULL);
15329	      assert(col == lp->lpicols[c]);
15330	      assert(coldstat[c] <= c);
15331	      col->lppos = coldstat[c];
15332	      if( coldstat[c] == -1 )
15333	      {
15334	         assert(col->removable);
15335	
15336	         /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15337	          * function vector norms
15338	          */
15339	         markColDeleted(col);
15340	         colUpdateDelLP(col, set);
15341	         lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15342	         col->lpdepth = -1;
15343	
15344	         lp->cols[c] = NULL;
15345	         lp->lpicols[c] = NULL;
15346	         lp->ncols--;
15347	         lp->nremovablecols--;
15348	         lp->nlpicols--;
15349	      }
15350	      else if( coldstat[c] < c )
15351	      {
15352	         assert(lp->cols[coldstat[c]] == NULL);
15353	         assert(lp->lpicols[coldstat[c]] == NULL);
15354	         lp->cols[coldstat[c]] = col;
15355	         lp->lpicols[coldstat[c]] = col;
15356	         lp->cols[coldstat[c]]->lppos = coldstat[c];
15357	         lp->cols[coldstat[c]]->lpipos = coldstat[c];
15358	         lp->cols[c] = NULL;
15359	         lp->lpicols[c] = NULL;
15360	      }
15361	   }
15362	
15363	   /* remove columns which are deleted from the lazy column array */
15364	   c = 0;
15365	   while( c < lp->nlazycols )
15366	   {
15367	      if( lp->lazycols[c]->lpipos < 0 )
15368	      {
15369	         lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15370	         lp->nlazycols--;
15371	      }
15372	      else
15373	         c++;
15374	   }
15375	
15376	   /* mark LP to be unsolved */
15377	   if( lp->ncols < ncols )
15378	   {
15379	      assert(lp->ncols == lp->nlpicols);
15380	      assert(lp->nchgcols == 0);
15381	      assert(lp->flushed);
15382	
15383	      lp->lpifirstchgcol = lp->nlpicols;
15384	
15385	      /* mark the current solution invalid */
15386	      lp->solved = FALSE;
15387	      lp->primalfeasible = FALSE;
15388	      lp->primalchecked = FALSE;
15389	      lp->lpobjval = SCIP_INVALID;
15390	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
15391	   }
15392	
15393	   checkLazyColArray(lp, set);
15394	   checkLinks(lp);
15395	
15396	   return SCIP_OKAY;
15397	}
15398	
15399	/* deletes the marked rows from the LP and the LP interface */
15400	static
15401	SCIP_RETCODE lpDelRowset(
15402	   SCIP_LP*              lp,                 /**< current LP data */
15403	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15404	   SCIP_SET*             set,                /**< global SCIP settings */
15405	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15406	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
15407	   int*                  rowdstat            /**< deletion status of rows:  1 if row should be deleted, 0 if not */
15408	   )
15409	{
15410	   SCIP_ROW* row;
15411	   int nrows;
15412	   int r;
15413	
15414	   assert(lp != NULL);
15415	   assert(lp->flushed);
15416	   assert(lp->nrows == lp->nlpirows);
15417	   assert(!lp->diving);
15418	   assert(rowdstat != NULL);
15419	
15420	   nrows = lp->nrows;
15421	
15422	   /* delete rows in LP solver */
15423	   SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15424	
15425	   /* update LP data respectively */
15426	   for( r = 0; r < nrows; ++r )
15427	   {
15428	      row = lp->rows[r];
15429	      assert(row == lp->lpirows[r]);
15430	      assert(rowdstat[r] <= r);
15431	      assert(row != NULL);
15432	      row->lppos = rowdstat[r];
15433	      if( rowdstat[r] == -1 )
15434	      {
15435	         if( row->removable )
15436	            lp->nremovablerows--;
15437	
15438	         /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15439	         markRowDeleted(row);
15440	         rowUpdateDelLP(row);
15441	         row->lpdepth = -1;
15442	
15443	         /* check, if row deletion events are tracked
15444	          * if so, issue ROWDELETEDLP event
15445	          */
15446	         if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15447	         {
15448	            SCIP_EVENT* event;
15449	
15450	            SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15451	            SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15452	         }
15453	
15454	         SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15455	         SCIProwUnlock(lp->rows[r]);
15456	         SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15457	         assert(lp->lpirows[r] == NULL);
15458	         assert(lp->rows[r] == NULL);
15459	         lp->nrows--;
15460	         lp->nlpirows--;
15461	      }
15462	      else if( rowdstat[r] < r )
15463	      {
15464	         assert(lp->rows[rowdstat[r]] == NULL);
15465	         assert(lp->lpirows[rowdstat[r]] == NULL);
15466	         lp->rows[rowdstat[r]] = row;
15467	         lp->lpirows[rowdstat[r]] = row;
15468	         lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15469	         lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15470	         lp->rows[r] = NULL;
15471	         lp->lpirows[r] = NULL;
15472	      }
15473	   }
15474	
15475	   /* mark LP to be unsolved */
15476	   if( lp->nrows < nrows )
15477	   {
15478	      assert(lp->nrows == lp->nlpirows);
15479	      assert(lp->nchgrows == 0);
15480	      assert(lp->flushed);
15481	
15482	      lp->lpifirstchgrow = lp->nlpirows;
15483	
15484	      /* mark the current solution invalid */
15485	      lp->solved = FALSE;
15486	      lp->dualfeasible = FALSE;
15487	      lp->dualchecked = FALSE;
15488	      lp->lpobjval = SCIP_INVALID;
15489	      lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
15490	   }
15491	
15492	   checkLinks(lp);
15493	
15494	   return SCIP_OKAY;
15495	}
15496	
15497	/** removes all non-basic columns, that are too old, beginning with the given firstcol */
15498	static
15499	SCIP_RETCODE lpRemoveObsoleteCols(
15500	   SCIP_LP*              lp,                 /**< current LP data */
15501	   SCIP_SET*             set,                /**< global SCIP settings */
15502	   SCIP_STAT*            stat,               /**< problem statistics */
15503	   int                   firstcol            /**< first column to check for clean up */
15504	   )
15505	{
15506	   SCIP_COL** cols;
15507	#ifndef NDEBUG
15508	   SCIP_COL** lpicols;
15509	#endif
15510	   int* coldstat;
15511	   int ncols;
15512	   int ndelcols;
15513	   int c;
15514	
15515	   assert(lp != NULL);
15516	   assert(lp->flushed);
15517	   assert(lp->ncols == lp->nlpicols);
15518	   assert(lp->nremovablecols <= lp->ncols);
15519	   assert(!lp->diving);
15520	   assert(set != NULL);
15521	   assert(stat != NULL);
15522	
15523	   if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15524	      return SCIP_OKAY;
15525	
15526	   ncols = lp->ncols;
15527	   cols = lp->cols;
15528	#ifndef NDEBUG
15529	   lpicols = lp->lpicols;
15530	#endif
15531	
15532	   /* get temporary memory */
15533	   SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15534	
15535	   /* mark obsolete columns to be deleted */
15536	   ndelcols = 0;
15537	   BMSclearMemoryArray(coldstat, ncols);
15538	   for( c = firstcol; c < ncols; ++c )
15539	   {
15540	      assert(cols[c] == lpicols[c]);
15541	      assert(cols[c]->lppos == c);
15542	      assert(cols[c]->lpipos == c);
15543	      if( cols[c]->removable
15544	         && cols[c]->obsoletenode != stat->nnodes /* don't remove column a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15545	         && cols[c]->age > set->lp_colagelimit
15546	         && (SCIP_BASESTAT)cols[c]->basisstatus != SCIP_BASESTAT_BASIC
15547	         && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15548	      {
15549	         assert(cols[c]->primsol == 0.0);
15550	         coldstat[c] = 1;
15551	         ndelcols++;
15552	         cols[c]->obsoletenode = stat->nnodes;
15553	         SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15554	            SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15555	      }
15556	   }
15557	
15558	   SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15559	
15560	   /* delete the marked columns in the LP solver interface, update the LP respectively */
15561	   if( ndelcols > 0 )
15562	   {
15563	      SCIP_CALL( lpDelColset(lp, set, coldstat) );
15564	   }
15565	   assert(lp->ncols == ncols - ndelcols);
15566	
15567	   /* release temporary memory */
15568	   SCIPsetFreeBufferArray(set, &coldstat);
15569	
15570	   return SCIP_OKAY;
15571	}
15572	
15573	/** removes all basic rows, that are too old, beginning with the given firstrow */
15574	static
15575	SCIP_RETCODE lpRemoveObsoleteRows(
15576	   SCIP_LP*              lp,                 /**< current LP data */
15577	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15578	   SCIP_SET*             set,                /**< global SCIP settings */
15579	   SCIP_STAT*            stat,               /**< problem statistics */
15580	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15581	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
15582	   int                   firstrow            /**< first row to check for clean up */
15583	   )
15584	{
15585	   SCIP_ROW** rows;
15586	#ifndef NDEBUG
15587	   SCIP_ROW** lpirows;
15588	#endif
15589	   int* rowdstat;
15590	   int nrows;
15591	   int ndelrows;
15592	   int r;
15593	
15594	   assert(lp != NULL);
15595	   assert(lp->flushed);
15596	   assert(lp->nrows == lp->nlpirows);
15597	   assert(lp->nremovablerows <= lp->nrows);
15598	   assert(!lp->diving);
15599	   assert(set != NULL);
15600	   assert(stat != NULL);
15601	
15602	   if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15603	      return SCIP_OKAY;
15604	
15605	   nrows = lp->nrows;
15606	   rows = lp->rows;
15607	#ifndef NDEBUG
15608	   lpirows = lp->lpirows;
15609	#endif
15610	
15611	   /* get temporary memory */
15612	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15613	
15614	   /* mark obsolete rows to be deleted */
15615	   ndelrows = 0;
15616	   BMSclearMemoryArray(rowdstat, nrows);
15617	   for( r = firstrow; r < nrows; ++r )
15618	   {
15619	      assert(rows[r] == lpirows[r]);
15620	      assert(rows[r]->lppos == r);
15621	      assert(rows[r]->lpipos == r);
15622	      if( rows[r]->removable
15623	         && rows[r]->obsoletenode != stat->nnodes  /* don't remove row a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15624	         && rows[r]->age > set->lp_rowagelimit
15625	         && (SCIP_BASESTAT)rows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15626	      {
15627	         rowdstat[r] = 1;
15628	         ndelrows++;
15629	         rows[r]->obsoletenode = stat->nnodes;
15630	         SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15631	            rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15632	      }
15633	   }
15634	
15635	   SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15636	
15637	   /* delete the marked rows in the LP solver interface, update the LP respectively */
15638	   if( ndelrows > 0 )
15639	   {
15640	      SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15641	   }
15642	   assert(lp->nrows == nrows - ndelrows);
15643	
15644	   /* release temporary memory */
15645	   SCIPsetFreeBufferArray(set, &rowdstat);
15646	
15647	   return SCIP_OKAY;
15648	}
15649	
15650	/** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15651	SCIP_RETCODE SCIPlpRemoveNewObsoletes(
15652	   SCIP_LP*              lp,                 /**< current LP data */
15653	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15654	   SCIP_SET*             set,                /**< global SCIP settings */
15655	   SCIP_STAT*            stat,               /**< problem statistics */
15656	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15657	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
15658	   )
15659	{
15660	   assert(lp != NULL);
15661	   assert(lp->solved);
15662	   assert(!lp->diving);
15663	   assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15664	   assert(set != NULL);
15665	
15666	   SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15667	      lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15668	
15669	   if( lp->firstnewcol < lp->ncols )
15670	   {
15671	      SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15672	   }
15673	   if( lp->firstnewrow < lp->nrows )
15674	   {
15675	      SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15676	   }
15677	
15678	   return SCIP_OKAY;
15679	}
15680	
15681	/** removes all non-basic columns and basic rows in whole LP, that are too old */
15682	SCIP_RETCODE SCIPlpRemoveAllObsoletes(
15683	   SCIP_LP*              lp,                 /**< current LP data */
15684	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15685	   SCIP_SET*             set,                /**< global SCIP settings */
15686	   SCIP_STAT*            stat,               /**< problem statistics */
15687	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15688	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
15689	   )
15690	{
15691	   assert(lp != NULL);
15692	   assert(lp->solved);
15693	   assert(!lp->diving);
15694	   assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15695	   assert(set != NULL);
15696	
15697	   SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15698	
15699	   if( 0 < lp->ncols )
15700	   {
15701	      SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15702	   }
15703	   if( 0 < lp->nrows )
15704	   {
15705	      SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15706	   }
15707	
15708	   return SCIP_OKAY;
15709	}
15710	
15711	/** removes all non-basic columns at 0.0 beginning with the given firstcol */
15712	static
15713	SCIP_RETCODE lpCleanupCols(
15714	   SCIP_LP*              lp,                 /**< current LP data */
15715	   SCIP_SET*             set,                /**< global SCIP settings */
15716	   SCIP_STAT*            stat,               /**< problem statistics */
15717	   int                   firstcol            /**< first column to check for clean up */
15718	   )
15719	{
15720	   SCIP_COL** cols;
15721	   SCIP_COL** lpicols;
15722	   int* coldstat;
15723	   int ncols;
15724	   int ndelcols;
15725	   int c;
15726	
15727	   assert(lp != NULL);
15728	   assert(lp->flushed);
15729	   assert(lp->ncols == lp->nlpicols);
15730	   assert(!lp->diving);
15731	   assert(stat != NULL);
15732	   assert(lp->validsollp == stat->lpcount);
15733	   assert(0 <= firstcol && firstcol < lp->ncols);
15734	
15735	   if( lp->nremovablecols == 0 || !lp->solisbasic )
15736	      return SCIP_OKAY;
15737	
15738	   ncols = lp->ncols;
15739	   cols = lp->cols;
15740	   lpicols = lp->lpicols;
15741	
15742	   /* get temporary memory */
15743	   SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15744	
15745	   /* mark unused columns to be deleted */
15746	   ndelcols = 0;
15747	   BMSclearMemoryArray(coldstat, ncols);
15748	   for( c = firstcol; c < ncols; ++c )
15749	   {
15750	      assert(cols[c] == lpicols[c]);
15751	      assert(cols[c]->lppos == c);
15752	      assert(cols[c]->lpipos == c);
15753	      if( lpicols[c]->removable
15754	         && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15755	         && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15756	         && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15757	      {
15758	         coldstat[c] = 1;
15759	         ndelcols++;
15760	      }
15761	   }
15762	
15763	   SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15764	
15765	   /* delete the marked columns in the LP solver interface, update the LP respectively */
15766	   if( ndelcols > 0 )
15767	   {
15768	      SCIP_CALL( lpDelColset(lp, set, coldstat) );
15769	   }
15770	   assert(lp->ncols == ncols - ndelcols);
15771	
15772	   /* release temporary memory */
15773	   SCIPsetFreeBufferArray(set, &coldstat);
15774	
15775	   return SCIP_OKAY;
15776	}
15777	
15778	/** removes all basic rows beginning with the given firstrow */
15779	static
15780	SCIP_RETCODE lpCleanupRows(
15781	   SCIP_LP*              lp,                 /**< current LP data */
15782	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15783	   SCIP_SET*             set,                /**< global SCIP settings */
15784	   SCIP_STAT*            stat,               /**< problem statistics */
15785	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15786	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
15787	   int                   firstrow            /**< first row to check for clean up */
15788	   )
15789	{
15790	#ifndef NDEBUG
15791	   SCIP_ROW** rows;
15792	#endif
15793	   SCIP_ROW** lpirows;
15794	   int* rowdstat;
15795	   int nrows;
15796	   int ndelrows;
15797	   int r;
15798	
15799	   assert(lp != NULL);
15800	   assert(lp->flushed);
15801	   assert(lp->ncols == lp->nlpicols);
15802	   assert(lp->nrows == lp->nlpirows);
15803	   assert(!lp->diving);
15804	   assert(stat != NULL);
15805	   assert(lp->validsollp == stat->lpcount);
15806	   assert(0 <= firstrow && firstrow < lp->nrows);
15807	
15808	   if( lp->nremovablerows == 0 || !lp->solisbasic  )
15809	      return SCIP_OKAY;
15810	
15811	#ifndef NDEBUG
15812	   rows = lp->rows;
15813	#endif
15814	   nrows = lp->nrows;
15815	   lpirows = lp->lpirows;
15816	
15817	   /* get temporary memory */
15818	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15819	
15820	   /* mark unused rows to be deleted */
15821	   ndelrows = 0;
15822	   BMSclearMemoryArray(rowdstat, nrows);
15823	   for( r = firstrow; r < nrows; ++r )
15824	   {
15825	      assert(rows[r] == lpirows[r]);
15826	      assert(rows[r]->lppos == r);
15827	      assert(rows[r]->lpipos == r);
15828	      if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15829	      {
15830	         rowdstat[r] = 1;
15831	         ndelrows++;
15832	      }
15833	   }
15834	
15835	   SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15836	
15837	   /* delete the marked rows in the LP solver interface, update the LP respectively */
15838	   if( ndelrows > 0 )
15839	   {
15840	      SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15841	   }
15842	   assert(lp->nrows == nrows - ndelrows);
15843	
15844	   /* release temporary memory */
15845	   SCIPsetFreeBufferArray(set, &rowdstat);
15846	
15847	   return SCIP_OKAY;
15848	}
15849	
15850	/** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15851	SCIP_RETCODE SCIPlpCleanupNew(
15852	   SCIP_LP*              lp,                 /**< current LP data */
15853	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15854	   SCIP_SET*             set,                /**< global SCIP settings */
15855	   SCIP_STAT*            stat,               /**< problem statistics */
15856	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15857	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
15858	   SCIP_Bool             root                /**< are we at the root node? */
15859	   )
15860	{
15861	   SCIP_Bool cleanupcols;
15862	   SCIP_Bool cleanuprows;
15863	
15864	   assert(lp != NULL);
15865	   assert(lp->solved);
15866	   assert(!lp->diving);
15867	   assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15868	   assert(set != NULL);
15869	
15870	   /* check, if we want to clean up the columns and rows */
15871	   cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15872	   cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15873	
15874	   SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15875	      lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15876	
15877	   if( cleanupcols && lp->firstnewcol < lp->ncols )
15878	   {
15879	      SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15880	   }
15881	   if( cleanuprows && lp->firstnewrow < lp->nrows )
15882	   {
15883	      SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15884	   }
15885	
15886	   return SCIP_OKAY;
15887	}
15888	
15889	/** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15890	SCIP_RETCODE SCIPlpCleanupAll(
15891	   SCIP_LP*              lp,                 /**< current LP data */
15892	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15893	   SCIP_SET*             set,                /**< global SCIP settings */
15894	   SCIP_STAT*            stat,               /**< problem statistics */
15895	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15896	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
15897	   SCIP_Bool             root                /**< are we at the root node? */
15898	   )
15899	{
15900	   SCIP_Bool cleanupcols;
15901	   SCIP_Bool cleanuprows;
15902	
15903	   assert(lp != NULL);
15904	   assert(lp->solved);
15905	   assert(!lp->diving);
15906	   assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
15907	   assert(set != NULL);
15908	
15909	   /* check, if we want to clean up the columns and rows */
15910	   cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15911	   cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15912	
15913	   SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15914	      cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15915	
15916	   if( cleanupcols && 0 < lp->ncols )
15917	   {
15918	      SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15919	   }
15920	   if( cleanuprows && 0 < lp->nrows )
15921	   {
15922	      SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15923	   }
15924	
15925	   return SCIP_OKAY;
15926	}
15927	
15928	/** removes all redundant rows that were added at the current node */
15929	SCIP_RETCODE SCIPlpRemoveRedundantRows(
15930	   SCIP_LP*              lp,                 /**< current LP data */
15931	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
15932	   SCIP_SET*             set,                /**< global SCIP settings */
15933	   SCIP_STAT*            stat,               /**< problem statistics */
15934	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
15935	   SCIP_EVENTFILTER*     eventfilter         /**< global event filter */
15936	   )
15937	{
15938	#ifndef NDEBUG
15939	   SCIP_ROW** rows;
15940	#endif
15941	   SCIP_ROW** lpirows;
15942	   int* rowdstat;
15943	   int nrows;
15944	   int ndelrows;
15945	   int r;
15946	
15947	   assert(lp != NULL);
15948	   assert(lp->flushed);
15949	   assert(lp->ncols == lp->nlpicols);
15950	   assert(lp->nrows == lp->nlpirows);
15951	   assert(!lp->diving);
15952	   assert(stat != NULL);
15953	   assert(lp->validsollp == stat->lpcount);
15954	   assert(lp->firstnewrow <= lp->nrows);
15955	
15956	   if( lp->firstnewrow == lp->nrows )
15957	      return SCIP_OKAY;
15958	
15959	#ifndef NDEBUG
15960	   rows = lp->rows;
15961	#endif
15962	   nrows = lp->nrows;
15963	   lpirows = lp->lpirows;
15964	
15965	   /* get temporary memory */
15966	   SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15967	
15968	   /* mark redundant rows to be deleted (only delete basic rows!) */
15969	   ndelrows = 0;
15970	   BMSclearMemoryArray(rowdstat, nrows);
15971	   for( r = lp->firstnewrow; r < nrows; ++r )
15972	   {
15973	      assert(rows[r] == lpirows[r]);
15974	      assert(rows[r]->lppos == r);
15975	      assert(rows[r]->lpipos == r);
15976	      if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
15977	         && SCIProwIsRedundant(lpirows[r], set, stat) )
15978	      {
15979	         SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
15980	            SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
15981	            SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
15982	         rowdstat[r] = 1;
15983	         ndelrows++;
15984	      }
15985	   }
15986	
15987	   SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
15988	
15989	   /* delete the marked rows in the LP solver interface, update the LP respectively */
15990	   if( ndelrows > 0 )
15991	   {
15992	      SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15993	   }
15994	   assert(lp->nrows == nrows - ndelrows);
15995	
15996	   /* release temporary memory */
15997	   SCIPsetFreeBufferArray(set, &rowdstat);
15998	
15999	   return SCIP_OKAY;
16000	}
16001	
16002	/** initiates LP diving */
16003	SCIP_RETCODE SCIPlpStartDive(
16004	   SCIP_LP*              lp,                 /**< current LP data */
16005	   BMS_BLKMEM*           blkmem,             /**< block memory */
16006	   SCIP_SET*             set,                /**< global SCIP settings */
16007	   SCIP_STAT*            stat                /**< problem statistics */
16008	   )
16009	{
16010	   int c;
16011	   int r;
16012	
16013	   assert(lp != NULL);
16014	   assert(lp->flushed || !lp->solved);
16015	   assert(!lp->diving);
16016	   assert(!lp->probing);
16017	   assert(lp->divelpistate == NULL);
16018	   assert(lp->divelpwasprimfeas);
16019	   assert(lp->divelpwasdualfeas);
16020	   assert(lp->validsollp <= stat->lpcount);
16021	   assert(blkmem != NULL);
16022	   assert(set != NULL);
16023	   assert(lp->ndivechgsides == 0);
16024	
16025	   SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16026	      lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16027	
16028	#ifndef NDEBUG
16029	   for( c = 0; c < lp->ncols; ++c )
16030	   {
16031	      assert(lp->cols[c] != NULL);
16032	      assert(lp->cols[c]->var != NULL);
16033	      assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16034	      assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16035	      assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16036	      assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16037	      assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16038	   }
16039	#endif
16040	
16041	   /* save current LPI state (basis information) */
16042	   SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16043	   lp->divelpwasprimfeas = lp->primalfeasible;
16044	   lp->divelpwasdualfeas = lp->dualfeasible;
16045	   lp->divelpwasprimchecked = lp->primalchecked;
16046	   lp->divelpwasdualchecked = lp->dualchecked;
16047	
16048	   /* save current LP values dependent on the solution */
16049	   SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16050	   assert(lp->storedsolvals != NULL);
16051	   if( !set->lp_resolverestore && lp->solved )
16052	   {
16053	      SCIP_Bool store = TRUE;
16054	
16055	      switch ( lp->lpsolstat )
16056	      {
16057	      case SCIP_LPSOLSTAT_OPTIMAL:
16058	         SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16059	         assert(lp->validsollp == stat->lpcount);
16060	         break;
16061	      case SCIP_LPSOLSTAT_UNBOUNDEDRAY:
16062	         SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) );
16063	         assert(lp->validsollp == stat->lpcount);
16064	         break;
16065	      case SCIP_LPSOLSTAT_OBJLIMIT:
16066	      case SCIP_LPSOLSTAT_ITERLIMIT:
16067	      case SCIP_LPSOLSTAT_TIMELIMIT:
16068	         SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16069	         assert(lp->validsollp == stat->lpcount);
16070	         break;
16071	      case SCIP_LPSOLSTAT_INFEASIBLE:
16072	         SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, NULL) );
16073	         break;
16074	      case SCIP_LPSOLSTAT_NOTSOLVED:
16075	      case SCIP_LPSOLSTAT_ERROR:
16076	      default:
16077	         store = FALSE;
16078	      }
16079	
16080	      if ( store )
16081	      {
16082	         for( c = 0; c < lp->ncols; ++c )
16083	         {
16084	            SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16085	         }
16086	         for( r = 0; r < lp->nrows; ++r )
16087	         {
16088	            SCIP_CALL( rowStoreSolVals(lp->rows[r], blkmem, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16089	         }
16090	      }
16091	   }
16092	
16093	   /* store LPI iteration limit */
16094	   SCIP_CALL( SCIPlpiGetIntpar(lp->lpi, SCIP_LPPAR_LPITLIM, &lp->divinglpiitlim) );
16095	
16096	   /* remember the number of domain changes */
16097	   lp->divenolddomchgs = stat->domchgcount;
16098	
16099	   /* store current number of rows */
16100	   lp->ndivingrows = lp->nrows;
16101	
16102	   /* switch to diving mode */
16103	   lp->diving = TRUE;
16104	
16105	   return SCIP_OKAY;
16106	}
16107	
16108	/** quits LP diving and resets bounds and objective values of columns to the current node's values */
16109	SCIP_RETCODE SCIPlpEndDive(
16110	   SCIP_LP*              lp,                 /**< current LP data */
16111	   BMS_BLKMEM*           blkmem,             /**< block memory */
16112	   SCIP_SET*             set,                /**< global SCIP settings */
16113	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
16114	   SCIP_STAT*            stat,               /**< problem statistics */
16115	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
16116	   SCIP_EVENTFILTER*     eventfilter,        /**< global event filter */
16117	   SCIP_PROB*            prob,               /**< problem data */
16118	   SCIP_VAR**            vars,               /**< array with all active variables */
16119	   int                   nvars               /**< number of active variables */
16120	   )
16121	{
16122	   SCIP_VAR* var;
16123	   int v;
16124	
16125	   assert(lp != NULL);
16126	   assert(lp->diving);
16127	   assert(blkmem != NULL);
16128	   assert(nvars == 0 || vars != NULL);
16129	
16130	   SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16131	
16132	   /* reset all columns' objective values and bounds to its original values */
16133	   for( v = 0; v < nvars; ++v )
16134	   {
16135	      var = vars[v];
16136	      assert(var != NULL);
16137	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
16138	      {
16139	         SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, SCIPvarGetObj(var)) );
16140	         SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, SCIPvarGetLbLocal(var)) );
16141	         SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, SCIPvarGetUbLocal(var)) );
16142	      }
16143	   }
16144	
16145	   /* remove rows which were added in diving mode */
16146	   SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16147	
16148	   /* undo changes to left hand sides and right hand sides */
16149	   while( lp->ndivechgsides > 0 )
16150	   {
16151	      SCIP_Real oldside;
16152	      SCIP_SIDETYPE sidetype;
16153	      SCIP_ROW* row;
16154	
16155	      lp->ndivechgsides--;
16156	      oldside = lp->divechgsides[lp->ndivechgsides];
16157	      sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16158	      row = lp->divechgrows[lp->ndivechgsides];
16159	
16160	      if( sidetype == SCIP_SIDETYPE_LEFT )
16161	      {
16162	         SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16163	      }
16164	      else
16165	      {
16166	         SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16167	      }
16168	   }
16169	
16170	   /* restore LPI iteration limit */
16171	   SCIP_CALL( lpSetIterationLimit(lp, lp->divinglpiitlim) );
16172	
16173	   /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16174	    * happens
16175	    */
16176	   SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16177	         lp->divelpwasprimfeas, lp->divelpwasprimchecked, lp->divelpwasdualfeas, lp->divelpwasdualchecked) );
16178	   SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16179	   lp->divelpwasprimfeas = TRUE;
16180	   lp->divelpwasdualfeas = TRUE;
16181	   lp->divelpwasprimchecked = TRUE;
16182	   lp->divelpwasdualchecked = TRUE;
16183	   assert(lp->divelpistate == NULL);
16184	
16185	   /* switch to standard (non-diving) mode */
16186	   lp->diving = FALSE;
16187	   lp->divingobjchg = FALSE;
16188	
16189	   /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16190	    * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16191	    * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16192	    * the parameter resolverestore to TRUE
16193	    * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16194	    */
16195	   assert(lp->storedsolvals != NULL);
16196	   if( lp->storedsolvals->lpissolved
16197	      && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16198	   {
16199	      SCIP_Bool lperror;
16200	
16201	      SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr,  blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) );
16202	      if( lperror )
16203	      {
16204	         lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16205	         lp->resolvelperror = TRUE;
16206	      }
16207	      else if( SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL
16208	         && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_INFEASIBLE
16209	         && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_UNBOUNDEDRAY
16210	         && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OBJLIMIT )
16211	      {
16212	         SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16213	            "LP was not resolved to a sufficient status after diving\n");
16214	         lp->resolvelperror = TRUE;
16215	      }
16216	   }
16217	   /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16218	    * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16219	    * re-solve as above can lead to a different LP status
16220	    */
16221	   else
16222	   {
16223	      int c;
16224	      int r;
16225	
16226	      /* if there are lazy bounds, remove them from the LP */
16227	      if( lp->nlazycols > 0 )
16228	      {
16229	         /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16230	          * first resolve LP?
16231	          */
16232	         SCIP_CALL( updateLazyBounds(lp, set) );
16233	         assert(lp->diving == lp->divinglazyapplied);
16234	
16235	         /* flush changes to the LP solver */
16236	         SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16237	      }
16238	
16239	      /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16240	      SCIPstatIncrement(stat, set, lpcount);
16241	
16242	      /* restore LP solution values in lp data, columns and rows */
16243	      if( lp->storedsolvals->lpissolved &&
16244	         (lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
16245	            lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY ||
16246	            lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT ||
16247	            lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT ||
16248	            lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT ||
16249	            lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE)
16250	         )
16251	      {
16252	         SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16253	
16254	         for( c = 0; c < lp->ncols; ++c )
16255	         {
16256	            SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16257	         }
16258	         for( r = 0; r < lp->nrows; ++r )
16259	         {
16260	            SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16261	         }
16262	      }
16263	      else
16264	      {
16265	         SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16266	      }
16267	   }
16268	
16269	#ifndef NDEBUG
16270	   {
16271	      int c;
16272	      for( c = 0; c < lp->ncols; ++c )
16273	      {
16274	         assert(lp->cols[c] != NULL);
16275	         assert(lp->cols[c]->var != NULL);
16276	         assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16277	         assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16278	         assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16279	         assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16280	         assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16281	      }
16282	   }
16283	#endif
16284	
16285	   return SCIP_OKAY;
16286	}
16287	
16288	#define DIVESTACKGROWFACT 1.5
16289	
16290	/** records a current row side such that any change will be undone after diving */
16291	SCIP_RETCODE SCIPlpRecordOldRowSideDive(
16292	   SCIP_LP*              lp,                 /**< LP data object */
16293	   SCIP_ROW*             row,                /**< row affected by the change */
16294	   SCIP_SIDETYPE         sidetype            /**< side type */
16295	   )
16296	{
16297	   assert(lp != NULL);
16298	   assert(row != NULL);
16299	
16300	   if( lp->ndivechgsides == lp->divechgsidessize )
16301	   {
16302	      SCIP_CALL( reallocDiveChgSideArrays(lp, lp->divechgsidessize + 1, DIVESTACKGROWFACT) );
16303	   }
16304	   assert(lp->ndivechgsides < lp->divechgsidessize);
16305	
16306	   lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16307	   lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16308	   lp->divechgrows[lp->ndivechgsides] = row;
16309	   lp->ndivechgsides++;
16310	
16311	   return SCIP_OKAY;
16312	}
16313	
16314	/** informs the LP that probing mode was initiated */
16315	SCIP_RETCODE SCIPlpStartProbing(
16316	   SCIP_LP*              lp                  /**< current LP data */
16317	   )
16318	{
16319	   assert(lp != NULL);
16320	   assert(!lp->probing);
16321	   assert(!lp->strongbranching);
16322	   assert(!lp->strongbranchprobing);
16323	
16324	   lp->probing = TRUE;
16325	
16326	   return SCIP_OKAY;
16327	}
16328	
16329	/** informs the LP that probing mode was finished */
16330	SCIP_RETCODE SCIPlpEndProbing(
16331	   SCIP_LP*              lp                  /**< current LP data */
16332	   )
16333	{
16334	   assert(lp != NULL);
16335	   assert(lp->probing);
16336	   assert(!lp->strongbranching);
16337	   assert(!lp->strongbranchprobing);
16338	
16339	   lp->probing = FALSE;
16340	
16341	   return SCIP_OKAY;
16342	}
16343	
16344	/** informs the LP that the probing mode is now used for strongbranching */
16345	void SCIPlpStartStrongbranchProbing(
16346	   SCIP_LP*              lp                  /**< current LP data */
16347	   )
16348	{
16349	   assert(lp != NULL);
16350	   assert(lp->probing);
16351	   assert(!lp->strongbranching);
16352	   assert(!lp->strongbranchprobing);
16353	
16354	   lp->strongbranchprobing = TRUE;
16355	}
16356	
16357	/** informs the LP that the probing mode is not used for strongbranching anymore */
16358	void SCIPlpEndStrongbranchProbing(
16359	   SCIP_LP*              lp                  /**< current LP data */
16360	   )
16361	{
16362	   assert(lp != NULL);
16363	   assert(lp->probing);
16364	   assert(!lp->strongbranching);
16365	   assert(lp->strongbranchprobing);
16366	
16367	   lp->strongbranchprobing = FALSE;
16368	}
16369	
16370	/** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16371	 *  the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16372	 *  Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16373	 *  we have only left hand sides):
16374	 *           min{cx       |  b <=  Ax, lb <= x <= ub}
16375	 *   >=      min{cx       | yb <= yAx, lb <= x <= ub}   (restriction in minimum is relaxed)
16376	 *   == yb + min{cx - yb  | yb <= yAx, lb <= x <= ub}   (added yb - yb == 0)
16377	 *   >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub}   (because yAx >= yb inside minimum)
16378	 *   >= yb + min{cx - yAx |            lb <= x <= ub}   (restriction in minimum is relaxed)
16379	 */
16380	static
16381	SCIP_RETCODE provedBound(
16382	   SCIP_LP*              lp,                 /**< current LP data */
16383	   SCIP_SET*             set,                /**< global SCIP settings */
16384	   SCIP_Bool             usefarkas,          /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16385	   SCIP_Real*            bound               /**< result of interval arithmetic minimization */
16386	   )
16387	{
16388	   SCIP_INTERVAL* yinter;
16389	   SCIP_INTERVAL b;
16390	   SCIP_INTERVAL ytb;
16391	   SCIP_INTERVAL prod;
16392	   SCIP_INTERVAL diff;
16393	   SCIP_INTERVAL x;
16394	   SCIP_INTERVAL minprod;
16395	   SCIP_INTERVAL a;
16396	   SCIP_ROW* row;
16397	   SCIP_COL* col;
16398	   SCIP_Real y;
16399	   SCIP_Real c;
16400	   int i;
16401	   int j;
16402	
16403	   assert(lp != NULL);
16404	   assert(lp->solved);
16405	   assert(set != NULL);
16406	   assert(bound != NULL);
16407	
16408	   /* allocate buffer for storing y in interval arithmetic */
16409	   SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16410	
16411	   /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16412	   SCIPintervalSet(&ytb, 0.0);
16413	   for( j = 0; j < lp->nrows; ++j )
16414	   {
16415	      row = lp->rows[j];
16416	      assert(row != NULL);
16417	
16418	      y = (usefarkas ? row->dualfarkas : row->dualsol);
16419	
16420	      if( SCIPsetIsFeasPositive(set, y) )
16421	      {
16422	         SCIPintervalSet(&yinter[j], y);
16423	         SCIPintervalSet(&b, row->lhs - row->constant);
16424	      }
16425	      else if( SCIPsetIsFeasNegative(set, y) )
16426	      {
16427	         SCIPintervalSet(&yinter[j], y);
16428	         SCIPintervalSet(&b, row->rhs - row->constant);
16429	      }
16430	      else
16431	      {
16432	         SCIPintervalSet(&yinter[j], 0.0);
16433	         SCIPintervalSet(&b, 0.0);
16434	      }
16435	
16436	      SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16437	      SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16438	   }
16439	
16440	   /* calculate min{(c^T - y^TA)x} */
16441	   SCIPintervalSet(&minprod, 0.0);
16442	   for( j = 0; j < lp->ncols; ++j )
16443	   {
16444	      col = lp->cols[j];
16445	      assert(col != NULL);
16446	      assert(col->nunlinked == 0);
16447	
16448	      SCIPintervalSetBounds(&x, SCIPcolGetLb(col), SCIPcolGetUb(col));
16449	
16450	      c = usefarkas ? 0.0 : col->obj;
16451	      SCIPintervalSet(&diff, c);
16452	
16453	      for( i = 0; i < col->nlprows; ++i )
16454	      {
16455	         assert(col->rows[i] != NULL);
16456	         assert(col->rows[i]->lppos >= 0);
16457	         assert(col->linkpos[i] >= 0);
16458	         SCIPintervalSet(&a, col->vals[i]);
16459	         SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16460	         SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16461	      }
16462	
16463	#ifndef NDEBUG
16464	      for( i = col->nlprows; i < col->len; ++i )
16465	      {
16466	         assert(col->rows[i] != NULL);
16467	         assert(col->rows[i]->lppos == -1);
16468	         assert(col->rows[i]->dualsol == 0.0);
16469	         assert(col->rows[i]->dualfarkas == 0.0);
16470	         assert(col->linkpos[i] >= 0);
16471	      }
16472	#endif
16473	
16474	      SCIPintervalSetBounds(&x, col->lb, col->ub);
16475	      SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16476	      SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16477	   }
16478	
16479	   /* add y^Tb */
16480	   SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16481	
16482	   /* free buffer for storing y in interval arithmetic */
16483	   SCIPsetFreeBufferArray(set, &yinter);
16484	
16485	   *bound = SCIPintervalGetInf(minprod);
16486	
16487	   return SCIP_OKAY;
16488	}
16489	
16490	/** gets proven lower (dual) bound of last LP solution */
16491	SCIP_RETCODE SCIPlpGetProvedLowerbound(
16492	   SCIP_LP*              lp,                 /**< current LP data */
16493	   SCIP_SET*             set,                /**< global SCIP settings */
16494	   SCIP_Real*            bound               /**< pointer to store proven dual bound */
16495	   )
16496	{
16497	   SCIP_CALL( provedBound(lp, set, FALSE, bound) );
16498	
16499	   SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16500	
16501	   return SCIP_OKAY;
16502	}
16503	
16504	/** gets proven dual bound of last LP solution */
16505	SCIP_RETCODE SCIPlpIsInfeasibilityProved(
16506	   SCIP_LP*              lp,                 /**< current LP data */
16507	   SCIP_SET*             set,                /**< global SCIP settings */
16508	   SCIP_Bool*            proved              /**< pointer to store whether infeasibility is proven */
16509	   )
16510	{
16511	   SCIP_Real bound;
16512	
16513	   assert(proved != NULL);
16514	
16515	   SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16516	
16517	   *proved = (bound > 0.0);
16518	
16519	   SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16520	
16521	   return SCIP_OKAY;
16522	}
16523	
16524	
16525	
16526	/** writes LP to a file */
16527	SCIP_RETCODE SCIPlpWrite(
16528	   SCIP_LP*              lp,                 /**< current LP data */
16529	   const char*           fname               /**< file name */
16530	   )
16531	{
16532	   assert(lp != NULL);
16533	   assert(lp->flushed);
16534	   assert(fname != NULL);
16535	
16536	   SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16537	
16538	   return SCIP_OKAY;
16539	}
16540	
16541	/** writes MIP relaxation of the current B&B node to a file */
16542	SCIP_RETCODE SCIPlpWriteMip(
16543	   SCIP_LP*              lp,                 /**< current LP data */
16544	   SCIP_SET*             set,                /**< global SCIP settings */
16545	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
16546	   const char*           fname,              /**< file name */
16547	   SCIP_Bool             genericnames,       /**< should generic names like x_i and row_j be used in order to avoid
16548	                                              *   troubles with reserved symbols? */
16549	   SCIP_Bool             origobj,            /**< should the original objective function be used? */
16550	   SCIP_OBJSENSE         objsense,           /**< objective sense */
16551	   SCIP_Real             objscale,           /**< objective scaling factor */
16552	   SCIP_Real             objoffset,          /**< objective offset, e.g., caused by variable fixings in presolving */
16553	   SCIP_Bool             lazyconss           /**< output removable rows as lazy constraints? */
16554	   )
16555	{
16556	   FILE* file;
16557	   int i;
16558	   int j;
16559	   char rowname[SCIP_MAXSTRLEN];
16560	   SCIP_Real coeff;
16561	
16562	   assert(lp != NULL);
16563	   assert(lp->flushed);
16564	   assert(fname != NULL);
16565	
16566	   SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16567	   file = fopen(fname, "w");
16568	   if( file == NULL )
16569	   {
16570	      SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16571	      SCIPprintSysError(fname);
16572	      return SCIP_FILECREATEERROR;
16573	   }
16574	
16575	   /* print comments */
16576	   if( genericnames )
16577	      SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16578	   else
16579	   {
16580	      SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16581	      SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16582	   }
16583	
16584	   if( origobj && objoffset != 0.0 )
16585	   {
16586	      SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16587	      SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16588	   }
16589	
16590	   /* print objective function */
16591	   /**@note the transformed problem in SCIP is always a minimization problem */
16592	   if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16593	      SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16594	   else
16595	      SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16596	
16597	   /* print objective */
16598	   SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16599	   j = 0;
16600	   for( i = 0; i < lp->ncols; ++i )
16601	   {
16602	      if( lp->cols[i]->obj != 0.0 )
16603	      {
16604	         coeff = lp->cols[i]->obj;
16605	         if( origobj )
16606	         {
16607	            coeff *= (SCIP_Real) objsense;
16608	            coeff *= objscale;
16609	         }
16610	
16611	         if( genericnames )
16612	            SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16613	         else
16614	            SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16615	
16616	         ++j;
16617	         if( j % 10 == 0 )
16618	            SCIPmessageFPrintInfo(messagehdlr, file, "\n     ");
16619	      }
16620	   }
16621	   /* add artificial variable 'objoffset' to transfer objective offset */
16622	   if( origobj && objoffset != 0.0 )
16623	      SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16624	
16625	   /* print constraint section */
16626	   SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16627	   for( i = 0; i < lp->nrows; i++ )
16628	   {
16629	      char type = 'i';
16630	
16631	      /* skip removable rows if we want to write them as lazy constraints */
16632	      if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16633	         continue;
16634	
16635	      /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16636	       * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16637	       * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16638	       * type 'i' means: lhs and rhs are both infinite */
16639	      if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16640	         type = 'r';
16641	      else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16642	         type = 'l';
16643	      else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16644	         type = 'e';
16645	      else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16646	         type = 'b';
16647	
16648	      /* print name of row */
16649	      if( genericnames )
16650	         (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16651	      else
16652	         (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16653	
16654	   WRITEROW:
16655	      switch( type )
16656	      {
16657	      case 'r':
16658	      case 'l':
16659	      case 'e':
16660	         if( strlen(rowname) > 0 )
16661	            SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16662	         break;
16663	      case 'i':
16664	         SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16665	         SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16666	         SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16667	         type = 'b';
16668	         /*lint -fallthrough*/
16669	      case 'b':
16670	         SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16671	         break;
16672	      default:
16673	         assert(type == 'B');
16674	         SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16675	         break;
16676	      }
16677	
16678	      /* print coefficients and variables */
16679	      for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16680	      {
16681	         if( genericnames )
16682	            SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16683	         else
16684	            SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16685	
16686	         if( (j+1) % 10 == 0 )
16687	            SCIPmessageFPrintInfo(messagehdlr, file, "\n          ");
16688	      }
16689	
16690	      /* print right hand side */
16691	      switch( type )
16692	      {
16693	      case 'b':
16694	         SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16695	         type = 'B';
16696	         goto WRITEROW;
16697	      case 'l':
16698	         SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16699	         break;
16700	      case 'B':
16701	      case 'r':
16702	         SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16703	         break;
16704	      case 'e':
16705	         SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16706	         break;
16707	      default:
16708	         SCIPerrorMessage("Undefined row type!\n");
16709	         fclose(file);
16710	         return SCIP_ERROR;
16711	      }
16712	   }
16713	
16714	   if ( lazyconss )
16715	   {
16716	      /* print lazy constraint section */
16717	      SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16718	      for( i = 0; i < lp->nrows; i++ )
16719	      {
16720	         char type = 'i';
16721	
16722	         /* skip non-removable rows if we want to write lazy constraints */
16723	         if ( ! SCIProwIsRemovable(lp->rows[i]) )
16724	            continue;
16725	
16726	         /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16727	          * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16728	          * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16729	          * type 'i' means: lhs and rhs are both infinite */
16730	         if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16731	            type = 'r';
16732	         else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16733	            type = 'l';
16734	         else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16735	            type = 'e';
16736	         else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16737	            type = 'b';
16738	
16739	         /* print name of row */
16740	         if( genericnames )
16741	            (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16742	         else
16743	            (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16744	
16745	      WRITELAZYROW:
16746	         switch( type )
16747	         {
16748	         case 'r':
16749	         case 'l':
16750	         case 'e':
16751	            if( strlen(rowname) > 0 )
16752	               SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16753	            break;
16754	         case 'i':
16755	            SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16756	            SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16757	            SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16758	            type = 'b';
16759	            /*lint -fallthrough*/
16760	         case 'b':
16761	            SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16762	            break;
16763	         default:
16764	            assert(type == 'B');
16765	            SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16766	            break;
16767	         }
16768	
16769	         /* print coefficients and variables */
16770	         for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16771	         {
16772	            if( genericnames )
16773	               SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16774	            else
16775	               SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16776	
16777	            if( (j+1) % 10 == 0 )
16778	               SCIPmessageFPrintInfo(messagehdlr, file, "\n          ");
16779	         }
16780	
16781	         /* print right hand side */
16782	         switch( type )
16783	         {
16784	         case 'b':
16785	            SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16786	            type = 'B';
16787	            goto WRITELAZYROW;
16788	         case 'l':
16789	            SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16790	            break;
16791	         case 'B':
16792	         case 'r':
16793	            SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16794	            break;
16795	         case 'e':
16796	            SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16797	            break;
16798	         default:
16799	            SCIPerrorMessage("Undefined row type!\n");
16800	            fclose(file);
16801	            return SCIP_ERROR;
16802	         }
16803	      }
16804	   }
16805	
16806	   /* print variable bounds */
16807	   SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16808	   for( i = 0; i < lp->ncols; ++i )
16809	   {
16810	      if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16811	      {
16812	         /* print lower bound as far this one is not infinity */
16813	         if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16814	            SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16815	
16816	         /* print variable name */
16817	         if( genericnames )
16818	            SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16819	         else
16820	            SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16821	
16822	         /* print upper bound as far this one is not infinity */
16823	         if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16824	            SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16825	         SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16826	      }
16827	   }
16828	   if( origobj && objoffset != 0.0 )
16829	      SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16830	
16831	   /* print integer variables */
16832	   SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16833	   j = 0;
16834	   for( i = 0; i < lp->ncols; ++i )
16835	   {
16836	      if( SCIPvarIsIntegral(lp->cols[i]->var) )
16837	      {
16838	         /* print variable name */
16839	         if( genericnames )
16840	            SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16841	         else
16842	            SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16843	
16844	         j++;
16845	         if( j % 10 == 0 )
16846	            SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16847	      }
16848	   }
16849	
16850	   SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16851	   fclose(file);
16852	
16853	   return SCIP_OKAY;
16854	}
16855	
16856	/*
16857	 * simple functions implemented as defines
16858	 */
16859	
16860	/* In debug mode, the following methods are implemented as function calls to ensure
16861	 * type validity.
16862	 * In optimized mode, the methods are implemented as defines to improve performance.
16863	 * However, we want to have them in the library anyways, so we have to undef the defines.
16864	 */
16865	
16866	#undef SCIPcolGetObj
16867	#undef SCIPcolGetLb
16868	#undef SCIPcolGetUb
16869	#undef SCIPcolGetBestBound
16870	#undef SCIPcolGetPrimsol
16871	#undef SCIPcolGetMinPrimsol
16872	#undef SCIPcolGetMaxPrimsol
16873	#undef SCIPcolGetBasisStatus
16874	#undef SCIPcolGetVar
16875	#undef SCIPcolGetIndex
16876	#undef SCIPcolGetVarProbindex
16877	#undef SCIPcolIsIntegral
16878	#undef SCIPcolIsRemovable
16879	#undef SCIPcolGetLPPos
16880	#undef SCIPcolGetLPDepth
16881	#undef SCIPcolIsInLP
16882	#undef SCIPcolGetNNonz
16883	#undef SCIPcolGetNLPNonz
16884	#undef SCIPcolGetRows
16885	#undef SCIPcolGetVals
16886	#undef SCIPcolGetStrongbranchNode
16887	#undef SCIPcolGetNStrongbranchs
16888	#undef SCIPcolGetAge
16889	#undef SCIPboundtypeOpposite
16890	#undef SCIProwGetNNonz
16891	#undef SCIProwGetNLPNonz
16892	#undef SCIProwGetCols
16893	#undef SCIProwGetVals
16894	#undef SCIProwGetConstant
16895	#undef SCIProwGetNorm
16896	#undef SCIProwGetSumNorm
16897	#undef SCIProwGetLhs
16898	#undef SCIProwGetRhs
16899	#undef SCIProwGetDualsol
16900	#undef SCIProwGetDualfarkas
16901	#undef SCIProwGetBasisStatus
16902	#undef SCIProwGetName
16903	#undef SCIProwGetIndex
16904	#undef SCIProwGetAge
16905	#undef SCIProwGetRank
16906	#undef SCIProwIsIntegral
16907	#undef SCIProwIsLocal
16908	#undef SCIProwIsModifiable
16909	#undef SCIProwIsRemovable
16910	#undef SCIProwGetOrigintype
16911	#undef SCIProwGetOriginCons
16912	#undef SCIProwGetOriginConshdlr
16913	#undef SCIProwGetOriginSepa
16914	#undef SCIProwIsInGlobalCutpool
16915	#undef SCIProwGetLPPos
16916	#undef SCIProwGetLPDepth
16917	#undef SCIProwIsInLP
16918	#undef SCIProwGetActiveLPCount
16919	#undef SCIProwGetNLPsAfterCreation
16920	#undef SCIProwChgRank
16921	#undef SCIPlpGetCols
16922	#undef SCIPlpGetNCols
16923	#undef SCIPlpGetRows
16924	#undef SCIPlpGetNRows
16925	#undef SCIPlpGetNewcols
16926	#undef SCIPlpGetNNewcols
16927	#undef SCIPlpGetNewrows
16928	#undef SCIPlpGetNNewrows
16929	#undef SCIPlpGetObjNorm
16930	#undef SCIPlpGetRootObjval
16931	#undef SCIPlpGetRootColumnObjval
16932	#undef SCIPlpGetRootLooseObjval
16933	#undef SCIPlpGetLPI
16934	#undef SCIPlpSetIsRelax
16935	#undef SCIPlpIsRelax
16936	#undef SCIPlpIsSolved
16937	#undef SCIPlpIsSolBasic
16938	#undef SCIPlpDiving
16939	#undef SCIPlpDivingObjChanged
16940	#undef SCIPlpMarkDivingObjChanged
16941	#undef SCIPlpUnmarkDivingObjChanged
16942	#undef SCIPlpDivingRowsChanged
16943	#undef SCIPlpIsFeasEQ
16944	#undef SCIPlpIsFeasLT
16945	#undef SCIPlpIsFeasLE
16946	#undef SCIPlpIsFeasGT
16947	#undef SCIPlpIsFeasGE
16948	#undef SCIPlpIsFeasZero
16949	#undef SCIPlpIsFeasPositive
16950	#undef SCIPlpIsFeasNegative
16951	
16952	/** gets objective value of column */
16953	SCIP_Real SCIPcolGetObj(
16954	   SCIP_COL*             col                 /**< LP column */
16955	   )
16956	{
16957	   assert(col != NULL);
16958	
16959	   return col->obj;
16960	}
16961	
16962	/** gets lower bound of column */
16963	SCIP_Real SCIPcolGetLb(
16964	   SCIP_COL*             col                 /**< LP column */
16965	   )
16966	{
16967	   assert(col != NULL);
16968	
16969	   return col->lb;
16970	}
16971	
16972	/** gets upper bound of column */
16973	SCIP_Real SCIPcolGetUb(
16974	   SCIP_COL*             col                 /**< LP column */
16975	   )
16976	{
16977	   assert(col != NULL);
16978	
16979	   return col->ub;
16980	}
16981	
16982	/** gets best bound of column with respect to the objective function */
16983	SCIP_Real SCIPcolGetBestBound(
16984	   SCIP_COL*             col                 /**< LP column */
16985	   )
16986	{
16987	   assert(col != NULL);
16988	
16989	   if( col->obj >= 0.0 )
16990	      return col->lb;
16991	   else
16992	      return col->ub;
16993	}
16994	
16995	/** gets the primal LP solution of a column */
16996	SCIP_Real SCIPcolGetPrimsol(
16997	   SCIP_COL*             col                 /**< LP column */
16998	   )
16999	{
17000	   assert(col != NULL);
17001	
17002	   if( col->lppos >= 0 )
17003	      return col->primsol;
17004	   else
17005	      return 0.0;
17006	}
17007	
17008	/** gets the minimal LP solution value, this column ever assumed */
17009	SCIP_Real SCIPcolGetMinPrimsol(
17010	   SCIP_COL*             col                 /**< LP column */
17011	   )
17012	{
17013	   assert(col != NULL);
17014	
17015	   return col->minprimsol;
17016	}
17017	
17018	/** gets the maximal LP solution value, this column ever assumed */
17019	SCIP_Real SCIPcolGetMaxPrimsol(
17020	   SCIP_COL*             col                 /**< LP column */
17021	   )
17022	{
17023	   assert(col != NULL);
17024	
17025	   return col->maxprimsol;
17026	}
17027	
17028	/** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17029	 *  and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17030	 */
17031	SCIP_BASESTAT SCIPcolGetBasisStatus(
17032	   SCIP_COL*             col                 /**< LP column */
17033	   )
17034	{
17035	   assert(col != NULL);
17036	   assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
17037	
17038	   return (SCIP_BASESTAT)col->basisstatus;
17039	}
17040	
17041	/** gets variable this column represents */
17042	SCIP_VAR* SCIPcolGetVar(
17043	   SCIP_COL*             col                 /**< LP column */
17044	   )
17045	{
17046	   assert(col != NULL);
17047	
17048	   return col->var;
17049	}
17050	
17051	/** gets unique index of col */
17052	int SCIPcolGetIndex(
17053	   SCIP_COL*             col                 /**< LP col */
17054	   )
17055	{
17056	   assert(col != NULL);
17057	
17058	   return col->index;
17059	}
17060	
17061	/** gets probindex of corresponding variable */
17062	int SCIPcolGetVarProbindex(
17063	   SCIP_COL*             col                 /**< LP col */
17064	   )
17065	{
17066	   assert(col != NULL);
17067	
17068	   return col->var_probindex;
17069	}
17070	
17071	/** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17072	SCIP_Bool SCIPcolIsIntegral(
17073	   SCIP_COL*             col                 /**< LP column */
17074	   )
17075	{
17076	   assert(col != NULL);
17077	   assert(SCIPvarIsIntegral(col->var) == col->integral);
17078	
17079	   return col->integral;
17080	}
17081	
17082	/** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17083	SCIP_Bool SCIPcolIsRemovable(
17084	   SCIP_COL*             col                 /**< LP column */
17085	   )
17086	{
17087	   assert(col != NULL);
17088	
17089	   return col->removable;
17090	}
17091	
17092	/** gets position of column in current LP, or -1 if it is not in LP */
17093	int SCIPcolGetLPPos(
17094	   SCIP_COL*             col                 /**< LP column */
17095	   )
17096	{
17097	   assert(col != NULL);
17098	   assert((col->lppos == -1) == (col->lpdepth == -1));
17099	
17100	   return col->lppos;
17101	}
17102	
17103	/** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17104	int SCIPcolGetLPDepth(
17105	   SCIP_COL*             col                 /**< LP column */
17106	   )
17107	{
17108	   assert(col != NULL);
17109	   assert((col->lppos == -1) == (col->lpdepth == -1));
17110	
17111	   return col->lpdepth;
17112	}
17113	
17114	/** returns TRUE iff column is member of current LP */
17115	SCIP_Bool SCIPcolIsInLP(
17116	   SCIP_COL*             col                 /**< LP column */
17117	   )
17118	{
17119	   assert(col != NULL);
17120	   assert((col->lppos == -1) == (col->lpdepth == -1));
17121	
17122	   return (col->lppos >= 0);
17123	}
17124	
17125	/** get number of nonzero entries in column vector */
17126	int SCIPcolGetNNonz(
17127	   SCIP_COL*             col                 /**< LP column */
17128	   )
17129	{
17130	   assert(col != NULL);
17131	
17132	   return col->len;
17133	}
17134	
17135	/** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17136	 *
17137	 *  @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17138	 *  that is in the current LP and the LP was solved, or a column that was in a solved LP and didn't change afterwards
17139	 */
17140	int SCIPcolGetNLPNonz(
17141	   SCIP_COL*             col                 /**< LP column */
17142	   )
17143	{
17144	   assert(col != NULL);
17145	   assert(col->nunlinked == 0);
17146	
17147	   return col->nlprows;
17148	}
17149	
17150	/** gets array with rows of nonzero entries */
17151	SCIP_ROW** SCIPcolGetRows(
17152	   SCIP_COL*             col                 /**< LP column */
17153	   )
17154	{
17155	   assert(col != NULL);
17156	
17157	   return col->rows;
17158	}
17159	
17160	/** gets array with coefficients of nonzero entries */
17161	SCIP_Real* SCIPcolGetVals(
17162	   SCIP_COL*             col                 /**< LP column */
17163	   )
17164	{
17165	   assert(col != NULL);
17166	
17167	   return col->vals;
17168	}
17169	
17170	/** gets node number of the last node in current branch and bound run, where strong branching was used on the
17171	 *  given column, or -1 if strong branching was never applied to the column in current run
17172	 */
17173	SCIP_Longint SCIPcolGetStrongbranchNode(
17174	   SCIP_COL*             col                 /**< LP column */
17175	   )
17176	{
17177	   assert(col != NULL);
17178	
17179	   return col->sbnode;
17180	}
17181	
17182	/** gets number of times, strong branching was applied in current run on the given column */
17183	int SCIPcolGetNStrongbranchs(
17184	   SCIP_COL*             col                 /**< LP column */
17185	   )
17186	{
17187	   assert(col != NULL);
17188	
17189	   return col->nsbcalls;
17190	}
17191	
17192	/** gets the age of a column, i.e., the total number of successive times a column was in the LP and was 0.0 in the solution */
17193	int SCIPcolGetAge(
17194	   SCIP_COL*             col                 /**< LP column */
17195	   )
17196	{
17197	   assert(col != NULL);
17198	
17199	   return col->age;
17200	}
17201	
17202	/** gets opposite bound type of given bound type */
17203	SCIP_BOUNDTYPE SCIPboundtypeOpposite(
17204	   SCIP_BOUNDTYPE        boundtype           /**< type of bound (lower or upper) */
17205	   )
17206	{
17207	   assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17208	
17209	   return (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
17210	}
17211	
17212	/** get number of nonzero entries in row vector */
17213	int SCIProwGetNNonz(
17214	   SCIP_ROW*             row                 /**< LP row */
17215	   )
17216	{
17217	   assert(row != NULL);
17218	
17219	   return row->len;
17220	}
17221	
17222	/** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17223	 *
17224	 *  @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17225	 *  that is in the current LP and the LP was solved, or a row that was in a solved LP and didn't change afterwards
17226	 */
17227	int SCIProwGetNLPNonz(
17228	   SCIP_ROW*             row                 /**< LP row */
17229	   )
17230	{
17231	   assert(row != NULL);
17232	   assert(row->nunlinked == 0);
17233	
17234	   return row->nlpcols;
17235	}
17236	
17237	/** gets array with columns of nonzero entries */
17238	SCIP_COL** SCIProwGetCols(
17239	   SCIP_ROW*             row                 /**< LP row */
17240	   )
17241	{
17242	   assert(row != NULL);
17243	
17244	   return row->cols;
17245	}
17246	
17247	/** gets array with coefficients of nonzero entries */
17248	SCIP_Real* SCIProwGetVals(
17249	   SCIP_ROW*             row                 /**< LP row */
17250	   )
17251	{
17252	   assert(row != NULL);
17253	
17254	   return row->vals;
17255	}
17256	
17257	/** gets constant shift of row */
17258	SCIP_Real SCIProwGetConstant(
17259	   SCIP_ROW*             row                 /**< LP row */
17260	   )
17261	{
17262	   assert(row != NULL);
17263	
17264	   return row->constant;
17265	}
17266	
17267	/** gets Euclidean norm of row vector */
17268	SCIP_Real SCIProwGetNorm(
17269	   SCIP_ROW*             row                 /**< LP row */
17270	   )
17271	{
17272	   assert(row != NULL);
17273	
17274	   checkRowSqrnorm(row);
17275	
17276	   return sqrt(row->sqrnorm);
17277	}
17278	
17279	/** gets sum norm of row vector (sum of absolute values of coefficients) */
17280	SCIP_Real SCIProwGetSumNorm(
17281	   SCIP_ROW*             row                 /**< LP row */
17282	   )
17283	{
17284	   assert(row != NULL);
17285	
17286	   checkRowSumnorm(row);
17287	
17288	   return row->sumnorm;
17289	}
17290	
17291	/** returns the left hand side of the row */
17292	SCIP_Real SCIProwGetLhs(
17293	   SCIP_ROW*             row                 /**< LP row */
17294	   )
17295	{
17296	   assert(row != NULL);
17297	
17298	   return row->lhs;
17299	}
17300	
17301	/** returns the right hand side of the row */
17302	SCIP_Real SCIProwGetRhs(
17303	   SCIP_ROW*             row                 /**< LP row */
17304	   )
17305	{
17306	   assert(row != NULL);
17307	
17308	   return row->rhs;
17309	}
17310	
17311	/** gets the dual LP solution of a row */
17312	SCIP_Real SCIProwGetDualsol(
17313	   SCIP_ROW*             row                 /**< LP row */
17314	   )
17315	{
17316	   assert(row != NULL);
17317	
17318	   if( row->lppos >= 0 )
17319	      return row->dualsol;
17320	   else
17321	      return 0.0;
17322	}
17323	
17324	/** gets the dual Farkas coefficient of a row in an infeasible LP */
17325	SCIP_Real SCIProwGetDualfarkas(
17326	   SCIP_ROW*             row                 /**< LP row */
17327	   )
17328	{
17329	   assert(row != NULL);
17330	
17331	   if( row->lppos >= 0 )
17332	      return row->dualfarkas;
17333	   else
17334	      return 0.0;
17335	}
17336	
17337	/** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17338	 *  and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17339	 */
17340	SCIP_BASESTAT SCIProwGetBasisStatus(
17341	   SCIP_ROW*             row                 /**< LP row */
17342	   )
17343	{
17344	   assert(row != NULL);
17345	   assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
17346	
17347	   return (SCIP_BASESTAT)row->basisstatus;
17348	}
17349	
17350	/** returns the name of the row */
17351	const char* SCIProwGetName(
17352	   SCIP_ROW*             row                 /**< LP row */
17353	   )
17354	{
17355	   assert(row != NULL);
17356	
17357	   return row->name;
17358	}
17359	
17360	/** gets unique index of row */
17361	int SCIProwGetIndex(
17362	   SCIP_ROW*             row                 /**< LP row */
17363	   )
17364	{
17365	   assert(row != NULL);
17366	
17367	   return row->index;
17368	}
17369	
17370	/** gets age of row */
17371	int SCIProwGetAge(
17372	   SCIP_ROW*             row                 /**< LP row */
17373	   )
17374	{
17375	   assert(row != NULL);
17376	
17377	   return row->age;
17378	}
17379	
17380	/** gets rank of row */
17381	int SCIProwGetRank(
17382	   SCIP_ROW*             row                 /**< LP row */
17383	   )
17384	{
17385	   assert(row != NULL);
17386	
17387	   return row->rank;
17388	}
17389	
17390	/** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17391	SCIP_Bool SCIProwIsIntegral(
17392	   SCIP_ROW*             row                 /**< LP row */
17393	   )
17394	{
17395	   assert(row != NULL);
17396	
17397	   return row->integral;
17398	}
17399	
17400	/** returns TRUE iff row is only valid locally */
17401	SCIP_Bool SCIProwIsLocal(
17402	   SCIP_ROW*             row                 /**< LP row */
17403	   )
17404	{
17405	   assert(row != NULL);
17406	
17407	   return row->local;
17408	}
17409	
17410	/** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17411	SCIP_Bool SCIProwIsModifiable(
17412	   SCIP_ROW*             row                 /**< LP row */
17413	   )
17414	{
17415	   assert(row != NULL);
17416	
17417	   return row->modifiable;
17418	}
17419	
17420	/** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17421	SCIP_Bool SCIProwIsRemovable(
17422	   SCIP_ROW*             row                 /**< LP row */
17423	   )
17424	{
17425	   assert(row != NULL);
17426	
17427	   return row->removable;
17428	}
17429	
17430	/** returns type of origin that created the row */
17431	SCIP_ROWORIGINTYPE SCIProwGetOrigintype(
17432	   SCIP_ROW*             row                 /**< LP row */
17433	   )
17434	{
17435	   assert( row != NULL );
17436	
17437	   return (SCIP_ROWORIGINTYPE) row->origintype;
17438	}
17439	
17440	/** returns origin constraint that created the row (NULL if not available) */
17441	SCIP_CONS* SCIProwGetOriginCons(
17442	   SCIP_ROW*             row                 /**< LP row */
17443	   )
17444	{
17445	   assert( row != NULL );
17446	
17447	   if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS )
17448	   {
17449	      assert( row->origin != NULL );
17450	      return (SCIP_CONS*) row->origin;
17451	   }
17452	   return NULL;
17453	}
17454	
17455	/** returns origin constraint handler that created the row (NULL if not available) */
17456	SCIP_CONSHDLR* SCIProwGetOriginConshdlr(
17457	   SCIP_ROW*             row                 /**< LP row */
17458	   )
17459	{
17460	   assert( row != NULL );
17461	
17462	   if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONSHDLR )
17463	   {
17464	      assert( row->origin != NULL );
17465	      return (SCIP_CONSHDLR*) row->origin;
17466	   }
17467	   else if( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS )
17468	   {
17469	      assert(row->origin != NULL);
17470	      return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17471	   }
17472	   return NULL;
17473	}
17474	
17475	/** returns origin separator that created the row (NULL if not available) */
17476	SCIP_SEPA* SCIProwGetOriginSepa(
17477	   SCIP_ROW*             row                 /**< LP row */
17478	   )
17479	{
17480	   assert( row != NULL );
17481	
17482	   if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_SEPA )
17483	   {
17484	      assert( row->origin != NULL );
17485	      return (SCIP_SEPA*) row->origin;
17486	   }
17487	   return NULL;
17488	}
17489	
17490	/** returns TRUE iff row is member of the global cut pool */
17491	SCIP_Bool SCIProwIsInGlobalCutpool(
17492	   SCIP_ROW*             row                 /**< LP row */
17493	   )
17494	{
17495	   assert(row != NULL);
17496	
17497	   return row->inglobalcutpool;
17498	}
17499	
17500	/** gets position of row in current LP, or -1 if it is not in LP */
17501	int SCIProwGetLPPos(
17502	   SCIP_ROW*             row                 /**< LP row */
17503	   )
17504	{
17505	   assert(row != NULL);
17506	   assert((row->lppos == -1) == (row->lpdepth == -1));
17507	
17508	   return row->lppos;
17509	}
17510	
17511	/** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17512	int SCIProwGetLPDepth(
17513	   SCIP_ROW*             row                 /**< LP row */
17514	   )
17515	{
17516	   assert(row != NULL);
17517	   assert((row->lppos == -1) == (row->lpdepth == -1));
17518	
17519	   return row->lpdepth;
17520	}
17521	
17522	/** returns TRUE iff row is member of current LP */
17523	SCIP_Bool SCIProwIsInLP(
17524	   SCIP_ROW*             row                 /**< LP row */
17525	   )
17526	{
17527	   assert(row != NULL);
17528	   assert((row->lppos == -1) == (row->lpdepth == -1));
17529	
17530	   return (row->lppos >= 0);
17531	}
17532	
17533	/** changes the rank of LP row */
17534	void SCIProwChgRank(
17535	   SCIP_ROW*             row,                /**< LP row */
17536	   int                   rank                /**< new value for rank */
17537	   )
17538	{
17539	   assert(row != NULL);
17540	
17541	   row->rank = rank;
17542	}
17543	
17544	/** returns the number of times that this row has been sharp in an optimal LP solution */
17545	SCIP_Longint SCIProwGetActiveLPCount(
17546	   SCIP_ROW*             row                 /**< row */
17547	   )
17548	{
17549	   assert(row != NULL);
17550	
17551	   return row->activeinlpcounter;
17552	}
17553	
17554	/** returns the number of LPs since this row has been created */
17555	SCIP_Longint SCIProwGetNLPsAfterCreation(
17556	   SCIP_ROW*             row                 /**< row */
17557	   )
17558	{
17559	   assert(row != NULL);
17560	
17561	   return row->nlpsaftercreation;
17562	}
17563	
17564	/** gets array with columns of the LP */
17565	SCIP_COL** SCIPlpGetCols(
17566	   SCIP_LP*              lp                  /**< current LP data */
17567	   )
17568	{
17569	   assert(lp != NULL);
17570	
17571	   return lp->cols;
17572	}
17573	
17574	/** gets current number of columns in LP */
17575	int SCIPlpGetNCols(
17576	   SCIP_LP*              lp                  /**< current LP data */
17577	   )
17578	{
17579	   assert(lp != NULL);
17580	
17581	   return lp->ncols;
17582	}
17583	
17584	/** gets current number of unfixed columns in LP */
17585	int SCIPlpGetNUnfixedCols(
17586	   SCIP_LP*              lp,                 /**< current LP data */
17587	   SCIP_Real             eps                 /**< numerical tolerance */
17588	   )
17589	{
17590	   SCIP_COL** lpcols;
17591	   int nlpcols;
17592	   int nunfixedcols;
17593	   int c;
17594	
17595	   assert(lp != NULL);
17596	   assert(eps > 0.0);
17597	
17598	   lpcols = lp->cols;
17599	   nlpcols = lp->ncols;
17600	
17601	   nunfixedcols = 0;
17602	   for( c = 0; c < nlpcols; ++c )
17603	   {
17604	      if( lpcols[c]->ub - lpcols[c]->lb > eps )
17605	         ++nunfixedcols;
17606	   }
17607	
17608	   return nunfixedcols;
17609	}
17610	
17611	/** gets array with rows of the LP */
17612	SCIP_ROW** SCIPlpGetRows(
17613	   SCIP_LP*              lp                  /**< current LP data */
17614	   )
17615	{
17616	   assert(lp != NULL);
17617	
17618	   return lp->rows;
17619	}
17620	
17621	/** gets current number of rows in LP */
17622	int SCIPlpGetNRows(
17623	   SCIP_LP*              lp                  /**< current LP data */
17624	   )
17625	{
17626	   assert(lp != NULL);
17627	
17628	   return lp->nrows;
17629	}
17630	
17631	/** gets array with newly added columns after the last mark */
17632	SCIP_COL** SCIPlpGetNewcols(
17633	   SCIP_LP*              lp                  /**< current LP data */
17634	   )
17635	{
17636	   assert(lp != NULL);
17637	   assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17638	
17639	   return &(lp->cols[lp->firstnewcol]);
17640	}
17641	
17642	/** gets number of newly added columns after the last mark */
17643	int SCIPlpGetNNewcols(
17644	   SCIP_LP*              lp                  /**< current LP data */
17645	   )
17646	{
17647	   assert(lp != NULL);
17648	   assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17649	
17650	   return lp->ncols - lp->firstnewcol;
17651	}
17652	
17653	/** gets array with newly added rows after the last mark */
17654	SCIP_ROW** SCIPlpGetNewrows(
17655	   SCIP_LP*              lp                  /**< current LP data */
17656	   )
17657	{
17658	   assert(lp != NULL);
17659	   assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17660	
17661	   return &(lp->rows[lp->firstnewrow]);
17662	}
17663	
17664	/** gets number of newly added rows after the last mark */
17665	int SCIPlpGetNNewrows(
17666	   SCIP_LP*              lp                  /**< current LP data */
17667	   )
17668	{
17669	   assert(lp != NULL);
17670	   assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17671	
17672	   return lp->nrows - lp->firstnewrow;
17673	}
17674	
17675	/** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17676	void SCIPlpRecalculateObjSqrNorm(
17677	   SCIP_SET*             set,                /**< global SCIP settings */
17678	   SCIP_LP*              lp                  /**< LP data */
17679	   )
17680	{
17681	   if( lp->objsqrnormunreliable )
17682	   {
17683	      SCIP_COL** cols;
17684	      int c;
17685	
17686	      cols = lp->cols;
17687	      assert(cols != NULL || lp->ncols == 0);
17688	
17689	      lp->objsqrnorm = 0.0;
17690	
17691	      for( c = lp->ncols - 1; c >= 0; --c )
17692	      {
17693	         lp->objsqrnorm += SQR(cols[c]->unchangedobj);  /*lint !e613*/
17694	      }
17695	      assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17696	
17697	      /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17698	      lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17699	
17700	      lp->objsqrnormunreliable = FALSE;
17701	   }
17702	   return;
17703	}
17704	
17705	/** gets Euclidean norm of objective function vector of column variables, only use this method if
17706	 *  lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17707	SCIP_Real SCIPlpGetObjNorm(
17708	   SCIP_LP*              lp                  /**< LP data */
17709	   )
17710	{
17711	   assert(lp != NULL);
17712	   assert(!lp->objsqrnormunreliable);
17713	   assert(lp->objsqrnorm >= 0.0);
17714	
17715	   return SQRT(lp->objsqrnorm);
17716	}
17717	
17718	/** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17719	void SCIPlpSetRootLPIsRelax(
17720	   SCIP_LP*              lp,                 /**< LP data */
17721	   SCIP_Bool             isrelax             /**< is the root lp a relaxation of the problem? */
17722	   )
17723	{
17724	   assert(lp != NULL);
17725	
17726	   lp->rootlpisrelax = isrelax;
17727	}
17728	
17729	/** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17730	SCIP_Bool SCIPlpIsRootLPRelax(
17731	   SCIP_LP*              lp                  /**< LP data */
17732	   )
17733	{
17734	   assert(lp != NULL);
17735	
17736	   return lp->rootlpisrelax;
17737	}
17738	
17739	/** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17740	SCIP_Real SCIPlpGetRootObjval(
17741	   SCIP_LP*              lp                  /**< LP data */
17742	   )
17743	{
17744	   assert(lp != NULL);
17745	
17746	   return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17747	}
17748	
17749	/** gets part of the objective value of the root node LP that results from COLUMN variables only;
17750	 *  returns SCIP_INVALID if the root node LP was not (yet) solved
17751	 */
17752	SCIP_Real SCIPlpGetRootColumnObjval(
17753	   SCIP_LP*              lp                  /**< LP data */
17754	   )
17755	{
17756	   assert(lp != NULL);
17757	
17758	   return lp->rootlpobjval;
17759	}
17760	
17761	/** gets part of the objective value of the root node LP that results from LOOSE variables only;
17762	 *  returns SCIP_INVALID if the root node LP was not (yet) solved
17763	 */
17764	SCIP_Real SCIPlpGetRootLooseObjval(
17765	   SCIP_LP*              lp                  /**< LP data */
17766	   )
17767	{
17768	   assert(lp != NULL);
17769	
17770	   return lp->rootlooseobjval;
17771	}
17772	
17773	/** gets the LP solver interface */
17774	SCIP_LPI* SCIPlpGetLPI(
17775	   SCIP_LP*              lp                  /**< current LP data */
17776	   )
17777	{
17778	   assert(lp != NULL);
17779	
17780	   return lp->lpi;
17781	}
17782	
17783	/** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17784	void SCIPlpSetIsRelax(
17785	   SCIP_LP*              lp,                 /**< LP data */
17786	   SCIP_Bool             relax               /**< is the current lp a relaxation? */
17787	   )
17788	{
17789	   assert(lp != NULL);
17790	
17791	   lp->isrelax = relax;
17792	}
17793	
17794	/** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17795	 *  solution value a valid local lower bound?
17796	 */
17797	SCIP_Bool SCIPlpIsRelax(
17798	   SCIP_LP*              lp                  /**< LP data */
17799	   )
17800	{
17801	   assert(lp != NULL);
17802	
17803	   return lp->isrelax;
17804	}
17805	
17806	/** returns whether the current LP is flushed and solved */
17807	SCIP_Bool SCIPlpIsSolved(
17808	   SCIP_LP*              lp                  /**< current LP data */
17809	   )
17810	{
17811	   assert(lp != NULL);
17812	
17813	   return lp->flushed && lp->solved;
17814	}
17815	
17816	/** return whether the current LP solution passed the primal feasibility check */
17817	SCIP_Bool SCIPlpIsPrimalReliable(
17818	   SCIP_LP*              lp                  /**< current LP data */
17819	   )
17820	{
17821	   assert(lp != NULL);
17822	
17823	   return (lp->primalchecked && lp->primalfeasible);
17824	}
17825	
17826	/** return whether the current LP solution passed the dual feasibility check */
17827	SCIP_Bool SCIPlpIsDualReliable(
17828	   SCIP_LP*              lp                  /**< current LP data */
17829	   )
17830	{
17831	   assert(lp != NULL);
17832	
17833	   return (lp->dualchecked && lp->dualfeasible);
17834	}
17835	
17836	/** returns whether the current LP solution is a basic solution */
17837	SCIP_Bool SCIPlpIsSolBasic(
17838	   SCIP_LP*              lp                  /**< current LP data */
17839	   )
17840	{
17841	   assert(lp != NULL);
17842	
17843	   return lp->solisbasic;
17844	}
17845	
17846	/** returns whether the LP is in diving mode */
17847	SCIP_Bool SCIPlpDiving(
17848	   SCIP_LP*              lp                  /**< current LP data */
17849	   )
17850	{
17851	   assert(lp != NULL);
17852	
17853	   return lp->diving;
17854	}
17855	
17856	/** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17857	SCIP_Bool SCIPlpDivingObjChanged(
17858	   SCIP_LP*              lp                  /**< current LP data */
17859	   )
17860	{
17861	   assert(lp != NULL);
17862	
17863	   return lp->divingobjchg;
17864	}
17865	
17866	/** marks the diving LP to have a changed objective function */
17867	void SCIPlpMarkDivingObjChanged(
17868	   SCIP_LP*              lp                  /**< current LP data */
17869	   )
17870	{
17871	   assert(lp != NULL);
17872	   assert(lp->diving || lp->probing);
17873	
17874	   lp->divingobjchg = TRUE;
17875	}
17876	
17877	/** marks the diving LP to not have a changed objective function anymore */
17878	void SCIPlpUnmarkDivingObjChanged(
17879	   SCIP_LP*              lp                  /**< current LP data */
17880	   )
17881	{
17882	   assert(lp != NULL);
17883	   assert(lp->diving || lp->probing);
17884	
17885	   lp->divingobjchg = FALSE;
17886	}
17887	
17888	/* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17889	SCIP_Bool SCIPlpDivingRowsChanged(
17890	   SCIP_LP*              lp                  /**< current LP data */
17891	   )
17892	{
17893	   assert(lp != NULL);
17894	   assert(lp->diving || lp->ndivechgsides == 0);
17895	
17896	   return (lp->ndivechgsides > 0);
17897	}
17898	
17899	/** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17900	static
17901	SCIP_RETCODE computeRelIntPoint(
17902	   SCIP_LPI*             lpi,                /**< auxiliary LP interface */
17903	   SCIP_SET*             set,                /**< global SCIP settings */
17904	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
17905	   SCIP_LP*              lp,                 /**< LP data */
17906	   SCIP_PROB*            prob,               /**< problem data */
17907	   SCIP_Bool             relaxrows,          /**< should the rows be relaxed */
17908	   SCIP_Bool             inclobjcutoff,      /**< should a row for the objective cutoff be included */
17909	   SCIP_Real             timelimit,          /**< time limit for LP solver */
17910	   int                   iterlimit,          /**< iteration limit for LP solver */
17911	   SCIP_Real*            point,              /**< array to store relative interior point on exit */
17912	   SCIP_Bool*            success             /**< buffer to indicate whether interior point was successfully computed */
17913	   )
17914	{
17915	   SCIP_RETCODE retcode;
17916	   SCIP_Real* primal;
17917	   SCIP_Real* obj;
17918	   SCIP_Real* lb;
17919	   SCIP_Real* ub;
17920	   SCIP_Real* matvals;
17921	   SCIP_Real* matlhs;
17922	   SCIP_Real* matrhs;
17923	   SCIP_Real objval;
17924	   SCIP_Real alpha;
17925	   int* matinds;
17926	   int* matbeg;
17927	#ifndef NDEBUG
17928	   int nslacks;
17929	#endif
17930	   int nnewcols;
17931	   int ntotnonz = 0;
17932	   int ntotrows = 0;
17933	   int matrowidx;
17934	   int matidx;
17935	   int cnt;
17936	   int j;
17937	   int i;
17938	
17939	   assert(lpi != NULL);
17940	
17941	   retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17942	   if( retcode != SCIP_OKAY )
17943	   {
17944	      /* stop execution on error, since result is likely to be unsuable */
17945	      SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17946	      return SCIP_LPERROR;
17947	   }
17948	
17949	   retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_DUALFEASTOL, SCIPsetDualfeastol(set));
17950	   if( retcode != SCIP_OKAY )
17951	   {
17952	      /* stop execution on error, since result is likely to be unsuable */
17953	      SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17954	      return SCIP_LPERROR;
17955	   }
17956	
17957	   /* get storage */
17958	   nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17959	   SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17960	   SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17961	   SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17962	
17963	   /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17964	   for( j = 0; j < lp->ncols; ++j )
17965	   {
17966	      /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
17967	      obj[j] = 0.0;
17968	      lb[j] = -SCIPlpiInfinity(lpi);
17969	      ub[j] =  SCIPlpiInfinity(lpi);
17970	      /* note: we could also use the original bounds - free variables seem to be faster. */
17971	   }
17972	
17973	   /* add artificial alpha variable */
17974	   nnewcols = lp->ncols;
17975	   obj[nnewcols] = 0.0;
17976	   lb[nnewcols] = 1.0;
17977	   ub[nnewcols] = SCIPlpiInfinity(lpi);
17978	   ++nnewcols;
17979	
17980	   /* create slacks for rows */
17981	   for( i = 0; i < lp->nrows; ++i )
17982	   {
17983	      SCIP_ROW* row;
17984	
17985	      row = lp->rows[i];
17986	      assert( row != NULL );
17987	
17988	      if( SCIProwIsModifiable(row) )
17989	         continue;
17990	
17991	      /* make sure row is sorted */
17992	      rowSortLP(row);
17993	      assert( row->lpcolssorted );
17994	
17995	      /* check whether we have an equation */
17996	      if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
17997	      {
17998	         assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
17999	         assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
18000	         ntotnonz += row->nlpcols + 1;
18001	         ++ntotrows;
18002	      }
18003	      else
18004	      {
18005	         /* otherwise add slacks for each side if necessary */
18006	         if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18007	         {
18008	            if ( relaxrows )
18009	            {
18010	               lb[nnewcols] = 0.0;
18011	               ub[nnewcols] = 1.0;
18012	               obj[nnewcols++] = 1.0;
18013	               ntotnonz += row->nlpcols + 2;
18014	            }
18015	            else
18016	               ntotnonz += row->nlpcols + 1;
18017	            ++ntotrows;
18018	         }
18019	         if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18020	         {
18021	            if ( relaxrows )
18022	            {
18023	               lb[nnewcols] = 0.0;
18024	               ub[nnewcols] = 1.0;
18025	               obj[nnewcols++] = 1.0;
18026	               ntotnonz += row->nlpcols + 2;
18027	            }
18028	            else
18029	               ntotnonz += row->nlpcols + 1;
18030	            ++ntotrows;
18031	         }
18032	      }
18033	   }
18034	
18035	   /* create slacks for objective cutoff row */
18036	   if( inclobjcutoff && relaxrows )
18037	   {
18038	      /* add slacks for right hand side */
18039	      lb[nnewcols] = 0.0;
18040	      ub[nnewcols] = 1.0;
18041	      obj[nnewcols++] = 1.0;
18042	      ntotnonz += lp->ncols + 2;
18043	      ++ntotrows;
18044	   }
18045	
18046	   /* create slacks for bounds */
18047	   for( j = 0; j < lp->ncols; ++j )
18048	   {
18049	      SCIP_COL* col;
18050	
18051	      col = lp->cols[j];
18052	      assert( col != NULL );
18053	
18054	      /* no slacks for fixed variables */
18055	      if( SCIPsetIsEQ(set, col->lb, col->ub) )
18056	      {
18057	         ++ntotrows;
18058	         ntotnonz += 2;
18059	      }
18060	      else
18061	      {
18062	         /* add slacks for each bound if necessary */
18063	         if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18064	         {
18065	            lb[nnewcols] = 0.0;
18066	            ub[nnewcols] = 1.0;
18067	            obj[nnewcols++] = 1.0;
18068	            ntotnonz += 3;
18069	            ++ntotrows;
18070	         }
18071	         if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18072	         {
18073	            lb[nnewcols] = 0.0;
18074	            ub[nnewcols] = 1.0;
18075	            obj[nnewcols++] = 1.0;
18076	            ntotnonz += 3;
18077	            ++ntotrows;
18078	         }
18079	      }
18080	   }
18081	#ifndef NDEBUG
18082	   nslacks = nnewcols - lp->ncols - 1;
18083	   assert( nslacks >= 0 );
18084	   assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18085	#endif
18086	
18087	   /* add columns */
18088	   SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18089	
18090	   /* free storage */
18091	   SCIPsetFreeBufferArray(set, &obj);
18092	   SCIPsetFreeBufferArray(set, &ub);
18093	   SCIPsetFreeBufferArray(set, &lb);
18094	
18095	   /* prepare storage for rows */
18096	   SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18097	   SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18098	   SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18099	   SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18100	   SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18101	
18102	   /* create rows arising from original rows */
18103	   cnt = 0;
18104	   matrowidx = 0;
18105	   matidx = 0;
18106	   for( i = 0; i < lp->nrows; ++i )
18107	   {
18108	      SCIP_ROW* row;
18109	      SCIP_COL** rowcols;
18110	      SCIP_Real* rowvals;
18111	      SCIP_Real lhs;
18112	      SCIP_Real rhs;
18113	      int nnonz;
18114	
18115	      row = lp->rows[i];
18116	      assert( row != NULL );
18117	
18118	      if( SCIProwIsModifiable(row) )
18119	         continue;
18120	      assert( row->lpcolssorted );
18121	
18122	      /* get row data */
18123	      lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18124	      rhs = row->rhs - (SCIPsetIsInfinity(set,  row->rhs) ? 0.0 : row->constant);
18125	      nnonz = row->nlpcols;
18126	      assert( nnonz <= lp->ncols );
18127	      rowcols = row->cols;
18128	      rowvals = row->vals;
18129	
18130	      /* if we have an equation */
18131	      if( SCIPsetIsEQ(set, lhs, rhs) )
18132	      {
18133	         /* set up indices */
18134	         matbeg[matrowidx] = matidx;
18135	         for( j = 0; j < nnonz; ++j )
18136	         {
18137	            assert( rowcols[j] != NULL );
18138	            assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18139	            assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18140	            assert( ! SCIPsetIsZero(set, rowvals[j]) );
18141	            matinds[matidx] = rowcols[j]->lppos;
18142	            matvals[matidx++] = rowvals[j];
18143	            assert( matidx <= ntotnonz );
18144	         }
18145	
18146	         /* add artificial variable */
18147	         if ( ! SCIPsetIsZero(set, rhs) )
18148	         {
18149	            matinds[matidx] = lp->ncols;
18150	            matvals[matidx++] = -rhs;
18151	            assert( matidx <= ntotnonz );
18152	         }
18153	
18154	         matlhs[matrowidx] = 0.0;
18155	         matrhs[matrowidx++] = 0.0;
18156	         assert( matrowidx <= ntotrows );
18157	      }
18158	      else
18159	      {
18160	         SCIP_Real abslhs = REALABS(lhs);
18161	         SCIP_Real absrhs = REALABS(rhs);
18162	
18163	         assert(!SCIPsetIsEQ(set, lhs, rhs));
18164	
18165	         /* treat lhs */
18166	         if( !SCIPsetIsInfinity(set, abslhs) )
18167	         {
18168	            /* set up indices */
18169	            matbeg[matrowidx] = matidx;
18170	            for( j = 0; j < nnonz; ++j )
18171	            {
18172	               assert( rowcols[j] != NULL );
18173	               assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18174	               assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18175	               assert( ! SCIPsetIsZero(set, rowvals[j]) );
18176	               matinds[matidx] = rowcols[j]->lppos;
18177	               matvals[matidx++] = rowvals[j];
18178	               assert( matidx <= ntotnonz );
18179	            }
18180	
18181	            /* add artificial variable */
18182	            if ( ! SCIPsetIsZero(set, lhs) )
18183	            {
18184	               matinds[matidx] = lp->ncols;
18185	               matvals[matidx++] = -lhs;
18186	               assert( matidx <= ntotnonz );
18187	            }
18188	
18189	            if( relaxrows )
18190	            {
18191	               /* add slack variable */
18192	               matvals[matidx] = -MAX(1.0, lhs);      /*lint !e679*/
18193	               matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18194	               assert( matidx <= ntotnonz );
18195	               ++cnt;
18196	            }
18197	
18198	            matlhs[matrowidx] = 0.0;
18199	            matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18200	            assert( matrowidx <= ntotrows );
18201	         }
18202	
18203	         /* treat rhs */
18204	         if( !SCIPsetIsInfinity(set, absrhs) )
18205	         {
18206	            /* set up indices */
18207	            matbeg[matrowidx] = matidx;
18208	            for( j = 0; j < nnonz; ++j )
18209	            {
18210	               assert( rowcols[j] != NULL );
18211	               assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18212	               assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18213	               assert( ! SCIPsetIsZero(set, rowvals[j]) );
18214	               matinds[matidx] = rowcols[j]->lppos;
18215	               matvals[matidx++] = rowvals[j];
18216	               assert( matidx <= ntotnonz );
18217	            }
18218	
18219	            /* add artificial variable */
18220	            if ( ! SCIPsetIsZero(set, rhs) )
18221	            {
18222	               matinds[matidx] = lp->ncols;
18223	               matvals[matidx++] = -rhs;
18224	               assert( matidx <= ntotnonz );
18225	            }
18226	
18227	            if( relaxrows )
18228	            {
18229	               /* add slack variable */
18230	               matvals[matidx] = MAX(1.0, absrhs);    /*lint !e679*/
18231	               matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18232	               ++cnt;
18233	            }
18234	
18235	            matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18236	            matrhs[matrowidx++] = 0.0;
18237	            assert( matrowidx <= ntotrows );
18238	         }
18239	      }
18240	   }
18241	
18242	   /* create row arising from objective cutoff */
18243	   if( inclobjcutoff )
18244	   {
18245	      SCIP_Real rhs;
18246	
18247	      /* get row data */
18248	      assert(lp->looseobjvalinf == 0);
18249	      rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18250	
18251	      /* set up indices and coefficients */
18252	      matbeg[matrowidx] = matidx;
18253	      for( j = 0; j < lp->ncols; ++j )
18254	      {
18255	         assert( lp->cols[j] != NULL );
18256	         assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18257	         assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18258	
18259	         if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18260	         {
18261	            matinds[matidx] = lp->cols[j]->lppos;
18262	            matvals[matidx++] = lp->cols[j]->obj;
18263	            assert( matidx <= ntotnonz );
18264	         }
18265	      }
18266	
18267	      /* treat rhs */
18268	
18269	      /* add artificial variable */
18270	      if ( ! SCIPsetIsZero(set, rhs) )
18271	      {
18272	         matinds[matidx] = lp->ncols;
18273	         matvals[matidx++] = -rhs;
18274	         assert( matidx <= ntotnonz );
18275	      }
18276	
18277	      if( relaxrows )
18278	      {
18279	         SCIP_Real absrhs = REALABS(rhs);
18280	
18281	         /* add slack variable */
18282	         matvals[matidx] = MAX(1.0, absrhs);
18283	         matinds[matidx++] = lp->ncols + 1 + cnt;
18284	         assert( matidx <= ntotnonz );
18285	         ++cnt;
18286	      }
18287	      matlhs[matrowidx] = -SCIPsetInfinity(set);
18288	      matrhs[matrowidx++] = 0.0;
18289	      assert( matrowidx <= ntotrows );
18290	   }
18291	
18292	   /* create rows arising from bounds */
18293	   for( j = 0; j < lp->ncols; ++j )
18294	   {
18295	      SCIP_COL* col;
18296	      SCIP_Real abscollb;
18297	      SCIP_Real abscolub;
18298	
18299	      col = lp->cols[j];
18300	      assert( col != NULL );
18301	      assert( col->lppos == j );
18302	
18303	      /* fixed variable */
18304	      if( SCIPsetIsEQ(set, col->lb, col->ub) )
18305	      {
18306	         /* set up index of column */
18307	         matbeg[matrowidx] = matidx;
18308	
18309	         matinds[matidx] = j;
18310	         matvals[matidx++] = 1.0;
18311	         assert( matidx <= ntotnonz );
18312	
18313	         /* add artificial variable */
18314	         if ( ! SCIPsetIsZero(set, col->ub) )
18315	         {
18316	            matinds[matidx] = lp->ncols;
18317	            matvals[matidx++] = -col->ub;
18318	            assert( matidx <= ntotnonz );
18319	         }
18320	
18321	         matlhs[matrowidx] = 0.0;
18322	         matrhs[matrowidx++] = 0.0;
18323	         assert( matrowidx <= ntotrows );
18324	
18325	         continue;
18326	      }
18327	
18328	      abscollb = REALABS(col->lb);
18329	      abscolub = REALABS(col->ub);
18330	
18331	      /* lower bound */
18332	      if ( ! SCIPsetIsInfinity(set, abscollb) )
18333	      {
18334	         /* set up index of column */
18335	         matbeg[matrowidx] = matidx;
18336	
18337	         matinds[matidx] = j;
18338	         matvals[matidx++] = 1.0;
18339	         assert( matidx <= ntotnonz );
18340	
18341	         /* add artificial variable */
18342	         if ( ! SCIPsetIsZero(set, col->lb) )
18343	         {
18344	            matinds[matidx] = lp->ncols;
18345	            matvals[matidx++] = -col->lb;
18346	            assert( matidx <= ntotnonz );
18347	         }
18348	
18349	         /* add slack variable */
18350	         matvals[matidx] = -MAX(1.0, abscollb);
18351	         matinds[matidx++] = lp->ncols + 1 + cnt;
18352	         assert( matidx <= ntotnonz );
18353	         ++cnt;
18354	
18355	         matlhs[matrowidx] = 0.0;
18356	         matrhs[matrowidx++] = SCIPsetInfinity(set);
18357	         assert( matrowidx <= ntotrows );
18358	      }
18359	
18360	      /* upper bound */
18361	      if ( ! SCIPsetIsInfinity(set, abscolub) )
18362	      {
18363	         /* set up index of column */
18364	         matbeg[matrowidx] = matidx;
18365	
18366	         matinds[matidx] = j;
18367	         matvals[matidx++] = 1.0;
18368	         assert( matidx <= ntotnonz );
18369	
18370	         /* add artificial variable */
18371	         if ( ! SCIPsetIsZero(set, col->ub) )
18372	         {
18373	            matinds[matidx] = lp->ncols;
18374	            matvals[matidx++] = -col->ub;
18375	            assert( matidx <= ntotnonz );
18376	         }
18377	
18378	         /* add slack variable */
18379	         matvals[matidx] = MAX(1.0, abscolub);
18380	         matinds[matidx++] = lp->ncols + 1 + cnt;
18381	         assert( matidx <= ntotnonz );
18382	         ++cnt;
18383	
18384	         matlhs[matrowidx] = -SCIPsetInfinity(set);
18385	         matrhs[matrowidx++] = 0.0;
18386	         assert( matrowidx <= ntotrows );
18387	      }
18388	   }
18389	   assert( cnt == nslacks );
18390	   assert( matrowidx == ntotrows );
18391	
18392	   /* add rows */
18393	   SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18394	
18395	   SCIPsetFreeBufferArray(set, &matrhs);
18396	   SCIPsetFreeBufferArray(set, &matlhs);
18397	   SCIPsetFreeBufferArray(set, &matbeg);
18398	   SCIPsetFreeBufferArray(set, &matvals);
18399	   SCIPsetFreeBufferArray(set, &matinds);
18400	
18401	#ifdef SCIP_OUTPUT
18402	   SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18403	#endif
18404	
18405	#ifndef NDEBUG
18406	   {
18407	      int ncols;
18408	      SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18409	      assert( ncols == nnewcols );
18410	   }
18411	#endif
18412	
18413	   /* set time limit */
18414	   if( SCIPsetIsInfinity(set, timelimit) )
18415	      timelimit = SCIPlpiInfinity(lpi);
18416	   retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18417	
18418	   /* check, if parameter is unknown */
18419	   if( retcode == SCIP_PARAMETERUNKNOWN )
18420	      SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18421	   else if ( retcode != SCIP_OKAY )
18422	      return retcode;
18423	
18424	   /* set iteration limit */
18425	   retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18426	
18427	   /* check, if parameter is unknown */
18428	   if( retcode == SCIP_PARAMETERUNKNOWN )
18429	      SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18430	   else if ( retcode != SCIP_OKAY )
18431	      return retcode;
18432	
18433	   /* solve and store point */
18434	   /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18435	   SCIP_CALL( SCIPlpiSolveDual(lpi) );   /* dual is usually faster */
18436	
18437	#ifndef NDEBUG
18438	   if ( SCIPlpiIsIterlimExc(lpi) )
18439	      SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18440	   if ( SCIPlpiIsTimelimExc(lpi) )
18441	      SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18442	#endif
18443	
18444	   if( SCIPlpiIsOptimal(lpi) )
18445	   {
18446	      /* get primal solution */
18447	      SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18448	      SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18449	      alpha = primal[lp->ncols];
18450	      assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18451	
18452	      SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18453	
18454	      /* construct relative interior point */
18455	      for( j = 0; j < lp->ncols; ++j )
18456	         point[j] = primal[j]/alpha;
18457	
18458	#ifdef SCIP_DEBUG
18459	      /* check whether the point is a relative interior point */
18460	      cnt = 0;
18461	      if( relaxrows )
18462	      {
18463	         for( i = 0; i < lp->nrows; ++i )
18464	         {
18465	            SCIP_ROW* row;
18466	            SCIP_COL** rowcols;
18467	            SCIP_Real* rowvals;
18468	            SCIP_Real lhs;
18469	            SCIP_Real rhs;
18470	            SCIP_Real sum;
18471	            int nnonz;
18472	
18473	            row = lp->rows[i];
18474	            assert( row != NULL );
18475	
18476	            /* get row data */
18477	            lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18478	            rhs = row->rhs - (SCIPsetIsInfinity(set,  row->rhs) ? 0.0 : row->constant);
18479	            nnonz = row->nlpcols;
18480	            assert( nnonz <= lp->ncols );
18481	            rowcols = row->cols;
18482	            rowvals = row->vals;
18483	
18484	            sum = 0.0;
18485	            for( j = 0; j < nnonz; ++j )
18486	               sum += rowvals[j] * primal[rowcols[j]->lppos];
18487	            sum /= alpha;
18488	
18489	            /* if we have an equation */
18490	            if( SCIPsetIsEQ(set, lhs, rhs) )
18491	            {
18492	               assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18493	            }
18494	            else
18495	            {
18496	               /* treat lhs */
18497	               if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18498	               {
18499	                  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18500	                  ++cnt;
18501	               }
18502	               /* treat rhs */
18503	               if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18504	               {
18505	                  assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18506	                  ++cnt;
18507	               }
18508	            }
18509	         }
18510	         if( inclobjcutoff )
18511	         {
18512	            SCIP_Real sum;
18513	#ifndef NDEBUG
18514	            SCIP_Real rhs;
18515	
18516	            rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18517	#endif
18518	            sum = 0.0;
18519	            for( j = 0; j < lp->ncols; ++j )
18520	               sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18521	            sum /= alpha;
18522	
18523	            assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18524	            ++cnt;
18525	         }
18526	      }
18527	      /* check bounds */
18528	      for( j = 0; j < lp->ncols; ++j )
18529	      {
18530	         SCIP_COL* col;
18531	#ifndef NDEBUG
18532	         SCIP_Real val;
18533	#endif
18534	
18535	         col = lp->cols[j];
18536	         assert( col != NULL );
18537	#ifndef NDEBUG
18538	         val = primal[col->lppos] / alpha;
18539	#endif
18540	         /* if the variable is not fixed */
18541	         if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18542	         {
18543	            /* treat lb */
18544	            if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18545	            {
18546	               assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18547	               ++cnt;
18548	            }
18549	            /* treat rhs */
18550	            if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18551	            {
18552	               assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18553	               ++cnt;
18554	            }
18555	         }
18556	      }
18557	#endif
18558	
18559	      /* free */
18560	      SCIPsetFreeBufferArray(set, &primal);
18561	
18562	      *success = TRUE;
18563	   }
18564	
18565	   return SCIP_OKAY;
18566	}
18567	
18568	/** compute relative interior point
18569	 *
18570	 *  We use the approach of@par
18571	 *  R. Freund, R. Roundy, M. J. Todd@par
18572	 *  "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18573	 *  Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18574	 *
18575	 *  to compute a relative interior point for the current LP.
18576	 *
18577	 *  Assume the original LP looks as follows:
18578	 *  \f[
18579	 *     \begin{array}{rrl}
18580	 *        \min & c^T x &\\
18581	 *             & A x & \geq a\\
18582	 *             & B x & \leq b\\
18583	 *             & D x & = d.
18584	 *     \end{array}
18585	 *  \f]
18586	 *  Note that bounds should be included in the system.
18587	 *
18588	 *  To find an interior point the following LP does the job:
18589	 *  \f[
18590	 *     \begin{array}{rrl}
18591	 *        \max & 1^T y &\\
18592	 *             & A x - y - \alpha a & \geq 0\\
18593	 *             & B x + y - \alpha b & \leq 0\\
18594	 *             & D x - \alpha d & = 0\\
18595	 *             & 0 \leq y & \leq 1\\
18596	 *             & \alpha & \geq 1.
18597	 *     \end{array}
18598	 *  \f]
18599	 *  If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18600	 *  \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18601	 *  particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18602	 */
18603	SCIP_RETCODE SCIPlpComputeRelIntPoint(
18604	   SCIP_SET*             set,                /**< global SCIP settings */
18605	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
18606	   SCIP_LP*              lp,                 /**< LP data */
18607	   SCIP_PROB*            prob,               /**< problem data */
18608	   SCIP_Bool             relaxrows,          /**< should the rows be relaxed */
18609	   SCIP_Bool             inclobjcutoff,      /**< should a row for the objective cutoff be included */
18610	   SCIP_Real             timelimit,          /**< time limit for LP solver */
18611	   int                   iterlimit,          /**< iteration limit for LP solver */
18612	   SCIP_Real*            point,              /**< array to store relative interior point on exit */
18613	   SCIP_Bool*            success             /**< buffer to indicate whether interior point was successfully computed */
18614	   )
18615	{
18616	   SCIP_LPI* lpi;
18617	   SCIP_RETCODE retcode;
18618	
18619	   assert(set != NULL);
18620	   assert(lp  != NULL);
18621	   assert(point != NULL);
18622	   assert(success != NULL);
18623	
18624	   *success = FALSE;
18625	
18626	   /* check time and iteration limits */
18627	   if ( timelimit <= 0.0 || iterlimit <= 0 )
18628	      return SCIP_OKAY;
18629	
18630	   /* exit if there are no columns */
18631	   assert(lp->nrows >= 0);
18632	   assert(lp->ncols >= 0);
18633	   if( lp->ncols == 0 )
18634	      return SCIP_OKAY;
18635	
18636	   /* disable objective cutoff if we have none */
18637	   if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18638	      inclobjcutoff = FALSE;
18639	
18640	   SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18641	
18642	   /* if there are no rows, we return the zero point */
18643	   if( lp->nrows == 0 && !inclobjcutoff )
18644	   {
18645	      /* create zero point */
18646	      BMSclearMemoryArray(point, lp->ncols);
18647	      *success = TRUE;
18648	
18649	      return SCIP_OKAY;
18650	   }
18651	
18652	   /* create auxiliary LP */
18653	   SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18654	
18655	   /* catch return code and ensure that lpi is freed, anyway */
18656	   retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18657	
18658	   SCIP_CALL( SCIPlpiFree(&lpi) );
18659	
18660	   /* return error, unless we obtained an LP error */
18661	   if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18662	   {
18663	      SCIP_CALL( retcode );
18664	   }
18665	
18666	   return SCIP_OKAY;
18667	}
18668	
18669	/** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18670	 *  based on the changes applied when reducing the problem to the optimal face
18671	 *
18672	 *  returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18673	 *  and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18674	 */
18675	SCIP_RETCODE SCIPlpGetDualDegeneracy(
18676	   SCIP_LP*              lp,                 /**< LP data */
18677	   SCIP_SET*             set,                /**< global SCIP settings */
18678	   SCIP_STAT*            stat,               /**< problem statistics */
18679	   SCIP_Real*            degeneracy,         /**< pointer to store the dual degeneracy rate */
18680	   SCIP_Real*            varconsratio        /**< pointer to store the variable-constraint ratio */
18681	   )
18682	{
18683	   assert(lp != NULL);
18684	   assert(lp->solved);
18685	   assert(lp->flushed);
18686	
18687	   if( lp->validdegeneracylp != stat->nlps )
18688	   {
18689	      lp->validdegeneracylp = stat->nlps;
18690	
18691	      /* if the LP was solved to optimality, we determine the dual degeneracy */
18692	      if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL )
18693	      {
18694	         SCIP_COL** cols;
18695	         SCIP_ROW** rows;
18696	         SCIP_COL* col;
18697	         int ncols;
18698	         int nrows;
18699	         int nfixedcols = 0;
18700	         int nalreadyfixedcols = 0;
18701	         int nfixedrows = 0;
18702	#ifndef NDEBUG
18703	         int nimplicitfixedrows = 0;
18704	#endif
18705	         int nineq = 0;
18706	         int c;
18707	         int r;
18708	         int nbasicequalities = 0;
18709	
18710	         cols = lp->cols;
18711	         rows = lp->rows;
18712	         ncols = lp->ncols;
18713	         nrows = lp->nrows;
18714	
18715	         /* count number of columns that will be fixed when reducing the LP to the optimal face */
18716	         for( c = ncols - 1 ; c >= 0; --c )
18717	         {
18718	            col = cols[c];
18719	            assert(SCIPcolIsInLP(col));
18720	
18721	            /* column is not basic and not fixed already */
18722	            if( (SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_BASIC) )
18723	            {
18724	               /* variable with nonzero reduced costs are fixed */
18725	               /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18726	               if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18727	                  ++nfixedcols;
18728	               else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18729	                  ++nalreadyfixedcols;
18730	            }
18731	         }
18732	
18733	         /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18734	         for( r = nrows - 1; r >= 0; --r )
18735	         {
18736	            SCIP_ROW* row = rows[r];
18737	
18738	            assert(SCIProwIsInLP(row));
18739	
18740	            if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18741	            {
18742	               SCIP_Real dualsol = SCIProwGetDualsol(row);
18743	
18744	               ++nineq;
18745	
18746	               if( (SCIProwGetBasisStatus(row) != SCIP_BASESTAT_BASIC) )
18747	               {
18748	                  /* rows with nonzero dual solution are turned into equations */
18749	                  /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18750	                  if( !SCIPsetIsZero(set, dualsol) )
18751	                  {
18752	                     if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18753	                     {
18754	                        assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol));
18755	                        ++nfixedrows;
18756	                     }
18757	                     else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18758	                     {
18759	                        assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol));
18760	                        ++nfixedrows;
18761	                     }
18762	                  }
18763	#ifndef NDEBUG
18764	                  else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18765	                     || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18766	                  {
18767	                     ++nimplicitfixedrows;
18768	                  }
18769	#endif
18770	               }
18771	            }
18772	            else if( SCIProwGetBasisStatus(row) == SCIP_BASESTAT_BASIC )
18773	               ++nbasicequalities;
18774	         }
18775	         assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18776	
18777	         if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18778	            lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18779	         else
18780	            lp->degeneracy = 0.0;
18781	
18782	         if( nrows > 0 )
18783	            lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18784	         else
18785	            lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18786	         assert(lp->degeneracy >= 0);
18787	         assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18788	         assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18789	      }
18790	      else
18791	      {
18792	         lp->degeneracy = 0.0;
18793	         lp->varconsratio = 0.0;
18794	      }
18795	   }
18796	
18797	   *degeneracy = lp->degeneracy;
18798	   *varconsratio = lp->varconsratio;
18799	
18800	   return SCIP_OKAY;
18801	}
18802	
18803	/** checks, if absolute difference of values is in range of LP primal feastol */
18804	SCIP_Bool SCIPlpIsFeasEQ(
18805	   SCIP_SET*             set,                /**< global SCIP settings */
18806	   SCIP_LP*              lp,                 /**< current LP data */
18807	   SCIP_Real             val1,               /**< first value to be compared */
18808	   SCIP_Real             val2                /**< second value to be compared */
18809	   )
18810	{
18811	   assert(set != NULL);
18812	   assert(lp != NULL);
18813	
18814	   /* avoid to compare two different infinities; the reason for that is
18815	    * that such a comparison can lead to unexpected results */
18816	   assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18817	         && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18818	      || val1 == val2 );    /*lint !e777*/
18819	
18820	   return EPSEQ(val1, val2, lp->feastol);
18821	}
18822	
18823	/** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18824	SCIP_Bool SCIPlpIsFeasLT(
18825	   SCIP_SET*             set,                /**< global SCIP settings */
18826	   SCIP_LP*              lp,                 /**< current LP data */
18827	   SCIP_Real             val1,               /**< first value to be compared */
18828	   SCIP_Real             val2                /**< second value to be compared */
18829	   )
18830	{
18831	   assert(set != NULL);
18832	   assert(lp != NULL);
18833	
18834	   /* avoid to compare two different infinities; the reason for that is
18835	    * that such a comparison can lead to unexpected results */
18836	   assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18837	         && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18838	      || val1 == val2 );    /*lint !e777*/
18839	
18840	   return EPSLT(val1, val2, lp->feastol);
18841	}
18842	
18843	/** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18844	SCIP_Bool SCIPlpIsFeasLE(
18845	   SCIP_SET*             set,                /**< global SCIP settings */
18846	   SCIP_LP*              lp,                 /**< current LP data */
18847	   SCIP_Real             val1,               /**< first value to be compared */
18848	   SCIP_Real             val2                /**< second value to be compared */
18849	   )
18850	{
18851	   assert(set != NULL);
18852	   assert(lp != NULL);
18853	
18854	   /* avoid to compare two different infinities; the reason for that is
18855	    * that such a comparison can lead to unexpected results */
18856	   assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18857	         && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18858	      || val1 == val2 );    /*lint !e777*/
18859	
18860	   return EPSLE(val1, val2, lp->feastol);
18861	}
18862	
18863	/** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18864	SCIP_Bool SCIPlpIsFeasGT(
18865	   SCIP_SET*             set,                /**< global SCIP settings */
18866	   SCIP_LP*              lp,                 /**< current LP data */
18867	   SCIP_Real             val1,               /**< first value to be compared */
18868	   SCIP_Real             val2                /**< second value to be compared */
18869	   )
18870	{
18871	   assert(set != NULL);
18872	   assert(lp != NULL);
18873	
18874	   /* avoid to compare two different infinities; the reason for that is
18875	    * that such a comparison can lead to unexpected results */
18876	   assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18877	         && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18878	      || val1 == val2 );    /*lint !e777*/
18879	
18880	   return EPSGT(val1, val2, lp->feastol);
18881	}
18882	
18883	/** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18884	SCIP_Bool SCIPlpIsFeasGE(
18885	   SCIP_SET*             set,                /**< global SCIP settings */
18886	   SCIP_LP*              lp,                 /**< current LP data */
18887	   SCIP_Real             val1,               /**< first value to be compared */
18888	   SCIP_Real             val2                /**< second value to be compared */
18889	   )
18890	{
18891	   assert(set != NULL);
18892	   assert(lp != NULL);
18893	
18894	   /* avoid to compare two different infinities; the reason for that is
18895	    * that such a comparison can lead to unexpected results */
18896	   assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18897	         && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18898	      || val1 == val2 );    /*lint !e777*/
18899	
18900	   return EPSGE(val1, val2, lp->feastol);
18901	}
18902	
18903	/** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18904	SCIP_Bool SCIPlpIsFeasZero(
18905	   SCIP_LP*              lp,                 /**< current LP data */
18906	   SCIP_Real             val                 /**< value to process */
18907	   )
18908	{
18909	   assert(lp != NULL);
18910	
18911	   return EPSZ(val, lp->feastol);
18912	}
18913	
18914	/** checks, if value is greater than LP primal feasibility tolerance */
18915	SCIP_Bool SCIPlpIsFeasPositive(
18916	   SCIP_LP*              lp,                 /**< current LP data */
18917	   SCIP_Real             val                 /**< value to process */
18918	   )
18919	{
18920	   assert(lp != NULL);
18921	
18922	   return EPSP(val, lp->feastol);
18923	}
18924	
18925	/** checks, if value is lower than -LP primal feasibility tolerance */
18926	SCIP_Bool SCIPlpIsFeasNegative(
18927	   SCIP_LP*              lp,                 /**< current LP data */
18928	   SCIP_Real             val                 /**< value to process */
18929	   )
18930	{
18931	   assert(lp != NULL);
18932	
18933	   return EPSN(val, lp->feastol);
18934	}
18935