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   reopt.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  data structures and methods for collecting reoptimization information
28   	 * @author Jakob Witzig
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	#include <assert.h>
33   	#include <string.h>
34   	
35   	#include "scip/def.h"
36   	#include "scip/mem.h"
37   	#include "scip/event.h"
38   	#include "scip/scip.h"
39   	#include "scip/set.h"
40   	#include "scip/sol.h"
41   	#include "scip/var.h"
42   	#include "scip/lp.h"
43   	#include "scip/misc.h"
44   	#include "scip/reopt.h"
45   	#include "scip/tree.h"
46   	#include "scip/primal.h"
47   	#include "scip/sepastore.h"
48   	#include "scip/cutpool.h"
49   	#include "scip/prob.h"
50   	#include "scip/cons.h"
51   	#include "scip/cons_bounddisjunction.h"
52   	#include "scip/cons_linear.h"
53   	#include "scip/cons_logicor.h"
54   	#include "scip/cons_setppc.h"
55   	#include "scip/cons_linear.h"
56   	#include "scip/clock.h"
57   	#include "scip/history.h"
58   	#include "blockmemshell/memory.h"
59   	
60   	#define DEFAULT_MEM_VARAFTERDUAL    10
61   	#define DEFAULT_MEM_VAR             10
62   	#define DEFAULT_MEM_NODES         1000
63   	#define DEFAULT_MEM_RUN            200
64   	#define DEFAULT_MEM_DUALCONS        10
65   	
66   	#define DEFAULT_RANDSEED            67
67   	
68   	/* event handler properties */
69   	#define EVENTHDLR_NAME         "Reopt"
70   	#define EVENTHDLR_DESC         "node event handler for reoptimization"
71   	
72   	/* ---------------- Callback methods of event handler ---------------- */
73   	
74   	/** exec the event handler */
75   	static
76   	SCIP_DECL_EVENTEXEC(eventExecReopt)
77   	{  /*lint --e{715}*/
78   	   SCIP_NODE*          eventnode;
79   	   SCIP_Real           oldbound;
80   	   SCIP_Real           newbound;
81   	
82   	   assert(scip != NULL);
83   	   assert(eventhdlr != NULL);
84   	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
85   	   assert(SCIPvarGetType(SCIPeventGetVar(event)) != SCIP_VARTYPE_CONTINUOUS);
86   	
87   	   if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
88   	      return SCIP_OKAY;
89   	
90   	   eventnode = SCIPgetCurrentNode(scip);
91   	   oldbound = SCIPeventGetOldbound(event);
92   	   newbound = SCIPeventGetNewbound(event);
93   	
94   	   /* if we are called from the last node in the tree that is cut off, eventnode will be NULL and we do not have to store the bound changes */
95   	   if( eventnode == NULL )
96   	      return SCIP_OKAY;
97   	
98   	   /* skip if the node is not the focus node */
99   	   if( SCIPnodeGetType(eventnode) != SCIP_NODETYPE_FOCUSNODE || SCIPnodeGetDepth(eventnode) != SCIPgetEffectiveRootDepth(scip) )
100  	      return SCIP_OKAY;
101  	
102  	   SCIPdebugMsg(scip, "catch event for node %lld: <%s>: %g -> %g\n", SCIPnodeGetNumber(eventnode),
103  	         SCIPvarGetName(SCIPeventGetVar(event)), SCIPeventGetOldbound(event), SCIPeventGetNewbound(event));
104  	
105  	   assert(SCIPisFeasLT(scip, newbound, oldbound) || SCIPisFeasGT(scip, newbound, oldbound));
106  	
107  	   SCIP_CALL( SCIPaddReoptDualBndchg(scip, eventnode, SCIPeventGetVar(event), newbound, oldbound) );
108  	
109  	   return SCIP_OKAY;
110  	}
111  	
112  	/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
113  	static
114  	SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
115  	{
116  	   SCIP_VAR** vars;
117  	
118  	   assert(scip != NULL);
119  	   assert(eventhdlr != NULL);
120  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
121  	
122  	   if( !SCIPisReoptEnabled(scip) )
123  	      return SCIP_OKAY;
124  	
125  	   vars = SCIPgetVars(scip);
126  	   for( int varnr = 0; varnr < SCIPgetNVars(scip); ++varnr )
127  	   {
128  	      if( SCIPvarGetType(vars[varnr]) != SCIP_VARTYPE_CONTINUOUS )
129  	      {
130  	         SCIP_CALL(SCIPcatchVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED, eventhdlr, NULL, NULL));
131  	      }
132  	   }
133  	
134  	   return SCIP_OKAY;
135  	}
136  	
137  	/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
138  	static
139  	SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
140  	{
141  	   SCIP_VAR** vars;
142  	
143  	   assert(scip != NULL);
144  	
145  	   assert(eventhdlr != NULL);
146  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
147  	
148  	   if( !SCIPisReoptEnabled(scip) )
149  	      return SCIP_OKAY;
150  	
151  	   vars = SCIPgetVars(scip);
152  	
153  	   for( int varnr = 0; varnr < SCIPgetNVars(scip); ++varnr )
154  	   {
155  	      if( SCIPvarGetType(vars[varnr]) == SCIP_VARTYPE_BINARY )
156  	      {
157  	         SCIP_CALL(SCIPdropVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED , eventhdlr, NULL, -1));
158  	      }
159  	   }
160  	   return SCIP_OKAY;
161  	}
162  	
163  	/* ---------------- Callback methods of reoptimization methods ---------------- */
164  	
165  	/*
166  	 * memory growing methods for dynamically allocated arrays
167  	 */
168  	
169  	/** ensures size for activeconss */
170  	static
171  	SCIP_RETCODE ensureActiveconssSize(
172  	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
173  	   SCIP_SET*             set,                /**< global SCIP settings */
174  	   BMS_BLKMEM*           blkmem,             /**< block memory */
175  	   int                   num                 /**< minimum number of entries to store */
176  	   )
177  	{
178  	   if( reopt->nmaxactiveconss < num )
179  	   {
180  	      int newsize = SCIPsetCalcMemGrowSize(set, num + 1);
181  	
182  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->activeconss, reopt->nmaxactiveconss, newsize) );
183  	      reopt->nmaxactiveconss = newsize;
184  	   }
185  	   assert(num <= reopt->nmaxactiveconss);
186  	
187  	   return SCIP_OKAY;
188  	}
189  	
190  	/** ensures, that sols[pos] array can store at least num entries */
191  	static
192  	SCIP_RETCODE ensureSolsSize(
193  	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
194  	   SCIP_SET*             set,                /**< global SCIP settings */
195  	   BMS_BLKMEM*           blkmem,             /**< block memory */
196  	   int                   num,                /**< minimum number of entries to store */
197  	   int                   runidx              /**< run index for which the memory should checked */
198  	   )
199  	{
200  	   assert(runidx >= 0);
201  	   assert(runidx <= reopt->runsize);
202  	
203  	   if( num > reopt->soltree->solssize[runidx] )
204  	   {
205  	      int newsize = SCIPsetCalcMemGrowSize(set, num + 1);
206  	
207  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols[runidx],
208  	            reopt->soltree->solssize[runidx], newsize) ); /*lint !e866 */
209  	
210  	      reopt->soltree->solssize[runidx] = newsize;
211  	   }
212  	   assert(num <= reopt->soltree->solssize[runidx]);
213  	
214  	   return SCIP_OKAY;
215  	}
216  	
217  	/** ensures, that sols array can store at least num entries */
218  	static
219  	SCIP_RETCODE ensureRunSize(
220  	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
221  	   SCIP_SET*             set,                /**< gloabl SCIP settings */
222  	   int                   num,                /**< minimum number of entries to store */
223  	   BMS_BLKMEM*           blkmem              /**< block memory */
224  	   )
225  	{
226  	   if( num >= reopt->runsize )
227  	   {
228  	      int newsize = SCIPsetCalcMemGrowSize(set, num+1);
229  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize, newsize) );
230  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize, newsize) );
231  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize, newsize) );
232  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->prevbestsols, reopt->runsize, newsize) );
233  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->varhistory, reopt->runsize, newsize) );
234  	      SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs, newsize) );
235  	
236  	      for( int s = reopt->runsize; s < newsize; ++s )
237  	      {
238  	         reopt->varhistory[s] = NULL;
239  	         reopt->prevbestsols[s] = NULL;
240  	         reopt->objs[s] = NULL;
241  	         reopt->soltree->solssize[s] = 0;
242  	         reopt->soltree->nsols[s] = 0;
243  	         reopt->soltree->sols[s] = NULL;
244  	      }
245  	
246  	      reopt->runsize = newsize;
247  	   }
248  	   assert(num < reopt->runsize);
249  	
250  	   return SCIP_OKAY;
251  	}
252  	
253  	/** check the memory of the reoptimization tree and if necessary reallocate */
254  	static
255  	SCIP_RETCODE reopttreeCheckMemory(
256  	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
257  	   SCIP_SET*             set,                /**< global SCIP settings */
258  	   BMS_BLKMEM*           blkmem              /**< block memory */
259  	   )
260  	{
261  	   assert(reopttree != NULL);
262  	   assert(blkmem != NULL);
263  	
264  	   if( SCIPqueueIsEmpty(reopttree->openids) )
265  	   {
266  	      int newsize;
267  	
268  	      assert(reopttree->nreoptnodes == (int)(reopttree->reoptnodessize));
269  	
270  	      newsize = SCIPsetCalcMemGrowSize(set, (int)reopttree->reoptnodessize+1);
271  	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize, newsize) ); /*lint !e647*/
272  	
273  	      for( unsigned int id = reopttree->reoptnodessize; id < (unsigned int)newsize; ++id )
274  	      {
275  	         SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
276  	         reopttree->reoptnodes[id] = NULL;
277  	      }
278  	
279  	      reopttree->reoptnodessize = (unsigned int)newsize;
280  	   }
281  	
282  	   return SCIP_OKAY;
283  	}
284  	
285  	/** check allocated memory of a node within the reoptimization tree and if necessary reallocate */
286  	static
287  	SCIP_RETCODE reoptnodeCheckMemory(
288  	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reoptimization tree */
289  	   SCIP_SET*             set,                /**< global SCIP settings */
290  	   BMS_BLKMEM*           blkmem,             /**< block memory */
291  	   int                   var_mem,            /**< memory for variables */
292  	   int                   child_mem,          /**< memory for child nodes */
293  	   int                   conss_mem           /**< memory for constraints */
294  	   )
295  	{
296  	   int newsize;
297  	
298  	   assert(reoptnode != NULL);
299  	   assert(blkmem != NULL);
300  	   assert(var_mem >= 0);
301  	   assert(child_mem >= 0);
302  	   assert(conss_mem >= 0);
303  	
304  	   /* check allocated memory for variable and bound information */
305  	   if( var_mem > 0 )
306  	   {
307  	      if( reoptnode->varssize == 0 )
308  	      {
309  	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->vars, var_mem) );
310  	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varbounds, var_mem) );
311  	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, var_mem) );
312  	         reoptnode->varssize = var_mem;
313  	      }
314  	      else if( reoptnode->varssize < var_mem )
315  	      {
316  	         newsize = SCIPsetCalcMemGrowSize(set, var_mem+1);
317  	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->vars, reoptnode->varssize, newsize) );
318  	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varbounds, reoptnode->varssize, newsize) );
319  	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, reoptnode->varssize, newsize) );
320  	         reoptnode->varssize = newsize;
321  	      }
322  	   }
323  	
324  	   /* check allocated memory for child node information */
325  	   if( child_mem > 0 )
326  	   {
327  	      if( reoptnode->allocchildmem == 0 )
328  	      {
329  	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->childids, child_mem) );
330  	         reoptnode->nchilds = 0;
331  	         reoptnode->allocchildmem = child_mem;
332  	      }
333  	      else if( reoptnode->allocchildmem < child_mem )
334  	      {
335  	         newsize = SCIPsetCalcMemGrowSize(set, child_mem+1);
336  	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->childids, reoptnode->allocchildmem, newsize) );
337  	         reoptnode->allocchildmem = newsize;
338  	      }
339  	   }
340  	
341  	   /* check allocated memory for add constraints */
342  	   if( conss_mem > 0 )
343  	   {
344  	      if( reoptnode->consssize == 0 )
345  	      {
346  	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->conss, conss_mem) );
347  	         reoptnode->nconss = 0;
348  	         reoptnode->consssize = conss_mem;
349  	      }
350  	      else if( reoptnode->consssize < conss_mem )
351  	      {
352  	         newsize = SCIPsetCalcMemGrowSize(set, conss_mem);
353  	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->conss, reoptnode->consssize, newsize) );
354  	         reoptnode->consssize = newsize;
355  	      }
356  	   }
357  	
358  	   return SCIP_OKAY;
359  	}
360  	
361  	/*
362  	 * local methods
363  	 */
364  	
365  	/** returns the number of stored solutions in the subtree induced by @p solnode */
366  	static
367  	int soltreeNInducedSols(
368  	   SCIP_SOLNODE*         solnode             /**< node within the solution tree */
369  	   )
370  	{
371  	   SCIP_SOLNODE* sibling;
372  	   int nsols;
373  	
374  	   assert(solnode != NULL);
375  	
376  	   if( solnode->child == NULL && solnode->sol == NULL )
377  	      return 0;
378  	   if( solnode->child == NULL && solnode->sol != NULL )
379  	      return 1;
380  	
381  	   nsols = 0;
382  	   sibling = solnode->child;
383  	
384  	   /* traverse through the list */
385  	   while( sibling != NULL )
386  	   {
387  	      nsols += soltreeNInducedSols(sibling);
388  	      sibling = sibling->sibling;
389  	   }
390  	
391  	   return nsols;
392  	}
393  	
394  	/** returns the similarity of the objective functions of two given iterations */
395  	static
396  	SCIP_Real reoptSimilarity(
397  	   SCIP_REOPT*           reopt,              /**< reoptimization data */
398  	   SCIP_SET*             set,                /**< global SCIP settings */
399  	   int                   obj1_id,            /**< id of one objective function */
400  	   int                   obj2_id,            /**< id of the other objective function */
401  	   SCIP_VAR**            vars,               /**< problem variables */
402  	   int                   nvars               /**< number of problem variables */
403  	   )
404  	{
405  	   SCIP_Real similarity;
406  	   SCIP_Real norm_obj1;
407  	   SCIP_Real norm_obj2;
408  	
409  	   assert(reopt != NULL);
410  	   assert(vars != NULL);
411  	   assert(nvars >= 0);
412  	
413  	   similarity = 0.0;
414  	   norm_obj1 = 0.0;
415  	   norm_obj2 = 0.0;
416  	
417  	   /* calculate similarity */
418  	   for( int v = 0; v < nvars; ++v )
419  	   {
420  	      SCIP_VAR* origvar;
421  	      SCIP_VAR* transvar;
422  	      SCIP_Real c1;
423  	      SCIP_Real c2;
424  	      SCIP_Real lb;
425  	      SCIP_Real ub;
426  	
427  	      origvar = vars[v];
428  	
429  	      /* get the original variable */
430  	      if( !SCIPvarIsOriginal(origvar) )
431  	      {
432  	         SCIP_RETCODE retcode;
433  	         SCIP_Real constant = 0.0;
434  	         SCIP_Real scalar = 1.0;
435  	
436  	         retcode = SCIPvarGetOrigvarSum(&origvar, &scalar, &constant);
437  	
438  	         if( retcode != SCIP_OKAY )
439  	            return SCIP_INVALID;
440  	      }
441  	      assert(origvar != NULL && SCIPvarIsOriginal(origvar));
442  	
443  	      /* get the transformed variable, we skip globally fixed variables */
444  	      transvar = SCIPvarGetTransVar(origvar);
445  	      assert(transvar != NULL);
446  	
447  	      lb = SCIPvarGetLbLocal(transvar);
448  	      ub = SCIPvarGetUbLocal(transvar);
449  	
450  	      if( SCIPsetIsFeasLT(set, lb, ub) )
451  	      {
452  	         int probidx;
453  	
454  	         probidx = SCIPvarGetIndex(origvar);
455  	         assert(0 <= probidx && probidx < reopt->nobjvars);
456  	
457  	         c1 = reopt->objs[obj1_id][probidx];
458  	         c2 = reopt->objs[obj2_id][probidx];
459  	
460  	         /* vector product */
461  	         similarity += c1*c2;
462  	         norm_obj1 += SQR(c1);
463  	         norm_obj2 += SQR(c2);
464  	      }
465  	   }
466  	
467  	   /* divide similarity by norms of the objective vectors */
468  	   norm_obj1 = SQRT(norm_obj1);
469  	   norm_obj2 = SQRT(norm_obj2);
470  	
471  	   if( !SCIPsetIsZero(set, norm_obj1) && !SCIPsetIsZero(set, norm_obj2) )
472  	      similarity /= (norm_obj1 * norm_obj2);
473  	
474  	   /* make sure that we are between -1.0 und +1.0 */
475  	   similarity = MAX(similarity, -1.0);
476  	   similarity = MIN(similarity, 1.0);
477  	
478  	   return similarity;
479  	}
480  	
481  	/** delete the given reoptimization node */
482  	static
483  	SCIP_RETCODE reoptnodeDelete(
484  	   SCIP_REOPTNODE**      reoptnode,          /**< node of the reoptimization tree */
485  	   BMS_BLKMEM*           blkmem              /**< block memory */
486  	   )
487  	{
488  	   assert((*reoptnode) != NULL );
489  	   assert(blkmem != NULL );
490  	
491  	   /* delete data for constraints */
492  	   if( (*reoptnode)->consssize > 0 )
493  	   {
494  	      assert((*reoptnode)->conss != NULL);
495  	
496  	      for( int c = 0; c < (*reoptnode)->nconss; ++c )
497  	      {
498  	         assert((*reoptnode)->conss[c] != NULL);
499  	         assert((*reoptnode)->conss[c]->vals != NULL);
500  	         assert((*reoptnode)->conss[c]->vars != NULL);
501  	
502  	         BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->boundtypes, (*reoptnode)->conss[c]->varssize);
503  	         BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->vals, (*reoptnode)->conss[c]->varssize);
504  	         BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->vars, (*reoptnode)->conss[c]->varssize);
505  	         BMSfreeBlockMemory(blkmem, &(*reoptnode)->conss[c]); /*lint !e866*/
506  	      }
507  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->conss, (*reoptnode)->consssize);
508  	      (*reoptnode)->nconss = 0;
509  	      (*reoptnode)->consssize = 0;
510  	      (*reoptnode)->conss = NULL;
511  	   }
512  	
513  	   /* free list of children */
514  	   if( (*reoptnode)->childids != NULL )
515  	   {
516  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->childids, (*reoptnode)->allocchildmem);
517  	      (*reoptnode)->nchilds = 0;
518  	      (*reoptnode)->allocchildmem = 0;
519  	      (*reoptnode)->childids = NULL;
520  	   }
521  	
522  	   /* delete dual constraint */
523  	   if( (*reoptnode)->dualredscur != NULL )
524  	   {
525  	      assert((*reoptnode)->dualredscur->varssize > 0);
526  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->boundtypes, (*reoptnode)->dualredscur->varssize);
527  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->vals, (*reoptnode)->dualredscur->varssize);
528  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->vars, (*reoptnode)->dualredscur->varssize);
529  	      BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualredscur);
530  	      (*reoptnode)->dualredscur = NULL;
531  	   }
532  	
533  	   /* delete dual constraint */
534  	   if( (*reoptnode)->dualredsnex != NULL )
535  	   {
536  	      assert((*reoptnode)->dualredsnex->varssize > 0);
537  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->boundtypes, (*reoptnode)->dualredsnex->varssize);
538  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->vals, (*reoptnode)->dualredsnex->varssize);
539  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->vars, (*reoptnode)->dualredsnex->varssize);
540  	      BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualredsnex);
541  	      (*reoptnode)->dualredsnex = NULL;
542  	   }
543  	
544  	   /* free boundtypes */
545  	   if ((*reoptnode)->varboundtypes != NULL )
546  	   {
547  	      assert((*reoptnode)->varssize > 0);
548  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varboundtypes, (*reoptnode)->varssize);
549  	      (*reoptnode)->varboundtypes = NULL;
550  	   }
551  	
552  	   /* free bounds */
553  	   if ((*reoptnode)->varbounds != NULL )
554  	   {
555  	      assert((*reoptnode)->varssize > 0);
556  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varbounds, (*reoptnode)->varssize);
557  	      (*reoptnode)->varbounds = NULL;
558  	   }
559  	
560  	   /* free variables */
561  	   if ((*reoptnode)->vars != NULL )
562  	   {
563  	      assert((*reoptnode)->varssize > 0);
564  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->vars, (*reoptnode)->varssize);
565  	      (*reoptnode)->vars = NULL;
566  	   }
567  	
568  	   (*reoptnode)->varssize = 0;
569  	
570  	   /* free afterdual-boundtypes */
571  	   if ((*reoptnode)->afterdualvarboundtypes != NULL )
572  	   {
573  	      assert((*reoptnode)->afterdualvarssize > 0);
574  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarboundtypes, (*reoptnode)->afterdualvarssize);
575  	      (*reoptnode)->afterdualvarboundtypes = NULL;
576  	   }
577  	
578  	   /* free afterdual-bounds */
579  	   if ((*reoptnode)->afterdualvarbounds != NULL )
580  	   {
581  	      assert((*reoptnode)->afterdualvarssize > 0);
582  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarbounds, (*reoptnode)->afterdualvarssize);
583  	      (*reoptnode)->afterdualvarbounds = NULL;
584  	   }
585  	
586  	   /* free afterdual-variables */
587  	   if ((*reoptnode)->afterdualvars != NULL )
588  	   {
589  	      assert((*reoptnode)->afterdualvarssize > 0);
590  	      BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvars, (*reoptnode)->afterdualvarssize);
591  	      (*reoptnode)->afterdualvars = NULL;
592  	   }
593  	
594  	   (*reoptnode)->afterdualvarssize = 0;
595  	
596  	   BMSfreeBlockMemory(blkmem, reoptnode);
597  	   (*reoptnode) = NULL;
598  	
599  	   return SCIP_OKAY;
600  	}
601  	
602  	/** reset the given reoptimization node */
603  	static
604  	SCIP_RETCODE reoptnodeReset(
605  	   SCIP_REOPTNODE*       reoptnode,          /**< reoptimization node */
606  	   SCIP_SET*             set,                /**< global SCIP settings */
607  	   BMS_BLKMEM*           blkmem              /**< block memory */
608  	   )
609  	{
610  	   assert(reoptnode != NULL);
611  	   assert(set != NULL);
612  	   assert(blkmem != NULL);
613  	
614  	   /* remove and delete all constraints */
615  	   if( reoptnode->nconss > 0 )
616  	   {
617  	      assert(reoptnode->conss != NULL);
618  	      assert(reoptnode->consssize > 0);
619  	
620  	      for( int c = 0; c < reoptnode->nconss; ++c )
621  	      {
622  	         if( !reoptnode->conss[c]->linear )
623  	         {
624  	            assert(reoptnode->conss[c]->boundtypes != NULL);
625  	            BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
626  	         }
627  	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
628  	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
629  	         BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866 */
630  	      }
631  	      reoptnode->nconss = 0;
632  	   }
633  	
634  	   /* remove all children */
635  	   if( reoptnode->childids != NULL )
636  	      reoptnode->nchilds = 0;
637  	
638  	   /* delete dual constraint */
639  	   if( reoptnode->dualredscur != NULL )
640  	   {
641  	      assert(reoptnode->dualredscur->varssize > 0);
642  	      if( !reoptnode->dualredscur->linear )
643  	      {
644  	         assert(reoptnode->dualredscur->boundtypes != NULL);
645  	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->boundtypes, reoptnode->dualredscur->varssize);
646  	      }
647  	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vals, reoptnode->dualredscur->varssize);
648  	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vars, reoptnode->dualredscur->varssize);
649  	      BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
650  	      reoptnode->dualredscur = NULL;
651  	   }
652  	
653  	   /* delete dual constraint */
654  	   if( reoptnode->dualredsnex != NULL )
655  	   {
656  	      assert(reoptnode->dualredsnex->varssize > 0);
657  	      if( !reoptnode->dualredsnex->linear )
658  	      {
659  	         assert(reoptnode->dualredsnex->boundtypes != NULL);
660  	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->boundtypes, reoptnode->dualredsnex->varssize);
661  	      }
662  	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->vals, reoptnode->dualredsnex->varssize);
663  	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->vars, reoptnode->dualredsnex->varssize);
664  	      BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
665  	      reoptnode->dualredsnex = NULL;
666  	   }
667  	
668  	   reoptnode->parentID = 0;
669  	   reoptnode->nvars = 0;
670  	   reoptnode->nafterdualvars = 0;
671  	   reoptnode->dualreds = FALSE;
672  	   reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
673  	   reoptnode->lowerbound = -SCIPsetInfinity(set);
674  	
675  	   return SCIP_OKAY;
676  	}
677  	
678  	/** delete the node stored at position @p nodeID of the reoptimization tree */
679  	static
680  	SCIP_RETCODE reopttreeDeleteNode(
681  	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
682  	   SCIP_SET*             set,                /**< global SCIP settings */
683  	   BMS_BLKMEM*           blkmem,             /**< block memory */
684  	   unsigned int          id,                 /**< id of a node */
685  	   SCIP_Bool             softreset           /**< delete at the end of the solving process */
686  	   )
687  	{
688  	   assert(reopttree != NULL );
689  	   assert(id < reopttree->reoptnodessize);
690  	   assert(reopttree->reoptnodes[id] != NULL );
691  	
692  	   if( softreset )
693  	   {
694  	      SCIP_CALL( reoptnodeReset(reopttree->reoptnodes[id], set, blkmem) );
695  	   }
696  	   else
697  	   {
698  	      SCIP_CALL( reoptnodeDelete(&reopttree->reoptnodes[id], blkmem) );
699  	   }
700  	
701  	   assert(softreset || reopttree->reoptnodes[id] == NULL);
702  	   assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->conss == NULL || reopttree->reoptnodes[id]->nconss == 0);
703  	   assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->childids == NULL || reopttree->reoptnodes[id]->nchilds == 0);
704  	
705  	   --reopttree->nreoptnodes;
706  	
707  	   return SCIP_OKAY;
708  	}
709  	
710  	/** constructor of the solution tree */
711  	static
712  	SCIP_RETCODE createSolTree(
713  	   SCIP_SOLTREE*         soltree,            /**< solution tree */
714  	   BMS_BLKMEM*           blkmem              /**< block memory */
715  	   )
716  	{
717  	   assert(soltree != NULL);
718  	
719  	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &soltree->sols, DEFAULT_MEM_RUN) );
720  	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &soltree->nsols, DEFAULT_MEM_RUN) );
721  	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &soltree->solssize, DEFAULT_MEM_RUN) );
722  	
723  	   for( int s = 0; s < DEFAULT_MEM_RUN; ++s )
724  	   {
725  	      soltree->nsols[s] = 0;
726  	      soltree->solssize[s] = 0;
727  	      soltree->sols[s] = NULL;
728  	   }
729  	
730  	   /* allocate the root node */
731  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, &soltree->root) );
732  	   soltree->root->sol = NULL;
733  	   soltree->root->value = SCIP_INVALID;
734  	   soltree->root->updated = FALSE;
735  	   soltree->root->father = NULL;
736  	   soltree->root->child = NULL;
737  	   soltree->root->sibling = NULL;
738  	
739  	   return SCIP_OKAY;
740  	}
741  	
742  	/** free the given solution node */
743  	static
744  	SCIP_RETCODE soltreefreeNode(
745  	   SCIP_REOPT*           reopt,              /**< reoptimization data */
746  	   SCIP_SET*             set,                /**< global SCIP settings */
747  	   SCIP_PRIMAL*          primal,             /**< the primal */
748  	   BMS_BLKMEM*           blkmem,             /**< block memory */
749  	   SCIP_SOLNODE**        solnode             /**< node within the solution tree */
750  	   )
751  	{
752  	   SCIP_SOLNODE* child;
753  	   SCIP_SOLNODE* sibling;
754  	
755  	   assert(reopt != NULL);
756  	   assert(set != NULL);
757  	   assert(primal != NULL || set->stage == SCIP_STAGE_INIT);
758  	   assert(solnode != NULL);
759  	   assert(blkmem != NULL);
760  	
761  	   child = (*solnode)->child;
762  	
763  	   /* traverse through the list and free recursive all subtree */
764  	   while( child != NULL )
765  	   {
766  	      SCIP_CALL( soltreefreeNode(reopt, set, primal, blkmem, &child) );
767  	      assert(child != NULL);
768  	
769  	      sibling = child->sibling;
770  	      BMSfreeBlockMemoryNull(blkmem, &child);
771  	      child = sibling;
772  	   }
773  	
774  	   if( (*solnode)->sol != NULL )
775  	   {
776  	      assert(set->stage == SCIP_STAGE_PROBLEM);
777  	
778  	      SCIP_CALL( SCIPsolFree(&(*solnode)->sol, blkmem, primal) );
779  	   }
780  	
781  	   return SCIP_OKAY;
782  	}
783  	
784  	/** free the solution tree */
785  	static
786  	SCIP_RETCODE freeSolTree(
787  	   SCIP_REOPT*           reopt,              /**< reoptimization data */
788  	   SCIP_SET*             set,                /**< global SCIP settings */
789  	   SCIP_PRIMAL*          origprimal,         /**< the origprimal */
790  	   BMS_BLKMEM*           blkmem              /**< block memory */
791  	   )
792  	{
793  	   assert(reopt != NULL);
794  	   assert(reopt->soltree != NULL);
795  	   assert(reopt->soltree->root != NULL);
796  	   assert(set != NULL);
797  	   assert(blkmem != NULL);
798  	
799  	   /* free all nodes recursive */
800  	   SCIP_CALL( soltreefreeNode(reopt, set, origprimal, blkmem, &reopt->soltree->root) );
801  	   BMSfreeBlockMemoryNull(blkmem, &reopt->soltree->root);
802  	
803  	   BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize);
804  	   BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize);
805  	   BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize);
806  	
807  	   BMSfreeMemory(&reopt->soltree);
808  	
809  	   return SCIP_OKAY;
810  	}
811  	
812  	/** creates and adds a solution node to the solution tree */
813  	static
814  	SCIP_RETCODE solnodeAddChild(
815  	   SCIP_SET*             set,                /**< global SCIP settings */
816  	   BMS_BLKMEM*           blkmem,             /**< block memory */
817  	   SCIP_SOLNODE*         curnode,            /**< current node in the solution tree */
818  	   SCIP_SOLNODE**        child,              /**< pointer to store the node representing the solution value */
819  	   SCIP_VAR*             var,                /**< variable represented by this node */
820  	   SCIP_Real             val,                /**< value the child shell represent */
821  	   SCIP_Bool*            added               /**< TRUE iff we created a new node, i.e, we have not seen this solution so far */
822  	   )
823  	{
824  	   SCIP_SOLNODE* solnode;
825  	
826  	   assert(set != NULL);
827  	   assert(blkmem != NULL);
828  	   assert(curnode != NULL);
829  	   assert(child != NULL && *child == NULL);
830  	   assert(!SCIPsetIsInfinity(set, -val) && !SCIPsetIsInfinity(set, val));
831  	
832  	   /* get the first node of the child node list */
833  	   *child = curnode->child;
834  	
835  	   /* this is the first solution in the subtree induced by the current node */
836  	   if( *child == NULL )
837  	   {
838  	      assert(soltreeNInducedSols(curnode) == 0);
839  	
840  	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
841  	      solnode->sol = NULL;
842  	      solnode->updated = FALSE;
843  	      solnode->father = curnode;
844  	      solnode->child = NULL;
845  	      solnode->sibling = NULL;
846  	      solnode->value = val;
847  	#ifndef NDEBUG
848  	      assert(var != NULL);
849  	      solnode->var = var;
850  	#endif
851  	
852  	      *added = TRUE;
853  	      *child = solnode;
854  	
855  	      curnode->child = *child;
856  	
857  	#ifdef SCIP_MORE_DEBUG
858  	      SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
859  	            (void*) solnode->sibling);
860  	#endif
861  	   }
862  	   else
863  	   {
864  	      /* we traverse through all children */
865  	      while( *child != NULL )
866  	      {
867  	#ifdef SCIP_MORE_DEBUG
868  	         SCIPsetDebugMsg(set, "-> check %p: father=%p, value=%g, sibling=%p\n", (void*) *child, (void*) (*child)->father,
869  	               (*child)->value, (void*) (*child)->sibling);
870  	#endif
871  	         /* we found a node repesenting this solution value */
872  	         if( SCIPsetIsEQ(set, val, (*child)->value) )
873  	            break;
874  	
875  	         /* we are at the end of the list */
876  	         if( (*child)->sibling == NULL )
877  	         {
878  	            /* create a new solnode */
879  	            SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
880  	            solnode->sol = NULL;
881  	            solnode->updated = FALSE;
882  	            solnode->father = curnode;
883  	            solnode->child = NULL;
884  	            solnode->value = val;
885  	#ifndef NDEBUG
886  	            assert(var != NULL);
887  	            solnode->var = var;
888  	#endif
889  	            *added = TRUE;
890  	
891  	            /* we have to append the new node at the end of the list. but we have to check whether the insertion before
892  	             * the current node would be correct. in that case, we switch the values, the child pointer, and the
893  	             * solution
894  	             */
895  	            solnode->sibling = NULL;
896  	            (*child)->sibling = solnode;
897  	
898  	#ifdef SCIP_MORE_DEBUG
899  	            SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
900  	               (void*) solnode->sibling);
901  	#endif
902  	            /* the given value is lower than the current, insertion before the current node would be correct
903  	             * in this case we do not have to change the child pointer
904  	             */
905  	            if( SCIPsetIsLT(set, val, (*child)->value) )
906  	            {
907  	#ifdef SCIP_MORE_DEBUG
908  	               SCIPsetDebugMsg(set, "-> need to switch:\n");
909  	               SCIPsetDebugMsg(set, "   before switching: node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
910  	                  (void*) (*child), (void*) (*child)->child, (void*) (*child)->sibling, (void*) (*child)->sol,
911  	                  (*child)->value);
912  	               SCIPsetDebugMsg(set, "                     node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
913  	                  (void*) solnode, (void*) solnode->child, (void*) solnode->sibling, (void*) solnode->sol,
914  	                  solnode->value);
915  	#endif
916  	               /* switch child pointer */
917  	               solnode->child = (*child)->child;
918  	               (*child)->child = NULL;
919  	
920  	               /* switch solution values */
921  	               solnode->value = (*child)->value;
922  	               (*child)->value = val;
923  	               assert(SCIPsetIsLT(set, (*child)->value, solnode->value));
924  	
925  	               /* switch solution pointer */
926  	               solnode->sol = (*child)->sol;
927  	               (*child)->sol = NULL;
928  	#ifdef SCIP_MORE_DEBUG
929  	               SCIPsetDebugMsg(set, "    after switching: node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
930  	                  (void*) (*child), (void*) (*child)->child, (void*) (*child)->sibling, (void*) (*child)->sol,
931  	                  (*child)->value);
932  	               SCIPsetDebugMsg(set, "                     node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
933  	                  (void*) solnode, (void*) solnode->child, (void*) solnode->sibling, (void*) solnode->sol,
934  	                  solnode->value);
935  	#endif
936  	            }
937  	            /* set the child pointer to the new created solnode */
938  	            else
939  	               (*child) = solnode;
940  	
941  	            break;
942  	         }
943  	
944  	         /* the next sibling represents a solution value of larger size.
945  	          * we insert a new node between the current child and the next sibling.
946  	          */
947  	         if( SCIPsetIsLT(set, val, (*child)->sibling->value) )
948  	         {
949  	            /* create a new solnode that points to the sibling of the current child */
950  	            SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
951  	            solnode->sol = NULL;
952  	            solnode->updated = FALSE;
953  	            solnode->father = curnode;
954  	            solnode->child = NULL;
955  	            solnode->sibling = (*child)->sibling;
956  	            solnode->value = val;
957  	#ifndef NDEBUG
958  	            assert(var != NULL);
959  	            solnode->var = var;
960  	#endif
961  	            *added = TRUE;
962  	
963  	            /* change the poiter of the next sibling to the new node */
964  	            (*child)->sibling = solnode;
965  	
966  	            *child = solnode;
967  	#ifdef SCIP_MORE_DEBUG
968  	            SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
969  	                  (void*) solnode->sibling);
970  	#endif
971  	            break;
972  	         }
973  	
974  	         /* go to the next sibling */
975  	         *child = (*child)->sibling;
976  	      }
977  	
978  	#ifdef SCIP_DEBUG
979  	      /* check whether the insert was correct and the list is increasing */
980  	      solnode = curnode->child;
981  	      assert(solnode != NULL);
982  	
983  	      while( solnode->sibling != NULL )
984  	      {
985  	         assert(SCIPsetIsLT(set, solnode->value, solnode->sibling->value));
986  	         solnode = solnode->sibling;
987  	      }
988  	#endif
989  	   }
990  	   return SCIP_OKAY;
991  	}
992  	
993  	/** add a solution to the solution tree */
994  	static
995  	SCIP_RETCODE soltreeAddSol(
996  	   SCIP_REOPT*           reopt,              /**< reoptimization data */
997  	   SCIP_SET*             set,                /**< global SCIP settings */
998  	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
999  	   SCIP_PRIMAL*          origprimal,         /**< orig primal */
1000 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1001 	   SCIP_VAR**            vars,               /**< array of original variables */
1002 	   SCIP_SOL*             sol,                /**< solution to add */
1003 	   SCIP_SOLNODE**        solnode,            /**< current solution node */
1004 	   int                   nvars,              /**< number of variables */
1005 	   SCIP_Bool             bestsol,            /**< is the solution an optimal (best found) solution */
1006 	   SCIP_Bool*            added               /**< pointer to store the result */
1007 	   )
1008 	{
1009 	   SCIP_SOLNODE* cursolnode;
1010 	   SCIP_Bool purelp;
1011 	
1012 	   assert(reopt != NULL);
1013 	   assert(set != NULL);
1014 	   assert(stat != NULL);
1015 	   assert(origprimal != NULL);
1016 	   assert(blkmem != NULL);
1017 	   assert(vars != NULL);
1018 	   assert(sol != NULL);
1019 	   assert(solnode != NULL);
1020 	
1021 	   cursolnode = reopt->soltree->root;
1022 	   *added = FALSE;
1023 	   purelp = TRUE;
1024 	
1025 	   if( set->reopt_savesols > 0 )
1026 	   {
1027 	#ifdef MORE_DEBUG
1028 	      SCIPsetDebugMsg(set, "try to add solution found by <%s>\n", (SCIPsolGetHeur(sol) == NULL ?
1029 	            "relaxation" : SCIPheurGetName(SCIPsolGetHeur(sol))));
1030 	#endif
1031 	
1032 	      for( int varid = 0; varid < nvars; ++varid )
1033 	      {
1034 	         if( SCIPvarGetType(vars[varid]) != SCIP_VARTYPE_CONTINUOUS )
1035 	         {
1036 	            SCIP_SOLNODE* child;
1037 	
1038 	            purelp = FALSE;
1039 	            child = NULL;
1040 	            SCIP_CALL( solnodeAddChild(set, blkmem, cursolnode, &child, vars[varid],
1041 	                  SCIPsolGetVal(sol, set, stat, vars[varid]), added) );
1042 	            assert(child != NULL);
1043 	            cursolnode = child;
1044 	         }
1045 	      }
1046 	
1047 	      /* the solution was added or is an optimal solution */
1048 	      if( (*added || bestsol) && !purelp )
1049 	      {
1050 	         SCIP_SOL* copysol;
1051 	
1052 	         assert(cursolnode->child == NULL);
1053 	
1054 	         if( *added )
1055 	         {
1056 	            SCIP_CALL( SCIPsolCopy(&copysol, blkmem, set, stat, origprimal, sol) );
1057 	            cursolnode->sol = copysol;
1058 	         }
1059 	         else
1060 	            /* this is a pseudo add; we do not want to save this solution more than once, but we will link this solution
1061 	             * to the solution storage of this round
1062 	             */
1063 	            (*added) = TRUE;
1064 	
1065 	         if( bestsol )
1066 	         {
1067 	            assert(reopt->prevbestsols != NULL);
1068 	            assert(cursolnode->sol != NULL);
1069 	
1070 	            reopt->prevbestsols[reopt->run-1] = cursolnode->sol;
1071 	         }
1072 	
1073 	         (*solnode) = cursolnode;
1074 	      }
1075 	   }
1076 	
1077 	   return SCIP_OKAY;
1078 	}
1079 	
1080 	/** reset all marks 'updated' to FALSE */
1081 	static
1082 	void soltreeResetMarks(
1083 	   SCIP_SOLNODE*         node                /**< node within the solution tree */
1084 	   )
1085 	{
1086 	   assert(node != NULL);
1087 	
1088 	   if( node->child != NULL )
1089 	   {
1090 	      SCIP_SOLNODE* child;
1091 	
1092 	      /* the node is no leaf */
1093 	      assert(node->sol == NULL);
1094 	      assert(!node->updated);
1095 	
1096 	      child = node->child;
1097 	
1098 	      /* traverse through the list of siblings */
1099 	      while( child != NULL )
1100 	      {
1101 	         soltreeResetMarks(child);
1102 	         child = child->sibling;
1103 	      }
1104 	   }
1105 	   else
1106 	   {
1107 	      /* the node is a leaf */
1108 	      assert(node->father != NULL);
1109 	      assert(node->sol != NULL);
1110 	      node->updated = FALSE;
1111 	   }
1112 	}
1113 	
1114 	/** allocate memory for a node within the reoptimization tree */
1115 	static
1116 	SCIP_RETCODE createReoptnode(
1117 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
1118 	   SCIP_SET*             set,                /**< global SCIP settings */
1119 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1120 	   unsigned int          id                  /**< id of the node to create */
1121 	   )
1122 	{
1123 	   assert(reopttree != NULL );
1124 	   assert(id < reopttree->reoptnodessize);
1125 	
1126 	   SCIPsetDebugMsg(set, "create a reoptnode at ID %u\n", id);
1127 	
1128 	   if( reopttree->reoptnodes[id] == NULL )
1129 	   {
1130 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]) ); /*lint !e866*/
1131 	
1132 	      reopttree->reoptnodes[id]->conss = NULL;
1133 	      reopttree->reoptnodes[id]->nconss = 0;
1134 	      reopttree->reoptnodes[id]->consssize = 0;
1135 	      reopttree->reoptnodes[id]->childids = NULL;
1136 	      reopttree->reoptnodes[id]->allocchildmem = 0;
1137 	      reopttree->reoptnodes[id]->nchilds = 0;
1138 	      reopttree->reoptnodes[id]->nvars = 0;
1139 	      reopttree->reoptnodes[id]->nafterdualvars = 0;
1140 	      reopttree->reoptnodes[id]->parentID = 0;
1141 	      reopttree->reoptnodes[id]->dualreds = FALSE;
1142 	      reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
1143 	      reopttree->reoptnodes[id]->varssize = 0;
1144 	      reopttree->reoptnodes[id]->afterdualvarssize = 0;
1145 	      reopttree->reoptnodes[id]->vars = NULL;
1146 	      reopttree->reoptnodes[id]->varbounds = NULL;
1147 	      reopttree->reoptnodes[id]->varboundtypes = NULL;
1148 	      reopttree->reoptnodes[id]->afterdualvars = NULL;
1149 	      reopttree->reoptnodes[id]->afterdualvarbounds = NULL;
1150 	      reopttree->reoptnodes[id]->afterdualvarboundtypes = NULL;
1151 	      reopttree->reoptnodes[id]->dualredscur = NULL;
1152 	      reopttree->reoptnodes[id]->dualredsnex = NULL;
1153 	      reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
1154 	   }
1155 	   else
1156 	   {
1157 	      assert(reopttree->reoptnodes[id]->nvars == 0);
1158 	      assert(reopttree->reoptnodes[id]->nafterdualvars == 0);
1159 	      reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
1160 	      reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
1161 	   }
1162 	
1163 	   /* increase the counter */
1164 	   ++reopttree->nreoptnodes;
1165 	
1166 	   assert(reopttree->nreoptnodes + SCIPqueueNElems(reopttree->openids) == (int)reopttree->reoptnodessize);
1167 	
1168 	   return SCIP_OKAY;
1169 	}
1170 	
1171 	/** constructor of the reoptimization tree */
1172 	static
1173 	SCIP_RETCODE createReopttree(
1174 	   SCIP_REOPTTREE*       reopttree,          /**< pointer to the reoptimization tree */
1175 	   SCIP_SET*             set,                /**< global SCIP settings */
1176 	   BMS_BLKMEM*           blkmem              /**< block memory */
1177 	   )
1178 	{
1179 	   assert(reopttree != NULL);
1180 	   assert(set != NULL);
1181 	   assert(blkmem != NULL);
1182 	
1183 	   /* allocate memory */
1184 	   reopttree->reoptnodessize = DEFAULT_MEM_NODES;
1185 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize) );
1186 	
1187 	   /* initialize the queue of open IDs */
1188 	   SCIP_CALL( SCIPqueueCreate(&reopttree->openids, (int)reopttree->reoptnodessize, 2.0) );
1189 	
1190 	   /* fill the queue, but reserve the 0 for the root */
1191 	   for( unsigned int id = 1; id < reopttree->reoptnodessize; ++id )
1192 	   {
1193 	      reopttree->reoptnodes[id] = NULL;
1194 	      SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
1195 	   }
1196 	   assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
1197 	
1198 	   reopttree->nreoptnodes = 0;
1199 	   reopttree->ntotalfeasnodes = 0;
1200 	   reopttree->nfeasnodes = 0;
1201 	   reopttree->ninfnodes = 0;
1202 	   reopttree->ntotalinfnodes= 0;
1203 	   reopttree->nprunednodes = 0;
1204 	   reopttree->ntotalprunednodes= 0;
1205 	   reopttree->ncutoffreoptnodes = 0;
1206 	   reopttree->ntotalcutoffreoptnodes = 0;
1207 	
1208 	   /* initialize the root node */
1209 	   reopttree->reoptnodes[0] = NULL;
1210 	   SCIP_CALL( createReoptnode(reopttree, set, blkmem, 0) );
1211 	
1212 	   return SCIP_OKAY;
1213 	}
1214 	
1215 	/** clears the reopttree, e.g., to restart and solve the next problem from scratch */
1216 	static
1217 	SCIP_RETCODE clearReoptnodes(
1218 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
1219 	   SCIP_SET*             set,                /**< global SCIP settings */
1220 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1221 	   SCIP_Bool             softreset           /**< delete nodes before exit the solving process */
1222 	   )
1223 	{
1224 	   assert(reopttree != NULL );
1225 	
1226 	   /* clear queue with open IDs */
1227 	   SCIPqueueClear(reopttree->openids);
1228 	   assert(SCIPqueueNElems(reopttree->openids) == 0);
1229 	
1230 	   /* delete all data about nodes */
1231 	   for( unsigned int id = 0; id < reopttree->reoptnodessize; ++id )
1232 	   {
1233 	      if( reopttree->reoptnodes[id] != NULL )
1234 	      {
1235 	         SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, softreset) );
1236 	         assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->nvars == 0);
1237 	      }
1238 	
1239 	      if( id > 0 )
1240 	      {
1241 	         SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
1242 	      }
1243 	   }
1244 	   assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
1245 	
1246 	   reopttree->nreoptnodes = 0;
1247 	
1248 	   return SCIP_OKAY;
1249 	}
1250 	
1251 	/** free the reoptimization tree */
1252 	static
1253 	SCIP_RETCODE freeReoptTree(
1254 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree data */
1255 	   SCIP_SET*             set,                /**< global SCIP settings  */
1256 	   BMS_BLKMEM*           blkmem              /**< block memory */
1257 	   )
1258 	{
1259 	   assert(reopttree != NULL);
1260 	   assert(blkmem != NULL);
1261 	
1262 	   /* free nodes */
1263 	   SCIP_CALL( clearReoptnodes(reopttree, set, blkmem, FALSE) );
1264 	
1265 	   /* free the data */
1266 	   BMSfreeBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize);
1267 	   SCIPqueueFree(&reopttree->openids);
1268 	
1269 	   /* free the tree itself */
1270 	   BMSfreeMemory(&reopttree);
1271 	
1272 	   return SCIP_OKAY;
1273 	}
1274 	
1275 	/** check memory for the constraint to handle bound changes based on dual information */
1276 	static
1277 	SCIP_RETCODE checkMemDualCons(
1278 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1279 	   SCIP_SET*             set,                /**< global SCIP settings */
1280 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1281 	   int                   size                /**< size which need to be allocated */
1282 	   )
1283 	{
1284 	   assert(reopt != NULL);
1285 	   assert(blkmem != NULL);
1286 	   assert(size > 0);
1287 	
1288 	   if( reopt->dualreds == NULL )
1289 	   {
1290 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->dualreds) );
1291 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->vars, size) );
1292 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->vals, size) );
1293 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->boundtypes, size) );
1294 	      reopt->dualreds->varssize = size;
1295 	      reopt->dualreds->nvars = 0;
1296 	   }
1297 	   else if( reopt->dualreds->varssize < size )
1298 	   {
1299 	      int newsize = SCIPsetCalcMemGrowSize(set, size+1);
1300 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->vars, reopt->dualreds->varssize, newsize) );
1301 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->vals, reopt->dualreds->varssize, newsize) );
1302 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->boundtypes, reopt->dualreds->varssize, newsize) );
1303 	      reopt->dualreds->varssize = newsize;
1304 	   }
1305 	
1306 	   return SCIP_OKAY;
1307 	}
1308 	
1309 	/** check the memory to store global constraints */
1310 	static
1311 	SCIP_RETCODE checkMemGlbCons(
1312 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1313 	   SCIP_SET*             set,                /**< global SCIP settings */
1314 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1315 	   int                   mem                 /**< memory which has to be allocated */
1316 	   )
1317 	{
1318 	   assert(reopt != NULL);
1319 	   assert(blkmem != NULL);
1320 	   assert(mem > 0);
1321 	
1322 	   if( mem > 0 ) /*lint !e774*/
1323 	   {
1324 	      if( reopt->glbconss == NULL )
1325 	      {
1326 	         SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->glbconss, mem) );
1327 	         reopt->nglbconss = 0;
1328 	         reopt->allocmemglbconss = mem;
1329 	
1330 	         for( int c = 0; c < reopt->allocmemglbconss; ++c )
1331 	            reopt->glbconss[c] = NULL;
1332 	      }
1333 	      else if( reopt->allocmemglbconss < mem )
1334 	      {
1335 	         int newsize = SCIPsetCalcMemGrowSize(set, mem+1);
1336 	
1337 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->glbconss, reopt->allocmemglbconss, newsize) );
1338 	
1339 	         for( int c = reopt->allocmemglbconss; c < newsize; ++c )
1340 	            reopt->glbconss[c] = NULL;
1341 	
1342 	         reopt->allocmemglbconss = newsize;
1343 	      }
1344 	   }
1345 	
1346 	   return SCIP_OKAY;
1347 	}
1348 	
1349 	/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
1350 	static
1351 	SCIP_RETCODE cleanActiveConss(
1352 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1353 	   SCIP_SET*             set,                /**< global SCIP settings */
1354 	   BMS_BLKMEM*           blkmem              /**< block memory */
1355 	   )
1356 	{
1357 	   assert(reopt != NULL);
1358 	
1359 	   /* exit if there are no active constraints */
1360 	   if( reopt->nactiveconss == 0 )
1361 	      return SCIP_OKAY;
1362 	
1363 	   SCIPsetDebugMsg(set, "Cleaning %d active conss.\n", reopt->nactiveconss);
1364 	   assert(reopt->activeconss != NULL);
1365 	   assert(reopt->activeconssset != NULL);
1366 	   assert(reopt->nactiveconss <= reopt->nmaxactiveconss);
1367 	
1368 	   /* loop over all stored constraints and reactivate deactivated constraints */
1369 	   for( int i = 0; i < reopt->nactiveconss; ++i )
1370 	   {
1371 	      assert(reopt->activeconss[i] != NULL);
1372 	      assert(SCIPhashsetExists(reopt->activeconssset, reopt->activeconss[i]));
1373 	      SCIP_CALL( SCIPconsRelease(&reopt->activeconss[i], blkmem, set) );
1374 	   }
1375 	
1376 	   /* also clean up hashset */
1377 	   SCIPhashsetRemoveAll(reopt->activeconssset);
1378 	   reopt->nactiveconss = 0;
1379 	
1380 	   return SCIP_OKAY;
1381 	}
1382 	
1383 	/** update the bound changes made by constraint propagations during current iteration; stop saving the bound changes if
1384 	 *  we reach a branching decision based on a dual information.
1385 	 */
1386 	static
1387 	SCIP_RETCODE updateConstraintPropagation(
1388 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1389 	   SCIP_SET*             set,                /**< global SCIP settings */
1390 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1391 	   SCIP_NODE*            node,               /**< node of the search tree */
1392 	   unsigned int          id,                 /**< id of the node */
1393 	   SCIP_Bool*            transintoorig       /**< transform variables into originals */
1394 	   )
1395 	{
1396 	   int nvars;
1397 	   int nconsprops;
1398 	   int naddedbndchgs;
1399 	
1400 	   assert(reopt != NULL);
1401 	   assert(blkmem != NULL);
1402 	   assert(node != NULL);
1403 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
1404 	   assert(reopt->reopttree->reoptnodes[id] != NULL );
1405 	
1406 	   /* get the number of all stored constraint propagations */
1407 	   SCIPnodeGetNDomchg(node, NULL, &nconsprops, NULL);
1408 	   nvars = reopt->reopttree->reoptnodes[id]->nvars;
1409 	
1410 	   if( nconsprops > 0 )
1411 	   {
1412 	      /* check the memory */
1413 	      SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, nvars + nconsprops, 0, 0) );
1414 	
1415 	      SCIPnodeGetConsProps(node,
1416 	            &reopt->reopttree->reoptnodes[id]->vars[nvars],
1417 	            &reopt->reopttree->reoptnodes[id]->varbounds[nvars],
1418 	            &reopt->reopttree->reoptnodes[id]->varboundtypes[nvars],
1419 	            &naddedbndchgs,
1420 	            reopt->reopttree->reoptnodes[id]->varssize-nvars);
1421 	
1422 	      assert(nvars + naddedbndchgs <= reopt->reopttree->reoptnodes[id]->varssize);
1423 	
1424 	      reopt->reopttree->reoptnodes[id]->nvars += naddedbndchgs;
1425 	
1426 	      *transintoorig = TRUE;
1427 	   }
1428 	
1429 	   return SCIP_OKAY;
1430 	}
1431 	
1432 	/** save bound changes made after the first bound change based on dual information, e.g., mode by strong branching
1433 	 *
1434 	 *  This method can be used during reoptimization. If we want to reconstruct a node containing dual bound changes we
1435 	 *  have to split the node into the original one and at least one node representing the pruned part. All bound changes,
1436 	 *  i.e., (constraint) propagation, made after the first bound change based on dual information are still valid for
1437 	 *  the original node after changing the objective function. thus, we can store them for the following iterations.
1438 	 *
1439 	 *  It should be noted, that these bound changes will be found by (constraint) propagation methods anyway after changing
1440 	 *  the objective function. do not saving these information and find them again might be useful for conflict analysis.
1441 	 */
1442 	static
1443 	SCIP_RETCODE saveAfterDualBranchings(
1444 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1445 	   SCIP_SET*             set,                /**< global SCIP settings */
1446 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1447 	   SCIP_NODE*            node,               /**< node of the search tree */
1448 	   unsigned int          id,                 /**< id of the node */
1449 	   SCIP_Bool*            transintoorig       /**< transform variables into originals */
1450 	   )
1451 	{
1452 	   int nbranchvars;
1453 	
1454 	   assert(reopt != NULL);
1455 	   assert(blkmem != NULL);
1456 	   assert(node != NULL);
1457 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
1458 	   assert(reopt->reopttree->reoptnodes[id] != NULL );
1459 	
1460 	   nbranchvars = 0;
1461 	
1462 	   /* allocate memory */
1463 	   if (reopt->reopttree->reoptnodes[id]->afterdualvarssize == 0)
1464 	   {
1465 	      assert(reopt->reopttree->reoptnodes[id]->afterdualvars == NULL );
1466 	      assert(reopt->reopttree->reoptnodes[id]->afterdualvarbounds == NULL );
1467 	      assert(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes == NULL );
1468 	
1469 	      /* allocate block memory for node information */
1470 	      reopt->reopttree->reoptnodes[id]->afterdualvarssize = DEFAULT_MEM_VARAFTERDUAL;
1471 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvars), \
1472 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1473 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvarbounds), \
1474 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1475 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes), \
1476 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1477 	   }
1478 	
1479 	   assert(reopt->reopttree->reoptnodes[id]->afterdualvarssize > 0);
1480 	   assert(reopt->reopttree->reoptnodes[id]->nafterdualvars >= 0);
1481 	
1482 	   SCIPnodeGetBdChgsAfterDual(node,
1483 	         reopt->reopttree->reoptnodes[id]->afterdualvars,
1484 	         reopt->reopttree->reoptnodes[id]->afterdualvarbounds,
1485 	         reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes,
1486 	         reopt->reopttree->reoptnodes[id]->nafterdualvars,
1487 	         &nbranchvars,
1488 	         reopt->reopttree->reoptnodes[id]->afterdualvarssize);
1489 	
1490 	   if( nbranchvars > reopt->reopttree->reoptnodes[id]->afterdualvarssize )
1491 	   {
1492 	      int newsize = SCIPsetCalcMemGrowSize(set, nbranchvars+1);
1493 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvars), \
1494 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
1495 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvarbounds), \
1496 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
1497 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes), \
1498 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
1499 	      reopt->reopttree->reoptnodes[id]->afterdualvarssize = newsize;
1500 	
1501 	      SCIPnodeGetBdChgsAfterDual(node,
1502 	            reopt->reopttree->reoptnodes[id]->afterdualvars,
1503 	            reopt->reopttree->reoptnodes[id]->afterdualvarbounds,
1504 	            reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes,
1505 	            reopt->reopttree->reoptnodes[id]->nafterdualvars,
1506 	            &nbranchvars,
1507 	            reopt->reopttree->reoptnodes[id]->afterdualvarssize);
1508 	   }
1509 	
1510 	   /* the stored variables of this node need to be transformed into the original space */
1511 	   if( nbranchvars > 0 )
1512 	      *transintoorig = TRUE;
1513 	
1514 	   SCIPsetDebugMsg(set, " -> save %d bound changes after dual reductions\n", nbranchvars);
1515 	
1516 	   assert(nbranchvars <= reopt->reopttree->reoptnodes[id]->afterdualvarssize); /* this should be the case */
1517 	
1518 	   reopt->reopttree->reoptnodes[id]->nafterdualvars = nbranchvars;
1519 	
1520 	   return SCIP_OKAY;
1521 	}
1522 	
1523 	/** store cuts that are active in the current LP */
1524 	static
1525 	SCIP_RETCODE storeCuts(
1526 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1527 	   SCIP_SET*             set,                /**< global SCIP settings */
1528 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1529 	   SCIP_LP*              lp,                 /**< current LP */
1530 	   unsigned int          id                  /**< id in the reopttree */
1531 	   )
1532 	{
1533 	   SCIP_ROW** lprows;
1534 	   int nlprows;
1535 	
1536 	   assert(reopt != NULL);
1537 	   assert(set != NULL);
1538 	   assert(lp != NULL);
1539 	   assert(blkmem != NULL);
1540 	
1541 	   lprows = SCIPlpGetRows(lp);
1542 	   nlprows = SCIPlpGetNRows(lp);
1543 	
1544 	   for( int r = 0; r < nlprows; ++r )
1545 	   {
1546 	      /* we can break if we reach the first row that is not part of the current LP */
1547 	      if( SCIProwGetLPPos(lprows[r]) == -1 )
1548 	         break;
1549 	
1550 	      /* currently we only want to store cuts generated by a seperator */
1551 	      if( SCIProwGetOrigintype(lprows[r]) == SCIP_ROWORIGINTYPE_SEPA && SCIProwGetAge(lprows[r]) <= set->reopt_maxcutage )
1552 	      {
1553 	         SCIP_VAR** cutvars;
1554 	         SCIP_COL** cols;
1555 	         SCIP_Real* cutvals;
1556 	         SCIP_Real lhs;
1557 	         SCIP_Real rhs;
1558 	         int ncutvars;
1559 	         SCIP_Bool storecut;
1560 	
1561 	         ncutvars = SCIProwGetNLPNonz(lprows[r]);
1562 	         lhs = SCIProwGetLhs(lprows[r]);
1563 	         rhs = SCIProwGetRhs(lprows[r]);
1564 	
1565 	         /* subtract row constant */
1566 	         if( !SCIPsetIsInfinity(set, -lhs) )
1567 	            lhs -= SCIProwGetConstant(lprows[r]);
1568 	         if( !SCIPsetIsInfinity(set, rhs) )
1569 	            rhs -= SCIProwGetConstant(lprows[r]);
1570 	
1571 	         cutvals = SCIProwGetVals(lprows[r]);
1572 	         cols = SCIProwGetCols(lprows[r]);
1573 	         storecut = TRUE;
1574 	
1575 	         SCIP_CALL( SCIPsetAllocBufferArray(set, &cutvars, ncutvars) );
1576 	
1577 	         for( int c = 0; c < ncutvars; ++c )
1578 	         {
1579 	            SCIP_Real constant;
1580 	            SCIP_Real scalar;
1581 	
1582 	            cutvars[c] = SCIPcolGetVar(cols[c]);
1583 	            assert(cutvars[c] != NULL);
1584 	
1585 	            constant = 0.0;
1586 	            scalar = 1.0;
1587 	
1588 	            SCIP_CALL( SCIPvarGetOrigvarSum(&cutvars[c], &scalar, &constant) );
1589 	
1590 	            /* the cut contains an artificial variable that might not be present after modifying the problem */
1591 	            if( cutvars[c] != NULL )
1592 	            {
1593 	               storecut = FALSE;
1594 	               break;
1595 	            }
1596 	
1597 	            assert(cutvars[c] != NULL);
1598 	            assert(!SCIPsetIsZero(set, scalar));
1599 	
1600 	            /* subtract constant from sides */
1601 	            if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, -lhs) )
1602 	               lhs -= constant;
1603 	            if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, rhs) )
1604 	               rhs -= constant;
1605 	
1606 	            cutvals[c] = cutvals[c]/scalar;
1607 	         }
1608 	
1609 	         if( storecut )
1610 	         {
1611 	            /* add cut as a linear constraint */
1612 	            SCIP_CALL( SCIPreoptnodeAddCons(reopt->reopttree->reoptnodes[id], set, blkmem, cutvars, cutvals, NULL,
1613 	                  lhs, rhs, ncutvars, REOPT_CONSTYPE_CUT, TRUE) );
1614 	         }
1615 	
1616 	         SCIPsetFreeBufferArray(set, &cutvars);
1617 	      }
1618 	   }
1619 	
1620 	   return SCIP_OKAY;
1621 	}
1622 	
1623 	/** transform variable and bounds back to the original space */
1624 	static
1625 	SCIP_RETCODE transformIntoOrig(
1626 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1627 	   unsigned int          id                  /**< id of the node */
1628 	   )
1629 	{
1630 	   assert(reopt != NULL );
1631 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
1632 	   assert(reopt->reopttree->reoptnodes[id] != NULL );
1633 	
1634 	   /* transform branching variables and bound changes applied before the first dual reduction */
1635 	   for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
1636 	   {
1637 	      SCIP_Real constant = 0.0;
1638 	      SCIP_Real scalar = 1.0;
1639 	
1640 	      if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]) )
1641 	      {
1642 	         SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->vars[varnr], &scalar, &constant)) ;
1643 	         reopt->reopttree->reoptnodes[id]->varbounds[varnr] = (reopt->reopttree->reoptnodes[id]->varbounds[varnr] - constant) / scalar;
1644 	      }
1645 	      assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]));
1646 	   }
1647 	
1648 	   /* transform bound changes affected by dual reduction */
1649 	   for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
1650 	   {
1651 	      SCIP_Real constant = 0.0;
1652 	      SCIP_Real scalar = 1.0;
1653 	
1654 	      if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]) )
1655 	      {
1656 	         SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->afterdualvars[varnr], &scalar, &constant)) ;
1657 	         reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]
1658 	            = (reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr] - constant) / scalar;
1659 	      }
1660 	      assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]));
1661 	   }
1662 	
1663 	   return SCIP_OKAY;
1664 	}
1665 	
1666 	/** search the next node along the root path that was saved by reoptimization */
1667 	static
1668 	SCIP_RETCODE getLastSavedNode(
1669 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1670 	   SCIP_SET*             set,                /**< global SCIP settings */
1671 	   SCIP_NODE*            node,               /**< node of the search tree */
1672 	   SCIP_NODE**           parent,             /**< parent node within the search tree */
1673 	   unsigned int*         parentid,           /**< id of the parent node */
1674 	   int*                  nbndchgs            /**< number of bound changes */
1675 	   )
1676 	{
1677 	   assert(reopt != NULL);
1678 	   assert(reopt->reopttree != NULL);
1679 	   assert(reopt->reopttree->reoptnodes != NULL);
1680 	
1681 	   (*nbndchgs) = 0;
1682 	   (*parent) = node;
1683 	
1684 	   /* look for a saved parent along the root-path */
1685 	   while( SCIPnodeGetDepth(*parent) != 0 )
1686 	   {
1687 	      int nbranchings = 0;
1688 	      int nconsprop = 0;
1689 	
1690 	      if( set->reopt_saveconsprop )
1691 	         SCIPnodeGetNDomchg((*parent), &nbranchings, &nconsprop, NULL);
1692 	      else
1693 	         SCIPnodeGetNDomchg((*parent), &nbranchings, NULL, NULL);
1694 	
1695 	      (*nbndchgs) = (*nbndchgs) + nbranchings + nconsprop;
1696 	      (*parent) = SCIPnodeGetParent(*parent);
1697 	      (*parentid) = SCIPnodeGetReoptID(*parent);
1698 	
1699 	      if( SCIPnodeGetDepth(*parent) == 0)
1700 	      {
1701 	         (*parentid) = 0;
1702 	         break;
1703 	      }
1704 	      else if( SCIPnodeGetReopttype((*parent)) >= SCIP_REOPTTYPE_TRANSIT )
1705 	      {
1706 	         /* this is a special case: due to re-propagation the node could be already deleted. We need to reset reoptid
1707 	          * and reopttype and continue upto we have found the last stored node
1708 	          */
1709 	         if( reopt->reopttree->reoptnodes[*parentid] == NULL )
1710 	         {
1711 	            SCIPnodeSetReoptID(*parent, 0);
1712 	            SCIPnodeSetReopttype(*parent, SCIP_REOPTTYPE_NONE);
1713 	         }
1714 	         else
1715 	         {
1716 	            assert(reopt->reopttree->reoptnodes[*parentid] != NULL);
1717 	            assert(SCIPnodeGetReoptID((*parent)) < reopt->reopttree->reoptnodessize);
1718 	            assert((*parentid) && (*parentid) < reopt->reopttree->reoptnodessize);
1719 	            break;
1720 	         }
1721 	      }
1722 	   }
1723 	
1724 	   return SCIP_OKAY;
1725 	}
1726 	
1727 	/** adds the id @p childid to the array of child nodes of @p parentid */
1728 	static
1729 	SCIP_RETCODE reoptAddChild(
1730 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
1731 	   SCIP_SET*             set,                /**< global SCIP settings */
1732 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1733 	   unsigned int          parentid,           /**< id of the parent node */
1734 	   unsigned int          childid             /**< id of the child node */
1735 	   )
1736 	{
1737 	   int nchilds;
1738 	
1739 	   assert(reopttree != NULL);
1740 	   assert(blkmem != NULL);
1741 	   assert(parentid < (unsigned int)reopttree->reoptnodessize);
1742 	   assert(childid < (unsigned int)reopttree->reoptnodessize);
1743 	   assert(reopttree->reoptnodes[parentid] != NULL);
1744 	
1745 	   nchilds = reopttree->reoptnodes[parentid]->nchilds;
1746 	
1747 	   /* ensure that the array is large enough */
1748 	   SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[parentid], set, blkmem, 0, nchilds+1, 0) );
1749 	   assert(reopttree->reoptnodes[parentid]->allocchildmem > nchilds);
1750 	
1751 	   /* add the child */
1752 	   reopttree->reoptnodes[parentid]->childids[nchilds] = childid;
1753 	   ++reopttree->reoptnodes[parentid]->nchilds;
1754 	
1755 	   SCIPsetDebugMsg(set, "add ID %u as a child of ID %u.\n", childid, parentid);
1756 	
1757 	   return SCIP_OKAY;
1758 	}
1759 	
1760 	/** move all children to the next node (along the root path) stored in the reoptimization tree */
1761 	static
1762 	SCIP_RETCODE moveChildrenUp(
1763 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1764 	   SCIP_SET*             set,                /**< global SCIP settings */
1765 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1766 	   unsigned int          nodeid,             /**< id of the node */
1767 	   unsigned int          parentid            /**< id of the parent node */
1768 	   )
1769 	{
1770 	   unsigned int childid;
1771 	   int nvars;
1772 	
1773 	   assert(reopt != NULL);
1774 	   assert(blkmem != NULL);
1775 	   assert(0 < nodeid && nodeid < reopt->reopttree->reoptnodessize);
1776 	   assert(parentid < reopt->reopttree->reoptnodessize);
1777 	   assert(reopt->reopttree->reoptnodes[nodeid]->childids != NULL);
1778 	
1779 	   /* ensure that enough memory at the parentID is available */
1780 	   SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0,
1781 	         reopt->reopttree->reoptnodes[parentid]->nchilds + reopt->reopttree->reoptnodes[nodeid]->nchilds, 0) );
1782 	
1783 	   while( reopt->reopttree->reoptnodes[nodeid]->nchilds > 0 )
1784 	   {
1785 	      int nchilds;
1786 	
1787 	      nchilds = reopt->reopttree->reoptnodes[nodeid]->nchilds;
1788 	      childid = reopt->reopttree->reoptnodes[nodeid]->childids[nchilds-1];
1789 	      assert(0 < childid && childid < reopt->reopttree->reoptnodessize);
1790 	
1791 	      /* check the memory */
1792 	      SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[childid], set, blkmem,
1793 	            reopt->reopttree->reoptnodes[childid]->nvars + reopt->reopttree->reoptnodes[nodeid]->nvars, 0, 0) );
1794 	      assert(reopt->reopttree->reoptnodes[childid]->varssize >= reopt->reopttree->reoptnodes[childid]->nvars
1795 	         + reopt->reopttree->reoptnodes[nodeid]->nvars);
1796 	
1797 	      /* save branching information */
1798 	      for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[nodeid]->nvars; ++varnr )
1799 	      {
1800 	         nvars = reopt->reopttree->reoptnodes[childid]->nvars;
1801 	         reopt->reopttree->reoptnodes[childid]->vars[nvars] = reopt->reopttree->reoptnodes[nodeid]->vars[varnr];
1802 	         reopt->reopttree->reoptnodes[childid]->varbounds[nvars] = reopt->reopttree->reoptnodes[nodeid]->varbounds[varnr];
1803 	         reopt->reopttree->reoptnodes[childid]->varboundtypes[nvars] = reopt->reopttree->reoptnodes[nodeid]->varboundtypes[varnr];
1804 	         ++reopt->reopttree->reoptnodes[childid]->nvars;
1805 	      }
1806 	
1807 	      /* update the ID of the parent node */
1808 	      reopt->reopttree->reoptnodes[childid]->parentID = parentid;
1809 	
1810 	      /* insert the node as a child */
1811 	      SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, childid) );
1812 	
1813 	      /* reduce the number of child nodes by 1 */
1814 	      --reopt->reopttree->reoptnodes[nodeid]->nchilds;
1815 	   }
1816 	
1817 	   return SCIP_OKAY;
1818 	}
1819 	
1820 	/** delete all nodes in the subtree induced by nodeID */
1821 	static
1822 	SCIP_RETCODE deleteChildrenBelow(
1823 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
1824 	   SCIP_SET*             set,                /**< global SCIP settings */
1825 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1826 	   unsigned int          id,                 /**< id of the node */
1827 	   SCIP_Bool             delnodeitself,      /**< should the node be deleted after deleting the induced subtree? */
1828 	   SCIP_Bool             exitsolve           /**< will the solving process end after deletion */
1829 	   )
1830 	{
1831 	   assert(reopttree != NULL );
1832 	   assert(blkmem != NULL);
1833 	   assert(id < reopttree->reoptnodessize);
1834 	   assert(reopttree->reoptnodes[id] != NULL);
1835 	
1836 	   /* delete all children below */
1837 	   if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
1838 	   {
1839 	      SCIPsetDebugMsg(set, "-> delete subtree induced by ID %u (hard remove = %u)\n", id, exitsolve);
1840 	
1841 	      while( reopttree->reoptnodes[id]->nchilds > 0 )
1842 	      {
1843 	         int nchilds;
1844 	         unsigned int childid;
1845 	
1846 	         nchilds = reopttree->reoptnodes[id]->nchilds;
1847 	         childid = reopttree->reoptnodes[id]->childids[nchilds-1];
1848 	         assert(0 < childid && childid < reopttree->reoptnodessize);
1849 	
1850 	         SCIP_CALL( deleteChildrenBelow(reopttree, set, blkmem, childid, TRUE, exitsolve) );
1851 	
1852 	         --reopttree->reoptnodes[id]->nchilds;
1853 	      }
1854 	   }
1855 	
1856 	   /* delete node data*/
1857 	   if( delnodeitself )
1858 	   {
1859 	      SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, exitsolve) );
1860 	      SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
1861 	   }
1862 	
1863 	   return SCIP_OKAY;
1864 	}
1865 	
1866 	/** replaces a reoptimization nodes by its stored child nodes */
1867 	static
1868 	SCIP_RETCODE shrinkNode(
1869 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
1870 	   SCIP_SET*             set,                /**< global SCIP settings */
1871 	   SCIP_NODE*            node,               /**< node of the search tree */
1872 	   unsigned int          id,                 /**< id of the node */
1873 	   SCIP_Bool*            shrank,             /**< pointer to store if the node was shrank */
1874 	   BMS_BLKMEM*           blkmem              /**< block memory */
1875 	   )
1876 	{
1877 	   SCIP_REOPTNODE** reoptnodes;
1878 	
1879 	   assert(reopt != NULL);
1880 	   assert(node != NULL);
1881 	   assert(id < reopt->reopttree->reoptnodessize);
1882 	
1883 	   reoptnodes = reopt->reopttree->reoptnodes;
1884 	   assert(reoptnodes != NULL);
1885 	   assert(reoptnodes[id] != NULL);
1886 	
1887 	   if( reoptnodes[id]->childids != NULL && reoptnodes[id]->nchilds > 0 )
1888 	   {
1889 	      int ndomchgs = 0;
1890 	      unsigned int parentid = 0;
1891 	      SCIP_NODE* parent = NULL;
1892 	
1893 	      SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &ndomchgs) );
1894 	
1895 	      assert(parentid != id);
1896 	      assert(reoptnodes[parentid] != NULL );
1897 	      assert(reoptnodes[parentid]->childids != NULL && reoptnodes[parentid]->nchilds);
1898 	
1899 	      /* check if we want move all children to the next saved node above
1900 	       * we want to shrink the path if either
1901 	       * - the maximal number of bound changes fix and the number of bound changes is
1902 	       *   less than the given threshold set->reopt_maxdiffofnodes
1903 	       * or
1904 	       * - the number is calculated dynamically and the number of bound changes
1905 	       *   is less than log2(SCIPgetNBinVars - (#vars of parent))
1906 	       * */
1907 	      if( ndomchgs <= set->reopt_maxdiffofnodes )
1908 	      {
1909 	         int c;
1910 	
1911 	         SCIPsetDebugMsg(set, " -> shrink node %lld at ID %u, replaced by %d child nodes.\n", SCIPnodeGetNumber(node),
1912 	            id, reoptnodes[id]->nchilds);
1913 	
1914 	         /* copy the references of child nodes to the parent*/
1915 	         SCIP_CALL( moveChildrenUp(reopt, set, blkmem, id, parentid) );
1916 	
1917 	         /* delete the current node */
1918 	         c = 0;
1919 	         while( reoptnodes[parentid]->childids[c] != id )
1920 	         {
1921 	            ++c;
1922 	            assert(c < reoptnodes[parentid]->nchilds);
1923 	         }
1924 	
1925 	         assert(reoptnodes[parentid]->childids[c] == id);
1926 	
1927 	         /* replace the childid at position c by the last one */
1928 	         reoptnodes[parentid]->childids[c] = reoptnodes[parentid]->childids[reoptnodes[parentid]->nchilds-1];
1929 	         --reoptnodes[parentid]->nchilds;
1930 	
1931 	         SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
1932 	         SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, id) );
1933 	
1934 	         *shrank = TRUE;
1935 	
1936 	         /* set the reopttype to none */
1937 	         SCIPnodeSetReopttype(node, SCIP_REOPTTYPE_NONE);
1938 	      }
1939 	   }
1940 	
1941 	   return SCIP_OKAY;
1942 	}
1943 	
1944 	/** change all reopttypes in the subtree induced by @p nodeID */
1945 	static
1946 	SCIP_RETCODE changeReopttypeOfSubtree(
1947 	   SCIP_REOPTTREE*       reopttree,          /**< reopttree */
1948 	   unsigned int          id,                 /**< id of the node */
1949 	   SCIP_REOPTTYPE        reopttype           /**< reopttype */
1950 	   )
1951 	{
1952 	   assert(reopttree != NULL);
1953 	   assert(id < reopttree->reoptnodessize);
1954 	   assert(reopttree->reoptnodes[id] != NULL);
1955 	
1956 	   if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
1957 	   {
1958 	      unsigned int childid;
1959 	      int nchildids;
1960 	      int seenids = 0;
1961 	
1962 	      nchildids = reopttree->reoptnodes[id]->nchilds;
1963 	
1964 	      while( seenids < nchildids )
1965 	      {
1966 	         /* get childID */
1967 	         childid = reopttree->reoptnodes[id]->childids[seenids];
1968 	         assert(childid < reopttree->reoptnodessize);
1969 	         assert(reopttree->reoptnodes[childid] != NULL);
1970 	
1971 	         /* change the reopttype of the node iff the node is neither infeasible nor induces an
1972 	          * infeasible subtree and if the node contains no bound changes based on dual decisions
1973 	          */
1974 	         if( reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_STRBRANCHED
1975 	            && reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_INFSUBTREE ) /*lint !e641*/
1976 	            reopttree->reoptnodes[childid]->reopttype = reopttype; /*lint !e641*/
1977 	
1978 	         /* change reopttype of subtree */
1979 	         SCIP_CALL( changeReopttypeOfSubtree(reopttree, childid, reopttype) );
1980 	
1981 	         ++seenids;
1982 	      }
1983 	   }
1984 	
1985 	   return SCIP_OKAY;
1986 	}
1987 	
1988 	/** delete the constraint handling dual information for the current iteration and replace it with the dual constraint
1989 	 *  for the next iteration
1990 	 */
1991 	static
1992 	SCIP_RETCODE reoptnodeUpdateDualConss(
1993 	   SCIP_REOPTNODE*       reoptnode,          /**< reoptimization node */
1994 	   BMS_BLKMEM*           blkmem              /**< block memory */
1995 	   )
1996 	{
1997 	   assert(reoptnode != NULL);
1998 	   assert(blkmem != NULL);
1999 	
2000 	   if( reoptnode->dualredscur != NULL )
2001 	   {
2002 	      SCIPdebugMessage("reset dual information (current run)\n");
2003 	
2004 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->boundtypes, reoptnode->dualredscur->varssize);
2005 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vals, reoptnode->dualredscur->varssize);
2006 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vars, reoptnode->dualredscur->varssize);
2007 	      BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
2008 	      reoptnode->dualredscur = NULL;
2009 	   }
2010 	
2011 	   if( reoptnode->dualredsnex != NULL )
2012 	   {
2013 	      SCIPdebugMessage("set dual information of next run to current run\n");
2014 	      reoptnode->dualredscur = reoptnode->dualredsnex;
2015 	      reoptnode->dualredsnex = NULL;
2016 	   }
2017 	
2018 	   reoptnode->dualreds = (reoptnode->dualredscur != NULL ? TRUE : FALSE);
2019 	
2020 	   return SCIP_OKAY;
2021 	}
2022 	
2023 	/** calculates a (local) similarity of a given node and returns if the subproblem should be solved from scratch */
2024 	static
2025 	SCIP_RETCODE reoptCheckLocalRestart(
2026 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
2027 	   SCIP_SET*             set,                /**< global SCIP settings */
2028 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2029 	   SCIP_NODE*            node,               /**< node of the search tree */
2030 	   SCIP_VAR**            transvars,          /**< transformed variables */
2031 	   int                   ntransvars,         /**< number of transformed variables */
2032 	   SCIP_Bool*            localrestart        /**< pointer to store if we want to restart solving the (sub)problem */
2033 	   )
2034 	{
2035 	   unsigned int id;
2036 	
2037 	   assert(reopt != NULL);
2038 	   assert(reopt->reopttree != NULL);
2039 	   assert(set != NULL);
2040 	   assert(blkmem != NULL);
2041 	   assert(node != NULL);
2042 	   assert(transvars != NULL);
2043 	
2044 	   /* node == NULL is equivalent to node == root, this case should be handled by SCIPreoptCheckReopt */
2045 	   assert(node != NULL);
2046 	
2047 	   *localrestart = FALSE;
2048 	
2049 	   id = SCIPnodeGetReoptID(node);
2050 	   assert(id < reopt->reopttree->reoptnodessize);
2051 	
2052 	   /* set the id to -1 if the node is not part of the reoptimization tree */
2053 	   if( SCIPnodeGetDepth(node) > 0 && id == 0 )
2054 	      return SCIP_OKAY;
2055 	
2056 	   if( set->reopt_objsimdelay > -1 )
2057 	   {
2058 	      SCIP_Real sim = 0.0;
2059 	      SCIP_Real lb;
2060 	      SCIP_Real ub;
2061 	      SCIP_Real oldcoef;
2062 	      SCIP_Real newcoef;
2063 	      int idx;
2064 	
2065 	      if( id == 0 )
2066 	         reopt->nlocrestarts = 0;
2067 	
2068 	      /* since the stored objective functions are already normalize the dot-product is equivalent to the similarity */
2069 	      for( int v = 0; v < ntransvars; ++v )
2070 	      {
2071 	         lb = SCIPvarGetLbLocal(transvars[v]);
2072 	         ub = SCIPvarGetUbLocal(transvars[v]);
2073 	
2074 	         /* skip already fixed variables */
2075 	         if( SCIPsetIsFeasLT(set, lb, ub) )
2076 	         {
2077 	            idx = SCIPvarGetProbindex(transvars[v]);
2078 	            assert(0 <= idx && idx < ntransvars);
2079 	
2080 	            oldcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run-1, idx);
2081 	            newcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run, idx);
2082 	
2083 	            sim += (oldcoef * newcoef);
2084 	         }
2085 	      }
2086 	
2087 	      /* delete the stored subtree and information about bound changes
2088 	       * based on dual information */
2089 	      if( SCIPsetIsLT(set, sim, set->reopt_objsimdelay) )
2090 	      {
2091 	         /* set the flag */
2092 	         *localrestart = TRUE;
2093 	
2094 	         ++reopt->nlocrestarts;
2095 	         ++reopt->ntotallocrestarts;
2096 	
2097 	         /* delete the stored subtree */
2098 	         SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2099 	
2100 	         /* delete the stored constraints; we do this twice in a row because we want to delete both constraints */
2101 	         SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
2102 	         SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
2103 	      }
2104 	
2105 	      SCIPsetDebugMsg(set, " -> local similarity: %.4f%s\n", sim, *localrestart ? " (solve subproblem from scratch)" : "");
2106 	   }
2107 	
2108 	   return SCIP_OKAY;
2109 	}
2110 	
2111 	/** save ancestor branching information up to the next stored node */
2112 	static
2113 	SCIP_RETCODE saveAncestorBranchings(
2114 	   SCIP_REOPTTREE*       reopttree,          /**< reoptimization tree */
2115 	   SCIP_SET*             set,                /**< global SCIP settings */
2116 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2117 	   SCIP_NODE*            node,               /**< node of the branch and bound tree */
2118 	   SCIP_NODE*            parent,             /**< parent node */
2119 	   unsigned int          id,                 /**< id of the node */
2120 	   unsigned int          parentid            /**< id of the parent node */
2121 	   )
2122 	{
2123 	   int nbranchvars;
2124 	
2125 	   assert(reopttree != NULL );
2126 	   assert(node != NULL );
2127 	   assert(parent != NULL );
2128 	   assert(1 <= id && id < reopttree->reoptnodessize);
2129 	   assert(reopttree->reoptnodes[id] != NULL );
2130 	   assert(parentid < reopttree->reoptnodessize);
2131 	   assert(parentid == 0 || reopttree->reoptnodes[parentid] != NULL ); /* if the root is the next saved node, the nodedata can be NULL */
2132 	
2133 	   SCIPsetDebugMsg(set, " -> save ancestor branchings\n");
2134 	
2135 	   /* allocate memory */
2136 	   if (reopttree->reoptnodes[id]->varssize == 0)
2137 	   {
2138 	      assert(reopttree->reoptnodes[id]->vars == NULL );
2139 	      assert(reopttree->reoptnodes[id]->varbounds == NULL );
2140 	      assert(reopttree->reoptnodes[id]->varboundtypes == NULL );
2141 	
2142 	      /* allocate memory for node information */
2143 	      SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, DEFAULT_MEM_VAR, 0, 0) );
2144 	   }
2145 	
2146 	   assert(reopttree->reoptnodes[id]->varssize > 0);
2147 	   assert(reopttree->reoptnodes[id]->nvars == 0);
2148 	
2149 	   SCIPnodeGetAncestorBranchingsPart(node, parent,
2150 	         reopttree->reoptnodes[id]->vars,
2151 	         reopttree->reoptnodes[id]->varbounds,
2152 	         reopttree->reoptnodes[id]->varboundtypes,
2153 	         &nbranchvars,
2154 	         reopttree->reoptnodes[id]->varssize);
2155 	
2156 	   if( nbranchvars >  reopttree->reoptnodes[id]->varssize )
2157 	   {
2158 	      /* reallocate memory */
2159 	      SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, nbranchvars, 0, 0) );
2160 	
2161 	      SCIPnodeGetAncestorBranchingsPart(node, parent,
2162 	            reopttree->reoptnodes[id]->vars,
2163 	            reopttree->reoptnodes[id]->varbounds,
2164 	            reopttree->reoptnodes[id]->varboundtypes,
2165 	            &nbranchvars,
2166 	            reopttree->reoptnodes[id]->varssize);
2167 	   }
2168 	
2169 	   assert(nbranchvars <= reopttree->reoptnodes[id]->varssize); /* this should be the case */
2170 	
2171 	   reopttree->reoptnodes[id]->nvars = nbranchvars;
2172 	
2173 	   assert(nbranchvars <= reopttree->reoptnodes[id]->varssize);
2174 	   assert(reopttree->reoptnodes[id]->vars != NULL );
2175 	
2176 	   return SCIP_OKAY;
2177 	}
2178 	
2179 	
2180 	/** transform a constraint with linear representation into reoptimization constraint data */
2181 	static
2182 	SCIP_RETCODE saveConsLinear(
2183 	   SCIP_REOPTCONSDATA*   reoptconsdata,      /**< reoptimization constraint data */
2184 	   SCIP_SET*             set,                /**< global SCIP settings */
2185 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2186 	   SCIP_CONS*            cons,               /**< linear constraint that should be stored */
2187 	   SCIP_Bool*            success             /**< pointer to store the success */
2188 	   )
2189 	{
2190 	   SCIP_VAR** vars;
2191 	   SCIP_Real* vals;
2192 	   SCIP_CONSHDLR* conshdlr;
2193 	   SCIP_Bool allocbuffervals;
2194 	
2195 	   assert(reoptconsdata != NULL);
2196 	   assert(cons != NULL);
2197 	
2198 	   *success = FALSE;
2199 	   allocbuffervals = FALSE;
2200 	   reoptconsdata->linear = TRUE;
2201 	
2202 	   vars = NULL;
2203 	   vals = NULL;
2204 	   SCIP_CALL( SCIPconsGetNVars(cons, set, &reoptconsdata->nvars, success) );
2205 	   assert(*success);
2206 	
2207 	   /* allocate memory for variables and values; boundtypes are not needed */
2208 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->nvars) );
2209 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->nvars) );
2210 	   reoptconsdata->varssize = reoptconsdata->nvars;
2211 	
2212 	   /* only needed for bounddisjuction constraints, thus we set them to NULL to avoid compiler warnings */
2213 	   reoptconsdata->boundtypes = NULL;
2214 	
2215 	   conshdlr = SCIPconsGetHdlr(cons);
2216 	   assert(conshdlr != NULL);
2217 	
2218 	   /* get all variables, values, and sides */
2219 	   if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2220 	   {
2221 	      vars = SCIPgetVarsLinear(set->scip, cons);
2222 	      vals = SCIPgetValsLinear(set->scip, cons);
2223 	      reoptconsdata->lhs = SCIPgetLhsLinear(set->scip, cons);
2224 	      reoptconsdata->rhs = SCIPgetRhsLinear(set->scip, cons);
2225 	   }
2226 	   else if( strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0 )
2227 	   {
2228 	      vars = SCIPgetVarsLogicor(set->scip, cons);
2229 	
2230 	      /* initialize values to 1.0 */
2231 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, reoptconsdata->nvars) );
2232 	      allocbuffervals = TRUE;
2233 	
2234 	      for( int v = 0; v < reoptconsdata->nvars; ++v )
2235 	         vals[v] = 1.0;
2236 	
2237 	      reoptconsdata->lhs = 1.0;
2238 	      reoptconsdata->rhs = SCIPsetInfinity(set);
2239 	   }
2240 	   else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2241 	   {
2242 	      vars = SCIPgetVarsSetppc(set->scip, cons);
2243 	
2244 	      /* initialize values to 1.0 */
2245 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, reoptconsdata->nvars) );
2246 	      allocbuffervals = TRUE;
2247 	
2248 	      for( int v = 0; v < reoptconsdata->nvars; ++v )
2249 	         vals[v] = 1.0;
2250 	
2251 	      switch( SCIPgetTypeSetppc(set->scip, cons) ) {
2252 	      case SCIP_SETPPCTYPE_PARTITIONING:
2253 	         reoptconsdata->lhs = 1.0;
2254 	         reoptconsdata->rhs = 1.0;
2255 	         break;
2256 	      case SCIP_SETPPCTYPE_PACKING:
2257 	         reoptconsdata->lhs = -SCIPsetInfinity(set);
2258 	         reoptconsdata->rhs = 1.0;
2259 	         break;
2260 	      case SCIP_SETPPCTYPE_COVERING:
2261 	         reoptconsdata->lhs = 1.0;
2262 	         reoptconsdata->rhs = SCIPsetInfinity(set);
2263 	         break;
2264 	      default:
2265 	         *success = FALSE;
2266 	         return SCIP_OKAY;
2267 	      }
2268 	   }
2269 	   else
2270 	   {
2271 	      assert(strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 || strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0
2272 	         || strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0);
2273 	
2274 	      SCIPerrorMessage("Cannot handle constraints of type <%s> in saveConsLinear.\n", SCIPconshdlrGetName(conshdlr));
2275 	      return SCIP_INVALIDDATA;
2276 	   }
2277 	   assert(vars != NULL);
2278 	   assert(vals != NULL);
2279 	
2280 	   /* transform all variables into the original space */
2281 	   for( int v = 0; v < reoptconsdata->nvars; ++v )
2282 	   {
2283 	      SCIP_Real constant = 0.0;
2284 	      SCIP_Real scalar = 1.0;
2285 	
2286 	      assert(vars[v] != NULL);
2287 	
2288 	      reoptconsdata->vars[v] = vars[v];
2289 	      reoptconsdata->vals[v] = vals[v];
2290 	
2291 	      SCIP_CALL( SCIPvarGetOrigvarSum(&reoptconsdata->vars[v], &scalar, &constant) );
2292 	      assert(!SCIPsetIsZero(set, scalar));
2293 	
2294 	      assert(!SCIPsetIsInfinity(set, REALABS(reoptconsdata->vals[v])));
2295 	      reoptconsdata->vals[v] *= scalar;
2296 	
2297 	      if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, -reoptconsdata->lhs) )
2298 	         reoptconsdata->lhs -= constant;
2299 	      if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, reoptconsdata->rhs) )
2300 	         reoptconsdata->rhs -= constant;
2301 	   }
2302 	
2303 	   /* free buffer if needed */
2304 	   if( allocbuffervals )
2305 	   {
2306 	      SCIPsetFreeBufferArray(set, &vals);
2307 	   }
2308 	
2309 	   return SCIP_OKAY;
2310 	}
2311 	
2312 	/** transform a bounddisjunction constraint into reoptimization constraint data */
2313 	static
2314 	SCIP_RETCODE saveConsBounddisjuction(
2315 	   SCIP_REOPTCONSDATA*   reoptconsdata,      /**< reoptimization constraint data */
2316 	   SCIP_SET*             set,                /**< global SCIP settings */
2317 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2318 	   SCIP_CONS*            cons,               /**< bounddisjuction constraint that should be stored */
2319 	   SCIP_Bool*            success             /**< pointer to store the success */
2320 	   )
2321 	{
2322 	   SCIP_VAR** vars;
2323 	   SCIP_CONSHDLR* conshdlr;
2324 	   SCIP_BOUNDTYPE* boundtypes;
2325 	   SCIP_Real* bounds;
2326 	
2327 	   assert(reoptconsdata != NULL);
2328 	   assert(cons != NULL);
2329 	
2330 	   *success = FALSE;
2331 	   reoptconsdata->linear = FALSE;
2332 	
2333 	   conshdlr = SCIPconsGetHdlr(cons);
2334 	   assert(conshdlr != NULL);
2335 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") == 0);
2336 	
2337 	   if( strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") != 0 )
2338 	   {
2339 	      SCIPerrorMessage("Cannot handle constraints of type <%s> in saveConsBounddisjuction.\n",
2340 	         SCIPconshdlrGetName(conshdlr));
2341 	      return SCIP_INVALIDDATA;
2342 	   }
2343 	
2344 	   SCIP_CALL( SCIPconsGetNVars(cons, set, &reoptconsdata->nvars, success) );
2345 	   assert(*success);
2346 	
2347 	   /* allocate memory for variables and values; boundtypes are not needed */
2348 	   vars = SCIPgetVarsBounddisjunction(NULL, cons);
2349 	   bounds = SCIPgetBoundsBounddisjunction(NULL, cons);
2350 	   boundtypes = SCIPgetBoundtypesBounddisjunction(NULL, cons);
2351 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vars, vars, reoptconsdata->nvars) );
2352 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vals, bounds, reoptconsdata->nvars) );
2353 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, boundtypes, reoptconsdata->nvars) );
2354 	   reoptconsdata->varssize = reoptconsdata->nvars;
2355 	   reoptconsdata->lhs = SCIP_UNKNOWN;
2356 	   reoptconsdata->rhs = SCIP_UNKNOWN;
2357 	
2358 	   /* transform all variables into the original space */
2359 	   for( int v = 0; v < reoptconsdata->nvars; ++v )
2360 	   {
2361 	      SCIP_Real constant = 0.0;
2362 	      SCIP_Real scalar = 1.0;
2363 	
2364 	      assert(reoptconsdata->vars[v] != NULL);
2365 	
2366 	      SCIP_CALL( SCIPvarGetOrigvarSum(&reoptconsdata->vars[v], &scalar, &constant) );
2367 	      assert(!SCIPsetIsZero(set, scalar));
2368 	
2369 	      assert(!SCIPsetIsInfinity(set, REALABS(reoptconsdata->vals[v])));
2370 	      reoptconsdata->vals[v] -= constant;
2371 	      reoptconsdata->vals[v] *= scalar;
2372 	
2373 	      /* due to multipling with a negative scalar the relation need to be changed */
2374 	      if( SCIPsetIsNegative(set, scalar) )
2375 	         reoptconsdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - reoptconsdata->boundtypes[v]); /*lint !e656*/
2376 	   }
2377 	
2378 	   return SCIP_OKAY;
2379 	}
2380 	
2381 	/** save additional all constraints that were additionally added to @p node */
2382 	static
2383 	SCIP_RETCODE saveLocalConssData(
2384 	   SCIP_REOPTTREE*       reopttree,          /**< reopttree */
2385 	   SCIP_SET*             set,                /**< global SCIP settings */
2386 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2387 	   SCIP_NODE*            node,               /**< node of the branch and bound tree */
2388 	   unsigned int          id                  /**< id of the node*/
2389 	   )
2390 	{
2391 	   SCIP_CONS** addedcons;
2392 	   int naddedconss;
2393 	   int addedconsssize;
2394 	   int nconss;
2395 	
2396 	   assert(node != NULL );
2397 	   assert(reopttree != NULL);
2398 	   assert(id < reopttree->reoptnodessize);
2399 	
2400 	   /* save the added pseudo-constraint */
2401 	   if( SCIPnodeGetNAddedConss(node) > 0 )
2402 	   {
2403 	      addedconsssize = SCIPnodeGetNAddedConss(node);
2404 	
2405 	      SCIPsetDebugMsg(set, " -> save %d locally added constraints\n", addedconsssize);
2406 	
2407 	      /* get memory */
2408 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &addedcons, addedconsssize) );
2409 	      SCIPnodeGetAddedConss(node, addedcons, &naddedconss, addedconsssize);
2410 	
2411 	      nconss = reopttree->reoptnodes[id]->nconss;
2412 	
2413 	      /* check memory for added constraints */
2414 	      SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, 0, 0, naddedconss) );
2415 	
2416 	      /* since the first nconss are already stored in the data structure, we skip them */
2417 	      for( int c = nconss; c < naddedconss; ++c )
2418 	      {
2419 	         SCIP_CONSHDLR* conshdlr;
2420 	         SCIP_Bool islinear;
2421 	         SCIP_Bool success;
2422 	
2423 	         conshdlr = SCIPconsGetHdlr(addedcons[c]);
2424 	
2425 	         /* check whether the constraint has a linear representation */
2426 	         islinear = (strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0
2427 	               || strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0
2428 	               || strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0);
2429 	
2430 	         SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]->conss[c]) ); /*lint !e866*/
2431 	
2432 	         success = FALSE;
2433 	
2434 	         /* the constraint has a linear representation */
2435 	         if( islinear )
2436 	         {
2437 	            SCIP_CALL( saveConsLinear(reopttree->reoptnodes[id]->conss[c], set, blkmem, addedcons[c], &success) );
2438 	            assert(success);
2439 	
2440 	            /* increase the counter for added constraints */
2441 	            ++reopttree->reoptnodes[id]->nconss;
2442 	         }
2443 	         else
2444 	         {
2445 	            assert(strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") == 0);
2446 	            SCIP_CALL( saveConsBounddisjuction(reopttree->reoptnodes[id]->conss[c], set, blkmem, addedcons[c], &success) );
2447 	            assert(success);
2448 	
2449 	            /* increase the counter for added constraints */
2450 	            ++reopttree->reoptnodes[id]->nconss;
2451 	         }
2452 	         assert(reopttree->reoptnodes[id]->conss[c]->nvars > 0);
2453 	
2454 	         if( strcmp("reopt_inf", SCIPconsGetName(addedcons[c])) == 0 )
2455 	            reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_INFSUBTREE;
2456 	         else if( strcmp("reopt_dual", SCIPconsGetName(addedcons[c])) == 0 )
2457 	            reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_DUALREDS;
2458 	         else
2459 	            reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_UNKNOWN;
2460 	      }
2461 	
2462 	      assert(reopttree->reoptnodes[id]->nconss == naddedconss);
2463 	      SCIPsetFreeBufferArray(set, &addedcons);
2464 	   }
2465 	
2466 	   return SCIP_OKAY;
2467 	}
2468 	
2469 	/** collect all bound changes based on dual information
2470 	 *
2471 	 *  If the bound changes are global, all information are already stored because they were caught by the event handler.
2472 	 *  otherwise, we have to use SCIPnodeGetDualBoundchgs.
2473 	 *
2474 	 *  Afterwards, we check if the constraint will be added in the next iteration or after splitting the node.
2475 	 */
2476 	static
2477 	SCIP_RETCODE collectDualInformation(
2478 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
2479 	   SCIP_SET*             set,                /**< global SCIP settings */
2480 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2481 	   SCIP_NODE*            node,               /**< node of the search tree */
2482 	   unsigned int          id,                 /**< id of the node */
2483 	   SCIP_REOPTTYPE        reopttype           /**< reopttype */
2484 	   )
2485 	{
2486 	   SCIP_Bool cons_is_next = TRUE;
2487 	   int nbndchgs;
2488 	
2489 	   assert(reopt != NULL);
2490 	   assert(reopt->reopttree != NULL);
2491 	   assert(id < reopt->reopttree->reoptnodessize);
2492 	   assert(reopt->reopttree->reoptnodes[id]->dualreds);
2493 	   assert(node != NULL);
2494 	   assert(blkmem != NULL);
2495 	
2496 	   /* first case, all bound changes were global */
2497 	   if( reopt->currentnode == SCIPnodeGetNumber(node) && reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
2498 	   {
2499 	      nbndchgs = reopt->dualreds->nvars;
2500 	   }
2501 	   else
2502 	   {
2503 	      assert(reopt->currentnode == SCIPnodeGetNumber(node));
2504 	
2505 	      /* get the number of bound changes based on dual information */
2506 	      nbndchgs = SCIPnodeGetNDualBndchgs(node);
2507 	
2508 	      /* ensure that enough memory is allocated */
2509 	      SCIP_CALL( checkMemDualCons(reopt, set, blkmem, nbndchgs) );
2510 	
2511 	      /* collect the bound changes */
2512 	      SCIPnodeGetDualBoundchgs(node, reopt->dualreds->vars, reopt->dualreds->vals, reopt->dualreds->boundtypes,
2513 	            &nbndchgs, reopt->dualreds->varssize);
2514 	      assert(nbndchgs <= reopt->dualreds->varssize);
2515 	
2516 	      reopt->dualreds->nvars = nbndchgs;
2517 	      reopt->dualreds->linear = FALSE;
2518 	
2519 	      /* transform the variables into the original space */
2520 	      for( int v = 0; v < nbndchgs; ++v )
2521 	      {
2522 	         SCIP_Real constant = 0.0;
2523 	         SCIP_Real scalar = 1.0;
2524 	
2525 	         SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->dualreds->vars[v], &scalar, &constant) );
2526 	         reopt->dualreds->vals[v] = (reopt->dualreds->vals[v] - constant) / scalar;
2527 	
2528 	         assert(SCIPvarIsOriginal(reopt->dualreds->vars[v]));
2529 	      }
2530 	   }
2531 	
2532 	   assert(nbndchgs > 0);
2533 	
2534 	   /* due to the strong branching initialization it can be possible that two
2535 	    * constraints handling dual information are stored at the same time.
2536 	    * During reoptimizing a node we add the constraint stored at dualredscur only,
2537 	    * i.e, if dualredscur is not NULL, we need to store the constraint for the next
2538 	    * iteration at dualredsnex because the constraint stored at dualredscur is needed
2539 	    * to split the constraint in the current iteration.
2540 	    */
2541 	   if( reopt->reopttree->reoptnodes[id]->dualredscur != NULL )
2542 	   {
2543 	      assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
2544 	      cons_is_next = FALSE;
2545 	   }
2546 	   assert((cons_is_next && reopt->reopttree->reoptnodes[id]->dualredscur == NULL)
2547 	       || (!cons_is_next && reopt->reopttree->reoptnodes[id]->dualredsnex == NULL));
2548 	
2549 	   /* the constraint will be added next */
2550 	   if( cons_is_next )
2551 	   {
2552 	      assert(reopt->reopttree->reoptnodes[id]->dualredscur == NULL);
2553 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur) );
2554 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur->vars, \
2555 	            reopt->dualreds->vars, nbndchgs) );
2556 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur->vals, \
2557 	            reopt->dualreds->vals, nbndchgs) );
2558 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur->boundtypes, \
2559 	            reopt->dualreds->boundtypes, nbndchgs) );
2560 	
2561 	      reopt->reopttree->reoptnodes[id]->dualredscur->nvars = nbndchgs;
2562 	      reopt->reopttree->reoptnodes[id]->dualredscur->varssize = nbndchgs;
2563 	      reopt->reopttree->reoptnodes[id]->dualredscur->lhs = 1.0;
2564 	      reopt->reopttree->reoptnodes[id]->dualredscur->rhs = SCIPsetInfinity(set);
2565 	      reopt->reopttree->reoptnodes[id]->dualredscur->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
2566 	         REOPT_CONSTYPE_DUALREDS : REOPT_CONSTYPE_INFSUBTREE);
2567 	      reopt->reopttree->reoptnodes[id]->dualredscur->linear = FALSE;
2568 	
2569 	      SCIPsetDebugMsg(set, " -> save dual information of type 1: node %lld, nvars %d, constype %d\n",
2570 	            SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredscur->nvars,
2571 	            reopt->reopttree->reoptnodes[id]->dualredscur->constype);
2572 	   }
2573 	   /* the constraint will be added after next */
2574 	   else
2575 	   {
2576 	      assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
2577 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex) );
2578 	      reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = -1;
2579 	
2580 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex->vars, \
2581 	            reopt->dualreds->vars, nbndchgs) );
2582 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex->vals, \
2583 	            reopt->dualreds->vals, nbndchgs) );
2584 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex->boundtypes, \
2585 	            reopt->dualreds->boundtypes, nbndchgs) );
2586 	      reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = nbndchgs;
2587 	      reopt->reopttree->reoptnodes[id]->dualredsnex->varssize = nbndchgs;
2588 	      reopt->reopttree->reoptnodes[id]->dualredsnex->lhs = 1.0;
2589 	      reopt->reopttree->reoptnodes[id]->dualredsnex->rhs = SCIPsetInfinity(set);
2590 	      reopt->reopttree->reoptnodes[id]->dualredsnex->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
2591 	         REOPT_CONSTYPE_DUALREDS : REOPT_CONSTYPE_INFSUBTREE);
2592 	
2593 	      SCIPsetDebugMsg(set, " -> save dual information of type 2: node %lld, nvars %d, constype %d\n",
2594 	         SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredsnex->nvars,
2595 	         reopt->reopttree->reoptnodes[id]->dualredsnex->constype);
2596 	   }
2597 	
2598 	   return SCIP_OKAY;
2599 	}
2600 	
2601 	/** adds a node of the branch and bound tree to the reoptimization tree */
2602 	static
2603 	SCIP_RETCODE addNode(
2604 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
2605 	   SCIP_SET*             set,                /**< global SCIP settings */
2606 	   SCIP_LP*              lp,                 /**< current LP */
2607 	   BMS_BLKMEM*           blkmem,             /**< block memory */
2608 	   SCIP_NODE*            node,               /**< current node */
2609 	   SCIP_REOPTTYPE        reopttype,          /**< reason for storing the node*/
2610 	   SCIP_Bool             saveafterdual,      /**< save branching decisions after the first dual */
2611 	   SCIP_Bool             isrootnode,         /**< node is the root node */
2612 	   SCIP_Real             lowerbound          /**< lower bound of the node */
2613 	   )
2614 	{
2615 	   SCIP_NODE* parent = NULL;
2616 	   SCIP_Bool shrank = FALSE;
2617 	   unsigned int id;
2618 	   unsigned int parentid = 0;
2619 	
2620 	   assert(reopt != NULL);
2621 	   assert(set != NULL);
2622 	   assert(blkmem != NULL);
2623 	   assert(node != NULL);
2624 	
2625 	   if( set->reopt_maxsavednodes == 0 )
2626 	      return SCIP_OKAY;
2627 	
2628 	   assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2629 	       || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2630 	       || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2631 	       || reopttype == SCIP_REOPTTYPE_LOGICORNODE
2632 	       || reopttype == SCIP_REOPTTYPE_LEAF
2633 	       || reopttype == SCIP_REOPTTYPE_PRUNED
2634 	       || reopttype == SCIP_REOPTTYPE_FEASIBLE);
2635 	
2636 	   /* start clock */
2637 	   SCIPclockStart(reopt->savingtime, set);
2638 	
2639 	   /* the node was created by reoptimization, i.e., we need to update the
2640 	    * stored data */
2641 	   if( SCIPnodeGetReoptID(node) >= 1 )
2642 	   {
2643 	      SCIP_Bool transintoorig;
2644 	
2645 	      assert(reopttype != SCIP_REOPTTYPE_LEAF);
2646 	      assert(!isrootnode);
2647 	
2648 	      id = SCIPnodeGetReoptID(node);
2649 	      assert(id < reopt->reopttree->reoptnodessize);
2650 	
2651 	      /* this is a special case:
2652 	       *   due to re-propagation of the an anchester node it can happen that we try to update a node that was created by
2653 	       *   reoptimization and already removed by deleteChildrenBelow. In this case we do not want to save the current
2654 	       *   node
2655 	       */
2656 	      if( reopt->reopttree->reoptnodes[id] == NULL )
2657 	      {
2658 	         parent = SCIPnodeGetParent(node);
2659 	         assert(parent != NULL);
2660 	
2661 	         parentid = SCIPnodeGetReoptID(parent);
2662 	
2663 	         /* traverse along the branching path until reaching a node that is part of the reoptimization tree or the root node */
2664 	         while( SCIPnodeGetDepth(parent) > 0 && reopt->reopttree->reoptnodes[parentid] == NULL )
2665 	         {
2666 	            /* the parent node is not part of the reoptimization, reset the reoptid and reopttype of the parent node */
2667 	            SCIPnodeSetReoptID(parent, 0);
2668 	            SCIPnodeSetReopttype(parent, SCIP_REOPTTYPE_NONE);
2669 	
2670 	            parent = SCIPnodeGetParent(parent);
2671 	            assert(parent != NULL);
2672 	
2673 	            parentid = SCIPnodeGetReoptID(parent);
2674 	         }
2675 	
2676 	         /* the anchestor node has to be part of the reoptimization tree. either the parent is the root itself or
2677 	          * marked to be a leaf, pruned or feasible
2678 	          */
2679 	         assert(reopt->reopttree->reoptnodes[parentid] != NULL);
2680 	         assert(parentid == 0
2681 	             || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_FEASIBLE
2682 	             || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_INFSUBTREE
2683 	             || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_LEAF
2684 	             || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_PRUNED); /*lint !e641*/
2685 	
2686 	         SCIPsetDebugMsg(set, " -> skip saving\n");
2687 	         SCIPnodeSetReoptID(node, 0);
2688 	         SCIPnodeSetReopttype(node, SCIP_REOPTTYPE_NONE);
2689 	
2690 	         /* stop clock */
2691 	         SCIPclockStop(reopt->savingtime, set);
2692 	
2693 	         return SCIP_OKAY;
2694 	      }
2695 	
2696 	      SCIPsetDebugMsg(set, "update node %lld at ID %u:\n", SCIPnodeGetNumber(node), id);
2697 	
2698 	      transintoorig = FALSE;
2699 	
2700 	      /* store separated cuts */
2701 	      if( set->reopt_usecuts )
2702 	      {
2703 	         SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
2704 	      }
2705 	
2706 	      /* save primal bound changes made after the first dual bound change */
2707 	      if( saveafterdual )
2708 	      {
2709 	         assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
2710 	         SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
2711 	      }
2712 	
2713 	      /* update constraint propagations */
2714 	      if( set->reopt_saveconsprop )
2715 	      {
2716 	         SCIP_CALL( updateConstraintPropagation(reopt, set, blkmem, node, id, &transintoorig) );
2717 	      }
2718 	
2719 	      /* ensure that all variables describing the branching path are original */
2720 	      if( transintoorig )
2721 	      {
2722 	         SCIP_CALL( transformIntoOrig(reopt, id) );
2723 	      }
2724 	
2725 	      /* update the lowerbound if the new lower bound is finite */
2726 	      if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2727 	         reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2728 	      SCIPsetDebugMsg(set, " -> reopttype: %d, lowerbound: %g\n", reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
2729 	
2730 	#ifdef SCIP_MORE_DEBUG
2731 	      {
2732 	         SCIPsetDebugMsg(set, " -> saved variables:\n");
2733 	         for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
2734 	         {
2735 	            SCIPsetDebugMsg(set, "  <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
2736 	               reopt->reopttree->reoptnodes[id]->varboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
2737 	               "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
2738 	         }
2739 	         for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
2740 	         {
2741 	            SCIPsetDebugMsg(set, " -> saved variables:\n");
2742 	            for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
2743 	            {
2744 	               SCIPsetDebugMsg(set, "  <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
2745 	                  reopt->reopttree->reoptnodes[id]->varboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
2746 	                  "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
2747 	            }
2748 	            for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
2749 	            {
2750 	               SCIPsetDebugMsg(set, "  <%s> %s %g (after dual red.)\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
2751 	                  reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
2752 	                  "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
2753 	            }
2754 	         }
2755 	      }
2756 	#endif
2757 	
2758 	      /* update LPI state */
2759 	      switch( reopttype )
2760 	      {
2761 	      case SCIP_REOPTTYPE_TRANSIT:
2762 	         if( set->reopt_shrinkinner )
2763 	         {
2764 	            SCIP_CALL( shrinkNode(reopt, set, node, id, &shrank, blkmem) );
2765 	         }
2766 	         goto TRANSIT;
2767 	
2768 	      case SCIP_REOPTTYPE_LOGICORNODE:
2769 	      case SCIP_REOPTTYPE_LEAF:
2770 	         goto TRANSIT;
2771 	
2772 	      case SCIP_REOPTTYPE_INFSUBTREE:
2773 	         /* delete the whole subtree induced be the current node */
2774 	         SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2775 	         goto PSEUDO;
2776 	
2777 	      case SCIP_REOPTTYPE_STRBRANCHED:
2778 	         goto PSEUDO;
2779 	
2780 	      case SCIP_REOPTTYPE_FEASIBLE:
2781 	         /* delete the subtree */
2782 	         if( set->reopt_reducetofrontier )
2783 	         {
2784 	            SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2785 	            SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2786 	         }
2787 	         /* dive through all children and change the reopttype to PRUNED */
2788 	         else
2789 	         {
2790 	            SCIP_CALL( changeReopttypeOfSubtree(reopt->reopttree, id, SCIP_REOPTTYPE_PRUNED) );
2791 	         }
2792 	         goto FEASIBLE;
2793 	
2794 	      case SCIP_REOPTTYPE_PRUNED:
2795 	         /* delete the subtree */
2796 	         if( set->reopt_reducetofrontier )
2797 	         {
2798 	            SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2799 	            SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2800 	         }
2801 	         /* dive through all children and change the reopttype to LEAF */
2802 	         else
2803 	         {
2804 	            SCIP_CALL( changeReopttypeOfSubtree(reopt->reopttree, id, SCIP_REOPTTYPE_PRUNED) );
2805 	         }
2806 	
2807 	         /* increase number of reoptimized nodes that could be pruned */
2808 	         ++reopt->reopttree->ncutoffreoptnodes;
2809 	         ++reopt->reopttree->ntotalcutoffreoptnodes;
2810 	
2811 	         goto PRUNED;
2812 	
2813 	      default:
2814 	         break;
2815 	      } /*lint !e788*/
2816 	
2817 	      /* stop clock */
2818 	      SCIPclockStart(reopt->savingtime, set);
2819 	
2820 	      return SCIP_OKAY;
2821 	   }
2822 	
2823 	   /* get new IDs */
2824 	   SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
2825 	
2826 	   /* the current node is the root node */
2827 	   if( isrootnode )
2828 	   {
2829 	      id = 0;
2830 	
2831 	      /* save local constraints
2832 	       * note: currently, there will be no constraint to save because all global constraints are added by calling
2833 	       * SCIPprobAddCons.
2834 	       */
2835 	      if (SCIPnodeGetNAddedConss(node) >= 1)
2836 	      {
2837 	         assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
2838 	
2839 	         SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
2840 	      }
2841 	
2842 	      /* store separated cuts
2843 	       * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
2844 	       * local constraints, then cuts
2845 	       */
2846 	      if( set->reopt_usecuts )
2847 	      {
2848 	         SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
2849 	      }
2850 	
2851 	      switch( reopttype )
2852 	      {
2853 	      case SCIP_REOPTTYPE_TRANSIT:
2854 	         /* ensure that no dual constraints are stored */
2855 	         SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2856 	
2857 	         /* update the lowerbound */
2858 	         if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2859 	            reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2860 	
2861 	         goto TRANSIT;
2862 	
2863 	      case SCIP_REOPTTYPE_INFSUBTREE:
2864 	      case SCIP_REOPTTYPE_STRBRANCHED:
2865 	         reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)reopttype;
2866 	         reopt->reopttree->reoptnodes[0]->dualreds = TRUE;
2867 	         reopt->reopttree->reoptnodes[0]->nvars = 0;
2868 	
2869 	         if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
2870 	         {
2871 	            /* delete the whole subtree induced be the current node */
2872 	            SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2873 	         }
2874 	
2875 	         /* update the lowerbound */
2876 	         if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2877 	            reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2878 	
2879 	         SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2880 	         SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
2881 	               reopt->reopttree->reoptnodes[id]->lowerbound);
2882 	
2883 	         goto PSEUDO;
2884 	
2885 	      case SCIP_REOPTTYPE_FEASIBLE:
2886 	         ++reopt->reopttree->ntotalfeasnodes;
2887 	         ++reopt->reopttree->nfeasnodes;
2888 	         reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
2889 	         reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
2890 	
2891 	         if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2892 	         {
2893 	            /* delete the subtree */
2894 	            if( set->reopt_reducetofrontier )
2895 	            {
2896 	               SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2897 	               SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2898 	            }
2899 	            /* dive through all children and change the reopttype to LEAF */
2900 	            else
2901 	            {
2902 	               SCIP_CALL( changeReopttypeOfSubtree(reopt->reopttree, 0, SCIP_REOPTTYPE_PRUNED) );
2903 	            }
2904 	         }
2905 	         else
2906 	            SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2907 	
2908 	         /* update the lowerbound */
2909 	         if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2910 	            reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2911 	
2912 	         SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2913 	         SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
2914 	               reopt->reopttree->reoptnodes[id]->lowerbound);
2915 	
2916 	         break;
2917 	
2918 	      case SCIP_REOPTTYPE_PRUNED:
2919 	         ++reopt->reopttree->nprunednodes;
2920 	         ++reopt->reopttree->ntotalprunednodes;
2921 	         reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
2922 	         reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
2923 	
2924 	         if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2925 	         {
2926 	            /* delete the subtree */
2927 	            if( set->reopt_reducetofrontier )
2928 	            {
2929 	               SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2930 	               SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2931 	            }
2932 	            /* dive through all children and change the reopttype to LEAF */
2933 	            else
2934 	            {
2935 	               SCIP_CALL( changeReopttypeOfSubtree(reopt->reopttree, 0, SCIP_REOPTTYPE_PRUNED) );
2936 	            }
2937 	         }
2938 	         else
2939 	            SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2940 	
2941 	         /* update the lowerbound if it was not set */
2942 	         if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2943 	            reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2944 	
2945 	         SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2946 	         SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound:%g \n", reopttype,
2947 	               reopt->reopttree->reoptnodes[id]->lowerbound);
2948 	
2949 	         break;
2950 	
2951 	      default:
2952 	         assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2953 	            || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2954 	            || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2955 	            || reopttype == SCIP_REOPTTYPE_PRUNED
2956 	            || reopttype == SCIP_REOPTTYPE_FEASIBLE);
2957 	         break;
2958 	      }/*lint !e788*/
2959 	
2960 	      /* reset the information of dual bound changes */
2961 	      reopt->currentnode = -1;
2962 	      if( reopt->dualreds != NULL )
2963 	         reopt->dualreds->nvars = 0;
2964 	
2965 	      /* stop clock */
2966 	      SCIPclockStop(reopt->savingtime, set);
2967 	
2968 	      return SCIP_OKAY;
2969 	   }
2970 	   else
2971 	   {
2972 	      int nbndchgdiff;
2973 	      SCIP_Bool transintoorig;
2974 	
2975 	      SCIPsetDebugMsg(set, "try to add node #%lld to the reopttree\n", SCIPnodeGetNumber(node));
2976 	      SCIPsetDebugMsg(set, " -> reopttype = %d\n", reopttype);
2977 	
2978 	      /* check if we really want to save this node:
2979 	       *   1. save the node if reopttype is at least SCIP_REOPTTYPE_INFSUBTREE
2980 	       *   2. save the node if the number of bound changes of this node
2981 	       *      and the last saved node is at least a given number n
2982 	       */
2983 	
2984 	      /* get the ID of the last saved node or 0 for the root */
2985 	      SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &nbndchgdiff) );
2986 	
2987 	      if( (reopttype < SCIP_REOPTTYPE_INFSUBTREE && nbndchgdiff <= set->reopt_maxdiffofnodes)
2988 	        || reopt->reopttree->reoptnodes[parentid]->reopttype >= SCIP_REOPTTYPE_LEAF ) /*lint !e641*/
2989 	      {
2990 	         SCIPsetDebugMsg(set, " -> skip saving\n");
2991 	
2992 	         /* stop clock */
2993 	         SCIPclockStop(reopt->savingtime, set);
2994 	
2995 	         return SCIP_OKAY;
2996 	      }
2997 	
2998 	      /* check if there are free slots to store the node */
2999 	      SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
3000 	
3001 	      id = SCIPqueueRemoveUInt(reopt->reopttree->openids);
3002 	
3003 	      SCIPsetDebugMsg(set, " -> save at ID %u\n", id);
3004 	
3005 	      assert(reopt->reopttree->reoptnodes[id] == NULL
3006 	         || (reopt->reopttree->reoptnodes[id]->nvars == 0 && reopt->reopttree->reoptnodes[id]->nconss == 0));
3007 	      assert(id >= 1 && id < reopt->reopttree->reoptnodessize);
3008 	      assert(!isrootnode);
3009 	
3010 	      /* get memory for nodedata */
3011 	      assert(reopt->reopttree->reoptnodes[id] == NULL || reopt->reopttree->reoptnodes[id]->nvars == 0);
3012 	      SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, id) );
3013 	      reopt->reopttree->reoptnodes[id]->parentID = parentid;
3014 	
3015 	      assert(parent != NULL );
3016 	      assert((SCIPnodeGetDepth(parent) == 0 && parentid == 0) || (SCIPnodeGetDepth(parent) >= 1 && parentid > 0));
3017 	      assert(id >= 1);
3018 	
3019 	      /* create the array of "child nodes" if they not exist */
3020 	      if( reopt->reopttree->reoptnodes[parentid]->childids == NULL
3021 	         || reopt->reopttree->reoptnodes[parentid]->allocchildmem == 0 )
3022 	      {
3023 	         SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0, 2, 0) );
3024 	      }
3025 	
3026 	      /* add the new node as a "child node" of the last saved reoptminization node */
3027 	      SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, id) );
3028 	
3029 	      /* save branching path */
3030 	      SCIP_CALL( saveAncestorBranchings(reopt->reopttree, set, blkmem, node, parent, id, parentid) );
3031 	
3032 	      /* save bound changes after some dual reduction */
3033 	      if( saveafterdual )
3034 	      {
3035 	         assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
3036 	         SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
3037 	      }
3038 	      else
3039 	      {
3040 	         SCIPsetDebugMsg(set, " -> skip saving bound changes after dual reductions.\n");
3041 	      }
3042 	
3043 	      /* transform all bounds of branched variables and ensure that they are original. */
3044 	      SCIP_CALL( transformIntoOrig(reopt, id) );
3045 	
3046 	      /* save pseudo-constraints (if one exists) */
3047 	      if (SCIPnodeGetNAddedConss(node) >= 1)
3048 	      {
3049 	         assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
3050 	
3051 	         SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
3052 	      }
3053 	
3054 	      /* store separated cuts
3055 	       * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
3056 	       * local constraints, then cuts
3057 	       */
3058 	      if( set->reopt_usecuts )
3059 	      {
3060 	         SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
3061 	      }
3062 	
3063 	      /* update the lowerbound if it was not set */
3064 	      if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
3065 	         reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
3066 	
3067 	      /* set ID */
3068 	      SCIPnodeSetReoptID(node, id);
3069 	
3070 	      /* set the REOPTTYPE */
3071 	      SCIPnodeSetReopttype(node, reopttype);
3072 	
3073 	      SCIPsetDebugMsg(set, "save node #%lld successful\n", SCIPnodeGetNumber(node));
3074 	      SCIPsetDebugMsg(set, " -> nvars: %d, ncons: %d, parentID: %u, reopttype: %d, lowerbound: %g\n",
3075 	         reopt->reopttree->reoptnodes[id]->nvars + reopt->reopttree->reoptnodes[id]->nafterdualvars,
3076 	         reopt->reopttree->reoptnodes[id]->nconss, reopt->reopttree->reoptnodes[id]->parentID,
3077 	         reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
3078 	#ifdef SCIP_MORE_DEBUG
3079 	      {
3080 	         for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
3081 	         {
3082 	            for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
3083 	            {
3084 	               SCIPsetDebugMsg(set, "  <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
3085 	                  reopt->reopttree->reoptnodes[id]->varboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
3086 	                  "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
3087 	            }
3088 	            for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
3089 	            {
3090 	               SCIPsetDebugMsg(set, "  <%s> %s %g (after dual red.)\n",
3091 	                  SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
3092 	                  reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
3093 	                  "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
3094 	            }
3095 	         }
3096 	      }
3097 	#endif
3098 	   } /*lint !e438*/
3099 	
3100 	   switch( reopttype )
3101 	   {
3102 	   case SCIP_REOPTTYPE_TRANSIT:
3103 	   case SCIP_REOPTTYPE_LOGICORNODE:
3104 	   case SCIP_REOPTTYPE_LEAF:
3105 	  TRANSIT:
3106 	      if( !shrank )
3107 	         reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
3108 	      else
3109 	      {
3110 	         SCIPnodeSetReoptID(node, 0);
3111 	         SCIPnodeSetReopttype(node, SCIP_REOPTTYPE_NONE);
3112 	      }
3113 	      break;
3114 	
3115 	   case SCIP_REOPTTYPE_INFSUBTREE:
3116 	   case SCIP_REOPTTYPE_STRBRANCHED:
3117 	  PSEUDO:
3118 	      assert(reopt->currentnode == SCIPnodeGetNumber(node));
3119 	
3120 	      reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
3121 	      reopt->reopttree->reoptnodes[id]->dualreds = TRUE;
3122 	
3123 	      /* get all the dual information and decide if the constraint need
3124 	       * to be added next or after next */
3125 	      SCIP_CALL( collectDualInformation(reopt, set, blkmem, node, id, reopttype) );
3126 	
3127 	      break;
3128 	
3129 	   case SCIP_REOPTTYPE_FEASIBLE:
3130 	  FEASIBLE:
3131 	      reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
3132 	      reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
3133 	      ++reopt->reopttree->nfeasnodes;
3134 	      ++reopt->reopttree->ntotalfeasnodes;
3135 	
3136 	      break;
3137 	
3138 	   case SCIP_REOPTTYPE_PRUNED:
3139 	  PRUNED:
3140 	      reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
3141 	      reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
3142 	      ++reopt->reopttree->nprunednodes;
3143 	      ++reopt->reopttree->ntotalprunednodes;
3144 	
3145 	      break;
3146 	
3147 	   default:
3148 	      assert(reopttype == SCIP_REOPTTYPE_TRANSIT
3149 	         || reopttype == SCIP_REOPTTYPE_LOGICORNODE
3150 	         || reopttype == SCIP_REOPTTYPE_LEAF
3151 	         || reopttype == SCIP_REOPTTYPE_INFSUBTREE
3152 	         || reopttype == SCIP_REOPTTYPE_STRBRANCHED
3153 	         || reopttype == SCIP_REOPTTYPE_FEASIBLE
3154 	         || reopttype == SCIP_REOPTTYPE_PRUNED);
3155 	      break;
3156 	   } /*lint !e788*/
3157 	
3158 	   /* stop clock */
3159 	   SCIPclockStop(reopt->savingtime, set);
3160 	
3161 	   /* reset the information of dual bound changes */
3162 	   reopt->currentnode = -1;
3163 	   if( reopt->dualreds != NULL )
3164 	      reopt->dualreds->nvars = 0;
3165 	
3166 	   return SCIP_OKAY;
3167 	}
3168 	
3169 	/** delete the stored information about dual bound changes of the last focused node */
3170 	static
3171 	void deleteLastDualBndchgs(
3172 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
3173 	   )
3174 	{
3175 	   assert(reopt != NULL);
3176 	
3177 	   if( reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
3178 	   {
3179 	      SCIPdebugMessage("delete %d dual variable information about node %lld\n", reopt->dualreds->nvars,
3180 	            reopt->currentnode);
3181 	      reopt->dualreds->nvars = 0;
3182 	      reopt->currentnode = -1;
3183 	   }
3184 	}
3185 	
3186 	/** delete the stored constraints that dual information at the given reoptimization node */
3187 	static
3188 	SCIP_RETCODE reoptnodeResetDualConss(
3189 	   SCIP_REOPTNODE*       reoptnode,          /**< reoptimization node */
3190 	   BMS_BLKMEM*           blkmem              /**< block memory */
3191 	   )
3192 	{
3193 	   assert(reoptnode != NULL);
3194 	   assert(blkmem != NULL);
3195 	
3196 	   if( reoptnode->dualredscur != NULL )
3197 	   {
3198 	      SCIP_REOPTCONSDATA* reoptconsdata;
3199 	
3200 	      SCIPdebugMessage("reset dual information (current run)\n");
3201 	
3202 	      reoptconsdata = reoptnode->dualredscur;
3203 	
3204 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
3205 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
3206 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
3207 	      BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
3208 	      reoptnode->dualredscur = NULL;
3209 	   }
3210 	
3211 	   if( reoptnode->dualredsnex != NULL )
3212 	   {
3213 	      SCIP_REOPTCONSDATA* reoptconsdata;
3214 	
3215 	      SCIPdebugMessage("reset dual information (next run)\n");
3216 	
3217 	      reoptconsdata = reoptnode->dualredsnex;
3218 	
3219 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
3220 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
3221 	      BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
3222 	      BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
3223 	      reoptnode->dualredsnex = NULL;
3224 	   }
3225 	
3226 	   reoptnode->dualreds = FALSE;
3227 	
3228 	   return SCIP_OKAY;
3229 	}
3230 	
3231 	
3232 	/** transform given set of variables, bounds and boundtypes into a global cut.
3233 	 *
3234 	 *  @note: boundtypes can be NULL if all variables are binary or a MIP solution should be separated.
3235 	 *  @note: continuous variables will be skiped if boundtypes is NULL
3236 	 */
3237 	static
3238 	SCIP_RETCODE addGlobalCut(
3239 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3240 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3241 	   SCIP_SET*             set,                /**< global SCIP settings */
3242 	   SCIP_VAR**            vars,               /**< variables of the cut */
3243 	   SCIP_Real*            vals,               /**< values of the cut */
3244 	   SCIP_BOUNDTYPE*       boundtypes,         /**< bounds of the cut */
3245 	   int                   nvars,              /**< number of variables in the cut */
3246 	   int                   nbinvars,           /**< number of binary variables */
3247 	   int                   nintvars            /**< number of integer variables */
3248 	   )
3249 	{
3250 	   SCIP_REOPTCONSDATA* reoptconsdata;
3251 	   int nglbconss;
3252 	   int nvarsadded;
3253 	
3254 	   assert(reopt != NULL);
3255 	   assert(blkmem != NULL);
3256 	   assert(set != NULL);
3257 	   assert(vars != NULL);
3258 	   assert(vals != NULL);
3259 	   assert(nbinvars + nintvars == nvars);
3260 	
3261 	   nvarsadded = 0;
3262 	
3263 	   /* check whether we have enough memory allocated */
3264 	   SCIP_CALL( checkMemGlbCons(reopt, set, blkmem, 10) );
3265 	   nglbconss = reopt->nglbconss;
3266 	   reoptconsdata = NULL;
3267 	
3268 	   if( reopt->glbconss[nglbconss] == NULL )
3269 	   {
3270 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[nglbconss]) ); /*lint !e866*/
3271 	      reoptconsdata = reopt->glbconss[nglbconss];
3272 	
3273 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, (int)(nbinvars+2*nintvars)) );
3274 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, (int)(nbinvars+2*nintvars)) );
3275 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, (int)(nbinvars+2*nintvars)) );
3276 	      reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
3277 	      reoptconsdata->nvars = 0;
3278 	   }
3279 	   else
3280 	   {
3281 	      assert(reopt->glbconss[nglbconss]->nvars == 0);
3282 	      assert(reopt->glbconss[nglbconss]->varssize > 0);
3283 	
3284 	      reoptconsdata = reopt->glbconss[nglbconss];
3285 	
3286 	      if( reoptconsdata->varssize < nbinvars+2*nintvars )
3287 	      {
3288 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize, \
3289 	               (int)(nbinvars+2*nintvars)) );
3290 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize, \
3291 	               (int)(nbinvars+2*nintvars)) );
3292 	         SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize, \
3293 	               (int)(nbinvars+2*nintvars)) );
3294 	         reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
3295 	      }
3296 	   }
3297 	   assert(reoptconsdata != NULL);
3298 	
3299 	   reoptconsdata->lhs = 1.0;
3300 	   reoptconsdata->rhs = SCIPsetInfinity(set);
3301 	   reoptconsdata->linear = FALSE;
3302 	   reoptconsdata->constype = REOPT_CONSTYPE_CUT;
3303 	
3304 	   for( int v = 0; v < nvars; ++v )
3305 	   {
3306 	      assert(nvarsadded < reoptconsdata->varssize);
3307 	      assert(vars[v] != NULL);
3308 	      assert(SCIPvarIsOriginal(vars[v]));
3309 	      assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsIntegral(set, vals[v]));
3310 	
3311 	      /* if no boundtypes are given we skip continuous variables, otherwise we would add trivial clauses:
3312 	       * a)       x <= ub
3313 	       * b) lb <= x
3314 	       * c) (x <= val) or (x >= val)
3315 	       */
3316 	      if( boundtypes == NULL && SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
3317 	         continue;
3318 	
3319 	      if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
3320 	      {
3321 	         reoptconsdata->vars[nvarsadded] = vars[v];
3322 	
3323 	         if( SCIPsetIsEQ(set, vals[v], 1.0) )
3324 	         {
3325 	            assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3326 	            reoptconsdata->vals[nvarsadded] = 0.0;
3327 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3328 	         }
3329 	         else
3330 	         {
3331 	            assert(SCIPsetIsEQ(set, vals[v], 0.0));
3332 	            assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
3333 	            reoptconsdata->vals[nvarsadded] = 1.0;
3334 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3335 	         }
3336 	         ++nvarsadded;
3337 	      }
3338 	      else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS)
3339 	      {
3340 	         assert(boundtypes != NULL);
3341 	
3342 	         reoptconsdata->vals[nvarsadded] = vals[v];
3343 	         reoptconsdata->boundtypes[nvarsadded] = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
3344 	         ++nvarsadded;
3345 	      }
3346 	      else
3347 	      {
3348 	         SCIP_Real roundedval;
3349 	         SCIP_Real ubglb;
3350 	         SCIP_Real lbglb;
3351 	
3352 	         assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_IMPLINT);
3353 	
3354 	         reoptconsdata->vars[nvarsadded] = vars[v];
3355 	
3356 	         ubglb = SCIPvarGetUbGlobal(vars[v]);
3357 	         lbglb = SCIPvarGetLbGlobal(vars[v]);
3358 	
3359 	         /* case 1  :      x == val == ub -> x <= ub-1
3360 	          * case 2  :      x == val == lb -> x >= lb+1
3361 	          * case 3.1:      x <= val <  ub -> x >= y+1
3362 	          * case 3.2:      x >= val >  lb -> x <= y-1
3363 	          * case 4  : lb < x == val <  ub -> (x <= y-1) or (x >= y+1)
3364 	          */
3365 	
3366 	         /* case 1 */
3367 	         if( SCIPsetIsEQ(set, vals[v], ubglb) )
3368 	         {
3369 	            assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3370 	            reoptconsdata->vals[nvarsadded] = ubglb - 1.0;
3371 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3372 	            ++nvarsadded;
3373 	         }
3374 	         /* case 2 */
3375 	         else if( SCIPsetIsEQ(set, vals[v], lbglb) )
3376 	         {
3377 	            assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
3378 	            reoptconsdata->vals[nvarsadded] = lbglb + 1.0;
3379 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3380 	            ++nvarsadded;
3381 	         }
3382 	         else if( boundtypes != NULL )
3383 	         {
3384 	            /* we round the solution value to get a 'clean' bound */
3385 	            assert(SCIPsetIsIntegral(set, vals[v]));
3386 	            roundedval = SCIPsetRound(set, vals[v]);
3387 	
3388 	            /* case 3.1 */
3389 	            if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
3390 	            {
3391 	               reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
3392 	               reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3393 	               ++nvarsadded;
3394 	            }
3395 	            /* case 3.2 */
3396 	            else
3397 	            {
3398 	               assert(boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3399 	               reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
3400 	               reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3401 	               ++nvarsadded;
3402 	            }
3403 	         }
3404 	         /* case 4: in this case we have to add two clauses: (x <= val-1) and (x >= val+1) */
3405 	         else
3406 	         {
3407 	            /* we round the solution value to get a 'clean' bound */
3408 	            assert(SCIPsetIsIntegral(set, vals[v]));
3409 	            roundedval = SCIPsetRound(set, vals[v]);
3410 	
3411 	            /* first clause: x <= val-1 */
3412 	            reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
3413 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3414 	            ++nvarsadded;
3415 	
3416 	            /* second clause:  x >= val+1 */
3417 	            reoptconsdata->vars[nvarsadded] = vars[v];
3418 	            reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
3419 	            reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3420 	            ++nvarsadded;
3421 	         }
3422 	      }
3423 	   }
3424 	   assert(nvars <= nvarsadded);
3425 	   assert(nvarsadded == nbinvars + 2 * nintvars);
3426 	
3427 	   reoptconsdata->nvars = nvarsadded;
3428 	   ++reopt->nglbconss;
3429 	
3430 	   return SCIP_OKAY;
3431 	}
3432 	
3433 	/** generate a global constraint to separate an infeasible subtree */
3434 	static
3435 	SCIP_RETCODE saveGlobalCons(
3436 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3437 	   SCIP_SET*             set,                /**< global SCIP settings */
3438 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3439 	   SCIP_NODE*            node,               /**< node of the search tree */
3440 	   REOPT_CONSTYPE        consttype           /**< reopttype of the constraint */
3441 	   )
3442 	{
3443 	   assert(reopt != NULL);
3444 	   assert(node != NULL);
3445 	
3446 	   if( consttype == REOPT_CONSTYPE_INFSUBTREE )
3447 	   {
3448 	      SCIP_VAR** vars;
3449 	      SCIP_Real* vals;
3450 	      SCIP_BOUNDTYPE* boundtypes;
3451 	      int allocmem;
3452 	      int nbranchvars;
3453 	      int nbinvars;
3454 	      int nintvars;
3455 	
3456 	      /* allocate memory to store the infeasible path */
3457 	      allocmem = SCIPnodeGetDepth(node);
3458 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, allocmem) );
3459 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, allocmem) );
3460 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, allocmem) );
3461 	
3462 	      /* get the branching path */
3463 	      SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
3464 	
3465 	      if( allocmem < nbranchvars )
3466 	      {
3467 	         SCIP_CALL( SCIPsetReallocBufferArray(set, &vars, nbranchvars) );
3468 	         SCIP_CALL( SCIPsetReallocBufferArray(set, &vals, nbranchvars) );
3469 	         SCIP_CALL( SCIPsetReallocBufferArray(set, &boundtypes, nbranchvars) );
3470 	         allocmem = nbranchvars;
3471 	
3472 	         SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
3473 	      }
3474 	
3475 	      /* we count the number of binary and (impl) integer variables */
3476 	      nbinvars = 0;
3477 	      nintvars = 0;
3478 	      for( int v = 0; v < nbranchvars; ++v )
3479 	      {
3480 	         if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
3481 	            ++nbinvars;
3482 	         if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_IMPLINT )
3483 	            ++nintvars;
3484 	      }
3485 	      assert(nbinvars + nintvars == nbranchvars);
3486 	
3487 	      SCIP_CALL( addGlobalCut(reopt, blkmem, set, vars, vals, boundtypes, nbranchvars, nbinvars, nintvars) );
3488 	      assert(!reopt->glbconss[reopt->nglbconss - 1]->linear);
3489 	
3490 	      /* free buffer */
3491 	      SCIPsetFreeBufferArray(set, &boundtypes);
3492 	      SCIPsetFreeBufferArray(set, &vals);
3493 	      SCIPsetFreeBufferArray(set, &vars);
3494 	   }
3495 	
3496 	   return SCIP_OKAY;
3497 	}
3498 	
3499 	
3500 	/** move all id of child nodes from reoptimization node stored at @p id1 to the node stored at @p id2 */
3501 	static
3502 	SCIP_RETCODE reoptMoveIDs(
3503 	   SCIP_REOPTTREE*       reopttree,          /**< reopttree */
3504 	   SCIP_SET*             set,                /**< global SCIP settings */
3505 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3506 	   unsigned int          id1,                /**< source id */
3507 	   unsigned int          id2                 /**< target id */
3508 	   )
3509 	{
3510 	   int nchilds_id1;
3511 	   int nchilds_id2;
3512 	
3513 	   assert(reopttree != NULL);
3514 	   assert(blkmem != NULL);
3515 	   assert(id1 < reopttree->reoptnodessize);
3516 	   assert(id2 < reopttree->reoptnodessize);
3517 	   assert(reopttree->reoptnodes[id1] != NULL);
3518 	   assert(reopttree->reoptnodes[id2] != NULL);
3519 	
3520 	   nchilds_id1 = reopttree->reoptnodes[id1]->nchilds;
(1) Event index_parm: Pointer "reopttree->reoptnodes" is directly accessed by "id2" with an offset of 0.
3521 	   nchilds_id2 = reopttree->reoptnodes[id2]->nchilds;
3522 	
3523 	   /* ensure that the array storing the child id's is large enough */
3524 	   SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id2], set, blkmem, 0, nchilds_id1+nchilds_id2, 0) );
3525 	   assert(reopttree->reoptnodes[id2]->allocchildmem >= nchilds_id1+nchilds_id2);
3526 	
3527 	   SCIPsetDebugMsg(set, "move %d IDs: %u -> %u\n", nchilds_id1, id1, id2);
3528 	
3529 	   /* move the ids */
3530 	   for( int c = 0; c < nchilds_id1; ++c )
3531 	   {
3532 	#ifdef SCIP_DEBUG
3533 	      {
3534 	         /* check that no id is added twice */
3535 	         for( int k = 0; k < nchilds_id2; ++k )
3536 	            assert(reopttree->reoptnodes[id2]->childids[k] != reopttree->reoptnodes[id1]->childids[c]);
3537 	      }
3538 	#endif
3539 	
3540 	      reopttree->reoptnodes[id2]->childids[nchilds_id2+c] = reopttree->reoptnodes[id1]->childids[c];
3541 	   }
3542 	
3543 	   /* update the number of childs */
3544 	   reopttree->reoptnodes[id1]->nchilds = 0;
3545 	   reopttree->reoptnodes[id2]->nchilds += nchilds_id1;
3546 	
3547 	   return SCIP_OKAY;
3548 	}
3549 	
3550 	/** change all bound changes along the root path */
3551 	static
3552 	SCIP_RETCODE changeAncestorBranchings(
3553 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3554 	   SCIP_SET*             set,                /**< global SCIP settings */
3555 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
3556 	   SCIP_PROB*            transprob,          /**< transformed problem */
3557 	   SCIP_PROB*            origprob,           /**< original problem */
3558 	   SCIP_TREE*            tree,               /**< search tree */
3559 	   SCIP_LP*              lp,                 /**< current LP */
3560 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidates */
3561 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3562 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table */
3563 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3564 	   SCIP_NODE*            node,               /**< node of the branch and bound tree */
3565 	   unsigned int          id,                 /**< id of stored node */
3566 	   SCIP_Bool             afterdualbranching  /**< convert all bound changes made directly after the first bound
3567 	                                              *   changes based on dual information into normal branchings */
3568 	   )
3569 	{
3570 	   SCIP_REOPTTREE* reopttree;
3571 	   SCIP_REOPTNODE* reoptnode;
3572 	
3573 	   assert(reopt != NULL);
3574 	   assert(set != NULL);
3575 	   assert(stat != NULL);
3576 	   assert(transprob != NULL);
3577 	   assert(tree != NULL);
3578 	   assert(lp != NULL);
3579 	   assert(branchcand != NULL);
3580 	   assert(eventqueue != NULL);
3581 	   assert(cliquetable != NULL);
3582 	   assert(node != NULL);
3583 	   assert(blkmem != NULL);
3584 	
3585 	   reopttree = reopt->reopttree;
3586 	   assert(reopttree != NULL);
3587 	   assert(id < reopttree->reoptnodessize);
3588 	
3589 	   reoptnode = reopttree->reoptnodes[id];
3590 	   assert(reoptnode != NULL);
3591 	
3592 	   /* copy memory to ensure that only original variables are saved */
3593 	   if( reoptnode->nvars == 0 && reoptnode->nafterdualvars == 0)
3594 	      return SCIP_OKAY;
3595 	
3596 	   /* change the bounds along the branching path */
3597 	   for( int v = 0; v < reoptnode->nvars; ++v )
3598 	   {
3599 	      SCIP_VAR* var;
3600 	      SCIP_Real val;
3601 	      SCIP_BOUNDTYPE boundtype;
3602 	      SCIP_Real oldlb;
3603 	      SCIP_Real oldub;
3604 	      SCIP_Real newbound;
3605 	
3606 	      var = reoptnode->vars[v];
3607 	      val = reoptnode->varbounds[v];
3608 	      boundtype = reoptnode->varboundtypes[v];
3609 	
3610 	      assert(SCIPvarIsOriginal(var));
3611 	      SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
3612 	      assert(SCIPvarIsTransformed(var));
3613 	      assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR);
3614 	
3615 	      oldlb = SCIPvarGetLbLocal(var);
3616 	      oldub = SCIPvarGetUbLocal(var);
3617 	      newbound = val;
3618 	
3619 	      assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3620 	
3621 	      if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3622 	      {
3623 	         SCIPvarAdjustLb(var, set, &newbound);
3624 	
3625 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3626 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3627 	      }
3628 	      else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3629 	      {
3630 	         SCIPvarAdjustUb(var, set, &newbound);
3631 	
3632 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3633 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3634 	      }
3635 	#ifdef SCIP_MORE_DEBUG
3636 	      SCIPsetDebugMsg(set, "  (path) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3637 	#endif
3638 	   }
3639 	
3640 	   if( afterdualbranching && reoptnode->nafterdualvars > 0 )
3641 	   {
3642 	      /* check the memory to convert this bound changes into 'normal' */
3643 	      SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem,
3644 	            reoptnode->nvars + reoptnode->nafterdualvars, 0, 0) );
3645 	
3646 	      /* change the bounds */
3647 	      for( int v = 0; v < reoptnode->nafterdualvars; ++v )
3648 	      {
3649 	         SCIP_VAR* var;
3650 	         SCIP_Real val;
3651 	         SCIP_BOUNDTYPE boundtype;
3652 	         SCIP_Bool bndchgd;
3653 	         SCIP_Real oldlb;
3654 	         SCIP_Real oldub;
3655 	         SCIP_Real newbound;
3656 	
3657 	         var = reoptnode->afterdualvars[v];
3658 	         val = reoptnode->afterdualvarbounds[v];
3659 	         boundtype = reoptnode->afterdualvarboundtypes[v];
3660 	
3661 	         assert(SCIPvarIsOriginal(var));
3662 	         SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
3663 	         assert(SCIPvarIsTransformed(var));
3664 	         assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR);
3665 	
3666 	         bndchgd = FALSE;
3667 	
3668 	         oldlb = SCIPvarGetLbLocal(var);
3669 	         oldub = SCIPvarGetUbLocal(var);
3670 	         newbound = val;
3671 	
3672 	         if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3673 	         {
3674 	            SCIPvarAdjustLb(var, set, &newbound);
3675 	            SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3676 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3677 	
3678 	            bndchgd = TRUE;
3679 	         }
3680 	         else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3681 	         {
3682 	            SCIPvarAdjustUb(var, set, &newbound);
3683 	            SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3684 	                  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3685 	
3686 	            bndchgd = TRUE;
3687 	         }
3688 	
3689 	         assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3690 	
3691 	#ifdef SCIP_MORE_DEBUG
3692 	         SCIPsetDebugMsg(set, "   (prop) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3693 	#endif
3694 	         if( bndchgd )
3695 	         {
3696 	            int nvars;
3697 	
3698 	            nvars = reoptnode->nvars;
3699 	            reoptnode->vars[nvars] = reoptnode->afterdualvars[v];
3700 	            reoptnode->varbounds[nvars] = reoptnode->afterdualvarbounds[v];
3701 	            reoptnode->varboundtypes[nvars] = reoptnode->afterdualvarboundtypes[v];
3702 	            ++reoptnode->nvars;
3703 	         }
3704 	      }
3705 	
3706 	      /* free the afterdualvars, -bounds, and -boundtypes */
3707 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarboundtypes, reoptnode->afterdualvarssize);
3708 	      reoptnode->afterdualvarboundtypes = NULL;
3709 	
3710 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarbounds, reoptnode->afterdualvarssize);
3711 	      reoptnode->afterdualvarbounds = NULL;
3712 	
3713 	      BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvars, reoptnode->afterdualvarssize);
3714 	      reoptnode->afterdualvars = NULL;
3715 	
3716 	      reoptnode->nafterdualvars = 0;
3717 	      reoptnode->afterdualvarssize = 0;
3718 	   }
3719 	
3720 	   return SCIP_OKAY;
3721 	}
3722 	
3723 	
3724 	/** add a constraint to ensure that at least one variable bound gets different */
3725 	static
3726 	SCIP_RETCODE addSplitcons(
3727 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3728 	   SCIP*                 scip,               /**< SCIP data structure */
3729 	   SCIP_SET*             set,                /**< global SCIP settings */
3730 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
3731 	   BMS_BLKMEM*           blkmem,             /**< block memory */
3732 	   SCIP_PROB*            transprob,          /**< transformed problem */
3733 	   SCIP_PROB*            origprob,           /**< original problem */
3734 	   SCIP_TREE*            tree,               /**< search tree */
3735 	   SCIP_LP*              lp,                 /**< current LP */
3736 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidates */
3737 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
3738 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
3739 	   SCIP_NODE*            node,               /**< node corresponding to the pruned part */
3740 	   unsigned int          id                  /**< id of stored node */
3741 	   )
3742 	{
3743 	   SCIP_CONS* cons;
3744 	   char name[SCIP_MAXSTRLEN];
3745 	
3746 	   assert(reopt != NULL);
3747 	   assert(reopt->reopttree != NULL);
3748 	   assert(id < reopt->reopttree->reoptnodessize);
3749 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
3750 	   assert(reopt->reopttree->reoptnodes[id]->dualreds);
3751 	   assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
3752 	   assert(scip != NULL);
3753 	   assert(set != NULL);
3754 	   assert(stat != NULL);
3755 	   assert(blkmem != NULL);
3756 	   assert(transprob != NULL);
3757 	   assert(origprob != NULL);
3758 	   assert(tree != NULL);
3759 	   assert(lp != NULL);
3760 	   assert(branchcand != NULL);
3761 	   assert(eventqueue != NULL);
3762 	   assert(node != NULL);
3763 	
3764 	   assert(reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS
3765 	         || reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
3766 	
3767 	#ifndef NDEBUG
3768 	   if( reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS )
3769 	      SCIPsetDebugMsg(set, " create a split-node #%lld\n", SCIPnodeGetNumber(node));
3770 	   else
3771 	      SCIPsetDebugMsg(set, " separate an infeasible subtree\n");
3772 	#endif
3773 	
3774 	   /* if the constraint consists of exactly one variable it can be interpreted
3775 	    * as a normal branching step, i.e., we can fix the variable to the negated bound */
3776 	   if( reopt->reopttree->reoptnodes[id]->dualredscur->nvars == 1 )
3777 	   {
3778 	      SCIP_REOPTCONSDATA* reoptconsdata;
3779 	      SCIP_VAR* var;
3780 	      SCIP_BOUNDTYPE boundtype;
3781 	      SCIP_Real oldlb;
3782 	      SCIP_Real oldub;
3783 	      SCIP_Real newbound;
3784 	
3785 	      reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
3786 	      assert(!reoptconsdata->linear);
3787 	      assert(reoptconsdata->vars != NULL);
3788 	      assert(reoptconsdata->vals != NULL);
3789 	      assert(reoptconsdata->boundtypes != NULL);
3790 	
3791 	      var = reoptconsdata->vars[0];
3792 	      newbound = reoptconsdata->vals[0];
3793 	      boundtype = reoptconsdata->boundtypes[0];
3794 	
3795 	      assert(SCIPvarIsOriginal(var));
3796 	      SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
3797 	      assert(SCIPvarIsTransformed(var));
3798 	
3799 	      oldlb = SCIPvarGetLbLocal(var);
3800 	      oldub = SCIPvarGetUbLocal(var);
3801 	
3802 	      if( boundtype == SCIP_BOUNDTYPE_LOWER )
3803 	      {
3804 	         newbound = reoptconsdata->vals[0] - 1.0;
3805 	         /* if newbound > local upper bound, the variable cannot take the old value and we exit */
3806 	         if( SCIPisGT(scip, newbound, oldub) )
3807 	            return SCIP_OKAY;
3808 	         assert(SCIPisLE(scip, newbound, oldub));
3809 	      }
3810 	      else
3811 	      {
3812 	         newbound = reoptconsdata->vals[0] + 1.0;
3813 	         /* if newbound < local lower bound, the variable cannot take the old value and we exit */
3814 	         if( SCIPisLT(scip, newbound, oldlb) )
3815 	            return SCIP_OKAY;
3816 	         assert(SCIPisGE(scip, newbound, oldlb));
3817 	      }
3818 	      boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
3819 	      assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3820 	
3821 	      if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3822 	      {
3823 	         SCIPvarAdjustLb(var, set, &newbound);
3824 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3825 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3826 	      }
3827 	      else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3828 	      {
3829 	         SCIPvarAdjustUb(var, set, &newbound);
3830 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3831 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3832 	      }
3833 	
3834 	      SCIPsetDebugMsg(set, "  -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
3835 	            boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3836 	   }
3837 	   else
3838 	   {
3839 	      SCIP_REOPTCONSDATA* reoptconsdata;
3840 	      SCIP_VAR** consvars;
3841 	      SCIP_Real consval;
3842 	      SCIP_BOUNDTYPE consboundtype;
3843 	      int nbinvars = 0;
3844 	#ifndef NDEBUG
3845 	      int nintvars = 0;
3846 	      int ncontvars = 0;
3847 	#endif
3848 	
3849 	      reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
3850 	      assert(!reoptconsdata->linear);
3851 	      assert(reoptconsdata->vars != NULL);
3852 	      assert(reoptconsdata->vals != NULL);
3853 	      assert(reoptconsdata->boundtypes != NULL);
3854 	
3855 	      /* allocate buffer */
3856 	      SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reoptconsdata->nvars) );
3857 	
3858 	      /* count number of binary, integer, and continuous variables */
3859 	      for( int v = 0; v < reoptconsdata->nvars; ++v )
3860 	      {
3861 	         switch ( SCIPvarGetType(reoptconsdata->vars[v]) )
3862 	         {
3863 	         case SCIP_VARTYPE_BINARY:
3864 	            ++nbinvars;
3865 	            break;
3866 	         case SCIP_VARTYPE_IMPLINT:
3867 	         case SCIP_VARTYPE_INTEGER:
3868 	            if( SCIPisEQ(scip, SCIPvarGetLbLocal(reoptconsdata->vars[v]), 0.0)
3869 	               && SCIPisEQ(scip, SCIPvarGetUbLocal(reoptconsdata->vars[v]), 1.0) )
3870 	               ++nbinvars;
3871 	#ifndef NDEBUG
3872 	            else
3873 	               ++nintvars;
3874 	#endif
3875 	            break;
3876 	         case SCIP_VARTYPE_CONTINUOUS:
3877 	#ifndef NDEBUG
3878 	            ++ncontvars;
3879 	#endif
3880 	            break;
3881 	         default:
3882 	            SCIPerrorMessage("Variable <%s> has to be either binary, (implied) integer, or continuous.\n",
3883 	               SCIPvarGetName(reoptconsdata->vars[v]));
3884 	            return SCIP_INVALIDDATA;
3885 	         }
3886 	      }
3887 	
3888 	      if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
3889 	         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
3890 	      else
3891 	      {
3892 	         assert(reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS);
3893 	         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
3894 	      }
3895 	
3896 	      /* case 1: all variables are binary, we use a logic-or constraint. */
3897 	      if( reoptconsdata->nvars == nbinvars )
3898 	      {
3899 	         for( int v = 0; v < reoptconsdata->nvars; ++v )
3900 	         {
3901 	            consvars[v] = reoptconsdata->vars[v];
3902 	            consval = reoptconsdata->vals[v];
3903 	            consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
3904 	
3905 	           assert(SCIPvarIsOriginal(consvars[v]));
3906 	           SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
3907 	           assert(SCIPvarIsTransformed(consvars[v]));
3908 	           assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3909 	
3910 	           if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
3911 	           {
3912 	              SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
3913 	              assert(SCIPvarIsNegated(consvars[v]));
3914 	           }
3915 	         }
3916 	
3917 	         SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reoptconsdata->nvars, consvars,
3918 	               FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
3919 	      }
3920 	      /* case 2: at least one variable is integer or continuous. we use a bounddisjunction constraint. */
3921 	      else
3922 	      {
3923 	         SCIP_Real* consvals;
3924 	         SCIP_BOUNDTYPE* consboundtypes;
3925 	
3926 	         assert(nintvars > 0 || ncontvars > 0);
3927 	
3928 	         /* alloc buffer memory */
3929 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, reoptconsdata->nvars) );
3930 	         SCIP_CALL( SCIPallocBufferArray(scip, &consboundtypes, reoptconsdata->nvars) );
3931 	
3932 	         /* iterate over all variables and transform them */
3933 	         for( int v = 0; v < reoptconsdata->nvars; ++v )
3934 	         {
3935 	            consvars[v] = reoptconsdata->vars[v];
3936 	            consvals[v] = reoptconsdata->vals[v];
3937 	            consboundtypes[v] = reoptconsdata->boundtypes[v];
3938 	
3939 	            /* we have to switch the bounds.
3940 	             * case 1: integer variable with bound x <= u is transformed to u+1 <= x
3941 	             *                                 and l <= x is transformed to   x <= l-1
3942 	             * case 2: continuous variable with bound x <= u is transformed to u <= x
3943 	             *                                    and l <= x is transformed to x <= l
3944 	             */
3945 	            if( SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_BINARY
3946 	             || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_INTEGER
3947 	             || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_IMPLINT )
3948 	            {
3949 	               if( consboundtypes[v] == SCIP_BOUNDTYPE_UPPER )
3950 	               {
3951 	                  consvals[v] += 1.0;
3952 	                  assert(SCIPsetIsLE(set, consvals[v], SCIPvarGetUbGlobal(consvars[v])));
3953 	               }
3954 	               else
3955 	               {
3956 	                  consvals[v] -= 1.0;
3957 	                  assert(SCIPsetIsGE(set, consvals[v], SCIPvarGetLbGlobal(consvars[v])));
3958 	               }
3959 	            }
3960 	
3961 	            consboundtypes[v] = (SCIP_BOUNDTYPE)(1 - consboundtypes[v]); /*lint !e641*/
3962 	
3963 	            assert(SCIPvarIsOriginal(consvars[v]));
3964 	            SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consvals[v], &consboundtypes[v]) );
3965 	            assert(SCIPvarIsTransformed(consvars[v]));
3966 	            assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3967 	         }
3968 	
3969 	         /* create the constraints and add them to the corresponding nodes */
3970 	         SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, consvars, consboundtypes,
3971 	               consvals, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
3972 	
3973 	         /* free buffer memory */
3974 	         SCIPfreeBufferArray(scip, &consboundtypes);
3975 	         SCIPfreeBufferArray(scip, &consvals);
3976 	      }
3977 	
3978 	      SCIPsetDebugMsg(set, " -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
3979 	#ifdef SCIP_DEBUG_CONSS
3980 	      SCIPdebugPrintCons(scip, cons, NULL);
3981 	#endif
3982 	
3983 	      SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
3984 	      SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3985 	
3986 	      /* free buffer */
3987 	      SCIPfreeBufferArray(scip, &consvars);
3988 	   }
3989 	
3990 	   return SCIP_OKAY;
3991 	}
3992 	
3993 	/** fix all bounds ad stored in dualredscur at the given node @p node_fix */
3994 	static
3995 	SCIP_RETCODE fixBounds(
3996 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
3997 	   SCIP_SET*             set,                /**< global SCIP settings */
3998 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
3999 	   SCIP_PROB*            transprob,          /**< transformed problem */
4000 	   SCIP_PROB*            origprob,           /**< original problem */
4001 	   SCIP_TREE*            tree,               /**< search tree */
4002 	   SCIP_LP*              lp,                 /**< current LP */
4003 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidates */
4004 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4005 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table */
4006 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4007 	   SCIP_NODE*            node,               /**< node corresponding to the fixed part */
4008 	   unsigned int          id,                 /**< id of stored node */
4009 	   SCIP_Bool             updatedualconss     /**< update constraint representing dual bound changes */
4010 	   )
4011 	{
4012 	   SCIP_REOPTTREE* reopttree;
4013 	   SCIP_REOPTNODE* reoptnode;
4014 	
4015 	   assert(reopt != NULL);
4016 	   assert(set != NULL);
4017 	   assert(stat != NULL);
4018 	   assert(transprob != NULL);
4019 	   assert(origprob != NULL);
4020 	   assert(tree != NULL);
4021 	   assert(lp != NULL);
4022 	   assert(branchcand != NULL);
4023 	   assert(eventqueue != NULL);
4024 	   assert(cliquetable != NULL);
4025 	   assert(node != NULL);
4026 	   assert(blkmem != NULL);
4027 	
4028 	   reopttree = reopt->reopttree;
4029 	   assert(reopttree != NULL);
4030 	   assert(0 < id && id < reopttree->reoptnodessize);
4031 	
4032 	   reoptnode = reopttree->reoptnodes[id];
4033 	   assert(reoptnode != NULL);
4034 	   assert(reoptnode->dualreds);
4035 	   assert(reoptnode->dualredscur != NULL);
4036 	
4037 	   /* ensure that the arrays to store the bound changes are large enough */
4038 	   SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, reoptnode->nvars + reoptnode->dualredscur->nvars, 0, 0) );
4039 	
4040 	   for( int v = 0; v < reoptnode->dualredscur->nvars; ++v )
4041 	   {
4042 	      SCIP_VAR* var;
4043 	      SCIP_Real val;
4044 	      SCIP_BOUNDTYPE boundtype;
4045 	      SCIP_Bool bndchgd;
4046 	
4047 	      var = reoptnode->dualredscur->vars[v];
4048 	      val = reoptnode->dualredscur->vals[v];
4049 	      boundtype = reoptnode->dualredscur->boundtypes[v];
4050 	
4051 	      SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4052 	      assert(SCIPvarIsTransformedOrigvar(var));
4053 	
4054 	      bndchgd = FALSE;
4055 	
4056 	      if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4057 	         && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4058 	      {
4059 	         SCIPvarAdjustLb(var, set, &val);
4060 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4061 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4062 	
4063 	         bndchgd = TRUE;
4064 	      }
4065 	      else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4066 	         && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4067 	      {
4068 	         SCIPvarAdjustUb(var, set, &val);
4069 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4070 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4071 	
4072 	         bndchgd = TRUE;
4073 	      }
4074 	      else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4075 	      {
4076 	         SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4077 	         return SCIP_INVALIDDATA;
4078 	      }
4079 	#ifdef SCIP_MORE_DEBUG
4080 	      SCIPsetDebugMsg(set, "  (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4081 	#endif
4082 	      /* add variable and bound to branching path information, because we don't want to delete this data */
4083 	      if( bndchgd )
4084 	      {
4085 	         int pos;
4086 	         SCIP_Real constant;
4087 	         SCIP_Real scalar;
4088 	
4089 	         pos = reoptnode->nvars;
4090 	
4091 	         reoptnode->vars[pos] = var;
4092 	         scalar = 1.0;
4093 	         constant = 0.0;
4094 	         SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
4095 	         assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
4096 	
4097 	         reoptnode->varbounds[pos] = reoptnode->dualredscur->vals[v];
4098 	         reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
4099 	         ++reoptnode->nvars;
4100 	      }
4101 	   }
4102 	
4103 	   if( updatedualconss )
4104 	   {
4105 	      /* delete dualredscur and move dualredsnex -> dualredscur */
4106 	      SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
4107 	   }
4108 	
4109 	   return SCIP_OKAY;
4110 	}
4111 	
4112 	/** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
4113 	 *  keep the first negbndchg-1 bound changes as stored in dualredscur and negate the negbndchg-th bound.
4114 	 */
4115 	static
4116 	SCIP_RETCODE fixInterdiction(
4117 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4118 	   SCIP_SET*             set,                /**< global SCIP settings */
4119 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4120 	   SCIP_PROB*            transprob,          /**< transformed problem */
4121 	   SCIP_PROB*            origprob,           /**< original problem */
4122 	   SCIP_TREE*            tree,               /**< search tree */
4123 	   SCIP_LP*              lp,                 /**< current LP */
4124 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidates */
4125 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
4126 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table */
4127 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4128 	   SCIP_NODE*            node,               /**< child node */
4129 	   unsigned int          id,                 /**< id of the node */
4130 	   int*                  perm,               /**< array of permuted indices */
4131 	   SCIP_VAR**            vars,               /**< variables */
4132 	   SCIP_Real*            vals,               /**< bounds */
4133 	   SCIP_BOUNDTYPE*       boundtypes,         /**< boundtypes */
4134 	   int                   nvars,              /**< number of variables */
4135 	   int                   negbndchg           /**< index of the variable that should negated */
4136 	   )
4137 	{
4138 	   SCIP_VAR* var;
4139 	   SCIP_Real val;
4140 	   SCIP_BOUNDTYPE boundtype;
4141 	   int nbndchgs;
4142 	
4143 	   assert(reopt != NULL);
4144 	   assert(set != NULL);
4145 	   assert(stat != NULL);
4146 	   assert(transprob != NULL);
4147 	   assert(origprob != NULL);
4148 	   assert(tree != NULL);
4149 	   assert(lp != NULL);
4150 	   assert(branchcand != NULL);
4151 	   assert(eventqueue != NULL);
4152 	   assert(cliquetable != NULL);
4153 	   assert(node != NULL);
4154 	   assert(perm != NULL);
4155 	   assert(vars != NULL);
4156 	   assert(vals != NULL);
4157 	   assert(boundtypes != NULL);
4158 	   assert(nvars >= 0);
4159 	   assert(blkmem != NULL);
4160 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
4161 	
4162 	#ifndef NDEBUG
4163 	   {
4164 	      SCIP_REOPTTREE* reopttree;
4165 	      SCIP_REOPTNODE* reoptnode;
4166 	
4167 	      reopttree = reopt->reopttree;
4168 	      assert(reopttree != NULL);
4169 	
4170 	      reoptnode = reopttree->reoptnodes[id];
4171 	      assert(reoptnode != NULL);
4172 	      assert(reoptnode->dualreds);
4173 	   }
4174 	#endif
4175 	
4176 	   nbndchgs = MIN(negbndchg, nvars);
4177 	
4178 	   /* change the first nbndchg-1 bounds as stored in dualredscur and negate the negbndchg-th bound */
4179 	   for( int v = 0; v < nbndchgs; ++v )
4180 	   {
4181 	      var = vars[perm[v]];
4182 	      val = vals[perm[v]];
4183 	      boundtype = boundtypes[perm[v]];
4184 	
4185 	      SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4186 	      assert(SCIPvarIsTransformedOrigvar(var));
4187 	
4188 	      /* negate the last bound change */
4189 	      if( v == nbndchgs-1 )
4190 	      {
4191 	         boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
4192 	         if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_UPPER )
4193 	            val = val - 1.0;
4194 	         else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_LOWER )
4195 	            val = val + 1.0;
4196 	      }
4197 	
4198 	      if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4199 	         && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4200 	      {
4201 	         SCIPvarAdjustLb(var, set, &val);
4202 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4203 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4204 	      }
4205 	      else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4206 	         && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4207 	      {
4208 	         SCIPvarAdjustUb(var, set, &val);
4209 	         SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4210 	               tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4211 	      }
4212 	      else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4213 	      {
4214 	         SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4215 	         return SCIP_INVALIDDATA;
4216 	      }
4217 	#ifdef SCIP_MORE_DEBUG
4218 	      SCIPsetDebugMsg(set, "  (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4219 	#endif
4220 	   }
4221 	
4222 	   return SCIP_OKAY;
4223 	}
4224 	
4225 	/** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
4226 	static
4227 	SCIP_RETCODE addLocalConss(
4228 	   SCIP*                 scip,               /**< SCIP data structure */
4229 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4230 	   SCIP_SET*             set,                /**< global SCIP settings */
4231 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4232 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4233 	   SCIP_NODE*            node,               /**< node of the branch and bound tree*/
4234 	   unsigned int          id                  /**< id of stored node */
4235 	   )
4236 	{
4237 	   char name[SCIP_MAXSTRLEN];
4238 	
4239 	   assert(scip != NULL);
4240 	   assert(reopt != NULL);
4241 	   assert(reopt->reopttree != NULL);
4242 	   assert(set != NULL);
4243 	   assert(stat != NULL);
4244 	   assert(blkmem != NULL);
4245 	   assert(node != NULL);
4246 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
4247 	
4248 	   if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
4249 	      return SCIP_OKAY;
4250 	
4251 	   SCIPsetDebugMsg(set, " -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss,
4252 	      SCIPnodeGetNumber(node));
4253 	
4254 	   for( int c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; ++c )
4255 	   {
4256 	      SCIP_CONS* cons;
4257 	      SCIP_REOPTCONSDATA* reoptconsdata;
4258 	
4259 	      reoptconsdata = reopt->reopttree->reoptnodes[id]->conss[c];
4260 	      assert(reoptconsdata != NULL);
4261 	      assert(reoptconsdata->nvars > 0);
4262 	      assert(reoptconsdata->varssize >= reoptconsdata->nvars);
4263 	
4264 	      if( reoptconsdata->constype == REOPT_CONSTYPE_CUT )
4265 	         continue;
4266 	
4267 	      if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
4268 	         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
4269 	      else if( reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS )
4270 	         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
4271 	      else
4272 	         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_unkn");
4273 	
4274 	      if( reoptconsdata->linear )
4275 	      {
4276 	         SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->vals,
4277 	            reoptconsdata->lhs, reoptconsdata->rhs, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4278 	      }
4279 	      else
4280 	      {
4281 	         assert(reoptconsdata->boundtypes != NULL);
4282 	         SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->boundtypes,
4283 	            reoptconsdata->vals, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4284 	      }
4285 	#ifdef SCIP_DEBUG_CONSS
4286 	      SCIPdebugPrintCons(scip, cons, NULL);
4287 	#endif
4288 	      SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
4289 	      SCIP_CALL( SCIPreleaseCons(scip, &cons) );
4290 	   }
4291 	
4292 	   return SCIP_OKAY;
4293 	}
4294 	
4295 	/** reset the internal statistics at the beginning of a new iteration */
4296 	static
4297 	void resetStats(
4298 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4299 	   )
4300 	{
4301 	   assert(reopt != NULL);
4302 	
4303 	   reopt->lastbranched = -1;
4304 	   reopt->currentnode = -1;
4305 	   reopt->lastseennode = -1;
4306 	   reopt->reopttree->nfeasnodes = 0;
4307 	   reopt->reopttree->ninfnodes = 0;
4308 	   reopt->reopttree->nprunednodes = 0;
4309 	   reopt->reopttree->ncutoffreoptnodes = 0;
4310 	
4311 	   if( reopt->dualreds != NULL )
4312 	      reopt->dualreds->nvars = 0;
4313 	}
4314 	
4315 	/** check the stored bound changes of all child nodes for redundancy and infeasibility
4316 	 *
4317 	 *  Due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
4318 	 *  child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
4319 	 *  method we remove all redundant bound changes and delete infeasible child nodes.
4320 	 */
4321 	static
4322 	SCIP_RETCODE dryBranch(
4323 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4324 	   SCIP_SET*             set,                /**< global SCIP settings */
4325 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4326 	   SCIP_Bool*            runagain,           /**< pointer to store of this method should run again */
4327 	   unsigned int          id                  /**< id of stored node */
4328 	   )
4329 	{
4330 	   SCIP_REOPTNODE* reoptnode;
4331 	   unsigned int* cutoffchilds;
4332 	   int ncutoffchilds = 0;
4333 	   unsigned int* redchilds;
4334 	   int nredchilds = 0;
4335 	   int c;
4336 	
4337 	   assert(reopt != NULL);
4338 	   assert(reopt->reopttree != NULL);
4339 	   assert(id < reopt->reopttree->reoptnodessize);
4340 	   assert(reopt->reopttree->reoptnodes != NULL);
4341 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
4342 	
4343 	   reoptnode = reopt->reopttree->reoptnodes[id];
4344 	
4345 	   *runagain = FALSE;
4346 	
4347 	   SCIPsetDebugMsg(set, "start dry branching of node at ID %u\n", id);
4348 	
4349 	   /* allocate buffer arrays */
4350 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
4351 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
4352 	
4353 	   /* iterate over all child nodes and check each bound changes
4354 	    * for redundancy and conflict */
4355 	   for( c = 0; c < reoptnode->nchilds; ++c )
4356 	   {
4357 	      SCIP_REOPTNODE* child;
4358 	      SCIP_Bool cutoff;
4359 	      SCIP_Bool redundant;
4360 	      int* redundantvars;
4361 	      int nredundantvars;
4362 	      unsigned int childid;
4363 	
4364 	      cutoff = FALSE;
4365 	      redundant = FALSE;
4366 	      nredundantvars = 0;
4367 	
4368 	      childid = reoptnode->childids[c];
4369 	      assert(childid < reopt->reopttree->reoptnodessize);
4370 	      child = reopt->reopttree->reoptnodes[childid];
4371 	      assert(child != NULL);
4372 	#ifdef SCIP_MORE_DEBUG
4373 	      SCIPsetDebugMsg(set, "-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
4374 	#endif
4375 	      if( child->nvars > 0 )
4376 	      {
4377 	         /* allocate buffer memory to store the redundant variables */
4378 	         SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
4379 	
4380 	         for( int v = 0; v < child->nvars && !cutoff; ++v )
4381 	         {
4382 	            SCIP_VAR* transvar;
4383 	            SCIP_Real transval;
4384 	            SCIP_BOUNDTYPE transbndtype;
4385 	            SCIP_Real ub;
4386 	            SCIP_Real lb;
4387 	
4388 	            transvar = child->vars[v];
4389 	            transval = child->varbounds[v];
4390 	            transbndtype = child->varboundtypes[v];
4391 	
4392 	            /* transform into the transformed space */
4393 	            SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
4394 	
4395 	            lb = SCIPvarGetLbLocal(transvar);
4396 	            ub = SCIPvarGetUbLocal(transvar);
4397 	
4398 	            /* check for infeasibility */
4399 	            if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
4400 	            {
4401 	               SCIPsetDebugMsg(set, " -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
4402 	                  SCIPvarGetName(transvar), lb, transval);
4403 	
4404 	               cutoff = TRUE;
4405 	               break;
4406 	            }
4407 	
4408 	            /* check for redundancy */
4409 	            if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
4410 	            {
4411 	               SCIPsetDebugMsg(set, " -> <%s> is already fixed to %g -> redundant bound change\n",
4412 	                  SCIPvarGetName(transvar), lb);
4413 	
4414 	               redundantvars[nredundantvars] = v;
4415 	               ++nredundantvars;
4416 	            }
4417 	         }
4418 	
4419 	         if( !cutoff && nredundantvars > 0 )
4420 	         {
4421 	            for( int v = 0; v < nredundantvars; ++v )
4422 	            {
4423 	               /* replace the redundant variable by the last stored variable */
4424 	               child->vars[redundantvars[v]] = child->vars[child->nvars-1];
4425 	               child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
4426 	               child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
4427 	               --child->nvars;
4428 	            }
4429 	         }
4430 	
4431 	         /* free buffer memory */
4432 	         SCIPsetFreeBufferArray(set, &redundantvars);
4433 	      }
4434 	      else if( child->nconss == 0 )
4435 	      {
4436 	         redundant = TRUE;
4437 	         SCIPsetDebugMsg(set, " -> redundant node found.\n");
4438 	      }
4439 	
4440 	      if( cutoff )
4441 	      {
4442 	         cutoffchilds[ncutoffchilds] = childid;
4443 	         ++ncutoffchilds;
4444 	      }
4445 	      else if( redundant )
4446 	      {
4447 	         redchilds[nredchilds] = childid;
4448 	         ++nredchilds;
4449 	      }
4450 	   }
4451 	
4452 	   SCIPsetDebugMsg(set, "-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
4453 	
4454 	   /* delete all nodes that can be cut off */
4455 	   while( ncutoffchilds > 0 )
4456 	   {
4457 	      /* delete the node and the induced subtree */
4458 	      SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
4459 	
4460 	      /* find the position in the childid array */
4461 	      c = 0;
4462 	      while( reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] && c < reoptnode->nchilds )
4463 	         ++c;
4464 	      assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
4465 	
4466 	      /* replace the ID at position c by the last ID */
4467 	      reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4468 	      --reoptnode->nchilds;
4469 	
4470 	      /* decrease the number of nodes to cutoff */
4471 	      --ncutoffchilds;
4472 	   }
4473 	
4474 	   /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
4475 	   while( nredchilds > 0 )
4476 	   {
4477 	      /* find the position in the childid array */
4478 	      c = 0;
4479 	      while( reoptnode->childids[c] != redchilds[nredchilds-1] && c < reoptnode->nchilds )
4480 	         ++c;
4481 	      assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
4482 	
4483 	      /* the node is a leaf and we can cutoff them  */
4484 	      if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
4485 	      {
4486 	         /* delete the node and the induced subtree */
4487 	         SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
4488 	
4489 	         /* replace the ID at position c by the last ID */
4490 	         reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4491 	         --reoptnode->nchilds;
4492 	
4493 	         /* decrease the number of redundant nodes */
4494 	         --nredchilds;
4495 	      }
4496 	      else
4497 	      {
4498 	         int ncc;
4499 	
4500 	         /* replace the ID at position c by the last ID */
4501 	         reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4502 	         --reoptnode->nchilds;
4503 	
4504 	         ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
4505 	
4506 	         /* check the memory */
4507 	         SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, 0, reoptnode->nchilds+ncc, 0) );
4508 	
4509 	         /* add all IDs of child nodes to the current node */
4510 	         for( int cc = 0; cc < ncc; ++cc )
4511 	         {
4512 	            reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
4513 	            ++reoptnode->nchilds;
4514 	         }
4515 	
4516 	         /* delete the redundant node */
4517 	         SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
4518 	         SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, redchilds[nredchilds-1]) );
4519 	
4520 	         /* decrease the number of redundant nodes */
4521 	         --nredchilds;
4522 	
4523 	         /* update the flag to rerun this method */
4524 	         *runagain = TRUE;
4525 	      }
4526 	   }
4527 	
4528 	   /* free buffer arrays */
4529 	   SCIPsetFreeBufferArray(set, &redchilds);
4530 	   SCIPsetFreeBufferArray(set, &cutoffchilds);
4531 	
4532 	   return SCIP_OKAY;
4533 	}
4534 	
4535 	/** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
4536 	static
4537 	int reopttreeGetNNodes(
4538 	   SCIP_REOPTTREE*       reopttree,          /**< reopttree */
4539 	   unsigned int          id                  /**< id of stored node */
4540 	   )
4541 	{
4542 	   int nnodes = 0;
4543 	
4544 	   assert(reopttree != NULL);
4545 	   assert(id < reopttree->reoptnodessize);
4546 	
4547 	   for( int i = 0; i < reopttree->reoptnodes[id]->nchilds; ++i )
4548 	      nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
4549 	
4550 	   return nnodes + 1;
4551 	}
4552 	
4553 	/** returns the number of leaf nodes of the induced subtree */
4554 	static
4555 	int reoptGetNLeaves(
4556 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4557 	   unsigned int          id                  /**< id of stored node */
4558 	   )
4559 	{
4560 	   int nleaves = 0;
4561 	
4562 	   assert(reopt != NULL);
4563 	   assert(id < reopt->reopttree->reoptnodessize);
4564 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
4565 	
4566 	   /* iterate over all child nods and check whether they are leaves or not */
4567 	   for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
4568 	   {
4569 	      unsigned int childid;
4570 	
4571 	      childid = reopt->reopttree->reoptnodes[id]->childids[i];
4572 	      assert(childid < reopt->reopttree->reoptnodessize);
4573 	
4574 	      if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4575 	         ++nleaves;
4576 	      else
4577 	         nleaves += reoptGetNLeaves(reopt, childid);
4578 	   }
4579 	
4580 	   return nleaves;
4581 	}
4582 	
4583 	/** returns all leaves of the subtree induced by the node stored at @p id*/
4584 	static
4585 	SCIP_RETCODE reoptGetLeaves(
4586 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure*/
4587 	   unsigned int          id,                 /**< id of stored node */
4588 	   unsigned int*         leaves,             /**< array of leave nodes */
4589 	   int                   leavessize,         /**< size of leaves array */
4590 	   int*                  nleaves             /**< pointer to store the number of leave nodes */
4591 	   )
4592 	{
4593 	   assert(reopt != NULL);
4594 	   assert(leavessize > 0 && leaves != NULL);
4595 	   assert((*nleaves) >= 0);
4596 	   assert(id < reopt->reopttree->reoptnodessize);
4597 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
4598 	
4599 	   for( int i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
4600 	   {
4601 	      unsigned int childid;
4602 	
4603 	      assert(*nleaves <= leavessize);
4604 	
4605 	      childid = reopt->reopttree->reoptnodes[id]->childids[i];
4606 	      assert(childid < reopt->reopttree->reoptnodessize);
4607 	
4608 	      if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4609 	      {
4610 	         leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
4611 	         ++l;
4612 	         ++(*nleaves);
4613 	      }
4614 	      else
4615 	      {
4616 	         int nleaves2 = 0;
4617 	
4618 	         SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
4619 	         l += nleaves2;
4620 	         (*nleaves) += nleaves2;
4621 	      }
4622 	   }
4623 	
4624 	   return SCIP_OKAY;
4625 	}
4626 	
4627 	/** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
4628 	static
4629 	SCIP_RETCODE reoptResetTree(
4630 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4631 	   SCIP_SET*             set,                /**< global SCIP settings */
4632 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4633 	   SCIP_Bool             softreset           /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
4634 	   )
4635 	{
4636 	   assert(reopt != NULL);
4637 	   assert(set != NULL);
4638 	   assert(blkmem != NULL);
4639 	
4640 	   /* clear the tree */
4641 	   SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
4642 	   assert(reopt->reopttree->nreoptnodes == 0);
4643 	
4644 	   /* reset the dual constraint */
4645 	   if( reopt->dualreds != NULL )
4646 	      reopt->dualreds->nvars = 0;
4647 	
4648 	   reopt->currentnode = -1;
4649 	
4650 	   return SCIP_OKAY;
4651 	}
4652 	
4653 	/** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
4654 	static
4655 	SCIP_RETCODE reoptRestart(
4656 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4657 	   SCIP_SET*             set,                /**< global SCIP settings */
4658 	   BMS_BLKMEM*           blkmem              /**< block memory */
4659 	   )
4660 	{
4661 	   assert(reopt != NULL);
4662 	   assert(reopt->reopttree != NULL);
4663 	   assert(set != NULL);
4664 	   assert(blkmem != NULL);
4665 	
4666 	   /* clear the tree */
4667 	   SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
4668 	   assert(reopt->reopttree->nreoptnodes == 0);
4669 	
4670 	   /* allocate memory for the root node */
4671 	   SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
4672 	
4673 	   reopt->nglbrestarts += 1;
4674 	
4675 	   if( reopt->firstrestart == -1 )
4676 	      reopt->firstrestart = reopt->run;
4677 	
4678 	   reopt->lastrestart = reopt->run;
4679 	
4680 	   return SCIP_OKAY;
4681 	}
4682 	
4683 	/** save the new objective function */
4684 	static
4685 	SCIP_RETCODE reoptSaveNewObj(
4686 	   SCIP_REOPT*           reopt,              /**< reoptimization data */
4687 	   SCIP_SET*             set,                /**< global SCIP settings */
4688 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4689 	   SCIP_VAR**            origvars,           /**< original problem variables */
4690 	   int                   norigvars           /**< number of original problem variables */
4691 	   )
4692 	{
4693 	   int probidx;
4694 	
4695 	   assert(reopt != NULL);
4696 	   assert(set != NULL);
4697 	   assert(blkmem != NULL);
4698 	   assert(origvars != NULL);
4699 	   assert(norigvars >= 0);
4700 	
4701 	   /* check memory */
4702 	   SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
4703 	
4704 	   /* get memory and check whether we have to resize all previous objectives */
4705 	   if( reopt->nobjvars < norigvars )
4706 	   {
4707 	      for( int i = 0; i < reopt->run-1; ++i )
4708 	      {
4709 	         SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], norigvars) ); /*lint !e866*/
4710 	         for( int v = reopt->nobjvars-1; v < norigvars; ++v )
4711 	            reopt->objs[i][v] = 0.0;
4712 	      }
4713 	      reopt->nobjvars = norigvars;
4714 	   }
4715 	   SCIP_ALLOC( BMSallocClearMemoryArray(&reopt->objs[reopt->run-1], reopt->nobjvars) ); /*lint !e866*/
4716 	
4717 	   /* save coefficients */
4718 	   for( int v = 0; v < norigvars; ++v )
4719 	   {
4720 	      assert(SCIPvarIsOriginal(origvars[v]));
4721 	
4722 	      probidx = SCIPvarGetIndex(origvars[v]);
4723 	
4724 	      /* it can happen that the index is greater than the number of problem variables,
4725 	       * i.e., not all created variables were added
4726 	       */
4727 	      if( probidx >= reopt->nobjvars )
4728 	      {
4729 	         int newsize = SCIPsetCalcMemGrowSize(set, probidx+1);
4730 	         for( int i = 0; i < reopt->run; ++i )
4731 	         {
4732 	            SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], newsize) ); /*lint !e866*/
4733 	            for( int j = reopt->nobjvars; j < newsize; ++j )
4734 	               reopt->objs[i][j] = 0.0;
4735 	         }
4736 	         reopt->nobjvars = newsize;
4737 	      }
4738 	      assert(0 <= probidx && probidx < reopt->nobjvars);
4739 	
4740 	      reopt->objs[reopt->run-1][probidx] = SCIPvarGetObj(origvars[v]);
4741 	
4742 	      /* update flag to remember if the objective function has changed */
4743 	      if( !reopt->objhaschanged && reopt->run >= 2
4744 	          && ! SCIPsetIsEQ(set, reopt->objs[reopt->run-2][probidx], reopt->objs[reopt->run-1][probidx]) )
4745 	         reopt->objhaschanged = TRUE;
4746 	
4747 	      /* mark this objective as the first non empty */
4748 	      if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][probidx] != 0 )
4749 	         reopt->firstobj = reopt->run-1;
4750 	   }
4751 	
4752 	   /* calculate similarity to last objective */
4753 	   if( reopt->run-1 >= 1 )
4754 	   {
4755 	      /* calculate similarity to last objective */
4756 	      reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, origvars, norigvars);
4757 	
4758 	      if( reopt->simtolastobj == SCIP_INVALID )  /*lint !e777*/
4759 	         return SCIP_INVALIDRESULT;
4760 	
4761 	      SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "new objective has similarity of %g compared to previous.\n",
4762 	         reopt->simtolastobj);
4763 	   }
4764 	
4765 	   SCIPsetDebugMsg(set, "saved obj for run %d.\n", reopt->run);
4766 	
4767 	   return SCIP_OKAY;
4768 	}
4769 	
4770 	/** orders the variable by inference score */
4771 	static
4772 	SCIP_RETCODE getInferenceOrder(
4773 	   SCIP_SET*             set,                /**< global SCIP settings */
4774 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
4775 	   int*                  perm,               /**< array of indices that need to be permuted */
4776 	   SCIP_VAR**            vars,               /**< variable array to permute */
4777 	   SCIP_Real*            bounds,             /**< bound array to permute in the same order */
4778 	   SCIP_BOUNDTYPE*       boundtypes,         /**< boundtype array to permute in the same order */
4779 	   int                   nvars               /**< number of variables */
4780 	   )
4781 	{
4782 	   SCIP_Real* infscore;
4783 	
4784 	   assert(set != NULL);
4785 	   assert(perm != NULL);
4786 	   assert(vars != NULL);
4787 	   assert(bounds != NULL);
4788 	   assert(boundtypes != NULL);
4789 	   assert(nvars >= 0);
4790 	
4791 	   /* allocate buffer for the scores */
4792 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &infscore, nvars) );
4793 	
4794 	   for( int v = 0; v < nvars; ++v )
4795 	   {
4796 	      if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
4797 	      {
4798 	         infscore[v] = 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4799 	            + 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4800 	      }
4801 	      else
4802 	      {
4803 	         infscore[v] = 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4804 	               + 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4805 	      }
4806 	   }
4807 	
4808 	   /* permute indices by inference score */
4809 	   SCIPsortDownRealInt(infscore, perm, nvars);
4810 	
4811 	   /* free buffer */
4812 	   SCIPsetFreeBufferArray(set, &infscore);
4813 	
4814 	   return SCIP_OKAY;
4815 	}
4816 	
4817 	/** create a global constraint to separate the given solution */
4818 	static
4819 	SCIP_RETCODE separateSolution(
4820 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
4821 	   BMS_BLKMEM*           blkmem,             /**< block memory */
4822 	   SCIP_SET*             set,                /**< global SCIP settings */
4823 	   SCIP_STAT*            stat,               /**< dynamic SCIP statistics */
4824 	   SCIP_SOL*             sol,                /**< solution to separate */
4825 	   SCIP_VAR**            vars,               /**< array of original problem variables */
4826 	   int                   nvars               /**< number of original problem variables */
4827 	   )
4828 	{
4829 	   SCIP_VAR** origvars;
4830 	   SCIP_Real* vals;
4831 	   int nintvars;
4832 	   int nbinvars;
4833 	   int w;
4834 	
4835 	   assert(reopt != NULL);
4836 	   assert(sol != NULL);
4837 	   assert(blkmem != NULL);
4838 	   assert(set != NULL);
4839 	   assert(stat != NULL);
4840 	   assert(vars != NULL);
4841 	   assert(nvars != 0);
4842 	   assert(SCIPsolIsOriginal(sol));
4843 	
4844 	   /* allocate buffer memory */
4845 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &origvars, nvars) );
4846 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
4847 	
4848 	   nbinvars = 0;
4849 	   nintvars = 0;
4850 	   w = 0;
4851 	
4852 	   /* get the solution values of the variables */
4853 	   for( int v = 0; v < nvars; ++v )
4854 	   {
4855 	      assert(SCIPvarIsOriginal(vars[v]));
4856 	      assert(nbinvars + nintvars == w);
4857 	
4858 	      /* we do not want to create cuts for continous variables */
4859 	      if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4860 	         continue;
4861 	
4862 	      if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
4863 	         ++nbinvars;
4864 	      if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_IMPLINT )
4865 	         ++nintvars;
4866 	
4867 	      origvars[v] = vars[v];
4868 	      assert(origvars[v] != NULL);
4869 	      assert(SCIPvarIsOriginal(origvars[v]));
4870 	
4871 	      vals[w] = SCIPsolGetVal(sol, set, stat, origvars[v]);
4872 	      ++w;
4873 	   }
4874 	
4875 	   SCIP_CALL( addGlobalCut(reopt, blkmem, set, origvars, vals, NULL, w, nbinvars, nintvars) );
4876 	
4877 	   /* free buffer memory */
4878 	   SCIPsetFreeBufferArray(set, &vals);
4879 	   SCIPsetFreeBufferArray(set, &origvars);
4880 	
4881 	   return SCIP_OKAY;
4882 	}
4883 	
4884 	/*
4885 	 * public methods
4886 	 */
4887 	
4888 	/* ---------------- methods of general reoptimization ---------------- */
4889 	
4890 	/* In debug mode, the following methods are implemented as function calls to ensure
4891 	 * type validity.
4892 	 * In optimized mode, the methods are implemented as defines to improve performance.
4893 	 * However, we want to have them in the library anyways, so we have to undef the defines.
4894 	 */
4895 	
4896 	#undef SCIPreoptGetNRestartsGlobal
4897 	#undef SCIPreoptGetNRestartsLocal
4898 	#undef SCIPreoptGetNTotalRestartsLocal
4899 	#undef SCIPreoptGetFirstRestarts
4900 	#undef SCIPreoptGetLastRestarts
4901 	#undef SCIPreoptGetNFeasNodes
4902 	#undef SCIPreoptGetNTotalFeasNodes
4903 	#undef SCIPreoptGetNPrunedNodes
4904 	#undef SCIPreoptGetNTotalPrunedNodes
4905 	#undef SCIPreoptGetNCutoffReoptnodes
4906 	#undef SCIPreoptGetNTotalCutoffReoptnodes
4907 	#undef SCIPreoptGetNInfNodes
4908 	#undef SCIPreoptGetNTotalInfNodes
4909 	#undef SCIPreoptGetNInfSubtrees
4910 	
4911 	
4912 	/** returns the number of global restarts */
4913 	int SCIPreoptGetNRestartsGlobal(
4914 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4915 	   )
4916 	{
4917 	   assert(reopt != NULL);
4918 	
4919 	   return reopt->nglbrestarts;
4920 	}
4921 	
4922 	/** returns the number of local restarts in the current run */
4923 	int SCIPreoptGetNRestartsLocal(
4924 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4925 	   )
4926 	{
4927 	   assert(reopt != NULL);
4928 	
4929 	   return reopt->nlocrestarts;
4930 	}
4931 	
4932 	/** returns the number of local restarts over all runs */
4933 	int SCIPreoptGetNTotalRestartsLocal(
4934 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4935 	   )
4936 	{
4937 	   assert(reopt != NULL);
4938 	
4939 	   return reopt->ntotallocrestarts;
4940 	}
4941 	
4942 	/** returns the number of iteration with the first global restarts */
4943 	int SCIPreoptGetFirstRestarts(
4944 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4945 	   )
4946 	{
4947 	   assert(reopt != NULL);
4948 	
4949 	   return reopt->firstrestart;
4950 	}
4951 	
4952 	/** returns the number of iteration with the last global restarts */
4953 	int SCIPreoptGetLastRestarts(
4954 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4955 	   )
4956 	{
4957 	   assert(reopt != NULL);
4958 	
4959 	   return reopt->lastrestart;
4960 	}
4961 	
4962 	/** returns the number of stored nodes providing an improving feasible LP solution in the current run */
4963 	int SCIPreoptGetNFeasNodes(
4964 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4965 	   )
4966 	{
4967 	   assert(reopt != NULL);
4968 	
4969 	   return reopt->reopttree->nfeasnodes;
4970 	}
4971 	
4972 	/** returns the number of stored nodes providing an improving feasible LP solution over all runs */
4973 	int SCIPreoptGetNTotalFeasNodes(
4974 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4975 	   )
4976 	{
4977 	   assert(reopt != NULL);
4978 	
4979 	   return reopt->reopttree->ntotalfeasnodes;
4980 	}
4981 	
4982 	/** returns the number of stored nodes that exceeded the cutoff bound in the current run */
4983 	int SCIPreoptGetNPrunedNodes(
4984 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4985 	   )
4986 	{
4987 	   assert(reopt != NULL);
4988 	
4989 	   return reopt->reopttree->nprunednodes;
4990 	}
4991 	
4992 	/** returns the number of stored nodes that exceeded the cutoff bound over all runs */
4993 	int SCIPreoptGetNTotalPrunedNodes(
4994 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
4995 	   )
4996 	{
4997 	   assert(reopt != NULL);
4998 	
4999 	   return reopt->reopttree->ntotalprunednodes;
5000 	}
5001 	
5002 	/** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
5003 	int SCIPreoptGetNCutoffReoptnodes(
5004 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5005 	   )
5006 	{
5007 	   assert(reopt != NULL);
5008 	
5009 	   return reopt->reopttree->ncutoffreoptnodes;
5010 	}
5011 	
5012 	/** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
5013 	int SCIPreoptGetNTotalCutoffReoptnodes(
5014 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5015 	   )
5016 	{
5017 	   assert(reopt != NULL);
5018 	
5019 	   return reopt->reopttree->ntotalcutoffreoptnodes;
5020 	}
5021 	
5022 	/** returns the number of stored nodes with an infeasible LP in the current run */
5023 	int SCIPreoptGetNInfNodes(
5024 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5025 	   )
5026 	{
5027 	   assert(reopt != NULL);
5028 	
5029 	   return reopt->reopttree->ninfnodes;
5030 	}
5031 	
5032 	/** returns the number of stored nodes with an infeasible LP over all runs */
5033 	int SCIPreoptGetNTotalInfNodes(
5034 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5035 	   )
5036 	{
5037 	   assert(reopt != NULL);
5038 	
5039 	   return reopt->reopttree->ntotalinfnodes;
5040 	}
5041 	
5042 	/** constructor for the reoptimization data */
5043 	SCIP_RETCODE SCIPreoptCreate(
5044 	   SCIP_REOPT**          reopt,              /**< pointer to reoptimization data structure */
5045 	   SCIP_SET*             set,                /**< global SCIP settings */
5046 	   BMS_BLKMEM*           blkmem              /**< block memory */
5047 	   )
5048 	{
5049 	   SCIP_EVENTHDLR* eventhdlr;
5050 	
5051 	   assert(reopt != NULL);
5052 	
5053 	   SCIP_ALLOC( BMSallocMemory(reopt) );
5054 	   (*reopt)->runsize = DEFAULT_MEM_RUN;
5055 	   (*reopt)->run = 0;
5056 	   (*reopt)->simtolastobj = -2.0;
5057 	   (*reopt)->simtofirstobj = -2.0;
5058 	   (*reopt)->firstobj = -1;
5059 	   (*reopt)->currentnode = -1;
5060 	   (*reopt)->lastbranched = -1;
5061 	   (*reopt)->dualreds = NULL;
5062 	   (*reopt)->glbconss = NULL;
5063 	   (*reopt)->nglbconss = 0;
5064 	   (*reopt)->allocmemglbconss = 0;
5065 	   (*reopt)->ncheckedsols = 0;
5066 	   (*reopt)->nimprovingsols = 0;
5067 	   (*reopt)->noptsolsbyreoptsol = 0;
5068 	   (*reopt)->nglbrestarts = 0;
5069 	   (*reopt)->nlocrestarts = 0;
5070 	   (*reopt)->ntotallocrestarts = 0;
5071 	   (*reopt)->firstrestart = -1;
5072 	   (*reopt)->lastrestart = 0;
5073 	   (*reopt)->nobjvars = 0;
5074 	   (*reopt)->objhaschanged = FALSE;
5075 	   (*reopt)->consadded = FALSE;
5076 	   (*reopt)->addedconss = NULL;
5077 	   (*reopt)->naddedconss = 0;
5078 	   (*reopt)->addedconsssize = 0;
5079 	   (*reopt)->glblb = NULL;
5080 	   (*reopt)->glbub = NULL;
5081 	   (*reopt)->nactiveconss = 0;
5082 	   (*reopt)->nmaxactiveconss = 0;
5083 	   (*reopt)->activeconss = NULL;
5084 	   (*reopt)->activeconssset = NULL;
5085 	
5086 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize) );
5087 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
5088 	   SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
5089 	
5090 	   for( int i = 0; i < (*reopt)->runsize; ++i )
5091 	   {
5092 	      (*reopt)->objs[i] = NULL;
5093 	      (*reopt)->prevbestsols[i] = NULL;
5094 	      (*reopt)->varhistory[i] = NULL;
5095 	   }
5096 	
5097 	   /* clocks */
5098 	   SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
5099 	
5100 	   /* create and initialize SCIP_SOLTREE */
5101 	   SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
5102 	   SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
5103 	
5104 	   /* create and initialize SCIP_REOPTTREE */
5105 	   SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
5106 	   SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
5107 	
5108 	   /* create a random number generator */
5109 	   SCIP_CALL( SCIPrandomCreate(&(*reopt)->randnumgen, blkmem, (unsigned int)SCIPsetInitializeRandomSeed(set, DEFAULT_RANDSEED)) );
5110 	
5111 	   /* create event handler for node events */
5112 	   eventhdlr = NULL;
5113 	
5114 	   /* include event handler into SCIP */
5115 	   SCIP_CALL( SCIPeventhdlrCreate(&eventhdlr, set, EVENTHDLR_NAME, EVENTHDLR_DESC, NULL, NULL, NULL, NULL,
5116 	      eventInitsolReopt, eventExitsolReopt, NULL, eventExecReopt, NULL) );
5117 	   SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
5118 	   assert(eventhdlr != NULL);
5119 	
5120 	   return SCIP_OKAY;
5121 	}
5122 	
5123 	/* release all variables and constraints captured during reoptimization */
5124 	SCIP_RETCODE SCIPreoptReleaseData(
5125 	   SCIP_REOPT*           reopt,              /**< pointer to reoptimization data structure */
5126 	   SCIP_SET*             set,                /**< global SCIP settings */
5127 	   BMS_BLKMEM*           blkmem              /**< block memory */
5128 	   )
5129 	{
5130 	   /* release all added constraints and free the data */
5131 	   if( reopt->addedconss != NULL )
5132 	   {
5133 	      for( int c = 0; c < reopt->naddedconss; ++c )
5134 	      {
5135 	         assert(reopt->addedconss[c] != NULL);
5136 	
5137 	         SCIP_CALL( SCIPconsRelease(&reopt->addedconss[c], blkmem, set) );
5138 	      }
5139 	
5140 	      BMSfreeBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize);
5141 	      reopt->naddedconss = 0;
5142 	      reopt->addedconsssize = 0;
5143 	   }
5144 	
5145 	   SCIP_CALL( cleanActiveConss(reopt, set, blkmem) );
5146 	
5147 	   return SCIP_OKAY;
5148 	}
5149 	
5150 	/** frees reoptimization data */
5151 	SCIP_RETCODE SCIPreoptFree(
5152 	   SCIP_REOPT**          reopt,              /**< reoptimization data structure */
5153 	   SCIP_SET*             set,                /**< global SCIP settings */
5154 	   SCIP_PRIMAL*          origprimal,         /**< original primal */
5155 	   BMS_BLKMEM*           blkmem              /**< block memory */
5156 	   )
5157 	{
5158 	   assert(reopt != NULL);
5159 	   assert(*reopt != NULL);
5160 	   assert(set != NULL);
5161 	   assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
5162 	   assert(blkmem != NULL);
5163 	
5164 	   /* free random number generator */
5165 	   SCIPrandomFree(&(*reopt)->randnumgen, blkmem);
5166 	
5167 	   /* free reopttree */
5168 	   SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
5169 	
5170 	   /* free solutions and variable histories */
5171 	   if( set->stage >= SCIP_STAGE_PROBLEM )
5172 	   {
5173 	      for( int p = (*reopt)->run-1; p >= 0; --p )
5174 	      {
5175 	         if( (*reopt)->soltree->sols[p] != NULL )
5176 	         {
5177 	            BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
5178 	            (*reopt)->soltree->sols[p] = NULL;
5179 	         }
5180 	
5181 	         if( set->reopt_storevarhistory && (*reopt)->varhistory[p] != NULL )
5182 	         {
5183 	            for( int v = SCIPgetNOrigVars(set->scip)-1; v >= 0; --v )
5184 	            {
5185 	               SCIPhistoryFree(&(*reopt)->varhistory[p][v], blkmem);
5186 	            }
5187 	
5188 	            BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory[p], SCIPgetNOrigVars(set->scip));
5189 	            (*reopt)->varhistory[p] = NULL;
5190 	         }
5191 	
5192 	         /* we have to free all optimal solution separatly, because those solutions are not stored in the
5193 	          * solution reopt_sepabestsol = TRUE
5194 	          */
5195 	         if( set->reopt_sepabestsol && (*reopt)->prevbestsols[p] != NULL )
5196 	         {
5197 	            SCIP_CALL( SCIPsolFree(&(*reopt)->prevbestsols[p], blkmem, origprimal) );
5198 	         }
5199 	
5200 	         if( (*reopt)->objs[p] != NULL )
5201 	         {
5202 	            BMSfreeMemoryArray(&(*reopt)->objs[p]);
5203 	         }
5204 	      }
5205 	   }
5206 	
5207 	   /* free solution tree */
5208 	   SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
5209 	
5210 	   if( (*reopt)->dualreds != NULL )
5211 	   {
5212 	      if( (*reopt)->dualreds->varssize > 0 )
5213 	      {
5214 	         assert(!(*reopt)->dualreds->linear);
5215 	
5216 	         BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->boundtypes, (*reopt)->dualreds->varssize);
5217 	         BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vals, (*reopt)->dualreds->varssize);
5218 	         BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vars, (*reopt)->dualreds->varssize);
5219 	         BMSfreeBlockMemory(blkmem, &(*reopt)->dualreds);
5220 	         (*reopt)->dualreds = NULL;
5221 	      }
5222 	   }
5223 	
5224 	   if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
5225 	   {
5226 	      /* free all constraint */
5227 	      for( int c = 0; c < (*reopt)->allocmemglbconss; ++c )
5228 	      {
5229 	         if( (*reopt)->glbconss[c] != NULL )
5230 	         {
5231 	            if( (*reopt)->glbconss[c]->varssize > 0 )
5232 	            {
5233 	               BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->boundtypes, (*reopt)->glbconss[c]->varssize);
5234 	               BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
5235 	               BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
5236 	               (*reopt)->glbconss[c]->varssize = 0;
5237 	            }
5238 	            BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
5239 	            --(*reopt)->nglbconss;
5240 	         }
5241 	      }
5242 	      assert((*reopt)->nglbconss == 0);
5243 	
5244 	      BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
5245 	      (*reopt)->allocmemglbconss = 0;
5246 	   }
5247 	
5248 	   /* clocks */
5249 	   SCIPclockFree(&(*reopt)->savingtime);
5250 	
5251 	   /* the hashmap need not to be exist, e.g., if the problem was solved during presolving */
5252 	   if( (*reopt)->activeconssset != NULL )
5253 	   {
5254 	      SCIPhashsetFree(&(*reopt)->activeconssset, blkmem);
5255 	   }
5256 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*reopt)->activeconss, (*reopt)->nmaxactiveconss);
5257 	
5258 	   if( (*reopt)->glblb != NULL )
5259 	   {
5260 	      SCIPhashmapFree(&(*reopt)->glblb);
5261 	      SCIPhashmapFree(&(*reopt)->glbub);
5262 	      (*reopt)->glblb = NULL;
5263 	      (*reopt)->glbub = NULL;
5264 	   }
5265 	   else
5266 	      assert((*reopt)->glbub == NULL);
5267 	
5268 	   BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize);
5269 	   BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
5270 	   BMSfreeMemoryArray(&(*reopt)->objs);
5271 	   BMSfreeMemory(reopt);
5272 	
5273 	   return SCIP_OKAY;
5274 	}
5275 	
5276 	/** returns the number of constraints added by the reoptimization plug-in */
5277 	int SCIPreoptGetNAddedConss(
5278 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5279 	   SCIP_NODE*            node                /**< node of the search tree */
5280 	   )
5281 	{
5282 	   unsigned int id;
5283 	
5284 	   assert(reopt != NULL);
5285 	   assert(node != NULL);
5286 	
5287 	   id = SCIPnodeGetReoptID(node);
5288 	   assert(id < reopt->reopttree->reoptnodessize);
5289 	
5290 	   /* set the id to -1 if the node is not part of the reoptimization tree */
5291 	   if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5292 	      return SCIPnodeGetNAddedConss(node);
5293 	
5294 	   if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
5295 	      return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
5296 	   else
5297 	      return SCIPnodeGetNAddedConss(node);
5298 	}
5299 	
5300 	/** add a solution to the solution tree */
5301 	SCIP_RETCODE SCIPreoptAddSol(
5302 	   SCIP_REOPT*           reopt,              /**< reoptimization data */
5303 	   SCIP_SET*             set,                /**< global SCIP settings */
5304 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
5305 	   SCIP_PRIMAL*          origprimal,         /**< original primal */
5306 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5307 	   SCIP_SOL*             sol,                /**< solution to add */
5308 	   SCIP_Bool             bestsol,            /**< is the current solution an optimal solution? */
5309 	   SCIP_Bool*            added,              /**< pointer to store the information if the soltion was added */
5310 	   SCIP_VAR**            vars,               /**< variable array */
5311 	   int                   nvars,              /**< number of variables */
5312 	   int                   run                 /**< number of the current run (1,2,...) */
5313 	   )
5314 	{
5315 	   SCIP_SOLNODE* solnode = NULL;
5316 	   SCIP_HEUR* heur;
5317 	   int insertpos;
5318 	
5319 	   assert(reopt != NULL);
5320 	   assert(set != NULL);
5321 	   assert(sol != NULL);
5322 	   assert(run > 0);
5323 	
5324 	   assert(reopt->soltree->sols[run-1] != NULL);
5325 	
5326 	   /* if the solution was found by reoptsols the solutions is already stored */
5327 	   heur = SCIPsolGetHeur(sol);
5328 	   if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
5329 	      ++reopt->noptsolsbyreoptsol;
5330 	   else if( bestsol )
5331 	      reopt->noptsolsbyreoptsol = 0;
5332 	
5333 	   /* check memory */
5334 	   SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1]+1, run-1) );
5335 	
5336 	   /* add solution to solution tree */
5337 	   SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
5338 	
5339 	   if( (*added) )
5340 	   {
5341 	      assert(solnode != NULL);
5342 	
5343 	      /* add solution */
5344 	      insertpos = reopt->soltree->nsols[run-1];
5345 	      reopt->soltree->sols[run-1][insertpos] = solnode;
5346 	      ++reopt->soltree->nsols[run-1];
5347 	      assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
5348 	   }
5349 	
5350 	   return SCIP_OKAY;
5351 	}
5352 	
5353 	/** we want to store the optimal solution of each run in a separate array */
5354 	SCIP_RETCODE SCIPreoptAddOptSol(
5355 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5356 	   SCIP_SOL*             sol,                /**< solution to add */
5357 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5358 	   SCIP_SET*             set,                /**< global SCIP settings */
5359 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
5360 	   SCIP_PRIMAL*          origprimal,         /**< original primal */
5361 	   SCIP_VAR**            vars,               /**< original problem variables */
5362 	   int                   nvars               /**< number of original problem variables */
5363 	   )
5364 	{
5365 	   /* cppcheck-suppress unassignedVariable */
5366 	   SCIP_SOL* solcopy;
5367 	
5368 	   assert(reopt != NULL);
5369 	   assert(reopt->run-1 >= 0);
5370 	   assert(sol != NULL);
5371 	   assert(blkmem != NULL);
5372 	   assert(set != NULL);
5373 	   assert(stat != NULL);
5374 	   assert(origprimal != NULL);
5375 	
5376 	   SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
5377 	   reopt->prevbestsols[reopt->run-1] = solcopy;
5378 	
5379 	   /* store a global constraint that cutsoff the solution */
5380 	   if( set->reopt_sepabestsol )
5381 	   {
5382 	      SCIP_CALL( separateSolution(reopt, blkmem, set, stat, sol, vars, nvars) );
5383 	   }
5384 	
5385 	   return SCIP_OKAY;
5386 	}
5387 	
5388 	/** add a new iteration after changing the objective function */
5389 	SCIP_RETCODE SCIPreoptAddRun(
5390 	   SCIP_REOPT*           reopt,              /**< reoptimization data sturcture */
5391 	   SCIP_SET*             set,                /**< global SCIP settings */
5392 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5393 	   SCIP_VAR**            origvars,           /**< original problem variables */
5394 	   int                   norigvars,          /**< number of original variables */
5395 	   int                   size                /**< number of expected solutions */
5396 	   )
5397 	{
5398 	   assert(reopt != NULL);
5399 	   assert(set != NULL);
5400 	   assert(blkmem !=  NULL);
5401 	   assert(origvars != NULL);
5402 	
5403 	   /* increase number of runs */
5404 	   ++reopt->run;
5405 	
5406 	   /* check memory */
5407 	   SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
5408 	
5409 	   /* allocate memory */
5410 	   reopt->soltree->solssize[reopt->run-1] = size;
5411 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
5412 	
5413 	   /* reset flag */
5414 	   reopt->objhaschanged = FALSE;
5415 	
5416 	   /* save the objective function */
5417 	   SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, origvars, norigvars) );
5418 	
5419 	   resetStats(reopt);
5420 	
5421 	   return SCIP_OKAY;
5422 	}
5423 	
5424 	/** get the number of checked solutions during the reoptimization process */
5425 	int SCIPreoptGetNCheckedSols(
5426 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5427 	   )
5428 	{
5429 	   assert(reopt != NULL);
5430 	
5431 	   return reopt->ncheckedsols;
5432 	}
5433 	
5434 	/** update the number of checked solutions during the reoptimization process */
5435 	void SCIPreoptAddNCheckedSols(
5436 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5437 	   int                   ncheckedsols        /**< number of updated solutions */
5438 	   )
5439 	{
5440 	   assert(reopt != NULL);
5441 	
5442 	   reopt->ncheckedsols += ncheckedsols;
5443 	}
5444 	
5445 	/** get the number of checked solutions during the reoptimization process */
5446 	int SCIPreoptGetNImprovingSols(
5447 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5448 	   )
5449 	{
5450 	   assert(reopt != NULL);
5451 	
5452 	   return reopt->nimprovingsols;
5453 	}
5454 	
5455 	/** update the number of checked solutions during the reoptimization process */
5456 	void SCIPreoptAddNImprovingSols(
5457 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5458 	   int                   nimprovingsols      /**< number of improving solutions */
5459 	   )
5460 	{
5461 	   assert(reopt != NULL);
5462 	
5463 	   reopt->nimprovingsols += nimprovingsols;
5464 	}
5465 	
5466 	/** returns number of solutions stored in the solution tree of a given run */
5467 	int SCIPreoptGetNSolsRun(
5468 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5469 	   int                   run                 /**< number of the run (1,2,..) */
5470 	   )
5471 	{
5472 	   assert(reopt != NULL);
5473 	   assert(0 < run && run <= reopt->runsize);
5474 	
5475 	   if( reopt->soltree->sols[run-1] == NULL )
5476 	      return 0;
5477 	   else
5478 	      return reopt->soltree->nsols[run-1];
5479 	}
5480 	
5481 	/** returns number of all solutions of all runs */
5482 	int SCIPreoptGetNSols(
5483 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5484 	   )
5485 	{
5486 	   int nsols = 0;
5487 	
5488 	   assert(reopt != NULL);
5489 	
5490 	   for( int r = 0; r < reopt->run; ++r )
5491 	      nsols += reopt->soltree->nsols[r];
5492 	
5493 	   return nsols;
5494 	}
5495 	
5496 	/** return the stored solutions of a given run */
5497 	SCIP_RETCODE SCIPreoptGetSolsRun(
5498 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5499 	   int                   run,                /**< number of the run (1,2,...) */
5500 	   SCIP_SOL**            sols,               /**< array of solutions to fill */
5501 	   int                   solssize,           /**< length of the array */
5502 	   int*                  nsols               /**< pointer to store the number of added solutions */
5503 	   )
5504 	{
5505 	   assert(reopt != NULL);
5506 	   assert(run > 0 && run <= reopt->run);
5507 	   assert(sols != NULL);
5508 	
5509 	   assert(solssize > 0);
5510 	   assert(nsols != NULL);
5511 	   *nsols = 0;
5512 	
5513 	   for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
5514 	   {
5515 	      if( !reopt->soltree->sols[run-1][s]->updated )
5516 	         ++(*nsols);
5517 	   }
5518 	
5519 	   if( solssize < (*nsols) )
5520 	      return SCIP_OKAY;
5521 	
5522 	   (*nsols) = 0;
5523 	   for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
5524 	   {
5525 	      if( !reopt->soltree->sols[run-1][s]->updated )
5526 	      {
5527 	         sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
5528 	         reopt->soltree->sols[run-1][s]->updated = TRUE;
5529 	         ++(*nsols);
5530 	      }
5531 	   }
5532 	
5533 	   return SCIP_OKAY;
5534 	}
5535 	
5536 	/** returns the number of saved solutions overall runs */
5537 	int SCIPreoptGetNSavedSols(
5538 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5539 	   )
5540 	{
5541 	   int nsavedsols = 0;
5542 	
5543 	   assert(reopt != NULL);
5544 	   assert(reopt->soltree->root != NULL);
5545 	
5546 	   if( reopt->soltree->root->child != NULL )
5547 	      nsavedsols = soltreeNInducedSols(reopt->soltree->root);
5548 	
5549 	   return nsavedsols;
5550 	}
5551 	
5552 	/** check if the reoptimization process should be (locally) restarted.
5553 	 *
5554 	 *  First, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
5555 	 *  the similarity again. we trigger a restart if
5556 	 *    1. the objective function has changed too much
5557 	 *    2. the number of stored nodes is exceeded
5558 	 *    3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
5559 	 *       prove the optimality and this can be probably faster by solving from scratch)
5560 	 *
5561 	 *  If the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
5562 	 *  that are already fixed by bounding.
5563 	 */
5564 	SCIP_RETCODE SCIPreoptCheckRestart(
5565 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5566 	   SCIP_SET*             set,                /**< global SCIP settings */
5567 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5568 	   SCIP_NODE*            node,               /**< current node of the branch and bound tree (or NULL) */
5569 	   SCIP_VAR**            transvars,          /**< transformed problem variables */
5570 	   int                   ntransvars,         /**< number of transformed problem variables */
5571 	   SCIP_Bool*            restart             /**< pointer to store if the reoptimization process should be restarted */
5572 	   )
5573 	{
5574 	   SCIP_Real sim = 1.0;
5575 	
5576 	   assert(reopt != NULL);
5577 	   assert(set != NULL);
5578 	   assert(blkmem != NULL);
5579 	   assert(transvars != NULL);
5580 	   assert(ntransvars >= 0);
5581 	   assert(restart != NULL);
5582 	
5583 	   *restart = FALSE;
5584 	
5585 	   /* check if the whole reoptimization process should start from scratch */
5586 	   if( node == NULL )
5587 	   {
5588 	      /* compute the similarity to the objective function of the first run after restarting */
5589 	      if( reopt->run > 1 && set->reopt_objsimdelay > -1.0 )
5590 	      {
5591 	         sim = reoptSimilarity(reopt, set, reopt->run-1, MAX(0, reopt->lastrestart-1), transvars, ntransvars);
5592 	
5593 	         if( sim == SCIP_INVALID )  /*lint !e777*/
5594 	            return SCIP_INVALIDRESULT;
5595 	      }
5596 	
5597 	      /* check similarity */
5598 	      if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
5599 	      {
5600 	         SCIPsetDebugMsg(set, "-> restart reoptimization (objective functions are not similar enough)\n");
5601 	         *restart = TRUE;
5602 	      }
5603 	      /* check size of the reoptimization tree */
5604 	      else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
5605 	      {
5606 	         SCIPsetDebugMsg(set, "-> restart reoptimization (node limit reached)\n");
5607 	         *restart = TRUE;
5608 	      }
5609 	      /* check if the tree was only needed to prove optimality */
5610 	      else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
5611 	      {
5612 	         SCIPsetDebugMsg(set, "-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
5613 	               reopt->noptsolsbyreoptsol);
5614 	         reopt->noptsolsbyreoptsol = 0;
5615 	         *restart = TRUE;
5616 	      }
5617 	
5618 	      if( *restart )
5619 	      {
5620 	         /* trigger a restart */
5621 	         SCIP_CALL( reoptRestart(reopt, set, blkmem) );
5622 	      }
5623 	   }
5624 	   /* check for a local restart, ie, start the solving process of an inner node from scatch */
5625 	   else
5626 	   {
5627 	      SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
5628 	   }
5629 	   return SCIP_OKAY;
5630 	}
5631 	
5632 	/** returns the similarity to the previous objective function, if no exist return -2.0 */
5633 	SCIP_Real SCIPreoptGetSimToPrevious(
5634 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5635 	   )
5636 	{
5637 	   assert(reopt != NULL);
5638 	   return reopt->simtolastobj;
5639 	}
5640 	
5641 	/** returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
5642 	SCIP_Real SCIPreoptGetSimToFirst(
5643 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5644 	   )
5645 	{
5646 	   assert(reopt != NULL);
5647 	   return reopt->simtofirstobj;
5648 	}
5649 	
5650 	/** return the similarity between two of objective functions of two given runs */
5651 	SCIP_Real SCIPreoptGetSimilarity(
5652 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5653 	   SCIP_SET*             set,                /**< global SCIP settings */
5654 	   int                   run1,               /**< number of the first run */
5655 	   int                   run2,               /**< number of the second run */
5656 	   SCIP_VAR**            origvars,           /**< original problem variables */
5657 	   int                   norigvars           /**< number of original problem variables */
5658 	   )
5659 	{
5660 	   assert(reopt != NULL);
5661 	   assert(run1 > 0 && run1 <= reopt->run);
5662 	   assert(run2 > 0 && run2 <= reopt->run);
5663 	   assert(origvars != NULL);
5664 	   assert(norigvars >= 0);
5665 	
5666 	   return reoptSimilarity(reopt, set, run1-1, run2-1, origvars, norigvars);
5667 	}
5668 	
5669 	/** returns the best solution of the last run */
5670 	SCIP_SOL* SCIPreoptGetLastBestSol(
5671 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5672 	   )
5673 	{
5674 	   assert(reopt != NULL);
5675 	   assert(reopt->prevbestsols != NULL);
5676 	
5677 	   if( reopt->run-2 < 0 )
5678 	      return NULL;
5679 	   else
5680 	      return reopt->prevbestsols[reopt->run-2];
5681 	}
5682 	
5683 	/** returns the node of the reoptimization tree corresponding to the unique @p id */
5684 	SCIP_REOPTNODE* SCIPreoptGetReoptnode(
5685 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5686 	   unsigned int          id                  /**< unique id */
5687 	   )
5688 	{
5689 	   assert(reopt != NULL);
5690 	   assert(reopt->reopttree != NULL);
5691 	   assert(id < reopt->reopttree->reoptnodessize);
5692 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
5693 	
5694 	   return reopt->reopttree->reoptnodes[id];
5695 	}
5696 	
5697 	/** returns the coefficient of variable with index @p idx in run @p run */
5698 	SCIP_Real SCIPreoptGetOldObjCoef(
5699 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5700 	   int                   run,                /**< number of the run (1,2,...) */
5701 	   int                   idx                 /**< index of original variable */
5702 	   )
5703 	{
5704 	   assert(reopt != NULL);
5705 	   assert(0 < run && run <= reopt->runsize);
5706 	
5707 	   return reopt->objs[run-1][idx];
5708 	}
5709 	
5710 	/** return the best solution of a given run.
5711 	 *
5712 	 *  @note the returned solution is part of the original space.
5713 	 */
5714 	SCIP_SOL* SCIPreoptGetBestSolRun(
5715 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5716 	   int                   run                 /**< number of the run (1,2,...) */
5717 	   )
5718 	{
5719 	   assert(reopt != NULL);
5720 	   assert(0 < run && run <= reopt->run);
5721 	
5722 	   return reopt->prevbestsols[run-1];
5723 	}
5724 	
5725 	/** reset solving specific parameters */
5726 	SCIP_RETCODE SCIPreoptReset(
5727 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5728 	   SCIP_SET*             set,                /**< global SCIP settings */
5729 	   BMS_BLKMEM*           blkmem              /**< block memory */
5730 	   )
5731 	{
5732 	   assert(reopt != NULL);
5733 	   assert(set != NULL);
5734 	   assert(blkmem != NULL);
5735 	
5736 	   /* clean addedconss array */
5737 	   for( int c = 0; c < reopt->naddedconss; ++c )
5738 	   {
5739 	      SCIP_CONS* cons;
5740 	
5741 	      cons = reopt->addedconss[c];
5742 	      assert(cons != NULL);
5743 	
5744 	#ifdef SCIP_MORE_DEBUG
5745 	      SCIPsetDebugMsg(set, "release cons <%s> from reoptimization data\n", SCIPconsGetName(cons));
5746 	#endif
5747 	
5748 	      SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5749 	      reopt->addedconss[c] = NULL;
5750 	   }
5751 	
5752 	   reopt->naddedconss = 0;
5753 	   reopt->consadded = FALSE;
5754 	   reopt->objhaschanged = FALSE;
5755 	
5756 	   return SCIP_OKAY;
5757 	}
5758 	
5759 	/** reset marks of stored solutions to not updated */
5760 	void SCIPreoptResetSolMarks(
5761 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
5762 	   )
5763 	{
5764 	   SCIP_SOLNODE* child;
5765 	
5766 	   assert(reopt != NULL);
5767 	   assert(reopt->soltree != NULL);
5768 	   assert(reopt->soltree->root != NULL);
5769 	
5770 	   child = reopt->soltree->root->child;
5771 	
5772 	   /* traverse through the list */
5773 	   while( child != NULL )
5774 	   {
5775 	      soltreeResetMarks(child);
5776 	      child = child->sibling;
5777 	   }
5778 	}
5779 	
5780 	/** returns the number of stored nodes in the subtree induced by @p node */
5781 	int SCIPreoptGetNNodes(
5782 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5783 	   SCIP_NODE*            node                /**< node of the search tree */
5784 	   )
5785 	{
5786 	   unsigned int id;
5787 	
5788 	   assert(reopt != NULL);
5789 	
5790 	   if( node == NULL || SCIPnodeGetDepth(node) == 0 )
5791 	      return reopt->reopttree->nreoptnodes;
5792 	
5793 	   id = SCIPnodeGetReoptID(node);
5794 	   assert(id < reopt->reopttree->reoptnodessize);
5795 	
5796 	   /* set the id to -1 if the node is not part of the reoptimization tree */
5797 	   if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5798 	      return 0;
5799 	
5800 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
5801 	
5802 	   return reopttreeGetNNodes(reopt->reopttree, id);
5803 	}
5804 	
5805 	/* ---------------- methods of general reoptimization nodes ---------------- */
5806 	
5807 	/** In debug mode, the following methods are implemented as function calls to ensure
5808 	 * type validity.
5809 	 * In optimized mode, the methods are implemented as defines to improve performance.
5810 	 * However, we want to have them in the library anyways, so we have to undef the defines.
5811 	 */
5812 	
5813 	#undef SCIPreoptnodeGetNVars
5814 	#undef SCIPreoptnodeGetNConss
5815 	#undef SCIPreoptnodeGetNDualBoundChgs
5816 	#undef SCIPreoptnodeGetNChildren
5817 	#undef SCIPreoptnodeGetLowerbound
5818 	#undef SCIPreoptnodeGetType
5819 	
5820 	/** returns the number of bound changes stored in the reopttree at ID id */
5821 	int SCIPreoptnodeGetNVars(
5822 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reopttree */
5823 	   )
5824 	{
5825 	   assert(reoptnode != NULL);
5826 	
5827 	   return reoptnode->nvars + reoptnode->nafterdualvars;
5828 	}
5829 	
5830 	/** returns the number of bound changes at the node stored at ID id */
5831 	int SCIPreoptnodeGetNConss(
5832 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reoptimization tree */
5833 	   )
5834 	{
5835 	   assert(reoptnode != NULL);
5836 	
5837 	   return reoptnode->nconss;
5838 	}
5839 	
5840 	/** returns the number of stored bound changes based on dual information in the reopttree at ID id */
5841 	int SCIPreoptnodeGetNDualBoundChgs(
5842 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reoptimization tree */
5843 	   )
5844 	{
5845 	   assert(reoptnode != NULL);
5846 	
5847 	   if( reoptnode->dualredscur == NULL )
5848 	      return 0;
5849 	   else
5850 	      return reoptnode->dualredscur->nvars;
5851 	}
5852 	
5853 	/** returns the number of child nodes of @p reoptnode */
5854 	int SCIPreoptnodeGetNChildren(
5855 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reoptimization tree */
5856 	   )
5857 	{
5858 	   assert(reoptnode != NULL);
5859 	
5860 	   return reoptnode->nchilds;
5861 	}
5862 	
5863 	/** return the lower bound stored at @p ID id */
5864 	SCIP_Real SCIPreoptnodeGetLowerbound(
5865 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reoptimization tree */
5866 	   )
5867 	{
5868 	   assert(reoptnode != NULL);
5869 	
5870 	   return reoptnode->lowerbound;
5871 	}
5872 	
5873 	/** returns the type of the @p reoptnode */
5874 	SCIP_REOPTTYPE SCIPreoptnodeGetType(
5875 	   SCIP_REOPTNODE*       reoptnode           /**< node of the reoptimization tree */
5876 	   )
5877 	{
5878 	   assert(reoptnode != NULL);
5879 	
5880 	   return (SCIP_REOPTTYPE)reoptnode->reopttype;
5881 	}
5882 	
5883 	/** returns all added constraints at ID id */
5884 	void SCIPreoptnodeGetConss(
5885 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reoptimization tree */
5886 	   SCIP_VAR***           vars,               /**< 2-dim array of variables */
5887 	   SCIP_Real**           bounds,             /**< 2-dim array of bounds */
5888 	   SCIP_BOUNDTYPE**      boundtypes,         /**< 2-dim array of boundtypes */
5889 	   int                   mem,                /**< allocated memory for constraints */
5890 	   int*                  nconss,             /**< pointer to store the number of constraints */
5891 	   int*                  nvars               /**< pointer to store the number of variables */
5892 	   )
5893 	{
5894 	   assert(reoptnode != NULL);
5895 	   assert(vars != NULL);
5896 	   assert(bounds != NULL);
5897 	   assert(boundtypes != NULL);
5898 	   assert(nvars != NULL);
5899 	   assert(nconss != NULL);
5900 	
5901 	   (*nconss) = reoptnode->nconss;
5902 	
5903 	   if( mem < *nconss )
5904 	      return;
5905 	
5906 	   for( int c = 0; c < *nconss; ++c )
5907 	   {
5908 	      assert(vars[c] != NULL);
5909 	      assert(bounds[c] != NULL);
5910 	
5911 	      vars[c] = reoptnode->conss[c]->vars;
5912 	      bounds[c] = reoptnode->conss[c]->vals;
5913 	      boundtypes[c] = reoptnode->conss[c]->boundtypes;
5914 	      nvars[c] = reoptnode->conss[c]->nvars;
5915 	   }
5916 	}
5917 	
5918 	/** set the parent id */
5919 	void SCIPreoptnodeSetParentID(
5920 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reopttree */
5921 	   unsigned int          parentid            /**< id of the parent node */
5922 	   )
5923 	{
5924 	   assert(reoptnode != NULL);
5925 	   assert(parentid <= 536870911); /* id can be at most 2^29 - 1 */
5926 	
5927 	   reoptnode->parentID = parentid;
5928 	}
5929 	
5930 	/** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
5931 	int SCIPreoptGetNLeaves(
5932 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5933 	   SCIP_NODE*            node                /**< node of the search tree (or NULL) */
5934 	   )
5935 	{
5936 	   int nleaves = 0;
5937 	   unsigned int id;
5938 	
5939 	   assert(reopt != NULL);
5940 	
5941 	   id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
5942 	   assert(id < reopt->reopttree->reoptnodessize);
5943 	
5944 	   /* return if the node is not part of the reoptimization tree */
5945 	   if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
5946 	      return nleaves;
5947 	
5948 	   for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
5949 	   {
5950 	      unsigned int childid;
5951 	
5952 	      childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
5953 	      assert(childid < reopt->reopttree->reoptnodessize);
5954 	
5955 	      if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
5956 	         ++nleaves;
5957 	      else
5958 	         nleaves += reoptGetNLeaves(reopt, childid);
5959 	   }
5960 	
5961 	   return nleaves;
5962 	}
5963 	
5964 	/** save information that given node is infeasible */
5965 	SCIP_RETCODE SCIPreoptAddInfNode(
5966 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5967 	   SCIP_SET*             set,                /**< global SCIP settings */
5968 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5969 	   SCIP_NODE*            node                /**< node of the search tree */
5970 	   )
5971 	{
5972 	   assert(reopt != NULL);
5973 	   assert(set != NULL);
5974 	   assert(blkmem != NULL);
5975 	   assert(node != NULL);
5976 	
5977 	   if( set->reopt_sepaglbinfsubtrees )
5978 	   {
5979 	      SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_CUT) );
5980 	   }
5981 	
5982 	   ++reopt->reopttree->ninfnodes;
5983 	   ++reopt->reopttree->ntotalinfnodes;
5984 	
5985 	   return SCIP_OKAY;
5986 	}
5987 	
5988 	/** check the reason for cut off a node and if necessary store the node */
5989 	SCIP_RETCODE SCIPreoptCheckCutoff(
5990 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
5991 	   SCIP_SET*             set,                /**< global SCIP settings */
5992 	   BMS_BLKMEM*           blkmem,             /**< block memory */
5993 	   SCIP_NODE*            node,               /**< node of the search tree */
5994 	   SCIP_EVENTTYPE        eventtype,          /**< eventtype */
5995 	   SCIP_LP*              lp,                 /**< LP data */
5996 	   SCIP_LPSOLSTAT        lpsolstat,          /**< solution status of the LP */
5997 	   SCIP_Bool             isrootnode,         /**< the node is the root */
5998 	   SCIP_Bool             isfocusnode,        /**< the node is the current focus node */
5999 	   SCIP_Real             lowerbound,         /**< lower bound of the node */
6000 	   int                   effectiverootdepth  /**< effective root depth */
6001 	   )
6002 	{
6003 	   SCIP_Bool strongbranched;
6004 	
6005 	   assert(reopt != NULL);
6006 	   assert(set != NULL);
6007 	   assert(blkmem != NULL);
6008 	   assert(lp != NULL);
6009 	   assert(node != NULL);
6010 	   assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
6011 	
6012 	   if( reopt->lastseennode == SCIPnodeGetNumber(node) )
6013 	      return SCIP_OKAY;
6014 	
6015 	   /* we do not want to store probing node */
6016 	   if( SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE )
6017 	      return SCIP_OKAY;
6018 	
6019 	   reopt->lastseennode = SCIPnodeGetNumber(node);
6020 	
6021 	   SCIPsetDebugMsg(set, "catch event %" SCIP_EVENTTYPE_FORMAT " for node %lld (type:%d)\n", eventtype, SCIPnodeGetNumber(node), SCIPnodeGetType(node));
6022 	
6023 	   /* case 1: the current node is the root node
6024 	    * we can skip if the root is (in)feasible or branched w/o bound
6025 	    * changes based on dual information.
6026 	    *
6027 	    * case 2: we need to store the current node if it contains
6028 	    * bound changes based on dual information or is a leave node
6029 	    */
6030 	   if( isrootnode )
6031 	   {
6032 	      if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
6033 	      {
6034 	         goto CHECK;
6035 	      }
6036 	      else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
6037 	      {
6038 	         /* store or update the information */
6039 	         SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6040 	      }
6041 	      else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
6042 	      {
6043 	         /* delete saved dual information which would lead to split the node in a further iteration */
6044 	         SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6045 	
6046 	         /* store or update the information */
6047 	         SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6048 	      }
6049 	      else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
6050 	      {
6051 	         /* delete saved dual information which would lead to split the node in a further iteration */
6052 	         SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6053 	
6054 	         if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT )
6055 	         {
6056 	            SCIP_Real cutoffbound = SCIPlpGetCutoffbound(lp);
6057 	            lowerbound = MIN(lowerbound, cutoffbound);
6058 	         }
6059 	
6060 	         /* store or update the information */
6061 	         SCIP_CALL( addNode(reopt, set, lp, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
6062 	               isrootnode, lowerbound) );
6063 	      }
6064 	
6065 	      assert(reopt->currentnode == -1);
6066 	      assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6067 	
6068 	      return SCIP_OKAY;
6069 	   }
6070 	
6071 	  CHECK:
6072 	
6073 	   if( effectiverootdepth == SCIPnodeGetDepth(node) )
6074 	      strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
6075 	   else
6076 	      strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
6077 	
6078 	   SCIPsetDebugMsg(set, "check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
6079 	   SCIPsetDebugMsg(set, " -> focusnode       : %s\n", isfocusnode ? "yes" : "no");
6080 	   SCIPsetDebugMsg(set, " -> depth           : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
6081 	   SCIPsetDebugMsg(set, " -> strong branched : %s\n", strongbranched ? "yes" : "no");
6082 	   SCIPsetDebugMsg(set, " -> LP lpsolstat    : %d\n", lpsolstat);
6083 	
6084 	   switch( eventtype )
6085 	   {
6086 	   case SCIP_EVENTTYPE_NODEFEASIBLE:
6087 	      /* current node has to be the eventnode */
6088 	      assert(isfocusnode);
6089 	
6090 	      SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_FEASIBLE);
6091 	
6092 	      /* delete strong branching information of some exists */
6093 	      deleteLastDualBndchgs(reopt);
6094 	
6095 	      SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6096 	      break;
6097 	
6098 	   case SCIP_EVENTTYPE_NODEINFEASIBLE:
6099 	      /* We have to check if the current node is the event node.
6100 	       * if the current node is not the event node, we have to save this node, else we have to
6101 	       * look at LP lpsolstat and decide.
6102 	       */
6103 	      if( isfocusnode )
6104 	      {
6105 	         /* An after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
6106 	          * because the node is already branched we have all children and can delete this node.
6107 	          */
6108 	         if( SCIPnodeGetNumber(node) == reopt->lastbranched )
6109 	         {
6110 	            deleteLastDualBndchgs(reopt);
6111 	            break;
6112 	         }
6113 	
6114 	         /* If the node is strong branched, we possibly detect an infeasible subtree;
6115 	          * otherwise, the whole node is either infeasible or exceeds the cutoff bound.
6116 	          */
6117 	         if( strongbranched )
6118 	         {
6119 	            /* 1. the LP is infeasible: the (sub-)node is infeasible and can be discarded
6120 	             *    because the LP proves infeasibility. We have to store an infeasible subtree separated by a constraint.
6121 	             * 2. the LP exceeds the objective limit or was not solved, we have to store the node and can delete the
6122 	             *    strong branching information
6123 	             */
6124 	            if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6125 	            {
6126 	               /* add a dummy variable, because the bound changes were not global in the sense of effective root depth */
6127 	               if( SCIPnodeGetDepth(node) > effectiverootdepth )
6128 	               {
6129 	                  SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6130 	               }
6131 	
6132 	               SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6133 	               SCIPsetDebugMsg(set, " -> new constype    : %d\n", REOPT_CONSTYPE_INFSUBTREE);
6134 	
6135 	               /* save the node as a strong branched node */
6136 	               SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
6137 	            }
6138 	            else
6139 	            {
6140 	               assert( lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
6141 	
6142 	               /* delete strong branching information if some exists */
6143 	               deleteLastDualBndchgs(reopt);
6144 	
6145 	               SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_PRUNED);
6146 	               SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6147 	            }
6148 	         }
6149 	         else
6150 	         {
6151 	            /* 1. the LP is infeasible: the whole node is infeasible and can be discarded
6152 	             * 2. the LP was not solved or exceeds the objective limit, we have to store the node
6153 	             */
6154 	            if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6155 	            {
6156 	               SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6157 	               SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
6158 	            }
6159 	            else
6160 	            {
6161 	               assert(lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED || lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
6162 	                  || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
6163 	
6164 	               if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6165 	               {
6166 	                  SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6167 	                  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6168 	               }
6169 	               else
6170 	               {
6171 	                  SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_PRUNED);
6172 	                  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6173 	               }
6174 	            }
6175 	         }
6176 	      }
6177 	      else
6178 	      {
6179 	         SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_PRUNED);
6180 	
6181 	         /* if the node was created by branch_nodereopt, nothing happens */
6182 	         SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6183 	      }
6184 	      break;
6185 	
6186 	   case SCIP_EVENTTYPE_NODEBRANCHED:
6187 	      /* current node has to be the eventnode */
6188 	      assert(isfocusnode);
6189 	
6190 	      reopt->lastbranched = SCIPnodeGetNumber(node);
6191 	
6192 	      /* we have to check the depth of the current node. if the depth is equal to the effective
6193 	       * root depth, then all information about bound changes based on dual information already exists,
6194 	       * else we have to look at the domchg-data-structure.
6195 	       */
6196 	      if (SCIPnodeGetDepth(node) == effectiverootdepth)
6197 	      {
6198 	         /* Save the node if there are added constraints, because this means the node is a copy create by the
6199 	          * reoptimization plug-in and contains at least one logic-or-constraint */
6200 	         if( strongbranched )
6201 	         {
6202 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6203 	            SCIPsetDebugMsg(set, " -> new constype    : %d\n", REOPT_CONSTYPE_DUALREDS);
6204 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6205 	         }
6206 	         else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6207 	         {
6208 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6209 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6210 	         }
6211 	         else
6212 	         {
6213 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_TRANSIT);
6214 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6215 	         }
6216 	      }
6217 	      else
6218 	      {
6219 	         /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
6220 	          *
6221 	          * we have to do this in the following order:
6222 	          * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
6223 	          *    on dual information.
6224 	          * 2) save or update the node.
6225 	          */
6226 	         if( strongbranched )
6227 	         {
6228 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6229 	            SCIPsetDebugMsg(set, " -> new constype    : %d\n", REOPT_CONSTYPE_DUALREDS);
6230 	            SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6231 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6232 	         }
6233 	         else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6234 	         {
6235 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6236 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6237 	         }
6238 	         else
6239 	         {
6240 	            SCIPsetDebugMsg(set, " -> new reopttype   : %d\n", SCIP_REOPTTYPE_TRANSIT);
6241 	            SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6242 	         }
6243 	      }
6244 	      break;
6245 	
6246 	   default:
6247 	      break;
6248 	   }
6249 	
6250 	   assert(reopt->currentnode == -1);
6251 	   assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6252 	
6253 	   return SCIP_OKAY; /*lint !e438*/
6254 	}
6255 	
6256 	/** store bound change based on dual information */
6257 	SCIP_RETCODE SCIPreoptAddDualBndchg(
6258 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6259 	   SCIP_SET*             set,                /**< global SCIP settings */
6260 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6261 	   SCIP_NODE*            node,               /**< node of the search tree */
6262 	   SCIP_VAR*             var,                /**< variable */
6263 	   SCIP_Real             newval,             /**< new bound */
6264 	   SCIP_Real             oldval              /**< old bound */
6265 	   )
6266 	{
6267 	   SCIP_Real constant = 0.0;
6268 	   SCIP_Real scalar = 1.0;
6269 	
6270 	   assert(reopt != NULL);
6271 	   assert(node != NULL);
6272 	
6273 	   /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
6274 	    * In that case, all bound changes were not global and we can find them within the
6275 	    * domchg data structure.
6276 	    * Otherwise, we allocate memory and store the information.
6277 	    */
6278 	   if( var != NULL )
6279 	   {
6280 	      SCIP_BOUNDTYPE boundtype;
6281 	      int resizelength;
6282 	      int allocmem;
6283 	
6284 	      if( SCIPsetFindBranchrule(set, "relpscost") != NULL )
6285 	      {
6286 	         SCIP_CALL( SCIPsetGetIntParam(set, "branching/relpscost/maxlookahead", &resizelength) );
6287 	      }
6288 	      else
6289 	         resizelength = 1;
6290 	
6291 	      if( reopt->dualreds == NULL || reopt->dualreds->varssize == 0 )
6292 	         allocmem = DEFAULT_MEM_DUALCONS;
6293 	      else
6294 	         allocmem = reopt->dualreds->nvars + resizelength;
6295 	
6296 	      /* allocate memory of necessary */
6297 	      SCIP_CALL( checkMemDualCons(reopt, set, blkmem, allocmem) );
6298 	
6299 	      assert(reopt->dualreds->varssize > 0);
6300 	      assert(reopt->dualreds->nvars >= 0);
6301 	      assert(reopt->currentnode == -1 || reopt->dualreds->nvars > 0);
6302 	      assert((reopt->dualreds->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
6303 	           || reopt->dualreds->nvars == 0);
6304 	
6305 	      reopt->currentnode = SCIPnodeGetNumber(node);
6306 	
6307 	      /* transform into the original space and then save the bound change */
6308 	      SCIP_CALL(SCIPvarGetOrigvarSum(&var, &scalar, &constant));
6309 	      newval = (newval - constant) / scalar;
6310 	      oldval = (oldval - constant) / scalar;
6311 	
6312 	      assert(SCIPvarIsOriginal(var));
6313 	
6314 	      if( SCIPsetIsEQ(set, oldval, newval) )
6315 	      {
6316 	         SCIPerrorMessage("cannot store equal bounds: old = %g, new = %g\n", oldval, newval);
6317 	         return SCIP_INVALIDDATA;
6318 	      }
6319 	
6320 	      if( SCIPsetIsLT(set, newval, oldval) )
6321 	         boundtype = SCIP_BOUNDTYPE_UPPER;
6322 	      else
6323 	         boundtype = SCIP_BOUNDTYPE_LOWER;
6324 	
6325 	      reopt->dualreds->vars[reopt->dualreds->nvars] = var;
6326 	      reopt->dualreds->vals[reopt->dualreds->nvars] = newval;
6327 	      reopt->dualreds->boundtypes[reopt->dualreds->nvars] = boundtype;
6328 	      ++reopt->dualreds->nvars;
6329 	
6330 	      SCIPsetDebugMsg(set, ">> store %s bound change of <%s>: %g -> %g\n",
6331 	         (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), SCIPvarGetName(var), oldval, newval);
6332 	
6333 	      reopt->dualreds->linear = FALSE;
6334 	   }
6335 	   else
6336 	   {
6337 	      assert(reopt->currentnode == -1);
6338 	      assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6339 	
6340 	      reopt->currentnode = SCIPnodeGetNumber(node);
6341 	   }
6342 	
6343 	   return SCIP_OKAY;
6344 	}
6345 	
6346 	/** returns the number of bound changes based on dual information */
6347 	int SCIPreoptGetNDualBndchgs(
6348 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6349 	   SCIP_NODE*            node                /**< node of the search tree */
6350 	   )
6351 	{
6352 	   int ndualbndchgs = 0;
6353 	
6354 	   assert(reopt != NULL);
6355 	   assert(node != NULL);
6356 	
6357 	   if( SCIPnodeGetNumber(node) == reopt->currentnode )
6358 	   {
6359 	      assert(reopt->dualreds != NULL);
6360 	      ndualbndchgs = reopt->dualreds->nvars;
6361 	   }
6362 	
6363 	   return ndualbndchgs;
6364 	}
6365 	
6366 	/** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
6367 	SCIP_RETCODE SCIPreoptGetChildIDs(
6368 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6369 	   SCIP_SET*             set,                /**< global SCIP settings */
6370 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6371 	   SCIP_NODE*            node,               /**< node of the search tree */
6372 	   unsigned int*         childs,             /**< array to store the child ids */
6373 	   int                   childssize,         /**< size of the childs array */
6374 	   int*                  nchilds             /**< pointer to store the number of child nodes */
6375 	   )
6376 	{
6377 	   SCIP_Bool runagain;
6378 	   unsigned int id;
6379 	
6380 	   assert(reopt != NULL);
6381 	   assert(childssize > 0 && childs != NULL);
6382 	   assert(nchilds != NULL);
6383 	
6384 	   (*nchilds) = 0;
6385 	
6386 	   if( node == NULL )
6387 	      id = 0;
6388 	   else
6389 	      id = SCIPnodeGetReoptID(node);
6390 	
6391 	   assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
6392 	   assert(id < reopt->reopttree->reoptnodessize);
6393 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
6394 	
6395 	   /* check if there are redundant bound changes or infeasible nodes */
6396 	   runagain = TRUE;
6397 	   while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6398 	   {
6399 	      SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
6400 	   }
6401 	
6402 	   /* return the list of child nodes if some exists; otherwise return NULL */
6403 	   if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6404 	   {
6405 	      (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
6406 	
6407 	      if( childssize < *nchilds )
6408 	         return SCIP_OKAY;
6409 	
6410 	      for( int c = 0; c < *nchilds; ++c )
6411 	         childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
6412 	   }
6413 	
6414 	   return SCIP_OKAY;
6415 	}
6416 	
6417 	/** returns all leaves of the subtree induced by @p node */
6418 	SCIP_RETCODE SCIPreoptGetLeaves(
6419 	   SCIP_REOPT*           reopt,              /**< reoptimization data */
6420 	   SCIP_NODE*            node,               /**< node of the search tree */
6421 	   unsigned int*         leaves,             /**< array to the the ids */
6422 	   int                   leavessize,         /**< size of leaves array */
6423 	   int*                  nleaves             /**< pointer to store the number of leave node */
6424 	   )
6425 	{
6426 	   unsigned int id;
6427 	
6428 	   assert(reopt != NULL);
6429 	   assert(leavessize > 0 && leaves != NULL);
6430 	   assert((*nleaves) >= 0);
6431 	
6432 	   /* if the given node is we start from the root */
6433 	   if( node == NULL )
6434 	      id = 0;
6435 	   else
6436 	      id = SCIPnodeGetReoptID(node);
6437 	
6438 	   /* return if the node is not part of the reoptimization tree */
6439 	   if( id == 0 && node != NULL )
6440 	   {
6441 	      (*nleaves) = 0;
6442 	      return SCIP_OKAY;
6443 	   }
6444 	
6445 	   assert(id < reopt->reopttree->reoptnodessize);
6446 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
6447 	
6448 	   for( int i = 0; i < leavessize; ++i )
6449 	      leaves[i] = 0;
6450 	
6451 	   /* we traverse through all child nodes of the given node an collect all leave nodes of the subtrees induced by them */
6452 	   for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
6453 	   {
6454 	      unsigned int childid;
6455 	
6456 	      assert(*nleaves + 1 <= leavessize);
6457 	
6458 	      childid = reopt->reopttree->reoptnodes[id]->childids[i];
6459 	      assert(childid < reopt->reopttree->reoptnodessize);
6460 	
6461 	      /* the node is already a leave */
6462 	      if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
6463 	      {
6464 	         leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
6465 	         ++(*nleaves);
6466 	      }
6467 	      /* go into the tree induced by the current child node */
6468 	      else
6469 	      {
6470 	         int nleaves2 = 0;
6471 	
6472 	         SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
6473 	         (*nleaves) += nleaves2;
6474 	      }
6475 	   }
6476 	
6477 	   return SCIP_OKAY;
6478 	}
6479 	
6480 	/** add all unprocessed nodes to the reoptimization tree */
6481 	SCIP_RETCODE SCIPreoptSaveOpenNodes(
6482 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6483 	   SCIP_SET*             set,                /**< global SCIP settings */
6484 	   SCIP_LP*              lp,                 /**< current LP */
6485 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6486 	   SCIP_NODE**           leaves,             /**< array of open leave nodes */
6487 	   int                   nleaves,            /**< number of open leave nodes */
6488 	   SCIP_NODE**           childs,             /**< array of open children nodes */
6489 	   int                   nchilds,            /**< number of open leave nodes */
6490 	   SCIP_NODE**           siblings,           /**< array of open sibling nodes */
6491 	   int                   nsiblings           /**< number of open leave nodes */
6492 	   )
6493 	{
6494 	   assert(reopt != NULL);
6495 	   assert(set != NULL);
6496 	   assert(blkmem != NULL);
6497 	   assert(nleaves >= 0);
6498 	   assert(nleaves == 0 || leaves != NULL);
6499 	   assert(nchilds >= 0);
6500 	   assert(nchilds == 0 || childs != NULL);
6501 	   assert(nsiblings >= 0);
6502 	   assert(nsiblings == 0 || siblings != NULL);
6503 	
6504 	   SCIPsetDebugMsg(set, "save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
6505 	
6506 	   /* save open leaves */
6507 	   for( int n = 0; n < nleaves; ++n )
6508 	   {
6509 	      SCIP_CALL( addNode(reopt, set, lp, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6510 	            SCIPnodeGetLowerbound(leaves[n])) );
6511 	   }
6512 	
6513 	   /* save open children */
6514 	   for( int n = 0; n < nchilds; ++n )
6515 	   {
6516 	      SCIP_CALL( addNode(reopt, set, lp, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6517 	            SCIPnodeGetLowerbound(childs[n])) );
6518 	   }
6519 	
6520 	   /* save open siblings */
6521 	   for( int n = 0; n < nsiblings; ++n )
6522 	   {
6523 	      SCIP_CALL( addNode(reopt, set, lp, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6524 	            SCIPnodeGetLowerbound(siblings[n])) );
6525 	   }
6526 	
6527 	   return SCIP_OKAY;
6528 	}
6529 	
6530 	/** merges the variable history of the current run with the stored history */
6531 	SCIP_RETCODE SCIPreoptMergeVarHistory(
6532 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6533 	   SCIP_SET*             set,                /**< global SCIP settings */
6534 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
6535 	   SCIP_VAR**            vars,               /**< original problem variables */
6536 	   int                   nvars               /**< number of original problem variables */
6537 	   )
6538 	{
6539 	   SCIP_VAR* transvar;
6540 	   SCIP_Real avginference[2];
6541 	   SCIP_Real avgcutoff[2];
6542 	   SCIP_Real bestsim;
6543 	   int bestrun;
6544 	   int idx;
6545 	
6546 	   assert(reopt != NULL);
6547 	   assert(stat != NULL);
6548 	   assert(nvars >= 0);
6549 	
6550 	   if( !set->reopt_storevarhistory )
6551 	      return SCIP_OKAY;
6552 	
6553 	   SCIPsetDebugMsg(set, "start merging variable histories:\n");
6554 	
6555 	   bestrun = reopt->run-2;
6556 	   bestsim = reopt->simtolastobj;
6557 	
6558 	   /* find the run with the most similar objective */
6559 	   for( int r = reopt->run-3; r >= 0 && reopt->objhaschanged && set->reopt_usepscost; --r )
6560 	   {
6561 	      SCIP_Real sim;
6562 	      sim = reoptSimilarity(reopt, set, r, reopt->run-1, vars, nvars);
6563 	
6564 	      if( sim == SCIP_INVALID )  /*lint !e777*/
6565 	         return SCIP_INVALIDRESULT;
6566 	
6567 	      if( SCIPsetIsGT(set, sim, bestsim) )
6568 	      {
6569 	         bestsim = sim;
6570 	         bestrun = r;
6571 	      }
6572 	   }
6573 	   SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "run %d has best similarity=%g\n", bestrun, bestsim);
6574 	
6575 	   /* iterate through all variables and scale the histories */
6576 	   for( int v = 0; v < nvars; ++v )
6577 	   {
6578 	      assert(SCIPvarIsOriginal(vars[v]));
6579 	
6580 	      transvar = SCIPvarGetTransVar(vars[v]);
6581 	      assert(transvar != NULL);
6582 	
6583 	      /* skip variable that are not active */
6584 	      if( !SCIPvarIsActive(transvar) )
6585 	         continue;
6586 	
6587 	      idx = SCIPvarGetIndex(vars[v]);
6588 	      assert(0 <= idx && idx <= nvars);
6589 	
6590 	      /* set the updated history for both directions */
6591 	      for( int d = 0; d <= 1; ++d )
6592 	      {
6593 	         if( set->reopt_usepscost && !SCIPsetIsZero(set, reopt->varhistory[bestrun][idx]->pscostcount[d])
6594 	            && SCIPsetIsGT(set, bestsim, 0.985) ) /* 0.985 is a magic number determined in some experiments */
6595 	         {
6596 	            transvar->history->pscostcount[d] = 1.0;
6597 	            transvar->history->pscostweightedmean[d] = reopt->varhistory[bestrun][idx]->pscostweightedmean[d];
6598 	            transvar->history->pscostvariance[d] = 0.0;
6599 	            SCIPsetDebugMsg(set, "-> <%s> pscosts %4s: count=%g weightedmean=%g variance=%g\n", SCIPvarGetName(transvar),
6600 	               (d == 0 ? "down" : "up"), transvar->history->pscostcount[d], transvar->history->pscostweightedmean[d],
6601 	               transvar->history->pscostvariance[d]);
6602 	         }
6603 	
6604 	         SCIPhistoryIncNBranchings(transvar->history, (SCIP_BRANCHDIR)d, 1);
6605 	
6606 	         /* inference score */
6607 	         avginference[d] = SCIPhistoryGetAvgInferences(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6608 	         SCIPhistoryIncInferenceSum(transvar->history, (SCIP_BRANCHDIR)d, avginference[d]);
6609 	
6610 	         /* cutoff score */
6611 	         avgcutoff[d] = SCIPhistoryGetAvgCutoffs(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6612 	         SCIPhistoryIncCutoffSum(transvar->history, (SCIP_BRANCHDIR)d, avgcutoff[d]);
6613 	
6614 	         SCIPsetDebugMsg(set, "-> <%s> %4s scores: inf=%g cutoff=%g\n", SCIPvarGetName(transvar),
6615 	            (d == 0 ? "down" : "up"), avginference[d], avgcutoff[d]);
6616 	      }
6617 	   }
6618 	
6619 	   return SCIP_OKAY;
6620 	}
6621 	
6622 	/** updates the variable history */
6623 	SCIP_RETCODE SCIPreoptUpdateVarHistory(
6624 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6625 	   SCIP_SET*             set,                /**< global SCIP settings */
6626 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
6627 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6628 	   SCIP_VAR**            vars,               /**< original variable array */
6629 	   int                   nvars               /**< number of original variables */
6630 	   )
6631 	{
6632 	   assert(reopt != NULL);
6633 	   assert(stat != NULL);
6634 	   assert(blkmem != NULL);
6635 	   assert(nvars >= 0);
6636 	
6637 	   if( !set->reopt_storevarhistory )
6638 	      return SCIP_OKAY;
6639 	
6640 	   SCIPsetDebugMsg(set, "updating variable history\n");
6641 	
6642 	   if( reopt->varhistory[reopt->run-1] == NULL )
6643 	   {
6644 	      /* allocate memory */
6645 	      SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->varhistory[reopt->run-1], nvars) );
6646 	
6647 	      for( int v = 0; v < nvars; ++v )
6648 	      {
6649 	         SCIP_CALL( SCIPhistoryCreate(&(reopt->varhistory[reopt->run-1][v]), blkmem) );
6650 	      }
6651 	   }
6652 	
6653 	   /* update the history and scale them */
6654 	   for( int v = 0; v < nvars; ++v )
6655 	   {
6656 	      SCIP_VAR* transvar;
6657 	      int idx;
6658 	
6659 	      assert(SCIPvarIsOriginal(vars[v]));
6660 	      idx = SCIPvarGetIndex(vars[v]);
6661 	      assert(idx >= 0 && idx < nvars);
6662 	
6663 	      transvar = SCIPvarGetTransVar(vars[v]);
6664 	      assert(transvar != NULL);
6665 	
6666 	      if( !SCIPvarIsActive(transvar) )
6667 	         continue;
6668 	
6669 	      /* we store the complete history */
6670 	      SCIPhistoryReset(reopt->varhistory[reopt->run-1][idx]);
6671 	      SCIPhistoryUnite(reopt->varhistory[reopt->run-1][idx], transvar->history, FALSE);
6672 	   }
6673 	
6674 	   return SCIP_OKAY;
6675 	}
6676 	
6677 	/** reset the complete tree and set the given search frontier */
6678 	SCIP_RETCODE SCIPreoptApplyCompression(
6679 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6680 	   SCIP_SET*             set,                /**< global SCIP settings */
6681 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6682 	   SCIP_REOPTNODE**      representatives,    /**< array of representatives */
6683 	   int                   nrepresentatives,   /**< number of representatives */
6684 	   SCIP_Bool*            success             /**< pointer to store if the method was successful */
6685 	   )
6686 	{
6687 	   SCIP_REOPTTREE* reopttree;
6688 	   unsigned int id;
6689 	
6690 	   assert(reopt != NULL);
6691 	   assert(set != NULL);
6692 	   assert(blkmem != NULL);
6693 	   assert(representatives != NULL);
6694 	   assert(nrepresentatives > 0);
6695 	
6696 	   reopttree = reopt->reopttree;
6697 	
6698 	   /* reset the current search tree */
6699 	   SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
6700 	   assert(reopttree->nreoptnodes == 0);
6701 	
6702 	   /* create a new root node */
6703 	   id = 0;
6704 	   SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6705 	
6706 	   /* set the reopttype */
6707 	   reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6708 	
6709 	   /* add all representatives */
6710 	   for( int r = 0; r < nrepresentatives; ++r )
6711 	   {
6712 	      /* get an empty slot*/
6713 	      id = SCIPqueueRemoveUInt(reopttree->openids);
6714 	      assert(1 <= id && id < reopttree->reoptnodessize);
6715 	      assert(reopttree->reoptnodes[id] == NULL);
6716 	
6717 	      SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6718 	      assert(reopttree->reoptnodes[id] != NULL);
6719 	
6720 	      /* set the new node
6721 	       * 1. copy all variables, bounds, and boundtypes
6722 	       * 2. copy all constraints
6723 	       * 3. set the parent relation
6724 	       */
6725 	      if( representatives[r]->nvars > 0 )
6726 	      {
6727 	         assert(representatives[r]->nvars <= representatives[r]->varssize);
6728 	
6729 	         for( int v = 0; v < representatives[r]->nvars; ++v )
6730 	         {
6731 	            SCIP_CALL( SCIPreoptnodeAddBndchg(reopttree->reoptnodes[id], set, blkmem, representatives[r]->vars[v],
6732 	                  representatives[r]->varbounds[v], representatives[r]->varboundtypes[v]) );
6733 	         }
6734 	      }
6735 	
6736 	      if( representatives[r]->nconss > 0 )
6737 	      {
6738 	         assert(representatives[r]->nconss <= representatives[r]->consssize);
6739 	
6740 	         for( int c = 0; c < representatives[r]->nconss; ++c )
6741 	         {
6742 	            SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], set, blkmem, representatives[r]->conss[c]->vars,
6743 	                  representatives[r]->conss[c]->vals, representatives[r]->conss[c]->boundtypes,
6744 	                  representatives[r]->conss[c]->lhs, representatives[r]->conss[c]->rhs,
6745 	                  representatives[r]->conss[c]->nvars, representatives[r]->conss[c]->constype,
6746 	                  representatives[r]->conss[c]->linear) );
6747 	         }
6748 	      }
6749 	
6750 	      reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
6751 	
6752 	      assert(reopttree->reoptnodes[id]->parentID == 0);
6753 	      assert(reopttree->reoptnodes[id]->nvars >= 0);
6754 	      assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
6755 	      assert(reopttree->reoptnodes[id]->nconss >= 0);
6756 	
6757 	      /* set the reopttype */
6758 	      if( reopttree->reoptnodes[id]->nconss == 0 )
6759 	         reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
6760 	      else
6761 	         reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
6762 	
6763 	      /* add the representative as a child of the root */
6764 	      SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
6765 	   }
6766 	
6767 	   SCIPsetDebugMsg(set, "-> new tree consists of %d nodes, the root has %d child nodes.\n",
6768 	         reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
6769 	
6770 	   (*success) = TRUE;
6771 	
6772 	   return SCIP_OKAY;
6773 	}
6774 	
6775 	/** transforms a set of dual reductions into a linear constraint */
6776 	static
6777 	SCIP_RETCODE transformDualredsToLinear(
6778 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6779 	   SCIP_SET*             set,                /**< global SCIP settings */
6780 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6781 	   SCIP_REOPTCONSDATA*   consdata,           /**< reoptimization constraint data that should represent to set of solutions
6782 	                                              *  pruned by the dual reductions */
6783 	   SCIP_REOPTCONSDATA*   dualreds            /**< set of dual reductions */
6784 	   )
6785 	{
6786 	   assert(reopt != NULL);
6787 	   assert(set != NULL);
6788 	   assert(blkmem != NULL);
6789 	   assert(consdata != NULL);
6790 	   assert(dualreds != NULL);
6791 	
6792 	   /* we have to transform the set of bound changes into a linear constraint */
6793 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6794 	   SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &consdata->vals, dualreds->nvars) );
6795 	   consdata->boundtypes = NULL;
6796 	
6797 	   consdata->varssize = dualreds->nvars;
6798 	   consdata->nvars = dualreds->nvars;
6799 	   consdata->constype = REOPT_CONSTYPE_DUALREDS;
6800 	   consdata->linear = TRUE;
6801 	
6802 	   /* set lhs and rhs */
6803 	   consdata->lhs = 1.0;
6804 	   consdata->rhs = SCIPsetInfinity(set);
6805 	
6806 	   for( int v = 0; v < consdata->nvars; ++v )
6807 	   {
6808 	      assert(consdata->vars[v] != NULL);
6809 	
6810 	      /* the bound is 0.0, the variable has to appear with a coefficient +1.0 in the constraint, sides do not change */
6811 	      if( SCIPsetIsEQ(set, dualreds->vals[v], 0.0) )
6812 	      {
6813 	         assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
6814 	         consdata->vals[v] = 1.0;
6815 	      }
6816 	      /* the bound is 1.0, the variable has to appear with a coefficient -1.0 in the constraint, we subtract -1.0 from lhs
6817 	       *   logicor:       sum x_i + ~y_i    >= 1
6818 	       *           <==>   sum x_i + (1-y_i) >= 1
6819 	       *           <==>   sum x_i - y_i     >= 0
6820 	       */
6821 	      else
6822 	      {
6823 	         assert(SCIPsetIsEQ(set, dualreds->vals[v], 1.0));
6824 	         assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6825 	
6826 	         consdata->vals[v] = -1.0;
6827 	         consdata->lhs -= 1.0;
6828 	      }
6829 	   }
6830 	
6831 	   return SCIP_OKAY;
6832 	}
6833 	
6834 	
6835 	/** transforms a set of dual reductions into a bounddisjuction constraint */
6836 	static
6837 	SCIP_RETCODE transformDualredsToBounddisjunction(
6838 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6839 	   SCIP_SET*             set,                /**< global SCIP settings */
6840 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6841 	   SCIP_REOPTCONSDATA*   consdata,           /**< reoptimization constraint data that should represent to set of solutions
6842 	                                              *  pruned by the dual reductions */
6843 	   SCIP_REOPTCONSDATA*   dualreds            /**< set of dual reductions */
6844 	   )
6845 	{
6846 	   assert(reopt != NULL);
6847 	   assert(set != NULL);
6848 	   assert(blkmem != NULL);
6849 	   assert(consdata != NULL);
6850 	   assert(dualreds != NULL);
6851 	
6852 	   /* we have to transform the set of bound changes into a linear constraint */
6853 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6854 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, dualreds->vals, dualreds->nvars) );
6855 	   SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->boundtypes, dualreds->boundtypes, dualreds->nvars) );
6856 	
6857 	   consdata->varssize = dualreds->nvars;
6858 	   consdata->nvars = dualreds->nvars;
6859 	   consdata->constype = REOPT_CONSTYPE_DUALREDS;
6860 	   consdata->linear = FALSE;
6861 	
6862 	   /* set lhs and rhs */
6863 	   consdata->lhs = SCIP_UNKNOWN;
6864 	   consdata->rhs = SCIP_UNKNOWN;
6865 	
6866 	   for( int v = 0; v < consdata->nvars; ++v )
6867 	   {
6868 	      SCIP_Real glbbd;
6869 	
6870 	      assert(consdata->vars[v] != NULL);
6871 	
6872 	      /* we do the followung to transformations:
6873 	       * (a) x <= val   ==>   (x >= val+1)
6874 	       * (b) x >= val   ==>   (x <= val-1)
6875 	       */
6876 	      if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
6877 	      {
6878 	         glbbd = SCIPvarGetUbGlobal(consdata->vars[v]);
6879 	         consdata->vals[v] = MIN(consdata->vals[v]+1.0, glbbd);
6880 	      }
6881 	      else
6882 	      {
6883 	         assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6884 	         glbbd = SCIPvarGetLbGlobal(consdata->vars[v]);
6885 	         consdata->vals[v] = MAX(glbbd, consdata->vals[v]-1.0);
6886 	      }
6887 	      consdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - consdata->boundtypes[v]); /*lint !e656*/
6888 	   }
6889 	
6890 	   return SCIP_OKAY;
6891 	}
6892 	
6893 	/** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
6894 	SCIP_RETCODE SCIPreoptSplitRoot(
6895 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
6896 	   SCIP_TREE*            tree,               /**< branch and bound tree */
6897 	   SCIP_SET*             set,                /**< global SCIP settings */
6898 	   SCIP_STAT*            stat,               /**< dynamic SCIP statistics */
6899 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6900 	   int*                  ncreatedchilds,     /**< pointer to store the number of created nodes */
6901 	   int*                  naddedconss         /**< pointer to store the number added constraints */
6902 	   )
6903 	{
6904 	   SCIP_REOPTTREE* reopttree;
6905 	   SCIP_REOPTNODE** reoptnodes;
6906 	   SCIP_REOPTCONSDATA* consdata;
6907 	   SCIP_VAR** vars;
6908 	   SCIP_Real* bounds;
6909 	   SCIP_BOUNDTYPE* boundtypes;
6910 	   int* perm = NULL;
6911 	   unsigned int id;
6912 	   int nbndchgs;
6913 	   int nchilds;
6914 	   int nvars = 0;
6915 	   int v;
6916 	
6917 	   assert(reopt != NULL);
6918 	   assert(set != NULL);
6919 	   assert(stat != NULL);
6920 	   assert(blkmem != NULL);
6921 	
6922 	   reopttree = reopt->reopttree;
6923 	   assert(reopttree != NULL);
6924 	
6925 	   reoptnodes = reopttree->reoptnodes;
6926 	   assert(reoptnodes != NULL);
6927 	   assert(reoptnodes[0] != NULL);
6928 	   assert(reoptnodes[0]->dualreds);
6929 	   assert(reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
6930 	
6931 	   nchilds = reoptnodes[0]->nchilds;
6932 	
6933 	   assert(reoptnodes[0]->dualredscur != NULL);
6934 	   nbndchgs = reoptnodes[0]->dualredscur->nvars;
6935 	
6936 	   (*ncreatedchilds) = 0;
6937 	   (*naddedconss) = 0;
6938 	
6939 	   /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
6940 	
6941 	   /* ensure that two free slots are available  */
(1) Event cond_false: Condition "(_restat_ = reopttreeCheckMemory(reopttree, set, blkmem)) != SCIP_OKAY", taking false branch.
(2) Event if_end: End of if statement.
6942 	   SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
(3) Event return_constant: Function call "SCIPqueueRemoveUInt(reopttree->openids)" may return 4294967295.
(4) Event assignment: Assigning: "id" = "SCIPqueueRemoveUInt(reopttree->openids)". The value of "id" is now 4294967295.
Also see events: [overrun-buffer-arg]
6943 	   id = SCIPqueueRemoveUInt(reopttree->openids);
6944 	
6945 	   assert(0 < id && id < reopt->reopttree->reoptnodessize);
6946 	   assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
6947 	
6948 	   /*   1. create the node
6949 	    *   2. add all bound changes
6950 	    *   3. move all child nodes to id
6951 	    *   4. add id as a child of the root node
6952 	    */
(5) Event cond_false: Condition "(_restat_ = createReoptnode(reopttree, set, blkmem, id)) != SCIP_OKAY", taking false branch.
(6) Event if_end: End of if statement.
6953 	   SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6954 	   reoptnodes[id]->parentID = 0;
6955 	   reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6956 	
6957 	   /* check memory */
(7) Event cond_false: Condition "(_restat_ = reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0)) != SCIP_OKAY", taking false branch.
(8) Event if_end: End of if statement.
6958 	   SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0) );
6959 	   assert(reoptnodes[id]->varssize >= nbndchgs);
6960 	   assert(reoptnodes[id]->nvars == 0);
6961 	   assert(reoptnodes[id]->vars != NULL);
6962 	   assert(reoptnodes[id]->varbounds != NULL);
6963 	   assert(reoptnodes[id]->varboundtypes != NULL);
6964 	
6965 	   /* create a permutation array */
(9) Event cond_true: Condition "!set->reopt_usesplitcons", taking true branch.
6966 	   if( !set->reopt_usesplitcons )
6967 	   {
6968 	      assert(perm == NULL);
(10) Event cond_false: Condition "(perm = BMSallocBufferMemoryArray_call(set->buffer, (size_t)(ptrdiff_t)nbndchgs, 4UL /* sizeof (*perm) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scip-soplex-9.0.0_rc1/scip/src/scip/reopt.c", 6969)) == NULL", taking false branch.
(11) Event cond_false: Condition "(_restat_ = (((perm = BMSallocBufferMemoryArray_call(set->buffer, (size_t)(ptrdiff_t)nbndchgs, 4UL /* sizeof (*perm) */, "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scip-soplex-9.0.0_rc1/scip/src/scip/reopt.c", 6969)) == NULL) ? SCIP_NOMEMORY : SCIP_OKAY)) != SCIP_OKAY", taking false branch.
(12) Event if_end: End of if statement.
6969 	      SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nbndchgs) );
6970 	   }
6971 	
6972 	   /* copy bounds */
(13) Event cond_true: Condition "v < nbndchgs", taking true branch.
(16) Event loop_begin: Jumped back to beginning of loop.
(17) Event cond_true: Condition "v < nbndchgs", taking true branch.
(20) Event loop_begin: Jumped back to beginning of loop.
(21) Event cond_false: Condition "v < nbndchgs", taking false branch.
6973 	   for( v = 0; v < nbndchgs; ++v )
6974 	   {
6975 	      reoptnodes[id]->vars[v] = reoptnodes[0]->dualredscur->vars[v];
6976 	      reoptnodes[id]->varbounds[v] = reoptnodes[0]->dualredscur->vals[v];
6977 	      reoptnodes[id]->varboundtypes[v] = reoptnodes[0]->dualredscur->boundtypes[v];
6978 	      ++reoptnodes[id]->nvars;
6979 	
6980 	      /* fill a permutation array */
(14) Event cond_true: Condition "!set->reopt_usesplitcons", taking true branch.
(18) Event cond_true: Condition "!set->reopt_usesplitcons", taking true branch.
6981 	      if( !set->reopt_usesplitcons )
6982 	         perm[v] = v;   /*lint !e613*/
(15) Event loop: Jumping back to the beginning of the loop.
(19) Event loop: Jumping back to the beginning of the loop.
(22) Event loop_end: Reached end of loop.
6983 	   }
6984 	   assert(reoptnodes[id]->nvars == reoptnodes[0]->dualredscur->nvars);
6985 	
6986 	   /* move the children */
(23) Event overrun-buffer-arg: Calling "reoptMoveIDs" with "reopttree->reoptnodes" and "id" is suspicious because of the very large index, 4294967295. The index may be due to a negative parameter being interpreted as unsigned. [details]
Also see events: [return_constant][assignment]
6987 	   SCIP_CALL( reoptMoveIDs(reopttree, set, blkmem, 0, id) );
6988 	   assert(reoptnodes[0]->nchilds == 0);
6989 	
6990 	   /* add the new reoptimization node as a child of the root node */
6991 	   SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
6992 	
6993 	   ++(*ncreatedchilds);
6994 	
6995 	   if( set->reopt_usesplitcons )
6996 	   {
6997 	      int nbinvars = 0;
6998 	#ifndef NDEBUG
6999 	      int nintvars = 0;
7000 	      int ncontvars = 0;
7001 	#endif
7002 	
7003 	      assert(*ncreatedchilds == 1);
7004 	
7005 	      /* ensure that there is a free slots */
7006 	      SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
7007 	      id = SCIPqueueRemoveUInt(reopttree->openids);
7008 	      assert(0 < id && id < reopt->reopttree->reoptnodessize);
7009 	
7010 	      /* 1. create the node
7011 	       * 2. add the constraint to ensure that at least one
7012 	       *    variable gets different
7013 	       * 3. add id as a child of the root node
7014 	       */
7015 	      SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7016 	      reoptnodes[id]->parentID = 0;
7017 	      reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
7018 	
7019 	      /* check memory for added constraints */
7020 	      SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, 0, 0, 1) );
7021 	
7022 	      /* create the constraint */
7023 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnodes[id]->conss[0]) );
7024 	      consdata = reoptnodes[id]->conss[0];
7025 	
7026 	      /* count number of binary, integer, and continuous varibales */
7027 	      for( v = 0; v < nbndchgs; ++v )
7028 	      {
7029 	         switch( SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]) ) {
7030 	         case SCIP_VARTYPE_BINARY:
7031 	            ++nbinvars;
7032 	            break;
7033 	         case SCIP_VARTYPE_INTEGER:
7034 	         case SCIP_VARTYPE_IMPLINT:
7035 	#ifndef NDEBUG
7036 	            ++nintvars;
7037 	#endif
7038 	            break;
7039 	         case SCIP_VARTYPE_CONTINUOUS:
7040 	#ifndef NDEBUG
7041 	            ++ncontvars;
7042 	#endif
7043 	            break;
7044 	         default:
7045 	            SCIPerrorMessage("Cannot handle vartype %d\n", SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]));
7046 	            return SCIP_INVALIDDATA;
7047 	         }
7048 	      }
7049 	
7050 	      /* we create a linear constraint, since all variables are binary */
7051 	      if( nbinvars == nbndchgs )
7052 	      {
7053 	         SCIP_CALL( transformDualredsToLinear(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7054 	      }
7055 	      /* we create a bounddisjunction constraint, since at least one variable is (implicit) integer or continuous */
7056 	      else
7057 	      {
7058 	         assert(nintvars > 0 || ncontvars > 0);
7059 	         SCIP_CALL( transformDualredsToBounddisjunction(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7060 	      }
7061 	      ++reoptnodes[id]->nconss;
7062 	
7063 	      /* add id as a child of the root node */
7064 	      SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7065 	      ++(*ncreatedchilds);
7066 	
7067 	      ++(*naddedconss);
7068 	   }
7069 	   else
7070 	   {
7071 	      assert(*ncreatedchilds == 1);
7072 	      assert(perm != NULL);
7073 	
7074 	      vars = reoptnodes[0]->dualredscur->vars;
7075 	      bounds = reoptnodes[0]->dualredscur->vals;
7076 	      boundtypes = reoptnodes[0]->dualredscur->boundtypes;
7077 	      nvars = reoptnodes[0]->dualredscur->nvars;
7078 	      assert(perm[0] == 0 && perm[nvars-1] == nvars-1);
7079 	
7080 	      /* calculate the order of the variables */
7081 	      switch (set->reopt_varorderinterdiction)
7082 	      {
7083 	         /* default order */
7084 	         case 'd':
7085 	            break;
7086 	
7087 	         /* inference order */
7088 	         case 'i':
7089 	            SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7090 	            break;
7091 	
7092 	         /* random order */
7093 	         case 'r':
7094 	            SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7095 	            break;
7096 	
7097 	         default:
7098 	            return SCIP_INVALIDDATA;
7099 	      }
7100 	
7101 	      /* create nvars nodes in the fashion of interdiction branching */
7102 	      for( int c = 0; c < nvars; ++c )
7103 	      {
7104 	         /* ensure that two free slots are available  */
7105 	         SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
7106 	         id = SCIPqueueRemoveUInt(reopttree->openids);
7107 	
7108 	         assert(0 < id && id < reopt->reopttree->reoptnodessize);
7109 	         assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
7110 	
7111 	         /*   1. create the node
7112 	          *   2. fix the first v bound changes to vals[v] and v+1 to vals[v] +/- 1 (depending on the bound- and vartype)
7113 	          *   4. add the ID id as a child of the root node
7114 	          */
7115 	         SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7116 	         reoptnodes[id]->parentID = 0;
7117 	         reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7118 	
7119 	         /* check memory */
7120 	         SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, c+1, 0, 0) );
7121 	         assert(reoptnodes[id]->varssize >= perm[c]+1);
7122 	         assert(reoptnodes[id]->nvars == 0);
7123 	         assert(reoptnodes[id]->vars != NULL);
7124 	         assert(reoptnodes[id]->varbounds != NULL);
7125 	         assert(reoptnodes[id]->varboundtypes != NULL);
7126 	
7127 	         /* the permutation is the identity */
7128 	         if( set->reopt_varorderinterdiction == 'd' )
7129 	         {
7130 	            /* copy first c bound changes */
7131 	            for( v = 0; v < c; ++v )
7132 	            {
7133 	               reoptnodes[id]->vars[v] = vars[v];
7134 	               reoptnodes[id]->varbounds[v] = bounds[v];
7135 	               reoptnodes[id]->varboundtypes[v] = boundtypes[v];
7136 	            }
7137 	         }
7138 	         else
7139 	         {
7140 	            /* copy first c bound changes */
7141 	            for( v = 0; v < c; ++v )
7142 	            {
7143 	               reoptnodes[id]->vars[v] = vars[perm[v]];
7144 	               reoptnodes[id]->varbounds[v] = bounds[perm[v]];
7145 	               reoptnodes[id]->varboundtypes[v] = boundtypes[perm[v]];
7146 	            }
7147 	         }
7148 	         reoptnodes[id]->nvars += c;
7149 	
7150 	         /* set bound change v+1 (= c) to vals[v] +/- 1 (depending on the bound- and vartype) */
7151 	         assert(v == c);
7152 	         reoptnodes[id]->vars[c] = vars[perm[c]];
7153 	         reoptnodes[id]->varbounds[c] = bounds[perm[c]];
7154 	         if( SCIPvarGetType(vars[perm[c]]) != SCIP_VARTYPE_CONTINUOUS )
7155 	         {
7156 	            if( boundtypes[perm[c]] == SCIP_BOUNDTYPE_LOWER )
7157 	               reoptnodes[id]->varbounds[c] -= 1.0;
7158 	            else
7159 	               reoptnodes[id]->varbounds[c] += 1.0;
7160 	         }
7161 	         reoptnodes[id]->varboundtypes[c] = (boundtypes[perm[c]] == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
7162 	         ++reoptnodes[id]->nvars;
7163 	
7164 	         /* add dummy1 as a child of the root node */
7165 	         SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7166 	
7167 	         ++(*ncreatedchilds);
7168 	      }
7169 	
7170 	      assert(*ncreatedchilds == nvars+1);
7171 	
7172 	      SCIPsetFreeBufferArray(set, &perm);
7173 	      perm = NULL;
7174 	   }
7175 	   assert(perm == NULL);
7176 	
7177 	   /* free the current dualredscur and assign dualredsnex */
7178 	   assert(reoptnodes[0]->dualredscur->vars != NULL);
7179 	   assert(reoptnodes[0]->dualredscur->vals != NULL);
7180 	   assert(reoptnodes[0]->dualredscur->boundtypes != NULL);
7181 	
7182 	   /* free the current dualredscur and assign dualredsnex */
7183 	   SCIP_CALL( reoptnodeUpdateDualConss(reoptnodes[0], blkmem) );
7184 	
7185 	   /* change the reopttype of the root node */
7186 	   SCIPnodeSetReopttype(SCIPtreeGetRootNode(tree), SCIP_REOPTTYPE_TRANSIT);
7187 	
7188 	   return SCIP_OKAY;
7189 	}
7190 	
7191 	/** reset the stored information abound bound changes based on dual information */
7192 	SCIP_RETCODE SCIPreoptResetDualBndchgs(
7193 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7194 	   SCIP_NODE*            node,               /**< node of the search tree */
7195 	   BMS_BLKMEM*           blkmem              /**< block memory */
7196 	   )
7197 	{
7198 	   unsigned int id;
7199 	
7200 	   assert(reopt != NULL);
7201 	   assert(node != NULL);
7202 	
7203 	   id = SCIPnodeGetReoptID(node);
7204 	   assert(id < reopt->reopttree->reoptnodessize);
7205 	
7206 	   /* return if the node is not part of the reoptimization tree */
7207 	   if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7208 	      return SCIP_OKAY;
7209 	
7210 	   /* reset the dual constraint */
7211 	   SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7212 	
7213 	   return SCIP_OKAY;
7214 	}
7215 	
7216 	/** return the branching path stored of the given node in the reoptimization tree */
7217 	void SCIPreoptnodeGetPath(
7218 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7219 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reoptimization tree */
7220 	   SCIP_VAR**            vars,               /**< array for variables */
7221 	   SCIP_Real*            vals,               /**< array for values */
7222 	   SCIP_BOUNDTYPE*       boundtypes,         /**< array for bound types */
7223 	   int                   varssize,           /**< size of arrays vars, vals, and boundtypes */
7224 	   int*                  nbndchgs,           /**< pointer to store the number of bound changes */
7225 	   int*                  nbndchgsafterdual   /**< pointer to store the number of bound changes applied after
7226 	                                              *  the first dual reduction at the given node */
7227 	   )
7228 	{
7229 	   int v;
7230 	   int nvars2;
7231 	   int nafterdualvars2;
7232 	
7233 	   assert(reopt != NULL);
7234 	   assert(reoptnode != NULL);
7235 	   assert(vars != NULL);
7236 	   assert(vals != NULL);
7237 	   assert(boundtypes != NULL);
7238 	
7239 	   (*nbndchgs) = reoptnode->nvars;
7240 	   (*nbndchgsafterdual) = reoptnode->nafterdualvars;
7241 	
7242 	   /* return if the size of the given array is not large enough */
7243 	   if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
7244 	      return;
7245 	
7246 	   /* add all bound changes made by branching (including dual reductions) */
7247 	   for( v = 0; v < *nbndchgs; ++v )
7248 	   {
7249 	      vars[v] = reoptnode->vars[v];
7250 	      vals[v] = reoptnode->varbounds[v];
7251 	      boundtypes[v] = reoptnode->varboundtypes[v];
7252 	   }
7253 	
7254 	   /* add all bound changes made applied after a dual reduction */
7255 	   for( ; v < *nbndchgs + *nbndchgsafterdual; ++v )
7256 	   {
7257 	      vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
7258 	      vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
7259 	      boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
7260 	   }
7261 	
7262 	   /* go along the root path within the reoptimization tree */
7263 	   if( reoptnode->parentID != 0 )
7264 	   {
7265 	      SCIP_REOPTNODE* parent;
7266 	
7267 	      parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
7268 	      SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
7269 	
7270 	      (*nbndchgs) += nvars2;
7271 	      (*nbndchgsafterdual) += nafterdualvars2;
7272 	   }
7273 	}
7274 	
7275 	/** delete a node stored in the reoptimization tree */
7276 	SCIP_RETCODE SCIPreoptDeleteNode(
7277 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7278 	   SCIP_SET*             set,                /**< global SCIP settings */
7279 	   unsigned int          id,                 /**< id of a stored node */
7280 	   BMS_BLKMEM*           blkmem              /**< block memory */
7281 	   )
7282 	{
7283 	   assert(reopt != NULL);
7284 	   assert(reopt->reopttree != NULL);
7285 	   assert(id < reopt->reopttree->reoptnodessize);
7286 	   assert(reopt->reopttree->reoptnodes[id] != NULL);
7287 	   assert(blkmem != NULL);
7288 	
7289 	   SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
7290 	   SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, id) );
7291 	
7292 	   return SCIP_OKAY;
7293 	}
7294 	
7295 	/** reactivate the given @p reoptnode and split them into several nodes if necessary */
7296 	SCIP_RETCODE SCIPreoptApply(
7297 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7298 	   SCIP*                 scip,               /**< SCIP data structure */
7299 	   SCIP_SET*             set,                /**< global SCIP settings */
7300 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
7301 	   SCIP_PROB*            transprob,          /**< transformed problem */
7302 	   SCIP_PROB*            origprob,           /**< original problem */
7303 	   SCIP_TREE*            tree,               /**< branching tree */
7304 	   SCIP_LP*              lp,                 /**< current LP */
7305 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate */
7306 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7307 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table */
7308 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7309 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reoptimization tree to reactivate */
7310 	   unsigned int          id,                 /**< id of the node to reactivate */
7311 	   SCIP_Real             estimate,           /**< estimate of the child nodes that should be created */
7312 	   SCIP_NODE**           childnodes,         /**< array to store the created child nodes */
7313 	   int*                  ncreatedchilds,     /**< pointer to store number of created child nodes */
7314 	   int*                  naddedconss,        /**< pointer to store number of generated constraints */
7315 	   int                   childnodessize,     /**< available size of childnodes array */
7316 	   SCIP_Bool*            success             /**< pointer store the result */
7317 	   )
7318 	{
7319 	   assert(reopt != NULL);
7320 	   assert(scip != NULL);
7321 	   assert(set != NULL);
7322 	   assert(stat != NULL);
7323 	   assert(transprob != NULL);
7324 	   assert(origprob != NULL);
7325 	   assert(tree != NULL);
7326 	   assert(lp != NULL);
7327 	   assert(branchcand != NULL);
7328 	   assert(eventqueue != NULL);
7329 	   assert(cliquetable != NULL);
7330 	   assert(blkmem != NULL);
7331 	   assert(reoptnode != NULL);
7332 	   assert(childnodes != NULL);
7333 	   assert(reopt->reopttree != NULL);
7334 	   assert(id < reopt->reopttree->reoptnodessize);
7335 	   assert(success != NULL);
7336 	
7337 	   SCIPsetDebugMsg(set, "reactivating node at id %u:\n", id);
7338 	
7339 	   *success = FALSE;
7340 	
7341 	   /* check if we need to split the node */
7342 	   if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
7343 	      || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7344 	   {
7345 	      assert(reoptnode->dualreds);
7346 	
7347 	      /* we want use a constraint to split the node into two disjoint node */
7348 	      if( set->reopt_usesplitcons )
7349 	      {
7350 	         if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7351 	         {
7352 	            assert(reoptnode->dualredscur != NULL);
7353 	            assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
7354 	            (*ncreatedchilds) = 1;
7355 	         }
7356 	         else
7357 	         {
7358 	            assert(reoptnode->dualredscur != NULL);
7359 	            assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7360 	            (*ncreatedchilds) = 2;
7361 	         }
7362 	
7363 	         /* in both cases we add exactly one constraint */
7364 	         (*naddedconss) = 1;
7365 	
7366 	         if( childnodessize < *ncreatedchilds )
7367 	            return SCIP_OKAY;
7368 	
7369 	         /* generate the nodes */
7370 	         for( int c = 0; c < *ncreatedchilds; ++c )
7371 	         {
7372 	            /* create the child node */
7373 	            SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7374 	
7375 	            /* change all bounds; convert the bound changes after the first based on dual reductions into branching
7376 	             * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
7377 	             * changes anyway.
7378 	             */
7379 	            SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7380 	                  cliquetable, blkmem, childnodes[c], id, c == 1) );
7381 	
7382 	            /* add all local constraints */
7383 	            SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7384 	
7385 	            /* we can use the old lowerbound if the objective function has not changed */
7386 	            if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7387 	               SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7388 	
7389 	            if( c == 0 )
7390 	            {
7391 	               /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
7392 	               SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_NONE);
7393 	
7394 	               /* add the constraint to the node */
7395 	               assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7396 	               SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
7397 	                     eventqueue, cliquetable, childnodes[c], id) );
7398 	
7399 	               /* fixBounds() does the same, but in this case we go not into it */
7400 	               if( reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE )
7401 	               {
7402 	                  assert(reoptnode->dualredscur->nvars > 0);
7403 	                  assert(reoptnode->dualredscur->varssize > 0);
7404 	
7405 	                  /* delete dualredscur and move dualredsnex -> dualredscur */
7406 	                  SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
7407 	               }
7408 	
7409 	               /* the added constraint could be deleted due to propagation, thus, we store the node in the reoptimization
7410 	                * tree. the node has to stored anyway, because of the constraint representing the dual reductions
7411 	                */
7412 	               SCIP_CALL( addNode(reopt, set, lp, blkmem, childnodes[c], SCIP_REOPTTYPE_LOGICORNODE, FALSE, FALSE,
7413 	                     -SCIPsetInfinity(set)) );
7414 	            }
7415 	            else
7416 	            {
7417 	               /* if we reach this lines of code, the current node represents the original node including all bound
7418 	                * changes based in dual information.
7419 	                */
7420 	               assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7421 	               if( reoptnode->nconss == 0 )
7422 	                  SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_TRANSIT);
7423 	               else
7424 	                  SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_LOGICORNODE);
7425 	
7426 	               /* fix all bound changes based on dual information and convert them into branchings */
7427 	               assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7428 	               SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7429 	                     blkmem, childnodes[c], id, TRUE) );
7430 	
7431 	               /* set the unique id the id of the original node */
7432 	               SCIPnodeSetReoptID(childnodes[c], id);
7433 	            }
7434 	         }
7435 	
7436 	         /* reset the stored dual constraints */
7437 	         SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7438 	
7439 	         /* set the reoptimization type */
7440 	         if( reopt->reopttree->reoptnodes[id]->dualreds )
7441 	            reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7442 	         else
7443 	            reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7444 	
7445 	         *success = TRUE;
7446 	      }
7447 	      else
7448 	      {
7449 	         SCIP_VAR** vars;
7450 	         SCIP_Real* bounds;
7451 	         SCIP_BOUNDTYPE* boundtypes;
7452 	         int* perm = NULL;
7453 	         int nvars;
7454 	
7455 	         vars = reoptnode->dualredscur->vars;
7456 	         bounds = reoptnode->dualredscur->vals;
7457 	         boundtypes = reoptnode->dualredscur->boundtypes;
7458 	         nvars = reoptnode->dualredscur->nvars;
7459 	
7460 	         *ncreatedchilds = nvars+1;
7461 	         *naddedconss = 0;
7462 	
7463 	         /* check if there is enough memory allocated */
7464 	         if( childnodessize < *ncreatedchilds )
7465 	            return SCIP_OKAY;
7466 	
7467 	         /* create and fill permutation array */
7468 	         SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nvars) );
7469 	         for( int c = 0; c < nvars; ++c )
7470 	            perm[c] = c;
7471 	
7472 	         /* calculate the order of the variables */
7473 	         switch (set->reopt_varorderinterdiction)
7474 	         {
7475 	            /* default order */
7476 	            case 'd':
7477 	               break;
7478 	
7479 	            /* inference order */
7480 	            case 'i':
7481 	               SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7482 	               break;
7483 	
7484 	            /* random order */
7485 	            case 'r':
7486 	               SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7487 	               break;
7488 	
7489 	            default:
7490 	               return SCIP_INVALIDDATA;
7491 	         }
7492 	
7493 	         assert(reopt->reopttree->reoptnodes[id] != NULL);
7494 	         reoptnode = reopt->reopttree->reoptnodes[id];
7495 	
7496 	         /* enough that the node need to split */
7497 	         assert(reoptnode->dualreds);
7498 	
7499 	         /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
7500 	          * we need to do this in the reverse order because we want to transform the bound changes based on dual information
7501 	          * into branching decisions at nodes[0].
7502 	          */
7503 	         for( int c = nvars; c >= 0; --c )
7504 	         {
7505 	            /* create the child node */
7506 	            SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7507 	
7508 	#ifdef SCIP_MORE_DEBUG
7509 	            SCIPsetDebugMsg(set, " change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
7510 	#endif
7511 	
7512 	            /* change all bounds */
7513 	            SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7514 	                  cliquetable, blkmem, childnodes[c], id, FALSE) );
7515 	
7516 	            /* reconstruct the original node and the pruned part, respectively */
7517 	            if( c == 0 )
7518 	            {
7519 	               /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
7520 	               SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7521 	                     blkmem, childnodes[c], id, TRUE) );
7522 	
7523 	               /* set the reopttype of the node */
7524 	               SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_TRANSIT);
7525 	
7526 	               /* set the unique id */
7527 	               SCIPnodeSetReoptID(childnodes[c], id);
7528 	            }
7529 	            else
7530 	            {
7531 	               /* fix the first c bound changes and negate the (c+1)th */
7532 	               SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7533 	                     blkmem, childnodes[c], id, perm, vars, bounds, boundtypes, nvars, c) );
7534 	            }
7535 	
7536 	            /* add all local constraints */
7537 	            SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7538 	
7539 	            /* we can use the old lowerbound if the objective function has not changed */
7540 	            if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7541 	               SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7542 	         }
7543 	
7544 	         /* free buffer array */
7545 	         SCIPsetFreeBufferArray(set, &perm);
7546 	
7547 	         /* reset the stored dual constraints */
7548 	         SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7549 	
7550 	         /* set the reoptimization type to transit */
7551 	         if( reopt->reopttree->reoptnodes[id]->dualreds )
7552 	            reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7553 	         else
7554 	            reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7555 	
7556 	         *success = TRUE;
7557 	      }
7558 	   }
7559 	   else
7560 	   {
7561 	      /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
7562 	      (*ncreatedchilds) = 1;
7563 	      (*naddedconss) = 0;
7564 	
7565 	      if( childnodessize < *ncreatedchilds )
7566 	         return SCIP_OKAY;
7567 	
7568 	      /* create the child node */
7569 	      SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
7570 	
7571 	      /* change all bounds */
7572 	      assert(reoptnode->nafterdualvars == 0);
7573 	      SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7574 	            cliquetable, blkmem, childnodes[0], id, FALSE) );
7575 	
7576 	      /* add all local constraints */
7577 	      SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
7578 	
7579 	      /* we can use the old lowerbound if the objective function has not changed */
7580 	      if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7581 	         SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7582 	
7583 	      /* set the reopttype */
7584 	      assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
7585 	          && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
7586 	      SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
7587 	
7588 	      /* set the unique id */
7589 	      SCIPnodeSetReoptID(childnodes[0], id);
7590 	
7591 	      *success = TRUE;
7592 	   }
7593 	
7594 	   return SCIP_OKAY;
7595 	}
7596 	
7597 	/** returns the time needed to store the nodes for reoptimization */
7598 	SCIP_Real SCIPreoptGetSavingtime(
7599 	   SCIP_REOPT*           reopt               /**< reoptimization data structure */
7600 	   )
7601 	{
7602 	   assert(reopt != NULL);
7603 	
7604 	   return SCIPclockGetTime(reopt->savingtime);
7605 	}
7606 	
7607 	/** add the stored constraints globally to the problem */
7608 	SCIP_RETCODE SCIPreoptApplyGlbConss(
7609 	   SCIP*                 scip,               /**< SCIP data structure */
7610 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7611 	   SCIP_SET*             set,                /**< global SCIP settings */
7612 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
7613 	   BMS_BLKMEM*           blkmem              /**< block memory */
7614 	   )
7615 	{
7616 	   char name[SCIP_MAXSTRLEN];
7617 	
7618 	   assert(scip != NULL);
7619 	   assert(reopt != NULL);
7620 	   assert(set != NULL);
7621 	   assert(stat != NULL);
7622 	   assert(blkmem != NULL);
7623 	
7624 	   if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
7625 	      return SCIP_OKAY;
7626 	
7627 	   for( int c = reopt->nglbconss-1; c >= 0; --c )
7628 	   {
7629 	      SCIP_CONS* cons;
7630 	      SCIP_VAR** consvars;
7631 	      int nbinvars;
7632 	      int nintvars;
7633 	
7634 	      assert(reopt->glbconss[c] != NULL);
7635 	      assert(reopt->glbconss[c]->nvars > 0);
7636 	
7637 	      cons = NULL;
7638 	      consvars = NULL;
7639 	      nbinvars = 0;
7640 	      nintvars = 0;
7641 	
7642 	      /* check if we can use a logic-or or if we have to use a bounddisjuction constraint */
7643 	      for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
7644 	      {
7645 	         if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_BINARY )
7646 	            ++nbinvars;
7647 	         else if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_INTEGER
7648 	               || SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_IMPLINT )
7649 	            ++nintvars;
7650 	         else
7651 	         {
7652 	            SCIPerrorMessage("Expected variable type binary or (impl.) integer for variable <%s> in global constraint at pos. %d.\n",
7653 	                  SCIPvarGetName(reopt->glbconss[c]->vars[v]), c);
7654 	            return SCIP_INVALIDDATA;
7655 	         }
7656 	      }
7657 	
7658 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "glb_%s_%d_%d", reopt->glbconss[c]->constype == REOPT_CONSTYPE_CUT ? "cut" : "inf", reopt->run, c);
7659 	
7660 	      /* @todo use active representatives */
7661 	
7662 	      /* all variables are binary, we can create a logic-or constraint */
7663 	      if( nbinvars == reopt->glbconss[c]->nvars )
7664 	      {
7665 	         SCIPsetDebugMsg(set, "-> add logic-or constraints with %d binvars\n", nbinvars);
7666 	
7667 	         /* allocate buffer */
7668 	         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
7669 	
7670 	         for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
7671 	         {
7672 	            consvars[v] = reopt->glbconss[c]->vars[v];
7673 	            assert(SCIPvarIsOriginal(consvars[v]));
7674 	
7675 	            /* negate the variable if it was fixed to 1 */
7676 	            if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 0.0) )
7677 	            {
7678 	               assert(reopt->glbconss[c]->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
7679 	               SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
7680 	            }
7681 	         }
7682 	
7683 	         /* create the logic-or constraint */
7684 	         SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->glbconss[c]->nvars,
7685 	               consvars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7686 	
7687 	         /* free buffer */
7688 	         SCIPfreeBufferArray(scip, &consvars);
7689 	      }
7690 	      /* not all variables are binary, we need a bounddisjunction constraint */
7691 	      else
7692 	      {
7693 	         assert(reopt->glbconss[c]->nvars == nbinvars + 2*nintvars);
7694 	
7695 	         SCIPsetDebugMsg(set, "-> add bounddisjuction constraints with %d binvars, %d intvars\n", nbinvars, (int) (2*nintvars));
7696 	
7697 	         /* create the bounddisjuction constraint */
7698 	         SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, name, reopt->glbconss[c]->nvars, reopt->glbconss[c]->vars,
7699 	               reopt->glbconss[c]->boundtypes, reopt->glbconss[c]->vals) );
7700 	      }
7701 	
7702 	#ifdef SCIP_DEBUG_CONSS
7703 	      SCIPdebugPrintCons(scip, cons, NULL);
7704 	#endif
7705 	
7706 	      SCIP_CALL( SCIPaddCons(scip, cons) );
7707 	
7708 	      /* remember the constraint for re-activation */
7709 	      assert(!SCIPhashsetExists(reopt->activeconssset, (void*)cons));
7710 	      SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)cons) );
7711 	      SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, reopt->nactiveconss + 1) );
7712 	      assert(reopt->nactiveconss < reopt->nmaxactiveconss);
7713 	      reopt->activeconss[reopt->nactiveconss++] = cons;
7714 	
7715 	      /* don't release the constraint because we would need to capture the constraint anyway */
7716 	
7717 	      /* mark the constraint as empty */
7718 	      reopt->glbconss[c]->nvars = 0;
7719 	   }
7720 	
7721 	   SCIPsetDebugMsg(set, "added %d gobal constraints\n", reopt->nglbconss);
7722 	
7723 	   /* reset number of global constraints */
7724 	   reopt->nglbconss = 0;
7725 	
7726 	   return SCIP_OKAY;
7727 	}
7728 	
7729 	/** add the stored cuts to the separation storage */
7730 	SCIP_RETCODE SCIPreoptApplyCuts(
7731 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7732 	   SCIP_NODE*            node,               /**< current focus node */
7733 	   SCIP_SEPASTORE*       sepastore,          /**< separation storage */
7734 	   SCIP_CUTPOOL*         cutpool,            /**< global cutpool */
7735 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7736 	   SCIP_SET*             set,                /**< global SCIP settings */
7737 	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
7738 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
7739 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter */
7740 	   SCIP_LP*              lp,                 /**< current LP */
7741 	   SCIP_Bool             root                /**< bool whether the current node is the root */
7742 	   )
7743 	{
7744 	   SCIP_REOPTNODE* reoptnode;
7745 	   SCIP_Bool infeasible;
7746 	   unsigned int id;
7747 	   int ncuts;
7748 	
7749 	   assert(reopt != NULL);
7750 	   assert(node != NULL);
7751 	   assert(sepastore != NULL);
7752 	   assert(blkmem != NULL);
7753 	   assert(set != NULL);
7754 	   assert(stat != NULL);
7755 	   assert(eventqueue != NULL);
7756 	   assert(eventfilter != NULL);
7757 	   assert(lp != NULL);
7758 	
7759 	   id = SCIPnodeGetReoptID(node);
7760 	   assert(id < reopt->reopttree->reoptnodessize);
7761 	
7762 	   /* skip nodes that are node part of the reoptimization tree */
7763 	   if( id == 0 && SCIPnodeGetDepth(node) > 0 )
7764 	      return SCIP_OKAY;
7765 	
7766 	   reoptnode = reopt->reopttree->reoptnodes[id];
7767 	   assert(reoptnode != NULL);
7768 	
7769 	   ncuts = 0;
7770 	   for( int c = reoptnode->nconss-1; c >= 0; --c )
7771 	   {
7772 	      SCIP_REOPTCONSDATA* cons;
7773 	
7774 	      cons = reoptnode->conss[c];
7775 	      assert(cons != NULL);
7776 	
7777 	      if( cons->constype == REOPT_CONSTYPE_CUT )
7778 	      {
7779 	         SCIP_ROW* cut;
7780 	         SCIP_COL** cols;
7781 	         SCIP_Real* vals;
7782 	         char cutname[SCIP_MAXSTRLEN];
7783 	         int ncols;
7784 	
7785 	         SCIP_CALL( SCIPsetAllocBufferArray(set, &cols, cons->nvars) );
7786 	         SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, cons->nvars) );
7787 	
7788 	         ncols = 0;
7789 	         for( int v = 0; v < cons->nvars; ++v )
7790 	         {
7791 	            SCIP_VAR* transvar;
7792 	
7793 	            assert(SCIPvarIsOriginal(cons->vars[v]));
7794 	
7795 	            transvar = SCIPvarGetTransVar(cons->vars[v]);
7796 	            assert(transvar != NULL);
7797 	            assert(SCIPvarGetStatus(transvar) == SCIP_VARSTATUS_COLUMN);
7798 	
7799 	            vals[ncols] = cons->vals[v];
7800 	            cols[ncols] = SCIPvarGetCol(transvar);
7801 	            assert(cols[ncols] != NULL);
7802 	
7803 	            ++ncols;
7804 	         }
7805 	         assert(ncols == cons->nvars);
7806 	
7807 	         (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "reoptcut_%d_%d", id, ncuts);
7808 	         infeasible = FALSE;
7809 	
7810 	         if( id == 0 )
7811 	         {
7812 	            SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7813 	                  SCIP_ROWORIGINTYPE_REOPT, NULL, FALSE, FALSE, TRUE) );
7814 	            SCIP_CALL( SCIPcutpoolAddRow(cutpool, blkmem, set, stat, lp, cut) );
7815 	
7816 	            SCIPsetDebugMsg(set, "add cut <%s> of size %d to cutpool, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7817 	               ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7818 	         }
7819 	         else
7820 	         {
7821 	            SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7822 	                  SCIP_ROWORIGINTYPE_REOPT, NULL, TRUE, TRUE, TRUE) );
7823 	            SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, FALSE, root,
7824 	                  &infeasible) );
7825 	
7826 	            SCIPsetDebugMsg(set, "add cut <%s> of size %d to sepastore, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7827 	               ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7828 	         }
7829 	
7830 	         SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
7831 	
7832 	         if( infeasible )
7833 	            SCIPsetDebugMsg(set, "cut %d stored at node %" SCIP_LONGINT_FORMAT " (id: %u) is infeasible.\n", c, SCIPnodeGetNumber(node), id);
7834 	         else
7835 	            ++ncuts;
7836 	
7837 	         SCIPsetFreeBufferArray(set, &vals);
7838 	         SCIPsetFreeBufferArray(set, &cols);
7839 	
7840 	         BMSfreeBlockMemoryArrayNull(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
7841 	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
7842 	         BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
7843 	         BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866*/
7844 	         --reoptnode->nconss;
7845 	      }
7846 	      else
7847 	      {
7848 	#ifndef NDEBUG
7849 	         for( int i = c-1; i >= 0; --i )
7850 	            assert(reoptnode->conss[i]->constype != REOPT_CONSTYPE_CUT);
7851 	#endif
7852 	         break;
7853 	      }
7854 	   }
7855 	
7856 	   return SCIP_OKAY;
7857 	}
7858 	
7859 	/** check if the LP of the given node should be solved or not */
7860 	SCIP_Bool SCIPreoptGetSolveLP(
7861 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7862 	   SCIP_SET*             set,                /**< global SCIP settings */
7863 	   SCIP_NODE*            node                /**< node of the current search tree */
7864 	   )
7865 	{
7866 	   unsigned int id;
7867 	
7868 	   assert(reopt != NULL);
7869 	   assert(node != NULL);
7870 	
7871 	   /* get the ID */
7872 	   id = SCIPnodeGetReoptID(node);
7873 	   assert(id < reopt->reopttree->reoptnodessize);
7874 	
7875 	   /* return if the node is not part of the reoptimization tree */
7876 	   if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7877 	      return TRUE;
7878 	
7879 	   /* return always true if the parameter is set to 1.0 */
7880 	   if( SCIPsetIsGE(set, set->reopt_objsimrootlp, 1.0) )
7881 	      return TRUE;
7882 	
7883 	   /* current node is the root */
7884 	   if( id == 0 )
7885 	   {
7886 	      if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
7887 	      {
7888 	         /* the objective function has changed only slightly */
7889 	         if( SCIPsetIsGE(set, reopt->simtolastobj, set->reopt_objsimrootlp) )
7890 	            return FALSE;
7891 	      }
7892 	   }
7893 	   else
7894 	   {
7895 	      /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
7896 	      if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
7897 	      {
7898 	         assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
7899 	         return FALSE;
7900 	      }
7901 	   }
7902 	
7903 	   return TRUE;
7904 	}
7905 	
7906 	/** initialize an empty node */
7907 	void SCIPreoptnodeInit(
7908 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reopttree */
7909 	   SCIP_SET*             set                 /**< global SCIP settings */
7910 	   )
7911 	{
7912 	   assert(reoptnode != NULL);
7913 	   assert(set != NULL);
7914 	
7915 	   reoptnode->conss = NULL;
7916 	   reoptnode->nconss = 0;
7917 	   reoptnode->consssize = 0;
7918 	   reoptnode->childids = NULL;
7919 	   reoptnode->allocchildmem = 0;
7920 	   reoptnode->nchilds = 0;
7921 	   reoptnode->nvars = 0;
7922 	   reoptnode->nafterdualvars = 0;
7923 	   reoptnode->parentID = 0;
7924 	   reoptnode->dualreds = FALSE;
7925 	   reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
7926 	   reoptnode->varssize = 0;
7927 	   reoptnode->afterdualvarssize = 0;
7928 	   reoptnode->vars = NULL;
7929 	   reoptnode->varbounds = NULL;
7930 	   reoptnode->varboundtypes = NULL;
7931 	   reoptnode->afterdualvars = NULL;
7932 	   reoptnode->afterdualvarbounds = NULL;
7933 	   reoptnode->afterdualvarboundtypes = NULL;
7934 	   reoptnode->dualredscur = NULL;
7935 	   reoptnode->dualredsnex = NULL;
7936 	   reoptnode->lowerbound = -SCIPsetInfinity(set);
7937 	}
7938 	
7939 	/** reset the given reoptimization node */
7940 	SCIP_RETCODE SCIPreoptnodeReset(
7941 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
7942 	   SCIP_SET*             set,                /**< global SCIP settings */
7943 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7944 	   SCIP_REOPTNODE*       reoptnode           /**< reoptimization node */
7945 	   )
7946 	{
7947 	   assert(reopt != NULL);
7948 	   assert(set != NULL);
7949 	   assert(blkmem != NULL);
7950 	   assert(reoptnode != NULL);
7951 	
7952 	   SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
7953 	
7954 	   return SCIP_OKAY;
7955 	}
7956 	
7957 	/** delete the given reoptimization node */
7958 	SCIP_RETCODE SCIPreoptnodeDelete(
7959 	   SCIP_REOPTNODE**      reoptnode,          /**< pointer of reoptnode */
7960 	   BMS_BLKMEM*           blkmem              /**< block memory */
7961 	   )
7962 	{
7963 	   assert(reoptnode != NULL);
7964 	   assert(blkmem != NULL);
7965 	
7966 	   SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
7967 	
7968 	   return SCIP_OKAY;
7969 	}
7970 	
7971 	/** add a variable to a given reoptnode */
7972 	SCIP_RETCODE SCIPreoptnodeAddBndchg(
7973 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reopttree */
7974 	   SCIP_SET*             set,                /**< global SCIP settings */
7975 	   BMS_BLKMEM*           blkmem,             /**< block memory */
7976 	   SCIP_VAR*             var,                /**< variable to add */
7977 	   SCIP_Real             val,                /**< value of the variable */
7978 	   SCIP_BOUNDTYPE        boundtype           /**< boundtype of the variable */
7979 	   )
7980 	{
7981 	   int nvars;
7982 	
7983 	   assert(reoptnode != NULL);
7984 	   assert(var != NULL);
7985 	   assert(blkmem != NULL);
7986 	
7987 	   nvars = reoptnode->nvars;
7988 	
7989 	   SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, nvars + 1, 0, 0) );
7990 	
7991 	   reoptnode->vars[nvars] = var;
7992 	   reoptnode->varbounds[nvars] = val;
7993 	   reoptnode->varboundtypes[nvars] = boundtype;
7994 	   ++reoptnode->nvars;
7995 	
7996 	   return SCIP_OKAY;
7997 	}
7998 	
7999 	/** add a constraint to a given reoptnode */
8000 	SCIP_RETCODE SCIPreoptnodeAddCons(
8001 	   SCIP_REOPTNODE*       reoptnode,          /**< node of the reopttree */
8002 	   SCIP_SET*             set,                /**< global SCIP settings */
8003 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8004 	   SCIP_VAR**            vars,               /**< variables which are part of the constraint */
8005 	   SCIP_Real*            bounds,             /**< bounds of the variables */
8006 	   SCIP_BOUNDTYPE*       boundtypes,         /**< boundtypes of the variables (or NULL is the constraint is a cut) */
8007 	   SCIP_Real             lhs,                /**< lhs of the constraint */
8008 	   SCIP_Real             rhs,                /**< rhs of the constraint */
8009 	   int                   nvars,              /**< number of variables */
8010 	   REOPT_CONSTYPE        constype,           /**< type of the constraint */
8011 	   SCIP_Bool             linear              /**< the given constraint has a linear representation */
8012 	   )
8013 	{
8014 	   int nconss;
8015 	
8016 	   assert(reoptnode != NULL);
8017 	   assert(set != NULL);
8018 	   assert(vars != NULL);
8019 	   assert(bounds != NULL);
8020 	   assert(constype == REOPT_CONSTYPE_CUT || boundtypes != NULL);
8021 	   assert(nvars > 0);
8022 	   assert(blkmem != NULL);
8023 	
8024 	   /* the constraint can be interpreted as a normal bound change */
8025 	   if( nvars == 1 && constype != REOPT_CONSTYPE_CUT )
8026 	   {
8027 	      assert(constype == REOPT_CONSTYPE_DUALREDS || constype == REOPT_CONSTYPE_INFSUBTREE);
8028 	
8029 	      SCIPsetDebugMsg(set, "-> constraint has size 1 -> save as normal bound change.\n");
8030 	
8031 	      if( SCIPvarGetType(vars[0]) == SCIP_VARTYPE_BINARY )
8032 	      {
8033 	         SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], 1-bounds[0],
8034 	               1-bounds[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
8035 	      }
8036 	      else
8037 	      {
8038 	         SCIP_Real newbound;
8039 	         SCIP_BOUNDTYPE newboundtype;
8040 	
8041 	         assert(SCIPvarGetType(vars[0]) == SCIP_VARTYPE_INTEGER);
8042 	         assert(boundtypes != NULL);
8043 	
8044 	         if( boundtypes[0] == SCIP_BOUNDTYPE_UPPER )
8045 	         {
8046 	            newbound = bounds[0] + 1.0;
8047 	            assert(SCIPsetIsLE(set, newbound, SCIPvarGetUbLocal(vars[0])));
8048 	
8049 	            newboundtype = SCIP_BOUNDTYPE_LOWER;
8050 	         }
8051 	         else
8052 	         {
8053 	            newbound = bounds[0] - 1.0;
8054 	            assert(SCIPsetIsGE(set, newbound, SCIPvarGetLbLocal(vars[0])));
8055 	
8056 	            newboundtype = SCIP_BOUNDTYPE_UPPER;
8057 	         }
8058 	
8059 	         SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], newbound, newboundtype) );
8060 	      }
8061 	   }
8062 	   else
8063 	   {
8064 	      nconss = reoptnode->nconss;
8065 	
8066 	      SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, 0, 0, nconss+1) );
8067 	
8068 	      /* create the constraint */
8069 	      SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
8070 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, vars, nvars) );
8071 	      SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, bounds, nvars) );
8072 	      if( boundtypes != NULL )
8073 	      {
8074 	         assert(!linear);
8075 	         SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->boundtypes, boundtypes, nvars) );
8076 	      }
8077 	      else
8078 	         reoptnode->conss[nconss]->boundtypes = NULL;
8079 	
8080 	      reoptnode->conss[nconss]->varssize = nvars;
8081 	      reoptnode->conss[nconss]->nvars = nvars;
8082 	      reoptnode->conss[nconss]->lhs = lhs;
8083 	      reoptnode->conss[nconss]->rhs = rhs;
8084 	      reoptnode->conss[nconss]->constype = constype;
8085 	      reoptnode->conss[nconss]->linear = linear;
8086 	      ++reoptnode->nconss;
8087 	   }
8088 	   return SCIP_OKAY;
8089 	}
8090 	
8091 	/** add a constraint to the reoptimization data structure */
8092 	SCIP_RETCODE SCIPreoptAddCons(
8093 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8094 	   SCIP_SET*             set,                /**< global SCIP settings */
8095 	   BMS_BLKMEM*           blkmem,             /**< block memory */
8096 	   SCIP_CONS*            cons                /**< constraint to add */
8097 	   )
8098 	{
8099 	   assert(reopt != NULL);
8100 	   assert(set != NULL);
8101 	   assert(blkmem != NULL);
8102 	   assert(cons != NULL);
8103 	
8104 	#ifdef SCIP_MORE_DEBUG
8105 	   SCIPsetDebugMsg(set, "add cons <%s> to reoptimization data\n", SCIPconsGetName(cons));
8106 	#endif
8107 	
8108 	   /* check memory */
8109 	   if( reopt->addedconsssize == 0 )
8110 	   {
8111 	      assert(reopt->addedconss == NULL);
8112 	
8113 	      reopt->addedconsssize = 10;
8114 	      SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize) );
8115 	   }
8116 	   else if( reopt->naddedconss == reopt->addedconsssize )
8117 	   {
8118 	      int newsize = SCIPsetCalcMemGrowSize(set, reopt->addedconsssize+1);
8119 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize, newsize) );
8120 	
8121 	      /* clear the array */
8122 	      BMSclearMemoryArray(&reopt->addedconss[reopt->addedconsssize], newsize - reopt->addedconsssize); /*lint !e866 */
8123 	
8124 	      reopt->addedconsssize = newsize;
8125 	   }
8126 	   assert(reopt->naddedconss < reopt->addedconsssize);
8127 	   assert(reopt->addedconss[reopt->naddedconss] == NULL);
8128 	
8129 	   reopt->addedconss[reopt->naddedconss] = cons;
8130 	   reopt->consadded = TRUE;
8131 	   ++reopt->naddedconss;
8132 	
8133 	   /* capture the constraint */
8134 	   SCIPconsCapture(cons);
8135 	
8136 	   return SCIP_OKAY;
8137 	}
8138 	
8139 	/** save global lower and upper bounds
8140 	 *
8141 	 *  @note this method should only be called once, i.e., after fishing presolving of the first problem
8142 	 */
8143 	SCIP_RETCODE SCIPreoptSaveGlobalBounds(
8144 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8145 	   SCIP_PROB*            transprob,          /**< transformed problem data */
8146 	   BMS_BLKMEM*           blkmem              /**< block memory */
8147 	   )
8148 	{
8149 	   SCIP_VAR** vars;
8150 	   int nvars;
8151 	
8152 	   assert(reopt != NULL);
8153 	   assert(transprob != NULL);
8154 	   assert(reopt->glblb == NULL && reopt->glbub == NULL);
8155 	
8156 	   nvars = SCIPprobGetNVars(transprob);
8157 	   vars = SCIPprobGetVars(transprob);
8158 	
8159 	   /* create hashmaps */
8160 	   SCIP_CALL( SCIPhashmapCreate(&reopt->glbub, blkmem, nvars) );
8161 	   SCIP_CALL( SCIPhashmapCreate(&reopt->glblb, blkmem, nvars) );
8162 	
8163 	   /* store the global bounds */
8164 	   for( int i = 0; i < nvars; ++i )
8165 	   {
8166 	      assert(!SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8167 	      assert(!SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8168 	
8169 	      SCIP_CALL( SCIPhashmapInsertReal(reopt->glblb, (void*)vars[i], SCIPvarGetLbGlobal(vars[i])) );
8170 	      SCIP_CALL( SCIPhashmapInsertReal(reopt->glbub, (void*)vars[i], SCIPvarGetUbGlobal(vars[i])) );
8171 	   }
8172 	
8173 	   return SCIP_OKAY;
8174 	}
8175 	
8176 	/** save active constraints
8177 	 *
8178 	 *  @note this method can only called once, i.e., after fishing presolving of the first problem
8179 	 */
8180 	SCIP_RETCODE SCIPreoptSaveActiveConss(
8181 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8182 	   SCIP_SET*             set,                /**< global SCIP settings */
8183 	   SCIP_PROB*            transprob,          /**< transformed problem data */
8184 	   BMS_BLKMEM*           blkmem              /**< block memory */
8185 	   )
8186 	{
8187 	   SCIP_CONS** conss;
8188 	   int nconss;
8189 	
8190 	   assert(reopt != NULL);
8191 	   assert(transprob != NULL);
8192 	   assert(reopt->activeconss == NULL);
8193 	   assert(reopt->activeconssset == NULL);
8194 	   assert(reopt->nactiveconss == 0);
8195 	   assert(reopt->nmaxactiveconss == 0);
8196 	
8197 	   conss = transprob->conss;
8198 	   nconss = transprob->nconss;
8199 	
8200 	   SCIPsetDebugMsg(set, "save %d active conss\n", nconss);
8201 	
8202 	   /* create hashset and array */
8203 	   SCIP_CALL( SCIPhashsetCreate(&reopt->activeconssset, blkmem, nconss) );
8204 	   SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, nconss) );
8205 	
8206 	   for( int i = 0; i < nconss; ++i )
8207 	   {
8208 	      assert(SCIPconsIsActive(conss[i]));
8209 	      assert(!SCIPhashsetExists(reopt->activeconssset, (void*)conss[i]));
8210 	
8211 	      SCIPconsCapture(conss[i]);
8212 	      SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)conss[i]) );
8213 	      reopt->activeconss[reopt->nactiveconss++] = conss[i];
8214 	   }
8215 	
8216 	   return SCIP_OKAY;
8217 	}
8218 	
8219 	/** installs global lower and upper bounds */
8220 	SCIP_RETCODE SCIPreoptInstallBounds(
8221 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8222 	   SCIP_SET*             set,                /**< global SCIP settings */
8223 	   SCIP_STAT*            stat,               /**< dynamic SCIP statistics */
8224 	   SCIP_PROB*            transprob,          /**< transformed problem data */
8225 	   SCIP_LP*              lp,                 /**< current LP data */
8226 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
8227 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
8228 	   SCIP_CLIQUETABLE*     cliquetable,        /**< clique table data structure */
8229 	   BMS_BLKMEM*           blkmem              /**< block memory */
8230 	   )
8231 	{
8232 	   SCIP_VAR** vars;
8233 	   int nvars;
8234 	
8235 	   assert(reopt != NULL);
8236 	   assert(transprob != NULL);
8237 	   assert(reopt->glblb != NULL && reopt->glbub != NULL);
8238 	   assert(SCIPprobIsTransformed(transprob));
8239 	
8240 	   nvars = SCIPprobGetNVars(transprob);
8241 	   vars = SCIPprobGetVars(transprob);
8242 	
8243 	   /* install global lower and upper bounds */
8244 	   for( int i = 0; i < nvars; ++i )
8245 	   {
8246 	      SCIP_Real lb;
8247 	      SCIP_Real ub;
8248 	
8249 	      assert(SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8250 	      assert(SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8251 	
8252 	      lb = SCIPhashmapGetImageReal(reopt->glblb, (void*)vars[i]);
8253 	      ub = SCIPhashmapGetImageReal(reopt->glbub, (void*)vars[i]);
8254 	      assert(lb < SCIP_INVALID && ub < SCIP_INVALID);
8255 	
8256 	      /* reset the global bounds back */
8257 	      SCIP_CALL( SCIPvarChgLbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, lb) );
8258 	      SCIP_CALL( SCIPvarChgUbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, ub) );
8259 	
8260 	      /* reset the local bounds back */
8261 	      SCIP_CALL( SCIPvarChgLbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, lb) );
8262 	      SCIP_CALL( SCIPvarChgUbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, ub) );
8263 	   }
8264 	
8265 	   return SCIP_OKAY;
8266 	}
8267 	
8268 	/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
8269 	SCIP_RETCODE SCIPreoptResetActiveConss(
8270 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8271 	   SCIP_SET*             set,                /**< global SCIP settings */
8272 	   SCIP_STAT*            stat                /**< dynamic SCIP statistics */
8273 	   )
8274 	{
8275 	   assert(reopt != NULL);
8276 	   assert(reopt->activeconss != NULL || reopt->nmaxactiveconss == 0);
8277 	   assert(reopt->activeconssset != NULL || reopt->nmaxactiveconss == 0);
8278 	   assert(reopt->nmaxactiveconss >= 0);
8279 	
8280 	   SCIPsetDebugMsg(set, "Reset %d active conss.\n", reopt->nactiveconss);
8281 	
8282 	   /* loop over all storeed active constraints and reactivate deactivated constraints */
8283 	   for( int i = 0; i < reopt->nactiveconss; ++i )
8284 	   {
8285 	      SCIP_CONS* cons;
8286 	
8287 	      assert(reopt->activeconss != NULL);
8288 	      cons = reopt->activeconss[i];
8289 	      assert(cons != NULL);
8290 	      assert(SCIPhashsetExists(reopt->activeconssset, cons));
8291 	
8292 	      /* it can happen that the constraint got globally deleted */
8293 	      if( SCIPconsIsDeleted(cons) )
8294 	         cons->deleted = FALSE;
8295 	
8296 	      /* to ensure that the constraint will be added to all the data structures we need to deactivate the
8297 	       * constraint first.
8298 	       */
8299 	      if( SCIPconsIsActive(cons) )
8300 	      {
8301 	         SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
8302 	      }
8303 	      SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, TRUE) );
8304 	   }
8305 	
8306 	   return SCIP_OKAY;
8307 	}
8308 	
8309 	/** returns whether a constraint is necessary to ensure correctness and cannot be deleted */
8310 	SCIP_Bool SCIPreoptConsCanBeDeleted(
8311 	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
8312 	   SCIP_CONS*            cons                /**< problem constraint */
8313 	   )
8314 	{
8315 	   assert(reopt != NULL);
8316 	   assert(cons != NULL);
8317 	
8318 	   /* the hashset is not initialized, we can delete all constraints */
8319 	   if( reopt->activeconss == NULL )
8320 	      return TRUE;
8321 	
8322 	   return !SCIPhashsetExists(reopt->activeconssset, (void*)cons);
8323 	}
8324