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   prob.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  Methods and datastructures for storing and manipulating the main problem
28   	 * @author Tobias Achterberg
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include "scip/branch.h"
34   	#include "scip/conflictstore.h"
35   	#include "scip/cons.h"
36   	#include "scip/event.h"
37   	#include "scip/lp.h"
38   	#include "scip/primal.h"
39   	#include "scip/prob.h"
40   	#include "scip/pub_cons.h"
41   	#include "scip/pub_lp.h"
42   	#include "scip/pub_message.h"
43   	#include "scip/pub_misc.h"
44   	#include "scip/pub_misc_sort.h"
45   	#include "scip/pub_var.h"
46   	#include "scip/set.h"
47   	#include "scip/stat.h"
48   	#include "scip/struct_cons.h"
49   	#include "scip/struct_lp.h"
50   	#include "scip/struct_prob.h"
51   	#include "scip/struct_set.h"
52   	#include "scip/struct_stat.h"
53   	#include "scip/struct_var.h"
54   	#include "scip/var.h"
55   	#include <string.h>
56   	
57   	
58   	#define OBJSCALE_MAXDNOM          1000000LL  /**< maximal denominator in objective integral scaling */
59   	#define OBJSCALE_MAXSCALE         1000000.0  /**< maximal scalar to reach objective integrality */
60   	#define OBJSCALE_MAXFINALSCALE       1000.0  /**< maximal final value to apply as scaling */
61   	
62   	
63   	
64   	/*
65   	 * dymanic memory arrays
66   	 */
67   	
68   	/** resizes vars array to be able to store at least num entries */
69   	static
70   	SCIP_RETCODE probEnsureVarsMem(
71   	   SCIP_PROB*            prob,               /**< problem data */
72   	   SCIP_SET*             set,                /**< global SCIP settings */
73   	   int                   num                 /**< minimal number of slots in array */
74   	   )
75   	{
76   	   assert(prob != NULL);
77   	   assert(set != NULL);
78   	
79   	   if( num > prob->varssize )
80   	   {
81   	      int newsize;
82   	
83   	      newsize = SCIPsetCalcMemGrowSize(set, num);
84   	      SCIP_ALLOC( BMSreallocMemoryArray(&prob->vars, newsize) );
85   	      prob->varssize = newsize;
86   	   }
87   	   assert(num <= prob->varssize);
88   	
89   	   return SCIP_OKAY;
90   	}
91   	
92   	/** resizes fixedvars array to be able to store at least num entries */
93   	static
94   	SCIP_RETCODE probEnsureFixedvarsMem(
95   	   SCIP_PROB*            prob,               /**< problem data */
96   	   SCIP_SET*             set,                /**< global SCIP settings */
97   	   int                   num                 /**< minimal number of slots in array */
98   	   )
99   	{
100  	   assert(prob != NULL);
101  	   assert(set != NULL);
102  	
103  	   if( num > prob->fixedvarssize )
104  	   {
105  	      int newsize;
106  	
107  	      newsize = SCIPsetCalcMemGrowSize(set, num);
108  	      SCIP_ALLOC( BMSreallocMemoryArray(&prob->fixedvars, newsize) );
109  	      prob->fixedvarssize = newsize;
110  	   }
111  	   assert(num <= prob->fixedvarssize);
112  	
113  	   return SCIP_OKAY;
114  	}
115  	
116  	/** resizes deletedvars array to be able to store at least num entries */
117  	static
118  	SCIP_RETCODE probEnsureDeletedvarsMem(
119  	   SCIP_PROB*            prob,               /**< problem data */
120  	   SCIP_SET*             set,                /**< global SCIP settings */
121  	   int                   num                 /**< minimal number of slots in array */
122  	   )
123  	{
124  	   assert(prob != NULL);
125  	   assert(set != NULL);
126  	
127  	   if( num > prob->deletedvarssize )
128  	   {
129  	      int newsize;
130  	
131  	      newsize = SCIPsetCalcMemGrowSize(set, num);
132  	      SCIP_ALLOC( BMSreallocMemoryArray(&prob->deletedvars, newsize) );
133  	      prob->deletedvarssize = newsize;
134  	   }
135  	   assert(num <= prob->deletedvarssize);
136  	
137  	   return SCIP_OKAY;
138  	}
139  	
140  	/** resizes conss array to be able to store at least num entries */
141  	static
142  	SCIP_RETCODE probEnsureConssMem(
143  	   SCIP_PROB*            prob,               /**< problem data */
144  	   SCIP_SET*             set,                /**< global SCIP settings */
145  	   int                   num                 /**< minimal number of slots in array */
146  	   )
147  	{
148  	   assert(prob != NULL);
149  	   assert(set != NULL);
150  	
151  	   if( num > prob->consssize )
152  	   {
153  	      int newsize;
154  	
155  	      newsize = SCIPsetCalcMemGrowSize(set, num);
156  	      SCIP_ALLOC( BMSreallocMemoryArray(&prob->conss, newsize) );
157  	      /* resize sorted original constraints if they exist */
158  	      if( prob->origcheckconss != NULL )
159  	      {
160  	         SCIP_ALLOC( BMSreallocMemoryArray(&prob->origcheckconss, newsize) );
161  	      }
162  	      prob->consssize = newsize;
163  	   }
164  	   assert(num <= prob->consssize);
165  	
166  	   return SCIP_OKAY;
167  	}
168  	
169  	/** returns whether the constraint has a name */
170  	static
171  	SCIP_Bool consHasName(
172  	   SCIP_CONS*            cons                /**< constraint */
173  	   )
174  	{
175  	   const char* name;
176  	
177  	   name = SCIPconsGetName(cons);
178  	
179  	   return (name != NULL && name[0] != '\0');
180  	}
181  	
182  	/** returns whether the variable has a name */
183  	static
184  	SCIP_Bool varHasName(
185  	   SCIP_VAR*             var                 /**< variable */
186  	   )
187  	{
188  	   const char* name;
189  	
190  	   name = SCIPvarGetName(var);
191  	
192  	   return (name != NULL && name[0] != '\0');
193  	}
194  	
195  	
196  	
197  	/*
198  	 * problem creation
199  	 */
200  	
201  	/** creates problem data structure by copying the source problem
202  	 *
203  	 *  If the problem type requires the use of variable pricers, these pricers should be activated with calls
204  	 *  to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
205  	 */
206  	SCIP_RETCODE SCIPprobCopy(
207  	   SCIP_PROB**           prob,               /**< pointer to problem data structure */
208  	   BMS_BLKMEM*           blkmem,             /**< block memory */
209  	   SCIP_SET*             set,                /**< global SCIP settings */
210  	   const char*           name,               /**< problem name */
211  	   SCIP*                 sourcescip,         /**< source SCIP data structure */
212  	   SCIP_PROB*            sourceprob,         /**< source problem structure */
213  	   SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
214  	                                              *   target variables */
215  	   SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
216  	                                              *   target constraints */
217  	   SCIP_Bool             original,           /**< copy original or transformed problem? */
218  	   SCIP_Bool             global              /**< create a global or a local copy? */
219  	   )
220  	{
221  	   SCIP_PROBDATA* targetdata = NULL;
222  	   SCIP_RESULT result = SCIP_DIDNOTRUN;
223  	
224  	   assert(prob != NULL);
225  	   assert(set != NULL);
226  	   assert(blkmem != NULL);
227  	   assert(sourcescip != NULL);
228  	   assert(sourceprob != NULL);
229  	   assert(varmap != NULL);
230  	   assert(consmap != NULL);
231  	
232  	   /* create problem and initialize callbacks with NULL */
233  	   SCIP_CALL( SCIPprobCreate(prob, blkmem, set, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL, FALSE) );
234  	
235  	   /* call user copy callback method */
236  	   if( sourceprob->probdata != NULL && sourceprob->probcopy != NULL )
237  	   {
238  	      SCIP_CALL( sourceprob->probcopy(set->scip, sourcescip, sourceprob->probdata, varmap, consmap, &targetdata, original, global, &result) );
239  	
240  	      /* evaluate result */
241  	      if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
242  	      {
243  	         SCIPerrorMessage("probdata copying method returned invalid result <%d>\n", result);
244  	         return SCIP_INVALIDRESULT;
245  	      }
246  	
247  	      assert(targetdata == NULL || result == SCIP_SUCCESS);
248  	
249  	      /* if copying was successful, add data and callbacks */
250  	      if( result == SCIP_SUCCESS )
251  	      {
252  	         assert( targetdata != NULL );
253  	         (*prob)->probdelorig = sourceprob->probdelorig;
254  	         (*prob)->probtrans = sourceprob->probtrans;
255  	         (*prob)->probdeltrans = sourceprob->probdeltrans;
256  	         (*prob)->probinitsol = sourceprob->probinitsol;
257  	         (*prob)->probexitsol = sourceprob->probexitsol;
258  	         (*prob)->probcopy = sourceprob->probcopy;
259  	         (*prob)->probdata = targetdata;
260  	      }
261  	   }
262  	
263  	   return SCIP_OKAY;
264  	}
265  	
266  	/** creates problem data structure
267  	 *  If the problem type requires the use of variable pricers, these pricers should be activated with calls
268  	 *  to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
269  	 */
270  	SCIP_RETCODE SCIPprobCreate(
271  	   SCIP_PROB**           prob,               /**< pointer to problem data structure */
272  	   BMS_BLKMEM*           blkmem,             /**< block memory */
273  	   SCIP_SET*             set,                /**< global SCIP settings */
274  	   const char*           name,               /**< problem name */
275  	   SCIP_DECL_PROBDELORIG ((*probdelorig)),   /**< frees user data of original problem */
276  	   SCIP_DECL_PROBTRANS   ((*probtrans)),     /**< creates user data of transformed problem by transforming original user data */
277  	   SCIP_DECL_PROBDELTRANS((*probdeltrans)),  /**< frees user data of transformed problem */
278  	   SCIP_DECL_PROBINITSOL ((*probinitsol)),   /**< solving process initialization method of transformed data */
279  	   SCIP_DECL_PROBEXITSOL ((*probexitsol)),   /**< solving process deinitialization method of transformed data */
280  	   SCIP_DECL_PROBCOPY    ((*probcopy)),      /**< copies user data if you want to copy it to a subscip, or NULL */
281  	   SCIP_PROBDATA*        probdata,           /**< user problem data set by the reader */
282  	   SCIP_Bool             transformed         /**< is this the transformed problem? */
283  	   )
284  	{
285  	   assert(prob != NULL);
286  	
287  	   SCIP_ALLOC( BMSallocMemory(prob) );
288  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*prob)->name, name, strlen(name)+1) );
289  	
290  	   (*prob)->probdata = probdata;
291  	   (*prob)->probcopy = probcopy;
292  	   (*prob)->probdelorig = probdelorig;
293  	   (*prob)->probtrans = probtrans;
294  	   (*prob)->probdeltrans = probdeltrans;
295  	   (*prob)->probinitsol = probinitsol;
296  	   (*prob)->probexitsol = probexitsol;
297  	   if( set->misc_usevartable )
298  	   {
299  	      SCIP_CALL( SCIPhashtableCreate(&(*prob)->varnames, blkmem,
300  	            (set->misc_usesmalltables ? SCIP_HASHSIZE_NAMES_SMALL : SCIP_HASHSIZE_NAMES),
301  	            SCIPhashGetKeyVar, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
302  	   }
303  	   else
304  	      (*prob)->varnames = NULL;
305  	   (*prob)->vars = NULL;
306  	   (*prob)->varssize = 0;
307  	   (*prob)->nvars = 0;
308  	   (*prob)->nbinvars = 0;
309  	   (*prob)->nintvars = 0;
310  	   (*prob)->nimplvars = 0;
311  	   (*prob)->ncontvars = 0;
312  	   (*prob)->ncolvars = 0;
313  	   (*prob)->fixedvars = NULL;
314  	   (*prob)->fixedvarssize = 0;
315  	   (*prob)->nfixedvars = 0;
316  	   (*prob)->deletedvars = NULL;
317  	   (*prob)->deletedvarssize = 0;
318  	   (*prob)->ndeletedvars = 0;
319  	   (*prob)->nobjvars = 0;
320  	   if( set->misc_useconstable )
321  	   {
322  	      SCIP_CALL( SCIPhashtableCreate(&(*prob)->consnames, blkmem,
323  	            (set->misc_usesmalltables ? SCIP_HASHSIZE_NAMES_SMALL : SCIP_HASHSIZE_NAMES),
324  	            SCIPhashGetKeyCons, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
325  	   }
326  	   else
327  	      (*prob)->consnames = NULL;
328  	   (*prob)->conss = NULL;
329  	   (*prob)->origcheckconss = NULL;
330  	   (*prob)->consssize = 0;
331  	   (*prob)->nconss = 0;
332  	   (*prob)->maxnconss = 0;
333  	   (*prob)->startnvars = 0;
334  	   (*prob)->startnconss = 0;
335  	   (*prob)->objsense = SCIP_OBJSENSE_MINIMIZE;
336  	   (*prob)->objoffset = 0.0;
337  	   (*prob)->objscale = 1.0;
338  	   (*prob)->objlim = SCIP_INVALID;
339  	   (*prob)->dualbound = SCIP_INVALID;
340  	   (*prob)->objisintegral = FALSE;
341  	   (*prob)->transformed = transformed;
342  	   (*prob)->nlpenabled = FALSE;
343  	   (*prob)->permuted = FALSE;
344  	   (*prob)->consschecksorted = FALSE;
345  	   (*prob)->conscompression = FALSE;
346  	
347  	   return SCIP_OKAY;
348  	}
349  	
350  	/** sets callback to free user data of original problem */
351  	void SCIPprobSetDelorig(
352  	   SCIP_PROB*            prob,               /**< problem */
353  	   SCIP_DECL_PROBDELORIG ((*probdelorig))    /**< frees user data of original problem */
354  	   )
355  	{
356  	   assert(prob != NULL);
357  	
358  	   prob->probdelorig = probdelorig;
359  	}
360  	
361  	/** sets callback to create user data of transformed problem by transforming original user data */
362  	void SCIPprobSetTrans(
363  	   SCIP_PROB*            prob,               /**< problem */
364  	   SCIP_DECL_PROBTRANS   ((*probtrans))      /**< creates user data of transformed problem by transforming original user data */
365  	   )
366  	{
367  	   assert(prob != NULL);
368  	
369  	   prob->probtrans = probtrans;
370  	}
371  	
372  	/** sets callback to free user data of transformed problem */
373  	void SCIPprobSetDeltrans(
374  	   SCIP_PROB*            prob,               /**< problem */
375  	   SCIP_DECL_PROBDELTRANS((*probdeltrans))   /**< frees user data of transformed problem */
376  	   )
377  	{
378  	   assert(prob != NULL);
379  	
380  	   prob->probdeltrans = probdeltrans;
381  	}
382  	
383  	/** sets solving process initialization callback of transformed data */
384  	void SCIPprobSetInitsol(
385  	   SCIP_PROB*            prob,               /**< problem */
386  	   SCIP_DECL_PROBINITSOL ((*probinitsol))    /**< solving process initialization callback of transformed data */
387  	   )
388  	{
389  	   assert(prob != NULL);
390  	
391  	   prob->probinitsol= probinitsol;
392  	}
393  	
394  	/** sets solving process deinitialization callback of transformed data */
395  	void SCIPprobSetExitsol(
396  	   SCIP_PROB*            prob,               /**< problem */
397  	   SCIP_DECL_PROBEXITSOL ((*probexitsol))    /**< solving process deinitialization callback of transformed data */
398  	   )
399  	{
400  	   assert(prob != NULL);
401  	
402  	   prob->probexitsol= probexitsol;
403  	}
404  	
405  	/** sets callback to copy user data to copy it to a subscip, or NULL */
406  	void SCIPprobSetCopy(
407  	   SCIP_PROB*            prob,               /**< problem */
408  	   SCIP_DECL_PROBCOPY    ((*probcopy))       /**< copies user data if you want to copy it to a subscip, or NULL */
409  	   )
410  	{
411  	   assert(prob != NULL);
412  	
413  	   prob->probcopy= probcopy;
414  	}
415  	
416  	/** frees problem data structure */
417  	SCIP_RETCODE SCIPprobFree(
418  	   SCIP_PROB**           prob,               /**< pointer to problem data structure */
419  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
420  	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
421  	   SCIP_SET*             set,                /**< global SCIP settings */
422  	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
423  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
424  	   SCIP_LP*              lp                  /**< current LP data (or NULL, if it's the original problem) */
425  	   )
426  	{
427  	   int v;
428  	#ifndef NDEBUG
429  	   SCIP_Bool unreleasedvar = FALSE;
430  	#endif
431  	
432  	   assert(prob != NULL);
433  	   assert(*prob != NULL);
434  	   assert(set != NULL);
435  	
436  	   /* remove all constraints from the problem */
437  	   while( (*prob)->nconss > 0 )
438  	   {
439  	      /*@todo for debug mode it even might sense, to sort them downwards after their arraypos */
440  	      assert((*prob)->conss != NULL);
441  	      SCIP_CALL( SCIPprobDelCons(*prob, blkmem, set, stat, (*prob)->conss[(*prob)->nconss - 1]) );
442  	   }
443  	
444  	   if( (*prob)->transformed )
445  	   {
446  	      int h;
447  	
448  	      /* unlock variables for all constraint handlers that don't need constraints */
449  	      for( h = 0; h < set->nconshdlrs; ++h )
450  	      {
451  	         if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
452  	         {
453  	            SCIP_CALL( SCIPconshdlrUnlockVars(set->conshdlrs[h], set) );
454  	         }
455  	      }
456  	   }
457  	
458  	   /* free constraint array */
459  	   BMSfreeMemoryArrayNull(&(*prob)->origcheckconss);
460  	   BMSfreeMemoryArrayNull(&(*prob)->conss);
461  	
462  	   /* free user problem data */
463  	   if( (*prob)->transformed )
464  	   {
465  	      if( (*prob)->probdeltrans != NULL )
466  	      {
467  	         SCIP_CALL( (*prob)->probdeltrans(set->scip, &(*prob)->probdata) );
468  	      }
469  	   }
470  	   else
471  	   {
472  	      if( (*prob)->probdelorig != NULL )
473  	      {
474  	         SCIP_CALL( (*prob)->probdelorig(set->scip, &(*prob)->probdata) );
475  	      }
476  	   }
477  	
478  	   /* release problem variables */
479  	   for( v = (*prob)->nvars - 1; v >= 0; --v )
480  	   {
481  	      assert(SCIPvarGetProbindex((*prob)->vars[v]) >= 0);
482  	
483  	      if( SCIPvarGetNUses((*prob)->vars[v]) > 1 )
484  	      {
485  	         SCIPmessageFPrintWarning(messagehdlr, "%s variable <%s> not released when freeing SCIP problem <%s>.\n",
486  	            (*prob)->transformed ? "Transformed" : "Original", SCIPvarGetName((*prob)->vars[v]), SCIPprobGetName(*prob));
487  	#ifndef NDEBUG
488  	         unreleasedvar = TRUE;
489  	#endif
490  	      }
491  	
492  	      SCIP_CALL( SCIPvarRemove((*prob)->vars[v], blkmem, NULL, set, TRUE) );
493  	      SCIP_CALL( SCIPvarRelease(&(*prob)->vars[v], blkmem, set, eventqueue, lp) );
494  	   }
495  	   BMSfreeMemoryArrayNull(&(*prob)->vars);
496  	
497  	   /* release fixed problem variables */
498  	   for( v = (*prob)->nfixedvars - 1; v >= 0; --v )
499  	   {
500  	      assert(SCIPvarGetProbindex((*prob)->fixedvars[v]) == -1);
501  	
502  	      if( SCIPvarGetNUses((*prob)->fixedvars[v]) > 1 )
503  	      {
504  	         SCIPmessageFPrintWarning(messagehdlr, "%s variable <%s> not released when freeing SCIP problem <%s>.\n",
505  	            (*prob)->transformed ? "Transformed" : "Original", SCIPvarGetName((*prob)->fixedvars[v]), SCIPprobGetName(*prob));
506  	#ifndef NDEBUG
507  	         unreleasedvar = TRUE;
508  	#endif
509  	      }
510  	
511  	      SCIP_CALL( SCIPvarRelease(&(*prob)->fixedvars[v], blkmem, set, eventqueue, lp) );
512  	   }
513  	   BMSfreeMemoryArrayNull(&(*prob)->fixedvars);
514  	
515  	   assert(! unreleasedvar);
516  	
517  	   /* free deleted problem variables array */
518  	   BMSfreeMemoryArrayNull(&(*prob)->deletedvars);
519  	
520  	   /* free hash tables for names */
521  	   if( (*prob)->varnames != NULL )
522  	   {
523  	      SCIPhashtableFree(&(*prob)->varnames);
524  	   }
525  	   if( (*prob)->consnames != NULL )
526  	   {
527  	      SCIPhashtableFree(&(*prob)->consnames);
528  	   }
529  	   BMSfreeMemoryArray(&(*prob)->name);
530  	   BMSfreeMemory(prob);
531  	
532  	   return SCIP_OKAY;
533  	}
534  	
535  	/** transform problem data into normalized form */
536  	SCIP_RETCODE SCIPprobTransform(
537  	   SCIP_PROB*            source,             /**< problem to transform */
538  	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
539  	   SCIP_SET*             set,                /**< global SCIP settings */
540  	   SCIP_STAT*            stat,               /**< problem statistics */
541  	   SCIP_PRIMAL*          primal,             /**< primal data */
542  	   SCIP_TREE*            tree,               /**< branch and bound tree */
543  	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
544  	   SCIP_LP*              lp,                 /**< current LP data */
545  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
546  	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
547  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
548  	   SCIP_CONFLICTSTORE*   conflictstore,      /**< conflict store */
549  	   SCIP_PROB**           target              /**< pointer to target problem data structure */
550  	   )
551  	{
552  	   SCIP_VAR* targetvar;
553  	   SCIP_CONS* targetcons;
554  	   char transname[SCIP_MAXSTRLEN];
555  	   int v;
556  	   int c;
557  	   int h;
558  	
559  	   assert(set != NULL);
560  	   assert(source != NULL);
561  	   assert(blkmem != NULL);
562  	   assert(target != NULL);
563  	
564  	   SCIPsetDebugMsg(set, "transform problem: original has %d variables\n", source->nvars);
565  	
566  	   /* create target problem data (probdelorig and probtrans are not needed, probdata is set later) */
567  	   (void) SCIPsnprintf(transname, SCIP_MAXSTRLEN, "t_%s", source->name);
568  	   SCIP_CALL( SCIPprobCreate(target, blkmem, set, transname, source->probdelorig, source->probtrans, source->probdeltrans, 
569  	         source->probinitsol, source->probexitsol, source->probcopy, NULL, TRUE) );
570  	   SCIPprobSetObjsense(*target, source->objsense);
571  	
572  	   /* transform objective limit */
573  	   if( source->objlim < SCIP_INVALID )
574  	      SCIPprobSetObjlim(*target, source->objlim);
575  	
576  	   /* transform dual bound */
577  	   if( source->dualbound < SCIP_INVALID )
578  	      SCIPprobSetDualbound(*target, source->dualbound);
579  	
580  	   /* transform and copy all variables to target problem */
581  	   SCIP_CALL( probEnsureVarsMem(*target, set, source->nvars) );
582  	   for( v = 0; v < source->nvars; ++v )
583  	   {
584  	      SCIP_CALL( SCIPvarTransform(source->vars[v], blkmem, set, stat, source->objsense, &targetvar) );
585  	      SCIP_CALL( SCIPprobAddVar(*target, blkmem, set, lp, branchcand, eventfilter, eventqueue, targetvar) );
586  	      SCIP_CALL( SCIPvarRelease(&targetvar, blkmem, set, eventqueue, NULL) );
587  	   }
588  	   assert((*target)->nvars == source->nvars);
589  	   assert((*target)->nobjvars == SCIPprobGetNObjVars(*target, set));
590  	
591  	   /* call user data transformation */
592  	   if( source->probtrans != NULL )
593  	   {
594  	      SCIP_CALL( source->probtrans(set->scip, source->probdata, &(*target)->probdata) );
595  	   }
596  	   else
597  	      (*target)->probdata = source->probdata;
598  	
599  	   /* transform and copy all constraints to target problem */
600  	   for( c = 0; c < source->nconss; ++c )
601  	   {
602  	      SCIP_CALL( SCIPconsTransform(source->conss[c], blkmem, set, &targetcons) );
603  	      SCIP_CALL( SCIPprobAddCons(*target, set, stat, targetcons) );
604  	      SCIP_CALL( SCIPconsRelease(&targetcons, blkmem, set) );
605  	   }
606  	
607  	   /* lock variables for all constraint handlers that don't need constraints */
608  	   for( h = 0; h < set->nconshdlrs; ++h )
609  	   {
610  	      if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
611  	      {
612  	         SCIP_CALL( SCIPconshdlrLockVars(set->conshdlrs[h], set) );
613  	      }
614  	   }
615  	
616  	   /* objective value is always integral, iff original objective value is always integral and shift is integral */
617  	   (*target)->objisintegral = source->objisintegral && SCIPsetIsIntegral(set, (*target)->objoffset);
618  	
619  	   /* check, whether objective value is always integral by inspecting the problem, if it is the case adjust the
620  	    * cutoff bound if primal solution is already known 
621  	    */
622  	   SCIP_CALL( SCIPprobCheckObjIntegral(*target, source, blkmem, set, stat, primal, tree, reopt, lp, eventfilter, eventqueue) );
623  	
624  	   /* copy the nlpenabled flag */
625  	   (*target)->nlpenabled = source->nlpenabled;
626  	
627  	   /* mark the transformed problem to be permuted iff the source problem is permuted */
628  	   (*target)->permuted = source->permuted;
629  	
630  	   /* transform the conflict pool */
631  	   SCIP_CALL( SCIPconflictstoreTransform(conflictstore, blkmem, set, stat, tree, *target, reopt) );
632  	
633  	   return SCIP_OKAY;
634  	}
635  	
636  	/** resets the global and local bounds of original variables in original problem to their original values */
637  	SCIP_RETCODE SCIPprobResetBounds(
638  	   SCIP_PROB*            prob,               /**< original problem data */
639  	   BMS_BLKMEM*           blkmem,             /**< block memory */
640  	   SCIP_SET*             set,                /**< global SCIP settings */
641  	   SCIP_STAT*            stat                /**< problem statistics */
642  	   )
643  	{
644  	   int v;
645  	
646  	   assert(prob != NULL);
647  	   assert(prob->nfixedvars == 0);
648  	
649  	   for( v = 0; v < prob->nvars; ++v )
650  	   {
651  	      SCIP_CALL( SCIPvarResetBounds(prob->vars[v], blkmem, set, stat) );
652  	   }
653  	
654  	   return SCIP_OKAY;
655  	}
656  	
657  	/** (Re)Sort the variables, which appear in the four categories (binary, integer, implicit, continuous) after presolve
658  	 *  with respect to their original index (within their categories). Adjust the problem index afterwards which is
659  	 *  supposed to reflect the position in the variable array. This additional (re)sorting is supposed to get more robust
660  	 *  against the order presolving fixed variables. (We also reobtain a possible block structure induced by the user
661  	 *  model)
662  	 */
663  	void SCIPprobResortVars(
664  	   SCIP_PROB*            prob                /**< problem data */
665  	   )
666  	{
667  	   SCIP_VAR** vars;
668  	   int nbinvars;
669  	   int nintvars;
670  	   int nimplvars;
671  	   int ncontvars;
672  	   int nvars;
673  	   int v;
674  	
675  	   vars = prob->vars;
676  	   nvars = prob->nvars;
677  	   nbinvars = prob->nbinvars;
678  	   nintvars = prob->nintvars;
679  	   nimplvars = prob->nimplvars;
680  	   ncontvars = prob->ncontvars;
681  	
682  	   if( nvars == 0 )
683  	      return;
684  	
685  	   assert(vars != NULL);
686  	   assert(nbinvars + nintvars + nimplvars + ncontvars == nvars);
687  	
688  	   SCIPdebugMessage("entering sorting with respect to original block structure! \n");
689  	
690  	   /* sort binaries */
691  	   if( nbinvars > 0 )
692  	      SCIPsortPtr((void**)vars, SCIPvarComp, nbinvars);
693  	
694  	   /* sort integers */
695  	   if( nintvars > 0 )
696  	      SCIPsortPtr((void**)&vars[nbinvars], SCIPvarComp, nintvars);
697  	
698  	   /* sort implicit variables */
699  	   if( nimplvars > 0 )
700  	      SCIPsortPtr((void**)&vars[nbinvars + nintvars], SCIPvarComp, nimplvars);
701  	
702  	   /* sort continuous variables*/
703  	   if( ncontvars > 0 )
704  	      SCIPsortPtr((void**)&vars[nbinvars + nintvars + nimplvars], SCIPvarComp, ncontvars);
705  	
706  	   /* after sorting, the problem index of each variable has to be adjusted */
707  	   for( v = 0; v < nvars; ++v )
708  	   {
709  	      vars[v]->probindex = v;
710  	      SCIPdebugMessage("Variable: Problem index <%d>, original index <%d> \n", vars[v]->probindex, vars[v]->index);
711  	   }
712  	}
713  	
714  	/** possibly create and sort the constraints according to check priorties */
715  	SCIP_RETCODE SCIPprobSortConssCheck(
716  	   SCIP_PROB*            prob                /**< problem data */
717  	   )
718  	{
719  	   if( prob->consschecksorted || prob->transformed )
720  	      return SCIP_OKAY;
721  	
722  	   if( prob->nconss > 0 )
723  	   {
724  	      /* possibly create and copy constraints */
725  	      if( prob->origcheckconss == NULL )
726  	      {
727  	         SCIP_ALLOC( BMSduplicateMemoryArray(&prob->origcheckconss, prob->conss, prob->consssize) );
728  	      }
729  	      assert( prob->origcheckconss != NULL );
730  	
731  	      /* sort original constraint according to check priority */
732  	      SCIPsortPtr((void**)prob->origcheckconss, SCIPconsCompCheck, prob->nconss);
733  	   }
734  	   prob->consschecksorted = TRUE;
735  	
736  	   return SCIP_OKAY;
737  	}
738  	
739  	
740  	/*
741  	 * problem modification
742  	 */
743  	
744  	/** sets user problem data */
745  	void SCIPprobSetData(
746  	   SCIP_PROB*            prob,               /**< problem */
747  	   SCIP_PROBDATA*        probdata            /**< user problem data to use */
748  	   )
749  	{
750  	   assert(prob != NULL);
751  	
752  	   prob->probdata = probdata;
753  	}
754  	
755  	/** inserts variable at the correct position in vars array, depending on its type */
756  	static
757  	void probInsertVar(
758  	   SCIP_PROB*            prob,               /**< problem data */
759  	   SCIP_VAR*             var                 /**< variable to insert */
760  	   )
761  	{
762  	   int insertpos;
763  	   int intstart;
764  	   int implstart;
765  	   int contstart;
766  	
767  	   assert(prob != NULL);
768  	   assert(prob->vars != NULL);
769  	   assert(prob->nvars < prob->varssize);
770  	   assert(var != NULL);
771  	   assert(SCIPvarGetProbindex(var) == -1);
772  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
773  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
774  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
775  	   /* original variables cannot go into transformed problem and transformed variables cannot go into original problem */
776  	   assert((SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL) == prob->transformed);
777  	
778  	   /* insert variable in array */
779  	   insertpos = prob->nvars;
780  	   intstart = prob->nbinvars;
781  	   implstart = intstart + prob->nintvars;
782  	   contstart = implstart + prob->nimplvars;
783  	
784  	   if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
785  	      prob->ncontvars++;
786  	   else
787  	   {
788  	      if( insertpos > contstart )
789  	      {
790  	         prob->vars[insertpos] = prob->vars[contstart];
791  	         SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
792  	         insertpos = contstart;
793  	      }
794  	      assert(insertpos == contstart);
795  	
796  	      if( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT )
797  	         prob->nimplvars++;
798  	      else
799  	      {
800  	         if( insertpos > implstart )
801  	         {
802  	            prob->vars[insertpos] = prob->vars[implstart];
803  	            SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
804  	            insertpos = implstart;
805  	         }
806  	         assert(insertpos == implstart);
807  	
808  	         if( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
809  	            prob->nintvars++;
810  	         else
811  	         {
812  	            assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
813  	            if( insertpos > intstart )
814  	            {
815  	               prob->vars[insertpos] = prob->vars[intstart];
816  	               SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
817  	               insertpos = intstart;
818  	            }
819  	            assert(insertpos == intstart);
820  	
821  	            prob->nbinvars++;
822  	         }
823  	      }
824  	   }
825  	   prob->nvars++;
826  	
827  	   assert(prob->nvars == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars);
828  	   assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && insertpos == prob->nbinvars - 1)
829  	      || (SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER && insertpos == prob->nbinvars + prob->nintvars - 1)
830  	      || (SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT && insertpos == prob->nbinvars + prob->nintvars + prob->nimplvars - 1)
831  	      || (SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS
832  	         && insertpos == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars - 1));
833  	
834  	   prob->vars[insertpos] = var;
835  	   SCIPvarSetProbindex(var, insertpos);
836  	
837  	   /* update number of column variables in problem */
838  	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
839  	      prob->ncolvars++;
840  	   assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
841  	}
842  	
843  	/** removes variable from vars array */
844  	static
845  	SCIP_RETCODE probRemoveVar(
846  	   SCIP_PROB*            prob,               /**< problem data */
847  	   BMS_BLKMEM*           blkmem,             /**< block memory */
848  	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
849  	   SCIP_SET*             set,                /**< global SCIP settings */
850  	   SCIP_VAR*             var                 /**< variable to remove */
851  	   )
852  	{
853  	   int freepos;
854  	   int intstart;
855  	   int implstart;
856  	   int contstart;
857  	
858  	   assert(prob != NULL);
859  	   assert(var != NULL);
860  	   assert(SCIPvarGetProbindex(var) >= 0);
861  	   assert(prob->vars != NULL);
862  	   assert(prob->vars[SCIPvarGetProbindex(var)] == var);
863  	
864  	   intstart = prob->nbinvars;
865  	   implstart = intstart + prob->nintvars;
866  	   contstart = implstart + prob->nimplvars;
867  	
868  	   switch( SCIPvarGetType(var) )
869  	   {
870  	   case SCIP_VARTYPE_BINARY:
871  	      assert(0 <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < intstart);
872  	      prob->nbinvars--;
873  	      break;
874  	   case SCIP_VARTYPE_INTEGER:
875  	      assert(intstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < implstart);
876  	      prob->nintvars--;
877  	      break;
878  	   case SCIP_VARTYPE_IMPLINT:
879  	      assert(implstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < contstart);
880  	      prob->nimplvars--;
881  	      break;
882  	   case SCIP_VARTYPE_CONTINUOUS:
883  	      assert(contstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < prob->nvars);
884  	      prob->ncontvars--;
885  	      break;
886  	   default:
887  	      SCIPerrorMessage("unknown variable type\n");
888  	      SCIPABORT();
889  	      return SCIP_INVALIDDATA;  /*lint !e527*/
890  	   }
891  	
892  	   /* move last binary, last integer, last implicit, and last continuous variable forward to fill the free slot */
893  	   freepos = SCIPvarGetProbindex(var);
894  	   if( freepos < intstart-1 )
895  	   {
896  	      /* move last binary variable to free slot */
897  	      prob->vars[freepos] = prob->vars[intstart-1];
898  	      SCIPvarSetProbindex(prob->vars[freepos], freepos);
899  	      freepos = intstart-1;
900  	   }
901  	   if( freepos < implstart-1 )
902  	   {
903  	      /* move last integer variable to free slot */
904  	      prob->vars[freepos] = prob->vars[implstart-1];
905  	      SCIPvarSetProbindex(prob->vars[freepos], freepos);
906  	      freepos = implstart-1;
907  	   }
908  	   if( freepos < contstart-1 )
909  	   {
910  	      /* move last implicit integer variable to free slot */
911  	      prob->vars[freepos] = prob->vars[contstart-1];
912  	      SCIPvarSetProbindex(prob->vars[freepos], freepos);
913  	      freepos = contstart-1;
914  	   }
915  	   if( freepos < prob->nvars-1 )
916  	   {
917  	      /* move last implicit integer variable to free slot */
918  	      prob->vars[freepos] = prob->vars[prob->nvars-1];
919  	      SCIPvarSetProbindex(prob->vars[freepos], freepos);
920  	      freepos = prob->nvars-1;
921  	   }
922  	   assert(freepos == prob->nvars-1);
923  	
924  	   prob->nvars--;
925  	   assert(prob->nvars == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars);
926  	
927  	   /* update number of column variables in problem */
928  	   if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
929  	      prob->ncolvars--;
930  	   assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
931  	
932  	   /* inform the variable that it is no longer in the problem; if necessary, delete it from the implication graph */
933  	   SCIP_CALL( SCIPvarRemove(var, blkmem, cliquetable, set, FALSE) );
934  	
935  	   return SCIP_OKAY;
936  	}
937  	
938  	/** adds variable's name to the namespace */
939  	SCIP_RETCODE SCIPprobAddVarName(
940  	   SCIP_PROB*            prob,               /**< problem data */
941  	   SCIP_VAR*             var                 /**< variable */
942  	   )
943  	{
944  	   assert(SCIPvarGetProbindex(var) != -1);
945  	
946  	   if( varHasName(var) && prob->varnames != NULL )
947  	   {
948  	      SCIP_CALL( SCIPhashtableInsert(prob->varnames, (void*)var) );
949  	   }
950  	
951  	   return SCIP_OKAY;
952  	}
953  	
954  	/** removes variable's name from the namespace */
955  	SCIP_RETCODE SCIPprobRemoveVarName(
956  	   SCIP_PROB*            prob,               /**< problem data */
957  	   SCIP_VAR*             var                 /**< variable */
958  	   )
959  	{
960  	   if( varHasName(var) && prob->varnames != NULL )
961  	   {
962  	      assert(SCIPhashtableExists(prob->varnames, (void*)var));
963  	      SCIP_CALL( SCIPhashtableRemove(prob->varnames, (void*)var) );
964  	   }
965  	
966  	   return SCIP_OKAY;
967  	}
968  	
969  	/** adds variable to the problem and captures it */
970  	SCIP_RETCODE SCIPprobAddVar(
971  	   SCIP_PROB*            prob,               /**< problem data */
972  	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
973  	   SCIP_SET*             set,                /**< global SCIP settings */
974  	   SCIP_LP*              lp,                 /**< current LP data */
975  	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
976  	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
977  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
978  	   SCIP_VAR*             var                 /**< variable to add */
979  	   )
980  	{
981  	   assert(prob != NULL);
982  	   assert(set != NULL);
983  	   assert(var != NULL);
984  	   assert(SCIPvarGetProbindex(var) == -1);
985  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
986  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
987  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
988  	   /* original variables cannot go into transformed problem and transformed variables cannot go into original problem */
989  	   assert((SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL) == prob->transformed);
990  	
991  	#ifndef NDEBUG
992  	   /* check if we add this variables to the same scip, where we created it */
993  	   if( var->scip != set->scip )
994  	   {
995  	      SCIPerrorMessage("variable belongs to a different scip instance\n");
996  	      return SCIP_INVALIDDATA;
997  	   }
998  	#endif
999  	
1000 	   /* capture variable */
1001 	   SCIPvarCapture(var);
1002 	
1003 	   /* allocate additional memory */
1004 	   SCIP_CALL( probEnsureVarsMem(prob, set, prob->nvars+1) );
1005 	
1006 	   /* insert variable in vars array and mark it to be in problem */
1007 	   probInsertVar(prob, var);
1008 	
1009 	   /* add variable's name to the namespace */
1010 	   SCIP_CALL( SCIPprobAddVarName(prob, var) );
1011 	
1012 	   /* update branching candidates and pseudo and loose objective value in the LP */
1013 	   if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL )
1014 	   {
1015 	      SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1016 	      SCIP_CALL( SCIPlpUpdateAddVar(lp, set, var) );
1017 	   }
1018 	
1019 	   SCIPsetDebugMsg(set, "added variable <%s> to problem (%d variables: %d binary, %d integer, %d implicit, %d continuous)\n",
1020 	      SCIPvarGetName(var), prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
1021 	
1022 	   if( prob->transformed )
1023 	   {
1024 	      SCIP_EVENT* event;
1025 	
1026 	      /* issue VARADDED event */
1027 	      SCIP_CALL( SCIPeventCreateVarAdded(&event, blkmem, var) );
1028 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
1029 	
1030 	      /* update the number of variables with non-zero objective coefficient */
1031 	      SCIPprobUpdateNObjVars(prob, set, 0.0, SCIPvarGetObj(var));
1032 	
1033 	      /* SCIP assumes that the status of objisintegral does not change after transformation. Thus, the objective of all
1034 	       * new variables beyond that stage has to be compatible. */
1035 	      assert( SCIPsetGetStage(set) == SCIP_STAGE_TRANSFORMING || ! prob->objisintegral || SCIPsetIsZero(set, SCIPvarGetObj(var)) ||
1036 	         ( SCIPvarIsIntegral(var) && SCIPsetIsIntegral(set, SCIPvarGetObj(var)) ) );
1037 	   }
1038 	
1039 	   return SCIP_OKAY;
1040 	}
1041 	
1042 	/** marks variable to be removed from the problem; however, the variable is NOT removed from the constraints */
1043 	SCIP_RETCODE SCIPprobDelVar(
1044 	   SCIP_PROB*            prob,               /**< problem data */
1045 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1046 	   SCIP_SET*             set,                /**< global SCIP settings */
1047 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1048 	   SCIP_VAR*             var,                /**< problem variable */
1049 	   SCIP_Bool*            deleted             /**< pointer to store whether marking variable to be deleted was successful */
1050 	   )
1051 	{
1052 	   assert(prob != NULL);
1053 	   assert(set != NULL);
1054 	   assert(var != NULL);
1055 	   assert(deleted != NULL);
1056 	   assert(SCIPvarGetProbindex(var) != -1);
1057 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
1058 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
1059 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1060 	
1061 	   *deleted = FALSE;
1062 	
1063 	   /* don't remove variables that are not in the problem */
1064 	   /**@todo what about negated variables? should the negation variable be removed instead? */
1065 	   if( SCIPvarGetProbindex(var) == -1 )
1066 	      return SCIP_OKAY;
1067 	
1068 	   /* don't remove the direct counterpart of an original variable from the transformed problem, because otherwise
1069 	    * operations on the original variables would be applied to a NULL pointer
1070 	    */
1071 	   if( SCIPvarIsTransformedOrigvar(var) )
1072 	      return SCIP_OKAY;
1073 	
1074 	   assert(SCIPvarGetNegatedVar(var) == NULL);
1075 	
1076 	   SCIPsetDebugMsg(set, "deleting variable <%s> from problem (%d variables: %d binary, %d integer, %d implicit, %d continuous)\n",
1077 	      SCIPvarGetName(var), prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
1078 	
1079 	   /* mark variable to be deleted from the problem */
1080 	   SCIPvarMarkDeleted(var);
1081 	
1082 	   if( prob->transformed )
1083 	   {
1084 	      SCIP_EVENT* event;
1085 	
1086 	      assert(eventqueue != NULL);
1087 	
1088 	      /* issue VARDELETED event */
1089 	      SCIP_CALL( SCIPeventCreateVarDeleted(&event, blkmem, var) );
1090 	      SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
1091 	   }
1092 	
1093 	   /* remember that the variable should be deleted from the problem in SCIPprobPerformVarDeletions() */
1094 	   SCIP_CALL( probEnsureDeletedvarsMem(prob, set, prob->ndeletedvars+1) );
1095 	   prob->deletedvars[prob->ndeletedvars] = var;
1096 	   prob->ndeletedvars++;
1097 	
1098 	   *deleted = TRUE;
1099 	
1100 	   return SCIP_OKAY;
1101 	}
1102 	
1103 	/** actually removes the deleted variables from the problem and releases them */
1104 	SCIP_RETCODE SCIPprobPerformVarDeletions(
1105 	   SCIP_PROB*            prob,               /**< problem data */
1106 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1107 	   SCIP_SET*             set,                /**< global SCIP settings */
1108 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1109 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1110 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1111 	   SCIP_LP*              lp,                 /**< current LP data (may be NULL) */
1112 	   SCIP_BRANCHCAND*      branchcand          /**< branching candidate storage */
1113 	   )
1114 	{
1115 	   int i;
1116 	
1117 	   assert(prob != NULL);
1118 	   assert(set != NULL);
1119 	
1120 	   /* delete variables from the constraints;
1121 	    * do this only in solving stage, in presolving, it is already handled by the constraint handlers
1122 	    */
1123 	   if( SCIPsetGetStage(set) == SCIP_STAGE_SOLVING )
1124 	   {
1125 	      for( i = 0; i < set->nconshdlrs; ++i )
1126 	      {
1127 	         SCIP_CALL( SCIPconshdlrDelVars(set->conshdlrs[i], blkmem, set, stat) );
1128 	      }
1129 	   }
1130 	
1131 	   for( i = 0; i < prob->ndeletedvars; ++i )
1132 	   {
1133 	      SCIP_VAR* var;
1134 	
1135 	      var = prob->deletedvars[i];
1136 	
1137 	      /* don't delete the variable, if it was fixed or aggregated in the meantime */
1138 	      if( SCIPvarGetProbindex(var) >= 0 )
1139 	      {
1140 	         SCIPsetDebugMsg(set, "perform deletion of <%s> [%p]\n", SCIPvarGetName(var), (void*)var);
1141 	
1142 	         /* convert column variable back into loose variable, free LP column */
1143 	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
1144 	         {
1145 	            SCIP_CALL( SCIPvarLoose(var, blkmem, set, eventqueue, prob, lp) );
1146 	         }
1147 	
1148 	         /* update branching candidates and pseudo and loose objective value in the LP */
1149 	         if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL )
1150 	         {
1151 	            SCIP_CALL( SCIPlpUpdateDelVar(lp, set, var) );
1152 	            SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1153 	         }
1154 	
1155 	         /* remove variable's name from the namespace */
1156 	         SCIP_CALL( SCIPprobRemoveVarName(prob, var) );
1157 	
1158 	         /* remove variable from vars array and mark it to be not in problem */
1159 	         SCIP_CALL( probRemoveVar(prob, blkmem, cliquetable, set, var) );
1160 	
1161 	         /* update the number of variables with non-zero objective coefficient */
1162 	         if( prob->transformed )
1163 	            SCIPprobUpdateNObjVars(prob, set, SCIPvarGetObj(var), 0.0);
1164 	
1165 	         /* release variable */
1166 	         SCIP_CALL( SCIPvarRelease(&prob->deletedvars[i], blkmem, set, eventqueue, lp) );
1167 	      }
1168 	   }
1169 	   prob->ndeletedvars = 0;
1170 	
1171 	   return SCIP_OKAY;
1172 	}
1173 	
1174 	/** changes the type of a variable in the problem */
1175 	SCIP_RETCODE SCIPprobChgVarType(
1176 	   SCIP_PROB*            prob,               /**< problem data */
1177 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1178 	   SCIP_SET*             set,                /**< global SCIP settings */
1179 	   SCIP_PRIMAL*          primal,             /**< primal data */
1180 	   SCIP_LP*              lp,                 /**< current LP data */
1181 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1182 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1183 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1184 	   SCIP_VAR*             var,                /**< variable to add */
1185 	   SCIP_VARTYPE          vartype             /**< new type of variable */
1186 	   )
1187 	{
1188 	   assert(prob != NULL);
1189 	   assert(var != NULL);
1190 	   assert(SCIPvarGetProbindex(var) >= 0);
1191 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL
1192 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
1193 	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1194 	   assert(branchcand != NULL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
1195 	
1196 	   if( SCIPvarGetType(var) == vartype )
1197 	      return SCIP_OKAY;
1198 	
1199 	   /* temporarily remove variable from branching candidates */
1200 	   if( branchcand != NULL )
1201 	   {
1202 	      SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1203 	   }
1204 	
1205 	   /* temporarily remove variable from problem */
1206 	   SCIP_CALL( probRemoveVar(prob, blkmem, cliquetable, set, var) );
1207 	
1208 	   /* change the type of the variable */
1209 	   SCIP_CALL( SCIPvarChgType(var, blkmem, set, primal, lp, eventqueue, vartype) );
1210 	
1211 	   /* reinsert variable into problem */
1212 	   probInsertVar(prob, var);
1213 	
1214 	   /* update branching candidates */
1215 	   if( branchcand != NULL )
1216 	   {
1217 	      SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1218 	   }
1219 	
1220 	   return SCIP_OKAY;
1221 	}
1222 	
1223 	/** informs problem, that the given loose problem variable changed its status */
1224 	SCIP_RETCODE SCIPprobVarChangedStatus(
1225 	   SCIP_PROB*            prob,               /**< problem data */
1226 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1227 	   SCIP_SET*             set,                /**< global SCIP settings */
1228 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
1229 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
1230 	   SCIP_VAR*             var                 /**< problem variable */
1231 	   )
1232 	{
1233 	   assert(prob != NULL);
1234 	   assert(var != NULL);
1235 	   assert(SCIPvarGetProbindex(var) != -1);
1236 	
1237 	   /* get current status of variable */
1238 	   switch( SCIPvarGetStatus(var) )
1239 	   {
1240 	   case SCIP_VARSTATUS_ORIGINAL:
1241 	      SCIPerrorMessage("variables cannot switch to ORIGINAL status\n");
1242 	      return SCIP_INVALIDDATA;
1243 	
1244 	   case SCIP_VARSTATUS_LOOSE:
1245 	      /* variable switched from column to loose */
1246 	      prob->ncolvars--;
1247 	      break;
1248 	
1249 	   case SCIP_VARSTATUS_COLUMN:
1250 	      /* variable switched from non-column to column */
1251 	      prob->ncolvars++;
1252 	      break;
1253 	
1254 	   case SCIP_VARSTATUS_FIXED:
1255 	   case SCIP_VARSTATUS_AGGREGATED:
1256 	   case SCIP_VARSTATUS_MULTAGGR:
1257 	   case SCIP_VARSTATUS_NEGATED:
1258 	      /* variable switched from unfixed to fixed (if it was fixed before, probindex would have been -1) */
1259 	
1260 	      /* remove variable from problem */
1261 	      SCIP_CALL( probRemoveVar(prob, blkmem, cliquetable, set, var) );
1262 	
1263 	      /* insert variable in fixedvars array */
1264 	      SCIP_CALL( probEnsureFixedvarsMem(prob, set, prob->nfixedvars+1) );
1265 	      prob->fixedvars[prob->nfixedvars] = var;
1266 	      prob->nfixedvars++;
1267 	
1268 	      /* update branching candidates */
1269 	      SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1270 	      break;
1271 	
1272 	   default:
1273 	      SCIPerrorMessage("invalid variable status <%d>\n", SCIPvarGetStatus(var));
1274 	      return SCIP_INVALIDDATA;
1275 	   }
1276 	   assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
1277 	
1278 	   return SCIP_OKAY;
1279 	}
1280 	
1281 	/** adds constraint's name to the namespace */
1282 	SCIP_RETCODE SCIPprobAddConsName(
1283 	   SCIP_PROB*            prob,               /**< problem data */
1284 	   SCIP_CONS*            cons                /**< constraint */
1285 	   )
1286 	{
1287 	   /* add constraint's name to the namespace */
1288 	   if( consHasName(cons) && prob->consnames != NULL )
1289 	   {
1290 	      SCIP_CALL( SCIPhashtableInsert(prob->consnames, (void*)cons) );
1291 	   }
1292 	
1293 	   return SCIP_OKAY;
1294 	}
1295 	
1296 	/** remove constraint's name from the namespace */
1297 	SCIP_RETCODE SCIPprobRemoveConsName(
1298 	   SCIP_PROB*            prob,               /**< problem data */
1299 	   SCIP_CONS*            cons                /**< constraint */
1300 	   )
1301 	{
1302 	   /* remove constraint's name from the namespace */
1303 	   if( consHasName(cons) && prob->consnames != NULL )
1304 	   {
1305 	      SCIP_CONS* currentcons;
1306 	      currentcons = (SCIP_CONS*)SCIPhashtableRetrieve(prob->consnames, (void*)(cons->name));
1307 	      if( currentcons == cons )
1308 	      {
1309 	         SCIP_CALL( SCIPhashtableRemove(prob->consnames, (void*)cons) );
1310 	      }
1311 	   }
1312 	
1313 	   return SCIP_OKAY;
1314 	}
1315 	
1316 	/** adds constraint to the problem and captures it;
1317 	 *  a local constraint is automatically upgraded into a global constraint
1318 	 */
1319 	SCIP_RETCODE SCIPprobAddCons(
1320 	   SCIP_PROB*            prob,               /**< problem data */
1321 	   SCIP_SET*             set,                /**< global SCIP settings */
1322 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1323 	   SCIP_CONS*            cons                /**< constraint to add */
1324 	   )
1325 	{
1326 	   assert(prob != NULL);
1327 	   assert(cons != NULL);
1328 	   assert(cons->addconssetchg == NULL);
1329 	   assert(cons->addarraypos == -1);
1330 	
1331 	#ifndef NDEBUG
1332 	   /* check if we add this constraint to the same scip, where we create the constraint */
1333 	   if( cons->scip != set->scip )
1334 	   {
1335 	      SCIPerrorMessage("constraint belongs to different scip instance\n");
1336 	      return SCIP_INVALIDDATA;
1337 	   }
1338 	#endif
1339 	   SCIPsetDebugMsg(set, "adding constraint <%s> to global problem -> %d constraints\n",
1340 	      SCIPconsGetName(cons), prob->nconss+1);
1341 	
1342 	   /* mark the constraint as problem constraint, and remember the constraint's position */
1343 	   cons->addconssetchg = NULL;
1344 	   cons->addarraypos = prob->nconss;
1345 	
1346 	   /* add the constraint to the problem's constraint array */
1347 	   SCIP_CALL( probEnsureConssMem(prob, set, prob->nconss+1) );
1348 	   prob->conss[prob->nconss] = cons;
1349 	   if( prob->origcheckconss != NULL )
1350 	      prob->origcheckconss[prob->nconss] = cons;
1351 	   prob->nconss++;
1352 	   prob->maxnconss = MAX(prob->maxnconss, prob->nconss);
1353 	   prob->consschecksorted = FALSE;
1354 	   stat->nactiveconssadded++;
1355 	
1356 	   /* undelete constraint, if it was globally deleted in the past */
1357 	   cons->deleted = FALSE;
1358 	
1359 	   /* mark constraint to be globally valid */
1360 	   SCIPconsSetLocal(cons, FALSE);
1361 	
1362 	   /* capture constraint */
1363 	   SCIPconsCapture(cons);
1364 	
1365 	   /* add constraint's name to the namespace */
1366 	   SCIP_CALL( SCIPprobAddConsName(prob, cons) );
1367 	
1368 	   /* if the problem is the transformed problem, activate and lock constraint */
1369 	   if( prob->transformed )
1370 	   {
1371 	      /* activate constraint */
1372 	      if( !SCIPconsIsActive(cons) )
1373 	      {
1374 	         SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, (stat->nnodes <= 1)) );
1375 	      }
1376 	
1377 	      /* if constraint is a check-constraint, lock roundings of constraint's variables */
1378 	      if( SCIPconsIsChecked(cons) )
1379 	      {
1380 	         SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, +1, 0) );
1381 	      }
1382 	   }
1383 	
1384 	   return SCIP_OKAY;
1385 	}
1386 	
1387 	/** releases and removes constraint from the problem; if the user has not captured the constraint for his own use, the
1388 	 *  constraint may be invalid after the call
1389 	 */
1390 	SCIP_RETCODE SCIPprobDelCons(
1391 	   SCIP_PROB*            prob,               /**< problem data */
1392 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1393 	   SCIP_SET*             set,                /**< global SCIP settings */
1394 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
1395 	   SCIP_CONS*            cons                /**< constraint to remove */
1396 	   )
1397 	{
1398 	   int arraypos;
1399 	
1400 	   assert(prob != NULL);
1401 	   assert(blkmem != NULL);
1402 	   assert(cons != NULL);
1403 	   assert(cons->addconssetchg == NULL);
1404 	   assert(0 <= cons->addarraypos && cons->addarraypos < prob->nconss);
1405 	   assert(prob->conss != NULL);
1406 	   assert(prob->conss[cons->addarraypos] == cons);
1407 	
1408 	   /* if the problem is the transformed problem, deactivate and unlock constraint */
1409 	   if( prob->transformed )
1410 	   {
1411 	      /* if constraint is a check-constraint, unlock roundings of constraint's variables */
1412 	      if( SCIPconsIsChecked(cons) )
1413 	      {
1414 	         SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, -1, 0) );
1415 	      }
1416 	
1417 	      /* deactivate constraint, if it is currently active */
1418 	      if( cons->active && !cons->updatedeactivate )
1419 	      {
1420 	         SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
1421 	      }
1422 	   }
1423 	   assert(!cons->active || cons->updatedeactivate);
1424 	   assert(!cons->enabled || cons->updatedeactivate);
1425 	
1426 	   /* remove constraint's name from the namespace */
1427 	   SCIP_CALL( SCIPprobRemoveConsName(prob, cons) );
1428 	
1429 	   /* remove the constraint from the problem's constraint array */
1430 	   arraypos = cons->addarraypos;
1431 	   prob->conss[arraypos] = prob->conss[prob->nconss-1];
1432 	   assert(prob->conss[arraypos] != NULL);
1433 	   assert(prob->conss[arraypos]->addconssetchg == NULL);
1434 	   prob->conss[arraypos]->addarraypos = arraypos;
1435 	   prob->nconss--;
1436 	   prob->consschecksorted = FALSE;
1437 	
1438 	   /* if we delete constraints then delete array origcheckconss to be sure */
1439 	   if( prob->origcheckconss != NULL )
1440 	      BMSfreeMemoryArray(&prob->origcheckconss);
1441 	
1442 	   /* mark the constraint to be no longer in the problem */
1443 	   cons->addarraypos = -1;
1444 	
1445 	   /* release constraint */
1446 	   SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
1447 	
1448 	   return SCIP_OKAY;
1449 	}
1450 	
1451 	/** remembers the current number of constraints in the problem's internal data structure
1452 	 *  - resets maximum number of constraints to current number of constraints
1453 	 *  - remembers current number of constraints as starting number of constraints
1454 	 */
1455 	void SCIPprobMarkNConss(
1456 	   SCIP_PROB*            prob                /**< problem data */
1457 	   )
1458 	{
1459 	   assert(prob != NULL);
1460 	
1461 	   /* remember number of constraints for statistic */
1462 	   prob->maxnconss = prob->nconss;
1463 	   prob->startnvars = prob->nvars;
1464 	   prob->startnconss = prob->nconss;
1465 	}
1466 	
1467 	/** sets objective sense: minimization or maximization */
1468 	void SCIPprobSetObjsense(
1469 	   SCIP_PROB*            prob,               /**< problem data */
1470 	   SCIP_OBJSENSE         objsense            /**< new objective sense */
1471 	   )
1472 	{
1473 	   assert(prob != NULL);
1474 	   assert(prob->objsense == SCIP_OBJSENSE_MAXIMIZE || prob->objsense == SCIP_OBJSENSE_MINIMIZE);
1475 	   assert(objsense == SCIP_OBJSENSE_MAXIMIZE || objsense == SCIP_OBJSENSE_MINIMIZE);
1476 	
1477 	   prob->objsense = objsense;
1478 	}
1479 	
1480 	/** adds value to objective offset */
1481 	void SCIPprobAddObjoffset(
1482 	   SCIP_PROB*            prob,               /**< problem data */
1483 	   SCIP_Real             addval              /**< value to add to objective offset */
1484 	   )
1485 	{
1486 	   assert(prob != NULL);
1487 	   assert(prob->transformed);
1488 	
1489 	   SCIPdebugMessage("adding %g to objective offset %g: new offset = %g\n", addval, prob->objoffset, prob->objoffset + addval);
1490 	   prob->objoffset += addval;
1491 	}
1492 	
1493 	/** sets the dual bound on objective function */
1494 	void SCIPprobSetDualbound(
1495 	   SCIP_PROB*            prob,               /**< problem data */
1496 	   SCIP_Real             dualbound           /**< external dual bound */
1497 	   )
1498 	{
1499 	   assert(prob != NULL);
1500 	
1501 	   prob->dualbound = dualbound;
1502 	}
1503 	
1504 	/** sets limit on objective function, such that only solutions better than this limit are accepted */
1505 	void SCIPprobSetObjlim(
1506 	   SCIP_PROB*            prob,               /**< problem data */
1507 	   SCIP_Real             objlim              /**< external objective limit */
1508 	   )
1509 	{
1510 	   assert(prob != NULL);
1511 	
1512 	   prob->objlim = objlim;
1513 	}
1514 	
1515 	/** informs the problem, that its objective value is always integral in every feasible solution */
1516 	void SCIPprobSetObjIntegral(
1517 	   SCIP_PROB*            prob                /**< problem data */
1518 	   )
1519 	{
1520 	   assert(prob != NULL);
1521 	
1522 	   prob->objisintegral = TRUE;
1523 	}
1524 	
1525 	/** sets integral objective value flag, if all variables with non-zero objective values are integral and have 
1526 	 *  integral objective value and also updates the cutoff bound if primal solution is already known
1527 	 */
1528 	SCIP_RETCODE SCIPprobCheckObjIntegral(
1529 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
1530 	   SCIP_PROB*            origprob,           /**< original problem data */
1531 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1532 	   SCIP_SET*             set,                /**< global SCIP settings */
1533 	   SCIP_STAT*            stat,               /**< problem statistics data */
1534 	   SCIP_PRIMAL*          primal,             /**< primal data */
1535 	   SCIP_TREE*            tree,               /**< branch and bound tree */
1536 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1537 	   SCIP_LP*              lp,                 /**< current LP data */
1538 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
1539 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
1540 	   )
1541 	{
1542 	   SCIP_Real obj;
1543 	   int v;
1544 	
1545 	   assert(transprob != NULL);
1546 	   assert(origprob != NULL);
1547 	
1548 	   /* if we know already, that the objective value is integral, nothing has to be done */
1549 	   if( transprob->objisintegral )
1550 	      return SCIP_OKAY;
1551 	
1552 	   /* if there exist unknown variables, we cannot conclude that the objective value is always integral */
1553 	   if( set->nactivepricers != 0 || set->nactivebenders != 0 )
1554 	      return SCIP_OKAY;
1555 	
1556 	   /* if the objective value offset is fractional, the value itself is possibly fractional */
1557 	   if( !SCIPsetIsIntegral(set, transprob->objoffset) )
1558 	      return SCIP_OKAY;
1559 	
1560 	   /* scan through the variables */
1561 	   for( v = 0; v < transprob->nvars; ++v )
1562 	   {
1563 	      /* get objective value of variable */
1564 	      obj = SCIPvarGetObj(transprob->vars[v]);
1565 	
1566 	      /* check, if objective value is non-zero */
1567 	      if( !SCIPsetIsZero(set, obj) )
1568 	      {
1569 	         /* if variable's objective value is fractional, the problem's objective value may also be fractional */
1570 	         if( !SCIPsetIsIntegral(set, obj) )
1571 	            break;
1572 	
1573 	         /* if variable with non-zero objective value is continuous, the problem's objective value may be fractional */
1574 	         if( SCIPvarGetType(transprob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
1575 	            break;
1576 	      }
1577 	   }
1578 	
1579 	   /* objective value is integral, if the variable loop scanned all variables */
1580 	   if( v == transprob->nvars )
1581 	   {
1582 	      transprob->objisintegral = TRUE;
1583 	
1584 	      /* update upper bound and cutoff bound in primal data structure due to new internality information */
1585 	      SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
1586 	   }
1587 	
1588 	   return SCIP_OKAY;
1589 	}
1590 	
1591 	/** update the number of variables with non-zero objective coefficient */
1592 	void SCIPprobUpdateNObjVars(
1593 	   SCIP_PROB*            prob,               /**< problem data */
1594 	   SCIP_SET*             set,                /**< global SCIP settings */
1595 	   SCIP_Real             oldobj,             /**< old objective value for variable */
1596 	   SCIP_Real             newobj              /**< new objective value for variable */
1597 	   )
1598 	{
1599 	   assert(prob->transformed);
1600 	
1601 	   if( !SCIPsetIsZero(set, oldobj) )
1602 	      prob->nobjvars--;
1603 	
1604 	   if( !SCIPsetIsZero(set, newobj) )
1605 	      prob->nobjvars++;
1606 	}
1607 	
1608 	/** update the dual bound if its better as the current one */
1609 	void SCIPprobUpdateDualbound(
1610 	   SCIP_PROB*            prob,               /**< problem data */
1611 	   SCIP_Real             newbound            /**< new dual bound for the node (if it's tighter than the old one) */
1612 	   )
1613 	{
1614 	   if( prob->dualbound == SCIP_INVALID ) /*lint !e777*/
1615 	      SCIPprobSetDualbound(prob, newbound);
1616 	   else
1617 	   {
1618 	      switch( prob->objsense )
1619 	      {
1620 	      case SCIP_OBJSENSE_MINIMIZE:
1621 	         prob->dualbound = MAX(newbound, prob->dualbound);
1622 	         break;
1623 	
1624 	      case SCIP_OBJSENSE_MAXIMIZE:
1625 	         prob->dualbound = MIN(newbound, prob->dualbound);
1626 	         break;
1627 	
1628 	      default:
1629 	         SCIPerrorMessage("invalid objective sense <%d>\n", prob->objsense);
1630 	         SCIPABORT();
1631 	      }
1632 	   }
1633 	}
1634 	
1635 	/** invalidates the dual bound */
1636 	void SCIPprobInvalidateDualbound(
1637 	   SCIP_PROB*            prob                /**< problem data */
1638 	   )
1639 	{
1640 	   assert(prob != NULL);
1641 	
1642 	   prob->dualbound = SCIP_INVALID;
1643 	}
1644 	
1645 	/** if possible, scales objective function such that it is integral with gcd = 1 */
1646 	SCIP_RETCODE SCIPprobScaleObj(
1647 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
1648 	   SCIP_PROB*            origprob,           /**< original problem data */
1649 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1650 	   SCIP_SET*             set,                /**< global SCIP settings */
1651 	   SCIP_STAT*            stat,               /**< problem statistics data */
1652 	   SCIP_PRIMAL*          primal,             /**< primal data */
1653 	   SCIP_TREE*            tree,               /**< branch and bound tree */
1654 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1655 	   SCIP_LP*              lp,                 /**< current LP data */
1656 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
1657 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
1658 	   )
1659 	{
1660 	   int v;
1661 	   int nints;
1662 	
1663 	   assert(transprob != NULL);
1664 	   assert(set != NULL);
1665 	
1666 	   /* do not change objective if there are pricers involved */
1667 	   if( set->nactivepricers != 0 || set->nactivebenders != 0 || !set->misc_scaleobj )
1668 	      return SCIP_OKAY;
1669 	
1670 	   nints = transprob->nvars - transprob->ncontvars;
1671 	
1672 	   /* scan through the continuous variables */
1673 	   for( v = nints; v < transprob->nvars; ++v )
1674 	   {
1675 	      SCIP_Real obj;
1676 	
1677 	      /* get objective value of variable; it it is non-zero, no scaling can be applied */
1678 	      obj = SCIPvarGetObj(transprob->vars[v]);
1679 	      if( !SCIPsetIsZero(set, obj) )
1680 	         break;
1681 	   }
1682 	
1683 	   /* only continue if all continuous variables have obj = 0 */
1684 	   if( v == transprob->nvars )
1685 	   {
1686 	      SCIP_Real* objvals;
1687 	      SCIP_Real intscalar;
1688 	      SCIP_Bool success;
1689 	
1690 	      /* get temporary memory */
1691 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &objvals, nints) );
1692 	
1693 	      /* get objective values of integer variables */
1694 	      for( v = 0; v < nints; ++v )
1695 	         objvals[v] = SCIPvarGetObj(transprob->vars[v]);
1696 	
1697 	      /* calculate integral scalar */
1698 	      SCIP_CALL( SCIPcalcIntegralScalar(objvals, nints, -SCIPsetEpsilon(set), +SCIPsetEpsilon(set), OBJSCALE_MAXDNOM, OBJSCALE_MAXSCALE,
1699 	         &intscalar, &success) );
1700 	
1701 	      SCIPsetDebugMsg(set, "integral objective scalar: success=%u, intscalar=%g\n", success, intscalar);
1702 	
1703 	      if( success )
1704 	      {
1705 	         SCIP_Longint gcd;
1706 	
1707 	         assert(intscalar > 0.0);
1708 	
1709 	         /* calculate gcd of resulting integral coefficients */
1710 	         gcd = 0;
1711 	         for( v = 0; v < nints && gcd != 1; ++v )
1712 	         {
1713 	            SCIP_Longint absobj;
1714 	
1715 	            /* if absobj exceeds maximum SCIP_Longint value, return */
1716 	            if( REALABS(objvals[v]) * intscalar + 0.5 > (SCIP_Real)SCIP_LONGINT_MAX )
1717 	            {
1718 	               SCIPsetFreeBufferArray(set, &objvals);
1719 	               return SCIP_OKAY;
1720 	            }
1721 	
1722 	            absobj = (SCIP_Longint)(REALABS(objvals[v]) * intscalar + 0.5);
1723 	            if( gcd == 0 )
1724 	               gcd = absobj;
1725 	            else if( absobj > 0 )
1726 	               gcd = SCIPcalcGreComDiv(gcd, absobj);
1727 	         }
1728 	         if( gcd != 0 )
1729 	            intscalar /= gcd;
1730 	         SCIPsetDebugMsg(set, "integral objective scalar: gcd=%" SCIP_LONGINT_FORMAT ", intscalar=%g\n", gcd, intscalar);
1731 	
1732 	         /* only apply scaling if the final scalar is small enough */
1733 	         if( intscalar <= OBJSCALE_MAXFINALSCALE )
1734 	         {
1735 	            /* apply scaling */
1736 	            if( !SCIPsetIsEQ(set, intscalar, 1.0) )
1737 	            {
1738 	               /* calculate scaled objective values */
1739 	               for( v = 0; v < nints; ++v )
1740 	               {
1741 	                  SCIP_Real newobj;
1742 	
1743 	                  /* check if new obj is really integral */
1744 	                  newobj = intscalar * SCIPvarGetObj(transprob->vars[v]);
1745 	                  if( !SCIPsetIsFeasIntegral(set, newobj) )
1746 	                     break;
1747 	                  objvals[v] = SCIPsetFeasFloor(set, newobj);
1748 	               }
1749 	
1750 	               /* change the variables' objective values and adjust objscale and objoffset */
1751 	               if( v == nints )
1752 	               {
1753 	                  for( v = 0; v < nints; ++v )
1754 	                  {
1755 	                     SCIPsetDebugMsg(set, " -> var <%s>: newobj = %.6f\n", SCIPvarGetName(transprob->vars[v]), objvals[v]);
1756 	                     SCIP_CALL( SCIPvarChgObj(transprob->vars[v], blkmem, set, transprob, primal, lp, eventqueue, objvals[v]) );
1757 	                  }
1758 	                  transprob->objoffset *= intscalar;
1759 	                  transprob->objscale /= intscalar;
1760 	                  transprob->objisintegral = TRUE;
1761 	                  SCIPsetDebugMsg(set, "integral objective scalar: objscale=%g\n", transprob->objscale);
1762 	
1763 	                  /* update upperbound and cutoffbound in primal data structure */
1764 	                  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
1765 	               }
1766 	            }
1767 	         }
1768 	      }
1769 	
1770 	      /* free temporary memory */
1771 	      SCIPsetFreeBufferArray(set, &objvals);
1772 	   }
1773 	
1774 	   return SCIP_OKAY;
1775 	}
1776 	
1777 	/** remembers the current solution as root solution in the problem variables */
1778 	void SCIPprobStoreRootSol(
1779 	   SCIP_PROB*            prob,               /**< problem data */
1780 	   SCIP_SET*             set,                /**< global SCIP settings */
1781 	   SCIP_STAT*            stat,               /**< SCIP statistics */
1782 	   SCIP_LP*              lp,                 /**< current LP data */
1783 	   SCIP_Bool             roothaslp           /**< is the root solution from LP? */
1784 	   )
1785 	{
1786 	   int v;
1787 	
1788 	   assert(prob != NULL);
1789 	   assert(prob->transformed);
1790 	
1791 	   if( roothaslp )
1792 	   {
1793 	      for( v = 0; v < prob->nvars; ++v )
1794 	         SCIPvarStoreRootSol(prob->vars[v], roothaslp);
1795 	
1796 	      SCIPlpSetRootLPIsRelax(lp, SCIPlpIsRelax(lp));
1797 	      SCIPlpStoreRootObjval(lp, set, prob);
1798 	
1799 	      /* compute root LP best-estimate */
1800 	      SCIPstatComputeRootLPBestEstimate(stat, set, SCIPlpGetColumnObjval(lp), prob->vars, prob->nbinvars + prob->nintvars + prob->nimplvars);
1801 	   }
1802 	}
1803 	
1804 	/** remembers the best solution w.r.t. root reduced cost propagation as root solution in the problem variables */
1805 	void SCIPprobUpdateBestRootSol(
1806 	   SCIP_PROB*            prob,               /**< problem data */
1807 	   SCIP_SET*             set,                /**< global SCIP settings */
1808 	   SCIP_STAT*            stat,               /**< problem statistics */
1809 	   SCIP_LP*              lp                  /**< current LP data */
1810 	   )
1811 	{
1812 	   SCIP_Real rootlpobjval;
1813 	   int v;
1814 	
1815 	   assert(prob != NULL);
1816 	   assert(lp != NULL);
1817 	   assert(prob->transformed);
1818 	   assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
1819 	
1820 	   /* in case we have a zero objective fucntion, we skip the root reduced cost update */
1821 	   if( SCIPprobGetNObjVars(prob, set) == 0 )
1822 	      return;
1823 	
1824 	   if( !SCIPlpIsDualReliable(lp) )
1825 	      return;
1826 	
1827 	   SCIPsetDebugMsg(set, "update root reduced costs\n");
1828 	
1829 	   /* compute current root LP objective value */
1830 	   rootlpobjval = SCIPlpGetObjval(lp, set, prob);
1831 	   assert(rootlpobjval != SCIP_INVALID); /*lint !e777*/
1832 	
1833 	   for( v = 0; v < prob->nvars; ++v )
1834 	   {
1835 	      SCIP_VAR* var;
1836 	      SCIP_COL* col;
1837 	      SCIP_Real rootsol = 0.0;
1838 	      SCIP_Real rootredcost = 0.0;
1839 	
1840 	      var = prob->vars[v];
1841 	      assert(var != NULL);
1842 	
1843 	      /* check if the variable is part of the LP */
1844 	      if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
1845 	         continue;
1846 	
1847 	      col = SCIPvarGetCol(var);
1848 	      assert(col != NULL);
1849 	
1850 	      assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL);
1851 	
1852 	      if( !SCIPvarIsBinary(var) )
1853 	      {
1854 	         rootsol = SCIPvarGetSol(var, TRUE);
1855 	         rootredcost = SCIPcolGetRedcost(col, stat, lp);
1856 	      }
1857 	      else
1858 	      {
1859 	         SCIP_Real primsol;
1860 	         SCIP_BASESTAT basestat;
1861 	         SCIP_Bool lpissolbasic;
1862 	
1863 	         basestat = SCIPcolGetBasisStatus(col);
1864 	         lpissolbasic = SCIPlpIsSolBasic(lp);
1865 	         primsol = SCIPcolGetPrimsol(col);
1866 	
1867 	         if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
1868 	            (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) ||
1869 	               SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
1870 	         {
1871 	            SCIP_Real lbrootredcost;
1872 	            SCIP_Real ubrootredcost;
1873 	
1874 	            /* get reduced cost if the variable gets fixed to zero */
1875 	            lbrootredcost = SCIPvarGetImplRedcost(var, set, FALSE, stat, prob, lp);
1876 	            assert( !SCIPsetIsDualfeasPositive(set, lbrootredcost)
1877 	               || SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
1878 	
1879 	            /* get reduced cost if the variable gets fixed to one */
1880 	            ubrootredcost = SCIPvarGetImplRedcost(var, set, TRUE, stat, prob, lp);
1881 	            assert( !SCIPsetIsDualfeasNegative(set, ubrootredcost)
1882 	               || SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
1883 	
1884 	            if( -lbrootredcost > ubrootredcost )
1885 	            {
1886 	               rootredcost = lbrootredcost;
1887 	               rootsol = 1.0;
1888 	            }
1889 	            else
1890 	            {
1891 	               rootredcost = ubrootredcost;
1892 	               rootsol = 0.0;
1893 	            }
1894 	         }
1895 	      }
1896 	
1897 	      /* update the current solution as best root solution in the problem variables if it is better */
1898 	      SCIPvarUpdateBestRootSol(var, set, rootsol, rootredcost, rootlpobjval);
1899 	   }
1900 	}
1901 	
1902 	/** informs problem, that the presolving process was finished, and updates all internal data structures */ /*lint -e715*/
1903 	SCIP_RETCODE SCIPprobExitPresolve(
1904 	   SCIP_PROB*            prob,               /**< problem data */
1905 	   SCIP_SET*             set                 /**< global SCIP settings */
1906 	   )
1907 	{  /*lint --e{715}*/
1908 	   return SCIP_OKAY;
1909 	}
1910 	
1911 	/** initializes problem for branch and bound process and resets all constraint's ages and histories of current run */
1912 	SCIP_RETCODE SCIPprobInitSolve(
1913 	   SCIP_PROB*            prob,               /**< problem data */
1914 	   SCIP_SET*             set                 /**< global SCIP settings */
1915 	   )
1916 	{
1917 	   int c;
1918 	   int v;
1919 	
1920 	   assert(prob != NULL);
1921 	   assert(prob->transformed);
1922 	   assert(set != NULL);
1923 	
1924 	   /* reset constraint's ages */
1925 	   for( c = 0; c < prob->nconss; ++c )
1926 	   {
1927 	      SCIP_CALL( SCIPconsResetAge(prob->conss[c], set) );
1928 	   }
1929 	
1930 	   /* initialize variables for solving */
1931 	   for( v = 0; v < prob->nvars; ++v )
1932 	      SCIPvarInitSolve(prob->vars[v]);
1933 	
1934 	   /* call user data function */
1935 	   if( prob->probinitsol != NULL )
1936 	   {
1937 	      SCIP_CALL( prob->probinitsol(set->scip, prob->probdata) );
1938 	   }
1939 	
1940 	   /* assert that the counter for variables with nonzero objective is correct */
1941 	   assert(prob->nobjvars == SCIPprobGetNObjVars(prob, set));
1942 	
1943 	   return SCIP_OKAY;
1944 	}
1945 	
1946 	/** deinitializes problem after branch and bound process, and converts all COLUMN variables back into LOOSE variables */
1947 	SCIP_RETCODE SCIPprobExitSolve(
1948 	   SCIP_PROB*            prob,               /**< problem data */
1949 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1950 	   SCIP_SET*             set,                /**< global SCIP settings */
1951 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
1952 	   SCIP_LP*              lp,                 /**< current LP data */
1953 	   SCIP_Bool             restart             /**< was this exit solve call triggered by a restart? */
1954 	   )
1955 	{
1956 	   SCIP_VAR* var;
1957 	   int v;
1958 	
1959 	   assert(prob != NULL);
1960 	   assert(prob->transformed);
1961 	   assert(set != NULL);
1962 	
1963 	   /* call user data function */
1964 	   if( prob->probexitsol != NULL )
1965 	   {
1966 	      SCIP_CALL( prob->probexitsol(set->scip, prob->probdata, restart) );
1967 	   }
1968 	
1969 	   /* - convert all COLUMN variables back into LOOSE variables
1970 	    * - mark relaxation-only variables for deletion, if possible and restarting
1971 	    *   - initPresolve will then call SCIPprobPerformVarDeletions
1972 	    *   - if no restart, then the whole transformed problem will be deleted anyway
1973 	    */
1974 	   if( prob->ncolvars > 0 || restart )
1975 	   {
1976 	      for( v = 0; v < prob->nvars; ++v )
1977 	      {
1978 	         var = prob->vars[v];
1979 	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
1980 	         {
1981 	            SCIP_CALL( SCIPvarLoose(var, blkmem, set, eventqueue, prob, lp) );
1982 	         }
1983 	
1984 	         /* invalidate root reduced cost, root reduced solution, and root LP objective value for each variable */
1985 	         SCIPvarSetBestRootSol(var, 0.0, 0.0, SCIP_INVALID);
1986 	
1987 	         if( SCIPvarIsRelaxationOnly(var) && restart )
1988 	         {
1989 	            /* relaxation variables should be unlocked and only captured by prob at this moment */
1990 	            assert(SCIPvarGetNLocksDown(var) == 0);
1991 	            assert(SCIPvarGetNLocksUp(var) == 0);
1992 	            assert(SCIPvarGetNUses(var) == 1);
1993 	
1994 	            if( SCIPvarIsDeletable(var) )
1995 	            {
1996 	               SCIP_Bool deleted;
1997 	
1998 	               SCIPsetDebugMsg(set, "queue relaxation-only variable <%s> for deletion\n", SCIPvarGetName(var));
1999 	               SCIP_CALL( SCIPprobDelVar(prob, blkmem, set, eventqueue, var, &deleted) );
2000 	               assert(deleted);
2001 	            }
2002 	            else
2003 	            {
2004 	               SCIPsetDebugMsg(set, "cannot queue relaxation-only variable <%s> for deletion because it is marked non-deletable\n", SCIPvarGetName(var));
2005 	            }
2006 	         }
2007 	      }
2008 	   }
2009 	   assert(prob->ncolvars == 0);
2010 	
2011 	   return SCIP_OKAY;
2012 	}
2013 	
2014 	
2015 	
2016 	
2017 	/*
2018 	 * problem information
2019 	 */
2020 	
2021 	/** sets problem name */
2022 	SCIP_RETCODE SCIPprobSetName(
2023 	   SCIP_PROB*            prob,               /**< problem data */
2024 	   const char*           name                /**< name to be set */
2025 	   )
2026 	{
2027 	   assert(prob != NULL);
2028 	
2029 	   BMSfreeMemoryArray(&(prob->name));
2030 	   SCIP_ALLOC( BMSduplicateMemoryArray(&(prob->name), name, strlen(name)+1) );
2031 	
2032 	   return SCIP_OKAY;
2033 	}
2034 	
2035 	/** returns the number of implicit binary variables, meaning variable of vartype != SCIP_VARTYPE_BINARY and !=
2036 	 *  SCIP_VARTYPE_CONTINUOUS but with global bounds [0,1]
2037 	 *
2038 	 *  @note this number needs to be computed, because it cannot be updated like the other counters for binary and integer
2039 	 *        variables, each time the variable type changes(, we would need to update this counter each time a global bound
2040 	 *        changes), even at the end of presolving this cannot be computed, because some variable can change to an
2041 	 *        implicit binary status
2042 	 */
2043 	int SCIPprobGetNImplBinVars(
2044 	   SCIP_PROB*            prob                /**< problem data */
2045 	   )
2046 	{
2047 	   int v;
2048 	   int nimplbinvars = 0;
2049 	
2050 	   for( v = prob->nbinvars + prob->nintvars + prob->nimplvars - 1; v >= prob->nbinvars; --v )
2051 	   {
2052 	      if( SCIPvarIsBinary(prob->vars[v]) )
2053 	         ++nimplbinvars;
2054 	   }
2055 	
2056 	   return nimplbinvars;
2057 	}
2058 	
2059 	/** returns the number of variables with non-zero objective coefficient */
2060 	int SCIPprobGetNObjVars(
2061 	   SCIP_PROB*            prob,               /**< problem data */
2062 	   SCIP_SET*             set                 /**< global SCIP settings */
2063 	   )
2064 	{
2065 	   if( prob->transformed )
2066 	   {
2067 	      /* this is much too expensive, to check it in each debug run */
2068 	#ifdef SCIP_MORE_DEBUG
2069 	      int nobjvars;
2070 	      int v;
2071 	
2072 	      nobjvars = 0;
2073 	
2074 	      for( v = prob->nvars - 1; v >= 0; --v )
2075 	      {
2076 	         if( !SCIPsetIsZero(set, SCIPvarGetObj(prob->vars[v])) )
2077 	            nobjvars++;
2078 	      }
2079 	
2080 	      /* check that the internal count is correct */
2081 	      assert(prob->nobjvars == nobjvars);
2082 	#endif
2083 	      return prob->nobjvars;
2084 	   }
2085 	   else
2086 	   {
2087 	      int nobjvars;
2088 	      int v;
2089 	
2090 	      nobjvars = 0;
2091 	
2092 	      for( v = prob->nvars - 1; v >= 0; --v )
2093 	      {
2094 	         if( !SCIPsetIsZero(set, SCIPvarGetObj(prob->vars[v])) )
2095 	            nobjvars++;
2096 	      }
2097 	      return nobjvars;
2098 	   }
2099 	}
2100 	
2101 	/** returns the minimal absolute non-zero objective coefficient
2102 	 *
2103 	 *  @note currently, this is only used for statistics and printed after the solving process. if this information is
2104 	 *        needed during the (pre)solving process this should be implemented more efficiently, e.g., updating the minimal
2105 	 *        absolute non-zero coefficient every time an objective coefficient has changed.
2106 	 */
2107 	SCIP_Real SCIPprobGetAbsMinObjCoef(
2108 	   SCIP_PROB*            prob,               /**< problem data */
2109 	   SCIP_SET*             set                 /**< global SCIP settings */
2110 	   )
2111 	{
2112 	   SCIP_Real absmin;
2113 	   int v;
2114 	
2115 	   absmin = SCIPsetInfinity(set);
2116 	
2117 	   for( v = 0; v < prob->nvars; v++ )
2118 	   {
2119 	      SCIP_Real objcoef = SCIPvarGetObj(prob->vars[v]);
2120 	
2121 	      if( !SCIPsetIsZero(set, objcoef) && SCIPsetIsLT(set, REALABS(objcoef), absmin) )
2122 	         absmin = REALABS(objcoef);
2123 	   }
2124 	
2125 	   return absmin;
2126 	}
2127 	
2128 	/** returns the maximal absolute non-zero objective coefficient
2129 	 *
2130 	 *  @note currently, this is only used for statistics and printed after the solving process. if this information is
2131 	 *        needed during the (pre)solving process this should be implemented more efficiently, e.g., updating the maximal
2132 	 *        absolute non-zero coefficient every time an objective coefficient has changed.
2133 	 */
2134 	SCIP_Real SCIPprobGetAbsMaxObjCoef(
2135 	   SCIP_PROB*            prob,               /**< problem data */
2136 	   SCIP_SET*             set                 /**< global SCIP settings */
2137 	   )
2138 	{
2139 	   SCIP_Real absmax;
2140 	   int v;
2141 	
2142 	   absmax = -SCIPsetInfinity(set);
2143 	
2144 	   for( v = 0; v < prob->nvars; v++ )
2145 	   {
2146 	      SCIP_Real objcoef = SCIPvarGetObj(prob->vars[v]);
2147 	
2148 	      if( !SCIPsetIsZero(set, objcoef) && SCIPsetIsGT(set, REALABS(objcoef), absmax) )
2149 	         absmax = REALABS(objcoef);
2150 	   }
2151 	
2152 	   return absmax;
2153 	}
2154 	
2155 	
2156 	/** returns the external value of the given internal objective value */
2157 	SCIP_Real SCIPprobExternObjval(
2158 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
2159 	   SCIP_PROB*            origprob,           /**< original problem data */
2160 	   SCIP_SET*             set,                /**< global SCIP settings */
2161 	   SCIP_Real             objval              /**< internal objective value */
2162 	   )
2163 	{
2164 	   assert(set != NULL);
2165 	   assert(origprob != NULL);
2166 	   assert(transprob != NULL);
2167 	   assert(transprob->transformed);
2168 	   assert(transprob->objscale > 0.0);
2169 	
2170 	   if( SCIPsetIsInfinity(set, objval) )
2171 	      return (SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
2172 	   else if( SCIPsetIsInfinity(set, -objval) )
2173 	      return -(SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
2174 	   else
2175 	      return (SCIP_Real)transprob->objsense * transprob->objscale * (objval + transprob->objoffset) + origprob->objoffset;
2176 	}
2177 	
2178 	/** returns the internal value of the given external objective value */
2179 	SCIP_Real SCIPprobInternObjval(
2180 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
2181 	   SCIP_PROB*            origprob,           /**< original problem data */
2182 	   SCIP_SET*             set,                /**< global SCIP settings */
2183 	   SCIP_Real             objval              /**< external objective value */
2184 	   )
2185 	{
2186 	   assert(set != NULL);
2187 	   assert(origprob != NULL);
2188 	   assert(transprob != NULL);
2189 	   assert(transprob->transformed);
2190 	   assert(transprob->objscale > 0.0);
2191 	
2192 	   if( SCIPsetIsInfinity(set, objval) )
2193 	      return (SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
2194 	   else if( SCIPsetIsInfinity(set, -objval) )
2195 	      return -(SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
2196 	   else
2197 	      return (SCIP_Real)transprob->objsense * (objval - origprob->objoffset)/transprob->objscale - transprob->objoffset;
2198 	}
2199 	
2200 	/** returns variable of the problem with given name */
2201 	SCIP_VAR* SCIPprobFindVar(
2202 	   SCIP_PROB*            prob,               /**< problem data */
2203 	   const char*           name                /**< name of variable to find */
2204 	   )
2205 	{
2206 	   assert(prob != NULL);
2207 	   assert(name != NULL);
2208 	
2209 	   if( prob->varnames == NULL )
2210 	   {
2211 	      SCIPerrorMessage("Cannot find variable if variable-names hashtable was disabled (due to parameter <misc/usevartable>)\n");
2212 	      SCIPABORT();/*lint --e{527}*/ /* only in debug mode */
2213 	      return NULL;
2214 	   }
2215 	
2216 	   return (SCIP_VAR*)(SCIPhashtableRetrieve(prob->varnames, (char*)name));
2217 	}
2218 	
2219 	/** returns constraint of the problem with given name */
2220 	SCIP_CONS* SCIPprobFindCons(
2221 	   SCIP_PROB*            prob,               /**< problem data */
2222 	   const char*           name                /**< name of variable to find */
2223 	   )
2224 	{
2225 	   assert(prob != NULL);
2226 	   assert(name != NULL);
2227 	
2228 	   if( prob->consnames == NULL )
2229 	   {
2230 	      SCIPerrorMessage("Cannot find constraint if constraint-names hashtable was disabled (due to parameter <misc/useconstable>)\n");
2231 	      SCIPABORT();/*lint --e{527}*/ /* only in debug mode */
2232 	      return NULL;
2233 	   }
2234 	
2235 	   return (SCIP_CONS*)(SCIPhashtableRetrieve(prob->consnames, (char*)name));
2236 	}
2237 	
2238 	/** displays current pseudo solution */
2239 	void SCIPprobPrintPseudoSol(
2240 	   SCIP_PROB*            prob,               /**< problem data */
2241 	   SCIP_SET*             set,                /**< global SCIP settings */
2242 	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
2243 	   )
2244 	{
2245 	   SCIP_VAR* var;
2246 	   SCIP_Real solval;
2247 	   int v;
2248 	
2249 	   for( v = 0; v < prob->nvars; ++v )
2250 	   {
2251 	      var = prob->vars[v];
2252 	      assert(var != NULL);
2253 	      solval = SCIPvarGetPseudoSol(var);
2254 	      if( !SCIPsetIsZero(set, solval) )
2255 	         SCIPmessagePrintInfo(messagehdlr, " <%s>=%.15g", SCIPvarGetName(var), solval);
2256 	   }
2257 	   SCIPmessagePrintInfo(messagehdlr, "\n");
2258 	}
2259 	
2260 	/** outputs problem statistics */
2261 	void SCIPprobPrintStatistics(
2262 	   SCIP_PROB*            prob,               /**< problem data */
2263 	   SCIP_SET*             set,                /**< global SCIP settings */
2264 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2265 	   FILE*                 file                /**< output file (or NULL for standard output) */
2266 	   )
2267 	{
2268 	   assert(prob != NULL);
2269 	
2270 	   SCIPmessageFPrintInfo(messagehdlr, file, "  Problem name     : %s\n", prob->name);
2271 	   SCIPmessageFPrintInfo(messagehdlr, file, "  Variables        : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2272 	      prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
2273 	   SCIPmessageFPrintInfo(messagehdlr, file, "  Constraints      : %d initial, %d maximal\n", prob->startnconss, prob->maxnconss);
2274 	   SCIPmessageFPrintInfo(messagehdlr, file, "  Objective        : %s, %d non-zeros (abs.min = %g, abs.max = %g)\n",
2275 	         !prob->transformed ? (prob->objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize") : "minimize",
2276 	         SCIPprobGetNObjVars(prob, set), SCIPprobGetAbsMinObjCoef(prob, set), SCIPprobGetAbsMaxObjCoef(prob, set));
2277 	}
2278 	
2279 	
2280 	#ifndef NDEBUG
2281 	
2282 	/* In debug mode, the following methods are implemented as function calls to ensure
2283 	 * type validity.
2284 	 * In optimized mode, the methods are implemented as defines to improve performance.
2285 	 * However, we want to have them in the library anyways, so we have to undef the defines.
2286 	 */
2287 	
2288 	#undef SCIPprobIsPermuted
2289 	#undef SCIPprobMarkPermuted
2290 	#undef SCIPprobIsTransformed
2291 	#undef SCIPprobIsObjIntegral
2292 	#undef SCIPprobAllColsInLP
2293 	#undef SCIPprobGetObjlim
2294 	#undef SCIPprobGetData
2295 	#undef SCIPprobGetName
2296 	#undef SCIPprobGetNVars
2297 	#undef SCIPprobGetNBinVars
2298 	#undef SCIPprobGetNIntVars
2299 	#undef SCIPprobGetNImplVars
2300 	#undef SCIPprobGetNContVars
2301 	#undef SCIPprobGetNConss
2302 	#undef SCIPprobGetVars
2303 	#undef SCIPprobGetObjoffset
2304 	#undef SCIPisConsCompressedEnabled
2305 	#undef SCIPprobEnableConsCompression
2306 	
2307 	/** is the problem permuted */
2308 	SCIP_Bool SCIPprobIsPermuted(
2309 	   SCIP_PROB*            prob
2310 	   )
2311 	{
2312 	   assert(prob != NULL);
2313 	
2314 	   return prob->permuted;
2315 	}
2316 	
2317 	/** mark the problem as permuted */
2318 	void SCIPprobMarkPermuted(
2319 	   SCIP_PROB*            prob
2320 	   )
2321 	{
2322 	   assert(prob != NULL);
2323 	
2324 	   prob->permuted = TRUE;
2325 	}
2326 	
2327 	/** is the problem data transformed */
2328 	SCIP_Bool SCIPprobIsTransformed(
2329 	   SCIP_PROB*            prob                /**< problem data */
2330 	   )
2331 	{
2332 	   assert(prob != NULL);
2333 	
2334 	   return prob->transformed;
2335 	}
2336 	
2337 	/** returns whether the objective value is known to be integral in every feasible solution */
2338 	SCIP_Bool SCIPprobIsObjIntegral(
2339 	   SCIP_PROB*            prob                /**< problem data */
2340 	   )
2341 	{
2342 	   assert(prob != NULL);
2343 	
2344 	   return prob->objisintegral;
2345 	}
2346 	
2347 	/** returns TRUE iff all columns, i.e. every variable with non-empty column w.r.t. all ever created rows, are present
2348 	 *  in the LP, and FALSE, if there are additional already existing columns, that may be added to the LP in pricing
2349 	 */
2350 	SCIP_Bool SCIPprobAllColsInLP(
2351 	   SCIP_PROB*            prob,               /**< problem data */
2352 	   SCIP_SET*             set,                /**< global SCIP settings */
2353 	   SCIP_LP*              lp                  /**< current LP data */
2354 	   )
2355 	{
2356 	   assert(SCIPlpGetNCols(lp) <= prob->ncolvars && prob->ncolvars <= prob->nvars);
2357 	
2358 	   return (SCIPlpGetNCols(lp) == prob->ncolvars && set->nactivepricers == 0);
2359 	}
2360 	
2361 	/** gets limit on objective function in external space */
2362 	SCIP_Real SCIPprobGetObjlim(
2363 	   SCIP_PROB*            prob,               /**< problem data */
2364 	   SCIP_SET*             set                 /**< global SCIP settings */
2365 	   )
2366 	{
2367 	   assert(prob != NULL);
2368 	   assert(set != NULL);
2369 	
2370 	   return prob->objlim >= SCIP_INVALID ? (SCIP_Real)(prob->objsense) * SCIPsetInfinity(set) : prob->objlim;
2371 	}
2372 	
2373 	/** gets user problem data */
2374 	SCIP_PROBDATA* SCIPprobGetData(
2375 	   SCIP_PROB*            prob                /**< problem */
2376 	   )
2377 	{
2378 	   assert(prob != NULL);
2379 	
2380 	   return prob->probdata;
2381 	}
2382 	
2383 	/** gets problem name */
2384 	const char* SCIPprobGetName(
2385 	   SCIP_PROB*            prob                /**< problem data */
2386 	   )
2387 	{
2388 	   assert(prob != NULL);
2389 	   return prob->name;
2390 	}
2391 	
2392 	/** gets number of problem variables */
2393 	int SCIPprobGetNVars(
2394 	   SCIP_PROB*            prob                /**< problem data */
2395 	   )
2396 	{
2397 	   assert(prob != NULL);
2398 	   return prob->nvars;
2399 	}
2400 	
2401 	/** gets number of binary problem variables */
2402 	int SCIPprobGetNBinVars(
2403 	   SCIP_PROB*            prob                /**< problem data */
2404 	   )
2405 	{
2406 	   assert(prob != NULL);
2407 	   return prob->nbinvars;
2408 	}
2409 	
2410 	/** gets number of integer problem variables */
2411 	int SCIPprobGetNIntVars(
2412 	   SCIP_PROB*            prob                /**< problem data */
2413 	   )
2414 	{
2415 	   assert(prob != NULL);
2416 	   return prob->nintvars;
2417 	}
2418 	
2419 	/** gets number of implicit integer problem variables */
2420 	int SCIPprobGetNImplVars(
2421 	   SCIP_PROB*            prob                /**< problem data */
2422 	   )
2423 	{
2424 	   assert(prob != NULL);
2425 	   return prob->nimplvars;
2426 	}
2427 	
2428 	/** gets number of continuous problem variables */
2429 	int SCIPprobGetNContVars(
2430 	   SCIP_PROB*            prob                /**< problem data */
2431 	   )
2432 	{
2433 	   assert(prob != NULL);
2434 	   return prob->ncontvars;
2435 	}
2436 	
2437 	/** gets problem variables */
2438 	SCIP_VAR** SCIPprobGetVars(
2439 	   SCIP_PROB*            prob                /**< problem data */
2440 	   )
2441 	{
2442 	   assert(prob != NULL);
2443 	   return prob->vars;
2444 	}
2445 	
2446 	/** gets number of problem constraints */
2447 	int SCIPprobGetNConss(
2448 	   SCIP_PROB*            prob                /**< problem data */
2449 	   )
2450 	{
2451 	   assert(prob != NULL);
2452 	   return prob->nconss;
2453 	}
2454 	
2455 	/** gets the objective offset */
2456 	SCIP_Real SCIPprobGetObjoffset(
2457 	   SCIP_PROB*            prob                /**< problem data */
2458 	   )
2459 	{
2460 	   assert(prob != NULL);
2461 	   return prob->objoffset;
2462 	}
2463 	
2464 	/** gets the objective scalar */
2465 	SCIP_Real SCIPprobGetObjscale(
2466 	   SCIP_PROB*            prob                /**< problem data */
2467 	   )
2468 	{
2469 	   assert(prob != NULL);
2470 	   return prob->objscale;
2471 	}
2472 	
2473 	/** is constraint compression enabled for this problem? */
2474 	SCIP_Bool SCIPprobIsConsCompressionEnabled(
2475 	   SCIP_PROB*            prob                /**< problem data */
2476 	   )
2477 	{
2478 	   assert(prob != NULL);
2479 	
2480 	   return prob->conscompression;
2481 	}
2482 	
2483 	/** enable problem compression, i.e., constraints can reduce memory size by removing fixed variables during creation */
2484 	void SCIPprobEnableConsCompression(
2485 	   SCIP_PROB*            prob                /**< problem data */
2486 	   )
2487 	{
2488 	   assert(prob != NULL);
2489 	
2490 	   prob->conscompression = TRUE;
2491 	}
2492 	
2493 	#endif
2494