Scippy

SCIP

Solving Constraint Integer Programs

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