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