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