Scippy

SCIP

Solving Constraint Integer Programs

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