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-2015 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/misc.h"
33 #include "scip/reopt.h"
34 #include "scip/tree.h"
35 #include "scip/primal.h"
36 #include "scip/prob.h"
37 #include "scip/cons.h"
38 #include "scip/cons_logicor.h"
39 #include "scip/clock.h"
40 #include "scip/heur_reoptsols.h"
41 #include "blockmemshell/memory.h"
42 
43 #define DEFAULT_MEM_VARAFTERDUAL 10
44 #define DEFAULT_MEM_VAR 10
45 #define DEFAULT_MEM_NODES 1000
46 #define DEFAULT_MEM_RUN 200
47 #define DEFAULT_MEM_DUALCONS 10
48 
49 /* event handler properties */
50 #define EVENTHDLR_NAME "Reopt"
51 #define EVENTHDLR_DESC "node event handler for reoptimization"
52 
53 /* ---------------- Callback methods of event handler ---------------- */
54 
55 /* exec the event handler */
56 static
57 SCIP_DECL_EVENTEXEC(eventExecReopt)
58 {/*lint --e{715}*/
59  SCIP_NODE* eventnode;
60  SCIP_Real oldbound;
61  SCIP_Real newbound;
62 
63  assert(scip != NULL);
64  assert(eventhdlr != NULL);
65  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
67 
68  eventnode = SCIPgetCurrentNode(scip);
69  oldbound = SCIPeventGetOldbound(event);
70  newbound = SCIPeventGetNewbound(event);
71 
72  assert( eventnode != NULL );
73 
74  /* skip if the node is not the focus nodes */
76  || SCIPnodeGetDepth(eventnode) != SCIPgetEffectiveRootDepth(scip) )
77  return SCIP_OKAY;
78 
79  SCIPdebugMessage("catch event for node %lld: <%s>: %g -> %g\n", SCIPnodeGetNumber(eventnode),
81 
82  assert(SCIPisFeasLT(scip, newbound, oldbound) || SCIPisFeasGT(scip, newbound, oldbound));
83 
84  SCIP_CALL( SCIPaddReoptDualBndchg(scip, eventnode, SCIPeventGetVar(event), newbound, oldbound) );
85 
86  return SCIP_OKAY;
87 }
88 
89 /** solving process initialization method of event handler (called when branch and bound process is about to begin) */
90 static
91 SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
92 {
93  SCIP_VAR** vars;
94  int varnr;
95 
96  assert(scip != NULL);
97  assert(eventhdlr != NULL);
98  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
99  assert(SCIPisReoptEnabled(scip));
100 
101  vars = SCIPgetVars(scip);
102  for(varnr = 0; varnr < SCIPgetNVars(scip); ++varnr)
103  {
104  if( SCIPvarGetType(vars[varnr]) == SCIP_VARTYPE_BINARY )
105  {
106  SCIP_CALL(SCIPcatchVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED, eventhdlr, NULL, NULL));
107  }
108  }
109 
110  return SCIP_OKAY;
111 }
112 
113 /** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
114 static
115 SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
116 {
117  SCIP_VAR** vars;
118  int varnr;
119 
120  assert(scip != NULL);
121  assert(eventhdlr != NULL);
122  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
123  assert(SCIPisReoptEnabled(scip));
124 
125  vars = SCIPgetVars(scip);
126 
127  for(varnr = 0; varnr < SCIPgetNVars(scip); ++varnr)
128  {
129  if( SCIPvarGetType(vars[varnr]) == SCIP_VARTYPE_BINARY )
130  {
131  SCIP_CALL(SCIPdropVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED , eventhdlr, NULL, -1));
132  }
133  }
134  return SCIP_OKAY;
135 }
136 
137 /* ---------------- Callback methods of reoptimization methods ---------------- */
138 
139 /*
140  * memory growing methods for dynamically allocated arrays
141  */
142 
143 /** ensures, that sols[pos] array can store at least num entries */
144 static
146  SCIP_REOPT* reopt, /**< reoptimization data structure */
147  SCIP_SET* set, /**< global SCIP settings */
148  BMS_BLKMEM* blkmem, /**< block memory */
149  int num, /**< minimum number of entries to store */
150  int runidx /**< run index for which the memory should checked */
151  )
152 {
153  assert(runidx >= 0);
154  assert(runidx <= reopt->runsize);
155 
156  if( num > reopt->soltree->solssize[runidx] )
157  {
158  int newsize;
159 
160  newsize = SCIPsetCalcMemGrowSize(set, num);
161  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols[runidx], reopt->soltree->solssize[runidx],
162  newsize) ); /*lint !e866 */
163  reopt->soltree->solssize[runidx] = newsize;
164  }
165  assert(num <= reopt->soltree->solssize[runidx]);
166 
167  return SCIP_OKAY;
168 }
169 
170 /** ensures, that sols array can store at least num entries */
171 static
173  SCIP_REOPT* reopt, /**< reoptimization data structure */
174  int num, /**< minimum number of entries to store */
175  BMS_BLKMEM* blkmem /**< block memory */
176  )
177 {
178  if( num >= reopt->runsize )
179  {
180  int newsize;
181  int s;
182 
183  newsize = 2*num;
184  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize, newsize) );
185  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize, newsize) );
186  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize, newsize) );
187  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->prevbestsols, reopt->runsize, newsize) );
188  SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs, newsize) );
189 
190  for(s = reopt->runsize; s < newsize; s++)
191  {
192  reopt->prevbestsols[s] = NULL;
193  reopt->objs[s] = NULL;
194  reopt->soltree->solssize[s] = 0;
195  reopt->soltree->nsols[s] = 0;
196  reopt->soltree->sols[s] = NULL;
197  }
198 
199  reopt->runsize = newsize;
200  }
201  assert(num < reopt->runsize);
202 
203  return SCIP_OKAY;
204 }
205 
206 /** check the memory of the reoptimization tree and if necessary reallocate */
207 static
209  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
210  BMS_BLKMEM* blkmem /**< block memory */
211  )
212 {
213  assert(reopttree != NULL);
214  assert(blkmem != NULL);
215 
216  if( SCIPqueueIsEmpty(reopttree->openids) )
217  {
218  unsigned int id;
219 
220  assert(reopttree->nreoptnodes == (int)(reopttree->reoptnodessize));
221 
222  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize,
223  2*reopttree->reoptnodessize) ); /*lint !e647*/
224 
225  for( id = reopttree->reoptnodessize; id < 2*reopttree->reoptnodessize; id++ )
226  {
227  SCIP_CALL( SCIPqueueInsert(reopttree->openids, (void*) (size_t) id) ); /*lint !e571*/
228  reopttree->reoptnodes[id] = NULL;
229  }
230 
231  reopttree->reoptnodessize *= 2;
232  }
233 
234  return SCIP_OKAY;
235 }
236 
237 /** check allocated memory of a node within the reoptimization tree and if necessary reallocate */
238 static
240  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
241  BMS_BLKMEM* blkmem, /**< block memory */
242  int var_mem, /**< memory for variables */
243  int child_mem, /**< memory for child nodes */
244  int conss_mem /**< memory for constraints */
245  )
246 {
247  assert(reoptnode != NULL);
248  assert(blkmem != NULL);
249  assert(var_mem >= 0);
250  assert(child_mem >= 0);
251  assert(conss_mem >= 0);
252 
253  /* check allocated memory for variable and bound information */
254  if( var_mem > 0 )
255  {
256  if( reoptnode->varssize == 0 )
257  {
258  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->vars, var_mem) );
259  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varbounds, var_mem) );
260  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, var_mem) );
261  reoptnode->varssize = var_mem;
262  }
263  else if( reoptnode->varssize < var_mem )
264  {
265  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->vars, reoptnode->varssize, var_mem) );
266  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varbounds, reoptnode->varssize, var_mem) );
267  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, reoptnode->varssize, var_mem) );
268  reoptnode->varssize = var_mem;
269  }
270  }
271 
272  /* check allocated memory for child node information */
273  if( child_mem > 0 )
274  {
275  if( reoptnode->allocchildmem == 0 )
276  {
277  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->childids, child_mem) );
278  reoptnode->nchilds = 0;
279  reoptnode->allocchildmem = child_mem;
280  }
281  else if( reoptnode->allocchildmem < child_mem )
282  {
283  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->childids, reoptnode->allocchildmem, child_mem) );
284  reoptnode->allocchildmem = child_mem;
285  }
286  }
287 
288  /* check allocated memory for add constraints */
289  if( conss_mem > 0 )
290  {
291  if( reoptnode->consssize == 0 )
292  {
293  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->conss, conss_mem) );
294  reoptnode->nconss = 0;
295  reoptnode->consssize = conss_mem;
296  }
297  else if( reoptnode->consssize < conss_mem )
298  {
299  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->conss, reoptnode->consssize, conss_mem) );
300  reoptnode->consssize = conss_mem;
301  }
302  }
303 
304  return SCIP_OKAY;
305 }
306 
307 /*
308  * local methods
309  */
310 
311 /** returns the number of stored solutions in the subtree induced by @p solnode */
312 static
314  SCIP_SOLNODE* solnode /**< node within the solution tree */
315  )
316 {
317  assert(solnode != NULL);
318 
319  if( solnode->father == NULL && solnode->rchild == NULL && solnode->lchild == NULL )
320  return 0;
321  else if( solnode->rchild == NULL && solnode->lchild == NULL )
322  return 1;
323  else
324  {
325  if( solnode->rchild == NULL )
326  return soltreeNInducedSols(solnode->lchild);
327  else if( solnode->lchild == NULL )
328  return soltreeNInducedSols(solnode->rchild);
329  else
330  return soltreeNInducedSols(solnode->rchild) + soltreeNInducedSols(solnode->lchild);
331  }
332 }
333 
334 /** returns the similarity of the objective functions of two given iterations */
335 static
337  SCIP_REOPT* reopt, /**< reoptimization data */
338  SCIP_SET* set, /**< global SCIP settings */
339  int obj1_id, /**< id of one objective function */
340  int obj2_id, /**< id of the other objective function */
341  SCIP_VAR** transvars, /**< transformed problem variables */
342  int ntransvars /**< number of transformed problem variables */
343  )
344 {
345  SCIP_Real similarity;
346  SCIP_Bool onediffertozero;
347  int v;
348 
349  assert(reopt != NULL);
350  assert(transvars != NULL);
351  assert(ntransvars >= 0);
352 
353  onediffertozero = FALSE;
354 
355  /* calc similarity */
356  similarity = 0.0;
357  for(v = 0; v < ntransvars; v++)
358  {
359  SCIP_Real c1;
360  SCIP_Real c2;
361  SCIP_Real lb;
362  SCIP_Real ub;
363 
364  assert(SCIPvarIsActive(transvars[v]));
365  assert(!SCIPvarIsOriginal(transvars[v]));
366 
367  lb = SCIPvarGetLbLocal(transvars[v]);
368  ub = SCIPvarGetUbLocal(transvars[v]);
369 
370  if( SCIPsetIsFeasLT(set, lb, ub) )
371  {
372  int idx;
373 
374  idx = SCIPvarGetProbindex(transvars[v]);
375  assert(0 <= idx && idx < ntransvars);
376 
377  c1 = reopt->objs[obj1_id][idx];
378  c2 = reopt->objs[obj2_id][idx];
379 
380  if( c1 != 0 || c2 != 0 )
381  onediffertozero = TRUE;
382 
383  /* vector product */
384  similarity += c1*c2;
385  }
386  }
387 
388  if( !onediffertozero )
389  return -2.0;
390  else
391  return similarity;
392 }
393 
394 /** delete the given reoptimization node */
395 static
397  SCIP_REOPTNODE** reoptnode, /**< node of the reoptimization tree */
398  BMS_BLKMEM* blkmem /**< block memory */
399  )
400 {
401  assert((*reoptnode) != NULL );
402  assert(blkmem != NULL );
403 
404  /* delete data for constraints */
405  if((*reoptnode)->consssize > 0 )
406  {
407  int c;
408 
409  assert((*reoptnode)->conss != NULL);
410 
411  for(c = 0; c < (*reoptnode)->nconss; c++)
412  {
413  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->conss[c]->vals, (*reoptnode)->conss[c]->varssize);
414  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->conss[c]->vars, (*reoptnode)->conss[c]->varssize);
415  BMSfreeBlockMemory(blkmem, &(*reoptnode)->conss[c]); /*lint !e866*/
416  }
417  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->conss, (*reoptnode)->consssize);
418  (*reoptnode)->nconss = 0;
419  (*reoptnode)->consssize = 0;
420  (*reoptnode)->conss = NULL;
421  }
422 
423  /* free list of children */
424  if( (*reoptnode)->childids != NULL )
425  {
426  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->childids, (*reoptnode)->allocchildmem);
427  (*reoptnode)->nchilds = 0;
428  (*reoptnode)->allocchildmem = 0;
429  (*reoptnode)->childids = NULL;
430  }
431 
432  /* delete dual constraint */
433  if( (*reoptnode)->dualconscur != NULL )
434  {
435  assert((*reoptnode)->dualconscur->varssize > 0);
436  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualconscur->vals, (*reoptnode)->dualconscur->varssize);
437  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualconscur->vars, (*reoptnode)->dualconscur->varssize);
438  BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualconscur);
439  (*reoptnode)->dualconscur = NULL;
440  }
441 
442  if( (*reoptnode)->dualconsnex != NULL )
443  {
444  assert((*reoptnode)->dualconsnex->varssize > 0);
445  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualconsnex->vals, (*reoptnode)->dualconsnex->varssize);
446  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualconsnex->vars, (*reoptnode)->dualconsnex->varssize);
447  BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualconsnex);
448  (*reoptnode)->dualconsnex = NULL;
449  }
450 
451  /* free boundtypes */
452  if ((*reoptnode)->varboundtypes != NULL )
453  {
454  assert((*reoptnode)->varssize > 0);
455  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varboundtypes, (*reoptnode)->varssize);
456  (*reoptnode)->varboundtypes = NULL;
457  }
458 
459  /* free bounds */
460  if ((*reoptnode)->varbounds != NULL )
461  {
462  assert((*reoptnode)->varssize > 0);
463  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varbounds, (*reoptnode)->varssize);
464  (*reoptnode)->varbounds = NULL;
465  }
466 
467  /* free variables */
468  if ((*reoptnode)->vars != NULL )
469  {
470  assert((*reoptnode)->varssize > 0);
471  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->vars, (*reoptnode)->varssize);
472  (*reoptnode)->vars = NULL;
473  }
474 
475  (*reoptnode)->varssize = 0;
476 
477  /* free afterdual-boundtypes */
478  if ((*reoptnode)->afterdualvarboundtypes != NULL )
479  {
480  assert((*reoptnode)->afterdualvarssize > 0);
481  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarboundtypes, (*reoptnode)->afterdualvarssize);
482  (*reoptnode)->afterdualvarboundtypes = NULL;
483  }
484 
485  /* free afterdual-bounds */
486  if ((*reoptnode)->afterdualvarbounds != NULL )
487  {
488  assert((*reoptnode)->afterdualvarssize > 0);
489  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarbounds, (*reoptnode)->afterdualvarssize);
490  (*reoptnode)->afterdualvarbounds = NULL;
491  }
492 
493  /* free afterdual-variables */
494  if ((*reoptnode)->afterdualvars != NULL )
495  {
496  assert((*reoptnode)->afterdualvarssize > 0);
497  BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvars, (*reoptnode)->afterdualvarssize);
498  (*reoptnode)->afterdualvars = NULL;
499  }
500 
501  (*reoptnode)->afterdualvarssize = 0;
502 
503  BMSfreeBlockMemory(blkmem, reoptnode);
504  (*reoptnode) = NULL;
505 
506  return SCIP_OKAY;
507 }
508 
509 /** reset the given reoptimization node */
510 static
512  SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
513  SCIP_SET* set, /**< global SCIP settings */
514  BMS_BLKMEM* blkmem /**< block memory */
515  )
516 {
517  assert(reoptnode != NULL);
518  assert(set != NULL);
519  assert(blkmem != NULL);
520 
521  /* remove and delete all constraints */
522  if( reoptnode->nconss > 0 )
523  {
524  int c;
525 
526  assert(reoptnode->conss != NULL);
527  assert(reoptnode->consssize > 0);
528 
529  for(c = 0; c < reoptnode->nconss; c++)
530  {
531  BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
532  BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
533  BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866 */
534  }
535  reoptnode->nconss = 0;
536  }
537 
538  /* remove all children */
539  if (reoptnode->childids != NULL )
540  {
541  reoptnode->nchilds = 0;
542  }
543 
544  /* delete dual constraint */
545  if( reoptnode->dualconscur != NULL )
546  {
547  assert(reoptnode->dualconscur->varssize > 0);
548  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconscur->vals, reoptnode->dualconscur->varssize);
549  BMSfreeBlockMemoryArray(blkmem ,&reoptnode->dualconscur->vars, reoptnode->dualconscur->varssize);
550  BMSfreeBlockMemory(blkmem, &reoptnode->dualconscur);
551  reoptnode->dualconscur = NULL;
552  }
553 
554  if( reoptnode->dualconsnex != NULL )
555  {
556  assert(reoptnode->dualconsnex->varssize > 0);
557  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconsnex->vals, reoptnode->dualconsnex->varssize);
558  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconsnex->vars, reoptnode->dualconsnex->varssize);
559  BMSfreeBlockMemory(blkmem, &reoptnode->dualconsnex);
560  reoptnode->dualconsnex = NULL;
561  }
562 
563  reoptnode->parentID = 0;
564  reoptnode->nvars = 0;
565  reoptnode->nafterdualvars = 0;
566  reoptnode->dualfixing = FALSE;
567  reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
568  reoptnode->lowerbound = -SCIPsetInfinity(set);
569 
570  return SCIP_OKAY;
571 }
572 
573 /** delete the node stored at position @p nodeID of the reoptimization tree */
574 static
576  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
577  SCIP_SET* set, /**< global SCIP settings */
578  BMS_BLKMEM* blkmem, /**< block memory */
579  unsigned int id, /**< id of a node */
580  SCIP_Bool softreset /**< delete at the end of the solving process */
581  )
582 {
583  assert(reopttree != NULL );
584  assert(id < reopttree->reoptnodessize);
585  assert(reopttree->reoptnodes[id] != NULL );
586 
587  if( softreset )
588  {
589  SCIP_CALL( reoptnodeReset(reopttree->reoptnodes[id], set, blkmem) );
590  }
591  else
592  {
593  SCIP_CALL( reoptnodeDelete(&reopttree->reoptnodes[id], blkmem) );
594  }
595 
596  assert(softreset || reopttree->reoptnodes[id] == NULL);
597  assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->conss == NULL || reopttree->reoptnodes[id]->nconss == 0);
598  assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->childids == NULL || reopttree->reoptnodes[id]->nchilds == 0);
599 
600  --reopttree->nreoptnodes;
601 
602  return SCIP_OKAY;
603 }
604 
605 /** constructor of the solution tree */
606 static
608  SCIP_SOLTREE* soltree, /**< solution tree */
609  BMS_BLKMEM* blkmem /**< block memory */
610  )
611 {
612  int s;
613 
614  assert(soltree != NULL);
615 
619  for(s = 0; s < DEFAULT_MEM_RUN; s++)
620  {
621  soltree->nsols[s] = 0;
622  soltree->solssize[s] = 0;
623  soltree->sols[s] = NULL;
624  }
625 
626  /* allocate the root node */
627  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &soltree->root) );
628  soltree->root->sol = NULL;
629  soltree->root->updated = FALSE;
630  soltree->root->father = NULL;
631  soltree->root->rchild = NULL;
632  soltree->root->lchild = NULL;
633 
634  return SCIP_OKAY;
635 }
636 
637 /** free the given solution node */
638 static
640  SCIP_REOPT* reopt, /**< reoptimization data */
641  SCIP_SET* set, /**< global SCIP settings */
642  SCIP_PRIMAL* primal, /**< the primal */
643  BMS_BLKMEM* blkmem, /**< block memory */
644  SCIP_SOLNODE** solnode /**< node within the solution tree */
645  )
646 {
647  assert(reopt != NULL);
648  assert(set != NULL);
649  assert(primal != NULL || set->stage == SCIP_STAGE_INIT);
650  assert(solnode != NULL);
651  assert(blkmem != NULL);
652 
653  /* free recursive right subtree */
654  if( (*solnode)->rchild != NULL )
655  {
656  SCIP_CALL( soltreefreeNode(reopt, set, primal, blkmem, &(*solnode)->rchild) );
657  }
658  assert((*solnode)->rchild == NULL);
659 
660  /* free recursive left subtree */
661  if( (*solnode)->lchild != NULL )
662  {
663  SCIP_CALL( soltreefreeNode(reopt, set, primal, blkmem, &(*solnode)->lchild) );
664  }
665  assert((*solnode)->lchild == NULL);
666 
667  if( (*solnode)->sol != NULL )
668  {
669  assert(set->stage == SCIP_STAGE_PROBLEM);
670 
671  SCIP_CALL( SCIPsolFree(&(*solnode)->sol, blkmem, primal) );
672  }
673 
674  /* free this nodes */
675  BMSfreeBlockMemoryNull(blkmem, solnode);
676 
677  return SCIP_OKAY;
678 }
679 
680 /** free the solution tree */
681 static
683  SCIP_REOPT* reopt, /**< reoptimization data */
684  SCIP_SET* set, /**< global SCIP settings */
685  SCIP_PRIMAL* origprimal, /**< the origprimal */
686  BMS_BLKMEM* blkmem /**< block memory */
687  )
688 {
689  assert(reopt != NULL);
690  assert(reopt->soltree != NULL);
691  assert(reopt->soltree->root != NULL);
692  assert(set != NULL);
693  assert(blkmem != NULL);
694 
695  /* free all nodes recursive */
696  SCIP_CALL( soltreefreeNode(reopt, set, origprimal, blkmem, &reopt->soltree->root) );
697 
698  BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize);
699  BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize);
700  BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize);
701 
702  BMSfreeMemory(&reopt->soltree);
703 
704  return SCIP_OKAY;
705 }
706 
707 /** creates and adds a solution node to the solution tree */
708 static
710  BMS_BLKMEM* blkmem, /**< block memory */
711  SCIP_SOLNODE* father, /**< father of the node to add */
712  SCIP_Bool rchild, /**< 0-branch? */
713  SCIP_Bool lchild /**< 1-branch? */
714  )
715 {
716  SCIP_SOLNODE* solnode;
717 
718  assert(father != NULL);
719  assert(rchild == !lchild);
720  assert((rchild && father->rchild == NULL) || (lchild && father->lchild == NULL));
721 
722  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
723  solnode->sol = NULL;
724  solnode->updated = FALSE;
725  solnode->father = father;
726  solnode->rchild = NULL;
727  solnode->lchild = NULL;
728 
729  if( rchild )
730  father->rchild = solnode;
731  else
732  father->lchild = solnode;
733 
734  return SCIP_OKAY;
735 }
736 
737 /** add a solution to the solution tree */
738 static
740  SCIP_REOPT* reopt, /**< reoptimization data */
741  SCIP_SET* set, /**< global SCIP settings */
742  SCIP_STAT* stat, /**< dynamic problem statistics */
743  SCIP_PRIMAL* origprimal, /**< orig primal */
744  BMS_BLKMEM* blkmem, /**< block memory */
745  SCIP_VAR** vars, /**< array of original variables */
746  SCIP_SOL* sol, /**< solution to add */
747  SCIP_SOLNODE** solnode, /**< current solution node */
748  int nvars, /**< number of variables */
749  SCIP_Bool bestsol, /**< is the solution an optimal (best found) solution */
750  SCIP_Bool* added /**< pointer to store the result */
751  )
752 {
753  SCIP_SOLNODE* cursolnode;
754  int varid;
755 
756  assert(reopt != NULL);
757  assert(set != NULL);
758  assert(stat != NULL);
759  assert(origprimal != NULL);
760  assert(blkmem != NULL);
761  assert(vars != NULL);
762  assert(sol != NULL);
763  assert(solnode != NULL);
764 
765  cursolnode = reopt->soltree->root;
766  (*added) = FALSE;
767 
768  if( set->reopt_savesols > 0 )
769  {
770  for( varid = 0; varid < nvars; varid++ )
771  {
772  if( SCIPvarGetType(vars[varid]) == SCIP_VARTYPE_BINARY
773  || SCIPvarGetType(vars[varid]) == SCIP_VARTYPE_INTEGER
774  || SCIPvarGetType(vars[varid]) == SCIP_VARTYPE_IMPLINT )
775  {
776  SCIP_Real objval;
777 
778  objval = SCIPsolGetVal(sol, set, stat, vars[varid]);
779  if( SCIPsetIsFeasEQ(set, objval, 0.0) )
780  {
781  if( cursolnode->rchild == NULL )
782  {
783  SCIP_CALL( solnodeAddChild(blkmem, cursolnode, TRUE, FALSE) );
784  assert(cursolnode->rchild != NULL);
785  (*added) = TRUE;
786  }
787  cursolnode = cursolnode->rchild;
788  }
789  else
790  {
791  assert(SCIPsetIsFeasEQ(set, objval, 1.0));
792  if( cursolnode->lchild == NULL )
793  {
794  SCIP_CALL( solnodeAddChild(blkmem, cursolnode, FALSE, TRUE) );
795  assert(cursolnode->lchild != NULL);
796  (*added) = TRUE;
797  }
798  cursolnode = cursolnode->lchild;
799  }
800  }
801  }
802 
803  /* the solution was added or is an optimal solution */
804  if( *added || bestsol )
805  {
806  SCIP_SOL* copysol;
807 
808  assert(cursolnode->lchild == NULL && cursolnode->rchild == NULL);
809 
810  if( *added )
811  {
812  SCIP_CALL( SCIPsolCopy(&copysol, blkmem, set, stat, origprimal, sol) );
813  cursolnode->sol = copysol;
814  }
815  else
816  /* this is a pseudo add; we do not want to save this solution
817  * more than once, but we will link this solution to the solution
818  * storage of this round */
819  (*added) = TRUE;
820 
821  if( bestsol )
822  {
823  assert(reopt->prevbestsols != NULL);
824  assert(cursolnode->sol != NULL);
825 
826  reopt->prevbestsols[reopt->run-1] = cursolnode->sol;
827  }
828 
829  (*solnode) = cursolnode;
830  }
831  }
832 
833  return SCIP_OKAY;
834 }
835 
836 /** reset all marks 'updated' to FALSE */
837 static
839  SCIP_SOLNODE* node /**< node within the solution tree */
840  )
841 {
842  assert(node != NULL);
843 
844  if( node->rchild != NULL || node->lchild != NULL )
845  {
846  /* the node is no leaf */
847  assert(node->sol == NULL);
848  assert(!node->updated);
849 
850  if( node->rchild != NULL )
851  soltreeResetMarks(node->rchild);
852  if( node->lchild != NULL )
853  soltreeResetMarks(node->lchild);
854  }
855  else
856  {
857  /* the node is a leaf */
858  assert(node->father != NULL);
859  assert(node->sol != NULL);
860  node->updated = FALSE;
861  }
862 }
863 
864 /** allocate memory for a node within the reoptimization tree */
865 static
867  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
868  SCIP_SET* set, /**< global SCIP settings */
869  BMS_BLKMEM* blkmem, /**< block memory */
870  unsigned int id /**< id of the node to create */
871  )
872 {
873  assert(reopttree != NULL );
874  assert(id < reopttree->reoptnodessize);
875 
876  SCIPdebugMessage("create a reoptnode at ID %u\n", id);
877 
878  if(reopttree->reoptnodes[id] == NULL )
879  {
880  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]) ); /*lint !e866*/
881 
882  reopttree->reoptnodes[id]->conss = NULL;
883  reopttree->reoptnodes[id]->nconss = 0;
884  reopttree->reoptnodes[id]->consssize = 0;
885  reopttree->reoptnodes[id]->childids = NULL;
886  reopttree->reoptnodes[id]->allocchildmem = 0;
887  reopttree->reoptnodes[id]->nchilds = 0;
888  reopttree->reoptnodes[id]->nvars = 0;
889  reopttree->reoptnodes[id]->nafterdualvars = 0;
890  reopttree->reoptnodes[id]->parentID = 0;
891  reopttree->reoptnodes[id]->dualfixing = FALSE;
892  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
893  reopttree->reoptnodes[id]->varssize = 0;
894  reopttree->reoptnodes[id]->afterdualvarssize = 0;
895  reopttree->reoptnodes[id]->vars = NULL;
896  reopttree->reoptnodes[id]->varbounds = NULL;
897  reopttree->reoptnodes[id]->varboundtypes = NULL;
898  reopttree->reoptnodes[id]->afterdualvars = NULL;
899  reopttree->reoptnodes[id]->afterdualvarbounds = NULL;
900  reopttree->reoptnodes[id]->afterdualvarboundtypes = NULL;
901  reopttree->reoptnodes[id]->dualconscur = NULL;
902  reopttree->reoptnodes[id]->dualconsnex = NULL;
903  reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
904  }
905  else
906  {
907  assert(reopttree->reoptnodes[id]->nvars == 0);
908  assert(reopttree->reoptnodes[id]->nafterdualvars == 0);
909  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
910  reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
911  }
912 
913  /* increase the counter */
914  ++reopttree->nreoptnodes;
915 
916  return SCIP_OKAY;
917 }
918 
919 /** constructor of the reoptimization tree */
920 static
922  SCIP_REOPTTREE* reopttree, /**< pointer to the reoptimization tree */
923  SCIP_SET* set, /**< global SCIP settings */
924  BMS_BLKMEM* blkmem /**< block memory */
925  )
926 {
927  unsigned int id;
928 
929  assert(reopttree != NULL);
930  assert(set != NULL);
931  assert(blkmem != NULL);
932 
933  /* allocate memory */
934  reopttree->reoptnodessize = DEFAULT_MEM_NODES;
935  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize) );
936 
937  /* initialize the queue of open IDs */
938  SCIP_CALL( SCIPqueueCreate(&reopttree->openids, (int)reopttree->reoptnodessize, 2.0) );
939 
940  /* fill the queue, but reserve the 0 for the root */
941  for( id = 1; id < reopttree->reoptnodessize; id++ )
942  {
943  reopttree->reoptnodes[id] = NULL;
944  SCIP_CALL( SCIPqueueInsert(reopttree->openids, (void*) (size_t) id) ); /*lint !e571*/
945  }
946  assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
947 
948  reopttree->nreoptnodes = 0;
949  reopttree->ninfsubtrees = 0;
950  reopttree->ntotalfeasnodes = 0;
951  reopttree->nfeasnodes = 0;
952  reopttree->ninfnodes = 0;
953  reopttree->ntotalinfnodes= 0;
954  reopttree->nprunednodes = 0;
955  reopttree->ntotalprunednodes= 0;
956  reopttree->ncutoffreoptnodes = 0;
957  reopttree->ntotalcutoffreoptnodes = 0;
958 
959  /* initialize the root node */
960  reopttree->reoptnodes[0] = NULL;
961  SCIP_CALL( createReoptnode(reopttree, set, blkmem, 0) );
962 
963  return SCIP_OKAY;
964 }
965 
966 /** clears the reopttree, e.g., to restart and solve the next problem from scratch */
967 static
969  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
970  SCIP_SET* set, /**< global SCIP settings */
971  BMS_BLKMEM* blkmem, /**< block memory */
972  SCIP_Bool softreset /**< delete nodes before exit the solving process */
973  )
974 {
975  unsigned int id;
976 
977  assert(reopttree != NULL );
978 
979  /* clear queue with open IDs */
980  SCIPqueueClear(reopttree->openids);
981  assert(SCIPqueueNElems(reopttree->openids) == 0);
982 
983  /* delete all data about nodes */
984  for( id = 0; id < reopttree->reoptnodessize; id++ )
985  {
986  if( reopttree->reoptnodes[id] != NULL )
987  {
988  SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, softreset) );
989  assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->nvars == 0);
990  }
991 
992  if( id > 0 )
993  {
994  SCIP_CALL( SCIPqueueInsert(reopttree->openids, (void* ) (size_t ) id) ); /*lint !e571*/
995  }
996  }
997  assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
998 
999  reopttree->nreoptnodes = 0;
1000 
1001  return SCIP_OKAY;
1002 }
1003 
1004 /** free the reoptimization tree */
1005 static
1007  SCIP_REOPTTREE* reopttree, /**< reoptimization tree data */
1008  SCIP_SET* set, /**< global SCIP settings */
1009  BMS_BLKMEM* blkmem /**< block memory */
1010  )
1011 {
1012  assert(reopttree != NULL);
1013  assert(blkmem != NULL);
1014 
1015  /* free nodes */
1016  SCIP_CALL( clearReoptnodes(reopttree, set, blkmem, FALSE) );
1017 
1018  /* free the data */
1019  BMSfreeBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize);
1020  SCIPqueueFree(&reopttree->openids);
1021 
1022  /* free the tree itself */
1023  BMSfreeMemory(&reopttree);
1024 
1025  return SCIP_OKAY;
1026 }
1027 
1028 /** check memory for the constraint to handle bound changes based on dual information */
1029 static
1031  SCIP_REOPT* reopt, /**< reoptimization data structure */
1032  BMS_BLKMEM* blkmem, /**< block memory */
1033  int size /**< size which need to be allocated */
1034  )
1035 {
1036  assert(reopt != NULL);
1037  assert(blkmem != NULL);
1038  assert(size > 0);
1039 
1040  if( reopt->dualcons == NULL )
1041  {
1042  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->dualcons) );
1043  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualcons->vars, size) );
1044  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualcons->vals, size) );
1045  reopt->dualcons->varssize = size;
1046  reopt->dualcons->nvars = 0;
1047  }
1048  else
1049  {
1050  if( reopt->dualcons->varssize > 0 )
1051  {
1052  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualcons->vars, reopt->dualcons->varssize, size) );
1053  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualcons->vals, reopt->dualcons->varssize, size) );
1054  }
1055  else
1056  {
1057  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualcons->vars, size) );
1058  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualcons->vals, size) );
1059  reopt->dualcons->nvars = 0;
1060  }
1061 
1062  reopt->dualcons->varssize = size;
1063  }
1064 
1065  return SCIP_OKAY;
1066 }
1067 
1068 /** check the memory to store global constraints */
1069 static
1071  SCIP_REOPT* reopt, /**< reoptimization data structure */
1072  BMS_BLKMEM* blkmem, /**< block memory */
1073  int mem /**< memory which has to be allocated */
1074  )
1075 {
1076  assert(reopt != NULL);
1077  assert(blkmem != NULL);
1078  assert(mem >= 0);
1079 
1080  if( mem > 0 )
1081  {
1082  if( reopt->glbconss == NULL )
1083  {
1084  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->glbconss, mem) );
1085  reopt->nglbconss = 0;
1086  reopt->allocmemglbconss = mem;
1087  }
1088  else if( reopt->allocmemglbconss < mem )
1089  {
1090  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->glbconss, reopt->allocmemglbconss, mem) );
1091 
1092  reopt->allocmemglbconss = mem;
1093  }
1094  }
1095 
1096  return SCIP_OKAY;
1097 }
1098 
1099 /** update the bound changes made by constraint propagations during current iteration; stop saving the bound changes if
1100  * we reach a branching decision based on a dual information.
1101  */
1102 static
1104  SCIP_REOPT* reopt, /**< reoptimization data structure */
1105  BMS_BLKMEM* blkmem, /**< block memory */
1106  SCIP_NODE* node, /**< node of the search tree */
1107  unsigned int id, /**< id of the node */
1108  SCIP_Bool* transintoorig /**< transform variables into originals */
1109  )
1110 {
1111  int nvars;
1112  int nconsprops;
1113  int naddedbndchgs;
1114 
1115  assert(reopt != NULL);
1116  assert(blkmem != NULL);
1117  assert(node != NULL);
1118  assert(0 < id && id < reopt->reopttree->reoptnodessize);
1119  assert(reopt->reopttree->reoptnodes[id] != NULL );
1120 
1121  /* get the number of all stored constraint propagations */
1122  SCIPnodeGetNDomchg(node, NULL, &nconsprops, NULL);
1123  nvars = reopt->reopttree->reoptnodes[id]->nvars;
1124 
1125  if( nconsprops > 0 )
1126  {
1127  /* check the memory */
1128  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], blkmem, nvars + nconsprops, 0, 0) );
1129 
1130  SCIPnodeGetConsProps(node,
1131  &reopt->reopttree->reoptnodes[id]->vars[nvars],
1132  &reopt->reopttree->reoptnodes[id]->varbounds[nvars],
1133  &reopt->reopttree->reoptnodes[id]->varboundtypes[nvars],
1134  &naddedbndchgs,
1135  reopt->reopttree->reoptnodes[id]->varssize-nvars);
1136 
1137  assert(nvars + naddedbndchgs <= reopt->reopttree->reoptnodes[id]->varssize);
1138 
1139  reopt->reopttree->reoptnodes[id]->nvars += naddedbndchgs;
1140 
1141  *transintoorig = TRUE;
1142  }
1143 
1144  return SCIP_OKAY;
1145 }
1146 
1147 /** save bound changes made after the first bound change based on dual information, e.g., mode by strong branching.
1148  *
1149  * this method is can be used during reoptimization. if we want to reconstruct a node containing dual bound changes we
1150  * have to split the node into the original one and at least one node representing the pruned part. all bound changes,
1151  * i.e., (constraint) propagation, made after the first bound change based on dual information are still valid for
1152  * the original node after changing the objective function. thus, we can store them for the following iterations.
1153  *
1154  * it should be noted, that these bound change will be found by (constraint) propagation methods anyway after changing
1155  * the objective function. do not saving these information and find them again might be useful for conflict analysis.
1156  */
1157 static
1159  SCIP_REOPT* reopt, /**< reoptimization data structure */
1160  BMS_BLKMEM* blkmem, /**< block memory */
1161  SCIP_NODE* node, /**< node of the search tree */
1162  unsigned int id, /**< id of the node */
1163  SCIP_Bool* transintoorig /**< transform variables into originals */
1164  )
1165 {
1166  int nbranchvars;
1167 
1168  assert(reopt != NULL);
1169  assert(blkmem != NULL);
1170  assert(node != NULL);
1171  assert(0 < id && id < reopt->reopttree->reoptnodessize);
1172  assert(reopt->reopttree->reoptnodes[id] != NULL );
1173 
1174  nbranchvars = 0;
1175 
1176  /* allocate memory */
1177  if (reopt->reopttree->reoptnodes[id]->afterdualvarssize == 0)
1178  {
1179  assert(reopt->reopttree->reoptnodes[id]->afterdualvars == NULL );
1180  assert(reopt->reopttree->reoptnodes[id]->afterdualvarbounds == NULL );
1181  assert(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes == NULL );
1182 
1183  /* allocate block memory for node information */
1188  }
1189 
1190  assert(reopt->reopttree->reoptnodes[id]->afterdualvarssize > 0);
1191  assert(reopt->reopttree->reoptnodes[id]->nafterdualvars >= 0);
1192 
1194  reopt->reopttree->reoptnodes[id]->afterdualvars,
1197  reopt->reopttree->reoptnodes[id]->nafterdualvars,
1198  &nbranchvars,
1199  reopt->reopttree->reoptnodes[id]->afterdualvarssize);
1200 
1201  if( nbranchvars > reopt->reopttree->reoptnodes[id]->afterdualvarssize )
1202  {
1203  int newsize;
1204  newsize = nbranchvars + 1;
1208  reopt->reopttree->reoptnodes[id]->afterdualvarssize = newsize;
1209 
1211  reopt->reopttree->reoptnodes[id]->afterdualvars,
1214  reopt->reopttree->reoptnodes[id]->nafterdualvars,
1215  &nbranchvars,
1216  reopt->reopttree->reoptnodes[id]->afterdualvarssize);
1217  }
1218 
1219  /* the stored variables of this node need to be transformed into the original space */
1220  if( nbranchvars > 0 )
1221  *transintoorig = TRUE;
1222 
1223  SCIPdebugMessage(" -> save %d bound changes after dual reductions\n", nbranchvars);
1224 
1225  assert(nbranchvars <= reopt->reopttree->reoptnodes[id]->afterdualvarssize); /* this should be the case */
1226 
1227  reopt->reopttree->reoptnodes[id]->nafterdualvars = nbranchvars;
1228 
1229  return SCIP_OKAY;
1230 }
1231 
1232 /** transform variable and bounds back to the original space */
1233 static
1235  SCIP_REOPT* reopt, /**< reoptimization data structure */
1236  unsigned int id /**< id of the node */
1237  )
1238 {
1239  int varnr;
1240 
1241  assert(reopt != NULL );
1242  assert(0 < id && id < reopt->reopttree->reoptnodessize);
1243  assert(reopt->reopttree->reoptnodes[id] != NULL );
1244 
1245  /* transform branching variables and bound changes applied before the first dual reduction */
1246  for(varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; varnr++)
1247  {
1248  SCIP_Real constant;
1249  SCIP_Real scalar;
1250 
1251  scalar = 1;
1252  constant = 0;
1253 
1254  if(!SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]))
1255  {
1256  SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->vars[varnr], &scalar, &constant)) ;
1257  reopt->reopttree->reoptnodes[id]->varbounds[varnr] = (reopt->reopttree->reoptnodes[id]->varbounds[varnr] - constant) / scalar;
1258  }
1259  assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]));
1260  }
1261 
1262  /* transform bound changes affected by dual reduction */
1263  for(varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; varnr++)
1264  {
1265  SCIP_Real constant;
1266  SCIP_Real scalar;
1267 
1268  scalar = 1;
1269  constant = 0;
1270 
1271  if(!SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]))
1272  {
1273  SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->afterdualvars[varnr], &scalar, &constant)) ;
1274  reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr] = (reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr] - constant) / scalar;
1275  }
1276  assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]));
1277  }
1278 
1279  return SCIP_OKAY;
1280 }
1281 
1282 /** search the next node along the root path that was saved by reoptimization */
1283 static
1285  SCIP_REOPT* reopt, /**< reoptimization data structure */
1286  SCIP_SET* set, /**< global SCIP settings */
1287  SCIP_NODE* node, /**< node of the search tree */
1288  SCIP_NODE** parent, /**< parent node within the search tree */
1289  unsigned int* parentid, /**< id of the parent node */
1290  int* nbndchgs /**< number of bound changes */
1291  )
1292 {
1293  assert(reopt != NULL);
1294  assert(reopt->reopttree != NULL);
1295  assert(reopt->reopttree->reoptnodes != NULL);
1296 
1297  (*nbndchgs) = 0;
1298  (*parent) = node;
1299 
1300  /* look for a saved parent along the root-path */
1301  while( SCIPnodeGetDepth(*parent) != 0 )
1302  {
1303  int nbranchings;
1304  int nconsprop;
1305 
1306  nbranchings = 0;
1307  nconsprop = 0;
1308 
1309  if( set->reopt_saveconsprop )
1310  SCIPnodeGetNDomchg((*parent), &nbranchings, &nconsprop, NULL);
1311  else
1312  SCIPnodeGetNDomchg((*parent), &nbranchings, NULL, NULL);
1313 
1314  (*nbndchgs) = (*nbndchgs) + nbranchings + nconsprop;
1315  (*parent) = SCIPnodeGetParent(*parent);
1316 
1317  if( SCIPnodeGetDepth(*parent) == 0)
1318  {
1319  (*parentid) = 0;
1320  break;
1321  }
1322  else if( SCIPnodeGetReopttype((*parent)) >= SCIP_REOPTTYPE_TRANSIT )
1323  {
1324  assert(SCIPnodeGetReoptID((*parent)) < reopt->reopttree->reoptnodessize);
1325  (*parentid) = SCIPnodeGetReoptID((*parent));
1326  assert((*parentid) && (*parentid) < reopt->reopttree->reoptnodessize);
1327  break;
1328  }
1329  }
1330 
1331  return SCIP_OKAY;
1332 }
1333 
1334 /** adds the id @p childid to the array of child nodes of @p parentid */
1335 static
1337  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
1338  BMS_BLKMEM* blkmem, /**< block memory */
1339  unsigned int parentid, /**< id of the parent node */
1340  unsigned int childid /**< id of the child node */
1341  )
1342 {
1343  int nchilds;
1344 
1345  assert(reopttree != NULL);
1346  assert(blkmem != NULL);
1347  assert(parentid < (unsigned int)reopttree->reoptnodessize);
1348  assert(childid < (unsigned int)reopttree->reoptnodessize);
1349  assert(reopttree->reoptnodes[parentid] != NULL);
1350 
1351  nchilds = reopttree->reoptnodes[parentid]->nchilds;
1352 
1353  /* ensure that the array is large enough */
1354  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[parentid], blkmem, 0, nchilds+1, 0) );
1355  assert(reopttree->reoptnodes[parentid]->allocchildmem > nchilds);
1356 
1357  /* add the child */
1358  reopttree->reoptnodes[parentid]->childids[nchilds] = childid;
1359  ++reopttree->reoptnodes[parentid]->nchilds;
1360 
1361  SCIPdebugMessage("add ID %u as a child of ID %u.\n", childid, parentid);
1362 
1363  return SCIP_OKAY;
1364 }
1365 
1366 /** move all children to the next node (along the root path) stored in the reoptimization tree */
1367 static
1369  SCIP_REOPT* reopt, /**< reoptimization data structure */
1370  BMS_BLKMEM* blkmem, /**< block memory */
1371  unsigned int nodeid, /**< id of the node */
1372  unsigned int parentid /**< id of the parent node */
1373  )
1374 {
1375  unsigned int childid;
1376  int varnr;
1377  int nvars;
1378 
1379  assert(reopt != NULL);
1380  assert(blkmem != NULL);
1381  assert(0 < nodeid && nodeid < reopt->reopttree->reoptnodessize);
1382  assert(parentid < reopt->reopttree->reoptnodessize);
1383  assert(reopt->reopttree->reoptnodes[nodeid]->childids != NULL);
1384 
1385  /* ensure that enough memory at the parentID is available */
1386  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], blkmem, 0, reopt->reopttree->reoptnodes[parentid]->nchilds + reopt->reopttree->reoptnodes[nodeid]->nchilds, 0) );
1387 
1388  while( reopt->reopttree->reoptnodes[nodeid]->nchilds > 0 )
1389  {
1390  int nchilds;
1391 
1392  nchilds = reopt->reopttree->reoptnodes[nodeid]->nchilds;
1393  childid = reopt->reopttree->reoptnodes[nodeid]->childids[nchilds-1];
1394  assert(0 < childid && childid < reopt->reopttree->reoptnodessize);
1395 
1396  /* check the memory */
1397  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[childid], blkmem, reopt->reopttree->reoptnodes[childid]->nvars + reopt->reopttree->reoptnodes[nodeid]->nvars, 0, 0) );
1398  assert(reopt->reopttree->reoptnodes[childid]->varssize >= reopt->reopttree->reoptnodes[childid]->nvars + reopt->reopttree->reoptnodes[nodeid]->nvars);
1399 
1400  /* save branching information */
1401  for(varnr = 0; varnr < reopt->reopttree->reoptnodes[nodeid]->nvars; varnr++)
1402  {
1403  nvars = reopt->reopttree->reoptnodes[childid]->nvars;
1404  reopt->reopttree->reoptnodes[childid]->vars[nvars] = reopt->reopttree->reoptnodes[nodeid]->vars[varnr];
1405  reopt->reopttree->reoptnodes[childid]->varbounds[nvars] = reopt->reopttree->reoptnodes[nodeid]->varbounds[varnr];
1406  reopt->reopttree->reoptnodes[childid]->varboundtypes[nvars] = reopt->reopttree->reoptnodes[nodeid]->varboundtypes[varnr];
1407  ++reopt->reopttree->reoptnodes[childid]->nvars;
1408  }
1409 
1410  /* update the ID of the parent node */
1411  reopt->reopttree->reoptnodes[childid]->parentID = parentid;
1412 
1413  /* insert the node as a child */
1414  SCIP_CALL( reoptAddChild(reopt->reopttree, blkmem, parentid, childid) );
1415 
1416  /* reduce the number of child nodes by 1 */
1417  --reopt->reopttree->reoptnodes[nodeid]->nchilds;
1418  }
1419 
1420  return SCIP_OKAY;
1421 }
1422 
1423 /** delete all nodes in the subtree induced by nodeID */
1424 static
1426  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
1427  SCIP_SET* set, /**< global SCIP settings */
1428  BMS_BLKMEM* blkmem, /**< block memory */
1429  unsigned int id, /**< id of the node */
1430  SCIP_Bool delnodeitself, /**< should the node deleted after deleting the induced subtree? */
1431  SCIP_Bool exitsolve /**< will the solving process end after deletion */
1432  )
1433 {
1434  assert(reopttree != NULL );
1435  assert(blkmem != NULL);
1436  assert(id < reopttree->reoptnodessize);
1437  assert(reopttree->reoptnodes[id] != NULL);
1438 
1439  /* delete all children below */
1440  if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
1441  {
1442  SCIPdebugMessage("-> delete subtree induced by ID %u (hard remove = %u)\n", id, exitsolve);
1443 
1444  while( reopttree->reoptnodes[id]->nchilds > 0 )
1445  {
1446  int nchilds;
1447  unsigned int childid;
1448 
1449  nchilds = reopttree->reoptnodes[id]->nchilds;
1450  childid = reopttree->reoptnodes[id]->childids[nchilds-1];
1451  assert(0 < childid && childid < reopttree->reoptnodessize);
1452 
1453  SCIP_CALL( deleteChildrenBelow(reopttree, set, blkmem, childid, TRUE, exitsolve) );
1454 
1455  --reopttree->reoptnodes[id]->nchilds;
1456  }
1457  }
1458 
1459  /* delete node data*/
1460  if( delnodeitself )
1461  {
1462  SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, exitsolve) );
1463  SCIP_CALL( SCIPqueueInsert(reopttree->openids, (void*) (size_t) id) );
1464  }
1465 
1466  return SCIP_OKAY;
1467 }
1468 
1469 /** replaces a reoptimization nodes by its stored child nodes */
1470 static
1472  SCIP_REOPT* reopt, /**< reoptimization data structure */
1473  SCIP_SET* set, /**< global SCIP settings */
1474  SCIP_NODE* node, /**< node of the search tree */
1475  unsigned int id, /**< id of the node */
1476  SCIP_Bool* shrank, /**< pointer to store if the node was shrank */
1477  BMS_BLKMEM* blkmem /**< block memory */
1478  )
1479 {
1480  SCIP_NODE* parent;
1481  int ndomchgs;
1482  unsigned int parentid;
1483 
1484  assert(reopt != NULL);
1485  assert(node != NULL);
1486  assert(id < reopt->reopttree->reoptnodessize);
1487  assert(reopt->reopttree->reoptnodes[id] != NULL);
1488 
1489  if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
1490  {
1491  ndomchgs = 0;
1492  parentid = 0;
1493  parent = NULL;
1494 
1495  SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &ndomchgs) );
1496 
1497  assert(parentid != id);
1498  assert(reopt->reopttree->reoptnodes[parentid] != NULL );
1499  assert(reopt->reopttree->reoptnodes[parentid]->childids != NULL && reopt->reopttree->reoptnodes[parentid]->nchilds);
1500 
1501  /* check if we want move all children to the next saved node above
1502  * we want to shrink the path if either
1503  * - the maximal number of bound changes fix and the number of bound changes is
1504  * less than the given threshold set->reopt_maxdiffofnodes
1505  * or
1506  * - the number is calculated dynamically and the number of bound changes
1507  * is less than log2(SCIPgetNBinVars - (#vars of parent))
1508  * */
1509  if( ndomchgs <= set->reopt_maxdiffofnodes )
1510  {
1511  int c;
1512 
1513  SCIPdebugMessage(" -> shrink node %lld at ID %u, replaced by %d child nodes.\n", SCIPnodeGetNumber(node), id, reopt->reopttree->reoptnodes[id]->nchilds);
1514 
1515  /* copy the references of child nodes to the parent*/
1516  SCIP_CALL( moveChildrenUp(reopt, blkmem, id, parentid) );
1517 
1518  /* delete the current node */
1519  c = 0;
1520  while( reopt->reopttree->reoptnodes[parentid]->childids[c] != id && c < reopt->reopttree->reoptnodes[parentid]->nchilds )
1521  ++c;
1522 
1523  assert(reopt->reopttree->reoptnodes[parentid]->childids[c] == id);
1524 
1525  /* replace the childid at position c by the last one */
1526  reopt->reopttree->reoptnodes[parentid]->childids[c] = reopt->reopttree->reoptnodes[parentid]->childids[reopt->reopttree->reoptnodes[parentid]->nchilds-1];
1527  --reopt->reopttree->reoptnodes[parentid]->nchilds;
1528 
1529  SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
1530  SCIP_CALL( SCIPqueueInsert(reopt->reopttree->openids, (void*) (size_t) id) );
1531 
1532  *shrank = TRUE;
1533 
1534  /* set the reopttype to none */
1536  }
1537  }
1538 
1539  return SCIP_OKAY;
1540 }
1541 
1542 /** change all reopttypes in the subtree induced by @p nodeID */
1543 static
1545  SCIP_REOPTTREE* reopttree, /**< reopttree */
1546  unsigned int id, /**< id of the node */
1547  SCIP_REOPTTYPE reopttype /**< reopttype */
1548  )
1549 {
1550  assert(reopttree != NULL);
1551  assert(id < reopttree->reoptnodessize);
1552  assert(reopttree->reoptnodes[id] != NULL);
1553 
1554  if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
1555  {
1556  unsigned int childid;
1557  int nchildids;
1558  int seenids;
1559 
1560  nchildids = reopttree->reoptnodes[id]->nchilds;
1561  seenids = 0;
1562 
1563  while( seenids < nchildids )
1564  {
1565  /* get childID */
1566  childid = reopttree->reoptnodes[id]->childids[seenids];
1567  assert(childid < reopttree->reoptnodessize);
1568  assert(reopttree->reoptnodes[childid] != NULL);
1569 
1570  /* change the reopttype of the node iff the node is neither infeasible nor induces an
1571  * infeasible subtree and if the node contains no bound changes based on dual decisions */
1572  if( reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_STRBRANCHED
1573  && reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_INFSUBTREE ) /*lint !e641*/
1574  reopttree->reoptnodes[childid]->reopttype = reopttype; /*lint !e641*/
1575 
1576  /* change reopttype of subtree */
1577  SCIP_CALL( changeReopttypeOfSubtree(reopttree, childid, reopttype) );
1578 
1579  ++seenids;
1580  }
1581  }
1582 
1583  return SCIP_OKAY;
1584 }
1585 
1586 /** delete the constraint handling dual information for the current iteration and replace it with the dual constraint
1587  * for the next iteration
1588  */
1589 static
1591  SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
1592  BMS_BLKMEM* blkmem /**< block memory */
1593  )
1594 {
1595  assert(reoptnode != NULL);
1596  assert(blkmem != NULL);
1597 
1598  if( reoptnode->dualconscur != NULL )
1599  {
1600  SCIPdebugMessage("reset dual (1) information\n");
1601 
1602  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconscur->vals, reoptnode->dualconscur->varssize);
1603  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconscur->vars, reoptnode->dualconscur->varssize);
1604  BMSfreeBlockMemory(blkmem, &reoptnode->dualconscur);
1605  reoptnode->dualconscur = NULL;
1606  }
1607 
1608  if( reoptnode->dualconsnex != NULL )
1609  {
1610  reoptnode->dualconscur = reoptnode->dualconsnex;
1611  reoptnode->dualconsnex = NULL;
1612  }
1613 
1614  reoptnode->dualfixing = (reoptnode->dualconscur != NULL ? 1 : 0);
1615 
1616  return SCIP_OKAY;
1617 }
1618 
1619 /** calculates a (local) similarity of a given node and returns if the subproblem should be solved from scratch */
1620 static
1622  SCIP_REOPT* reopt, /**< reoptimization data structure */
1623  SCIP_SET* set, /**< global SCIP settings */
1624  BMS_BLKMEM* blkmem, /**< block memory */
1625  SCIP_NODE* node, /**< node of the search tree */
1626  SCIP_VAR** transvars, /**< transformed variables */
1627  int ntransvars, /**< number of transformed variables */
1628  SCIP_Bool* localrestart /**< pointer to store if we want to restart solving the (sub)problem */
1629  )
1630 {
1631  unsigned int id;
1632 
1633  assert(reopt != NULL);
1634  assert(reopt->reopttree != NULL);
1635  assert(set != NULL);
1636  assert(blkmem != NULL);
1637  assert(node != NULL);
1638  assert(transvars != NULL);
1639 
1640  /* node == NULL is equivalent to node == root, this case should be handled by SCIPreoptCheckReopt */
1641  assert(node != NULL);
1642 
1643  *localrestart = FALSE;
1644 
1645  id = SCIPnodeGetReoptID(node);
1646  assert(id < reopt->reopttree->reoptnodessize);
1647 
1648  /* set the id to -1 if the node is not part of the reoptimization tree */
1649  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
1650  return SCIP_OKAY;
1651 
1652  if( set->reopt_objsimdelay > -1 )
1653  {
1654  SCIP_Real sim;
1655  SCIP_Real lb;
1656  SCIP_Real ub;
1657  SCIP_Real oldcoef;
1658  SCIP_Real newcoef;
1659  int v;
1660  int idx;
1661 
1662  if( id == 0 )
1663  reopt->nlocrestarts = 0;
1664 
1665  sim = 0.0;
1666 
1667  /* since the stored objective functions are already normalize the dot-product is equivalent to the similarity */
1668  for(v = 0; v < ntransvars; v++)
1669  {
1670  lb = SCIPvarGetLbLocal(transvars[v]);
1671  ub = SCIPvarGetUbLocal(transvars[v]);
1672 
1673  /* skip already fixed variables */
1674  if( SCIPsetIsFeasLT(set, lb, ub) )
1675  {
1676  idx = SCIPvarGetProbindex(transvars[v]);
1677  assert(0 <= idx && idx < ntransvars);
1678 
1679  oldcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run-1, idx);
1680  newcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run, idx);
1681 
1682  sim += (oldcoef * newcoef);
1683  }
1684  }
1685 
1686  /* delete the stored subtree and information about bound changes
1687  * based on dual information */
1688  if( SCIPsetIsLT(set, sim, set->reopt_objsimdelay) )
1689  {
1690  /* set the flag */
1691  *localrestart = TRUE;
1692 
1693  ++reopt->nlocrestarts;
1694  ++reopt->ntotallocrestarts;
1695 
1696  /* delete the stored subtree */
1697  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
1698 
1699  /* delete the stored constraints; we do this twice in a row because we want to delete both constraints */
1700  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
1701  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
1702  }
1703 
1704  SCIPdebugMessage(" -> local similarity: %.4f%s\n", sim, *localrestart ? " (solve subproblem from scratch)" : "");
1705  }
1706 
1707  return SCIP_OKAY;
1708 }
1709 
1710 /** save ancestor branching information up to the next stored node */
1711 static
1713  SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
1714  BMS_BLKMEM* blkmem, /**< block memory */
1715  SCIP_NODE* node, /**< node of the branch and bound tree */
1716  SCIP_NODE* parent, /**< parent node */
1717  unsigned int id, /**< id of the node */
1718  unsigned int parentid /**< id of the parent node */
1719  )
1720 {
1721  int nbranchvars;
1722 
1723  assert(reopttree != NULL );
1724  assert(node != NULL );
1725  assert(parent != NULL );
1726  assert(1 <= id && id < reopttree->reoptnodessize);
1727  assert(reopttree->reoptnodes[id] != NULL );
1728  assert(parentid < reopttree->reoptnodessize);
1729  assert(parentid == 0 || reopttree->reoptnodes[parentid] != NULL ); /* if the root is the next saved node, the nodedata can be NULL */
1730 
1731  SCIPdebugMessage(" -> save ancestor branchings\n");
1732 
1733  /* allocate memory */
1734  if (reopttree->reoptnodes[id]->varssize == 0)
1735  {
1736  assert(reopttree->reoptnodes[id]->vars == NULL );
1737  assert(reopttree->reoptnodes[id]->varbounds == NULL );
1738  assert(reopttree->reoptnodes[id]->varboundtypes == NULL );
1739 
1740  /* allocate memory for node information */
1741  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, DEFAULT_MEM_VAR, 0, 0) );
1742  }
1743 
1744  assert(reopttree->reoptnodes[id]->varssize > 0);
1745  assert(reopttree->reoptnodes[id]->nvars == 0);
1746 
1747  SCIPnodeGetAncestorBranchingsPart(node, parent,
1748  reopttree->reoptnodes[id]->vars,
1749  reopttree->reoptnodes[id]->varbounds,
1750  reopttree->reoptnodes[id]->varboundtypes,
1751  &nbranchvars,
1752  reopttree->reoptnodes[id]->varssize);
1753 
1754  if( nbranchvars > reopttree->reoptnodes[id]->varssize )
1755  {
1756  /* reallocate memory */
1757  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, nbranchvars, 0, 0) );
1758 
1759  SCIPnodeGetAncestorBranchingsPart(node, parent,
1760  reopttree->reoptnodes[id]->vars,
1761  reopttree->reoptnodes[id]->varbounds,
1762  reopttree->reoptnodes[id]->varboundtypes,
1763  &nbranchvars,
1764  reopttree->reoptnodes[id]->varssize);
1765  }
1766 
1767  assert(nbranchvars <= reopttree->reoptnodes[id]->varssize); /* this should be the case */
1768 
1769  reopttree->reoptnodes[id]->nvars = nbranchvars;
1770 
1771  assert(nbranchvars <= reopttree->reoptnodes[id]->varssize);
1772  assert(reopttree->reoptnodes[id]->vars != NULL );
1773 
1774  return SCIP_OKAY;
1775 }
1776 
1777 /** save additional all constraints that were additionally added to @p node */
1778 static
1780  SCIP_REOPTTREE* reopttree, /**< reopttree */
1781  SCIP_SET* set, /**< global SCIP settings */
1782  BMS_BLKMEM* blkmem, /**< block memory */
1783  SCIP_NODE* node, /**< node of the branch and bound tree */
1784  unsigned int id /**< id of the node*/
1785  )
1786 {
1787  SCIP_CONS** addedcons;
1788  SCIP_Real constant;
1789  SCIP_Real scalar;
1790  int var;
1791  int consnr;
1792  int naddedconss;
1793  int addedconsssize;
1794  int nconss;
1795 
1796  assert(node != NULL );
1797  assert(reopttree != NULL);
1798  assert(id < reopttree->reoptnodessize);
1799 
1800  /* save the added pseudo-constraint */
1801  if(SCIPnodeGetNAddedConss(node) > 0)
1802  {
1803  addedconsssize = SCIPnodeGetNAddedConss(node);
1804 
1805  SCIPdebugMessage(" -> save %d locally added constraints\n", addedconsssize);
1806 
1807  /* get memory */
1808  SCIP_CALL( SCIPsetAllocBufferArray(set, &addedcons, addedconsssize) );
1809  SCIPnodeGetAddedConss(node, addedcons, &naddedconss, addedconsssize);
1810 
1811  nconss = reopttree->reoptnodes[id]->nconss;
1812 
1813  /* check memory for added constraints */
1814  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, 0, 0, nconss+naddedconss) );
1815 
1816  for(consnr = 0; consnr < naddedconss; consnr++)
1817  {
1818  SCIP_Bool success;
1819 
1820  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]->conss[nconss]) ); /*lint !e866*/
1821 
1822  success = FALSE;
1823  SCIP_CALL( SCIPconsGetNVars(addedcons[consnr], set, &reopttree->reoptnodes[id]->conss[nconss]->nvars, &success) );
1824  assert(success);
1825  reopttree->reoptnodes[id]->conss[nconss]->varssize = reopttree->reoptnodes[id]->conss[nconss]->nvars;
1826 
1827  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopttree->reoptnodes[id]->conss[nconss]->vars,
1828  reopttree->reoptnodes[id]->conss[nconss]->nvars) );
1829  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopttree->reoptnodes[id]->conss[nconss]->vals,
1830  reopttree->reoptnodes[id]->conss[nconss]->nvars) );
1831 
1832  success = FALSE;
1833  SCIP_CALL( SCIPconsGetVars(addedcons[consnr], set, reopttree->reoptnodes[id]->conss[nconss]->vars, reopttree->reoptnodes[id]->conss[nconss]->nvars, &success) );
1834  assert(success);
1835 
1836  if( strcmp("sepasol", SCIPconsGetName(addedcons[consnr])) == 0 )
1837  reopttree->reoptnodes[id]->conss[nconss]->constype = REOPT_CONSTYPE_SEPASOLUTION;
1838  else if( strcmp("infsubtree", SCIPconsGetName(addedcons[consnr])) == 0 )
1839  reopttree->reoptnodes[id]->conss[nconss]->constype = REOPT_CONSTYPE_INFSUBTREE;
1840  else if( strcmp("splitcons", SCIPconsGetName(addedcons[consnr])) == 0 )
1841  reopttree->reoptnodes[id]->conss[nconss]->constype = REOPT_CONSTYPE_STRBRANCHED;
1842 
1843  assert(reopttree->reoptnodes[id]->conss[nconss]->constype == REOPT_CONSTYPE_SEPASOLUTION
1844  || reopttree->reoptnodes[id]->conss[nconss]->constype == REOPT_CONSTYPE_INFSUBTREE
1845  || reopttree->reoptnodes[id]->conss[nconss]->constype == REOPT_CONSTYPE_STRBRANCHED);
1846 
1847  for(var = 0; var < reopttree->reoptnodes[id]->conss[nconss]->nvars; var++)
1848  {
1849  constant = 0;
1850  scalar = 1;
1851 
1852  if(!SCIPvarIsOriginal(reopttree->reoptnodes[id]->conss[nconss]->vars[var]))
1853  {
1854  if(SCIPvarIsNegated(reopttree->reoptnodes[id]->conss[nconss]->vars[var]))
1855  {
1856  SCIP_CALL(SCIPvarGetOrigvarSum(&reopttree->reoptnodes[id]->conss[nconss]->vars[var], &scalar, &constant));
1857  reopttree->reoptnodes[id]->conss[nconss]->vals[var] = 1;
1858  }
1859  else
1860  {
1861  SCIP_CALL(SCIPvarGetOrigvarSum(&reopttree->reoptnodes[id]->conss[nconss]->vars[var], &scalar, &constant));
1862  reopttree->reoptnodes[id]->conss[nconss]->vals[var] = 0;
1863  }
1864  assert(reopttree->reoptnodes[id]->conss[nconss]->vars[var] != NULL );
1865  }
1866  assert(SCIPvarIsOriginal(reopttree->reoptnodes[id]->conss[nconss]->vars[var]));
1867  }
1868 
1869  /* increase the counter for added constraints */
1870  ++reopttree->reoptnodes[id]->nconss;
1871  ++nconss;
1872  }
1873 
1874  assert(reopttree->reoptnodes[id]->nconss == naddedconss);
1875  SCIPsetFreeBufferArray(set, &addedcons);
1876  }
1877 
1878  return SCIP_OKAY;
1879 }
1880 
1881 /** collect all bound changes based on dual information
1882  *
1883  * if the bound changes are global, all information are already stored because they were caught by the event handler.
1884  * otherwise, we have to use SCIPnodeGetDualBoundchgs.
1885  *
1886  * afterwards, we check if the constraint will be added in the next iteration or after splitting the node.
1887  */
1888 static
1890  SCIP_REOPT* reopt, /**< reoptimization data structure */
1891  BMS_BLKMEM* blkmem, /**< block memory */
1892  SCIP_NODE* node, /**< node of the search tree */
1893  unsigned int id, /**< id of the node */
1894  SCIP_REOPTTYPE reopttype /**< reopttype */
1895  )
1896 {
1897  SCIP_Real constant;
1898  SCIP_Real scalar;
1899  SCIP_Bool cons_is_next;
1900  int nbndchgs;
1901  int v;
1902 
1903  assert(reopt != NULL);
1904  assert(reopt->reopttree != NULL);
1905  assert(id < reopt->reopttree->reoptnodessize);
1906  assert(reopt->reopttree->reoptnodes[id]->dualfixing);
1907  assert(node != NULL);
1908  assert(blkmem != NULL);
1909 
1910  cons_is_next = TRUE;
1911 
1912  /* first case, all bound changes were global */
1913  if( reopt->currentnode == SCIPnodeGetNumber(node) && reopt->dualcons != NULL && reopt->dualcons->nvars > 0 )
1914  {
1915  nbndchgs = reopt->dualcons->nvars;
1916  }
1917  else
1918  {
1919  assert(reopt->currentnode == SCIPnodeGetNumber(node));
1920 
1921  /* get the number of bound changes based on dual information */
1922  nbndchgs = SCIPnodeGetNDualBndchgs(node);
1923 
1924  /* ensure that enough memory is allocated */
1925  SCIP_CALL( checkMemDualCons(reopt, blkmem, nbndchgs) );
1926 
1927  /* collect the bound changes */
1929  reopt->dualcons->vars,
1930  reopt->dualcons->vals,
1931  &nbndchgs,
1932  reopt->dualcons->varssize);
1933 
1934  assert(nbndchgs <= reopt->dualcons->varssize);
1935 
1936  reopt->dualcons->nvars = nbndchgs;
1937 
1938  /* transform the variables into the original space */
1939  for(v = 0; v < nbndchgs; v++)
1940  {
1941  constant = 0.0;
1942  scalar = 1.0;
1943 
1944  SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->dualcons->vars[v], &scalar, &constant) );
1945  reopt->dualcons->vals[v] = (reopt->dualcons->vals[v] - constant) / scalar;
1946 
1947  assert(SCIPvarIsOriginal(reopt->dualcons->vars[v]));
1948  }
1949  }
1950 
1951  assert(nbndchgs > 0);
1952 
1953  /* due to the strong branching initialization it can be possible that two
1954  * constraints handling dual information are stored at the same time.
1955  * during reoptimizing a node we add the constraint stored at dualconscur only,
1956  * i.e, if dualconscur is not NULL, we need to store the constraint the
1957  * constraint for the next iteration at dualconsnex because the constraint
1958  * stored at dualconscur is needed to split the constraint in the current
1959  * iteration.
1960  */
1961  if( reopt->reopttree->reoptnodes[id]->dualconscur != NULL )
1962  {
1963  assert(reopt->reopttree->reoptnodes[id]->dualconsnex == NULL);
1964  cons_is_next = FALSE;
1965  }
1966  assert((cons_is_next && reopt->reopttree->reoptnodes[id]->dualconscur == NULL)
1967  || (!cons_is_next && reopt->reopttree->reoptnodes[id]->dualconsnex == NULL));
1968 
1969  /* the constraint will be added next */
1970  if( cons_is_next )
1971  {
1972  assert(reopt->reopttree->reoptnodes[id]->dualconscur == NULL);
1975  reopt->dualcons->vars, nbndchgs) );
1977  reopt->dualcons->vals, nbndchgs) );
1978 
1979  reopt->reopttree->reoptnodes[id]->dualconscur->nvars = nbndchgs;
1980  reopt->reopttree->reoptnodes[id]->dualconscur->varssize = nbndchgs;
1982 
1983  SCIPdebugMessage(" -> save dual information of type 1: node %lld, nvars %d, constype %d\n",
1985  reopt->reopttree->reoptnodes[id]->dualconscur->constype);
1986  }
1987  /* the constraint will be added after next */
1988  else
1989  {
1990  assert(reopt->reopttree->reoptnodes[id]->dualconsnex == NULL);
1992  reopt->reopttree->reoptnodes[id]->dualconsnex->nvars = -1;
1993 
1994  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualconsnex->vars, reopt->dualcons->vars, nbndchgs) );
1995  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualconsnex->vals, reopt->dualcons->vals, nbndchgs) );
1996  reopt->reopttree->reoptnodes[id]->dualconsnex->nvars = nbndchgs;
1997  reopt->reopttree->reoptnodes[id]->dualconsnex->varssize = nbndchgs;
1999 
2000  SCIPdebugMessage(" -> save dual information of type 2: node %lld, nvars %d, constype %d\n",
2002  reopt->reopttree->reoptnodes[id]->dualconsnex->constype);
2003  }
2004 
2005 
2006  return SCIP_OKAY;
2007 }
2008 
2009 /** adds a node of the branch and bound tree to the reoptimization tree */
2010 static
2012  SCIP_REOPT* reopt, /**< reoptimization data structure */
2013  SCIP_SET* set, /**< global SCIP settings */
2014  BMS_BLKMEM* blkmem, /**< block memory */
2015  SCIP_NODE* node, /**< current node */
2016  SCIP_REOPTTYPE reopttype, /**< reason for storing the node*/
2017  SCIP_Bool saveafterdual, /**< save branching decisions after the first dual */
2018  SCIP_Bool isrootnode, /**< node is the root node */
2019  SCIP_Real lowerbound /**< lower bound of the node */
2020  )
2021 {
2022  SCIP_NODE* parent;
2023  SCIP_Bool shrank;
2024  unsigned int id;
2025  unsigned int parentid;
2026 
2027  assert(reopt != NULL);
2028  assert(set != NULL);
2029  assert(blkmem != NULL);
2030  assert(node != NULL);
2031 
2032  parentid = 0;
2033  parent = NULL;
2034  shrank = FALSE;
2035 
2036  if( set->reopt_maxsavednodes == 0 )
2037  return SCIP_OKAY;
2038 
2039  assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2040  || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2041  || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2042  || reopttype == SCIP_REOPTTYPE_LOGICORNODE
2043  || reopttype == SCIP_REOPTTYPE_LEAF
2044  || reopttype == SCIP_REOPTTYPE_PRUNED
2045  || reopttype == SCIP_REOPTTYPE_FEASIBLE);
2046 
2047  /* start clock */
2048  SCIPclockStart(reopt->savingtime, set);
2049 
2050  /* the node was created by reoptimization, i.e., we need to update the
2051  * stored data */
2052  if( SCIPnodeGetReoptID(node) >= 1 )
2053  {
2054  SCIP_Bool transintoorig;
2055 
2056  assert(reopttype != SCIP_REOPTTYPE_LEAF);
2057  assert(!isrootnode);
2058 
2059  id = SCIPnodeGetReoptID(node);
2060  assert(id < reopt->reopttree->reoptnodessize);
2061  assert(reopt->reopttree->reoptnodes[id] != NULL);
2062 
2063  SCIPdebugMessage("update node %lld at ID %u:\n", SCIPnodeGetNumber(node), id);
2064 
2065  transintoorig = FALSE;
2066 
2067  /* store in*/
2068  if( saveafterdual )
2069  {
2070  SCIP_CALL( saveAfterDualBranchings(reopt, blkmem, node, id, &transintoorig) );
2071  }
2072 
2073  /* update constraint propagations */
2074  if( set->reopt_saveconsprop )
2075  {
2076  SCIP_CALL( updateConstraintPropagation(reopt, blkmem, node, id, &transintoorig) );
2077  }
2078 
2079  /* ensure that all variables are original */
2080  if( transintoorig )
2081  {
2082  SCIP_CALL( transformIntoOrig(reopt, id) );
2083  }
2084 
2085  /* update the lowerbound */
2086  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2087  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2088 
2089 #ifdef SCIP_DEBUG
2090  int varnr;
2091 
2092  SCIPdebugMessage(" -> nvars: %d, ncons: %d, parentID: %d, reopttype: %d\n",
2093  reopt->reopttree->reoptnodes[id]->nvars,
2094  reopt->reopttree->reoptnodes[id]->nconss,
2095  reopt->reopttree->reoptnodes[id]->parentID, reopttype);
2096 #ifdef SCIP_MORE_DEBUG
2097  SCIPdebugMessage(" -> saved variables:\n");
2098  for (varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; varnr++)
2099  {
2100  SCIPdebugMessage(" <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
2101  reopt->reopttree->reoptnodes[id]->varboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
2102  "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
2103  }
2104  for (varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; varnr++)
2105  {
2106  SCIPdebugMessage(" <%s> %s %g (after dual red.)\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
2108  "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
2109  }
2110 #endif
2111 #endif
2112 
2113  /* update LPI state if node is pseudobranched or feasible */
2114  switch( reopttype ) {
2116  assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
2117 
2118  if( set->reopt_shrinkinner )
2119  {
2120  SCIP_CALL( shrinkNode(reopt, set, node, id, &shrank, blkmem) );
2121  }
2122 
2123  goto TRANSIT;
2124 
2125  break; /*lint !e527*/
2126 
2128  case SCIP_REOPTTYPE_LEAF:
2129  goto TRANSIT;
2130  break; /*lint !e527*/
2131 
2133  /* delete the whole subtree induced be the current node */
2134  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2135  goto PSEUDO;
2136  break; /*lint !e527*/
2137 
2139  goto PSEUDO;
2140  break; /*lint !e527*/
2141 
2143  /* delete the subtree */
2144  if( set->reopt_reducetofrontier )
2145  {
2146  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2147  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2148  }
2149  /* dive through all children and change the reopttype to PRUNED */
2150  else
2151  {
2153  }
2154  goto FEASIBLE;
2155  break; /*lint !e527*/
2156 
2157  case SCIP_REOPTTYPE_PRUNED:
2158  /* delete the subtree */
2159  if( set->reopt_reducetofrontier )
2160  {
2161  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2162  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2163  }
2164  /* dive through all children and change the reopttype to LEAF */
2165  else
2166  {
2168  }
2169 
2170  ++reopt->reopttree->ncutoffreoptnodes;
2172 
2173  goto PRUNED;
2174  break; /*lint !e527*/
2175 
2176  default:
2177  break;
2178  } /*lint !e788*/
2179 
2180  /* stop clock */
2181  SCIPclockStart(reopt->savingtime, set);
2182 
2183  return SCIP_OKAY;
2184  }
2185 
2186  /* get new IDs */
2187  SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, blkmem) );
2188 
2189  /* the current node is the root node */
2190  if( isrootnode )
2191  {
2192  id = 0;
2193 
2194  switch( reopttype ) {
2196  /* ensure that no dual constraints are stored */
2197  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2198 
2199  /* update the lowerbound */
2200  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2201  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2202 
2203  goto TRANSIT;
2204  break; /*lint !e527*/
2205 
2208  reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)reopttype;
2209  reopt->reopttree->reoptnodes[0]->dualfixing = TRUE;
2210  reopt->reopttree->reoptnodes[0]->nvars = 0;
2211 
2212  if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
2213  {
2214  /* delete the whole subtree induced be the current node */
2215  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2216  }
2217 
2218  SCIPdebugMessage("update node %d at ID %d:\n", 1, 0);
2219  SCIPdebugMessage(" -> nvars: 0, ncons: 0, parentID: -, reopttype: %u\n", reopttype);
2220 
2221  /* update the lowerbound */
2222  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2223  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2224 
2225  goto PSEUDO;
2226  break; /*lint !e527*/
2227 
2229  ++reopt->reopttree->ntotalfeasnodes;
2230  ++reopt->reopttree->nfeasnodes;
2231  reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
2232  reopt->reopttree->reoptnodes[0]->dualfixing = FALSE;
2233 
2234  if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2235  {
2236  /* delete the subtree */
2237  if( set->reopt_reducetofrontier )
2238  {
2239  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2240  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2241  }
2242  /* dive through all children and change the reopttype to LEAF */
2243  else
2244  {
2246  }
2247  }
2248  else
2249  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2250 
2251  /* update the lowerbound */
2252  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2253  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2254 
2255  SCIPdebugMessage("update node %d at ID %d:\n", 1, 0);
2256  SCIPdebugMessage(" -> nvars: 0, ncons: 0, parentID: -, reopttype: %u\n", reopttype);
2257 
2258  break;
2259 
2260  case SCIP_REOPTTYPE_PRUNED:
2261  ++reopt->reopttree->nprunednodes;
2262  ++reopt->reopttree->ntotalprunednodes;
2263  reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
2264  reopt->reopttree->reoptnodes[0]->dualfixing = FALSE;
2265 
2266  if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2267  {
2268  /* delete the subtree */
2269  if( set->reopt_reducetofrontier )
2270  {
2271  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2272  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2273  }
2274  /* dive through all children and change the reopttype to LEAF */
2275  else
2276  {
2278  }
2279  }
2280  else
2281  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2282 
2283  /* update the lowerbound if it was not set */
2284  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2285  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2286 
2287  SCIPdebugMessage("update node %d at ID %d:\n", 1, 0);
2288  SCIPdebugMessage(" -> nvars: 0, ncons: 0, parentID: -, reopttype: %u\n", reopttype);
2289 
2290  break;
2291 
2292  default:
2293  assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2294  || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2295  || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2296  || reopttype == SCIP_REOPTTYPE_PRUNED
2297  || reopttype == SCIP_REOPTTYPE_FEASIBLE);
2298  break;
2299  }/*lint !e788*/
2300 
2301  /* reset the information of dual bound changes */
2302  reopt->currentnode = -1;
2303  if( reopt->dualcons != NULL )
2304  reopt->dualcons->nvars = 0;
2305 
2306  /* stop clock */
2307  SCIPclockStop(reopt->savingtime, set);
2308 
2309  return SCIP_OKAY;
2310  }
2311  else
2312  {
2313  int nbndchgdiff;
2314  SCIP_Bool transintoorig;
2315 
2316  SCIPdebugMessage("try to add node #%lld to the reopttree\n", SCIPnodeGetNumber(node));
2317  SCIPdebugMessage(" -> reopttype = %u\n", reopttype);
2318 
2319  /*
2320  * check if we really want to save this node:
2321  * 1. save the node if reopttype is at least LOGICORNODE
2322  * 2. save the node if the number of bound changes of this node
2323  * and the last saved node is at least a given number n
2324  */
2325 
2326  /* get the ID of the last saved node or 0 for the root */
2327  SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &nbndchgdiff) );
2328 
2329  if( reopttype < SCIP_REOPTTYPE_INFSUBTREE && nbndchgdiff <= set->reopt_maxdiffofnodes)
2330  {
2331  SCIPdebugMessage(" -> skip saving\n");
2332 
2333  /* stop clock */
2334  SCIPclockStop(reopt->savingtime, set);
2335 
2336  return SCIP_OKAY;
2337  }
2338 
2339  /* check if there are free slots to store the node */
2340  SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, blkmem) );
2341 
2342  id = (unsigned int) (size_t) SCIPqueueRemove(reopt->reopttree->openids);
2343 
2344  SCIPdebugMessage(" -> save at ID %u\n", id);
2345 
2346  assert(reopt->reopttree->reoptnodes[id] == NULL
2347  || (reopt->reopttree->reoptnodes[id]->nvars == 0 && reopt->reopttree->reoptnodes[id]->nconss == 0));
2348  assert(id >= 1 && id < reopt->reopttree->reoptnodessize);
2349  assert(!isrootnode);
2350 
2351  /* get memory for nodedata */
2352  assert(reopt->reopttree->reoptnodes[id] == NULL || reopt->reopttree->reoptnodes[id]->nvars == 0);
2353  SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, id) );
2354  reopt->reopttree->reoptnodes[id]->parentID = parentid;
2355 
2356  assert(parent != NULL );
2357  assert((SCIPnodeGetDepth(parent) == 0 && parentid == 0) || (SCIPnodeGetDepth(parent) >= 1 && parentid > 0));
2358  assert(id >= 1);
2359 
2360  /* create the array of "child nodes" if they not exist */
2361  if( reopt->reopttree->reoptnodes[parentid]->childids == NULL
2362  || reopt->reopttree->reoptnodes[parentid]->allocchildmem == 0 )
2363  {
2364  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], blkmem, 0, 10, 0) );
2365  }
2366 
2367  /* add the "child node" */
2368  SCIP_CALL( reoptAddChild(reopt->reopttree, blkmem, parentid, id) );
2369 
2370  /* save branching path */
2371  SCIP_CALL( saveAncestorBranchings(reopt->reopttree, blkmem, node, parent, id, parentid) );
2372 
2373  /* save bound changes after some dual reduction */
2374  if( saveafterdual )
2375  {
2376  SCIP_CALL( saveAfterDualBranchings(reopt, blkmem, node, id, &transintoorig) );
2377  }
2378  else
2379  {
2380  SCIPdebugMessage(" -> skip saving bound changes after dual reductions.\n");
2381  }
2382 
2383  /* transform all bounds of branched variables and ensure that they are original. */
2384  SCIP_CALL( transformIntoOrig(reopt, id) );
2385 
2386  /* save pseudo-constraints (if one exists) */
2387  if (SCIPnodeGetNAddedConss(node) >= 1)
2388  {
2389  assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
2390 
2391  SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
2392  }
2393 
2394  /* update the lowerbound if it was not set */
2395  if( !SCIPsetIsEQ(set, REALABS(lowerbound), SCIPsetInfinity(set)) )
2396  reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2397 
2398  /* set ID */
2399  SCIPnodeSetReoptID(node, id);
2400 
2401  /* set the REOPTTYPE */
2402  SCIPnodeSetReopttype(node, reopttype);
2403 
2404 #ifdef SCIP_DEBUG
2405  int varnr;
2406  SCIPdebugMessage("save node #%lld successful\n", SCIPnodeGetNumber(node));
2407  SCIPdebugMessage(" -> ID %d, nvars %d, ncons %d, reopttype %d\n",
2408  id, reopt->reopttree->reoptnodes[id]->nvars + reopt->reopttree->reoptnodes[id]->nafterdualvars,
2409  reopt->reopttree->reoptnodes[id]->nconss,
2410  reopttype);
2411 #ifdef SCIP_MORE_DEBUG
2412  for (varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; varnr++)
2413  {
2414  SCIPdebugMessage(" <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
2415  reopt->reopttree->reoptnodes[id]->varboundtypes[varnr] == SCIP_BOUNDTYPE_LOWER ?
2416  "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
2417  }
2418  for (varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; varnr++)
2419  {
2420  SCIPdebugMessage(" <%s> %s %g (after dual red.)\n",
2421  SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
2423  "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
2424  }
2425 #endif
2426 #endif
2427  }
2428 
2429  switch( reopttype ) {
2432  case SCIP_REOPTTYPE_LEAF:
2433  TRANSIT:
2434 
2435  if( !shrank )
2436  {
2437  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
2438  }
2439  else
2440  {
2441  SCIPnodeSetReoptID(node, 0);
2443  }
2444  break;
2445 
2448  PSEUDO:
2449 
2450  assert(reopt->currentnode == SCIPnodeGetNumber(node));
2451 
2452  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
2453  reopt->reopttree->reoptnodes[id]->dualfixing = TRUE;
2454 
2455  /* get all the dual information and decide if the constraint need
2456  * to be added next or after next */
2457  SCIP_CALL( collectDualInformation(reopt, blkmem, node, id, reopttype) );
2458 
2459  break;
2460 
2462  FEASIBLE:
2463  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
2464  reopt->reopttree->reoptnodes[id]->dualfixing = FALSE;
2465  ++reopt->reopttree->nfeasnodes;
2466  ++reopt->reopttree->ntotalfeasnodes;
2467 
2468  break;
2469 
2470  case SCIP_REOPTTYPE_PRUNED:
2471  PRUNED:
2472 
2473  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
2474  reopt->reopttree->reoptnodes[id]->dualfixing = FALSE;
2475  ++reopt->reopttree->nprunednodes;
2476  ++reopt->reopttree->ntotalprunednodes;
2477 
2478  break;
2479 
2480  default:
2481  assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2482  || reopttype == SCIP_REOPTTYPE_LOGICORNODE
2483  || reopttype == SCIP_REOPTTYPE_LEAF
2484  || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2485  || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2486  || reopttype == SCIP_REOPTTYPE_FEASIBLE
2487  || reopttype == SCIP_REOPTTYPE_PRUNED);
2488  break;
2489  } /*lint !e788*/
2490 
2491  /* stop clock */
2492  SCIPclockStop(reopt->savingtime, set);
2493 
2494  /* reset the information of dual bound changes */
2495  reopt->currentnode = -1;
2496  if( reopt->dualcons != NULL )
2497  reopt->dualcons->nvars = 0;
2498 
2499  return SCIP_OKAY;
2500 }
2501 
2502 /** delete the stored information about dual bound changes of the last focused node */
2503 static
2505  SCIP_REOPT* reopt /**< reoptimization data structure */
2506  )
2507 {
2508  assert(reopt != NULL);
2509 
2510  if( reopt->dualcons != NULL && reopt->dualcons->nvars > 0 )
2511  {
2512  SCIPdebugMessage("delete %d dual variable information about node %lld\n", reopt->dualcons->nvars,
2513  reopt->currentnode);
2514  reopt->dualcons->nvars = 0;
2515  reopt->currentnode = -1;
2516  }
2517 }
2518 
2519 /** delete the stored constraints that dual information at the given reoptimization node */
2520 static
2522  SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
2523  BMS_BLKMEM* blkmem /**< block memory */
2524  )
2525 {
2526  assert(reoptnode != NULL);
2527  assert(blkmem != NULL);
2528 
2529  if( reoptnode->dualconscur != NULL )
2530  {
2531  SCIPdebugMessage("reset dual (1) information\n");
2532 
2533  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconscur->vals, reoptnode->dualconscur->varssize);
2534  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconscur->vars, reoptnode->dualconscur->varssize);
2535  BMSfreeBlockMemory(blkmem, &reoptnode->dualconscur);
2536  reoptnode->dualconscur = NULL;
2537  }
2538 
2539  if( reoptnode->dualconsnex != NULL )
2540  {
2541  SCIPdebugMessage("reset dual (2) information\n");
2542 
2543  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconsnex->vals, reoptnode->dualconsnex->varssize);
2544  BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualconsnex->vars, reoptnode->dualconsnex->varssize);
2545  BMSfreeBlockMemory(blkmem, &reoptnode->dualconsnex);
2546  reoptnode->dualconsnex = NULL;
2547  }
2548 
2549  reoptnode->dualfixing = FALSE;
2550 
2551  return SCIP_OKAY;
2552 }
2553 
2554 /** generate a global constraint to separate an infeasible subtree */
2555 static
2557  SCIP_REOPT* reopt, /**< reoptimization data structure */
2558  SCIP_SET* set, /**< global SCIP settings */
2559  BMS_BLKMEM* blkmem, /**< block memory */
2560  SCIP_NODE* node, /**< node of the search tree */
2561  REOPT_CONSTYPE consttype /**< reopttype of the constraint */
2562  )
2563 {
2564  assert(reopt != NULL);
2565  assert(node != NULL);
2566 
2567  if( consttype == REOPT_CONSTYPE_INFSUBTREE )
2568  {
2569  SCIP_BOUNDTYPE* boundtypes;
2570  int nbranchvars;
2571  int nvars;
2572  int nglbconss;
2573  int v;
2574 
2575  nglbconss = reopt->nglbconss;
2576  nvars = SCIPnodeGetDepth(node)+1;
2577 
2578  /* check if enough memory to store the global constraint is available */
2579  SCIP_CALL( checkMemGlbCons(reopt, blkmem, nglbconss+1) );
2580 
2581  /* allocate memory to store the infeasible path
2582  * we use the permanent allocated array consbounds to store the boundtypes */
2583  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[nglbconss]) ); /*lint !e866*/
2584  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->glbconss[nglbconss]->vars, nvars) );
2585  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->glbconss[nglbconss]->vals, nvars) );
2586 
2587  /* allocate buffer */
2588  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, nvars) );
2589 
2590  reopt->glbconss[nglbconss]->varssize = nvars;
2591  reopt->glbconss[nglbconss]->constype = REOPT_CONSTYPE_INFSUBTREE;
2592 
2594  reopt->glbconss[nglbconss]->vars,
2595  reopt->glbconss[nglbconss]->vals,
2596  boundtypes,
2597  &nbranchvars,
2598  nvars);
2599 
2600  if( nvars < nbranchvars )
2601  {
2602  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->glbconss[nglbconss]->vars, nvars, nbranchvars) );
2603  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->glbconss[nglbconss]->vals, nvars, nbranchvars) );
2604  nvars = nbranchvars;
2605  reopt->glbconss[nglbconss]->varssize = nvars;
2606 
2607  SCIPnodeGetAncestorBranchings(node, reopt->glbconss[nglbconss]->vars, reopt->glbconss[nglbconss]->vals,
2608  boundtypes, &nbranchvars, nvars);
2609  }
2610 
2611  /* transform into original variables */
2612  for(v = 0; v < nbranchvars; v++)
2613  {
2614  SCIP_Real constant;
2615  SCIP_Real scalar;
2616 
2617  constant = 0;
2618  scalar = 1;
2619 
2620  SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->glbconss[nglbconss]->vars[v], &scalar, &constant) );
2621  reopt->glbconss[nglbconss]->vals[v] = (reopt->glbconss[nglbconss]->vals[v] - constant)/scalar;
2622 
2623  assert(SCIPsetIsFeasEQ(set, reopt->glbconss[nglbconss]->vals[v], 0.0) || SCIPsetIsFeasEQ(set,
2624  reopt->glbconss[nglbconss]->vals[v], 1.0));
2625  }
2626 
2627  /* free buffer */
2628  SCIPsetFreeBufferArray(set, &boundtypes);
2629 
2630  /* increase the number of global constraints */
2631  ++reopt->nglbconss;
2632  }
2633 
2634  return SCIP_OKAY;
2635 }
2636 
2637 
2638 /** move all id of child nodes from reoptimization node stored at @p id1 to the node stored at @p id2 */
2639 static
2641  SCIP_REOPTTREE* reopttree, /**< reopttree */
2642  BMS_BLKMEM* blkmem, /**< block memory */
2643  unsigned int id1, /**< source id */
2644  unsigned int id2 /**< target id */
2645  )
2646 {
2647  int c;
2648  int nchilds_id1;
2649  int nchilds_id2;
2650 
2651  assert(reopttree != NULL);
2652  assert(blkmem != NULL);
2653  assert(id1 < reopttree->reoptnodessize);
2654  assert(id2 < reopttree->reoptnodessize);
2655  assert(reopttree->reoptnodes[id1] != NULL);
2656  assert(reopttree->reoptnodes[id2] != NULL);
2657 
2658  nchilds_id1 = reopttree->reoptnodes[id1]->nchilds;
2659  nchilds_id2 = reopttree->reoptnodes[id2]->nchilds;
2660 
2661  /* ensure that the array storing the child id's is large enough */
2662  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id2], blkmem, 0, nchilds_id1+nchilds_id2, 0) );
2663  assert(reopttree->reoptnodes[id2]->allocchildmem >= nchilds_id1+nchilds_id2);
2664 
2665  SCIPdebugMessage("move %d IDs: %u -> %u\n", nchilds_id1, id1, id2);
2666 
2667  /* move the ids */
2668  for(c = 0; c < nchilds_id1; c++)
2669  {
2670 
2671 #ifdef SCIP_DEBUG
2672  /* check that no id is added twice */
2673  int k;
2674  for(k = 0; k < nchilds_id2; k++)
2675  assert(reopttree->reoptnodes[id2]->childids[k] != reopttree->reoptnodes[id1]->childids[c]);
2676 #endif
2677 
2678  reopttree->reoptnodes[id2]->childids[nchilds_id2+c] = reopttree->reoptnodes[id1]->childids[c];
2679  }
2680 
2681  /* update the number of childs */
2682  reopttree->reoptnodes[id1]->nchilds = 0;
2683  reopttree->reoptnodes[id2]->nchilds += nchilds_id1;
2684 
2685  return SCIP_OKAY;
2686 }
2687 
2688 /** change all bound changes along the root path */
2689 static
2691  SCIP_REOPT* reopt, /**< reoptimization data structure */
2692  SCIP_SET* set, /**< global SCIP settings */
2693  SCIP_STAT* stat, /**< dynamic problem statistics */
2694  SCIP_PROB* transprob, /**< transformed problem */
2695  SCIP_PROB* origprob, /**< original problem */
2696  SCIP_TREE* tree, /**< search tree */
2697  SCIP_LP* lp, /**< current LP */
2698  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
2699  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2700  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
2701  BMS_BLKMEM* blkmem, /**< block memory */
2702  SCIP_NODE* node, /**< node of the branch and bound tree */
2703  unsigned int id, /**< id of stored node */
2704  SCIP_Bool afterdualintobranching /**< apply and convert bound changes made after the first based on dual information into branchings */
2705  )
2706 {
2707  SCIP_REOPTTREE* reopttree;
2708  SCIP_REOPTNODE* reoptnode;
2709  int v;
2710 
2711  assert(reopt != NULL);
2712  assert(set != NULL);
2713  assert(stat != NULL);
2714  assert(transprob != NULL);
2715  assert(tree != NULL);
2716  assert(lp != NULL);
2717  assert(branchcand != NULL);
2718  assert(eventqueue != NULL);
2719  assert(cliquetable != NULL);
2720  assert(node != NULL);
2721  assert(blkmem != NULL);
2722 
2723  reopttree = reopt->reopttree;
2724  assert(reopttree != NULL);
2725  assert(id < reopttree->reoptnodessize);
2726 
2727  reoptnode = reopttree->reoptnodes[id];
2728  assert(reoptnode != NULL);
2729 
2730  /* copy memory to ensure that only original variables are saved */
2731  if( reoptnode->nvars == 0 && reoptnode->nafterdualvars == 0)
2732  return SCIP_OKAY;
2733 
2734  /* change the bounds along the branching path */
2735  for(v = 0; v < reoptnode->nvars; v++)
2736  {
2737  SCIP_VAR* var;
2738  SCIP_Real val;
2739  SCIP_BOUNDTYPE boundtype;
2740  SCIP_Real oldlb;
2741  SCIP_Real oldub;
2742  SCIP_Real newbound;
2743 
2744  var = reoptnode->vars[v];
2745  val = reoptnode->varbounds[v];
2746  boundtype = reoptnode->varboundtypes[v];
2747 
2748  assert(SCIPvarIsOriginal(var));
2749  SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
2750  assert(SCIPvarIsTransformed(var));
2751  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR);
2752 
2753  oldlb = SCIPvarGetLbLocal(var);
2754  oldub = SCIPvarGetUbLocal(var);
2755  newbound = val;
2756 
2757  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
2758 
2759  if(boundtype == SCIP_BOUNDTYPE_LOWER
2760  && SCIPsetIsGT(set, newbound, oldlb)
2761  && SCIPsetIsFeasLE(set, newbound, oldub))
2762  {
2763  SCIPvarAdjustLb(var, set, &newbound);
2764 
2765  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2766  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
2767  }
2768  else if(boundtype == SCIP_BOUNDTYPE_UPPER
2769  && SCIPsetIsLT(set, newbound, oldub)
2770  && SCIPsetIsFeasGE(set, newbound, oldlb))
2771  {
2772  SCIPvarAdjustUb(var, set, &newbound);
2773 
2774  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2775  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
2776  }
2777 #ifdef SCIP_MORE_DEBUG
2778  SCIPdebugMessage(" (path) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=",
2779  newbound);
2780 #endif
2781  }
2782 
2783  if( afterdualintobranching && reoptnode->nafterdualvars > 0 )
2784  {
2785  /* check the memory to convert this bound changes into 'normal' */
2786  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, reoptnode->nvars + reoptnode->nafterdualvars,
2787  0, 0) );
2788 
2789  /* change the bounds */
2790  for(v = 0; v < reoptnode->nafterdualvars; v++)
2791  {
2792  SCIP_VAR* var;
2793  SCIP_Real val;
2794  SCIP_BOUNDTYPE boundtype;
2795  SCIP_Bool bndchgd;
2796  SCIP_Real oldlb;
2797  SCIP_Real oldub;
2798  SCIP_Real newbound;
2799 
2800  var = reoptnode->afterdualvars[v];
2801  val = reoptnode->afterdualvarbounds[v];
2802  boundtype = reoptnode->afterdualvarboundtypes[v];
2803 
2804  assert(SCIPvarIsOriginal(var));
2805  SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
2806  assert(SCIPvarIsTransformed(var));
2807  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR);
2808 
2809  bndchgd = FALSE;
2810 
2811  oldlb = SCIPvarGetLbLocal(var);
2812  oldub = SCIPvarGetUbLocal(var);
2813  newbound = val;
2814 
2815  if(boundtype == SCIP_BOUNDTYPE_LOWER
2816  && SCIPsetIsGT(set, newbound, oldlb)
2817  && SCIPsetIsFeasLE(set, newbound, oldub))
2818  {
2819  SCIPvarAdjustLb(var, set, &newbound);
2820  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2821  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
2822 
2823  bndchgd = TRUE;
2824  }
2825  else if(boundtype == SCIP_BOUNDTYPE_UPPER
2826  && SCIPsetIsLT(set, newbound, oldub)
2827  && SCIPsetIsFeasGE(set, newbound, oldlb))
2828  {
2829  SCIPvarAdjustUb(var, set, &newbound);
2830  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2831  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
2832 
2833  bndchgd = TRUE;
2834  }
2835 
2836  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
2837 
2838 #ifdef SCIP_MORE_DEBUG
2839  SCIPdebugMessage(" (prop) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=",
2840  newbound);
2841 #endif
2842  if( bndchgd )
2843  {
2844  int nvars;
2845 
2846  nvars = reoptnode->nvars;
2847  reoptnode->vars[nvars] = reoptnode->afterdualvars[v];
2848  reoptnode->varbounds[nvars] = reoptnode->afterdualvarbounds[v];
2849  reoptnode->varboundtypes[nvars] = reoptnode->afterdualvarboundtypes[v];
2850  ++reoptnode->nvars;
2851  }
2852  }
2853 
2854  /* free the afterdualvars, -bounds, and -boundtypes */
2855  BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarboundtypes, reoptnode->afterdualvarssize);
2856  reoptnode->afterdualvarboundtypes = NULL;
2857 
2858  BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarbounds, reoptnode->afterdualvarssize);
2859  reoptnode->afterdualvarbounds = NULL;
2860 
2861  BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvars, reoptnode->afterdualvarssize);
2862  reoptnode->afterdualvars = NULL;
2863 
2864  reoptnode->nafterdualvars = 0;
2865  reoptnode->afterdualvarssize = 0;
2866  }
2867 
2868  return SCIP_OKAY;
2869 }
2870 
2871 /** add a constraint to ensure that at least one variable bound gets different */
2872 static
2874  SCIP_REOPT* reopt, /**< reoptimization data structure */
2875  SCIP* scip, /**< SCIP data structure */
2876  SCIP_SET* set, /**< global SCIP settings */
2877  SCIP_STAT* stat, /**< dynamic problem statistics */
2878  BMS_BLKMEM* blkmem, /**< block memory */
2879  SCIP_PROB* transprob, /**< transformed problem */
2880  SCIP_PROB* origprob, /**< original problem */
2881  SCIP_TREE* tree, /**< search tree */
2882  SCIP_LP* lp, /**< current LP */
2883  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
2884  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2885  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2886  SCIP_NODE* node, /**< node corresponding to the pruned part */
2887  unsigned int id /**< id of stored node */
2888  )
2889 {
2890  SCIP_CONS* cons;
2891  const char* name;
2892  int v;
2893 
2894  assert(reopt != NULL);
2895  assert(reopt->reopttree != NULL);
2896  assert(id < reopt->reopttree->reoptnodessize);
2897  assert(reopt->reopttree->reoptnodes[id] != NULL);
2898  assert(reopt->reopttree->reoptnodes[id]->dualfixing);
2899  assert(reopt->reopttree->reoptnodes[id]->dualconscur != NULL);
2900  assert(scip != NULL);
2901  assert(set != NULL);
2902  assert(stat != NULL);
2903  assert(blkmem != NULL);
2904  assert(transprob != NULL);
2905  assert(origprob != NULL);
2906  assert(tree != NULL);
2907  assert(lp != NULL);
2908  assert(branchcand != NULL);
2909  assert(eventqueue != NULL);
2910  assert(node != NULL);
2911 
2913  {
2914  SCIPdebugMessage(" create a split-node #%lld\n", SCIPnodeGetNumber(node));
2915  }
2917  {
2918  SCIPdebugMessage(" separate an infeasible subtree\n");
2919  }
2920 
2921  /* if the constraint consists of exactly one variable it can be interpreted
2922  * as a normal branching step, i.e., we can fix the variable to the negated bound */
2923  if( reopt->reopttree->reoptnodes[id]->dualconscur->nvars == 1 )
2924  {
2925  SCIP_VAR* var;
2926  SCIP_BOUNDTYPE boundtype;
2927  SCIP_Real oldlb;
2928  SCIP_Real oldub;
2929  SCIP_Real newbound;
2930 
2931  var = reopt->reopttree->reoptnodes[id]->dualconscur->vars[0];
2932  newbound = reopt->reopttree->reoptnodes[id]->dualconscur->vals[0];
2933  boundtype = SCIPsetIsFeasEQ(set, newbound, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
2934 
2935  assert(SCIPvarIsOriginal(var));
2936  SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
2937  assert(SCIPvarIsTransformed(var));
2938 
2939  oldlb = SCIPvarGetLbLocal(var);
2940  oldub = SCIPvarGetUbLocal(var);
2941 
2942  /* negate the bound */
2943  newbound = 1 - newbound;
2944  boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
2945 
2946  if(boundtype == SCIP_BOUNDTYPE_LOWER
2947  && SCIPsetIsGT(set, newbound, oldlb)
2948  && SCIPsetIsFeasLE(set, newbound, oldub))
2949  {
2950  SCIPvarAdjustLb(var, set, &newbound);
2951  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2952  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
2953  }
2954  else if(boundtype == SCIP_BOUNDTYPE_UPPER
2955  && SCIPsetIsLT(set, newbound, oldub)
2956  && SCIPsetIsFeasGE(set, newbound, oldlb))
2957  {
2958  SCIPvarAdjustUb(var, set, &newbound);
2959  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
2960  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
2961  }
2962 
2963  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
2964 
2965  SCIPdebugMessage(" -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
2966  boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
2967  }
2968  else
2969  {
2970  SCIP_VAR** consvars;
2971  SCIP_Real consval;
2972  SCIP_BOUNDTYPE consboundtype;
2973 
2974  /* allocate buffer */
2975  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->reopttree->reoptnodes[id]->dualconscur->nvars) );
2976 
2977  for(v = 0; v < reopt->reopttree->reoptnodes[id]->dualconscur->nvars; v++)
2978  {
2979  consvars[v] = reopt->reopttree->reoptnodes[id]->dualconscur->vars[v];
2980  consval = reopt->reopttree->reoptnodes[id]->dualconscur->vals[v];
2981  consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
2982 
2983  assert(SCIPvarIsOriginal(consvars[v]));
2984  SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
2985  assert(SCIPvarIsTransformed(consvars[v]));
2986  assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
2987 
2988  if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
2989  {
2990  SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
2991  assert(SCIPvarIsNegated(consvars[v]));
2992  }
2993  }
2994 
2996  name = "infsubtree";
2997  else
2998  {
3000  name = "splitcons";
3001  }
3002 
3003  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->reopttree->reoptnodes[id]->dualconscur->nvars, consvars,
3005 
3006  SCIPdebugMessage(" -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
3007  SCIPdebugPrintCons(scip, cons, NULL);
3008 
3009  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
3010  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3011 
3012  /* free buffer */
3013  SCIPfreeBufferArray(scip, &consvars);
3014  }
3015 
3016  return SCIP_OKAY;
3017 }
3018 
3019 /** fix all bounds ad stored in dualconscur at the given node @p node_fix */
3020 static
3022  SCIP_REOPT* reopt, /**< reoptimization data structure */
3023  SCIP_SET* set, /**< global SCIP settings */
3024  SCIP_STAT* stat, /**< dynamic problem statistics */
3025  SCIP_PROB* transprob, /**< transformed problem */
3026  SCIP_PROB* origprob, /**< original problem */
3027  SCIP_TREE* tree, /**< search tree */
3028  SCIP_LP* lp, /**< current LP */
3029  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
3030  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3031  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
3032  BMS_BLKMEM* blkmem, /**< block memory */
3033  SCIP_NODE* node, /**< node corresponding to the fixed part */
3034  unsigned int id, /**< id of stored node */
3035  SCIP_Bool updatedualconss /**< update constraint representing dual bound changes */
3036  )
3037 {
3038  SCIP_REOPTTREE* reopttree;
3039  SCIP_REOPTNODE* reoptnode;
3040  int v;
3041 
3042  assert(reopt != NULL);
3043  assert(set != NULL);
3044  assert(stat != NULL);
3045  assert(transprob != NULL);
3046  assert(origprob != NULL);
3047  assert(tree != NULL);
3048  assert(lp != NULL);
3049  assert(branchcand != NULL);
3050  assert(eventqueue != NULL);
3051  assert(cliquetable != NULL);
3052  assert(node != NULL);
3053  assert(blkmem != NULL);
3054 
3055  reopttree = reopt->reopttree;
3056  assert(0 < id && id < reopttree->reoptnodessize);
3057  assert(reopttree != NULL);
3058 
3059  reoptnode = reopttree->reoptnodes[id];
3060  assert(reoptnode != NULL);
3061  assert(reoptnode->dualfixing);
3062  assert(reoptnode->dualconscur != NULL);
3063 
3064  /* ensure that the arrays to store the bound changes are large enough */
3065  SCIP_CALL( reoptnodeCheckMemory(reoptnode, blkmem, reoptnode->nvars + reoptnode->dualconscur->nvars, 0, 0) );
3066 
3067  for(v = 0; v < reoptnode->dualconscur->nvars; v++)
3068  {
3069  SCIP_VAR* var;
3070  SCIP_Real val;
3071  SCIP_BOUNDTYPE boundtype;
3072  SCIP_Bool bndchgd;
3073 
3074  var = reoptnode->dualconscur->vars[v];
3075  val = reoptnode->dualconscur->vals[v];
3076  boundtype = SCIPsetIsFeasEQ(set, val, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
3077 
3078  SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
3079  assert(SCIPvarIsTransformedOrigvar(var));
3080 
3081  bndchgd = FALSE;
3082 
3083  if(boundtype == SCIP_BOUNDTYPE_LOWER
3084  && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
3085  && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)))
3086  {
3087  SCIPvarAdjustLb(var, set, &val);
3088  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3089  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
3090 
3091  bndchgd = TRUE;
3092  }
3093  else if(boundtype == SCIP_BOUNDTYPE_UPPER
3094  && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
3095  && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)))
3096  {
3097  SCIPvarAdjustUb(var, set, &val);
3098  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3099  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
3100 
3101  bndchgd = TRUE;
3102  }
3103  else if(boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER)
3104  {
3105  printf("** Unknown boundtype: %d **\n", boundtype);
3106  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3107  }
3108 #ifdef SCIP_MORE_DEBUG
3109  SCIPdebugMessage(" (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
3110 #endif
3111  /* add variable and bound to branching path information, because we don't want to delete this data */
3112  if( bndchgd )
3113  {
3114  int pos;
3115  SCIP_Real constant;
3116  SCIP_Real scalar;
3117 
3118  pos = reoptnode->nvars;
3119 
3120  reoptnode->vars[pos] = var;
3121  scalar = 1.0;
3122  constant = 0.0;
3123  SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
3124  assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
3125 
3126  reoptnode->varbounds[pos] = reoptnode->dualconscur->vals[v];
3127  reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
3128  ++reoptnode->nvars;
3129  }
3130  }
3131 
3132  if( updatedualconss )
3133  {
3134  /* delete dualconscur and move dualconsnex -> dualconscur */
3135  SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
3136  }
3137 
3138  return SCIP_OKAY;
3139 }
3140 
3141 /** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
3142  * keep the first negbndchg-1 bound changes as stored in dualconscur and negate the negbndchg-th bound.
3143  */
3144 static
3146  SCIP_REOPT* reopt, /**< reoptimization data structure */
3147  SCIP_SET* set, /**< global SCIP settings */
3148  SCIP_STAT* stat, /**< dynamic problem statistics */
3149  SCIP_PROB* transprob, /**< transformed problem */
3150  SCIP_PROB* origprob, /**< original problem */
3151  SCIP_TREE* tree, /**< search tree */
3152  SCIP_LP* lp, /**< current LP */
3153  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
3154  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3155  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
3156  BMS_BLKMEM* blkmem, /**< block memory */
3157  SCIP_NODE* node, /**< child node */
3158  unsigned int id, /**< id of the node */
3159  SCIP_VAR** vars, /**< variables in permuted order */
3160  SCIP_Real* vals, /**< bounds in permuted order */
3161  int nvars, /**< number of variables */
3162  int negbndchg /**< index of the variable that should negated */
3163  )
3164 {
3165  SCIP_VAR* var;
3166  SCIP_Real val;
3167  SCIP_BOUNDTYPE boundtype;
3168  int nbndchgs;
3169  int v;
3170 
3171  assert(reopt != NULL);
3172  assert(set != NULL);
3173  assert(stat != NULL);
3174  assert(transprob != NULL);
3175  assert(origprob != NULL);
3176  assert(tree != NULL);
3177  assert(lp != NULL);
3178  assert(branchcand != NULL);
3179  assert(eventqueue != NULL);
3180  assert(cliquetable != NULL);
3181  assert(node != NULL);
3182  assert(vars != NULL);
3183  assert(vals != NULL);
3184  assert(nvars >= 0);
3185  assert(blkmem != NULL);
3186  assert(0 < id && id < reopt->reopttree->reoptnodessize);
3187 
3188 #ifndef NDEBUG
3189  {
3190  SCIP_REOPTTREE* reopttree;
3191  SCIP_REOPTNODE* reoptnode;
3192 
3193  reopttree = reopt->reopttree;
3194  assert(reopttree != NULL);
3195 
3196  reoptnode = reopttree->reoptnodes[id];
3197  assert(reoptnode != NULL);
3198  assert(reoptnode->dualfixing);
3199  }
3200 #endif
3201 
3202  nbndchgs = MIN(negbndchg, nvars);
3203 
3204  /* change the first negbndchg-1 bounds as stored in dualconscur and negate the negbndchg-th bound */
3205  for(v = 0; v < nbndchgs; v++)
3206  {
3207  var = vars[v];
3208  val = vals[v];
3209  boundtype = SCIPsetIsFeasEQ(set, val, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
3210 
3211  SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
3212  assert(SCIPvarIsTransformedOrigvar(var));
3213 
3214  /* negate the negbndchg-th bound */
3215  if( v == nbndchgs-1 )
3216  {
3217  val = 1-val;
3218  boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
3219  }
3220 
3221  if(boundtype == SCIP_BOUNDTYPE_LOWER
3222  && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
3223  && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)))
3224  {
3225  SCIPvarAdjustLb(var, set, &val);
3226  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3227  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
3228  }
3229  else if(boundtype == SCIP_BOUNDTYPE_UPPER
3230  && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
3231  && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)))
3232  {
3233  SCIPvarAdjustUb(var, set, &val);
3234  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3235  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
3236  }
3237  else if(boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER)
3238  {
3239  printf("** Unknown boundtype: %d **\n", boundtype);
3240  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3241  }
3242 #ifdef SCIP_MORE_DEBUG
3243  SCIPdebugMessage(" (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
3244 #endif
3245  }
3246 
3247  return SCIP_OKAY;
3248 }
3249 
3250 /** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
3251 static
3253  SCIP* scip, /**< SCIP data structure */
3254  SCIP_REOPT* reopt, /**< reoptimization data structure */
3255  SCIP_SET* set, /**< global SCIP settings */
3256  SCIP_STAT* stat, /**< dynamic problem statistics */
3257  BMS_BLKMEM* blkmem, /**< block memory */
3258  SCIP_NODE* node, /**< node of the branch and bound tree*/
3259  unsigned int id /**< id of stored node */
3260  )
3261 {
3262  int c;
3263  const char* name;
3264 
3265  assert(scip != NULL);
3266  assert(reopt != NULL);
3267  assert(reopt->reopttree != NULL);
3268  assert(set != NULL);
3269  assert(stat != NULL);
3270  assert(blkmem != NULL);
3271  assert(node != NULL);
3272  assert(0 < id && id < reopt->reopttree->reoptnodessize);
3273 
3274  if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
3275  return SCIP_OKAY;
3276 
3277  SCIPdebugMessage(" -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss, SCIPnodeGetNumber(node));
3278 
3279  for( c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; c++ )
3280  {
3281  SCIP_CONS* cons;
3282  LOGICORDATA* consdata;
3283  SCIP_VAR** consvars;
3284  SCIP_Real consval;
3285  SCIP_BOUNDTYPE consboundtype;
3286  int v;
3287 
3288  consdata = reopt->reopttree->reoptnodes[id]->conss[c];
3289  assert(consdata != NULL);
3290  assert(consdata->nvars > 0);
3291  assert(consdata->varssize >= consdata->nvars);
3292 
3293  /* allocate buffer */
3294  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nvars) );
3295 
3296  /* iterate over all variable and transform them */
3297  for(v = 0; v < consdata->nvars; v++)
3298  {
3299  consvars[v] = consdata->vars[v];
3300  consval= consdata->vals[v];
3301  consboundtype = SCIPsetIsFeasEQ(set, consval, 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER;
3302 
3303  assert(SCIPvarIsOriginal(consvars[v]));
3304  SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
3305  assert(SCIPvarIsTransformed(consvars[v]));
3306  assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3307 
3308  if( SCIPsetIsFeasEQ(set, consval, 1.0) )
3309  {
3310  SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
3311  assert(SCIPvarIsNegated(consvars[v]));
3312  }
3313  }
3314 
3315  assert(consdata->constype == REOPT_CONSTYPE_INFSUBTREE || consdata->constype == REOPT_CONSTYPE_STRBRANCHED);
3316 
3317  if( consdata->constype == REOPT_CONSTYPE_INFSUBTREE )
3318  name = "infsubtree";
3319  else
3320  name = "splitcons";
3321 
3322 
3323  /* create the constraints and add them to the corresponding nodes */
3324  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, consdata->nvars, consvars,
3326 
3327  SCIPdebugPrintCons(scip, cons, NULL);
3328 
3329  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
3330  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3331 
3332  /* free buffer */
3333  SCIPfreeBufferArray(scip, &consvars);
3334  }
3335 
3336  return SCIP_OKAY;
3337 }
3338 
3339 /** reset the internal statistics at the beginning of a new iteration */
3340 static
3342  SCIP_REOPT* reopt /**< reoptimization data structure */
3343  )
3344 {
3345  assert(reopt != NULL);
3346 
3347  reopt->lastbranched = -1;
3348  reopt->currentnode = -1;
3349  reopt->lastseennode = -1;
3350  reopt->reopttree->nfeasnodes = 0;
3351  reopt->reopttree->ninfnodes = 0;
3352  reopt->reopttree->nprunednodes = 0;
3353  reopt->reopttree->ncutoffreoptnodes = 0;
3354 
3355  return;
3356 }
3357 
3358 /** check the stored bound changes of all child nodes for redundancy and infeasibility.
3359  *
3360  * due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
3361  * child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
3362  * method we remove all redundant bound changes and delete infeasible child nodes.
3363  */
3364 static
3366  SCIP_REOPT* reopt, /**< reoptimization data structure */
3367  SCIP_SET* set, /**< global SCIP settings */
3368  BMS_BLKMEM* blkmem, /**< block memory */
3369  SCIP_Bool* runagain, /**< pointer to store of this method should run again */
3370  unsigned int id /**< id of stored node */
3371  )
3372 {
3373  SCIP_REOPTNODE* reoptnode;
3374  unsigned int* cutoffchilds;
3375  int ncutoffchilds;
3376  unsigned int* redchilds;
3377  int nredchilds;
3378  int c;
3379 
3380  assert(reopt != NULL);
3381  assert(reopt->reopttree != NULL);
3382  assert(id < reopt->reopttree->reoptnodessize);
3383  assert(reopt->reopttree->reoptnodes != NULL);
3384  assert(reopt->reopttree->reoptnodes[id] != NULL);
3385 
3386  reoptnode = reopt->reopttree->reoptnodes[id];
3387 
3388  *runagain = FALSE;
3389  ncutoffchilds = 0;
3390  nredchilds = 0;
3391 
3392  SCIPdebugMessage("start dry branching of node at ID %u\n", id);
3393 
3394  /* allocate buffer arrays */
3395  SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
3396  SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
3397 
3398  /* iterate over all child nodes and check each bound changes
3399  * for redundancy and conflict */
3400  for( c = 0; c < reoptnode->nchilds; c++ )
3401  {
3402  SCIP_REOPTNODE* child;
3403  SCIP_Bool cutoff;
3404  SCIP_Bool redundant;
3405  int* redundantvars;
3406  int nredundantvars;
3407  int v;
3408  unsigned int childid;
3409 
3410  cutoff = FALSE;
3411  redundant = FALSE;
3412  nredundantvars = 0;
3413 
3414  childid = reoptnode->childids[c];
3415  assert(childid < reopt->reopttree->reoptnodessize);
3416  child = reopt->reopttree->reoptnodes[childid];
3417  assert(child != NULL);
3418 #ifdef SCIP_MORE_DEBUG
3419  SCIPdebugMessage("-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
3420 #endif
3421  if( child->nvars > 0 )
3422  {
3423  /* allocate buffer memory to store the redundant variables */
3424  SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
3425 
3426  for(v = 0; v < child->nvars && !cutoff; v++)
3427  {
3428  SCIP_VAR* transvar;
3429  SCIP_Real transval;
3430  SCIP_BOUNDTYPE transbndtype;
3431  SCIP_Real ub;
3432  SCIP_Real lb;
3433 
3434  transvar = child->vars[v];
3435  transval = child->varbounds[v];
3436  transbndtype = child->varboundtypes[v];
3437 
3438  /* transform into the transformed space */
3439  SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
3440 
3441  lb = SCIPvarGetLbLocal(transvar);
3442  ub = SCIPvarGetUbLocal(transvar);
3443 
3444  /* check for infeasibility */
3445  if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
3446  {
3447  SCIPdebugMessage(" -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
3448  SCIPvarGetName(transvar), lb, transval);
3449 
3450  cutoff = TRUE;
3451  break;
3452  }
3453 
3454  /* check for redundancy */
3455  if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
3456  {
3457  SCIPdebugMessage(" -> <%s> is already fixed to %g -> redundant bound change\n",
3458  SCIPvarGetName(transvar), lb);
3459 
3460  redundantvars[nredundantvars] = v;
3461  ++nredundantvars;
3462  }
3463  }
3464 
3465  if( !cutoff && nredundantvars > 0 )
3466  {
3467  for(v = 0; v < nredundantvars; v++)
3468  {
3469  /* replace the redundant variable by the last stored variable */
3470  child->vars[redundantvars[v]] = child->vars[child->nvars-1];
3471  child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
3472  child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
3473  --child->nvars;
3474  }
3475  }
3476 
3477  /* free buffer memory */
3478  SCIPsetFreeBufferArray(set, &redundantvars);
3479  }
3480  else if( child->nconss == 0 )
3481  {
3482  redundant = TRUE;
3483  SCIPdebugMessage(" -> redundant node found.\n");
3484  }
3485 
3486  if( cutoff )
3487  {
3488  cutoffchilds[ncutoffchilds] = childid;
3489  ++ncutoffchilds;
3490  }
3491  else if( redundant )
3492  {
3493  redchilds[nredchilds] = childid;
3494  ++nredchilds;
3495  }
3496  }
3497 
3498  SCIPdebugMessage("-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
3499 
3500  c = 0;
3501 
3502  /* delete all nodes that can be cut off */
3503  while( ncutoffchilds > 0 )
3504  {
3505  /* delete the node and the induced subtree */
3506  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
3507 
3508  /* find the position in the childid array */
3509  c = 0;
3510  while( reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] && c < reoptnode->nchilds )
3511  ++c;
3512  assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
3513 
3514  /* replace the ID at position c by the last ID */
3515  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
3516  --reoptnode->nchilds;
3517 
3518  /* decrease the number of nodes to cutoff */
3519  --ncutoffchilds;
3520  }
3521 
3522  c = 0;
3523 
3524  /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
3525  while( nredchilds > 0 )
3526  {
3527  /* find the position in the childid array */
3528  c = 0;
3529  while( reoptnode->childids[c] != redchilds[nredchilds-1] && c < reoptnode->nchilds )
3530  ++c;
3531  assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
3532 
3533  /* the node is a leaf and we can cutoff them */
3534  if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
3535  {
3536  /* delete the node and the induced subtree */
3537  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
3538 
3539  /* replace the ID at position c by the last ID */
3540  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
3541  --reoptnode->nchilds;
3542 
3543  /* decrease the number of redundant nodes */
3544  --nredchilds;
3545  }
3546  else
3547  {
3548  int cc;
3549  int ncc;
3550 
3551  /* replace the ID at position c by the last ID */
3552  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
3553  --reoptnode->nchilds;
3554 
3555  ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
3556 
3557  /* check the memory */
3558  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], blkmem, 0, reoptnode->nchilds+ncc, 0) );
3559 
3560  /* add all IDs of child nodes to the current node */
3561  for(cc = 0; cc < ncc; cc++)
3562  {
3563  reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
3564  ++reoptnode->nchilds;
3565  }
3566 
3567  /* delete the redundant node */
3568  SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
3569 
3570  /* decrease the number of redundant nodes */
3571  --nredchilds;
3572 
3573  /* update the flag to rerun this method */
3574  *runagain = TRUE;
3575  }
3576  }
3577 
3578  /* free buffer arrays */
3579  SCIPsetFreeBufferArray(set, &cutoffchilds);
3580  SCIPsetFreeBufferArray(set, &redchilds);
3581 
3582  return SCIP_OKAY;
3583 }
3584 
3585 /** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
3586 static
3588  SCIP_REOPTTREE* reopttree, /**< reopttree */
3589  unsigned int id /**< id of stored node */
3590  )
3591 {
3592  int nnodes;
3593  int i;
3594 
3595  assert(reopttree != NULL);
3596  assert(id < reopttree->reoptnodessize);
3597 
3598  nnodes = 0;
3599 
3600  for(i = 0; i < reopttree->reoptnodes[id]->nchilds; i++)
3601  {
3602  nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
3603  }
3604 
3605  return nnodes + 1;
3606 }
3607 
3608 /** returns the number of leaf nodes of the induced subtree */
3609 static
3611  SCIP_REOPT* reopt, /**< reoptimization data structure */
3612  unsigned int id /**< id of stored node */
3613  )
3614 {
3615  int i;
3616  int nleaves;
3617 
3618  assert(reopt != NULL);
3619  assert(id < reopt->reopttree->reoptnodessize);
3620  assert(reopt->reopttree->reoptnodes[id] != NULL);
3621 
3622  nleaves = 0;
3623 
3624  /* iterate over all child nods and check whether they are leaves or not */
3625  for(i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++)
3626  {
3627  unsigned int childid;
3628 
3629  childid = reopt->reopttree->reoptnodes[id]->childids[i];
3630  assert(childid < reopt->reopttree->reoptnodessize);
3631 
3632  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
3633  ++nleaves;
3634  else
3635  nleaves += reoptGetNLeaves(reopt, childid);
3636  }
3637 
3638  return nleaves;
3639 }
3640 
3641 /** returns all leaves of the subtree induced by the node stored at @p id*/
3642 static
3644  SCIP_REOPT* reopt, /**< reoptimization data structure*/
3645  unsigned int id, /**< id of stored node */
3646  unsigned int* leaves, /**< array of leave nodes */
3647  int leavessize, /**< size of leaves array */
3648  int* nleaves /**< pointer to store the number of leave nodes */
3649  )
3650 {
3651  int i;
3652  int l;
3653 
3654  assert(reopt != NULL);
3655  assert(leavessize > 0 && leaves != NULL);
3656  assert((*nleaves) >= 0);
3657  assert(id < reopt->reopttree->reoptnodessize);
3658  assert(reopt->reopttree->reoptnodes[id] != NULL);
3659 
3660  for(i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++)
3661  {
3662  unsigned int childid;
3663 
3664  assert(*nleaves <= leavessize);
3665 
3666  childid = reopt->reopttree->reoptnodes[id]->childids[i];
3667  assert(childid < reopt->reopttree->reoptnodessize);
3668 
3669  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
3670  {
3671  leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
3672  ++l;
3673  ++(*nleaves);
3674  }
3675  else
3676  {
3677  int nleaves2;
3678 
3679  nleaves2 = 0;
3680  SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
3681  l += nleaves2;
3682  (*nleaves) += nleaves2;
3683  }
3684  }
3685 
3686  return SCIP_OKAY;
3687 }
3688 
3689 /** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
3690 static
3692  SCIP_REOPT* reopt, /**< reoptimization data structure */
3693  SCIP_SET* set, /**< global SCIP settings */
3694  BMS_BLKMEM* blkmem, /**< block memory */
3695  SCIP_Bool softreset /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
3696  )
3697 {
3698  assert(reopt != NULL);
3699  assert(set != NULL);
3700  assert(blkmem != NULL);
3701 
3702  /* clear the tree */
3703  SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
3704  assert(reopt->reopttree->nreoptnodes == 0);
3705 
3706  /* reset the dual constraint */
3707  if( reopt->dualcons != NULL )
3708  reopt->dualcons->nvars = 0;
3709 
3710  reopt->currentnode = -1;
3711 
3712  return SCIP_OKAY;
3713 }
3714 
3715 /** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
3716 static
3718  SCIP_REOPT* reopt, /**< reoptimization data structure */
3719  SCIP_SET* set, /**< global SCIP settings */
3720  BMS_BLKMEM* blkmem /**< block memory */
3721  )
3722 {
3723  assert(reopt != NULL);
3724  assert(reopt->reopttree != NULL);
3725  assert(set != NULL);
3726  assert(blkmem != NULL);
3727 
3728  /* clear the tree */
3729  SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
3730  assert(reopt->reopttree->nreoptnodes == 0);
3731 
3732  /* allocate memory for the root node */
3733  SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
3734 
3735  reopt->nglbrestarts += 1;
3736 
3737  if( reopt->firstrestart == -1 )
3738  reopt->firstrestart = reopt->run;
3739 
3740  reopt->lastrestart = reopt->run;
3741 
3742  return SCIP_OKAY;
3743 }
3744 
3745 /** save the new objective function */
3746 static
3748  SCIP_REOPT* reopt, /**< reoptimization data */
3749  SCIP_SET* set, /**< global SCIP settings */
3750  BMS_BLKMEM* blkmem, /**< block memory */
3751  SCIP_VAR** transvars, /**< transformed problem variables */
3752  int ntransvars /**< number of transformed problem variables */
3753  )
3754 {
3755  SCIP_Real norm;
3756  int v;
3757  int idx;
3758 
3759  assert(reopt != NULL);
3760 
3761  /* check memory */
3762  SCIP_CALL( ensureRunSize(reopt, reopt->run, blkmem) );
3763 
3764  norm = 0;
3765 
3766  /* get memory */
3767  SCIP_ALLOC( BMSallocMemoryArray(&reopt->objs[reopt->run-1], ntransvars) ); /*lint !e866*/
3768 
3769  /* save coefficients */
3770  for( v = 0; v < ntransvars; v++ )
3771  {
3772  SCIP_Real glblb;
3773  SCIP_Real glbub;
3774 
3775  assert(SCIPvarIsActive(transvars[v]));
3776  assert(!SCIPvarIsOriginal(transvars[v]));
3777 
3778  idx = SCIPvarGetProbindex(transvars[v]);
3779  assert(idx < ntransvars);
3780  assert(0 <= idx);
3781 
3782  reopt->objs[reopt->run-1][idx] = SCIPvarGetObj(transvars[v]);
3783 
3784  /* we skip global fixed variables */
3785  glblb = SCIPvarGetLbGlobal(transvars[v]);
3786  glbub = SCIPvarGetUbGlobal(transvars[v]);
3787 
3788  if( SCIPsetIsFeasLT(set, glblb, glbub) )
3789  norm += SQR(reopt->objs[reopt->run-1][idx]);
3790 
3791  /* mark this objective as the first non empty */
3792  if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][idx] != 0 )
3793  reopt->firstobj = reopt->run-1;
3794  }
3795  assert(norm >= 0);
3796  norm = SQRT(norm);
3797 
3798  /* normalize the coefficients */
3799  for(idx = 0; idx < ntransvars && norm > 0; idx++)
3800  reopt->objs[reopt->run-1][idx] /= norm;
3801 
3802  /* calculate similarity to last objective */
3803  if( reopt->run-1 > 1 )
3804  {
3805  /* calculate similarity to first objective */
3806  if( reopt->run-1 > 1 && reopt->firstobj < reopt->run-1 && reopt->firstobj >= 0 )
3807  reopt->simtofirstobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->firstobj, transvars, ntransvars);
3808 
3809  /* calculate similarity to last objective */
3810  reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, transvars, ntransvars);
3811 
3812  SCIPdebugMessage("new objective has similarity of %g/%g compared to first/previous.\n", reopt->simtofirstobj,
3813  reopt->simtolastobj);
3814  printf("new objective has similarity of %g/%g compared to first/previous.\n", reopt->simtofirstobj,
3815  reopt->simtolastobj);
3816  }
3817 
3818  SCIPdebugMessage("saved obj for run %d.\n", reopt->run);
3819 
3820  return SCIP_OKAY;
3821 }
3822 
3823 /** permute the variable and bound array randomly */
3824 static
3826  SCIP_VAR** vars, /**< variable array to permute */
3827  SCIP_Real* vals, /**< bound array to permute in the same order */
3828  int nvars, /**< number of variables */
3829  unsigned int* randseed /**< seed value for the random generator */
3830  )
3831 {
3832  SCIP_VAR* tmpvar;
3833  SCIP_Real tmpval;
3834  int end;
3835  int i;
3836 
3837  end = nvars;
3838 
3839  /* loop backwards through all variables (and bounds) and always swap the current last element to a random position */
3840  while( end > 1 )
3841  {
3842  --end;
3843 
3844  /* get a random position into which the last variable should be shuffled */
3845  i = SCIPgetRandomInt(0, end, randseed);
3846 
3847  /* swap the last variable and the random variable */
3848  tmpvar = vars[i];
3849  vars[i] = vars[end];
3850  vars[end] = tmpvar;
3851 
3852  /* swap the last variable and the random variable */
3853  tmpval = vals[i];
3854  vals[i] = vals[end];
3855  vals[end] = tmpval;
3856  }
3857 }
3858 
3859 /*
3860  * public methods
3861  */
3862 
3863 /* ---------------- methods of general reoptimization ---------------- */
3864 
3865 /* In debug mode, the following methods are implemented as function calls to ensure
3866  * type validity.
3867  * In optimized mode, the methods are implemented as defines to improve performance.
3868  * However, we want to have them in the library anyways, so we have to undef the defines.
3869  */
3870 
3871 #undef SCIPreoptGetNRestartsGlobal
3872 #undef SCIPreoptGetNRestartsLocal
3873 #undef SCIPreoptGetNTotalRestartsLocal
3874 #undef SCIPreoptGetFirstRestarts
3875 #undef SCIPreoptGetLastRestarts
3876 #undef SCIPreoptGetNFeasNodes
3877 #undef SCIPreoptGetNTotalFeasNodes
3878 #undef SCIPreoptGetNPrunedNodes
3879 #undef SCIPreoptGetNTotalPrunedNodes
3880 #undef SCIPreoptGetNCutoffReoptnodes
3881 #undef SCIPreoptGetNTotalCutoffReoptnodes
3882 #undef SCIPreoptGetNInfNodes
3883 #undef SCIPreoptGetNTotalInfNodes
3884 #undef SCIPreoptGetNInfSubtrees
3885 
3886 
3887 /** returns the number of global restarts */
3889  SCIP_REOPT* reopt /**< reoptimization data structure */
3890  )
3891 {
3892  assert(reopt != NULL);
3893 
3894  return reopt->nglbrestarts;
3895 }
3896 
3897 /** returns the number of local restarts in the current run */
3899  SCIP_REOPT* reopt /**< reoptimization data structure */
3900  )
3901 {
3902  assert(reopt != NULL);
3903 
3904  return reopt->nlocrestarts;
3905 }
3906 
3907 /** returns the number of local restarts over all runs */
3909  SCIP_REOPT* reopt /**< reoptimization data structure */
3910  )
3911 {
3912  assert(reopt != NULL);
3913 
3914  return reopt->ntotallocrestarts;
3915 }
3916 
3917 /** returns the number of iteration with the first global restarts */
3919  SCIP_REOPT* reopt /**< reoptimization data structure */
3920  )
3921 {
3922  assert(reopt != NULL);
3923 
3924  return reopt->firstrestart;
3925 }
3926 
3927 /** returns the number of iteration with the last global restarts */
3929  SCIP_REOPT* reopt /**< reoptimization data structure */
3930  )
3931 {
3932  assert(reopt != NULL);
3933 
3934  return reopt->lastrestart;
3935 }
3936 
3937 /** returns the number of stored nodes providing an improving feasible LP solution in the current run */
3939  SCIP_REOPT* reopt /**< reoptimization data structure */
3940  )
3941 {
3942  assert(reopt != NULL);
3943 
3944  return reopt->reopttree->nfeasnodes;
3945 }
3946 
3947 /** returns the number of stored nodes providing an improving feasible LP solution over all runs */
3949  SCIP_REOPT* reopt /**< reoptimization data structure */
3950  )
3951 {
3952  assert(reopt != NULL);
3953 
3954  return reopt->reopttree->ntotalfeasnodes;
3955 }
3956 
3957 /** returns the number of stored nodes that exceeded the cutoff bound in the current run */
3959  SCIP_REOPT* reopt /**< reoptimization data structure */
3960  )
3961 {
3962  assert(reopt != NULL);
3963 
3964  return reopt->reopttree->nprunednodes;
3965 }
3966 
3967 /** returns the number of stored nodes that exceeded the cutoff bound over all runs */
3969  SCIP_REOPT* reopt /**< reoptimization data structure */
3970  )
3971 {
3972  assert(reopt != NULL);
3973 
3974  return reopt->reopttree->ntotalprunednodes;
3975 }
3976 
3977 /** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
3979  SCIP_REOPT* reopt /**< reoptimization data structure */
3980  )
3981 {
3982  assert(reopt != NULL);
3983 
3984  return reopt->reopttree->ncutoffreoptnodes;
3985 }
3986 
3987 /** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
3989  SCIP_REOPT* reopt /**< reoptimization data structure */
3990  )
3991 {
3992  assert(reopt != NULL);
3993 
3994  return reopt->reopttree->ntotalcutoffreoptnodes;
3995 }
3996 
3997 /** returns the number of stored nodes with an infeasible LP in the current run */
3999  SCIP_REOPT* reopt /**< reoptimization data structure */
4000  )
4001 {
4002  assert(reopt != NULL);
4003 
4004  return reopt->reopttree->ninfnodes;
4005 }
4006 
4007 /** returns the number of stored nodes with an infeasible LP over all runs */
4009  SCIP_REOPT* reopt /**< reoptimization data structure */
4010  )
4011 {
4012  assert(reopt != NULL);
4013 
4014  return reopt->reopttree->ntotalinfnodes;
4015 }
4016 
4017 /** returns the number of found infeasible subtrees */
4019  SCIP_REOPT* reopt /**< reoptimization data structure */
4020  )
4021 {
4022  assert(reopt != NULL);
4023 
4024  return reopt->reopttree->ninfsubtrees;
4025 }
4026 
4027 
4028 /** constructor for the reoptimization data */
4030  SCIP_REOPT** reopt, /**< pointer to reoptimization data structure */
4031  SCIP_SET* set, /**< global SCIP settings */
4032  BMS_BLKMEM* blkmem /**< block memory */
4033  )
4034 {
4035  SCIP_EVENTHDLR* eventhdlr;
4036  int i;
4037 
4038  assert(reopt != NULL);
4039 
4040  SCIP_ALLOC( BMSallocMemory(reopt) );
4041  (*reopt)->runsize = DEFAULT_MEM_RUN;
4042  (*reopt)->run = 0;
4043  (*reopt)->simtolastobj = -2.0;
4044  (*reopt)->simtofirstobj = -2.0;
4045  (*reopt)->firstobj = -1;
4046  (*reopt)->currentnode = -1;
4047  (*reopt)->lastbranched = -1;
4048  (*reopt)->dualcons = NULL;
4049  (*reopt)->glbconss = NULL;
4050  (*reopt)->nglbconss = 0;
4051  (*reopt)->allocmemglbconss = 0;
4052  (*reopt)->ncheckedsols = 0;
4053  (*reopt)->nimprovingsols = 0;
4054  (*reopt)->noptsolsbyreoptsol = 0;
4055  (*reopt)->nglbrestarts = 0;
4056  (*reopt)->nlocrestarts = 0;
4057  (*reopt)->ntotallocrestarts = 0;
4058  (*reopt)->firstrestart = 0;
4059  (*reopt)->lastrestart = 0;
4060 
4061  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
4062  SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
4063 
4064  for(i = 0; i < (*reopt)->runsize; i++)
4065  {
4066  (*reopt)->objs[i] = NULL;
4067  (*reopt)->prevbestsols[i] = NULL;
4068  }
4069 
4070  /* clocks */
4071  SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
4072 
4073  /* create and initialize SCIP_SOLTREE */
4074  SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
4075  SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
4076 
4077  /* create and initialize SCIP_REOPTTREE */
4078  SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
4079  SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
4080 
4081  /* create event handler for node events */
4082  eventhdlr = NULL;
4083 
4084  /* include event handler into SCIP */
4085  SCIP_CALL( SCIPeventhdlrCreate(&eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, NULL, NULL, NULL, NULL, eventInitsolReopt,
4086  eventExitsolReopt, NULL, eventExecReopt, NULL) );
4087  SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
4088  assert(eventhdlr != NULL);
4089 
4090  return SCIP_OKAY;
4091 }
4092 
4093 /** frees reoptimization data */
4095  SCIP_REOPT** reopt, /**< reoptimization data structure */
4096  SCIP_SET* set, /**< global SCIP settings */
4097  SCIP_PRIMAL* origprimal, /**< original primal */
4098  BMS_BLKMEM* blkmem /**< block memory */
4099  )
4100 {
4101  int p;
4102 
4103  assert(reopt != NULL);
4104  assert(*reopt != NULL);
4105  assert(set != NULL);
4106  assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
4107  assert(blkmem != NULL);
4108 
4109  /* free reopttree */
4110  SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
4111 
4112  /* free solutions */
4113  if( set->stage >= SCIP_STAGE_PROBLEM )
4114  {
4115  for( p = (*reopt)->run-1; p >= 0; p-- )
4116  {
4117  if( (*reopt)->soltree->sols[p] != NULL )
4118  {
4119  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
4120  (*reopt)->soltree->sols[p] = NULL;
4121  }
4122 
4123  if( (*reopt)->objs[p] != NULL )
4124  {
4125  BMSfreeMemoryArray(&(*reopt)->objs[p]);
4126  }
4127  }
4128  }
4129 
4130  /* free solution tree */
4131  SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
4132 
4133  if( (*reopt)->dualcons != NULL )
4134  {
4135  if( (*reopt)->dualcons->varssize > 0 )
4136  {
4137  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualcons->vals, (*reopt)->dualcons->varssize);
4138  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualcons->vars, (*reopt)->dualcons->varssize);
4139  BMSfreeBlockMemory(blkmem, &(*reopt)->dualcons);
4140  (*reopt)->dualcons = NULL;
4141  }
4142  }
4143 
4144  if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
4145  {
4146  --(*reopt)->nglbconss;
4147 
4148  /* free all constraint */
4149  while( (*reopt)->nglbconss > 0 )
4150  {
4151  int c;
4152  c = (*reopt)->nglbconss;
4153 
4154  if( (*reopt)->glbconss[c] != NULL )
4155  {
4156  if( (*reopt)->glbconss[c]->varssize > 0 )
4157  {
4158  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
4159  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
4160  (*reopt)->glbconss[c]->varssize = 0;
4161  }
4162  BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
4163  }
4164 
4165  --(*reopt)->nglbconss;
4166  }
4167  assert((*reopt)->nglbconss == 0);
4168 
4169  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
4170  (*reopt)->allocmemglbconss = 0;
4171  }
4172 
4173  /* clocks */
4174  SCIPclockFree(&(*reopt)->savingtime);
4175 
4176  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
4177  BMSfreeMemoryArray(&(*reopt)->objs);
4178  BMSfreeMemory(reopt);
4179 
4180  return SCIP_OKAY;
4181 }
4182 
4183 /** returns the number of constraints added by the reoptimization plug-in */
4185  SCIP_REOPT* reopt, /**< reoptimization data structure */
4186  SCIP_NODE* node /**< node of the search tree */
4187  )
4188 {
4189  unsigned int id;
4190 
4191  assert(reopt != NULL);
4192  assert(node != NULL);
4193 
4194  id = SCIPnodeGetReoptID(node);
4195  assert(id < reopt->reopttree->reoptnodessize);
4196 
4197  /* set the id to -1 if the node is not part of the reoptimization tree */
4198  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
4199  return SCIPnodeGetNAddedConss(node);
4200 
4201  if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
4202  return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
4203  else
4204  return SCIPnodeGetNAddedConss(node);
4205 }
4206 
4207 /** add a solution to the solution tree */
4209  SCIP_REOPT* reopt, /**< reoptimization data */
4210  SCIP_SET* set, /**< global SCIP settings */
4211  SCIP_STAT* stat, /**< dynamic problem statistics */
4212  SCIP_PRIMAL* origprimal, /**< original primal */
4213  BMS_BLKMEM* blkmem, /**< block memory */
4214  SCIP_SOL* sol, /**< solution to add */
4215  SCIP_Bool bestsol, /**< is the current solution an optimal solution? */
4216  SCIP_Bool* added, /**< pointer to store the information if the soltion was added */
4217  SCIP_VAR** vars, /**< variable array */
4218  int nvars, /**< number of variables */
4219  int run /**< number of the current run (1,2,...) */
4220  )
4221 {
4222  SCIP_SOLNODE* solnode;
4223  SCIP_HEUR* heur;
4224  int insertpos;
4225 
4226  assert(reopt != NULL);
4227  assert(set != NULL);
4228  assert(sol != NULL);
4229  assert(run > 0);
4230 
4231  assert(reopt->soltree->sols[run-1] != NULL);
4232 
4233  /* if the solution was found by reoptsols the solutions is already stored */
4234  heur = SCIPsolGetHeur(sol);
4235  if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
4236  ++reopt->noptsolsbyreoptsol;
4237  else if( bestsol )
4238  reopt->noptsolsbyreoptsol = 0;
4239 
4240  /* check memory */
4241  SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1], run-1) );
4242 
4243  solnode = NULL;
4244 
4245  /* add solution to solution tree */
4246  SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
4247 
4248  if( (*added) )
4249  {
4250  assert(solnode != NULL);
4251 
4252  /* add solution */
4253  insertpos = reopt->soltree->nsols[run-1];
4254  reopt->soltree->sols[run-1][insertpos] = solnode;
4255  ++reopt->soltree->nsols[run-1];
4256  assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
4257  }
4258 
4259  return SCIP_OKAY;
4260 }
4261 
4262 /** we want to store the optimal solution of each run in a separate array */
4264  SCIP_REOPT* reopt, /**< reoptimization data structure */
4265  SCIP_SOL* sol, /**< solution to add */
4266  BMS_BLKMEM* blkmem, /**< block memory */
4267  SCIP_SET* set, /**< global SCIP settings */
4268  SCIP_STAT* stat, /**< dynamic problem statistics */
4269  SCIP_PRIMAL* origprimal /**< original primal */
4270  )
4271 {
4272  SCIP_SOL* solcopy;
4273 
4274  assert(reopt != NULL);
4275  assert(reopt->run-1 >= 0);
4276  assert(sol != NULL);
4277  assert(blkmem != NULL);
4278  assert(set != NULL);
4279  assert(stat != NULL);
4280  assert(origprimal != NULL);
4281 
4282  SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
4283  reopt->prevbestsols[reopt->run-1] = solcopy;
4284 
4285  return SCIP_OKAY;
4286 }
4287 
4288 /** add a new iteration after changing the objective function */
4290  SCIP_REOPT* reopt, /**< reoptimization data sturcture */
4291  SCIP_SET* set, /**< global SCIP settings */
4292  BMS_BLKMEM* blkmem, /**< block memory */
4293  SCIP_VAR** transvars, /**< transformed variables */
4294  int ntransvars, /**< number of transformed variables */
4295  int size /**< number of expected solutions */
4296  )
4297 {
4298  assert(reopt != NULL);
4299  assert(set != NULL);
4300  assert(blkmem != NULL);
4301  assert(transvars != NULL);
4302 
4303  /* increase number of runs */
4304  ++reopt->run;
4305 
4306  /* check memory */
4307  SCIP_CALL( ensureRunSize(reopt, reopt->run, blkmem) );
4308 
4309  /* allocate memory */
4310  reopt->soltree->solssize[reopt->run-1] = size;
4311  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
4312  /* save the objective function */
4313  SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, transvars, ntransvars) );
4314 
4315  resetStats(reopt);
4316 
4317  return SCIP_OKAY;
4318 }
4319 
4320 /** get the number of checked during the reoptimization process */
4322  SCIP_REOPT* reopt /**< reoptimization data structure */
4323  )
4324 {
4325  assert(reopt != NULL);
4326 
4327  return reopt->ncheckedsols;
4328 }
4329 
4330 /** update the number of checked during the reoptimization process */
4332  SCIP_REOPT* reopt, /**< reoptimization data structure */
4333  int ncheckedsols /**< number of updated solutions */
4334  )
4335 {
4336  assert(reopt != NULL);
4337 
4338  reopt->ncheckedsols += ncheckedsols;
4339 }
4340 
4341 /** get the number of checked during the reoptimization process */
4343  SCIP_REOPT* reopt /**< reoptimization data structure */
4344  )
4345 {
4346  assert(reopt != NULL);
4347 
4348  return reopt->nimprovingsols;
4349 }
4350 
4351 /** update the number of checked during the reoptimization process */
4353  SCIP_REOPT* reopt, /**< reoptimization data structure */
4354  int nimprovingsols /**< number of improving solutions */
4355  )
4356 {
4357  assert(reopt != NULL);
4358 
4359  reopt->nimprovingsols += nimprovingsols;
4360 }
4361 
4362 /** returns number of solution of a given run */
4364  SCIP_REOPT* reopt, /**< reoptimization data structure */
4365  int run /**< number of the run (1,2,..) */
4366  )
4367 {
4368  assert(reopt != NULL);
4369  assert(0 < run && run <= reopt->runsize);
4370 
4371  if( reopt->soltree->sols[run-1] == NULL )
4372  return 0;
4373  else
4374  return reopt->soltree->nsols[run-1];
4375 }
4376 
4377 /** returns number of all solutions of all runs */
4379  SCIP_REOPT* reopt /**< reoptimization data structure */
4380  )
4381 {
4382  int nsols;
4383  int r;
4384 
4385  assert(reopt != NULL);
4386 
4387  nsols = 0;
4388 
4389  for( r = 0; r < reopt->run; r++)
4390  nsols += reopt->soltree->nsols[r];
4391 
4392  return nsols;
4393 }
4394 
4395 /** return the stored solutions of a given run */
4397  SCIP_REOPT* reopt, /**< reoptimization data structure */
4398  int run, /**< number of the run (1,2,...) */
4399  SCIP_SOL** sols, /**< array of solutions to fill */
4400  int solssize, /**< length of the array */
4401  int* nsols /**< pointer to store the number of added solutions */
4402  )
4403 {
4404  int s;
4405 
4406  assert(reopt != NULL);
4407  assert(run > 0 && run <= reopt->run);
4408  assert(sols != NULL);
4409 
4410  assert(solssize > 0);
4411  *nsols = 0;
4412 
4413  for( s = 0; s < reopt->soltree->nsols[run-1]; s++ )
4414  {
4415  if( !reopt->soltree->sols[run-1][s]->updated )
4416  ++(*nsols);
4417  }
4418 
4419  if( solssize < (*nsols) )
4420  return SCIP_OKAY;
4421 
4422  (*nsols) = 0;
4423  for( s = 0; s < reopt->soltree->nsols[run-1]; s++ )
4424  {
4425  if( !reopt->soltree->sols[run-1][s]->updated )
4426  {
4427  sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
4428  reopt->soltree->sols[run-1][s]->updated = TRUE;
4429  ++(*nsols);
4430  }
4431  }
4432 
4433  return SCIP_OKAY;
4434 }
4435 
4436 /** returns the number of saved solutions overall runs */
4438  SCIP_REOPT* reopt /**< reoptimization data structure */
4439  )
4440 {
4441  int nsavedsols;
4442 
4443  assert(reopt != NULL);
4444  assert(reopt->soltree->root != NULL);
4445 
4446  nsavedsols = 0;
4447 
4448  if( reopt->soltree->root->lchild != NULL
4449  || reopt->soltree->root->rchild != NULL)
4450  nsavedsols = soltreeNInducedSols(reopt->soltree->root);
4451 
4452  return nsavedsols;
4453 }
4454 
4455 /** check if the reoptimization process should be (locally) restarted.
4456  *
4457  * first, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
4458  * the similarity again. we trigger a restart if
4459  * 1. the objective function has changed too much
4460  * 2. the number of stored nodes is exceeded
4461  * 3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
4462  * prove the optimality and this can be probably faster by solving from scratch)
4463  *
4464  * if the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
4465  * that are already fixed by bounding.
4466  */
4468  SCIP_REOPT* reopt, /**< reoptimization data structure */
4469  SCIP_SET* set, /**< global SCIP settings */
4470  BMS_BLKMEM* blkmem, /**< block memory */
4471  SCIP_NODE* node, /**< current node of the branch and bound tree (or NULL) */
4472  SCIP_VAR** transvars, /**< transformed problem variables */
4473  int ntransvars, /**< number of transformed problem variables */
4474  SCIP_Bool* restart /**< pointer to store if the reoptimization process should be restarted */
4475  )
4476 {
4477  SCIP_Real sim;
4478 
4479  assert(reopt != NULL);
4480  assert(set != NULL);
4481  assert(blkmem != NULL);
4482  assert(transvars != NULL);
4483  assert(ntransvars >= 0);
4484 
4485  sim = 1.0;
4486  *restart = FALSE;
4487 
4488  /* check if the whole reoptimization process should start from scratch */
4489  if( node == NULL )
4490  {
4491  if( reopt->run > 0 && set->reopt_objsimdelay > -1.0 )
4492  {
4493  sim = reopt->simtolastobj;
4494  }
4495 
4496  /* check similarity */
4497  if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
4498  {
4499  SCIPdebugMessage("-> restart reoptimization (objective functions are not similar enough)\n");
4500  *restart = TRUE;
4501  }
4502  /* check size of the reoptimization tree */
4503  else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
4504  {
4505  SCIPdebugMessage("-> restart reoptimization (node limit reached)\n");
4506  *restart = TRUE;
4507  }
4508  /* check if the tree was only needed to prove optimality */
4509  else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
4510  {
4511  SCIPdebugMessage("-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
4512  reopt->noptsolsbyreoptsol);
4513  reopt->noptsolsbyreoptsol = 0;
4514  *restart = TRUE;
4515  }
4516 
4517  if( *restart )
4518  {
4519  /* trigger a restart */
4520  SCIP_CALL( reoptRestart(reopt, set, blkmem) );
4521  }
4522  }
4523  /* check for a local restart, ie, start the solving process of an inner node from scatch */
4524  else
4525  {
4526  SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
4527  }
4528  return SCIP_OKAY;
4529 }
4530 
4531 /** returns the similarity to the previous objective function, if no exist return -2.0 */
4533  SCIP_REOPT* reopt /**< reoptimization data structure */
4534  )
4535 {
4536  assert(reopt != NULL);
4537  return reopt->simtolastobj;
4538 }
4539 
4540 /**returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
4542  SCIP_REOPT* reopt /**< reoptimization data structure */
4543  )
4544 {
4545  assert(reopt != NULL);
4546  return reopt->simtofirstobj;
4547 }
4548 
4549 /** return the similarity between two of objective functions of two given runs */
4551  SCIP_REOPT* reopt, /**< reoptimization data structure */
4552  SCIP_SET* set, /**< global SCIP settings */
4553  int run1, /**< number of the first run */
4554  int run2, /**< number of the second run */
4555  SCIP_VAR** transvars, /**< original problem variables */
4556  int ntransvars /**< number of original problem variables */
4557  )
4558 {
4559  assert(reopt != NULL);
4560  assert(run1 > 0 && run1 <= reopt->run);
4561  assert(run2 > 0 && run2 <= reopt->run);
4562  assert(transvars != NULL);
4563  assert(ntransvars >= 0);
4564 
4565  return reoptSimilarity(reopt, set, run1-1, run2-1, transvars, ntransvars);
4566 }
4567 
4568 /** returns the best solution of the last run */
4570  SCIP_REOPT* reopt /**< reoptimization data structure */
4571  )
4572 {
4573  assert(reopt != NULL);
4574  assert(reopt->prevbestsols != NULL);
4575 
4576  if( reopt->run-2 < 0 )
4577  return NULL;
4578  else
4579  {
4580  assert(reopt->prevbestsols[reopt->run-2] != NULL);
4581  return reopt->prevbestsols[reopt->run-2];
4582  }
4583 }
4584 
4585 /** returns the node of the reoptimization tree corresponding to the unique @p id */
4587  SCIP_REOPT* reopt, /**< reoptimization data structure */
4588  unsigned int id /**< unique id */
4589  )
4590 {
4591  assert(reopt != NULL);
4592  assert(reopt->reopttree != NULL);
4593  assert(id < reopt->reopttree->reoptnodessize);
4594  assert(reopt->reopttree->reoptnodes[id] != NULL);
4595 
4596  return reopt->reopttree->reoptnodes[id];
4597 }
4598 
4599 /** returns the coefficient of variable with index @p idx in run @p run */
4601  SCIP_REOPT* reopt, /**< reoptimization data structure */
4602  int run, /**< number of the run (1,2,...) */
4603  int idx /**< index of variable */
4604  )
4605 {
4606  assert(reopt != NULL);
4607  assert(0 < run && run <= reopt->runsize);
4608 
4609  return reopt->objs[run-1][idx];
4610 }
4611 
4612 /** return the best solution of a given run.
4613  *
4614  * @note the return solution is part of the original space.
4615  */
4617  SCIP_REOPT* reopt, /**< reoptimization data structure */
4618  int run /**< number of the run (1,2,...) */
4619  )
4620 {
4621  assert(reopt != NULL);
4622  assert(0 < run && run <= reopt->run);
4623 
4624  return reopt->prevbestsols[run-1];
4625 }
4626 
4627 /** reset marks of stored solutions to not updated */
4629  SCIP_REOPT* reopt /**< reoptimization data structure */
4630  )
4631 {
4632  assert(reopt != NULL);
4633  assert(reopt->soltree != NULL);
4634  assert(reopt->soltree->root != NULL);
4635 
4636  if( reopt->soltree->root->rchild != NULL )
4638  if( reopt->soltree->root->lchild )
4640 }
4641 
4642 /** returns the number of stored nodes in the subtree induced by @p node */
4644  SCIP_REOPT* reopt, /**< reoptimization data structure */
4645  SCIP_NODE* node /**< node of the search tree */
4646  )
4647 {
4648  unsigned int id;
4649 
4650  assert(reopt != NULL);
4651 
4652  if( node == NULL || SCIPnodeGetDepth(node) == 0 )
4653  return reopt->reopttree->nreoptnodes;
4654 
4655  id = SCIPnodeGetReoptID(node);
4656  assert(id < reopt->reopttree->reoptnodessize);
4657 
4658  /* set the id to -1 if the node is not part of the reoptimization tree */
4659  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
4660  return 0;
4661 
4662  assert(0 < id && id < reopt->reopttree->reoptnodessize);
4663 
4664  return reopttreeGetNNodes(reopt->reopttree, id);
4665 }
4666 
4667 /* ---------------- methods of general reoptimization nodes ---------------- */
4668 
4669 /** In debug mode, the following methods are implemented as function calls to ensure
4670  * type validity.
4671  * In optimized mode, the methods are implemented as defines to improve performance.
4672  * However, we want to have them in the library anyways, so we have to undef the defines.
4673  */
4674 
4675 #undef SCIPreoptnodeGetNVars
4676 #undef SCIPreoptnodeGetNConss
4677 #undef SCIPreoptnodeGetNDualBoundChgs
4678 #undef SCIPreoptnodeGetNChildren
4679 #undef SCIPreoptnodeGetLowerbound
4680 #undef SCIPreoptnodeGetType
4681 
4682 /** returns the number of bound changes stored in the reopttree at ID id */
4684  SCIP_REOPTNODE* reoptnode /**< node of the roepttree */
4685  )
4686 {
4687  assert(reoptnode != NULL);
4688 
4689  return reoptnode->nvars + reoptnode->nafterdualvars;
4690 }
4691 
4692 /** returns the number of bound changes at the node stored at ID id */
4694  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
4695  )
4696 {
4697  assert(reoptnode != NULL);
4698 
4699  return reoptnode->nconss;
4700 }
4701 
4702 /** returns the number of stored bound changes based on dual information in the reopttree at ID id */
4704  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
4705  )
4706 {
4707  assert(reoptnode != NULL);
4708 
4709  if( reoptnode->dualconscur == NULL )
4710  return 0;
4711  else
4712  return reoptnode->dualconscur->nvars;
4713 }
4714 
4715 /** returns the number of child nodes of @p reoptnode */
4717  SCIP_REOPTNODE* reoptnode /**< node of the reoptimizzation tree */
4718  )
4719 {
4720  assert(reoptnode != NULL);
4721 
4722  return reoptnode->nchilds;
4723 }
4724 
4725 /** return the lower bound stored at @p ID id */
4727  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
4728  )
4729 {
4730  assert(reoptnode != NULL);
4731 
4732  return reoptnode->lowerbound;
4733 }
4734 
4735 /** returns the type of the @p reoptnode */
4737  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
4738  )
4739 {
4740  assert(reoptnode != NULL);
4741 
4742  return (SCIP_REOPTTYPE)reoptnode->reopttype;
4743 }
4744 
4745 /** create the constraint which splits the node stored at ID id on the basis of
4746  * the stored dual information.
4747  */
4749  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
4750  SCIP_VAR** vars, /**< array to store the variables of the constraint */
4751  SCIP_Real* vals, /**< array to store the coefficients of the variables */
4752  REOPT_CONSTYPE* constype, /**< type of the constraint */
4753  int conssize, /**< size of the arrays */
4754  int* nvars /**< pointer to store the size of the constraints */
4755  )
4756 {
4757  int v;
4758 
4759  assert(reoptnode != NULL);
4760  assert(vars != NULL);
4761  assert(vals != NULL);
4762 
4763  (*nvars) = reoptnode->dualconscur == NULL ? 0 : reoptnode->dualconscur->nvars;
4764 
4765  if( *nvars == 0 || *nvars > conssize )
4766  return;
4767 
4768  /* copy the variable information */
4769  for(v = 0; v < *nvars; v++)
4770  {
4771  vars[v] = reoptnode->dualconscur->vars[v];
4772  vals[v] = reoptnode->dualconscur->vals[v];
4773  }
4774 
4775  *constype = reoptnode->dualconscur->constype;
4776 
4777  return;
4778 }
4779 
4780 /** returns all added constraints at ID id */
4782  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
4783  SCIP_VAR*** vars, /**< 2-dim array of variables */
4784  SCIP_Real** vals, /**< 2-dim array of values */
4785  int mem, /**< allocated memory for constraints */
4786  int* nconss, /**< pointer to store the number of constraints */
4787  int* nvars /**< pointer to store the number of variables */
4788  )
4789 {
4790  int c;
4791 
4792  assert(reoptnode != NULL);
4793  assert(vars != NULL);
4794  assert(vals != NULL);
4795  assert(nvars != NULL);
4796 
4797 
4798  (*nconss) = reoptnode->nconss;
4799 
4800  if( mem < *nconss )
4801  return;
4802 
4803  for(c = 0; c < *nconss; c++)
4804  {
4805  assert(vars[c] != NULL);
4806  assert(vals[c] != NULL);
4807 
4808  vars[c] = reoptnode->conss[c]->vars;
4809  vals[c] = reoptnode->conss[c]->vals;
4810  nvars[c] = reoptnode->conss[c]->nvars;
4811  }
4812 
4813  return;
4814 }
4815 
4816 /** set the parent id */
4818  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
4819  unsigned int parentid /**< id of the parent node */
4820  )
4821 {
4822  assert(reoptnode != NULL);
4823  assert(parentid <= 536870912); /* id can be at least 2^29 */
4824 
4825  reoptnode->parentID = parentid;
4826 }
4827 
4828 /** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
4830  SCIP_REOPT* reopt, /**< reoptimization data structure */
4831  SCIP_NODE* node /**< node of the search tree (or NULL) */
4832  )
4833 {
4834  int nleaves;
4835  unsigned int id;
4836  int i;
4837 
4838  assert(reopt != NULL);
4839 
4840  nleaves = 0;
4841  id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
4842  assert(id < reopt->reopttree->reoptnodessize);
4843 
4844  /* return if the node is not part of the reoptimization tree */
4845  if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
4846  return nleaves;
4847 
4848  for(i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++)
4849  {
4850  unsigned int childid;
4851 
4852  childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
4853  assert(childid < reopt->reopttree->reoptnodessize);
4854 
4855  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4856  ++nleaves;
4857  else
4858  nleaves += reoptGetNLeaves(reopt, childid);
4859  }
4860 
4861  return nleaves;
4862 }
4863 
4864 /** save information that given node is infeasible */
4866  SCIP_REOPT* reopt, /**< reoptimization data structure */
4867  SCIP_SET* set, /**< global SCIP settings */
4868  BMS_BLKMEM* blkmem, /**< block memory */
4869  SCIP_NODE* node /**< node of the search tree */
4870  )
4871 {
4872  assert(reopt != NULL);
4873  assert(set != NULL);
4874  assert(blkmem != NULL);
4875  assert(node != NULL);
4876 
4877  if( set->reopt_sepaglbinfsubtrees )
4878  {
4879  SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_INFSUBTREE) );
4880  }
4881 
4882  ++reopt->reopttree->ninfnodes;
4883  ++reopt->reopttree->ntotalinfnodes;
4884 
4885  return SCIP_OKAY;
4886 }
4887 
4888 /** check the reason for cut off a node and if necessary store the node */
4890  SCIP_REOPT* reopt, /**< reoptimization data structure */
4891  SCIP_SET* set, /**< global SCIP settings */
4892  BMS_BLKMEM* blkmem, /**< block memory */
4893  SCIP_NODE* node, /**< node of the search tree */
4894  SCIP_EVENTTYPE eventtype, /**< eventtype */
4895  SCIP_LPSOLSTAT lpsolstat, /**< solution status of the LP */
4896  SCIP_Bool isrootnode, /**< the node is the root */
4897  SCIP_Bool isfocusnode, /**< the node is the current focus node */
4898  SCIP_Real lowerbound, /**< lower bound of the node */
4899  int effectiverootdepth /**< effective root depth */
4900  )
4901 {
4902  SCIP_Bool strongbranched;
4903 
4904  assert(reopt != NULL);
4905  assert(node != NULL);
4906  assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED
4907  || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE
4908  || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
4909 
4910  if( reopt->lastseennode == SCIPnodeGetNumber(node) )
4911  return SCIP_OKAY;
4912 
4913  reopt->lastseennode = SCIPnodeGetNumber(node);
4914 
4915  SCIPdebugMessage("catch event %x for node %lld\n", eventtype, SCIPnodeGetNumber(node));
4916 
4917  /* case 1: the current node is the root node
4918  * we can skip if the root is (in)feasible or branched w/o bound
4919  * changes based on dual information.
4920  *
4921  * case 2: we need to store the current node if it contains
4922  * bound changes based on dual information or is a leave node
4923  */
4924 
4925  if( isrootnode )
4926  {
4927  if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
4928  {
4929  goto CHECK;
4930  }
4931  else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
4932  {
4933  /* store or update the information */
4934  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_TRANSIT, TRUE, isrootnode, lowerbound) );
4935  }
4936  else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
4937  {
4938  /* delete saved dual information which would lead to split the node in a further iteration */
4939  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
4940 
4941  /* store or update the information */
4942  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
4943  }
4944  else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
4945  {
4946  /* delete saved dual information which would lead to split the node in a further iteration */
4947  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
4948 
4949  /* store or update the information */
4950  SCIP_CALL( addNode(reopt, set, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
4951  isrootnode, lowerbound) );
4952  }
4953 
4954  assert(reopt->currentnode == -1);
4955  assert(reopt->dualcons == NULL || reopt->dualcons->nvars == 0);
4956 
4957  return SCIP_OKAY;
4958  }
4959 
4960  CHECK:
4961 
4962  if( effectiverootdepth == SCIPnodeGetDepth(node) )
4963  {
4964  strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
4965  }
4966  else
4967  {
4968  strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
4969  }
4970 
4971  SCIPdebugMessage("check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
4972  SCIPdebugMessage(" -> focusnode : %s\n", isfocusnode ? "yes" : "no");
4973  SCIPdebugMessage(" -> depth : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
4974  SCIPdebugMessage(" -> strong branched : %s\n", strongbranched ? "yes" : "no");
4975  SCIPdebugMessage(" -> LP lpsolstat : %d\n", lpsolstat);
4976 
4977  switch( eventtype ) {
4979  /* current node has to be the eventnode */
4980  assert(isfocusnode);
4981 
4982  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_FEASIBLE);
4983 
4984  /* delete strong branching information of some exists */
4985  deleteLastDualBndchgs(reopt);
4986 
4987  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
4988  break;
4989 
4991  /* we have to check if the current node is the event node.
4992  * if the current node is not the event node, we have to save this node, else we have to
4993  * look at LP lpsolstat and decide.
4994  */
4995  if( isfocusnode )
4996  {
4997  /* an after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
4998  * because the node is already branched we have all children and can delete this node. */
4999  if( SCIPnodeGetNumber(node) == reopt->lastbranched )
5000  {
5001  deleteLastDualBndchgs(reopt);
5002  break;
5003  }
5004 
5005  /*
5006  * if the node is strong branched we possible detect an infeasible subtree, if not,
5007  * the whole node is either infeasible or exceeds the cutoff bound.
5008  */
5009  if( strongbranched )
5010  {
5011  /*
5012  * 1. the LP is not solved or infeasible: the subnode is infeasible and can be discarded
5013  * because either the LP proves infeasibility or a constraint handler.
5014  * We have to store an infeasible subtree constraint
5015  * 2. the LP exceeds the objective limit, we have to store the node and can delete the
5016  * strong branching information
5017  */
5018  if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
5019  {
5020  /* add a dummy variable, because the bound changes were not global in the
5021  * sense of effective root depth
5022  */
5023  if( SCIPnodeGetDepth(node) > effectiverootdepth )
5024  {
5025  SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
5026  }
5027 
5028  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
5029  SCIPdebugMessage(" -> new constype : %d\n", REOPT_CONSTYPE_INFSUBTREE);
5030 
5031  /* save the node as a strong branched node */
5032  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
5033  }
5034  else
5035  {
5037 
5038  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
5039 
5040  /* delete strong branching information of some exists */
5041  deleteLastDualBndchgs(reopt);
5042 
5043  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
5044  }
5045  }
5046  else
5047  {
5048  /*
5049  * 1. the LP is not solved or infeasible: the whole node is infeasible and can be discarded
5050  * because either the LP proves infeasibility or a constraint handler.
5051  * 2. the LP exceeds the objective limit, we have to store the node and can delete the
5052  * strong branching information
5053  */
5054  if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
5055  {
5056  /* save the information of an infeasible node */
5057  SCIPdebugMessage(" -> new reopttype : infeasible\n");
5058  SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
5059  }
5060  else
5061  {
5062  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
5063 
5064  /* store the node */
5065  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_PRUNED, TRUE, isrootnode, lowerbound) );
5066  }
5067  }
5068  }
5069  else
5070  {
5071  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
5072 
5073  /* if the node was created by branch_nodereopt, nothing happens */
5074  SCIP_CALL(addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_PRUNED, TRUE, isrootnode, lowerbound) );
5075 
5076  }
5077  break;
5078 
5080  /* current node has to be the eventnode */
5081  assert(isfocusnode);
5082 
5083  reopt->lastbranched = SCIPnodeGetNumber(node);
5084 
5085  /* we have to check the depth of the current node. if the depth is equal to the effective
5086  * root depth, then all information about bound changes based on dual information already exists,
5087  * else we have to look at the domchg-data-structure.*/
5088  if (SCIPnodeGetDepth(node) == effectiverootdepth)
5089  {
5090  /* Save the node if there are added constraints, because this means the node is a copy create by the
5091  * reoptimization plug-in and contains at least one logic-or-constraint */
5092  if( strongbranched )
5093  {
5094  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
5095  SCIPdebugMessage(" -> new constype : %d\n", REOPT_CONSTYPE_STRBRANCHED);
5096  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, TRUE, isrootnode, lowerbound) );
5097  }
5098  else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
5099  {
5100  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
5101  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, TRUE, isrootnode, lowerbound) );
5102  }
5103  else
5104  {
5105  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
5106  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_TRANSIT, TRUE, isrootnode, lowerbound) );
5107  }
5108  }
5109  else
5110  {
5111  /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
5112  *
5113  * we have to do this in the following order:
5114  * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
5115  * on dual information.
5116  * 2) save or update the node.
5117  */
5118  if( strongbranched )
5119  {
5120  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
5121  SCIPdebugMessage(" -> new constype : %d\n", REOPT_CONSTYPE_STRBRANCHED);
5122  SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
5123  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, TRUE, isrootnode, lowerbound) );
5124  }
5125  else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
5126  {
5127  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
5128  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, TRUE, isrootnode, lowerbound) );
5129  }
5130  else
5131  {
5132  SCIPdebugMessage(" -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
5133  SCIP_CALL( addNode(reopt, set, blkmem, node, SCIP_REOPTTYPE_TRANSIT, TRUE, isrootnode, lowerbound) );
5134  }
5135  }
5136  break;
5137 
5138  default:
5139  break;
5140  }
5141 
5142  assert(reopt->currentnode == -1);
5143  assert(reopt->dualcons == NULL || reopt->dualcons->nvars == 0);
5144 
5145  return SCIP_OKAY;
5146 }
5147 
5148 /** store bound change based on dual information */
5150  SCIP_REOPT* reopt, /**< reoptimization data structure */
5151  SCIP_SET* set, /**< global SCIP settings */
5152  BMS_BLKMEM* blkmem, /**< block memory */
5153  SCIP_NODE* node, /**< node of the search tree */
5154  SCIP_VAR* var, /**< variables */
5155  SCIP_Real newval, /**< new bound */
5156  SCIP_Real oldval /**< old bound */
5157  )
5158 {
5159  SCIP_Real constant;
5160  SCIP_Real scalar;
5161 
5162  assert(reopt != NULL);
5163  assert(node != NULL);
5164 
5165  constant = 0.0;
5166  scalar = 1.0;
5167 
5168  /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
5169  * In that case, all bound changes were not global and we can find them within the
5170  * domchg data structure.
5171  * Otherwise, we allocate memory and store the information.
5172  */
5173  if( var != NULL )
5174  {
5175  int allocmem;
5176 
5177  assert(SCIPsetIsFeasEQ(set, newval, 0.0) || SCIPsetIsFeasEQ(set, newval, 1.0));
5178 
5179  allocmem = (reopt->dualcons == NULL || reopt->dualcons->varssize == 0) ? DEFAULT_MEM_DUALCONS : reopt->dualcons->varssize+2;
5180 
5181  /* allocate memory of necessary */
5182  SCIP_CALL( checkMemDualCons(reopt, blkmem, allocmem) );
5183 
5184  assert(reopt->dualcons->varssize > 0);
5185  assert(reopt->dualcons->nvars >= 0);
5186  assert(reopt->currentnode == -1 || reopt->dualcons->nvars > 0);
5187  assert((reopt->dualcons->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
5188  || reopt->dualcons->nvars == 0);
5189 
5190  reopt->currentnode = SCIPnodeGetNumber(node);
5191 
5192  /* transform into the original space and then save the bound change */
5193  SCIP_CALL(SCIPvarGetOrigvarSum(&var, &scalar, &constant));
5194  newval = (newval - constant) / scalar;
5195  oldval = (oldval - constant) / scalar;
5196 
5197  assert(SCIPvarIsOriginal(var));
5198 
5199  reopt->dualcons->vars[reopt->dualcons->nvars] = var;
5200  reopt->dualcons->vals[reopt->dualcons->nvars] = newval;
5201  ++reopt->dualcons->nvars;
5202 
5203  SCIPdebugMessage(">> store bound change of <%s>: %g -> %g\n", SCIPvarGetName(var), oldval, newval);
5204  }
5205  else
5206  {
5207  assert(reopt->currentnode == -1);
5208  assert(reopt->dualcons == NULL || reopt->dualcons->nvars == 0);
5209 
5210  reopt->currentnode = SCIPnodeGetNumber(node);
5211  }
5212 
5213  return SCIP_OKAY;
5214 }
5215 
5216 /** returns the number of bound changes based on dual information */
5218  SCIP_REOPT* reopt, /**< reoptimization data structure */
5219  SCIP_NODE* node /**< node of the search tree */
5220  )
5221 {
5222  int ndualbndchgs;
5223 
5224  assert(reopt != NULL);
5225  assert(node != NULL);
5226 
5227  ndualbndchgs = 0;
5228 
5229  if( SCIPnodeGetNumber(node) == reopt->currentnode )
5230  {
5231  assert(reopt->dualcons != NULL);
5232  ndualbndchgs = reopt->dualcons->nvars;
5233  }
5234 
5235  return ndualbndchgs;
5236 }
5237 
5238 /** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
5240  SCIP_REOPT* reopt, /**< reoptimization data structure */
5241  SCIP_SET* set, /**< global SCIP settings */
5242  BMS_BLKMEM* blkmem, /**< block memory */
5243  SCIP_NODE* node, /**< node of the search tree */
5244  unsigned int* childs, /**< array to store the child ids */
5245  int childssize, /**< size of the childs array */
5246  int* nchilds /**< pointer to store the number of child nodes */
5247  )
5248 {
5249  SCIP_Bool runagain;
5250  unsigned int id;
5251 
5252  assert(reopt != NULL);
5253  assert(childssize > 0 && childs != NULL);
5254 
5255  (*nchilds) = 0;
5256 
5257  if( node == NULL )
5258  id = 0;
5259  else
5260  id = SCIPnodeGetReoptID(node);
5261 
5262  assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
5263  assert(id < reopt->reopttree->reoptnodessize);
5264  assert(reopt->reopttree->reoptnodes[id] != NULL);
5265 
5266  /* check if there are redundant bound changes or infeasible nodes */
5267  runagain = TRUE;
5268  while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
5269  {
5270  SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
5271  }
5272 
5273  /* return the list of child nodes if some exists; otherwise return NULL */
5274  if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
5275  {
5276  int c;
5277 
5278  (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
5279 
5280  if( childssize < *nchilds )
5281  return SCIP_OKAY;
5282 
5283  for( c = 0; c < *nchilds; c++ )
5284  {
5285  childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
5286  }
5287  }
5288 
5289  return SCIP_OKAY;
5290 }
5291 
5292 /** returns all leaves of the subtree induced by @p node */
5294  SCIP_REOPT* reopt, /**< reoptimization data */
5295  SCIP_NODE* node, /**< node of the search tree */
5296  unsigned int* leaves, /**< array to the the ids */
5297  int leavessize, /**< size of leaves array */
5298  int* nleaves /**< pointer to store the number of leav node */
5299  )
5300 {
5301  unsigned int id;
5302  int i;
5303 
5304  assert(reopt != NULL);
5305  assert(leavessize > 0 && leaves != NULL);
5306  assert((*nleaves) >= 0);
5307 
5308  if( node == NULL )
5309  id = 0;
5310  else
5311  id = SCIPnodeGetReoptID(node);
5312 
5313  /* return if the node is not part of the reoptimization tree */
5314  if( id == 0 && node != NULL )
5315  {
5316  (*nleaves) = 0;
5317  return SCIP_OKAY;
5318  }
5319 
5320  assert(id < reopt->reopttree->reoptnodessize);
5321  assert(reopt->reopttree->reoptnodes[id] != NULL);
5322 
5323  for( i = 0; i < leavessize; i++ )
5324  leaves[i] = 0;
5325 
5326  for( i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++ )
5327  {
5328  unsigned int childid;
5329 
5330  assert(*nleaves + 1 <= leavessize);
5331 
5332  childid = reopt->reopttree->reoptnodes[id]->childids[i];
5333  assert(childid < reopt->reopttree->reoptnodessize);
5334 
5335  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
5336  {
5337  leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
5338  ++(*nleaves);
5339  }
5340  else
5341  {
5342  int nleaves2;
5343 
5344  nleaves2 = 0;
5345  SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
5346  (*nleaves) += nleaves2;
5347  }
5348  }
5349 
5350  return SCIP_OKAY;
5351 }
5352 
5353 /** add all unprocessed nodes to the reoptimization tree */
5355  SCIP_REOPT* reopt, /**< reoptimization data structure */
5356  SCIP_SET* set, /**< global SCIP settings */
5357  BMS_BLKMEM* blkmem, /**< block memory */
5358  SCIP_NODE** leaves, /**< array of open leave nodes */
5359  int nleaves, /**< number of open leave nodes */
5360  SCIP_NODE** childs, /**< array of open children nodes */
5361  int nchilds, /**< number of open leave nodes */
5362  SCIP_NODE** siblings, /**< array of open sibling nodes */
5363  int nsiblings /**< number of open leave nodes */
5364  )
5365 {
5366  int n;
5367 
5368  assert(reopt != NULL);
5369  assert(set != NULL);
5370  assert(blkmem != NULL);
5371  assert(nleaves >= 0);
5372  assert(nleaves == 0 || leaves != NULL);
5373  assert(nchilds >= 0);
5374  assert(nchilds == 0 || childs != NULL);
5375  assert(nsiblings >= 0);
5376  assert(nsiblings == 0 || siblings != NULL);
5377 
5378  SCIPdebugMessage("save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
5379 
5380  /* save open leaves */
5381  for( n = 0; n < nleaves; n++ )
5382  {
5383  SCIP_CALL( addNode(reopt, set, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
5384  SCIPnodeGetLowerbound(leaves[n])) );
5385  }
5386 
5387  /* save open children */
5388  for( n = 0; n < nchilds; n++ )
5389  {
5390  SCIP_CALL( addNode(reopt, set, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
5391  SCIPnodeGetLowerbound(childs[n])) );
5392  }
5393 
5394  /* save open siblings */
5395  for( n = 0; n < nsiblings; n++ )
5396  {
5397  SCIP_CALL( addNode(reopt, set, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
5398  SCIPnodeGetLowerbound(siblings[n])) );
5399  }
5400 
5401  return SCIP_OKAY;
5402 }
5403 
5404 /** reset the complete tree and set the given search frontier */
5406  SCIP_REOPT* reopt, /**< reoptimization data structure */
5407  SCIP_SET* set, /**< global SCIP settings */
5408  BMS_BLKMEM* blkmem, /**< block memory */
5409  SCIP_REOPTNODE** representatives, /**< array of representatives */
5410  int nrepresentatives, /**< number of representatives */
5411  SCIP_Bool* success /**< pointer to store if the method was successful */
5412  )
5413 {
5414  SCIP_REOPTTREE* reopttree;
5415  unsigned int id;
5416  int r;
5417 
5418  assert(reopt != NULL);
5419  assert(set != NULL);
5420  assert(blkmem != NULL);
5421  assert(representatives != NULL);
5422  assert(nrepresentatives > 0);
5423 
5424  reopttree = reopt->reopttree;
5425 
5426  /* reset the current search tree */
5427  SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
5428  assert(reopttree->nreoptnodes == 0);
5429 
5430  /* create a new root node */
5431  id = 0;
5432  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
5433 
5434  /* set the reopttype */
5435  reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
5436 
5437  /* add all representatives */
5438  for( r = 0; r < nrepresentatives; r++ )
5439  {
5440  /* get an empty slot*/
5441  id = (unsigned int) (size_t) SCIPqueueRemove(reopttree->openids);
5442  assert(1 <= id && id < reopttree->reoptnodessize);
5443  assert(reopttree->reoptnodes[id] == NULL);
5444 
5445  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
5446  assert(reopttree->reoptnodes[id] != NULL);
5447 
5448  /* set the new node
5449  * 1. copy all variables, bounds, and boundtypes
5450  * 2. copy all constraints
5451  * 3. set the parent relation */
5452  if( representatives[r]->nvars > 0 )
5453  {
5454  assert(representatives[r]->nvars <= representatives[r]->varssize);
5455  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopttree->reoptnodes[id]->vars, representatives[r]->vars,
5456  representatives[r]->nvars) );
5457  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopttree->reoptnodes[id]->varbounds,
5458  representatives[r]->varbounds, representatives[r]->nvars) );
5460  representatives[r]->varboundtypes, representatives[r]->nvars) );
5461  reopttree->reoptnodes[id]->varssize = representatives[r]->varssize;
5462  reopttree->reoptnodes[id]->nvars = representatives[r]->nvars;
5463  }
5464 
5465  if( representatives[r]->nconss > 0 )
5466  {
5467  int c;
5468 
5469  assert(representatives[r]->nconss <= representatives[r]->consssize);
5470 
5471  for( c = 0; c < representatives[r]->nconss; c++ )
5472  {
5473  SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], blkmem, representatives[r]->conss[c]->vars,
5474  representatives[r]->conss[c]->vals, representatives[r]->conss[c]->nvars,
5475  representatives[r]->conss[c]->constype) );
5476  }
5477  }
5478 
5479  reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
5480 
5481  assert(reopttree->reoptnodes[id]->parentID == 0);
5482  assert(reopttree->reoptnodes[id]->nvars >= 0);
5483  assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
5484  assert(reopttree->reoptnodes[id]->nconss >= 0);
5485 
5486  /* set the reopttype */
5487  if( reopttree->reoptnodes[id]->nconss == 0 )
5488  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
5489  else
5490  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
5491 
5492  /* add the representative as a child of the root */
5493  SCIP_CALL( reoptAddChild(reopttree, blkmem, 0, id) );
5494  }
5495 
5496  SCIPdebugMessage("-> new tree consists of %d nodes, the root has %d child nodes.\n",
5497  reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
5498 
5499  (*success) = TRUE;
5500 
5501  return SCIP_OKAY;
5502 }
5503 
5504 /** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
5506  SCIP_REOPT* reopt, /**< reoptimization data structure */
5507  SCIP_TREE* tree, /**< branch and bound tree */
5508  SCIP_SET* set, /**< global SCIP settings */
5509  BMS_BLKMEM* blkmem, /**< block memory */
5510  unsigned int randseed, /**< seed value for random generator */
5511  int* ncreatedchilds, /**< pointer to store the number of created nodes */
5512  int* naddedconss /**< pointer to store the number added constraints */
5513  )
5514 {
5515  SCIP_REOPTTREE* reopttree;
5516  LOGICORDATA* consdata;
5517  SCIP_VAR** vars;
5518  SCIP_Real* vals;
5519  unsigned int id;
5520  int nbndchgs;
5521  int nchilds;
5522  int nvars;
5523  int v;
5524 
5525  assert(reopt != NULL);
5526  assert(reopt->reopttree != NULL);
5527  assert(reopt->reopttree->reoptnodes[0] != NULL);
5528  assert(reopt->reopttree->reoptnodes[0]->dualfixing);
5529  assert(reopt->reopttree->reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
5530  assert(set != NULL);
5531  assert(blkmem != NULL);
5532 
5533  reopttree = reopt->reopttree;
5534 
5535  nchilds = reopttree->reoptnodes[0]->nchilds;
5536 
5537  assert(reopttree->reoptnodes[0]->dualconscur != NULL);
5538  nbndchgs = reopttree->reoptnodes[0]->dualconscur->nvars;
5539 
5540  vars = NULL;
5541  vals = NULL;
5542  nvars = 0;
5543 
5544  (*ncreatedchilds) = 0;
5545  (*naddedconss) = 0;
5546 
5547  if( !set->reopt_usesplitcons )
5548  {
5549  vars = reopttree->reoptnodes[0]->dualconscur->vars;
5550  vals = reopttree->reoptnodes[0]->dualconscur->vals;
5551  nvars = reopttree->reoptnodes[0]->dualconscur->nvars;
5552 
5553  /* calculate the order of the variables */
5554  switch (set->reopt_varorderinterdiction) {
5555  case 'd':
5556  break;
5557 
5558  case 'r':
5559  permuteRandom(vars, vals, nvars, &randseed);
5560  break;
5561 
5562  default:
5563  return SCIP_INVALIDDATA;
5564  }
5565  }
5566 
5567  /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
5568 
5569  /* ensure that two free slots are available */
5570  SCIP_CALL( reopttreeCheckMemory(reopttree, blkmem) );
5571  id = (unsigned int) (size_t) SCIPqueueRemove(reopttree->openids);
5572 
5573  assert(0 < id && id < reopt->reopttree->reoptnodessize);
5574  assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->nvars == 0);
5575 
5576  /* 1. create the node
5577  * 2. add all bound changes
5578  * 3. move all child nodes to id
5579  * 4. add id as a child of the root node
5580  */
5581  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
5582  reopttree->reoptnodes[id]->parentID = 0;
5583  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
5584 
5585  /* check memory */
5586  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, nbndchgs, nchilds, 0) );
5587  assert(reopttree->reoptnodes[id]->varssize >= nbndchgs);
5588  assert(reopttree->reoptnodes[id]->nvars == 0);
5589  assert(reopttree->reoptnodes[id]->vars != NULL);
5590  assert(reopttree->reoptnodes[id]->varbounds != NULL);
5591  assert(reopttree->reoptnodes[id]->varboundtypes != NULL);
5592 
5593  /* copy bounds */
5594  for(v = 0; v < nbndchgs; v++)
5595  {
5596  reopttree->reoptnodes[id]->vars[v] = reopttree->reoptnodes[0]->dualconscur->vars[v];
5597  reopttree->reoptnodes[id]->varbounds[v] = reopttree->reoptnodes[0]->dualconscur->vals[v];
5598  reopttree->reoptnodes[id]->varboundtypes[v] = SCIPsetIsFeasEQ(set, reopttree->reoptnodes[0]->dualconscur->vals[v], 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
5599  ++reopttree->reoptnodes[id]->nvars;
5600  }
5601  assert(reopttree->reoptnodes[id]->nvars == reopttree->reoptnodes[0]->dualconscur->nvars);
5602 
5603  /* move the children */
5604  SCIP_CALL( reoptMoveIDs(reopttree, blkmem, 0, id) );
5605  assert(reopttree->reoptnodes[0]->nchilds == 0);
5606 
5607  /* add the new reoptimization node as a child of the root node */
5608  SCIP_CALL( reoptAddChild(reopttree, blkmem, 0, id) );
5609 
5610  ++(*ncreatedchilds);
5611 
5612  if( set->reopt_usesplitcons )
5613  {
5614  assert(*ncreatedchilds == 1);
5615 
5616  /* ensure that there is a free slots */
5617  SCIP_CALL( reopttreeCheckMemory(reopttree, blkmem) );
5618  id = (unsigned int) (size_t) SCIPqueueRemove(reopttree->openids);
5619  assert(0 < id && id < reopt->reopttree->reoptnodessize);
5620 
5621  /* 1. create the node
5622  * 2. add the constraint to ensure that at least one
5623  * variable gets different
5624  * 3. add id as a child of the root node
5625  */
5626  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
5627  reopttree->reoptnodes[id]->parentID = 0;
5628  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
5629 
5630  /* create the constraint */
5631  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &consdata) );
5632  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, reopttree->reoptnodes[0]->dualconscur->vars, nbndchgs) );
5633  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, reopttree->reoptnodes[0]->dualconscur->vals, nbndchgs) );
5634 
5635  consdata->varssize = nbndchgs;
5636  consdata->nvars = nbndchgs;
5638 
5639  ++(*naddedconss);
5640 
5641  /* check memory for added constraints */
5642  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, 0, 0, 1) );
5643 
5644  /* add the constraint */
5645  reopttree->reoptnodes[id]->conss[reopttree->reoptnodes[id]->nconss] = consdata;
5646  ++reopttree->reoptnodes[id]->nconss;
5647 
5648  /* add id as a child of the root node */
5649  SCIP_CALL( reoptAddChild(reopttree, blkmem, 0, id) );
5650 
5651  ++(*ncreatedchilds);
5652  }
5653  else
5654  {
5655  int c;
5656 
5657  assert(*ncreatedchilds == 1);
5658  assert(vars != NULL);
5659  assert(vals != NULL);
5660  assert(nvars > 0);
5661 
5662  /* create nvars nodes in the fashion of interdiction branching */
5663  for( c = 0; c < nvars; c++ )
5664  {
5665  /* ensure that two free slots are available */
5666  SCIP_CALL( reopttreeCheckMemory(reopttree, blkmem) );
5667  id = (unsigned int) (size_t) SCIPqueueRemove(reopttree->openids);
5668 
5669  assert(0 < id && id < reopt->reopttree->reoptnodessize);
5670  assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->nvars == 0);
5671 
5672  /* 1. create the node
5673  * 2. fix the first v bound changes to vals[v] and v+1 to 1-vals[v]
5674  * 4. add the ID id as a child of the root node
5675  */
5676  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
5677  reopttree->reoptnodes[id]->parentID = 0;
5678  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
5679 
5680  /* check memory */
5681  SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], blkmem, c+1, 0, 0) );
5682  assert(reopttree->reoptnodes[id]->varssize >= c+1);
5683  assert(reopttree->reoptnodes[id]->nvars == 0);
5684  assert(reopttree->reoptnodes[id]->vars != NULL);
5685  assert(reopttree->reoptnodes[id]->varbounds != NULL);
5686  assert(reopttree->reoptnodes[id]->varboundtypes != NULL);
5687 
5688  /* copy first v bound changes */
5689  for( v = 0; v < c; v++ )
5690  {
5691  reopttree->reoptnodes[id]->vars[v] = vars[v];
5692  reopttree->reoptnodes[id]->varbounds[v] = vals[v];
5693  reopttree->reoptnodes[id]->varboundtypes[v] = SCIPsetIsFeasEQ(set, vals[v], 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
5694  ++reopttree->reoptnodes[id]->nvars;
5695  }
5696 
5697  /* set bound change v+1 (= c) to 1-vals[c] */
5698  assert(v == c);
5699  reopttree->reoptnodes[id]->vars[c] = vars[c];
5700  reopttree->reoptnodes[id]->varbounds[c] = 1-vals[c];
5701  reopttree->reoptnodes[id]->varboundtypes[c] = SCIPsetIsFeasEQ(set, 1-vals[c], 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
5702  ++reopttree->reoptnodes[id]->nvars;
5703 
5704  /* add dummy1 as a child of the root node */
5705  SCIP_CALL( reoptAddChild(reopttree, blkmem, 0, id) );
5706 
5707  ++(*ncreatedchilds);
5708  }
5709 
5710  assert(*ncreatedchilds == nvars+1);
5711  }
5712 
5713  /* free the current dualconscur and assign dualconsnex */
5714  assert(reopttree->reoptnodes[0]->dualconscur->vars != NULL);
5715  assert(reopttree->reoptnodes[0]->dualconscur->vals != NULL);
5716 
5717  /* free the current dualconscur and assign dualconsnex */
5718  SCIP_CALL( reoptnodeUpdateDualConss(reopttree->reoptnodes[0], blkmem) );
5719 
5720  /* change the reopttype of the root node */
5722 
5723  return SCIP_OKAY;
5724 }
5725 
5726 /** reset the stored information abound bound changes based on dual information */
5728  SCIP_REOPT* reopt, /**< reoptimization data structure */
5729  SCIP_NODE* node, /**< node of the search tree */
5730  BMS_BLKMEM* blkmem /**< block memory */
5731  )
5732 {
5733  unsigned int id;
5734 
5735  assert(reopt != NULL);
5736  assert(node != NULL);
5737 
5738  id = SCIPnodeGetReoptID(node);
5739  assert(id < reopt->reopttree->reoptnodessize);
5740 
5741  /* return if the node ist not part of the reoptimization tree */
5742  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5743  return SCIP_OKAY;
5744 
5745  /* reset the dual constraint */
5746  SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
5747 
5748  return SCIP_OKAY;
5749 }
5750 
5751 /** return the branching path stored of the given node in the reoptimization tree */
5753  SCIP_REOPT* reopt, /**< reoptimization data structure */
5754  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
5755  SCIP_VAR** vars, /**< array for variables */
5756  SCIP_Real* vals, /**< array for values */
5757  SCIP_BOUNDTYPE* boundtypes, /**< array for bound types */
5758  int varssize, /**< size of arrays vars, vals, and boundtypes */
5759  int* nbndchgs, /**< pointer to store the number of bound changes */
5760  int* nbndchgsafterdual /**< pointer to store the number of bound changes applied after
5761  * the first dual reduction at the given node */
5762  )
5763 {
5764  int v;
5765  int nvars2;
5766  int nafterdualvars2;
5767 
5768  assert(reopt != NULL);
5769  assert(reoptnode != NULL);
5770  assert(vars != NULL);
5771  assert(vals != NULL);
5772  assert(boundtypes != NULL);
5773 
5774  (*nbndchgs) = reoptnode->nvars;
5775  (*nbndchgsafterdual) = reoptnode->nafterdualvars;
5776 
5777  if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
5778  return;
5779 
5780  for(v = 0; v < *nbndchgs; v++)
5781  {
5782  vars[v] = reoptnode->vars[v];
5783  vals[v] = reoptnode->varbounds[v];
5784  boundtypes[v] = reoptnode->varboundtypes[v];
5785  }
5786 
5787  for(; v < *nbndchgs + *nbndchgsafterdual; v++)
5788  {
5789  vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
5790  vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
5791  boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
5792  }
5793 
5794  if( reoptnode->parentID != 0 )
5795  {
5796  SCIP_REOPTNODE* parent;
5797 
5798  parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
5799  SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
5800 
5801  (*nbndchgs) += nvars2;
5802  (*nbndchgsafterdual) += nafterdualvars2;
5803  }
5804 
5805  return;
5806 }
5807 
5808 /** delete a node stored in the reoptimization tree */
5810  SCIP_REOPT* reopt, /**< reoptimization data structure */
5811  SCIP_SET* set, /**< global SCIP settings */
5812  unsigned int id, /**< id of a stored node */
5813  BMS_BLKMEM* blkmem /**< block memory */
5814  )
5815 {
5816  assert(reopt != NULL);
5817  assert(reopt->reopttree != NULL);
5818  assert(id < reopt->reopttree->reoptnodessize);
5819  assert(reopt->reopttree->reoptnodes[id] != NULL);
5820  assert(blkmem != NULL);
5821 
5822  SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
5823 
5824  return SCIP_OKAY;
5825 }
5826 
5827 /** reactivate the given @p reoptnode and split them into several nodes if necessary */
5829  SCIP_REOPT* reopt, /**< reoptimization data structure */
5830  SCIP* scip, /**< SCIP data structure */
5831  SCIP_SET* set, /**< global SCIP settings */
5832  SCIP_STAT* stat, /**< dynamic problem statistics */
5833  SCIP_PROB* transprob, /**< transformed problem */
5834  SCIP_PROB* origprob, /**< original problem */
5835  SCIP_TREE* tree, /**< branching tree */
5836  SCIP_LP* lp, /**< current LP */
5837  SCIP_BRANCHCAND* branchcand, /**< branching candidate */
5838  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5839  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
5840  BMS_BLKMEM* blkmem, /**< block memory */
5841  unsigned int randseed, /**< seed value for random generator */
5842  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree to reactivate */
5843  unsigned int id, /**< id of the node to reactivate */
5844  SCIP_Real estimate, /**< estimate of the child nodes that should be created */
5845  SCIP_NODE** childnodes, /**< array to store the created child nodes */
5846  int* ncreatedchilds, /**< pointer to store number of created child nodes */
5847  int* naddedconss, /**< pointer to store number of generated constraints */
5848  int childnodessize, /**< available size of childnodes array */
5849  SCIP_Bool* success /**< pointer store the result */
5850  )
5851 {
5852  assert(reopt != NULL);
5853  assert(scip != NULL);
5854  assert(set != NULL);
5855  assert(stat != NULL);
5856  assert(transprob != NULL);
5857  assert(origprob != NULL);
5858  assert(tree != NULL);
5859  assert(lp != NULL);
5860  assert(branchcand != NULL);
5861  assert(eventqueue != NULL);
5862  assert(cliquetable != NULL);
5863  assert(blkmem != NULL);
5864  assert(reoptnode != NULL);
5865  assert(childnodes != NULL);
5866  assert(reopt->reopttree != NULL);
5867  assert(id < reopt->reopttree->reoptnodessize);
5868 
5869  SCIPdebugMessage("reactivating node at id %u:\n", id);
5870 
5871  *success = FALSE;
5872 
5873  /* check if we need to split the node */
5874  if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
5875  || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
5876  {
5877  int c;
5878 
5879  assert(reoptnode->dualfixing);
5880 
5881  /* we want use a constraint to split the node into two disjoint node */
5882  if( set->reopt_usesplitcons )
5883  {
5884  if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
5885  {
5886  assert(reoptnode->dualconscur != NULL);
5887  assert(reoptnode->dualconscur->constype == REOPT_CONSTYPE_INFSUBTREE);
5888  (*ncreatedchilds) = 1;
5889  }
5890  else
5891  {
5892  assert(reoptnode->dualconscur != NULL);
5893  assert(reoptnode->dualconscur->constype == REOPT_CONSTYPE_STRBRANCHED);
5894  (*ncreatedchilds) = 2;
5895  }
5896 
5897  /* in both cases we add exactly one constraint */
5898  (*naddedconss) = 1;
5899 
5900  if( childnodessize < *ncreatedchilds )
5901  return SCIP_OKAY;
5902 
5903  /* generate the nodes */
5904  for( c = 0; c < *ncreatedchilds; c++ )
5905  {
5906  /* create the child node */
5907  SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
5908 
5909  /* change all bounds; convert the bound changes after the first based on dual reductions into branching
5910  * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
5911  * changes anyway.
5912  */
5913  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
5914  cliquetable, blkmem, childnodes[c], id, c == 1) );
5915 
5916  /* add all local constraints */
5917  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
5918 
5919  if( c == 0 )
5920  {
5921  /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
5922  SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_NONE);
5923 
5924  /* add the constraint to the node */
5925  assert(reopt->reopttree->reoptnodes[id]->dualconscur != NULL);
5926  SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
5927  eventqueue, cliquetable, childnodes[c], id) );
5928 
5929  /* fixBounds() does the same, but in this case we go not into it */
5930  if( reoptnode->dualconscur->constype == REOPT_CONSTYPE_INFSUBTREE )
5931  {
5932  assert(reoptnode->dualconscur->nvars > 0);
5933  assert(reoptnode->dualconscur->varssize > 0);
5934 
5935  /* delete dualconscur and move dualconsnex -> dualconscur */
5936  SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
5937  }
5938  }
5939  else
5940  {
5941  /* if we reach this lines of code, the current node represents the original node including all bound
5942  * changes based in dual information.
5943  */
5944  assert(reoptnode->dualconscur->constype == REOPT_CONSTYPE_STRBRANCHED);
5945  if( reoptnode->nconss == 0 )
5947  else
5949 
5950  /* fix all bound changes based on dual information and convert them into branchings */
5951  assert(reopt->reopttree->reoptnodes[id]->dualconscur != NULL);
5952  SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
5953  blkmem, childnodes[c], id, TRUE) );
5954 
5955  /* set the unique id the id of the original node */
5956  SCIPnodeSetReoptID(childnodes[c], id);
5957  }
5958 
5959  /* set the estimate */
5960  if( !SCIPsetIsInfinity(set, REALABS(reoptnode->lowerbound)) )
5961  {
5962  if( SCIPsetIsRelGE(set, reoptnode->lowerbound, SCIPnodeGetLowerbound(childnodes[c])) )
5963  SCIPnodeSetEstimate(childnodes[c], set, reoptnode->lowerbound);
5964  }
5965  }
5966 
5967  /* reset the stored dual constraints */
5968  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
5969 
5970  /* set the reoptimization type */
5971  if( reopt->reopttree->reoptnodes[id]->dualfixing )
5972  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
5973  else
5974  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
5975 
5976  *success = TRUE;
5977  }
5978  else
5979  {
5980  SCIP_VAR** vars;
5981  SCIP_Real* vals;
5982  int nvars;
5983 
5984  vars = reoptnode->dualconscur->vars;
5985  vals = reoptnode->dualconscur->vals;
5986  nvars = reoptnode->dualconscur->nvars;
5987 
5988  /* calculate the order of the variables */
5989  switch (set->reopt_varorderinterdiction)
5990  {
5991  case 'd':
5992  break;
5993 
5994  case 'r':
5995  permuteRandom(vars, vals, nvars, &randseed);
5996  break;
5997 
5998  default:
5999  return SCIP_INVALIDDATA;
6000  }
6001 
6002  *ncreatedchilds = nvars+1;
6003  *naddedconss = 0;
6004 
6005  if( childnodessize < *ncreatedchilds )
6006  return SCIP_OKAY;
6007 
6008  assert(reopt->reopttree->reoptnodes[id] != NULL);
6009  reoptnode = reopt->reopttree->reoptnodes[id];
6010 
6011  /* enough that the node need to split */
6012  assert(reoptnode->dualfixing);
6013 
6014  /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
6015  * we need to do this in the reverse order because we want to transform the bound changes based on dual information
6016  * into branching decisions at nodes[0].
6017  */
6018  for( c = nvars; c >= 0; c-- )
6019  {
6020  /* create the child node */
6021  SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
6022 
6023  #ifdef SCIP_MORE_DEBUG
6024  SCIPdebugMessage(" change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
6025  #endif
6026 
6027  /* change all bounds */
6028  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
6029  cliquetable, blkmem, childnodes[c], id, FALSE) );
6030 
6031  /* reconstruct the original node and the pruned part, respectively */
6032  if( c == 0 )
6033  {
6034  /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
6035  SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
6036  blkmem, childnodes[c], id, TRUE) );
6037 
6038  /* set the reopttype of the node */
6040 
6041  /* set the unique id */
6042  SCIPnodeSetReoptID(childnodes[c], id);
6043  }
6044  else
6045  {
6046  /* fix the first c bound changes and negate the (c+1)th */
6047  SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
6048  blkmem, childnodes[c], id, vars, vals, nvars, c) );
6049  }
6050 
6051  /* add all local constraints */
6052  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
6053 
6054  /* set estimates */
6055  if( !SCIPsetIsInfinity(set, REALABS(reopt->reopttree->reoptnodes[id]->lowerbound)) )
6056  {
6057  if( SCIPsetIsRelGE(set, reoptnode->lowerbound, SCIPnodeGetLowerbound(childnodes[c])))
6058  SCIPnodeSetEstimate(childnodes[c], set, reoptnode->lowerbound);
6059  }
6060  }
6061 
6062  /* reset the stored dual constraints */
6063  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
6064 
6065  /* set the reoptimization type to transit */
6066  if( reopt->reopttree->reoptnodes[id]->dualfixing )
6067  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
6068  else
6069  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6070 
6071  *success = TRUE;
6072  }
6073  }
6074  else
6075  {
6076  /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
6077  (*ncreatedchilds) = 1;
6078  (*naddedconss) = 0;
6079 
6080  if( childnodessize < *ncreatedchilds )
6081  return SCIP_OKAY;
6082 
6083  /* create the child node */
6084  SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
6085 
6086  /* change all bounds */
6087  assert(reoptnode->nafterdualvars == 0);
6088  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
6089  cliquetable, blkmem, childnodes[0], id, FALSE) );
6090 
6091  /* add all local constraints */
6092  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
6093 
6094  /* set the estimate */
6095  if( !SCIPsetIsInfinity(set, REALABS(reopt->reopttree->reoptnodes[id]->lowerbound)) )
6096  {
6097  if( SCIPsetIsRelGE(set, reopt->reopttree->reoptnodes[id]->lowerbound, SCIPnodeGetLowerbound(childnodes[0])) )
6098  SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
6099  }
6100 
6101  /* set the reopttype */
6102  assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
6103  && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE);
6104  SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
6105 
6106  /* set the unique id */
6107  SCIPnodeSetReoptID(childnodes[0], id);
6108 
6109  *success = TRUE;
6110  }
6111 
6112  return SCIP_OKAY;
6113 }
6114 
6115 #ifdef SCIP_DISABLED_CODE
6116 /** Reoptimize the node stored at ID @p id in the fashion of interdiction branching,
6117  * i.e. create and split the node in the current run, if necessary.
6118  *
6119  * To reconstruct the pruned part we create @p nnodes nodes, whereby
6120  * - nodes[0] corresponds to the original node
6121  * - nodes[k] contains: var[0] = ... = var[k-1] = 0 and var[k] = 1
6122  * where var are the (negated) variables fixed to 0 by dual reductions.
6123  */
6124 SCIP_RETCODE SCIPreoptApplyInterdiction(
6125  SCIP_REOPT* reopt, /**< reoptimization data structure */
6126  SCIP* scip, /**< SCIP data structure */
6127  SCIP_SET* set, /**< global SCIP settings */
6128  SCIP_STAT* stat, /**< dynamic problem statistics */
6129  SCIP_PROB* transprob, /**< transformed problem */
6130  SCIP_PROB* origprob, /**< original problem */
6131  SCIP_TREE* tree, /**< branching tree */
6132  SCIP_LP* lp, /**< current LP */
6133  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
6134  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6135  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
6136  SCIP_NODE** nodes, /**< array to store created nodes */
6137  int nnodes, /**< size of the array */
6138  int id, /**< id of a stored node which should be reoptimized */
6139  int* permutation, /**< permutation of the variable order (within the constraint) */
6140  BMS_BLKMEM* blkmem /**< block memory */
6141  )
6142 {
6143  SCIP_REOPTNODE* reoptnode;
6144  int c;
6145 
6146  assert(reopt != NULL);
6147  assert(scip != NULL);
6148  assert(set != NULL);
6149  assert(stat != NULL);
6150  assert(blkmem != NULL);
6151  assert(transprob != NULL);
6152  assert(origprob != NULL);
6153  assert(tree != NULL);
6154  assert(lp != NULL);
6155  assert(branchcand != NULL);
6156  assert(eventqueue != NULL);
6157  assert(cliquetable != NULL);
6158  assert(nodes != NULL || nnodes == 0);
6159  assert(blkmem != NULL);
6160 
6161  SCIPdebugMessage("reoptimizing node at ID %d:\n", id);
6162 
6163  assert(reopt->reopttree->reoptnodes[id] != NULL);
6164  reoptnode = reopt->reopttree->reoptnodes[id];
6165 
6166  /* enough that the node need to split */
6167  assert(reoptnode->dualfixing);
6168 
6169  /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
6170  * we need to do this in the reverse order because we want to transform the bound changes based on dual information
6171  * into branching decisions at nodes[0].
6172  */
6173  for( c = nnodes-1; c >= 0; c-- )
6174  {
6175 #ifdef SCIP_MORE_DEBUG
6176  SCIPdebugMessage(" change bounds at node %lld\n", SCIPnodeGetNumber(nodes[c]));
6177 #endif
6178 
6179  /* change all bounds */
6180  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
6181  cliquetable, blkmem, nodes[c], NULL, id) );
6182 
6183  /* reconstruct the original node and the pruned part, respectively */
6184  if( c == 0 )
6185  {
6186  /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
6187  SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
6188  blkmem, nodes[c], id, FALSE) );
6189  }
6190  else
6191  {
6192  /* fix the first c bound changes and negate the (c+1)th */
6193  SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
6194  blkmem, nodes[c], id, permutation, c) );
6195  }
6196 
6197  /* add all local constraints to both nodes */
6198  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, nodes[c], NULL, id) );
6199 
6200  /* set estimates */
6201  if( !SCIPsetIsInfinity(set, REALABS(reopt->reopttree->reoptnodes[id]->lowerbound)) )
6202  {
6203  if( SCIPsetIsRelGE(set, reopt->reopttree->reoptnodes[id]->lowerbound, SCIPnodeGetLowerbound(nodes[c])))
6204  SCIPnodeSetEstimate(nodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
6205  }
6206  }
6207 
6208  /* reset the stored dual constraints */
6209  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
6210 
6211  return SCIP_OKAY;
6212 }
6213 #endif
6214 
6215 /** returns the time needed to store the nodes for reoptimization */
6217  SCIP_REOPT* reopt /**< reoptimization data structure */
6218  )
6219 {
6220  assert(reopt != NULL);
6221 
6222  return SCIPclockGetTime(reopt->savingtime);
6223 }
6224 
6225 /** store a global constraint that should be added at the beginning of the next iteration */
6227  SCIP_REOPT* reopt, /**< reoptimization data structure */
6228  SCIP_VAR** vars, /**< array to store the variables of the constraint */
6229  SCIP_Real* vals, /**< array to store the coefficients of the variables */
6230  int nvars, /**< pointer to store the size of the constraints */
6231  BMS_BLKMEM* blkmem /**< block memory */
6232  )
6233 {
6234  assert(reopt != NULL);
6235  assert(vars != NULL);
6236  assert(vals != NULL);
6237  assert(blkmem != NULL);
6238 
6239  if( nvars > 0 )
6240  {
6241  int pos;
6242 
6243  /* check the memory */
6244  SCIP_CALL( checkMemGlbCons(reopt, blkmem, reopt->nglbconss + 1) );
6245  assert(reopt->allocmemglbconss >= reopt->nglbconss+1);
6246 
6247  pos = reopt->nglbconss;
6248 
6249  /* allocate memory */
6250  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[pos]) ); /*lint !e866*/
6251  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->glbconss[pos]->vars, &vars, nvars) );
6252  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->glbconss[pos]->vals, &vals, nvars) );
6253  reopt->glbconss[pos]->varssize = nvars;
6254  reopt->glbconss[pos]->nvars = nvars;
6255 
6256  ++reopt->nglbconss;
6257  }
6258 
6259  return SCIP_OKAY;
6260 }
6261 
6262 /** add the stored constraints globally to the problem */
6264  SCIP* scip, /**< SCIP data structure */
6265  SCIP_REOPT* reopt, /**< reoptimization data structure */
6266  SCIP_SET* set, /**< global SCIP settings */
6267  SCIP_STAT* stat, /**< dynamic problem statistics */
6268  BMS_BLKMEM* blkmem /**< block memory */
6269  )
6270 {
6271  int c;
6272 
6273  assert(scip != NULL);
6274  assert(reopt != NULL);
6275  assert(set != NULL);
6276  assert(stat != NULL);
6277  assert(blkmem != NULL);
6278 
6279  if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
6280  return SCIP_OKAY;
6281 
6282  SCIPdebugMessage("try to add %d glb constraints\n", reopt->nglbconss);
6283 
6284  for(c = 0; c < reopt->nglbconss; c++)
6285  {
6286  SCIP_CONS* cons;
6287  SCIP_VAR** consvars;
6288  int v;
6289 
6290  assert(reopt->glbconss[c]->nvars > 0);
6291 
6292  /* allocate buffer */
6293  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
6294 
6295  SCIPdebugMessage("-> add constraints with %d vars\n", reopt->glbconss[c]->nvars);
6296 
6297  for(v = 0; v < reopt->glbconss[c]->nvars; v++)
6298  {
6299  consvars[v] = SCIPvarGetTransVar(reopt->glbconss[c]->vars[v]);
6300 
6301  /* negate the variable if it was fixed to 1 */
6302  if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 1.0) )
6303  {
6304  SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
6305  }
6306  }
6307 
6308  /* create the logic-or constraint and add them to the problem */
6309  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, "glblogicor", reopt->glbconss[c]->nvars,
6310  consvars, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE) );
6311 
6312  SCIPdebugPrintCons(scip, cons, NULL);
6313 
6314  SCIP_CALL( SCIPaddCons(scip, cons) );
6315  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
6316 
6317  /* delete the global constraints data */
6318  SCIPfreeBlockMemoryArrayNull(scip, &reopt->glbconss[c]->vals, reopt->glbconss[c]->nvars);
6319  SCIPfreeBlockMemoryArrayNull(scip, &reopt->glbconss[c]->vars, reopt->glbconss[c]->nvars);
6320  SCIPfreeBlockMemoryNull(scip, &reopt->glbconss[c]); /*lint !e866*/
6321  reopt->glbconss[c]->nvars = 0;
6322 
6323  /* free buffer */
6324  SCIPfreeBufferArray(scip, &consvars);
6325  }
6326 
6327  /* reset the number of global constraints */
6328 #ifdef SCIP_DEBUG
6329  for(c = 0; c < reopt->nglbconss; c++)
6330  {
6331  assert(reopt->glbconss[c]->nvars == 0);
6332  assert(reopt->glbconss[c]->vars == NULL);
6333  assert(reopt->glbconss[c]->vals == NULL);
6334  }
6335 #endif
6336  reopt->nglbconss = 0;
6337 
6338  return SCIP_OKAY;
6339 }
6340 
6341 /** check if the LP of the given node should be solved or not */
6343  SCIP_REOPT* reopt, /**< reoptimization data structure */
6344  SCIP_SET* set, /**< global SCIP settings */
6345  SCIP_NODE* node /**< node of the current search tree */
6346  )
6347 {
6348  unsigned int id;
6349 
6350  assert(reopt != NULL);
6351  assert(node != NULL);
6352 
6353  /* get the ID */
6354  id = SCIPnodeGetReoptID(node);
6355  assert(id < reopt->reopttree->reoptnodessize);
6356 
6357  /* return if the node is not part of the reoptimization tree */
6358  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
6359  return TRUE;
6360 
6361  /* current node is the root */
6362  if( id == 0 )
6363  {
6364  if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
6365  {
6366  /* the objective function has changed only slightly */
6367  if( reopt->simtolastobj >= set->reopt_objsimrootlp )
6368  return FALSE;
6369  }
6370  }
6371  else
6372  {
6373  /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
6374  if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
6375  {
6376  assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
6377  return FALSE;
6378  }
6379  }
6380 
6381  return TRUE;
6382 }
6383 
6384 /** initialize an empty node */
6386  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
6387  SCIP_SET* set /**< global SCIP settings */
6388  )
6389 {
6390  assert(reoptnode != NULL);
6391  assert(set != NULL);
6392 
6393  reoptnode->conss = NULL;
6394  reoptnode->nconss = 0;
6395  reoptnode->consssize = 0;
6396  reoptnode->childids = NULL;
6397  reoptnode->allocchildmem = 0;
6398  reoptnode->nchilds = 0;
6399  reoptnode->nvars = 0;
6400  reoptnode->nafterdualvars = 0;
6401  reoptnode->parentID = 0;
6402  reoptnode->dualfixing = FALSE;
6403  reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
6404  reoptnode->varssize = 0;
6405  reoptnode->afterdualvarssize = 0;
6406  reoptnode->vars = NULL;
6407  reoptnode->varbounds = NULL;
6408  reoptnode->varboundtypes = NULL;
6409  reoptnode->afterdualvars = NULL;
6410  reoptnode->afterdualvarbounds = NULL;
6411  reoptnode->afterdualvarboundtypes = NULL;
6412  reoptnode->dualconscur = NULL;
6413  reoptnode->dualconsnex = NULL;
6414  reoptnode->lowerbound = -SCIPsetInfinity(set);
6415 }
6416 
6417 /** reset the given reoptimization node */
6419  SCIP_REOPT* reopt, /**< reoptimization data structure */
6420  SCIP_SET* set, /**< global SCIP settings */
6421  BMS_BLKMEM* blkmem, /**< block memory */
6422  SCIP_REOPTNODE* reoptnode /**< reoptimization node */
6423  )
6424 {
6425  assert(reopt != NULL);
6426  assert(set != NULL);
6427  assert(blkmem != NULL);
6428  assert(reoptnode != NULL);
6429 
6430  SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
6431 
6432  return SCIP_OKAY;
6433 }
6434 
6435 /** delete the given reoptimization node */
6437  SCIP_REOPTNODE** reoptnode, /**< pointer of reoptnode */
6438  BMS_BLKMEM* blkmem /**< block memory */
6439  )
6440 {
6441  assert(reoptnode != NULL);
6442  assert(blkmem != NULL);
6443 
6444  SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
6445 
6446  return SCIP_OKAY;
6447 }
6448 
6449 /** add a variable to a given reoptnode */
6451  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
6452  BMS_BLKMEM* blkmem, /**< block memory */
6453  SCIP_VAR* var, /**< variable to add */
6454  SCIP_Real val, /**< value of the variable */
6455  SCIP_BOUNDTYPE boundtype /**< boundtype of the variable */
6456  )
6457 {
6458  int nvars;
6459 
6460  assert(reoptnode != NULL);
6461  assert(var != NULL);
6462  assert(blkmem != NULL);
6463 
6464  nvars = reoptnode->nvars;
6465 
6466  SCIP_CALL( reoptnodeCheckMemory(reoptnode, blkmem, nvars + 1, 0, 0) );
6467 
6468  reoptnode->vars[nvars] = var;
6469  reoptnode->varbounds[nvars] = val;
6470  reoptnode->varboundtypes[nvars] = boundtype;
6471  ++reoptnode->nvars;
6472 
6473  return SCIP_OKAY;
6474 }
6475 
6476 /** add a constraint to a given reoptnode */
6478  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
6479  BMS_BLKMEM* blkmem, /**< block memory */
6480  SCIP_VAR** consvars, /**< variables which are part of the constraint */
6481  SCIP_Real* consvals, /**< values of the variables */
6482  int nvars, /**< number of variables */
6483  REOPT_CONSTYPE constype /**< type of the constraint */
6484  )
6485 {
6486  int nconss;
6487 
6488  assert(reoptnode != NULL);
6489  assert(consvars != NULL);
6490  assert(consvals != NULL);
6491  assert(nvars > 0);
6492  assert(blkmem != NULL);
6493 
6494  /* the constraint can be interpreted as a normal bound change */
6495  if( nvars == 1 )
6496  {
6497  SCIPdebugMessage("-> constraint has size 1 -> save as normal bound change.\n");
6498 
6499  SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, blkmem, consvars[0], 1-consvals[0],
6500  1-consvals[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
6501  }
6502  else
6503  {
6504  nconss = reoptnode->nconss;
6505 
6506  SCIP_CALL( reoptnodeCheckMemory(reoptnode, blkmem, 0, 0, nconss+1) );
6507 
6508  /* create the constraint */
6509  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
6510  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, consvars, nvars) );
6511  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, consvals, nvars) );
6512 
6513  reoptnode->conss[nconss]->varssize = nvars;
6514  reoptnode->conss[nconss]->nvars = nvars;
6515  reoptnode->conss[nconss]->constype = constype;
6516  ++reoptnode->nconss;
6517  }
6518  return SCIP_OKAY;
6519 }
static SCIP_RETCODE ensureRunSize(SCIP_REOPT *reopt, int num, BMS_BLKMEM *blkmem)
Definition: reopt.c:172
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16658
static int soltreeNInducedSols(SCIP_SOLNODE *solnode)
Definition: reopt.c:313
LOGICORDATA ** conss
Definition: struct_reopt.h:67
static SCIP_RETCODE saveAfterDualBranchings(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool *transintoorig)
Definition: reopt.c:1158
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPreoptApplyGlbConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: reopt.c:6263
#define DEFAULT_MEM_NODES
Definition: reopt.c:45
SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
Definition: set.c:3796
SCIP_Real SCIPreoptGetSimToPrevious(SCIP_REOPT *reopt)
Definition: reopt.c:4532
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5031
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:5149
unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
Definition: tree.c:7087
internal methods for managing events
int SCIPreoptGetNLeaves(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:4829
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:954
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2193
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
internal methods for storing primal CIP solutions
static void resetStats(SCIP_REOPT *reopt)
Definition: reopt.c:3341
static SCIP_RETCODE saveAncestorBranchings(SCIP_REOPTTREE *reopttree, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_NODE *parent, unsigned int id, unsigned int parentid)
Definition: reopt.c:1712
unsigned int parentID
Definition: struct_reopt.h:88
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
static SCIP_DECL_EVENTEXEC(eventExecReopt)
Definition: reopt.c:57
internal methods for branch and bound tree
REOPT_CONSTYPE constype
Definition: struct_reopt.h:59
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11991
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:739
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7006
void SCIPreoptnodeGetSplitCons(SCIP_REOPTNODE *reoptnode, SCIP_VAR **vars, SCIP_Real *vals, REOPT_CONSTYPE *constype, int conssize, int *nvars)
Definition: reopt.c:4748
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5429
SCIP_RETCODE SCIPreoptCheckCutoff(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_EVENTTYPE eventtype, SCIP_LPSOLSTAT lpsolstat, SCIP_Bool isrootnode, SCIP_Bool isfocusnode, SCIP_Real lowerbound, int effectiverootdepth)
Definition: reopt.c:4889
SCIP_REOPTNODE * SCIPreoptGetReoptnode(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:4586
int SCIPreoptGetNImprovingSols(SCIP_REOPT *reopt)
Definition: reopt.c:4342
void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
Definition: tree.c:7097
#define EVENTHDLR_NAME
Definition: reopt.c:50
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41528
LOGICORDATA * dualconscur
Definition: struct_reopt.h:70
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10690
static SCIP_RETCODE reoptResetTree(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
Definition: reopt.c:3691
internal methods for clocks and timing issues
#define NULL
Definition: lpi_spx.cpp:130
int SCIPreoptGetNInfNodes(SCIP_REOPT *reopt)
Definition: reopt.c:3998
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:940
SCIP_RETCODE SCIPreoptGetLeaves(SCIP_REOPT *reopt, SCIP_NODE *node, unsigned int *leaves, int leavessize, int *nleaves)
Definition: reopt.c:5293
int firstrestart
Definition: struct_reopt.h:138
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:783
SCIP_Real simtofirstobj
Definition: struct_reopt.h:123
int SCIPreoptGetNCutoffReoptnodes(SCIP_REOPT *reopt)
Definition: reopt.c:3978
int reopt_maxsavednodes
Definition: struct_set.h:389
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16965
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7026
void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
Definition: tree.c:1595
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:4208
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:4893
SCIP_BOUNDTYPE * afterdualvarboundtypes
Definition: struct_reopt.h:73
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, SCIP_VAR **vars, SCIP_Real *vals, int nvars, int negbndchg)
Definition: reopt.c:3145
void SCIPreoptSetNImprovingSols(SCIP_REOPT *reopt, int nimprovingsols)
Definition: reopt.c:4352
int SCIPreoptGetNFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:3938
SCIP_RETCODE SCIPreoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:6436
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
SCIP_RETCODE SCIPconsGetVars(SCIP_CONS *cons, SCIP_SET *set, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: cons.c:5940
int SCIPreoptnodeGetNVars(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4683
SCIP_Longint lastseennode
Definition: struct_reopt.h:125
#define FALSE
Definition: def.h:53
static SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
Definition: reopt.c:115
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_RETCODE SCIPreoptAddRun(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **transvars, int ntransvars, int size)
Definition: reopt.c:4289
static SCIP_RETCODE moveChildrenUp(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, unsigned int nodeid, unsigned int parentid)
Definition: reopt.c:1368
SCIP_RETCODE SCIPreoptApplyCompression(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE **representatives, int nrepresentatives, SCIP_Bool *success)
Definition: reopt.c:5405
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:6342
SCIP_Bool updated
Definition: struct_reopt.h:41
SCIP_RETCODE SCIPsolCopy(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_SOL *sourcesol)
Definition: sol.c:334
SCIP_STAGE stage
Definition: struct_set.h:57
SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
Definition: tree.c:7056
#define TRUE
Definition: def.h:52
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE checkMemDualCons(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, int size)
Definition: reopt.c:1030
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11686
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
#define BMSfreeBlockMemoryNull(mem, ptr)
Definition: memory.h:420
SCIP_RETCODE SCIPreoptFree(SCIP_REOPT **reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
Definition: reopt.c:4094
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4626
SCIP_Real simtolastobj
Definition: struct_reopt.h:122
LOGICORDATA ** glbconss
Definition: struct_reopt.h:117
SCIP_RETCODE SCIPreoptnodeAddCons(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem, SCIP_VAR **consvars, SCIP_Real *consvals, int nvars, REOPT_CONSTYPE constype)
Definition: reopt.c:6477
void SCIPreoptResetSolMarks(SCIP_REOPT *reopt)
Definition: reopt.c:4628
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:78
SCIP_REOPTNODE ** reoptnodes
Definition: struct_reopt.h:96
SCIP_Real SCIPreoptGetOldObjCoef(SCIP_REOPT *reopt, int run, int idx)
Definition: reopt.c:4600
#define SCIPdebugMessage
Definition: pub_message.h:77
int SCIPreoptGetNDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:5217
static SCIP_RETCODE dryBranch(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool *runagain, unsigned int id)
Definition: reopt.c:3365
#define DEFAULT_MEM_DUALCONS
Definition: reopt.c:47
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
static SCIP_RETCODE soltreefreeNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SOLNODE **solnode)
Definition: reopt.c:639
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16803
static void soltreeResetMarks(SCIP_SOLNODE *node)
Definition: reopt.c:838
static SCIP_RETCODE reoptGetLeaves(SCIP_REOPT *reopt, unsigned int id, unsigned int *leaves, int leavessize, int *nleaves)
Definition: reopt.c:3643
SCIP_SOL ** prevbestsols
Definition: struct_reopt.h:115
static void deleteLastDualBndchgs(SCIP_REOPT *reopt)
Definition: reopt.c:2504
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
static void permuteRandom(SCIP_VAR **vars, SCIP_Real *vals, int nvars, unsigned int *randseed)
Definition: reopt.c:3825
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:879
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
#define BMSfreeMemory(ptr)
Definition: memory.h:100
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6014
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24936
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
int nimprovingsols
Definition: struct_reopt.h:134
#define DEFAULT_MEM_VAR
Definition: reopt.c:44
int SCIPreoptGetLastRestarts(SCIP_REOPT *reopt)
Definition: reopt.c:3928
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:1190
static SCIP_RETCODE reoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:396
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7016
static SCIP_RETCODE freeReoptTree(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:1006
int SCIPreoptGetNNodes(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:4643
#define SCIP_EVENTTYPE_NODEFEASIBLE
Definition: type_event.h:72
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:74
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:772
static SCIP_RETCODE ensureSolsSize(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int num, int runidx)
Definition: reopt.c:145
SCIP_BOUNDTYPE * varboundtypes
Definition: struct_reopt.h:72
static SCIP_RETCODE reoptSaveNewObj(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **transvars, int ntransvars)
Definition: reopt.c:3747
#define EVENTHDLR_DESC
Definition: reopt.c:51
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36232
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, unsigned int randseed, SCIP_REOPTNODE *reoptnode, unsigned int id, SCIP_Real estimate, SCIP_NODE **childnodes, int *ncreatedchilds, int *naddedconss, int childnodessize, SCIP_Bool *success)
Definition: reopt.c:5828
static SCIP_RETCODE freeSolTree(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
Definition: reopt.c:682
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5071
SCIP_RETCODE SCIPreoptSplitRoot(SCIP_REOPT *reopt, SCIP_TREE *tree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int randseed, int *ncreatedchilds, int *naddedconss)
Definition: reopt.c:5505
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1096
SCIP_RETCODE SCIPreoptGetSolsRun(SCIP_REOPT *reopt, int run, SCIP_SOL **sols, int solssize, int *nsols)
Definition: reopt.c:4396
SCIP_RETCODE SCIPreoptSaveOpenNodes(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE **leaves, int nleaves, SCIP_NODE **childs, int nchilds, SCIP_NODE **siblings, int nsiblings)
Definition: reopt.c:5354
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16470
int SCIPreoptGetNRestartsGlobal(SCIP_REOPT *reopt)
Definition: reopt.c:3888
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16483
int SCIPreoptGetFirstRestarts(SCIP_REOPT *reopt)
Definition: reopt.c:3918
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:416
int ntotallocrestarts
Definition: struct_reopt.h:136
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:892
static SCIP_RETCODE reoptnodeCheckMemory(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem, int var_mem, int child_mem, int conss_mem)
Definition: reopt.c:239
int SCIPreoptGetNTotalCutoffReoptnodes(SCIP_REOPT *reopt)
Definition: reopt.c:3988
int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4716
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:102
internal methods for storing and manipulating the main problem
void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, int *nvars, int varssize)
Definition: tree.c:7214
static SCIP_RETCODE reoptRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:3717
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
int SCIPreoptGetNSols(SCIP_REOPT *reopt)
Definition: reopt.c:4378
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:20403
static SCIP_RETCODE clearReoptnodes(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
Definition: reopt.c:968
methods for block memory pools and memory buffers
LOGICORDATA * dualconsnex
Definition: struct_reopt.h:71
static SCIP_RETCODE reopttreeCheckMemory(SCIP_REOPTTREE *reopttree, BMS_BLKMEM *blkmem)
Definition: reopt.c:208
SCIP_SOLNODE * root
Definition: struct_reopt.h:49
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:1425
SCIP_RETCODE SCIPaddReoptDualBndchg(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_Real oldbound)
Definition: scip.c:14954
static SCIP_RETCODE createReoptnode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id)
Definition: reopt.c:866
SCIP_VAR ** vars
Definition: struct_reopt.h:57
SCIP_Real * vals
Definition: struct_reopt.h:58
static int reoptGetNLeaves(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:3610
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7624
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16496
SCIP_RETCODE SCIPreoptCreate(SCIP_REOPT **reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:4029
static SCIP_RETCODE checkMemGlbCons(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, int mem)
Definition: reopt.c:1070
int * solssize
Definition: struct_reopt.h:50
SCIP_SOLTREE * soltree
Definition: struct_reopt.h:120
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE type)
Definition: tree.c:7066
int SCIPreoptGetNTotalInfNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4008
SCIP_SOLNODE * lchild
Definition: struct_reopt.h:40
internal miscellaneous methods
enum SCIP_ReoptType SCIP_REOPTTYPE
Definition: type_reopt.h:56
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:3021
SCIP_SOLNODE *** sols
Definition: struct_reopt.h:48
#define REALABS(x)
Definition: def.h:148
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:2690
int allocmemglbconss
Definition: struct_reopt.h:132
void SCIPreoptnodeInit(SCIP_REOPTNODE *reoptnode, SCIP_SET *set)
Definition: reopt.c:6385
static SCIP_RETCODE changeReopttypeOfSubtree(SCIP_REOPTTREE *reopttree, unsigned int id, SCIP_REOPTTYPE reopttype)
Definition: reopt.c:1544
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:263
static SCIP_RETCODE transformIntoOrig(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:1234
SCIP_Longint currentnode
Definition: struct_reopt.h:126
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5517
SCIP_RETCODE SCIPreoptResetDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node, BMS_BLKMEM *blkmem)
Definition: reopt.c:5727
#define DEFAULT_MEM_RUN
Definition: reopt.c:46
static SCIP_RETCODE reoptnodeReset(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:511
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:5752
static SCIP_RETCODE saveLocalConssData(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id)
Definition: reopt.c:1779
SCIP_Real ** objs
Definition: struct_reopt.h:116
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5053
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41554
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:761
#define DEFAULT_MEM_VARAFTERDUAL
Definition: reopt.c:43
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11966
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5473
unsigned int * childids
Definition: struct_reopt.h:86
SCIP_Bool reopt_shrinkinner
Definition: struct_set.h:399
SCIP_Real reopt_objsimdelay
Definition: struct_set.h:387
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:160
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:419
int SCIPreoptGetNAddedConss(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:4184
data structures and methods for collecting reoptimization information
internal methods for problem variables
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2351
int SCIPnodeGetNDualBndchgs(SCIP_NODE *node)
Definition: tree.c:7173
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
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:1621
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
int nglbrestarts
Definition: struct_reopt.h:135
SCIP_RETCODE SCIPconsGetNVars(SCIP_CONS *cons, SCIP_SET *set, int *nvars, SCIP_Bool *success)
Definition: cons.c:5976
SCIP_REOPTTREE * reopttree
Definition: struct_reopt.h:119
SCIP_SOL * SCIPreoptGetLastBestSol(SCIP_REOPT *reopt)
Definition: reopt.c:4569
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:5239
#define SCIP_Bool
Definition: def.h:50
char reopt_varorderinterdiction
Definition: struct_set.h:388
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:408
static SCIP_RETCODE reoptAddChild(SCIP_REOPTTREE *reopttree, BMS_BLKMEM *blkmem, unsigned int parentid, unsigned int childid)
Definition: reopt.c:1336
static SCIP_RETCODE getLastSavedNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node, SCIP_NODE **parent, unsigned int *parentid, int *nbndchgs)
Definition: reopt.c:1284
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:4467
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:3252
SCIP_SOLNODE * rchild
Definition: struct_reopt.h:39
SCIP_VAR ** afterdualvars
Definition: struct_reopt.h:69
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:175
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
SCIP_Bool reopt_usesplitcons
Definition: struct_set.h:403
void SCIPreoptnodeSetParentID(SCIP_REOPTNODE *reoptnode, unsigned int parentid)
Definition: reopt.c:4817
#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:921
static SCIP_RETCODE createSolTree(SCIP_SOLTREE *soltree, BMS_BLKMEM *blkmem)
Definition: reopt.c:607
void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
Definition: tree.c:7121
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:73
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:2873
#define SCIPfreeBlockMemoryNull(scip, ptr)
Definition: scip.h:20401
int SCIPreoptGetNSolsRun(SCIP_REOPT *reopt, int run)
Definition: reopt.c:4363
unsigned int reoptnodessize
Definition: struct_reopt.h:109
SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4736
void SCIPnodeGetBdChgsAfterDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int start, int *nbranchvars, int branchvarssize)
Definition: tree.c:7527
reoptsols primal heuristic
void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7361
int reopt_solvelpdiff
Definition: struct_set.h:392
int SCIPreoptGetNInfSubtrees(SCIP_REOPT *reopt)
Definition: reopt.c:4018
int reopt_savesols
Definition: struct_set.h:393
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:94
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5451
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36389
int ntotalcutoffreoptnodes
Definition: struct_reopt.h:106
static SCIP_RETCODE addNode(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_REOPTTYPE reopttype, SCIP_Bool saveafterdual, SCIP_Bool isrootnode, SCIP_Real lowerbound)
Definition: reopt.c:2011
SCIP_RETCODE SCIPreoptDeleteNode(SCIP_REOPT *reopt, SCIP_SET *set, unsigned int id, BMS_BLKMEM *blkmem)
Definition: reopt.c:5809
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:7695
SCIP_Bool reopt_sepaglbinfsubtrees
Definition: struct_set.h:396
int SCIPreoptGetNRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:3898
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36278
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11514
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
static SCIP_RETCODE saveGlobalCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, REOPT_CONSTYPE consttype)
Definition: reopt.c:2556
static int reopttreeGetNNodes(SCIP_REOPTTREE *reopttree, unsigned int id)
Definition: reopt.c:3587
static SCIP_RETCODE reoptMoveIDs(SCIP_REOPTTREE *reopttree, BMS_BLKMEM *blkmem, unsigned int id1, unsigned int id2)
Definition: reopt.c:2640
SCIP_SOLNODE * father
Definition: struct_reopt.h:38
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
int SCIPnodeGetNAddedConss(SCIP_NODE *node)
Definition: tree.c:1625
SCIP_Real SCIPreoptnodeGetLowerbound(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4726
SCIP_Bool dualfixing
Definition: struct_reopt.h:77
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:737
static SCIP_RETCODE reoptnodeResetDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:2521
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8007
SCIP_RETCODE SCIPreoptAddInfNode(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node)
Definition: reopt.c:4865
SCIP_VAR ** vars
Definition: struct_reopt.h:68
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:1979
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12078
static SCIP_RETCODE reopttreeDeleteNode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id, SCIP_Bool softreset)
Definition: reopt.c:575
SCIP_RETCODE SCIPreoptAddOptSol(SCIP_REOPT *reopt, SCIP_SOL *sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *origprimal)
Definition: reopt.c:4263
SCIP_Bool reopt_saveconsprop
Definition: struct_set.h:402
SCIP_RETCODE SCIPreoptnodeAddBndchg(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real val, SCIP_BOUNDTYPE boundtype)
Definition: reopt.c:6450
SCIP_Real reopt_objsimrootlp
Definition: struct_set.h:386
int noptsolsbyreoptsol
Definition: struct_reopt.h:130
void SCIPreoptnodeGetConss(SCIP_REOPTNODE *reoptnode, SCIP_VAR ***vars, SCIP_Real **vals, int mem, int *nconss, int *nvars)
Definition: reopt.c:4781
SCIP_RETCODE SCIPreoptnodeReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:6418
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Real * varbounds
Definition: struct_reopt.h:74
SCIP_Bool reopt_reducetofrontier
Definition: struct_set.h:401
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16648
SCIP_QUEUE * openids
Definition: struct_reopt.h:97
static SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
Definition: reopt.c:91
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5107
SCIP_Real SCIPreoptGetSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int run1, int run2, SCIP_VAR **transvars, int ntransvars)
Definition: reopt.c:4550
static SCIP_RETCODE updateConstraintPropagation(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool *transintoorig)
Definition: reopt.c:1103
#define SCIP_Real
Definition: def.h:124
#define MIN(x, y)
Definition: memory.c:63
int SCIPreoptnodeGetNDualBoundChgs(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4703
LOGICORDATA * dualcons
Definition: struct_reopt.h:118
#define BMSallocMemory(ptr)
Definition: memory.h:74
SCIP_Real * afterdualvarbounds
Definition: struct_reopt.h:75
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:82
internal methods for constraints and constraint handlers
int SCIPreoptGetNTotalPrunedNodes(SCIP_REOPT *reopt)
Definition: reopt.c:3968
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7287
int SCIPreoptGetNTotalFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:3948
int ncheckedsols
Definition: struct_reopt.h:133
static SCIP_RETCODE solnodeAddChild(BMS_BLKMEM *blkmem, SCIP_SOLNODE *father, SCIP_Bool rchild, SCIP_Bool lchild)
Definition: reopt.c:709
SCIP_RETCODE SCIPreoptAddGlbCons(SCIP_REOPT *reopt, SCIP_VAR **vars, SCIP_Real *vals, int nvars, BMS_BLKMEM *blkmem)
Definition: reopt.c:6226
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:827
SCIP_Real SCIPreoptGetSimToFirst(SCIP_REOPT *reopt)
Definition: reopt.c:4541
int reopt_forceheurrestart
Definition: struct_set.h:394
void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7398
int SCIPreoptGetNPrunedNodes(SCIP_REOPT *reopt)
Definition: reopt.c:3958
enum Reopt_ConsType REOPT_CONSTYPE
Definition: type_reopt.h:64
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7036
int SCIPreoptGetNSavedSols(SCIP_REOPT *reopt)
Definition: reopt.c:4437
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16628
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6031
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:406
common defines and data types used in all packages of SCIP
int SCIPreoptGetNTotalRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:3908
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
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:1471
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1120
void SCIPreoptSetNCheckedSols(SCIP_REOPT *reopt, int ncheckedsols)
Definition: reopt.c:4331
#define SCIP_ALLOC(x)
Definition: def.h:274
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)
SCIP_Real lowerbound
Definition: struct_reopt.h:76
SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5996
static SCIP_RETCODE collectDualInformation(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_REOPTTYPE reopttype)
Definition: reopt.c:1889
SCIP_Real SCIPreoptGetSavingtime(SCIP_REOPT *reopt)
Definition: reopt.c:6216
unsigned int reopttype
Definition: struct_reopt.h:89
SCIP_Longint lastbranched
Definition: struct_reopt.h:124
static SCIP_RETCODE reoptnodeUpdateDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:1590
int SCIPgetEffectiveRootDepth(SCIP *scip)
Definition: scip.c:36425
SCIP_SOL * SCIPreoptGetBestSolRun(SCIP_REOPT *reopt, int run)
Definition: reopt.c:4616
void SCIPnodeGetConsProps(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nconspropvars, int conspropvarssize)
Definition: tree.c:7439
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:412
int nlocrestarts
Definition: struct_reopt.h:137
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5490
SCIP_CLOCK * savingtime
Definition: struct_reopt.h:121
SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
Definition: scip.c:15567
SCIP callable library.
int SCIPreoptGetNCheckedSols(SCIP_REOPT *reopt)
Definition: reopt.c:4321
SCIP_SOL * sol
Definition: struct_reopt.h:37
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:696
int SCIPreoptnodeGetNConss(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:4693
int reopt_solvelp
Definition: struct_set.h:391
static SCIP_Real reoptSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int obj1_id, int obj2_id, SCIP_VAR **transvars, int ntransvars)
Definition: reopt.c:336
memory allocation routines