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