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  assert(SCIPisLE(scip, newbound, oldub));
3836  }
3837  else
3838  {
3839  newbound = reoptconsdata->vals[0] + 1.0;
3840  assert(SCIPisGE(scip, newbound, oldlb));
3841  }
3842  boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
3843  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3844 
3845  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3846  {
3847  SCIPvarAdjustLb(var, set, &newbound);
3848  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3849  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3850  }
3851  else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3852  {
3853  SCIPvarAdjustUb(var, set, &newbound);
3854  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3855  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3856  }
3857 
3858  SCIPsetDebugMsg(set, " -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
3859  boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3860  }
3861  else
3862  {
3863  SCIP_REOPTCONSDATA* reoptconsdata;
3864  SCIP_VAR** consvars;
3865  SCIP_Real consval;
3866  SCIP_BOUNDTYPE consboundtype;
3867  int nbinvars = 0;
3868  int nintvars = 0;
3869  int ncontvars = 0;
3870 
3871  reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
3872  assert(!reoptconsdata->linear);
3873  assert(reoptconsdata->vars != NULL);
3874  assert(reoptconsdata->vals != NULL);
3875  assert(reoptconsdata->boundtypes != NULL);
3876 
3877  /* allocate buffer */
3878  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reoptconsdata->nvars) );
3879 
3880  /* count number of binary, integer, and continuous variables */
3881  for( v = 0; v < reoptconsdata->nvars; v++ )
3882  {
3883  switch ( SCIPvarGetType(reoptconsdata->vars[v]) )
3884  {
3885  case SCIP_VARTYPE_BINARY:
3886  ++nbinvars;
3887  break;
3888  case SCIP_VARTYPE_IMPLINT:
3889  case SCIP_VARTYPE_INTEGER:
3890  if( SCIPisEQ(scip, SCIPvarGetLbLocal(reoptconsdata->vars[v]), 0.0)
3891  && SCIPisEQ(scip, SCIPvarGetUbLocal(reoptconsdata->vars[v]), 1.0) )
3892  ++nbinvars;
3893  else
3894  ++nintvars;
3895  break;
3897  ++ncontvars;
3898  break;
3899  default:
3900  SCIPerrorMessage("Variable <%s> has to be either binary, (implied) integer, or continuous.\n",
3901  SCIPvarGetName(reoptconsdata->vars[v]));
3902  return SCIP_INVALIDDATA;
3903  }
3904  }
3905 
3906  if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
3907  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
3908  else
3909  {
3910  assert(reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS);
3911  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
3912  }
3913 
3914  /* case 1: all variables are binary, we use a logic-or constraint. */
3915  if( reoptconsdata->nvars == nbinvars )
3916  {
3917  for( v = 0; v < reoptconsdata->nvars; v++ )
3918  {
3919  consvars[v] = reoptconsdata->vars[v];
3920  consval = reoptconsdata->vals[v];
3921  consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
3922 
3923  assert(SCIPvarIsOriginal(consvars[v]));
3924  SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
3925  assert(SCIPvarIsTransformed(consvars[v]));
3926  assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3927 
3928  if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
3929  {
3930  SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
3931  assert(SCIPvarIsNegated(consvars[v]));
3932  }
3933  }
3934 
3935  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reoptconsdata->nvars, consvars,
3937  }
3938  /* case 2: at least one variable is integer or continuous. we use a bounddisjunction constraint. */
3939  else
3940  {
3941  SCIP_Real* consvals;
3942  SCIP_BOUNDTYPE* consboundtypes;
3943 
3944  assert(nintvars > 0 || ncontvars > 0);
3945 
3946  /* alloc buffer memory */
3947  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, reoptconsdata->nvars) );
3948  SCIP_CALL( SCIPallocBufferArray(scip, &consboundtypes, reoptconsdata->nvars) );
3949 
3950  /* iterate over all variables and transform them */
3951  for( v = 0; v < reoptconsdata->nvars; v++ )
3952  {
3953  consvars[v] = reoptconsdata->vars[v];
3954  consvals[v] = reoptconsdata->vals[v];
3955  consboundtypes[v] = reoptconsdata->boundtypes[v];
3956 
3957  /* we have to switch the bounds.
3958  * case 1: integer variable with bound x <= u is transformed to u+1 <= x
3959  * and l <= x is transformed to x <= l-1
3960  * case 2: continuous variable with bound x <= u is transformed to u <= x
3961  * and l <= x is transformed to x <= l
3962  */
3963  if( SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_BINARY
3964  || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_INTEGER
3965  || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_IMPLINT )
3966  {
3967  if( consboundtypes[v] == SCIP_BOUNDTYPE_UPPER )
3968  {
3969  consvals[v] += 1.0;
3970  assert(SCIPsetIsLE(set, consvals[v], SCIPvarGetUbGlobal(consvars[v])));
3971  }
3972  else
3973  {
3974  consvals[v] -= 1.0;
3975  assert(SCIPsetIsGE(set, consvals[v], SCIPvarGetLbGlobal(consvars[v])));
3976  }
3977  }
3978 
3979  consboundtypes[v] = (SCIP_BOUNDTYPE)(1 - consboundtypes[v]); /*lint !e641*/
3980 
3981  assert(SCIPvarIsOriginal(consvars[v]));
3982  SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consvals[v], &consboundtypes[v]) );
3983  assert(SCIPvarIsTransformed(consvars[v]));
3984  assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3985  }
3986 
3987  /* create the constraints and add them to the corresponding nodes */
3988  SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, consvars, consboundtypes,
3989  consvals, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
3990 
3991  /* free buffer memory */
3992  SCIPfreeBufferArray(scip, &consboundtypes);
3993  SCIPfreeBufferArray(scip, &consvals);
3994  }
3995 
3996  SCIPsetDebugMsg(set, " -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
3997 #ifdef SCIP_DEBUG_CONSS
3998  SCIPdebugPrintCons(scip, cons, NULL);
3999 #endif
4000 
4001  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
4002  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
4003 
4004  /* free buffer */
4005  SCIPfreeBufferArray(scip, &consvars);
4006  }
4007 
4008  return SCIP_OKAY;
4009 }
4010 
4011 /** fix all bounds ad stored in dualredscur at the given node @p node_fix */
4012 static
4014  SCIP_REOPT* reopt, /**< reoptimization data structure */
4015  SCIP_SET* set, /**< global SCIP settings */
4016  SCIP_STAT* stat, /**< dynamic problem statistics */
4017  SCIP_PROB* transprob, /**< transformed problem */
4018  SCIP_PROB* origprob, /**< original problem */
4019  SCIP_TREE* tree, /**< search tree */
4020  SCIP_LP* lp, /**< current LP */
4021  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
4022  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4023  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
4024  BMS_BLKMEM* blkmem, /**< block memory */
4025  SCIP_NODE* node, /**< node corresponding to the fixed part */
4026  unsigned int id, /**< id of stored node */
4027  SCIP_Bool updatedualconss /**< update constraint representing dual bound changes */
4028  )
4029 {
4030  SCIP_REOPTTREE* reopttree;
4031  SCIP_REOPTNODE* reoptnode;
4032  int v;
4033 
4034  assert(reopt != NULL);
4035  assert(set != NULL);
4036  assert(stat != NULL);
4037  assert(transprob != NULL);
4038  assert(origprob != NULL);
4039  assert(tree != NULL);
4040  assert(lp != NULL);
4041  assert(branchcand != NULL);
4042  assert(eventqueue != NULL);
4043  assert(cliquetable != NULL);
4044  assert(node != NULL);
4045  assert(blkmem != NULL);
4046 
4047  reopttree = reopt->reopttree;
4048  assert(reopttree != NULL);
4049  assert(0 < id && id < reopttree->reoptnodessize);
4050 
4051  reoptnode = reopttree->reoptnodes[id];
4052  assert(reoptnode != NULL);
4053  assert(reoptnode->dualreds);
4054  assert(reoptnode->dualredscur != NULL);
4055 
4056  /* ensure that the arrays to store the bound changes are large enough */
4057  SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, reoptnode->nvars + reoptnode->dualredscur->nvars, 0, 0) );
4058 
4059  for( v = 0; v < reoptnode->dualredscur->nvars; v++ )
4060  {
4061  SCIP_VAR* var;
4062  SCIP_Real val;
4063  SCIP_BOUNDTYPE boundtype;
4064  SCIP_Bool bndchgd;
4065 
4066  var = reoptnode->dualredscur->vars[v];
4067  val = reoptnode->dualredscur->vals[v];
4068  boundtype = reoptnode->dualredscur->boundtypes[v];
4069 
4070  SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4071  assert(SCIPvarIsTransformedOrigvar(var));
4072 
4073  bndchgd = FALSE;
4074 
4075  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4076  && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4077  {
4078  SCIPvarAdjustLb(var, set, &val);
4079  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4080  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4081 
4082  bndchgd = TRUE;
4083  }
4084  else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4085  && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4086  {
4087  SCIPvarAdjustUb(var, set, &val);
4088  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4089  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4090 
4091  bndchgd = TRUE;
4092  }
4093  else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4094  {
4095  SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4096  return SCIP_INVALIDDATA;
4097  }
4098 #ifdef SCIP_MORE_DEBUG
4099  SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4100 #endif
4101  /* add variable and bound to branching path information, because we don't want to delete this data */
4102  if( bndchgd )
4103  {
4104  int pos;
4105  SCIP_Real constant;
4106  SCIP_Real scalar;
4107 
4108  pos = reoptnode->nvars;
4109 
4110  reoptnode->vars[pos] = var;
4111  scalar = 1.0;
4112  constant = 0.0;
4113  SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
4114  assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
4115 
4116  reoptnode->varbounds[pos] = reoptnode->dualredscur->vals[v];
4117  reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
4118  ++reoptnode->nvars;
4119  }
4120  }
4121 
4122  if( updatedualconss )
4123  {
4124  /* delete dualredscur and move dualredsnex -> dualredscur */
4125  SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
4126  }
4127 
4128  return SCIP_OKAY;
4129 }
4130 
4131 /** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
4132  * keep the first negbndchg-1 bound changes as stored in dualredscur and negate the negbndchg-th bound.
4133  */
4134 static
4136  SCIP_REOPT* reopt, /**< reoptimization data structure */
4137  SCIP_SET* set, /**< global SCIP settings */
4138  SCIP_STAT* stat, /**< dynamic problem statistics */
4139  SCIP_PROB* transprob, /**< transformed problem */
4140  SCIP_PROB* origprob, /**< original problem */
4141  SCIP_TREE* tree, /**< search tree */
4142  SCIP_LP* lp, /**< current LP */
4143  SCIP_BRANCHCAND* branchcand, /**< branching candidates */
4144  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4145  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
4146  BMS_BLKMEM* blkmem, /**< block memory */
4147  SCIP_NODE* node, /**< child node */
4148  unsigned int id, /**< id of the node */
4149  int* perm, /**< array of permuted indices */
4150  SCIP_VAR** vars, /**< variables */
4151  SCIP_Real* vals, /**< bounds */
4152  SCIP_BOUNDTYPE* boundtypes, /**< boundtypes */
4153  int nvars, /**< number of variables */
4154  int negbndchg /**< index of the variable that should negated */
4155  )
4156 {
4157  SCIP_VAR* var;
4158  SCIP_Real val;
4159  SCIP_BOUNDTYPE boundtype;
4160  int nbndchgs;
4161  int v;
4162 
4163  assert(reopt != NULL);
4164  assert(set != NULL);
4165  assert(stat != NULL);
4166  assert(transprob != NULL);
4167  assert(origprob != NULL);
4168  assert(tree != NULL);
4169  assert(lp != NULL);
4170  assert(branchcand != NULL);
4171  assert(eventqueue != NULL);
4172  assert(cliquetable != NULL);
4173  assert(node != NULL);
4174  assert(perm != NULL);
4175  assert(vars != NULL);
4176  assert(vals != NULL);
4177  assert(boundtypes != NULL);
4178  assert(nvars >= 0);
4179  assert(blkmem != NULL);
4180  assert(0 < id && id < reopt->reopttree->reoptnodessize);
4181 
4182 #ifndef NDEBUG
4183  {
4184  SCIP_REOPTTREE* reopttree;
4185  SCIP_REOPTNODE* reoptnode;
4186 
4187  reopttree = reopt->reopttree;
4188  assert(reopttree != NULL);
4189 
4190  reoptnode = reopttree->reoptnodes[id];
4191  assert(reoptnode != NULL);
4192  assert(reoptnode->dualreds);
4193  }
4194 #endif
4195 
4196  nbndchgs = MIN(negbndchg, nvars);
4197 
4198  /* change the first nbndchg-1 bounds as stored in dualredscur and negate the negbndchg-th bound */
4199  for( v = 0; v < nbndchgs; v++ )
4200  {
4201  var = vars[perm[v]];
4202  val = vals[perm[v]];
4203  boundtype = boundtypes[perm[v]];
4204 
4205  SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4206  assert(SCIPvarIsTransformedOrigvar(var));
4207 
4208  /* negate the last bound change */
4209  if( v == nbndchgs-1 )
4210  {
4211  boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
4212  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_UPPER )
4213  val = val - 1.0;
4214  else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_LOWER )
4215  val = val + 1.0;
4216  }
4217 
4218  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4219  && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4220  {
4221  SCIPvarAdjustLb(var, set, &val);
4222  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4223  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4224  }
4225  else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4226  && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4227  {
4228  SCIPvarAdjustUb(var, set, &val);
4229  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4230  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4231  }
4232  else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4233  {
4234  SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4235  return SCIP_INVALIDDATA;
4236  }
4237 #ifdef SCIP_MORE_DEBUG
4238  SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4239 #endif
4240  }
4241 
4242  return SCIP_OKAY;
4243 }
4244 
4245 /** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
4246 static
4248  SCIP* scip, /**< SCIP data structure */
4249  SCIP_REOPT* reopt, /**< reoptimization data structure */
4250  SCIP_SET* set, /**< global SCIP settings */
4251  SCIP_STAT* stat, /**< dynamic problem statistics */
4252  BMS_BLKMEM* blkmem, /**< block memory */
4253  SCIP_NODE* node, /**< node of the branch and bound tree*/
4254  unsigned int id /**< id of stored node */
4255  )
4256 {
4257  int c;
4258  char name[SCIP_MAXSTRLEN];
4259 
4260  assert(scip != NULL);
4261  assert(reopt != NULL);
4262  assert(reopt->reopttree != NULL);
4263  assert(set != NULL);
4264  assert(stat != NULL);
4265  assert(blkmem != NULL);
4266  assert(node != NULL);
4267  assert(0 < id && id < reopt->reopttree->reoptnodessize);
4268 
4269  if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
4270  return SCIP_OKAY;
4271 
4272  SCIPsetDebugMsg(set, " -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss,
4273  SCIPnodeGetNumber(node));
4274 
4275  for( c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; c++ )
4276  {
4277  SCIP_CONS* cons;
4278  SCIP_REOPTCONSDATA* reoptconsdata;
4279 
4280  reoptconsdata = reopt->reopttree->reoptnodes[id]->conss[c];
4281  assert(reoptconsdata != NULL);
4282  assert(reoptconsdata->nvars > 0);
4283  assert(reoptconsdata->varssize >= reoptconsdata->nvars);
4284 
4285  if( reoptconsdata->constype == REOPT_CONSTYPE_CUT )
4286  continue;
4287 
4288  if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
4289  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
4290  else if( reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS )
4291  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
4292  else
4293  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_unkn");
4294 
4295  if( reoptconsdata->linear )
4296  {
4297  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->vals,
4298  reoptconsdata->lhs, reoptconsdata->rhs, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4299  }
4300  else
4301  {
4302  assert(reoptconsdata->boundtypes != NULL);
4303  SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->boundtypes,
4304  reoptconsdata->vals, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4305  }
4306 #ifdef SCIP_DEBUG_CONSS
4307  SCIPdebugPrintCons(scip, cons, NULL);
4308 #endif
4309  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
4310  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
4311  }
4312 
4313  return SCIP_OKAY;
4314 }
4315 
4316 /** reset the internal statistics at the beginning of a new iteration */
4317 static
4319  SCIP_REOPT* reopt /**< reoptimization data structure */
4320  )
4321 {
4322  assert(reopt != NULL);
4323 
4324  reopt->lastbranched = -1;
4325  reopt->currentnode = -1;
4326  reopt->lastseennode = -1;
4327  reopt->reopttree->nfeasnodes = 0;
4328  reopt->reopttree->ninfnodes = 0;
4329  reopt->reopttree->nprunednodes = 0;
4330  reopt->reopttree->ncutoffreoptnodes = 0;
4331 
4332  if( reopt->dualreds != NULL )
4333  reopt->dualreds->nvars = 0;
4334 }
4335 
4336 /** check the stored bound changes of all child nodes for redundancy and infeasibility
4337  *
4338  * Due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
4339  * child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
4340  * method we remove all redundant bound changes and delete infeasible child nodes.
4341  */
4342 static
4344  SCIP_REOPT* reopt, /**< reoptimization data structure */
4345  SCIP_SET* set, /**< global SCIP settings */
4346  BMS_BLKMEM* blkmem, /**< block memory */
4347  SCIP_Bool* runagain, /**< pointer to store of this method should run again */
4348  unsigned int id /**< id of stored node */
4349  )
4350 {
4351  SCIP_REOPTNODE* reoptnode;
4352  unsigned int* cutoffchilds;
4353  int ncutoffchilds = 0;
4354  unsigned int* redchilds;
4355  int nredchilds = 0;
4356  int c;
4357 
4358  assert(reopt != NULL);
4359  assert(reopt->reopttree != NULL);
4360  assert(id < reopt->reopttree->reoptnodessize);
4361  assert(reopt->reopttree->reoptnodes != NULL);
4362  assert(reopt->reopttree->reoptnodes[id] != NULL);
4363 
4364  reoptnode = reopt->reopttree->reoptnodes[id];
4365 
4366  *runagain = FALSE;
4367 
4368  SCIPsetDebugMsg(set, "start dry branching of node at ID %u\n", id);
4369 
4370  /* allocate buffer arrays */
4371  SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
4372  SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
4373 
4374  /* iterate over all child nodes and check each bound changes
4375  * for redundancy and conflict */
4376  for( c = 0; c < reoptnode->nchilds; c++ )
4377  {
4378  SCIP_REOPTNODE* child;
4379  SCIP_Bool cutoff;
4380  SCIP_Bool redundant;
4381  int* redundantvars;
4382  int nredundantvars;
4383  int v;
4384  unsigned int childid;
4385 
4386  cutoff = FALSE;
4387  redundant = FALSE;
4388  nredundantvars = 0;
4389 
4390  childid = reoptnode->childids[c];
4391  assert(childid < reopt->reopttree->reoptnodessize);
4392  child = reopt->reopttree->reoptnodes[childid];
4393  assert(child != NULL);
4394 #ifdef SCIP_MORE_DEBUG
4395  SCIPsetDebugMsg(set, "-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
4396 #endif
4397  if( child->nvars > 0 )
4398  {
4399  /* allocate buffer memory to store the redundant variables */
4400  SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
4401 
4402  for( v = 0; v < child->nvars && !cutoff; v++ )
4403  {
4404  SCIP_VAR* transvar;
4405  SCIP_Real transval;
4406  SCIP_BOUNDTYPE transbndtype;
4407  SCIP_Real ub;
4408  SCIP_Real lb;
4409 
4410  transvar = child->vars[v];
4411  transval = child->varbounds[v];
4412  transbndtype = child->varboundtypes[v];
4413 
4414  /* transform into the transformed space */
4415  SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
4416 
4417  lb = SCIPvarGetLbLocal(transvar);
4418  ub = SCIPvarGetUbLocal(transvar);
4419 
4420  /* check for infeasibility */
4421  if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
4422  {
4423  SCIPsetDebugMsg(set, " -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
4424  SCIPvarGetName(transvar), lb, transval);
4425 
4426  cutoff = TRUE;
4427  break;
4428  }
4429 
4430  /* check for redundancy */
4431  if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
4432  {
4433  SCIPsetDebugMsg(set, " -> <%s> is already fixed to %g -> redundant bound change\n",
4434  SCIPvarGetName(transvar), lb);
4435 
4436  redundantvars[nredundantvars] = v;
4437  ++nredundantvars;
4438  }
4439  }
4440 
4441  if( !cutoff && nredundantvars > 0 )
4442  {
4443  for( v = 0; v < nredundantvars; v++ )
4444  {
4445  /* replace the redundant variable by the last stored variable */
4446  child->vars[redundantvars[v]] = child->vars[child->nvars-1];
4447  child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
4448  child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
4449  --child->nvars;
4450  }
4451  }
4452 
4453  /* free buffer memory */
4454  SCIPsetFreeBufferArray(set, &redundantvars);
4455  }
4456  else if( child->nconss == 0 )
4457  {
4458  redundant = TRUE;
4459  SCIPsetDebugMsg(set, " -> redundant node found.\n");
4460  }
4461 
4462  if( cutoff )
4463  {
4464  cutoffchilds[ncutoffchilds] = childid;
4465  ++ncutoffchilds;
4466  }
4467  else if( redundant )
4468  {
4469  redchilds[nredchilds] = childid;
4470  ++nredchilds;
4471  }
4472  }
4473 
4474  SCIPsetDebugMsg(set, "-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
4475 
4476  /* delete all nodes that can be cut off */
4477  while( ncutoffchilds > 0 )
4478  {
4479  /* delete the node and the induced subtree */
4480  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
4481 
4482  /* find the position in the childid array */
4483  c = 0;
4484  while( reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] && c < reoptnode->nchilds )
4485  ++c;
4486  assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
4487 
4488  /* replace the ID at position c by the last ID */
4489  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4490  --reoptnode->nchilds;
4491 
4492  /* decrease the number of nodes to cutoff */
4493  --ncutoffchilds;
4494  }
4495 
4496  /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
4497  while( nredchilds > 0 )
4498  {
4499  /* find the position in the childid array */
4500  c = 0;
4501  while( reoptnode->childids[c] != redchilds[nredchilds-1] && c < reoptnode->nchilds )
4502  ++c;
4503  assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
4504 
4505  /* the node is a leaf and we can cutoff them */
4506  if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
4507  {
4508  /* delete the node and the induced subtree */
4509  SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
4510 
4511  /* replace the ID at position c by the last ID */
4512  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4513  --reoptnode->nchilds;
4514 
4515  /* decrease the number of redundant nodes */
4516  --nredchilds;
4517  }
4518  else
4519  {
4520  int cc;
4521  int ncc;
4522 
4523  /* replace the ID at position c by the last ID */
4524  reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4525  --reoptnode->nchilds;
4526 
4527  ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
4528 
4529  /* check the memory */
4530  SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, 0, reoptnode->nchilds+ncc, 0) );
4531 
4532  /* add all IDs of child nodes to the current node */
4533  for( cc = 0; cc < ncc; cc++ )
4534  {
4535  reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
4536  ++reoptnode->nchilds;
4537  }
4538 
4539  /* delete the redundant node */
4540  SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
4541  SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, redchilds[nredchilds-1]) );
4542 
4543  /* decrease the number of redundant nodes */
4544  --nredchilds;
4545 
4546  /* update the flag to rerun this method */
4547  *runagain = TRUE;
4548  }
4549  }
4550 
4551  /* free buffer arrays */
4552  SCIPsetFreeBufferArray(set, &redchilds);
4553  SCIPsetFreeBufferArray(set, &cutoffchilds);
4554 
4555  return SCIP_OKAY;
4556 }
4557 
4558 /** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
4559 static
4561  SCIP_REOPTTREE* reopttree, /**< reopttree */
4562  unsigned int id /**< id of stored node */
4563  )
4564 {
4565  int nnodes = 0;
4566  int i;
4567 
4568  assert(reopttree != NULL);
4569  assert(id < reopttree->reoptnodessize);
4570 
4571  for( i = 0; i < reopttree->reoptnodes[id]->nchilds; i++ )
4572  nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
4573 
4574  return nnodes + 1;
4575 }
4576 
4577 /** returns the number of leaf nodes of the induced subtree */
4578 static
4580  SCIP_REOPT* reopt, /**< reoptimization data structure */
4581  unsigned int id /**< id of stored node */
4582  )
4583 {
4584  int i;
4585  int nleaves = 0;
4586 
4587  assert(reopt != NULL);
4588  assert(id < reopt->reopttree->reoptnodessize);
4589  assert(reopt->reopttree->reoptnodes[id] != NULL);
4590 
4591  /* iterate over all child nods and check whether they are leaves or not */
4592  for( i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++ )
4593  {
4594  unsigned int childid;
4595 
4596  childid = reopt->reopttree->reoptnodes[id]->childids[i];
4597  assert(childid < reopt->reopttree->reoptnodessize);
4598 
4599  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4600  ++nleaves;
4601  else
4602  nleaves += reoptGetNLeaves(reopt, childid);
4603  }
4604 
4605  return nleaves;
4606 }
4607 
4608 /** returns all leaves of the subtree induced by the node stored at @p id*/
4609 static
4611  SCIP_REOPT* reopt, /**< reoptimization data structure*/
4612  unsigned int id, /**< id of stored node */
4613  unsigned int* leaves, /**< array of leave nodes */
4614  int leavessize, /**< size of leaves array */
4615  int* nleaves /**< pointer to store the number of leave nodes */
4616  )
4617 {
4618  int i;
4619  int l;
4620 
4621  assert(reopt != NULL);
4622  assert(leavessize > 0 && leaves != NULL);
4623  assert((*nleaves) >= 0);
4624  assert(id < reopt->reopttree->reoptnodessize);
4625  assert(reopt->reopttree->reoptnodes[id] != NULL);
4626 
4627  for( i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++ )
4628  {
4629  unsigned int childid;
4630 
4631  assert(*nleaves <= leavessize);
4632 
4633  childid = reopt->reopttree->reoptnodes[id]->childids[i];
4634  assert(childid < reopt->reopttree->reoptnodessize);
4635 
4636  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4637  {
4638  leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
4639  ++l;
4640  ++(*nleaves);
4641  }
4642  else
4643  {
4644  int nleaves2 = 0;
4645 
4646  SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
4647  l += nleaves2;
4648  (*nleaves) += nleaves2;
4649  }
4650  }
4651 
4652  return SCIP_OKAY;
4653 }
4654 
4655 /** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
4656 static
4658  SCIP_REOPT* reopt, /**< reoptimization data structure */
4659  SCIP_SET* set, /**< global SCIP settings */
4660  BMS_BLKMEM* blkmem, /**< block memory */
4661  SCIP_Bool softreset /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
4662  )
4663 {
4664  assert(reopt != NULL);
4665  assert(set != NULL);
4666  assert(blkmem != NULL);
4667 
4668  /* clear the tree */
4669  SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
4670  assert(reopt->reopttree->nreoptnodes == 0);
4671 
4672  /* reset the dual constraint */
4673  if( reopt->dualreds != NULL )
4674  reopt->dualreds->nvars = 0;
4675 
4676  reopt->currentnode = -1;
4677 
4678  return SCIP_OKAY;
4679 }
4680 
4681 /** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
4682 static
4684  SCIP_REOPT* reopt, /**< reoptimization data structure */
4685  SCIP_SET* set, /**< global SCIP settings */
4686  BMS_BLKMEM* blkmem /**< block memory */
4687  )
4688 {
4689  assert(reopt != NULL);
4690  assert(reopt->reopttree != NULL);
4691  assert(set != NULL);
4692  assert(blkmem != NULL);
4693 
4694  /* clear the tree */
4695  SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
4696  assert(reopt->reopttree->nreoptnodes == 0);
4697 
4698  /* allocate memory for the root node */
4699  SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
4700 
4701  reopt->nglbrestarts += 1;
4702 
4703  if( reopt->firstrestart == -1 )
4704  reopt->firstrestart = reopt->run;
4705 
4706  reopt->lastrestart = reopt->run;
4707 
4708  return SCIP_OKAY;
4709 }
4710 
4711 /** save the new objective function */
4712 static
4714  SCIP_REOPT* reopt, /**< reoptimization data */
4715  SCIP_SET* set, /**< global SCIP settings */
4716  BMS_BLKMEM* blkmem, /**< block memory */
4717  SCIP_VAR** origvars, /**< original problem variables */
4718  int norigvars /**< number of original problem variables */
4719  )
4720 {
4721  int probidx;
4722  int v;
4723 
4724  assert(reopt != NULL);
4725  assert(set != NULL);
4726  assert(blkmem != NULL);
4727  assert(origvars != NULL);
4728  assert(norigvars >= 0);
4729 
4730  /* check memory */
4731  SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
4732 
4733  /* get memory and check whether we have to resize all previous objectives */
4734  if( reopt->nobjvars < norigvars )
4735  {
4736  int i;
4737  for( i = 0; i < reopt->run-1; i++ )
4738  {
4739  SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], norigvars) ); /*lint !e866*/
4740  for( v = reopt->nobjvars-1; v < norigvars; v++ )
4741  reopt->objs[i][v] = 0.0;
4742  }
4743  reopt->nobjvars = norigvars;
4744  }
4745  SCIP_ALLOC( BMSallocClearMemoryArray(&reopt->objs[reopt->run-1], reopt->nobjvars) ); /*lint !e866*/
4746 
4747  /* save coefficients */
4748  for( v = 0; v < norigvars; v++ )
4749  {
4750  assert(SCIPvarIsOriginal(origvars[v]));
4751 
4752  probidx = SCIPvarGetIndex(origvars[v]);
4753 
4754  /* it can happen that the index is greater than the number of problem variables,
4755  * i.e., not all created variables were added
4756  */
4757  if( probidx >= reopt->nobjvars )
4758  {
4759  int i;
4760  int j;
4761  int newsize = SCIPsetCalcMemGrowSize(set, probidx+1);
4762  for( i = 0; i < reopt->run; i++ )
4763  {
4764  SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], newsize) ); /*lint !e866*/
4765  for( j = reopt->nobjvars; j < newsize; j++ )
4766  reopt->objs[i][j] = 0.0;
4767  }
4768  reopt->nobjvars = newsize;
4769  }
4770  assert(0 <= probidx && probidx < reopt->nobjvars);
4771 
4772  reopt->objs[reopt->run-1][probidx] = SCIPvarGetObj(origvars[v]);
4773 
4774  /* update flag to remember if the objective function has changed */
4775  if( !reopt->objhaschanged && reopt->run >= 2
4776  && ! SCIPsetIsEQ(set, reopt->objs[reopt->run-2][probidx], reopt->objs[reopt->run-1][probidx]) )
4777  reopt->objhaschanged = TRUE;
4778 
4779  /* mark this objective as the first non empty */
4780  if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][probidx] != 0 )
4781  reopt->firstobj = reopt->run-1;
4782  }
4783 
4784  /* calculate similarity to last objective */
4785  if( reopt->run-1 >= 1 )
4786  {
4787  /* calculate similarity to last objective */
4788  reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, origvars, norigvars);
4789 
4790  if( reopt->simtolastobj == SCIP_INVALID ) /*lint !e777*/
4791  return SCIP_INVALIDRESULT;
4792 
4793  SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "new objective has similarity of %g compared to previous.\n",
4794  reopt->simtolastobj);
4795  }
4796 
4797  SCIPsetDebugMsg(set, "saved obj for run %d.\n", reopt->run);
4798 
4799  return SCIP_OKAY;
4800 }
4801 
4802 /** orders the variable by inference score */
4803 static
4805  SCIP_SET* set, /**< global SCIP settings */
4806  SCIP_STAT* stat, /**< dynamic problem statistics */
4807  int* perm, /**< array of indices that need to be permuted */
4808  SCIP_VAR** vars, /**< variable array to permute */
4809  SCIP_Real* bounds, /**< bound array to permute in the same order */
4810  SCIP_BOUNDTYPE* boundtypes, /**< boundtype array to permute in the same order */
4811  int nvars /**< number of variables */
4812  )
4813 {
4814  SCIP_Real* infscore;
4815  int v;
4816 
4817  assert(set != NULL);
4818  assert(perm != NULL);
4819  assert(vars != NULL);
4820  assert(bounds != NULL);
4821  assert(boundtypes != NULL);
4822  assert(nvars >= 0);
4823 
4824  /* allocate buffer for the scores */
4825  SCIP_CALL( SCIPsetAllocBufferArray(set, &infscore, nvars) );
4826 
4827  for( v = 0; v < nvars; v++ )
4828  {
4829  if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
4830  {
4831  infscore[v] = 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4832  + 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4833  }
4834  else
4835  {
4836  infscore[v] = 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4837  + 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4838  }
4839  }
4840 
4841  /* permute indices by inference score */
4842  SCIPsortDownRealInt(infscore, perm, nvars);
4843 
4844  /* free buffer */
4845  SCIPsetFreeBufferArray(set, &infscore);
4846 
4847  return SCIP_OKAY;
4848 }
4849 
4850 /** create a global constraint to separate the given solution */
4851 static
4853  SCIP_REOPT* reopt, /**< reoptimization data structure */
4854  BMS_BLKMEM* blkmem, /**< block memory */
4855  SCIP_SET* set, /**< global SCIP settings */
4856  SCIP_STAT* stat, /**< dynamic SCIP statistics */
4857  SCIP_SOL* sol, /**< solution to separate */
4858  SCIP_VAR** vars, /**< array of original problem variables */
4859  int nvars /**< number of original problem variables */
4860  )
4861 {
4862  SCIP_VAR** origvars;
4863  SCIP_Real* vals;
4864  int nintvars;
4865  int nbinvars;
4866  int v;
4867  int w;
4868 
4869  assert(reopt != NULL);
4870  assert(sol != NULL);
4871  assert(blkmem != NULL);
4872  assert(set != NULL);
4873  assert(stat != NULL);
4874  assert(vars != NULL);
4875  assert(nvars != 0);
4876  assert(SCIPsolIsOriginal(sol));
4877 
4878  /* allocate buffer memory */
4879  SCIP_CALL( SCIPsetAllocBufferArray(set, &origvars, nvars) );
4880  SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
4881 
4882  nbinvars = 0;
4883  nintvars = 0;
4884 
4885  /* get the solution values of the variables */
4886  for( v = 0, w = 0; v < nvars; v++ )
4887  {
4888  assert(SCIPvarIsOriginal(vars[v]));
4889  assert(nbinvars + nintvars == w);
4890 
4891  /* we do not want to create cuts for continous variables */
4892  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4893  continue;
4894 
4895  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
4896  ++nbinvars;
4898  ++nintvars;
4899 
4900  origvars[v] = vars[v];
4901  assert(origvars[v] != NULL);
4902  assert(SCIPvarIsOriginal(origvars[v]));
4903 
4904  vals[w] = SCIPsolGetVal(sol, set, stat, origvars[v]);
4905  ++w;
4906  }
4907 
4908  SCIP_CALL( addGlobalCut(reopt, blkmem, set, origvars, vals, NULL, w, nbinvars, nintvars) );
4909 
4910  /* free buffer memory */
4911  SCIPsetFreeBufferArray(set, &vals);
4912  SCIPsetFreeBufferArray(set, &origvars);
4913 
4914  return SCIP_OKAY;
4915 }
4916 
4917 /*
4918  * public methods
4919  */
4920 
4921 /* ---------------- methods of general reoptimization ---------------- */
4922 
4923 /* In debug mode, the following methods are implemented as function calls to ensure
4924  * type validity.
4925  * In optimized mode, the methods are implemented as defines to improve performance.
4926  * However, we want to have them in the library anyways, so we have to undef the defines.
4927  */
4928 
4929 #undef SCIPreoptGetNRestartsGlobal
4930 #undef SCIPreoptGetNRestartsLocal
4931 #undef SCIPreoptGetNTotalRestartsLocal
4932 #undef SCIPreoptGetFirstRestarts
4933 #undef SCIPreoptGetLastRestarts
4934 #undef SCIPreoptGetNFeasNodes
4935 #undef SCIPreoptGetNTotalFeasNodes
4936 #undef SCIPreoptGetNPrunedNodes
4937 #undef SCIPreoptGetNTotalPrunedNodes
4938 #undef SCIPreoptGetNCutoffReoptnodes
4939 #undef SCIPreoptGetNTotalCutoffReoptnodes
4940 #undef SCIPreoptGetNInfNodes
4941 #undef SCIPreoptGetNTotalInfNodes
4942 #undef SCIPreoptGetNInfSubtrees
4943 
4944 
4945 /** returns the number of global restarts */
4947  SCIP_REOPT* reopt /**< reoptimization data structure */
4948  )
4949 {
4950  assert(reopt != NULL);
4951 
4952  return reopt->nglbrestarts;
4953 }
4954 
4955 /** returns the number of local restarts in the current run */
4957  SCIP_REOPT* reopt /**< reoptimization data structure */
4958  )
4959 {
4960  assert(reopt != NULL);
4961 
4962  return reopt->nlocrestarts;
4963 }
4964 
4965 /** returns the number of local restarts over all runs */
4967  SCIP_REOPT* reopt /**< reoptimization data structure */
4968  )
4969 {
4970  assert(reopt != NULL);
4971 
4972  return reopt->ntotallocrestarts;
4973 }
4974 
4975 /** returns the number of iteration with the first global restarts */
4977  SCIP_REOPT* reopt /**< reoptimization data structure */
4978  )
4979 {
4980  assert(reopt != NULL);
4981 
4982  return reopt->firstrestart;
4983 }
4984 
4985 /** returns the number of iteration with the last global restarts */
4987  SCIP_REOPT* reopt /**< reoptimization data structure */
4988  )
4989 {
4990  assert(reopt != NULL);
4991 
4992  return reopt->lastrestart;
4993 }
4994 
4995 /** returns the number of stored nodes providing an improving feasible LP solution in the current run */
4997  SCIP_REOPT* reopt /**< reoptimization data structure */
4998  )
4999 {
5000  assert(reopt != NULL);
5001 
5002  return reopt->reopttree->nfeasnodes;
5003 }
5004 
5005 /** returns the number of stored nodes providing an improving feasible LP solution over all runs */
5007  SCIP_REOPT* reopt /**< reoptimization data structure */
5008  )
5009 {
5010  assert(reopt != NULL);
5011 
5012  return reopt->reopttree->ntotalfeasnodes;
5013 }
5014 
5015 /** returns the number of stored nodes that exceeded the cutoff bound in the current run */
5017  SCIP_REOPT* reopt /**< reoptimization data structure */
5018  )
5019 {
5020  assert(reopt != NULL);
5021 
5022  return reopt->reopttree->nprunednodes;
5023 }
5024 
5025 /** returns the number of stored nodes that exceeded the cutoff bound over all runs */
5027  SCIP_REOPT* reopt /**< reoptimization data structure */
5028  )
5029 {
5030  assert(reopt != NULL);
5031 
5032  return reopt->reopttree->ntotalprunednodes;
5033 }
5034 
5035 /** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
5037  SCIP_REOPT* reopt /**< reoptimization data structure */
5038  )
5039 {
5040  assert(reopt != NULL);
5041 
5042  return reopt->reopttree->ncutoffreoptnodes;
5043 }
5044 
5045 /** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
5047  SCIP_REOPT* reopt /**< reoptimization data structure */
5048  )
5049 {
5050  assert(reopt != NULL);
5051 
5052  return reopt->reopttree->ntotalcutoffreoptnodes;
5053 }
5054 
5055 /** returns the number of stored nodes with an infeasible LP in the current run */
5057  SCIP_REOPT* reopt /**< reoptimization data structure */
5058  )
5059 {
5060  assert(reopt != NULL);
5061 
5062  return reopt->reopttree->ninfnodes;
5063 }
5064 
5065 /** returns the number of stored nodes with an infeasible LP over all runs */
5067  SCIP_REOPT* reopt /**< reoptimization data structure */
5068  )
5069 {
5070  assert(reopt != NULL);
5071 
5072  return reopt->reopttree->ntotalinfnodes;
5073 }
5074 
5075 /** constructor for the reoptimization data */
5077  SCIP_REOPT** reopt, /**< pointer to reoptimization data structure */
5078  SCIP_SET* set, /**< global SCIP settings */
5079  BMS_BLKMEM* blkmem /**< block memory */
5080  )
5081 {
5082  SCIP_EVENTHDLR* eventhdlr;
5083  int i;
5084 
5085  assert(reopt != NULL);
5086 
5087  SCIP_ALLOC( BMSallocMemory(reopt) );
5088  (*reopt)->runsize = DEFAULT_MEM_RUN;
5089  (*reopt)->run = 0;
5090  (*reopt)->simtolastobj = -2.0;
5091  (*reopt)->simtofirstobj = -2.0;
5092  (*reopt)->firstobj = -1;
5093  (*reopt)->currentnode = -1;
5094  (*reopt)->lastbranched = -1;
5095  (*reopt)->dualreds = NULL;
5096  (*reopt)->glbconss = NULL;
5097  (*reopt)->nglbconss = 0;
5098  (*reopt)->allocmemglbconss = 0;
5099  (*reopt)->ncheckedsols = 0;
5100  (*reopt)->nimprovingsols = 0;
5101  (*reopt)->noptsolsbyreoptsol = 0;
5102  (*reopt)->nglbrestarts = 0;
5103  (*reopt)->nlocrestarts = 0;
5104  (*reopt)->ntotallocrestarts = 0;
5105  (*reopt)->firstrestart = -1;
5106  (*reopt)->lastrestart = 0;
5107  (*reopt)->nobjvars = 0;
5108  (*reopt)->objhaschanged = FALSE;
5109  (*reopt)->consadded = FALSE;
5110  (*reopt)->addedconss = NULL;
5111  (*reopt)->naddedconss = 0;
5112  (*reopt)->addedconsssize = 0;
5113  (*reopt)->glblb = NULL;
5114  (*reopt)->glbub = NULL;
5115  (*reopt)->nactiveconss = 0;
5116  (*reopt)->nmaxactiveconss = 0;
5117  (*reopt)->activeconss = NULL;
5118  (*reopt)->activeconssset = NULL;
5119 
5120  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize) );
5121  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
5122  SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
5123 
5124  for( i = 0; i < (*reopt)->runsize; i++ )
5125  {
5126  (*reopt)->objs[i] = NULL;
5127  (*reopt)->prevbestsols[i] = NULL;
5128  (*reopt)->varhistory[i] = NULL;
5129  }
5130 
5131  /* clocks */
5132  SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
5133 
5134  /* create and initialize SCIP_SOLTREE */
5135  SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
5136  SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
5137 
5138  /* create and initialize SCIP_REOPTTREE */
5139  SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
5140  SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
5141 
5142  /* create a random number generator */
5143  SCIP_CALL( SCIPrandomCreate(&(*reopt)->randnumgen, blkmem, (unsigned int)SCIPsetInitializeRandomSeed(set, DEFAULT_RANDSEED)) );
5144 
5145  /* create event handler for node events */
5146  eventhdlr = NULL;
5147 
5148  /* include event handler into SCIP */
5150  eventInitsolReopt, eventExitsolReopt, NULL, eventExecReopt, NULL) );
5151  SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
5152  assert(eventhdlr != NULL);
5153 
5154  return SCIP_OKAY;
5155 }
5156 
5157 /* release all variables and constraints captured during reoptimization */
5159  SCIP_REOPT* reopt, /**< pointer to reoptimization data structure */
5160  SCIP_SET* set, /**< global SCIP settings */
5161  BMS_BLKMEM* blkmem /**< block memory */
5162  )
5163 {
5164  /* release all added constraints and free the data */
5165  if( reopt->addedconss != NULL )
5166  {
5167  int c;
5168  for( c = 0; c < reopt->naddedconss; c++)
5169  {
5170  assert(reopt->addedconss[c] != NULL);
5171 
5172  SCIP_CALL( SCIPconsRelease(&reopt->addedconss[c], blkmem, set) );
5173  }
5174 
5175  BMSfreeBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize);
5176  reopt->naddedconss = 0;
5177  reopt->addedconsssize = 0;
5178  }
5179 
5180  SCIP_CALL( cleanActiveConss(reopt, set, blkmem) );
5181 
5182  return SCIP_OKAY;
5183 }
5184 
5185 /** frees reoptimization data */
5187  SCIP_REOPT** reopt, /**< reoptimization data structure */
5188  SCIP_SET* set, /**< global SCIP settings */
5189  SCIP_PRIMAL* origprimal, /**< original primal */
5190  BMS_BLKMEM* blkmem /**< block memory */
5191  )
5192 {
5193  assert(reopt != NULL);
5194  assert(*reopt != NULL);
5195  assert(set != NULL);
5196  assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
5197  assert(blkmem != NULL);
5198 
5199  /* free random number generator */
5200  SCIPrandomFree(&(*reopt)->randnumgen, blkmem);
5201 
5202  /* free reopttree */
5203  SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
5204 
5205  /* free solutions */
5206  if( set->stage >= SCIP_STAGE_PROBLEM )
5207  {
5208  int p;
5209  for( p = (*reopt)->run-1; p >= 0; p-- )
5210  {
5211  if( (*reopt)->soltree->sols[p] != NULL )
5212  {
5213  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
5214  (*reopt)->soltree->sols[p] = NULL;
5215  }
5216 
5217  /* we have to free all optimal solution separatly, because those solutions are not stored in the
5218  * solution reopt_sepabestsol = TRUE
5219  */
5220  if( set->reopt_sepabestsol && (*reopt)->prevbestsols[p] != NULL )
5221  {
5222  SCIP_CALL( SCIPsolFree(&(*reopt)->prevbestsols[p], blkmem, origprimal) );
5223  }
5224 
5225  if( (*reopt)->objs[p] != NULL )
5226  {
5227  BMSfreeMemoryArray(&(*reopt)->objs[p]);
5228  }
5229  }
5230  }
5231 
5232  /* free solution tree */
5233  SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
5234 
5235  if( (*reopt)->dualreds != NULL )
5236  {
5237  if( (*reopt)->dualreds->varssize > 0 )
5238  {
5239  assert(!(*reopt)->dualreds->linear);
5240 
5241  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->boundtypes, (*reopt)->dualreds->varssize);
5242  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vals, (*reopt)->dualreds->varssize);
5243  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vars, (*reopt)->dualreds->varssize);
5244  BMSfreeBlockMemory(blkmem, &(*reopt)->dualreds);
5245  (*reopt)->dualreds = NULL;
5246  }
5247  }
5248 
5249  if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
5250  {
5251  int c;
5252 
5253  /* free all constraint */
5254  for( c = 0; c < (*reopt)->allocmemglbconss; c++ )
5255  {
5256  if( (*reopt)->glbconss[c] != NULL )
5257  {
5258  if( (*reopt)->glbconss[c]->varssize > 0 )
5259  {
5260  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->boundtypes, (*reopt)->glbconss[c]->varssize);
5261  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
5262  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
5263  (*reopt)->glbconss[c]->varssize = 0;
5264  }
5265  BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
5266  --(*reopt)->nglbconss;
5267  }
5268  }
5269  assert((*reopt)->nglbconss == 0);
5270 
5271  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
5272  (*reopt)->allocmemglbconss = 0;
5273  }
5274 
5275  /* clocks */
5276  SCIPclockFree(&(*reopt)->savingtime);
5277 
5278  /* the hashmap need not to be exist, e.g., if the problem was solved during presolving */
5279  if( (*reopt)->activeconssset != NULL )
5280  {
5281  SCIPhashsetFree(&(*reopt)->activeconssset, blkmem);
5282  }
5283  BMSfreeBlockMemoryArrayNull(blkmem, &(*reopt)->activeconss, (*reopt)->nmaxactiveconss);
5284 
5285  if( (*reopt)->glblb != NULL )
5286  {
5287  SCIPhashmapFree(&(*reopt)->glblb);
5288  SCIPhashmapFree(&(*reopt)->glbub);
5289  (*reopt)->glblb = NULL;
5290  (*reopt)->glbub = NULL;
5291  }
5292  else
5293  assert((*reopt)->glbub == NULL);
5294 
5295  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize);
5296  BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
5297  BMSfreeMemoryArray(&(*reopt)->objs);
5298  BMSfreeMemory(reopt);
5299 
5300  return SCIP_OKAY;
5301 }
5302 
5303 /** returns the number of constraints added by the reoptimization plug-in */
5305  SCIP_REOPT* reopt, /**< reoptimization data structure */
5306  SCIP_NODE* node /**< node of the search tree */
5307  )
5308 {
5309  unsigned int id;
5310 
5311  assert(reopt != NULL);
5312  assert(node != NULL);
5313 
5314  id = SCIPnodeGetReoptID(node);
5315  assert(id < reopt->reopttree->reoptnodessize);
5316 
5317  /* set the id to -1 if the node is not part of the reoptimization tree */
5318  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5319  return SCIPnodeGetNAddedConss(node);
5320 
5321  if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
5322  return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
5323  else
5324  return SCIPnodeGetNAddedConss(node);
5325 }
5326 
5327 /** add a solution to the solution tree */
5329  SCIP_REOPT* reopt, /**< reoptimization data */
5330  SCIP_SET* set, /**< global SCIP settings */
5331  SCIP_STAT* stat, /**< dynamic problem statistics */
5332  SCIP_PRIMAL* origprimal, /**< original primal */
5333  BMS_BLKMEM* blkmem, /**< block memory */
5334  SCIP_SOL* sol, /**< solution to add */
5335  SCIP_Bool bestsol, /**< is the current solution an optimal solution? */
5336  SCIP_Bool* added, /**< pointer to store the information if the soltion was added */
5337  SCIP_VAR** vars, /**< variable array */
5338  int nvars, /**< number of variables */
5339  int run /**< number of the current run (1,2,...) */
5340  )
5341 {
5342  SCIP_SOLNODE* solnode = NULL;
5343  SCIP_HEUR* heur;
5344  int insertpos;
5345 
5346  assert(reopt != NULL);
5347  assert(set != NULL);
5348  assert(sol != NULL);
5349  assert(run > 0);
5350 
5351  assert(reopt->soltree->sols[run-1] != NULL);
5352 
5353  /* if the solution was found by reoptsols the solutions is already stored */
5354  heur = SCIPsolGetHeur(sol);
5355  if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
5356  ++reopt->noptsolsbyreoptsol;
5357  else if( bestsol )
5358  reopt->noptsolsbyreoptsol = 0;
5359 
5360  /* check memory */
5361  SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1]+1, run-1) );
5362 
5363  /* add solution to solution tree */
5364  SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
5365 
5366  if( (*added) )
5367  {
5368  assert(solnode != NULL);
5369 
5370  /* add solution */
5371  insertpos = reopt->soltree->nsols[run-1];
5372  reopt->soltree->sols[run-1][insertpos] = solnode;
5373  ++reopt->soltree->nsols[run-1];
5374  assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
5375  }
5376 
5377  return SCIP_OKAY;
5378 }
5379 
5380 /** we want to store the optimal solution of each run in a separate array */
5382  SCIP_REOPT* reopt, /**< reoptimization data structure */
5383  SCIP_SOL* sol, /**< solution to add */
5384  BMS_BLKMEM* blkmem, /**< block memory */
5385  SCIP_SET* set, /**< global SCIP settings */
5386  SCIP_STAT* stat, /**< dynamic problem statistics */
5387  SCIP_PRIMAL* origprimal, /**< original primal */
5388  SCIP_VAR** vars, /**< original problem variables */
5389  int nvars /**< number of original problem variables */
5390  )
5391 {
5392  /* cppcheck-suppress unassignedVariable */
5393  SCIP_SOL* solcopy;
5394 
5395  assert(reopt != NULL);
5396  assert(reopt->run-1 >= 0);
5397  assert(sol != NULL);
5398  assert(blkmem != NULL);
5399  assert(set != NULL);
5400  assert(stat != NULL);
5401  assert(origprimal != NULL);
5402 
5403  SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
5404  reopt->prevbestsols[reopt->run-1] = solcopy;
5405 
5406  /* store a global constraint that cutsoff the solution */
5407  if( set->reopt_sepabestsol )
5408  {
5409  SCIP_CALL( separateSolution(reopt, blkmem, set, stat, sol, vars, nvars) );
5410  }
5411 
5412  return SCIP_OKAY;
5413 }
5414 
5415 /** add a new iteration after changing the objective function */
5417  SCIP_REOPT* reopt, /**< reoptimization data sturcture */
5418  SCIP_SET* set, /**< global SCIP settings */
5419  BMS_BLKMEM* blkmem, /**< block memory */
5420  SCIP_VAR** origvars, /**< original problem variables */
5421  int norigvars, /**< number of original variables */
5422  int size /**< number of expected solutions */
5423  )
5424 {
5425  assert(reopt != NULL);
5426  assert(set != NULL);
5427  assert(blkmem != NULL);
5428  assert(origvars != NULL);
5429 
5430  /* increase number of runs */
5431  ++reopt->run;
5432 
5433  /* check memory */
5434  SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
5435 
5436  /* allocate memory */
5437  reopt->soltree->solssize[reopt->run-1] = size;
5438  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
5439 
5440  /* reset flag */
5441  reopt->objhaschanged = FALSE;
5442 
5443  /* save the objective function */
5444  SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, origvars, norigvars) );
5445 
5446  resetStats(reopt);
5447 
5448  return SCIP_OKAY;
5449 }
5450 
5451 /** get the number of checked solutions during the reoptimization process */
5453  SCIP_REOPT* reopt /**< reoptimization data structure */
5454  )
5455 {
5456  assert(reopt != NULL);
5457 
5458  return reopt->ncheckedsols;
5459 }
5460 
5461 /** update the number of checked solutions during the reoptimization process */
5463  SCIP_REOPT* reopt, /**< reoptimization data structure */
5464  int ncheckedsols /**< number of updated solutions */
5465  )
5466 {
5467  assert(reopt != NULL);
5468 
5469  reopt->ncheckedsols += ncheckedsols;
5470 }
5471 
5472 /** get the number of checked solutions during the reoptimization process */
5474  SCIP_REOPT* reopt /**< reoptimization data structure */
5475  )
5476 {
5477  assert(reopt != NULL);
5478 
5479  return reopt->nimprovingsols;
5480 }
5481 
5482 /** update the number of checked solutions during the reoptimization process */
5484  SCIP_REOPT* reopt, /**< reoptimization data structure */
5485  int nimprovingsols /**< number of improving solutions */
5486  )
5487 {
5488  assert(reopt != NULL);
5489 
5490  reopt->nimprovingsols += nimprovingsols;
5491 }
5492 
5493 /** returns number of solutions stored in the solution tree of a given run */
5495  SCIP_REOPT* reopt, /**< reoptimization data structure */
5496  int run /**< number of the run (1,2,..) */
5497  )
5498 {
5499  assert(reopt != NULL);
5500  assert(0 < run && run <= reopt->runsize);
5501 
5502  if( reopt->soltree->sols[run-1] == NULL )
5503  return 0;
5504  else
5505  return reopt->soltree->nsols[run-1];
5506 }
5507 
5508 /** returns number of all solutions of all runs */
5510  SCIP_REOPT* reopt /**< reoptimization data structure */
5511  )
5512 {
5513  int nsols = 0;
5514  int r;
5515 
5516  assert(reopt != NULL);
5517 
5518  for( r = 0; r < reopt->run; r++)
5519  nsols += reopt->soltree->nsols[r];
5520 
5521  return nsols;
5522 }
5523 
5524 /** return the stored solutions of a given run */
5526  SCIP_REOPT* reopt, /**< reoptimization data structure */
5527  int run, /**< number of the run (1,2,...) */
5528  SCIP_SOL** sols, /**< array of solutions to fill */
5529  int solssize, /**< length of the array */
5530  int* nsols /**< pointer to store the number of added solutions */
5531  )
5532 {
5533  int s;
5534 
5535  assert(reopt != NULL);
5536  assert(run > 0 && run <= reopt->run);
5537  assert(sols != NULL);
5538 
5539  assert(solssize > 0);
5540  assert(nsols != NULL);
5541  *nsols = 0;
5542 
5543  for( s = 0; s < reopt->soltree->nsols[run-1]; s++ )
5544  {
5545  if( !reopt->soltree->sols[run-1][s]->updated )
5546  ++(*nsols);
5547  }
5548 
5549  if( solssize < (*nsols) )
5550  return SCIP_OKAY;
5551 
5552  (*nsols) = 0;
5553  for( s = 0; s < reopt->soltree->nsols[run-1]; s++ )
5554  {
5555  if( !reopt->soltree->sols[run-1][s]->updated )
5556  {
5557  sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
5558  reopt->soltree->sols[run-1][s]->updated = TRUE;
5559  ++(*nsols);
5560  }
5561  }
5562 
5563  return SCIP_OKAY;
5564 }
5565 
5566 /** returns the number of saved solutions overall runs */
5568  SCIP_REOPT* reopt /**< reoptimization data structure */
5569  )
5570 {
5571  int nsavedsols = 0;
5572 
5573  assert(reopt != NULL);
5574  assert(reopt->soltree->root != NULL);
5575 
5576  if( reopt->soltree->root->child != NULL )
5577  nsavedsols = soltreeNInducedSols(reopt->soltree->root);
5578 
5579  return nsavedsols;
5580 }
5581 
5582 /** check if the reoptimization process should be (locally) restarted.
5583  *
5584  * First, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
5585  * the similarity again. we trigger a restart if
5586  * 1. the objective function has changed too much
5587  * 2. the number of stored nodes is exceeded
5588  * 3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
5589  * prove the optimality and this can be probably faster by solving from scratch)
5590  *
5591  * If the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
5592  * that are already fixed by bounding.
5593  */
5595  SCIP_REOPT* reopt, /**< reoptimization data structure */
5596  SCIP_SET* set, /**< global SCIP settings */
5597  BMS_BLKMEM* blkmem, /**< block memory */
5598  SCIP_NODE* node, /**< current node of the branch and bound tree (or NULL) */
5599  SCIP_VAR** transvars, /**< transformed problem variables */
5600  int ntransvars, /**< number of transformed problem variables */
5601  SCIP_Bool* restart /**< pointer to store if the reoptimization process should be restarted */
5602  )
5603 {
5604  SCIP_Real sim = 1.0;
5605 
5606  assert(reopt != NULL);
5607  assert(set != NULL);
5608  assert(blkmem != NULL);
5609  assert(transvars != NULL);
5610  assert(ntransvars >= 0);
5611  assert(restart != NULL);
5612 
5613  *restart = FALSE;
5614 
5615  /* check if the whole reoptimization process should start from scratch */
5616  if( node == NULL )
5617  {
5618  /* compute the similarity to the objective function of the first run after restarting */
5619  if( reopt->run > 1 && set->reopt_objsimdelay > -1.0 )
5620  {
5621  sim = reoptSimilarity(reopt, set, reopt->run-1, MAX(0, reopt->lastrestart-1), transvars, ntransvars);
5622 
5623  if( sim == SCIP_INVALID ) /*lint !e777*/
5624  return SCIP_INVALIDRESULT;
5625  }
5626 
5627  /* check similarity */
5628  if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
5629  {
5630  SCIPsetDebugMsg(set, "-> restart reoptimization (objective functions are not similar enough)\n");
5631  *restart = TRUE;
5632  }
5633  /* check size of the reoptimization tree */
5634  else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
5635  {
5636  SCIPsetDebugMsg(set, "-> restart reoptimization (node limit reached)\n");
5637  *restart = TRUE;
5638  }
5639  /* check if the tree was only needed to prove optimality */
5640  else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
5641  {
5642  SCIPsetDebugMsg(set, "-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
5643  reopt->noptsolsbyreoptsol);
5644  reopt->noptsolsbyreoptsol = 0;
5645  *restart = TRUE;
5646  }
5647 
5648  if( *restart )
5649  {
5650  /* trigger a restart */
5651  SCIP_CALL( reoptRestart(reopt, set, blkmem) );
5652  }
5653  }
5654  /* check for a local restart, ie, start the solving process of an inner node from scatch */
5655  else
5656  {
5657  SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
5658  }
5659  return SCIP_OKAY;
5660 }
5661 
5662 /** returns the similarity to the previous objective function, if no exist return -2.0 */
5664  SCIP_REOPT* reopt /**< reoptimization data structure */
5665  )
5666 {
5667  assert(reopt != NULL);
5668  return reopt->simtolastobj;
5669 }
5670 
5671 /** returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
5673  SCIP_REOPT* reopt /**< reoptimization data structure */
5674  )
5675 {
5676  assert(reopt != NULL);
5677  return reopt->simtofirstobj;
5678 }
5679 
5680 /** return the similarity between two of objective functions of two given runs */
5682  SCIP_REOPT* reopt, /**< reoptimization data structure */
5683  SCIP_SET* set, /**< global SCIP settings */
5684  int run1, /**< number of the first run */
5685  int run2, /**< number of the second run */
5686  SCIP_VAR** origvars, /**< original problem variables */
5687  int norigvars /**< number of original problem variables */
5688  )
5689 {
5690  assert(reopt != NULL);
5691  assert(run1 > 0 && run1 <= reopt->run);
5692  assert(run2 > 0 && run2 <= reopt->run);
5693  assert(origvars != NULL);
5694  assert(norigvars >= 0);
5695 
5696  return reoptSimilarity(reopt, set, run1-1, run2-1, origvars, norigvars);
5697 }
5698 
5699 /** returns the best solution of the last run */
5701  SCIP_REOPT* reopt /**< reoptimization data structure */
5702  )
5703 {
5704  assert(reopt != NULL);
5705  assert(reopt->prevbestsols != NULL);
5706 
5707  if( reopt->run-2 < 0 )
5708  return NULL;
5709  else
5710  return reopt->prevbestsols[reopt->run-2];
5711 }
5712 
5713 /** returns the node of the reoptimization tree corresponding to the unique @p id */
5715  SCIP_REOPT* reopt, /**< reoptimization data structure */
5716  unsigned int id /**< unique id */
5717  )
5718 {
5719  assert(reopt != NULL);
5720  assert(reopt->reopttree != NULL);
5721  assert(id < reopt->reopttree->reoptnodessize);
5722  assert(reopt->reopttree->reoptnodes[id] != NULL);
5723 
5724  return reopt->reopttree->reoptnodes[id];
5725 }
5726 
5727 /** returns the coefficient of variable with index @p idx in run @p run */
5729  SCIP_REOPT* reopt, /**< reoptimization data structure */
5730  int run, /**< number of the run (1,2,...) */
5731  int idx /**< index of original variable */
5732  )
5733 {
5734  assert(reopt != NULL);
5735  assert(0 < run && run <= reopt->runsize);
5736 
5737  return reopt->objs[run-1][idx];
5738 }
5739 
5740 /** return the best solution of a given run.
5741  *
5742  * @note the returned solution is part of the original space.
5743  */
5745  SCIP_REOPT* reopt, /**< reoptimization data structure */
5746  int run /**< number of the run (1,2,...) */
5747  )
5748 {
5749  assert(reopt != NULL);
5750  assert(0 < run && run <= reopt->run);
5751 
5752  return reopt->prevbestsols[run-1];
5753 }
5754 
5755 /** reset solving specific parameters */
5757  SCIP_REOPT* reopt, /**< reoptimization data structure */
5758  SCIP_SET* set, /**< global SCIP settings */
5759  BMS_BLKMEM* blkmem /**< block memory */
5760  )
5761 {
5762  int c;
5763 
5764  assert(reopt != NULL);
5765  assert(set != NULL);
5766  assert(blkmem != NULL);
5767 
5768  /* clean addedconss array */
5769  for( c = 0; c < reopt->naddedconss; c++)
5770  {
5771  SCIP_CONS* cons;
5772 
5773  cons = reopt->addedconss[c];
5774  assert(cons != NULL);
5775 
5776 #ifdef SCIP_MORE_DEBUG
5777  SCIPsetDebugMsg(set, "release cons <%s> from reoptimization data\n", SCIPconsGetName(cons));
5778 #endif
5779 
5780  SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5781  reopt->addedconss[c] = NULL;
5782  }
5783 
5784  reopt->naddedconss = 0;
5785  reopt->consadded = FALSE;
5786  reopt->objhaschanged = FALSE;
5787 
5788  return SCIP_OKAY;
5789 }
5790 
5791 /** reset marks of stored solutions to not updated */
5793  SCIP_REOPT* reopt /**< reoptimization data structure */
5794  )
5795 {
5796  SCIP_SOLNODE* child;
5797 
5798  assert(reopt != NULL);
5799  assert(reopt->soltree != NULL);
5800  assert(reopt->soltree->root != NULL);
5801 
5802  child = reopt->soltree->root->child;
5803 
5804  /* traverse through the list */
5805  while( child != NULL )
5806  {
5807  soltreeResetMarks(child);
5808  child = child->sibling;
5809  }
5810 }
5811 
5812 /** returns the number of stored nodes in the subtree induced by @p node */
5814  SCIP_REOPT* reopt, /**< reoptimization data structure */
5815  SCIP_NODE* node /**< node of the search tree */
5816  )
5817 {
5818  unsigned int id;
5819 
5820  assert(reopt != NULL);
5821 
5822  if( node == NULL || SCIPnodeGetDepth(node) == 0 )
5823  return reopt->reopttree->nreoptnodes;
5824 
5825  id = SCIPnodeGetReoptID(node);
5826  assert(id < reopt->reopttree->reoptnodessize);
5827 
5828  /* set the id to -1 if the node is not part of the reoptimization tree */
5829  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5830  return 0;
5831 
5832  assert(0 < id && id < reopt->reopttree->reoptnodessize);
5833 
5834  return reopttreeGetNNodes(reopt->reopttree, id);
5835 }
5836 
5837 /* ---------------- methods of general reoptimization nodes ---------------- */
5838 
5839 /** In debug mode, the following methods are implemented as function calls to ensure
5840  * type validity.
5841  * In optimized mode, the methods are implemented as defines to improve performance.
5842  * However, we want to have them in the library anyways, so we have to undef the defines.
5843  */
5844 
5845 #undef SCIPreoptnodeGetNVars
5846 #undef SCIPreoptnodeGetNConss
5847 #undef SCIPreoptnodeGetNDualBoundChgs
5848 #undef SCIPreoptnodeGetNChildren
5849 #undef SCIPreoptnodeGetLowerbound
5850 #undef SCIPreoptnodeGetType
5851 
5852 /** returns the number of bound changes stored in the reopttree at ID id */
5854  SCIP_REOPTNODE* reoptnode /**< node of the reopttree */
5855  )
5856 {
5857  assert(reoptnode != NULL);
5858 
5859  return reoptnode->nvars + reoptnode->nafterdualvars;
5860 }
5861 
5862 /** returns the number of bound changes at the node stored at ID id */
5864  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5865  )
5866 {
5867  assert(reoptnode != NULL);
5868 
5869  return reoptnode->nconss;
5870 }
5871 
5872 /** returns the number of stored bound changes based on dual information in the reopttree at ID id */
5874  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5875  )
5876 {
5877  assert(reoptnode != NULL);
5878 
5879  if( reoptnode->dualredscur == NULL )
5880  return 0;
5881  else
5882  return reoptnode->dualredscur->nvars;
5883 }
5884 
5885 /** returns the number of child nodes of @p reoptnode */
5887  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5888  )
5889 {
5890  assert(reoptnode != NULL);
5891 
5892  return reoptnode->nchilds;
5893 }
5894 
5895 /** return the lower bound stored at @p ID id */
5897  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5898  )
5899 {
5900  assert(reoptnode != NULL);
5901 
5902  return reoptnode->lowerbound;
5903 }
5904 
5905 /** returns the type of the @p reoptnode */
5907  SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5908  )
5909 {
5910  assert(reoptnode != NULL);
5911 
5912  return (SCIP_REOPTTYPE)reoptnode->reopttype;
5913 }
5914 
5915 /** returns all added constraints at ID id */
5917  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
5918  SCIP_VAR*** vars, /**< 2-dim array of variables */
5919  SCIP_Real** bounds, /**< 2-dim array of bounds */
5920  SCIP_BOUNDTYPE** boundtypes, /**< 2-dim array of boundtypes */
5921  int mem, /**< allocated memory for constraints */
5922  int* nconss, /**< pointer to store the number of constraints */
5923  int* nvars /**< pointer to store the number of variables */
5924  )
5925 {
5926  int c;
5927 
5928  assert(reoptnode != NULL);
5929  assert(vars != NULL);
5930  assert(bounds != NULL);
5931  assert(boundtypes != NULL);
5932  assert(nvars != NULL);
5933  assert(nconss != NULL);
5934 
5935  (*nconss) = reoptnode->nconss;
5936 
5937  if( mem < *nconss )
5938  return;
5939 
5940  for( c = 0; c < *nconss; c++ )
5941  {
5942  assert(vars[c] != NULL);
5943  assert(bounds[c] != NULL);
5944 
5945  vars[c] = reoptnode->conss[c]->vars;
5946  bounds[c] = reoptnode->conss[c]->vals;
5947  boundtypes[c] = reoptnode->conss[c]->boundtypes;
5948  nvars[c] = reoptnode->conss[c]->nvars;
5949  }
5950 }
5951 
5952 /** set the parent id */
5954  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
5955  unsigned int parentid /**< id of the parent node */
5956  )
5957 {
5958  assert(reoptnode != NULL);
5959  assert(parentid <= 536870911); /* id can be at most 2^29 - 1 */
5960 
5961  reoptnode->parentID = parentid;
5962 }
5963 
5964 /** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
5966  SCIP_REOPT* reopt, /**< reoptimization data structure */
5967  SCIP_NODE* node /**< node of the search tree (or NULL) */
5968  )
5969 {
5970  int nleaves = 0;
5971  unsigned int id;
5972  int i;
5973 
5974  assert(reopt != NULL);
5975 
5976  id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
5977  assert(id < reopt->reopttree->reoptnodessize);
5978 
5979  /* return if the node is not part of the reoptimization tree */
5980  if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
5981  return nleaves;
5982 
5983  for( i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++ )
5984  {
5985  unsigned int childid;
5986 
5987  childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
5988  assert(childid < reopt->reopttree->reoptnodessize);
5989 
5990  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
5991  ++nleaves;
5992  else
5993  nleaves += reoptGetNLeaves(reopt, childid);
5994  }
5995 
5996  return nleaves;
5997 }
5998 
5999 /** save information that given node is infeasible */
6001  SCIP_REOPT* reopt, /**< reoptimization data structure */
6002  SCIP_SET* set, /**< global SCIP settings */
6003  BMS_BLKMEM* blkmem, /**< block memory */
6004  SCIP_NODE* node /**< node of the search tree */
6005  )
6006 {
6007  assert(reopt != NULL);
6008  assert(set != NULL);
6009  assert(blkmem != NULL);
6010  assert(node != NULL);
6011 
6012  if( set->reopt_sepaglbinfsubtrees )
6013  {
6014  SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_CUT) );
6015  }
6016 
6017  ++reopt->reopttree->ninfnodes;
6018  ++reopt->reopttree->ntotalinfnodes;
6019 
6020  return SCIP_OKAY;
6021 }
6022 
6023 /** check the reason for cut off a node and if necessary store the node */
6025  SCIP_REOPT* reopt, /**< reoptimization data structure */
6026  SCIP_SET* set, /**< global SCIP settings */
6027  BMS_BLKMEM* blkmem, /**< block memory */
6028  SCIP_NODE* node, /**< node of the search tree */
6029  SCIP_EVENTTYPE eventtype, /**< eventtype */
6030  SCIP_LP* lp, /**< LP data */
6031  SCIP_LPSOLSTAT lpsolstat, /**< solution status of the LP */
6032  SCIP_Bool isrootnode, /**< the node is the root */
6033  SCIP_Bool isfocusnode, /**< the node is the current focus node */
6034  SCIP_Real lowerbound, /**< lower bound of the node */
6035  int effectiverootdepth /**< effective root depth */
6036  )
6037 {
6038  SCIP_Bool strongbranched;
6039 
6040  assert(reopt != NULL);
6041  assert(set != NULL);
6042  assert(blkmem != NULL);
6043  assert(lp != NULL);
6044  assert(node != NULL);
6045  assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
6046 
6047  if( reopt->lastseennode == SCIPnodeGetNumber(node) )
6048  return SCIP_OKAY;
6049 
6050  /* we do not want to store probing node */
6052  return SCIP_OKAY;
6053 
6054  reopt->lastseennode = SCIPnodeGetNumber(node);
6055 
6056  SCIPsetDebugMsg(set, "catch event %" SCIP_EVENTTYPE_FORMAT " for node %lld (type:%d)\n", eventtype, SCIPnodeGetNumber(node), SCIPnodeGetType(node));
6057 
6058  /* case 1: the current node is the root node
6059  * we can skip if the root is (in)feasible or branched w/o bound
6060  * changes based on dual information.
6061  *
6062  * case 2: we need to store the current node if it contains
6063  * bound changes based on dual information or is a leave node
6064  */
6065  if( isrootnode )
6066  {
6067  if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
6068  {
6069  goto CHECK;
6070  }
6071  else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
6072  {
6073  /* store or update the information */
6074  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6075  }
6076  else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
6077  {
6078  /* delete saved dual information which would lead to split the node in a further iteration */
6079  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6080 
6081  /* store or update the information */
6082  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6083  }
6084  else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
6085  {
6086  /* delete saved dual information which would lead to split the node in a further iteration */
6087  SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6088 
6090  {
6091  SCIP_Real cutoffbound = SCIPlpGetCutoffbound(lp);
6092  lowerbound = MIN(lowerbound, cutoffbound);
6093  }
6094 
6095  /* store or update the information */
6096  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
6097  isrootnode, lowerbound) );
6098  }
6099 
6100  assert(reopt->currentnode == -1);
6101  assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6102 
6103  return SCIP_OKAY;
6104  }
6105 
6106  CHECK:
6107 
6108  if( effectiverootdepth == SCIPnodeGetDepth(node) )
6109  strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
6110  else
6111  strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
6112 
6113  SCIPsetDebugMsg(set, "check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
6114  SCIPsetDebugMsg(set, " -> focusnode : %s\n", isfocusnode ? "yes" : "no");
6115  SCIPsetDebugMsg(set, " -> depth : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
6116  SCIPsetDebugMsg(set, " -> strong branched : %s\n", strongbranched ? "yes" : "no");
6117  SCIPsetDebugMsg(set, " -> LP lpsolstat : %d\n", lpsolstat);
6118 
6119  switch( eventtype )
6120  {
6122  /* current node has to be the eventnode */
6123  assert(isfocusnode);
6124 
6125  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_FEASIBLE);
6126 
6127  /* delete strong branching information of some exists */
6128  deleteLastDualBndchgs(reopt);
6129 
6130  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6131  break;
6132 
6134  /* We have to check if the current node is the event node.
6135  * if the current node is not the event node, we have to save this node, else we have to
6136  * look at LP lpsolstat and decide.
6137  */
6138  if( isfocusnode )
6139  {
6140  /* An after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
6141  * because the node is already branched we have all children and can delete this node.
6142  */
6143  if( SCIPnodeGetNumber(node) == reopt->lastbranched )
6144  {
6145  deleteLastDualBndchgs(reopt);
6146  break;
6147  }
6148 
6149  /* If the node is strong branched, we possibly detect an infeasible subtree;
6150  * otherwise, the whole node is either infeasible or exceeds the cutoff bound.
6151  */
6152  if( strongbranched )
6153  {
6154  /* 1. the LP is infeasible: the (sub-)node is infeasible and can be discarded
6155  * because the LP proves infeasibility. We have to store an infeasible subtree separated by a constraint.
6156  * 2. the LP exceeds the objective limit or was not solved, we have to store the node and can delete the
6157  * strong branching information
6158  */
6159  if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6160  {
6161  /* add a dummy variable, because the bound changes were not global in the sense of effective root depth */
6162  if( SCIPnodeGetDepth(node) > effectiverootdepth )
6163  {
6164  SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6165  }
6166 
6167  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6168  SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_INFSUBTREE);
6169 
6170  /* save the node as a strong branched node */
6171  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
6172  }
6173  else
6174  {
6175  assert( lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
6176 
6177  /* delete strong branching information if some exists */
6178  deleteLastDualBndchgs(reopt);
6179 
6180  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6181  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6182  }
6183  }
6184  else
6185  {
6186  /* 1. the LP is infeasible: the whole node is infeasible and can be discarded
6187  * 2. the LP was not solved or exceeds the objective limit, we have to store the node
6188  */
6189  if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6190  {
6191  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6192  SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
6193  }
6194  else
6195  {
6196  assert(lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED || lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
6197  || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
6198 
6199  if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6200  {
6201  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6202  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6203  }
6204  else
6205  {
6206  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6207  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6208  }
6209  }
6210  }
6211  }
6212  else
6213  {
6214  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6215 
6216  /* if the node was created by branch_nodereopt, nothing happens */
6217  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6218  }
6219  break;
6220 
6222  /* current node has to be the eventnode */
6223  assert(isfocusnode);
6224 
6225  reopt->lastbranched = SCIPnodeGetNumber(node);
6226 
6227  /* we have to check the depth of the current node. if the depth is equal to the effective
6228  * root depth, then all information about bound changes based on dual information already exists,
6229  * else we have to look at the domchg-data-structure.
6230  */
6231  if (SCIPnodeGetDepth(node) == effectiverootdepth)
6232  {
6233  /* Save the node if there are added constraints, because this means the node is a copy create by the
6234  * reoptimization plug-in and contains at least one logic-or-constraint */
6235  if( strongbranched )
6236  {
6237  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6238  SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
6239  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6240  }
6241  else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6242  {
6243  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6244  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6245  }
6246  else
6247  {
6248  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
6249  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6250  }
6251  }
6252  else
6253  {
6254  /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
6255  *
6256  * we have to do this in the following order:
6257  * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
6258  * on dual information.
6259  * 2) save or update the node.
6260  */
6261  if( strongbranched )
6262  {
6263  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6264  SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
6265  SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6266  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6267  }
6268  else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6269  {
6270  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6271  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6272  }
6273  else
6274  {
6275  SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
6276  SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6277  }
6278  }
6279  break;
6280 
6281  default:
6282  break;
6283  }
6284 
6285  assert(reopt->currentnode == -1);
6286  assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6287 
6288  return SCIP_OKAY; /*lint !e438*/
6289 }
6290 
6291 /** store bound change based on dual information */
6293  SCIP_REOPT* reopt, /**< reoptimization data structure */
6294  SCIP_SET* set, /**< global SCIP settings */
6295  BMS_BLKMEM* blkmem, /**< block memory */
6296  SCIP_NODE* node, /**< node of the search tree */
6297  SCIP_VAR* var, /**< variable */
6298  SCIP_Real newval, /**< new bound */
6299  SCIP_Real oldval /**< old bound */
6300  )
6301 {
6302  SCIP_Real constant = 0.0;
6303  SCIP_Real scalar = 1.0;
6304 
6305  assert(reopt != NULL);
6306  assert(node != NULL);
6307 
6308  /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
6309  * In that case, all bound changes were not global and we can find them within the
6310  * domchg data structure.
6311  * Otherwise, we allocate memory and store the information.
6312  */
6313  if( var != NULL )
6314  {
6315  SCIP_BOUNDTYPE boundtype;
6316  int resizelength;
6317  int allocmem;
6318 
6319  if( SCIPsetFindBranchrule(set, "relpscost") != NULL )
6320  {
6321  SCIP_CALL( SCIPsetGetIntParam(set, "branching/relpscost/maxlookahead", &resizelength) );
6322  }
6323  else
6324  resizelength = 1;
6325 
6326  if( reopt->dualreds == NULL || reopt->dualreds->varssize == 0 )
6327  allocmem = DEFAULT_MEM_DUALCONS;
6328  else
6329  allocmem = reopt->dualreds->nvars + resizelength;
6330 
6331  /* allocate memory of necessary */
6332  SCIP_CALL( checkMemDualCons(reopt, set, blkmem, allocmem) );
6333 
6334  assert(reopt->dualreds->varssize > 0);
6335  assert(reopt->dualreds->nvars >= 0);
6336  assert(reopt->currentnode == -1 || reopt->dualreds->nvars > 0);
6337  assert((reopt->dualreds->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
6338  || reopt->dualreds->nvars == 0);
6339 
6340  reopt->currentnode = SCIPnodeGetNumber(node);
6341 
6342  /* transform into the original space and then save the bound change */
6343  SCIP_CALL(SCIPvarGetOrigvarSum(&var, &scalar, &constant));
6344  newval = (newval - constant) / scalar;
6345  oldval = (oldval - constant) / scalar;
6346 
6347  assert(SCIPvarIsOriginal(var));
6348 
6349  if( SCIPsetIsEQ(set, oldval, newval) )
6350  {
6351  SCIPerrorMessage("cannot store equal bounds: old = %g, new = %g\n", oldval, newval);
6352  return SCIP_INVALIDDATA;
6353  }
6354 
6355  if( SCIPsetIsLT(set, newval, oldval) )
6356  boundtype = SCIP_BOUNDTYPE_UPPER;
6357  else
6358  boundtype = SCIP_BOUNDTYPE_LOWER;
6359 
6360  reopt->dualreds->vars[reopt->dualreds->nvars] = var;
6361  reopt->dualreds->vals[reopt->dualreds->nvars] = newval;
6362  reopt->dualreds->boundtypes[reopt->dualreds->nvars] = boundtype;
6363  ++reopt->dualreds->nvars;
6364 
6365  SCIPsetDebugMsg(set, ">> store %s bound change of <%s>: %g -> %g\n",
6366  (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), SCIPvarGetName(var), oldval, newval);
6367 
6368  reopt->dualreds->linear = FALSE;
6369  }
6370  else
6371  {
6372  assert(reopt->currentnode == -1);
6373  assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6374 
6375  reopt->currentnode = SCIPnodeGetNumber(node);
6376  }
6377 
6378  return SCIP_OKAY;
6379 }
6380 
6381 /** returns the number of bound changes based on dual information */
6383  SCIP_REOPT* reopt, /**< reoptimization data structure */
6384  SCIP_NODE* node /**< node of the search tree */
6385  )
6386 {
6387  int ndualbndchgs = 0;
6388 
6389  assert(reopt != NULL);
6390  assert(node != NULL);
6391 
6392  if( SCIPnodeGetNumber(node) == reopt->currentnode )
6393  {
6394  assert(reopt->dualreds != NULL);
6395  ndualbndchgs = reopt->dualreds->nvars;
6396  }
6397 
6398  return ndualbndchgs;
6399 }
6400 
6401 /** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
6403  SCIP_REOPT* reopt, /**< reoptimization data structure */
6404  SCIP_SET* set, /**< global SCIP settings */
6405  BMS_BLKMEM* blkmem, /**< block memory */
6406  SCIP_NODE* node, /**< node of the search tree */
6407  unsigned int* childs, /**< array to store the child ids */
6408  int childssize, /**< size of the childs array */
6409  int* nchilds /**< pointer to store the number of child nodes */
6410  )
6411 {
6412  SCIP_Bool runagain;
6413  unsigned int id;
6414 
6415  assert(reopt != NULL);
6416  assert(childssize > 0 && childs != NULL);
6417  assert(nchilds != NULL);
6418 
6419  (*nchilds) = 0;
6420 
6421  if( node == NULL )
6422  id = 0;
6423  else
6424  id = SCIPnodeGetReoptID(node);
6425 
6426  assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
6427  assert(id < reopt->reopttree->reoptnodessize);
6428  assert(reopt->reopttree->reoptnodes[id] != NULL);
6429 
6430  /* check if there are redundant bound changes or infeasible nodes */
6431  runagain = TRUE;
6432  while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6433  {
6434  SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
6435  }
6436 
6437  /* return the list of child nodes if some exists; otherwise return NULL */
6438  if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6439  {
6440  int c;
6441 
6442  (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
6443 
6444  if( childssize < *nchilds )
6445  return SCIP_OKAY;
6446 
6447  for( c = 0; c < *nchilds; c++ )
6448  childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
6449  }
6450 
6451  return SCIP_OKAY;
6452 }
6453 
6454 /** returns all leaves of the subtree induced by @p node */
6456  SCIP_REOPT* reopt, /**< reoptimization data */
6457  SCIP_NODE* node, /**< node of the search tree */
6458  unsigned int* leaves, /**< array to the the ids */
6459  int leavessize, /**< size of leaves array */
6460  int* nleaves /**< pointer to store the number of leave node */
6461  )
6462 {
6463  unsigned int id;
6464  int i;
6465 
6466  assert(reopt != NULL);
6467  assert(leavessize > 0 && leaves != NULL);
6468  assert((*nleaves) >= 0);
6469 
6470  /* if the given node is we start from the root */
6471  if( node == NULL )
6472  id = 0;
6473  else
6474  id = SCIPnodeGetReoptID(node);
6475 
6476  /* return if the node is not part of the reoptimization tree */
6477  if( id == 0 && node != NULL )
6478  {
6479  (*nleaves) = 0;
6480  return SCIP_OKAY;
6481  }
6482 
6483  assert(id < reopt->reopttree->reoptnodessize);
6484  assert(reopt->reopttree->reoptnodes[id] != NULL);
6485 
6486  for( i = 0; i < leavessize; i++ )
6487  leaves[i] = 0;
6488 
6489  /* we traverse through all child nodes of the given node an collect all leave nodes of the subtrees induced by them */
6490  for( i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; i++ )
6491  {
6492  unsigned int childid;
6493 
6494  assert(*nleaves + 1 <= leavessize);
6495 
6496  childid = reopt->reopttree->reoptnodes[id]->childids[i];
6497  assert(childid < reopt->reopttree->reoptnodessize);
6498 
6499  /* the node is already a leave */
6500  if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
6501  {
6502  leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
6503  ++(*nleaves);
6504  }
6505  /* go into the tree induced by the current child node */
6506  else
6507  {
6508  int nleaves2 = 0;
6509 
6510  SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
6511  (*nleaves) += nleaves2;
6512  }
6513  }
6514 
6515  return SCIP_OKAY;
6516 }
6517 
6518 /** add all unprocessed nodes to the reoptimization tree */
6520  SCIP_REOPT* reopt, /**< reoptimization data structure */
6521  SCIP_SET* set, /**< global SCIP settings */
6522  SCIP_LP* lp, /**< current LP */
6523  BMS_BLKMEM* blkmem, /**< block memory */
6524  SCIP_NODE** leaves, /**< array of open leave nodes */
6525  int nleaves, /**< number of open leave nodes */
6526  SCIP_NODE** childs, /**< array of open children nodes */
6527  int nchilds, /**< number of open leave nodes */
6528  SCIP_NODE** siblings, /**< array of open sibling nodes */
6529  int nsiblings /**< number of open leave nodes */
6530  )
6531 {
6532  int n;
6533 
6534  assert(reopt != NULL);
6535  assert(set != NULL);
6536  assert(blkmem != NULL);
6537  assert(nleaves >= 0);
6538  assert(nleaves == 0 || leaves != NULL);
6539  assert(nchilds >= 0);
6540  assert(nchilds == 0 || childs != NULL);
6541  assert(nsiblings >= 0);
6542  assert(nsiblings == 0 || siblings != NULL);
6543 
6544  SCIPsetDebugMsg(set, "save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
6545 
6546  /* save open leaves */
6547  for( n = 0; n < nleaves; n++ )
6548  {
6549  SCIP_CALL( addNode(reopt, set, lp, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6550  SCIPnodeGetLowerbound(leaves[n])) );
6551  }
6552 
6553  /* save open children */
6554  for( n = 0; n < nchilds; n++ )
6555  {
6556  SCIP_CALL( addNode(reopt, set, lp, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6557  SCIPnodeGetLowerbound(childs[n])) );
6558  }
6559 
6560  /* save open siblings */
6561  for( n = 0; n < nsiblings; n++ )
6562  {
6563  SCIP_CALL( addNode(reopt, set, lp, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6564  SCIPnodeGetLowerbound(siblings[n])) );
6565  }
6566 
6567  return SCIP_OKAY;
6568 }
6569 
6570 /** merges the variable history of the current run with the stored history */
6572  SCIP_REOPT* reopt, /**< reoptimization data structure */
6573  SCIP_SET* set, /**< global SCIP settings */
6574  SCIP_STAT* stat, /**< dynamic problem statistics */
6575  SCIP_VAR** vars, /**< original problem variables */
6576  int nvars /**< number of original problem variables */
6577  )
6578 {
6579  SCIP_VAR* transvar;
6580  SCIP_Real avginference[2];
6581  SCIP_Real avgcutoff[2];
6582  SCIP_Real bestsim;
6583  int bestrun;
6584  int idx;
6585  int d;
6586  int r;
6587  int v;
6588 
6589  assert(reopt != NULL);
6590  assert(stat != NULL);
6591  assert(nvars >= 0);
6592 
6593  if( !set->reopt_storevarhistory )
6594  return SCIP_OKAY;
6595 
6596  SCIPsetDebugMsg(set, "start merging variable histories:\n");
6597 
6598  bestrun = reopt->run-2;
6599  bestsim = reopt->simtolastobj;
6600 
6601  /* find the run with the most similar objective */
6602  for( r = reopt->run-3; r >= 0 && reopt->objhaschanged && set->reopt_usepscost; r-- )
6603  {
6604  SCIP_Real sim;
6605  sim = reoptSimilarity(reopt, set, r, reopt->run-1, vars, nvars);
6606 
6607  if( sim == SCIP_INVALID ) /*lint !e777*/
6608  return SCIP_INVALIDRESULT;
6609 
6610  if( SCIPsetIsGT(set, sim, bestsim) )
6611  {
6612  bestsim = sim;
6613  bestrun = r;
6614  }
6615  }
6616  SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "run %d has best similarity=%g\n", bestrun, bestsim);
6617 
6618  /* iterate through all variables and scale the histories */
6619  for( v = 0; v < nvars; v++ )
6620  {
6621  assert(SCIPvarIsOriginal(vars[v]));
6622 
6623  transvar = SCIPvarGetTransVar(vars[v]);
6624  assert(transvar != NULL);
6625 
6626  /* skip variable that are not active */
6627  if( !SCIPvarIsActive(transvar) )
6628  continue;
6629 
6630  idx = SCIPvarGetIndex(vars[v]);
6631  assert(0 <= idx && idx <= nvars);
6632 
6633  /* set the updated history for both directions */
6634  for( d = 0; d <= 1; d++ )
6635  {
6636  if( set->reopt_usepscost && !SCIPsetIsZero(set, reopt->varhistory[bestrun][idx]->pscostcount[d])
6637  && SCIPsetIsGT(set, bestsim, 0.985) ) /* 0.985 is a magic number determined in some experiments */
6638  {
6639  transvar->history->pscostcount[d] = 1.0;
6640  transvar->history->pscostweightedmean[d] = reopt->varhistory[bestrun][idx]->pscostweightedmean[d];
6641  transvar->history->pscostvariance[d] = 0.0;
6642  SCIPsetDebugMsg(set, "-> <%s> pscosts %4s: count=%g weightedmean=%g variance=%g\n", SCIPvarGetName(transvar),
6643  (d == 0 ? "down" : "up"), transvar->history->pscostcount[d], transvar->history->pscostweightedmean[d],
6644  transvar->history->pscostvariance[d]);
6645  }
6646 
6648 
6649  /* inference score */
6650  avginference[d] = SCIPhistoryGetAvgInferences(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6651  SCIPhistoryIncInferenceSum(transvar->history, (SCIP_BRANCHDIR)d, avginference[d]);
6652 
6653  /* cutoff score */
6654  avgcutoff[d] = SCIPhistoryGetAvgCutoffs(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6655  SCIPhistoryIncCutoffSum(transvar->history, (SCIP_BRANCHDIR)d, avgcutoff[d]);
6656 
6657  SCIPsetDebugMsg(set, "-> <%s> %4s scores: inf=%g cutoff=%g\n", SCIPvarGetName(transvar),
6658  (d == 0 ? "down" : "up"), avginference[d], avgcutoff[d]);
6659  }
6660  }
6661 
6662  return SCIP_OKAY;
6663 }
6664 
6665 /** updates the variable history */
6667  SCIP_REOPT* reopt, /**< reoptimization data structure */
6668  SCIP_SET* set, /**< global SCIP settings */
6669  SCIP_STAT* stat, /**< dynamic problem statistics */
6670  BMS_BLKMEM* blkmem, /**< block memory */
6671  SCIP_VAR** vars, /**< original variable array */
6672  int nvars /**< number of original variables */
6673  )
6674 {
6675  int v;
6676 
6677  assert(reopt != NULL);
6678  assert(stat != NULL);
6679  assert(blkmem != NULL);
6680  assert(nvars >= 0);
6681 
6682  if( !set->reopt_storevarhistory )
6683  return SCIP_OKAY;
6684 
6685  SCIPsetDebugMsg(set, "updating variable history\n");
6686 
6687  if( reopt->varhistory[reopt->run-1] == NULL )
6688  {
6689  /* allocate memory */
6690  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->varhistory[reopt->run-1], nvars) );
6691 
6692  for( v = 0; v < nvars; v++ )
6693  {
6694  SCIP_CALL( SCIPhistoryCreate(&(reopt->varhistory[reopt->run-1][v]), blkmem) );
6695  }
6696  }
6697 
6698  /* update the history and scale them */
6699  for( v = 0; v < nvars; v++ )
6700  {
6701  SCIP_VAR* transvar;
6702  int idx;
6703 
6704  assert(SCIPvarIsOriginal(vars[v]));
6705  idx = SCIPvarGetIndex(vars[v]);
6706  assert(idx >= 0 && idx < nvars);
6707 
6708  transvar = SCIPvarGetTransVar(vars[v]);
6709  assert(transvar != NULL);
6710 
6711  if( !SCIPvarIsActive(transvar) )
6712  continue;
6713 
6714  /* we store the complete history */
6715  SCIPhistoryReset(reopt->varhistory[reopt->run-1][idx]);
6716  SCIPhistoryUnite(reopt->varhistory[reopt->run-1][idx], transvar->history, FALSE);
6717  }
6718 
6719  return SCIP_OKAY;
6720 }
6721 
6722 /** reset the complete tree and set the given search frontier */
6724  SCIP_REOPT* reopt, /**< reoptimization data structure */
6725  SCIP_SET* set, /**< global SCIP settings */
6726  BMS_BLKMEM* blkmem, /**< block memory */
6727  SCIP_REOPTNODE** representatives, /**< array of representatives */
6728  int nrepresentatives, /**< number of representatives */
6729  SCIP_Bool* success /**< pointer to store if the method was successful */
6730  )
6731 {
6732  SCIP_REOPTTREE* reopttree;
6733  unsigned int id;
6734  int r;
6735 
6736  assert(reopt != NULL);
6737  assert(set != NULL);
6738  assert(blkmem != NULL);
6739  assert(representatives != NULL);
6740  assert(nrepresentatives > 0);
6741 
6742  reopttree = reopt->reopttree;
6743 
6744  /* reset the current search tree */
6745  SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
6746  assert(reopttree->nreoptnodes == 0);
6747 
6748  /* create a new root node */
6749  id = 0;
6750  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6751 
6752  /* set the reopttype */
6753  reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6754 
6755  /* add all representatives */
6756  for( r = 0; r < nrepresentatives; r++ )
6757  {
6758  /* get an empty slot*/
6759  id = SCIPqueueRemoveUInt(reopttree->openids);
6760  assert(1 <= id && id < reopttree->reoptnodessize);
6761  assert(reopttree->reoptnodes[id] == NULL);
6762 
6763  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6764  assert(reopttree->reoptnodes[id] != NULL);
6765 
6766  /* set the new node
6767  * 1. copy all variables, bounds, and boundtypes
6768  * 2. copy all constraints
6769  * 3. set the parent relation
6770  */
6771  if( representatives[r]->nvars > 0 )
6772  {
6773  int v;
6774 
6775  assert(representatives[r]->nvars <= representatives[r]->varssize);
6776 
6777  for( v = 0; v < representatives[r]->nvars; v++ )
6778  {
6779  SCIP_CALL( SCIPreoptnodeAddBndchg(reopttree->reoptnodes[id], set, blkmem, representatives[r]->vars[v],
6780  representatives[r]->varbounds[v], representatives[r]->varboundtypes[v]) );
6781  }
6782  }
6783 
6784  if( representatives[r]->nconss > 0 )
6785  {
6786  int c;
6787 
6788  assert(representatives[r]->nconss <= representatives[r]->consssize);
6789 
6790  for( c = 0; c < representatives[r]->nconss; c++ )
6791  {
6792  SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], set, blkmem, representatives[r]->conss[c]->vars,
6793  representatives[r]->conss[c]->vals, representatives[r]->conss[c]->boundtypes,
6794  representatives[r]->conss[c]->lhs, representatives[r]->conss[c]->rhs,
6795  representatives[r]->conss[c]->nvars, representatives[r]->conss[c]->constype,
6796  representatives[r]->conss[c]->linear) );
6797  }
6798  }
6799 
6800  reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
6801 
6802  assert(reopttree->reoptnodes[id]->parentID == 0);
6803  assert(reopttree->reoptnodes[id]->nvars >= 0);
6804  assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
6805  assert(reopttree->reoptnodes[id]->nconss >= 0);
6806 
6807  /* set the reopttype */
6808  if( reopttree->reoptnodes[id]->nconss == 0 )
6809  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
6810  else
6811  reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
6812 
6813  /* add the representative as a child of the root */
6814  SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
6815  }
6816 
6817  SCIPsetDebugMsg(set, "-> new tree consists of %d nodes, the root has %d child nodes.\n",
6818  reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
6819 
6820  (*success) = TRUE;
6821 
6822  return SCIP_OKAY;
6823 }
6824 
6825 /** transforms a set of dual reductions into a linear constraint */
6826 static
6828  SCIP_REOPT* reopt, /**< reoptimization data structure */
6829  SCIP_SET* set, /**< global SCIP settings */
6830  BMS_BLKMEM* blkmem, /**< block memory */
6831  SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
6832  * pruned by the dual reductions */
6833  SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
6834  )
6835 {
6836  int v;
6837 
6838  assert(reopt != NULL);
6839  assert(set != NULL);
6840  assert(blkmem != NULL);
6841  assert(consdata != NULL);
6842  assert(dualreds != NULL);
6843 
6844  /* we have to transform the set of bound changes into a linear constraint */
6845  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6846  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &consdata->vals, dualreds->nvars) );
6847  consdata->boundtypes = NULL;
6848 
6849  consdata->varssize = dualreds->nvars;
6850  consdata->nvars = dualreds->nvars;
6851  consdata->constype = REOPT_CONSTYPE_DUALREDS;
6852  consdata->linear = TRUE;
6853 
6854  /* set lhs and rhs */
6855  consdata->lhs = 1.0;
6856  consdata->rhs = SCIPsetInfinity(set);
6857 
6858  for( v = 0; v < consdata->nvars; v++ )
6859  {
6860  assert(consdata->vars[v] != NULL);
6861 
6862  /* the bound is 0.0, the variable has to appear with a coefficient +1.0 in the constraint, sides do not change */
6863  if( SCIPsetIsEQ(set, dualreds->vals[v], 0.0) )
6864  {
6865  assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
6866  consdata->vals[v] = 1.0;
6867  }
6868  /* the bound is 1.0, the variable has to appear with a coefficient -1.0 in the constraint, we subtract -1.0 from lhs
6869  * logicor: sum x_i + ~y_i >= 1
6870  * <==> sum x_i + (1-y_i) >= 1
6871  * <==> sum x_i - y_i >= 0
6872  */
6873  else
6874  {
6875  assert(SCIPsetIsEQ(set, dualreds->vals[v], 1.0));
6876  assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6877 
6878  consdata->vals[v] = -1.0;
6879  consdata->lhs -= 1.0;
6880  }
6881  }
6882 
6883  return SCIP_OKAY;
6884 }
6885 
6886 
6887 /** transforms a set of dual reductions into a bounddisjuction constraint */
6888 static
6890  SCIP_REOPT* reopt, /**< reoptimization data structure */
6891  SCIP_SET* set, /**< global SCIP settings */
6892  BMS_BLKMEM* blkmem, /**< block memory */
6893  SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
6894  * pruned by the dual reductions */
6895  SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
6896  )
6897 {
6898  int v;
6899 
6900  assert(reopt != NULL);
6901  assert(set != NULL);
6902  assert(blkmem != NULL);
6903  assert(consdata != NULL);
6904  assert(dualreds != NULL);
6905 
6906  /* we have to transform the set of bound changes into a linear constraint */
6907  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6908  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, dualreds->vals, dualreds->nvars) );
6909  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->boundtypes, dualreds->boundtypes, dualreds->nvars) );
6910 
6911  consdata->varssize = dualreds->nvars;
6912  consdata->nvars = dualreds->nvars;
6913  consdata->constype = REOPT_CONSTYPE_DUALREDS;
6914  consdata->linear = FALSE;
6915 
6916  /* set lhs and rhs */
6917  consdata->lhs = SCIP_UNKNOWN;
6918  consdata->rhs = SCIP_UNKNOWN;
6919 
6920  for( v = 0; v < consdata->nvars; v++ )
6921  {
6922  SCIP_Real glbbd;
6923 
6924  assert(consdata->vars[v] != NULL);
6925 
6926  /* we do the followung to transformations:
6927  * (a) x <= val ==> (x >= val+1)
6928  * (b) x >= val ==> (x <= val-1)
6929  */
6930  if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
6931  {
6932  glbbd = SCIPvarGetUbGlobal(consdata->vars[v]);
6933  consdata->vals[v] = MIN(consdata->vals[v]+1.0, glbbd);
6934  }
6935  else
6936  {
6937  assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6938  glbbd = SCIPvarGetLbGlobal(consdata->vars[v]);
6939  consdata->vals[v] = MAX(glbbd, consdata->vals[v]-1.0);
6940  }
6941  consdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - consdata->boundtypes[v]); /*lint !e656*/
6942  }
6943 
6944  return SCIP_OKAY;
6945 }
6946 
6947 /** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
6949  SCIP_REOPT* reopt, /**< reoptimization data structure */
6950  SCIP_TREE* tree, /**< branch and bound tree */
6951  SCIP_SET* set, /**< global SCIP settings */
6952  SCIP_STAT* stat, /**< dynamic SCIP statistics */
6953  BMS_BLKMEM* blkmem, /**< block memory */
6954  int* ncreatedchilds, /**< pointer to store the number of created nodes */
6955  int* naddedconss /**< pointer to store the number added constraints */
6956  )
6957 {
6958  SCIP_REOPTTREE* reopttree;
6959  SCIP_REOPTNODE** reoptnodes;
6960  SCIP_REOPTCONSDATA* consdata;
6961  SCIP_VAR** vars;
6962  SCIP_Real* bounds;
6963  SCIP_BOUNDTYPE* boundtypes;
6964  int* perm = NULL;
6965  unsigned int id;
6966  int nbndchgs;
6967  int nchilds;
6968  int nvars = 0;
6969  int v;
6970 
6971  assert(reopt != NULL);
6972  assert(set != NULL);
6973  assert(stat != NULL);
6974  assert(blkmem != NULL);
6975 
6976  reopttree = reopt->reopttree;
6977  assert(reopttree != NULL);
6978 
6979  reoptnodes = reopttree->reoptnodes;
6980  assert(reoptnodes != NULL);
6981  assert(reoptnodes[0] != NULL);
6982  assert(reoptnodes[0]->dualreds);
6983  assert(reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
6984 
6985  nchilds = reoptnodes[0]->nchilds;
6986 
6987  assert(reoptnodes[0]->dualredscur != NULL);
6988  nbndchgs = reoptnodes[0]->dualredscur->nvars;
6989 
6990  (*ncreatedchilds) = 0;
6991  (*naddedconss) = 0;
6992 
6993  /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
6994 
6995  /* ensure that two free slots are available */
6996  SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
6997  id = SCIPqueueRemoveUInt(reopttree->openids);
6998 
6999  assert(0 < id && id < reopt->reopttree->reoptnodessize);
7000  assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
7001 
7002  /* 1. create the node
7003  * 2. add all bound changes
7004  * 3. move all child nodes to id
7005  * 4. add id as a child of the root node
7006  */
7007  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7008  reoptnodes[id]->parentID = 0;
7009  reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7010 
7011  /* check memory */
7012  SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0) );
7013  assert(reoptnodes[id]->varssize >= nbndchgs);
7014  assert(reoptnodes[id]->nvars == 0);
7015  assert(reoptnodes[id]->vars != NULL);
7016  assert(reoptnodes[id]->varbounds != NULL);
7017  assert(reoptnodes[id]->varboundtypes != NULL);
7018 
7019  /* create a permutation array */
7020  if( !set->reopt_usesplitcons )
7021  {
7022  assert(perm == NULL);
7023  SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nbndchgs) );
7024  }
7025 
7026  /* copy bounds */
7027  for( v = 0; v < nbndchgs; v++ )
7028  {
7029  reoptnodes[id]->vars[v] = reoptnodes[0]->dualredscur->vars[v];
7030  reoptnodes[id]->varbounds[v] = reoptnodes[0]->dualredscur->vals[v];
7031  reoptnodes[id]->varboundtypes[v] = reoptnodes[0]->dualredscur->boundtypes[v];
7032  ++reoptnodes[id]->nvars;
7033 
7034  /* fill a permutation array */
7035  if( !set->reopt_usesplitcons )
7036  perm[v] = v; /*lint !e613*/
7037  }
7038  assert(reoptnodes[id]->nvars == reoptnodes[0]->dualredscur->nvars);
7039 
7040  /* move the children */
7041  SCIP_CALL( reoptMoveIDs(reopttree, set, blkmem, 0, id) );
7042  assert(reoptnodes[0]->nchilds == 0);
7043 
7044  /* add the new reoptimization node as a child of the root node */
7045  SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7046 
7047  ++(*ncreatedchilds);
7048 
7049  if( set->reopt_usesplitcons )
7050  {
7051  int nbinvars = 0;
7052  int nintvars = 0;
7053  int ncontvars = 0;
7054 
7055  assert(*ncreatedchilds == 1);
7056 
7057  /* ensure that there is a free slots */
7058  SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
7059  id = SCIPqueueRemoveUInt(reopttree->openids);
7060  assert(0 < id && id < reopt->reopttree->reoptnodessize);
7061 
7062  /* 1. create the node
7063  * 2. add the constraint to ensure that at least one
7064  * variable gets different
7065  * 3. add id as a child of the root node
7066  */
7067  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7068  reoptnodes[id]->parentID = 0;
7069  reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
7070 
7071  /* check memory for added constraints */
7072  SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, 0, 0, 1) );
7073 
7074  /* create the constraint */
7075  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnodes[id]->conss[0]) );
7076  consdata = reoptnodes[id]->conss[0];
7077 
7078  /* count number of binary, integer, and continuous varibales */
7079  for( v = 0; v < nbndchgs; v++ )
7080  {
7081  switch( SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]) ) {
7082  case SCIP_VARTYPE_BINARY:
7083  ++nbinvars;
7084  break;
7085  case SCIP_VARTYPE_INTEGER:
7086  case SCIP_VARTYPE_IMPLINT:
7087  ++nintvars;
7088  break;
7090  ++ncontvars;
7091  break;
7092  default:
7093  SCIPerrorMessage("Cannot handle vartype %d\n", SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]));
7094  return SCIP_INVALIDDATA;
7095  }
7096  }
7097 
7098  /* we create a linear constraint, since all variables are binary */
7099  if( nbinvars == nbndchgs )
7100  {
7101  SCIP_CALL( transformDualredsToLinear(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7102  }
7103  /* we create a bounddisjunction constraint, since at least one variable is (implicit) integer or continuous */
7104  else
7105  {
7106  assert(nintvars > 0 || ncontvars > 0);
7107  SCIP_CALL( transformDualredsToBounddisjunction(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7108  }
7109  ++reoptnodes[id]->nconss;
7110 
7111  /* add id as a child of the root node */
7112  SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7113  ++(*ncreatedchilds);
7114 
7115  ++(*naddedconss);
7116  }
7117  else
7118  {
7119  int c;
7120 
7121  assert(*ncreatedchilds == 1);
7122  assert(perm != NULL);
7123 
7124  vars = reoptnodes[0]->dualredscur->vars;
7125  bounds = reoptnodes[0]->dualredscur->vals;
7126  boundtypes = reoptnodes[0]->dualredscur->boundtypes;
7127  nvars = reoptnodes[0]->dualredscur->nvars;
7128  assert(perm[0] == 0 && perm[nvars-1] == nvars-1);
7129 
7130  /* calculate the order of the variables */
7131  switch (set->reopt_varorderinterdiction)
7132  {
7133  /* default order */
7134  case 'd':
7135  break;
7136 
7137  /* inference order */
7138  case 'i':
7139  SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7140  break;
7141 
7142  /* random order */
7143  case 'r':
7144  SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7145  break;
7146 
7147  default:
7148  return SCIP_INVALIDDATA;
7149  }
7150 
7151  /* create nvars nodes in the fashion of interdiction branching */
7152  for( c = 0; c < nvars; c++ )
7153  {
7154  /* ensure that two free slots are available */
7155  SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
7156  id = SCIPqueueRemoveUInt(reopttree->openids);
7157 
7158  assert(0 < id && id < reopt->reopttree->reoptnodessize);
7159  assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
7160 
7161  /* 1. create the node
7162  * 2. fix the first v bound changes to vals[v] and v+1 to vals[v] +/- 1 (depending on the bound- and vartype)
7163  * 4. add the ID id as a child of the root node
7164  */
7165  SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7166  reoptnodes[id]->parentID = 0;
7167  reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7168 
7169  /* check memory */
7170  SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, c+1, 0, 0) );
7171  assert(reoptnodes[id]->varssize >= perm[c]+1);
7172  assert(reoptnodes[id]->nvars == 0);
7173  assert(reoptnodes[id]->vars != NULL);
7174  assert(reoptnodes[id]->varbounds != NULL);
7175  assert(reoptnodes[id]->varboundtypes != NULL);
7176 
7177  /* the permutation is the identity */
7178  if( set->reopt_varorderinterdiction == 'd' )
7179  {
7180  /* copy first c bound changes */
7181  for( v = 0; v < c; v++ )
7182  {
7183  reoptnodes[id]->vars[v] = vars[v];
7184  reoptnodes[id]->varbounds[v] = bounds[v];
7185  reoptnodes[id]->varboundtypes[v] = boundtypes[v];
7186  }
7187  }
7188  else
7189  {
7190  /* copy first c bound changes */
7191  for( v = 0; v < c; v++ )
7192  {
7193  reoptnodes[id]->vars[v] = vars[perm[v]];
7194  reoptnodes[id]->varbounds[v] = bounds[perm[v]];
7195  reoptnodes[id]->varboundtypes[v] = boundtypes[perm[v]];
7196  }
7197  }
7198  reoptnodes[id]->nvars += c;
7199 
7200  /* set bound change v+1 (= c) to vals[v] +/- 1 (depending on the bound- and vartype) */
7201  assert(v == c);
7202  reoptnodes[id]->vars[c] = vars[perm[c]];
7203  reoptnodes[id]->varbounds[c] = bounds[perm[c]];
7204  if( SCIPvarGetType(vars[perm[c]]) != SCIP_VARTYPE_CONTINUOUS )
7205  {
7206  if( boundtypes[perm[c]] == SCIP_BOUNDTYPE_LOWER )
7207  reoptnodes[id]->varbounds[c] -= 1.0;
7208  else
7209  reoptnodes[id]->varbounds[c] += 1.0;
7210  }
7211  reoptnodes[id]->varboundtypes[c] = (boundtypes[perm[c]] == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
7212  ++reoptnodes[id]->nvars;
7213 
7214  /* add dummy1 as a child of the root node */
7215  SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7216 
7217  ++(*ncreatedchilds);
7218  }
7219 
7220  assert(*ncreatedchilds == nvars+1);
7221 
7222  SCIPsetFreeBufferArray(set, &perm);
7223  perm = NULL;
7224  }
7225  assert(perm == NULL);
7226 
7227  /* free the current dualredscur and assign dualredsnex */
7228  assert(reoptnodes[0]->dualredscur->vars != NULL);
7229  assert(reoptnodes[0]->dualredscur->vals != NULL);
7230  assert(reoptnodes[0]->dualredscur->boundtypes != NULL);
7231 
7232  /* free the current dualredscur and assign dualredsnex */
7233  SCIP_CALL( reoptnodeUpdateDualConss(reoptnodes[0], blkmem) );
7234 
7235  /* change the reopttype of the root node */
7237 
7238  return SCIP_OKAY;
7239 }
7240 
7241 /** reset the stored information abound bound changes based on dual information */
7243  SCIP_REOPT* reopt, /**< reoptimization data structure */
7244  SCIP_NODE* node, /**< node of the search tree */
7245  BMS_BLKMEM* blkmem /**< block memory */
7246  )
7247 {
7248  unsigned int id;
7249 
7250  assert(reopt != NULL);
7251  assert(node != NULL);
7252 
7253  id = SCIPnodeGetReoptID(node);
7254  assert(id < reopt->reopttree->reoptnodessize);
7255 
7256  /* return if the node is not part of the reoptimization tree */
7257  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7258  return SCIP_OKAY;
7259 
7260  /* reset the dual constraint */
7261  SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7262 
7263  return SCIP_OKAY;
7264 }
7265 
7266 /** return the branching path stored of the given node in the reoptimization tree */
7268  SCIP_REOPT* reopt, /**< reoptimization data structure */
7269  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
7270  SCIP_VAR** vars, /**< array for variables */
7271  SCIP_Real* vals, /**< array for values */
7272  SCIP_BOUNDTYPE* boundtypes, /**< array for bound types */
7273  int varssize, /**< size of arrays vars, vals, and boundtypes */
7274  int* nbndchgs, /**< pointer to store the number of bound changes */
7275  int* nbndchgsafterdual /**< pointer to store the number of bound changes applied after
7276  * the first dual reduction at the given node */
7277  )
7278 {
7279  int v;
7280  int nvars2;
7281  int nafterdualvars2;
7282 
7283  assert(reopt != NULL);
7284  assert(reoptnode != NULL);
7285  assert(vars != NULL);
7286  assert(vals != NULL);
7287  assert(boundtypes != NULL);
7288 
7289  (*nbndchgs) = reoptnode->nvars;
7290  (*nbndchgsafterdual) = reoptnode->nafterdualvars;
7291 
7292  /* return if the size of the given array is not large enough */
7293  if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
7294  return;
7295 
7296  /* add all bound changes made by branching (including dual reductions) */
7297  for( v = 0; v < *nbndchgs; v++ )
7298  {
7299  vars[v] = reoptnode->vars[v];
7300  vals[v] = reoptnode->varbounds[v];
7301  boundtypes[v] = reoptnode->varboundtypes[v];
7302  }
7303 
7304  /* add all bound changes made applied after a dual reduction */
7305  for( ; v < *nbndchgs + *nbndchgsafterdual; v++ )
7306  {
7307  vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
7308  vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
7309  boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
7310  }
7311 
7312  /* go along the root path within the reoptimization tree */
7313  if( reoptnode->parentID != 0 )
7314  {
7315  SCIP_REOPTNODE* parent;
7316 
7317  parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
7318  SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
7319 
7320  (*nbndchgs) += nvars2;
7321  (*nbndchgsafterdual) += nafterdualvars2;
7322  }
7323 }
7324 
7325 /** delete a node stored in the reoptimization tree */
7327  SCIP_REOPT* reopt, /**< reoptimization data structure */
7328  SCIP_SET* set, /**< global SCIP settings */
7329  unsigned int id, /**< id of a stored node */
7330  BMS_BLKMEM* blkmem /**< block memory */
7331  )
7332 {
7333  assert(reopt != NULL);
7334  assert(reopt->reopttree != NULL);
7335  assert(id < reopt->reopttree->reoptnodessize);
7336  assert(reopt->reopttree->reoptnodes[id] != NULL);
7337  assert(blkmem != NULL);
7338 
7339  SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
7341 
7342  return SCIP_OKAY;
7343 }
7344 
7345 /** reactivate the given @p reoptnode and split them into several nodes if necessary */
7347  SCIP_REOPT* reopt, /**< reoptimization data structure */
7348  SCIP* scip, /**< SCIP data structure */
7349  SCIP_SET* set, /**< global SCIP settings */
7350  SCIP_STAT* stat, /**< dynamic problem statistics */
7351  SCIP_PROB* transprob, /**< transformed problem */
7352  SCIP_PROB* origprob, /**< original problem */
7353  SCIP_TREE* tree, /**< branching tree */
7354  SCIP_LP* lp, /**< current LP */
7355  SCIP_BRANCHCAND* branchcand, /**< branching candidate */
7356  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7357  SCIP_CLIQUETABLE* cliquetable, /**< clique table */
7358  BMS_BLKMEM* blkmem, /**< block memory */
7359  SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree to reactivate */
7360  unsigned int id, /**< id of the node to reactivate */
7361  SCIP_Real estimate, /**< estimate of the child nodes that should be created */
7362  SCIP_NODE** childnodes, /**< array to store the created child nodes */
7363  int* ncreatedchilds, /**< pointer to store number of created child nodes */
7364  int* naddedconss, /**< pointer to store number of generated constraints */
7365  int childnodessize, /**< available size of childnodes array */
7366  SCIP_Bool* success /**< pointer store the result */
7367  )
7368 {
7369  assert(reopt != NULL);
7370  assert(scip != NULL);
7371  assert(set != NULL);
7372  assert(stat != NULL);
7373  assert(transprob != NULL);
7374  assert(origprob != NULL);
7375  assert(tree != NULL);
7376  assert(lp != NULL);
7377  assert(branchcand != NULL);
7378  assert(eventqueue != NULL);
7379  assert(cliquetable != NULL);
7380  assert(blkmem != NULL);
7381  assert(reoptnode != NULL);
7382  assert(childnodes != NULL);
7383  assert(reopt->reopttree != NULL);
7384  assert(id < reopt->reopttree->reoptnodessize);
7385  assert(success != NULL);
7386 
7387  SCIPsetDebugMsg(set, "reactivating node at id %u:\n", id);
7388 
7389  *success = FALSE;
7390 
7391  /* check if we need to split the node */
7392  if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
7393  || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7394  {
7395  int c;
7396 
7397  assert(reoptnode->dualreds);
7398 
7399  /* we want use a constraint to split the node into two disjoint node */
7400  if( set->reopt_usesplitcons )
7401  {
7402  if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7403  {
7404  assert(reoptnode->dualredscur != NULL);
7405  assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
7406  (*ncreatedchilds) = 1;
7407  }
7408  else
7409  {
7410  assert(reoptnode->dualredscur != NULL);
7411  assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7412  (*ncreatedchilds) = 2;
7413  }
7414 
7415  /* in both cases we add exactly one constraint */
7416  (*naddedconss) = 1;
7417 
7418  if( childnodessize < *ncreatedchilds )
7419  return SCIP_OKAY;
7420 
7421  /* generate the nodes */
7422  for( c = 0; c < *ncreatedchilds; c++ )
7423  {
7424  /* create the child node */
7425  SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7426 
7427  /* change all bounds; convert the bound changes after the first based on dual reductions into branching
7428  * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
7429  * changes anyway.
7430  */
7431  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7432  cliquetable, blkmem, childnodes[c], id, c == 1) );
7433 
7434  /* add all local constraints */
7435  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7436 
7437  /* we can use the old lowerbound if the objective function has not changed */
7438  if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7439  SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7440 
7441  if( c == 0 )
7442  {
7443  /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
7444  SCIPnodeSetReopttype(childnodes[c], SCIP_REOPTTYPE_NONE);
7445 
7446  /* add the constraint to the node */
7447  assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7448  SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
7449  eventqueue, cliquetable, childnodes[c], id) );
7450 
7451  /* fixBounds() does the same, but in this case we go not into it */
7452  if( reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE )
7453  {
7454  assert(reoptnode->dualredscur->nvars > 0);
7455  assert(reoptnode->dualredscur->varssize > 0);
7456 
7457  /* delete dualredscur and move dualredsnex -> dualredscur */
7458  SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
7459  }
7460 
7461  /* the added constraint could be deleted due to propagation, thus, we store the node in the reoptimization
7462  * tree. the node has to stored anyway, because of the constraint representing the dual reductions
7463  */
7464  SCIP_CALL( addNode(reopt, set, lp, blkmem, childnodes[c], SCIP_REOPTTYPE_LOGICORNODE, FALSE, FALSE,
7465  -SCIPsetInfinity(set)) );
7466  }
7467  else
7468  {
7469  /* if we reach this lines of code, the current node represents the original node including all bound
7470  * changes based in dual information.
7471  */
7472  assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7473  if( reoptnode->nconss == 0 )
7475  else
7477 
7478  /* fix all bound changes based on dual information and convert them into branchings */
7479  assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7480  SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7481  blkmem, childnodes[c], id, TRUE) );
7482 
7483  /* set the unique id the id of the original node */
7484  SCIPnodeSetReoptID(childnodes[c], id);
7485  }
7486  }
7487 
7488  /* reset the stored dual constraints */
7489  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7490 
7491  /* set the reoptimization type */
7492  if( reopt->reopttree->reoptnodes[id]->dualreds )
7493  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7494  else
7495  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7496 
7497  *success = TRUE;
7498  }
7499  else
7500  {
7501  SCIP_VAR** vars;
7502  SCIP_Real* bounds;
7503  SCIP_BOUNDTYPE* boundtypes;
7504  int* perm = NULL;
7505  int nvars;
7506 
7507  vars = reoptnode->dualredscur->vars;
7508  bounds = reoptnode->dualredscur->vals;
7509  boundtypes = reoptnode->dualredscur->boundtypes;
7510  nvars = reoptnode->dualredscur->nvars;
7511 
7512  *ncreatedchilds = nvars+1;
7513  *naddedconss = 0;
7514 
7515  /* check if there is enough memory allocated */
7516  if( childnodessize < *ncreatedchilds )
7517  return SCIP_OKAY;
7518 
7519  /* create and fill permutation array */
7520  SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nvars) );
7521  for( c = 0; c < nvars; c++ )
7522  perm[c] = c;
7523 
7524  /* calculate the order of the variables */
7525  switch (set->reopt_varorderinterdiction)
7526  {
7527  /* default order */
7528  case 'd':
7529  break;
7530 
7531  /* inference order */
7532  case 'i':
7533  SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7534  break;
7535 
7536  /* random order */
7537  case 'r':
7538  SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7539  break;
7540 
7541  default:
7542  return SCIP_INVALIDDATA;
7543  }
7544 
7545  assert(reopt->reopttree->reoptnodes[id] != NULL);
7546  reoptnode = reopt->reopttree->reoptnodes[id];
7547 
7548  /* enough that the node need to split */
7549  assert(reoptnode->dualreds);
7550 
7551  /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
7552  * we need to do this in the reverse order because we want to transform the bound changes based on dual information
7553  * into branching decisions at nodes[0].
7554  */
7555  for( c = nvars; c >= 0; c-- )
7556  {
7557  /* create the child node */
7558  SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7559 
7560 #ifdef SCIP_MORE_DEBUG
7561  SCIPsetDebugMsg(set, " change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
7562 #endif
7563 
7564  /* change all bounds */
7565  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7566  cliquetable, blkmem, childnodes[c], id, FALSE) );
7567 
7568  /* reconstruct the original node and the pruned part, respectively */
7569  if( c == 0 )
7570  {
7571  /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
7572  SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7573  blkmem, childnodes[c], id, TRUE) );
7574 
7575  /* set the reopttype of the node */
7577 
7578  /* set the unique id */
7579  SCIPnodeSetReoptID(childnodes[c], id);
7580  }
7581  else
7582  {
7583  /* fix the first c bound changes and negate the (c+1)th */
7584  SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7585  blkmem, childnodes[c], id, perm, vars, bounds, boundtypes, nvars, c) );
7586  }
7587 
7588  /* add all local constraints */
7589  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7590 
7591  /* we can use the old lowerbound if the objective function has not changed */
7592  if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7593  SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7594  }
7595 
7596  /* free buffer array */
7597  SCIPsetFreeBufferArray(set, &perm);
7598 
7599  /* reset the stored dual constraints */
7600  SCIP_CALL( reoptnodeUpdateDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7601 
7602  /* set the reoptimization type to transit */
7603  if( reopt->reopttree->reoptnodes[id]->dualreds )
7604  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7605  else
7606  reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7607 
7608  *success = TRUE;
7609  }
7610  }
7611  else
7612  {
7613  /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
7614  (*ncreatedchilds) = 1;
7615  (*naddedconss) = 0;
7616 
7617  if( childnodessize < *ncreatedchilds )
7618  return SCIP_OKAY;
7619 
7620  /* create the child node */
7621  SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
7622 
7623  /* change all bounds */
7624  assert(reoptnode->nafterdualvars == 0);
7625  SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7626  cliquetable, blkmem, childnodes[0], id, FALSE) );
7627 
7628  /* add all local constraints */
7629  SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
7630 
7631  /* we can use the old lowerbound if the objective function has not changed */
7632  if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7633  SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7634 
7635  /* set the reopttype */
7636  assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
7637  && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
7638  SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
7639 
7640  /* set the unique id */
7641  SCIPnodeSetReoptID(childnodes[0], id);
7642 
7643  *success = TRUE;
7644  }
7645 
7646  return SCIP_OKAY;
7647 }
7648 
7649 /** returns the time needed to store the nodes for reoptimization */
7651  SCIP_REOPT* reopt /**< reoptimization data structure */
7652  )
7653 {
7654  assert(reopt != NULL);
7655 
7656  return SCIPclockGetTime(reopt->savingtime);
7657 }
7658 
7659 /** add the stored constraints globally to the problem */
7661  SCIP* scip, /**< SCIP data structure */
7662  SCIP_REOPT* reopt, /**< reoptimization data structure */
7663  SCIP_SET* set, /**< global SCIP settings */
7664  SCIP_STAT* stat, /**< dynamic problem statistics */
7665  BMS_BLKMEM* blkmem /**< block memory */
7666  )
7667 {
7668  char name[SCIP_MAXSTRLEN];
7669  int c;
7670 
7671  assert(scip != NULL);
7672  assert(reopt != NULL);
7673  assert(set != NULL);
7674  assert(stat != NULL);
7675  assert(blkmem != NULL);
7676 
7677  if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
7678  return SCIP_OKAY;
7679 
7680  for( c = reopt->nglbconss-1; c >= 0; c-- )
7681  {
7682  SCIP_CONS* cons;
7683  SCIP_VAR** consvars;
7684  int nbinvars;
7685  int nintvars;
7686  int v;
7687 
7688  assert(reopt->glbconss[c] != NULL);
7689  assert(reopt->glbconss[c]->nvars > 0);
7690 
7691  cons = NULL;
7692  consvars = NULL;
7693  nbinvars = 0;
7694  nintvars = 0;
7695 
7696  /* check if we can use a logic-or or if we have to use a bounddisjuction constraint */
7697  for( v = 0; v < reopt->glbconss[c]->nvars; v++ )
7698  {
7699  if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_BINARY )
7700  ++nbinvars;
7701  else if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_INTEGER
7702  || SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_IMPLINT )
7703  ++nintvars;
7704  else
7705  {
7706  SCIPerrorMessage("Expected variable type binary or (impl.) integer for variable <%s> in global constraint at pos. %d.\n",
7707  SCIPvarGetName(reopt->glbconss[c]->vars[v]), c);
7708  return SCIP_INVALIDDATA;
7709  }
7710  }
7711 
7712  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "glb_%s_%d_%d", reopt->glbconss[c]->constype == REOPT_CONSTYPE_CUT ? "cut" : "inf", reopt->run, c);
7713 
7714  /* @todo use active representatives */
7715 
7716  /* all variables are binary, we can create a logic-or constraint */
7717  if( nbinvars == reopt->glbconss[c]->nvars )
7718  {
7719  SCIPsetDebugMsg(set, "-> add logic-or constraints with %d binvars\n", nbinvars);
7720 
7721  /* allocate buffer */
7722  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
7723 
7724  for( v = 0; v < reopt->glbconss[c]->nvars; v++ )
7725  {
7726  consvars[v] = reopt->glbconss[c]->vars[v];
7727  assert(SCIPvarIsOriginal(consvars[v]));
7728 
7729  /* negate the variable if it was fixed to 1 */
7730  if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 0.0) )
7731  {
7732  assert(reopt->glbconss[c]->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
7733  SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
7734  }
7735  }
7736 
7737  /* create the logic-or constraint */
7738  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->glbconss[c]->nvars,
7739  consvars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7740 
7741  /* free buffer */
7742  SCIPfreeBufferArray(scip, &consvars);
7743  }
7744  /* not all variables are binary, we need a bounddisjunction constraint */
7745  else
7746  {
7747  assert(reopt->glbconss[c]->nvars == nbinvars + 2*nintvars);
7748 
7749  SCIPsetDebugMsg(set, "-> add bounddisjuction constraints with %d binvars, %d intvars\n", nbinvars, (int) (2*nintvars));
7750 
7751  /* create the bounddisjuction constraint */
7752  SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, name, reopt->glbconss[c]->nvars, reopt->glbconss[c]->vars,
7753  reopt->glbconss[c]->boundtypes, reopt->glbconss[c]->vals) );
7754  }
7755 
7756 #ifdef SCIP_DEBUG_CONSS
7757  SCIPdebugPrintCons(scip, cons, NULL);
7758 #endif
7759 
7760  SCIP_CALL( SCIPaddCons(scip, cons) );
7761 
7762  /* remember the constraint for re-activation */
7763  assert(!SCIPhashsetExists(reopt->activeconssset, (void*)cons));
7764  SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)cons) );
7765  SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, reopt->nactiveconss + 1) );
7766  assert(reopt->nactiveconss < reopt->nmaxactiveconss);
7767  reopt->activeconss[reopt->nactiveconss++] = cons;
7768 
7769  /* don't release the constraint because we would need to capture the constraint anyway */
7770 
7771  /* mark the constraint as empty */
7772  reopt->glbconss[c]->nvars = 0;
7773  }
7774 
7775  SCIPsetDebugMsg(set, "added %d gobal constraints\n", reopt->nglbconss);
7776 
7777  /* reset number of global constraints */
7778  reopt->nglbconss = 0;
7779 
7780  return SCIP_OKAY;
7781 }
7782 
7783 /** add the stored cuts to the separation storage */
7785  SCIP_REOPT* reopt, /**< reoptimization data structure */
7786  SCIP_NODE* node, /**< current focus node */
7787  SCIP_SEPASTORE* sepastore, /**< separation storage */
7788  SCIP_CUTPOOL* cutpool, /**< global cutpool */
7789  BMS_BLKMEM* blkmem, /**< block memory */
7790  SCIP_SET* set, /**< global SCIP settings */
7791  SCIP_STAT* stat, /**< dynamic problem statistics */
7792  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7793  SCIP_EVENTFILTER* eventfilter, /**< event filter */
7794  SCIP_LP* lp, /**< current LP */
7795  SCIP_Bool root /**< bool whether the current node is the root */
7796  )
7797 {
7798  SCIP_REOPTNODE* reoptnode;
7799  SCIP_Bool infeasible;
7800  unsigned int id;
7801  int ncuts;
7802  int c;
7803 
7804  assert(reopt != NULL);
7805  assert(node != NULL);
7806  assert(sepastore != NULL);
7807  assert(blkmem != NULL);
7808  assert(set != NULL);
7809  assert(stat != NULL);
7810  assert(eventqueue != NULL);
7811  assert(eventfilter != NULL);
7812  assert(lp != NULL);
7813 
7814  id = SCIPnodeGetReoptID(node);
7815  assert(id < reopt->reopttree->reoptnodessize);
7816 
7817  /* skip nodes that are node part of the reoptimization tree */
7818  if( id == 0 && SCIPnodeGetDepth(node) > 0 )
7819  return SCIP_OKAY;
7820 
7821  reoptnode = reopt->reopttree->reoptnodes[id];
7822  assert(reoptnode != NULL);
7823 
7824  ncuts = 0;
7825  for( c = reoptnode->nconss-1; c >= 0; c-- )
7826  {
7827  SCIP_REOPTCONSDATA* cons;
7828 
7829  cons = reoptnode->conss[c];
7830  assert(cons != NULL);
7831 
7832  if( cons->constype == REOPT_CONSTYPE_CUT )
7833  {
7834  SCIP_ROW* cut;
7835  SCIP_COL** cols;
7836  SCIP_Real* vals;
7837  char cutname[SCIP_MAXSTRLEN];
7838  int ncols;
7839  int v;
7840 
7841  SCIP_CALL( SCIPsetAllocBufferArray(set, &cols, cons->nvars) );
7842  SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, cons->nvars) );
7843 
7844  ncols = 0;
7845  for( v = 0; v < cons->nvars; v++ )
7846  {
7847  SCIP_VAR* transvar;
7848 
7849  assert(SCIPvarIsOriginal(cons->vars[v]));
7850 
7851  transvar = SCIPvarGetTransVar(cons->vars[v]);
7852  assert(transvar != NULL);
7853  assert(SCIPvarGetStatus(transvar) == SCIP_VARSTATUS_COLUMN);
7854 
7855  vals[ncols] = cons->vals[v];
7856  cols[ncols] = SCIPvarGetCol(transvar);
7857  assert(cols[ncols] != NULL);
7858 
7859  ++ncols;
7860  }
7861  assert(ncols == cons->nvars);
7862 
7863  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "reoptcut_%d_%d", id, ncuts);
7864  infeasible = FALSE;
7865 
7866  if( id == 0 )
7867  {
7868  SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7870  SCIP_CALL( SCIPcutpoolAddRow(cutpool, blkmem, set, stat, lp, cut) );
7871 
7872  SCIPsetDebugMsg(set, "add cut <%s> of size %d to cutpool, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7873  ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7874  }
7875  else
7876  {
7877  SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7879  SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, FALSE, root,
7880  &infeasible) );
7881 
7882  SCIPsetDebugMsg(set, "add cut <%s> of size %d to sepastore, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7883  ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7884  }
7885 
7886  SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
7887 
7888  if( infeasible )
7889  SCIPsetDebugMsg(set, "cut %d stored at node %" SCIP_LONGINT_FORMAT " (id: %u) is infeasible.\n", c, SCIPnodeGetNumber(node), id);
7890  else
7891  ++ncuts;
7892 
7893  SCIPsetFreeBufferArray(set, &vals);
7894  SCIPsetFreeBufferArray(set, &cols);
7895 
7896  BMSfreeBlockMemoryArrayNull(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
7897  BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
7898  BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
7899  BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866*/
7900  --reoptnode->nconss;
7901  }
7902  else
7903  {
7904 #ifndef NDEBUG
7905  int i;
7906  for( i = c-1; i >= 0; i-- )
7907  assert(reoptnode->conss[i]->constype != REOPT_CONSTYPE_CUT);
7908 #endif
7909  break;
7910  }
7911  }
7912 
7913  return SCIP_OKAY;
7914 }
7915 
7916 /** check if the LP of the given node should be solved or not */
7918  SCIP_REOPT* reopt, /**< reoptimization data structure */
7919  SCIP_SET* set, /**< global SCIP settings */
7920  SCIP_NODE* node /**< node of the current search tree */
7921  )
7922 {
7923  unsigned int id;
7924 
7925  assert(reopt != NULL);
7926  assert(node != NULL);
7927 
7928  /* get the ID */
7929  id = SCIPnodeGetReoptID(node);
7930  assert(id < reopt->reopttree->reoptnodessize);
7931 
7932  /* return if the node is not part of the reoptimization tree */
7933  if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7934  return TRUE;
7935 
7936  /* return always true if the parameter is set to 1.0 */
7937  if( SCIPsetIsGE(set, set->reopt_objsimrootlp, 1.0) )
7938  return TRUE;
7939 
7940  /* current node is the root */
7941  if( id == 0 )
7942  {
7943  if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
7944  {
7945  /* the objective function has changed only slightly */
7946  if( SCIPsetIsGE(set, reopt->simtolastobj, set->reopt_objsimrootlp) )
7947  return FALSE;
7948  }
7949  }
7950  else
7951  {
7952  /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
7953  if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
7954  {
7955  assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
7956  return FALSE;
7957  }
7958  }
7959 
7960  return TRUE;
7961 }
7962 
7963 /** initialize an empty node */
7965  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
7966  SCIP_SET* set /**< global SCIP settings */
7967  )
7968 {
7969  assert(reoptnode != NULL);
7970  assert(set != NULL);
7971 
7972  reoptnode->conss = NULL;
7973  reoptnode->nconss = 0;
7974  reoptnode->consssize = 0;
7975  reoptnode->childids = NULL;
7976  reoptnode->allocchildmem = 0;
7977  reoptnode->nchilds = 0;
7978  reoptnode->nvars = 0;
7979  reoptnode->nafterdualvars = 0;
7980  reoptnode->parentID = 0;
7981  reoptnode->dualreds = FALSE;
7982  reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
7983  reoptnode->varssize = 0;
7984  reoptnode->afterdualvarssize = 0;
7985  reoptnode->vars = NULL;
7986  reoptnode->varbounds = NULL;
7987  reoptnode->varboundtypes = NULL;
7988  reoptnode->afterdualvars = NULL;
7989  reoptnode->afterdualvarbounds = NULL;
7990  reoptnode->afterdualvarboundtypes = NULL;
7991  reoptnode->dualredscur = NULL;
7992  reoptnode->dualredsnex = NULL;
7993  reoptnode->lowerbound = -SCIPsetInfinity(set);
7994 }
7995 
7996 /** reset the given reoptimization node */
7998  SCIP_REOPT* reopt, /**< reoptimization data structure */
7999  SCIP_SET* set, /**< global SCIP settings */
8000  BMS_BLKMEM* blkmem, /**< block memory */
8001  SCIP_REOPTNODE* reoptnode /**< reoptimization node */
8002  )
8003 {
8004  assert(reopt != NULL);
8005  assert(set != NULL);
8006  assert(blkmem != NULL);
8007  assert(reoptnode != NULL);
8008 
8009  SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
8010 
8011  return SCIP_OKAY;
8012 }
8013 
8014 /** delete the given reoptimization node */
8016  SCIP_REOPTNODE** reoptnode, /**< pointer of reoptnode */
8017  BMS_BLKMEM* blkmem /**< block memory */
8018  )
8019 {
8020  assert(reoptnode != NULL);
8021  assert(blkmem != NULL);
8022 
8023  SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
8024 
8025  return SCIP_OKAY;
8026 }
8027 
8028 /** add a variable to a given reoptnode */
8030  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
8031  SCIP_SET* set, /**< global SCIP settings */
8032  BMS_BLKMEM* blkmem, /**< block memory */
8033  SCIP_VAR* var, /**< variable to add */
8034  SCIP_Real val, /**< value of the variable */
8035  SCIP_BOUNDTYPE boundtype /**< boundtype of the variable */
8036  )
8037 {
8038  int nvars;
8039 
8040  assert(reoptnode != NULL);
8041  assert(var != NULL);
8042  assert(blkmem != NULL);
8043 
8044  nvars = reoptnode->nvars;
8045 
8046  SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, nvars + 1, 0, 0) );
8047 
8048  reoptnode->vars[nvars] = var;
8049  reoptnode->varbounds[nvars] = val;
8050  reoptnode->varboundtypes[nvars] = boundtype;
8051  ++reoptnode->nvars;
8052 
8053  return SCIP_OKAY;
8054 }
8055 
8056 /** add a constraint to a given reoptnode */
8058  SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
8059  SCIP_SET* set, /**< global SCIP settings */
8060  BMS_BLKMEM* blkmem, /**< block memory */
8061  SCIP_VAR** vars, /**< variables which are part of the constraint */
8062  SCIP_Real* bounds, /**< bounds of the variables */
8063  SCIP_BOUNDTYPE* boundtypes, /**< boundtypes of the variables (or NULL is the constraint is a cut) */
8064  SCIP_Real lhs, /**< lhs of the constraint */
8065  SCIP_Real rhs, /**< rhs of the constraint */
8066  int nvars, /**< number of variables */
8067  REOPT_CONSTYPE constype, /**< type of the constraint */
8068  SCIP_Bool linear /**< the given constraint has a linear representation */
8069  )
8070 {
8071  int nconss;
8072 
8073  assert(reoptnode != NULL);
8074  assert(set != NULL);
8075  assert(vars != NULL);
8076  assert(bounds != NULL);
8077  assert(constype == REOPT_CONSTYPE_CUT || boundtypes != NULL);
8078  assert(nvars > 0);
8079  assert(blkmem != NULL);
8080 
8081  /* the constraint can be interpreted as a normal bound change */
8082  if( nvars == 1 && constype != REOPT_CONSTYPE_CUT )
8083  {
8084  assert(constype == REOPT_CONSTYPE_DUALREDS || constype == REOPT_CONSTYPE_INFSUBTREE);
8085 
8086  SCIPsetDebugMsg(set, "-> constraint has size 1 -> save as normal bound change.\n");
8087 
8088  if( SCIPvarGetType(vars[0]) == SCIP_VARTYPE_BINARY )
8089  {
8090  SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], 1-bounds[0],
8091  1-bounds[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
8092  }
8093  else
8094  {
8095  SCIP_Real newbound;
8096  SCIP_BOUNDTYPE newboundtype;
8097 
8098  assert(SCIPvarGetType(vars[0]) == SCIP_VARTYPE_INTEGER);
8099  assert(boundtypes != NULL);
8100 
8101  if( boundtypes[0] == SCIP_BOUNDTYPE_UPPER )
8102  {
8103  newbound = bounds[0] + 1.0;
8104  assert(SCIPsetIsLE(set, newbound, SCIPvarGetUbLocal(vars[0])));
8105 
8106  newboundtype = SCIP_BOUNDTYPE_LOWER;
8107  }
8108  else
8109  {
8110  newbound = bounds[0] - 1.0;
8111  assert(SCIPsetIsGE(set, newbound, SCIPvarGetLbLocal(vars[0])));
8112 
8113  newboundtype = SCIP_BOUNDTYPE_UPPER;
8114  }
8115 
8116  SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], newbound, newboundtype) );
8117  }
8118  }
8119  else
8120  {
8121  nconss = reoptnode->nconss;
8122 
8123  SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, 0, 0, nconss+1) );
8124 
8125  /* create the constraint */
8126  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
8127  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, vars, nvars) );
8128  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, bounds, nvars) );
8129  if( boundtypes != NULL )
8130  {
8131  assert(!linear);
8132  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->boundtypes, boundtypes, nvars) );
8133  }
8134  else
8135  reoptnode->conss[nconss]->boundtypes = NULL;
8136 
8137  reoptnode->conss[nconss]->varssize = nvars;
8138  reoptnode->conss[nconss]->nvars = nvars;
8139  reoptnode->conss[nconss]->lhs = lhs;
8140  reoptnode->conss[nconss]->rhs = rhs;
8141  reoptnode->conss[nconss]->constype = constype;
8142  reoptnode->conss[nconss]->linear = linear;
8143  ++reoptnode->nconss;
8144  }
8145  return SCIP_OKAY;
8146 }
8147 
8148 /** add a constraint to the reoptimization data structure */
8150  SCIP_REOPT* reopt, /**< reoptimization data structure */
8151  SCIP_SET* set, /**< global SCIP settings */
8152  BMS_BLKMEM* blkmem, /**< block memory */
8153  SCIP_CONS* cons /**< constraint to add */
8154  )
8155 {
8156  assert(reopt != NULL);
8157  assert(set != NULL);
8158  assert(blkmem != NULL);
8159  assert(cons != NULL);
8160 
8161 #ifdef SCIP_MORE_DEBUG
8162  SCIPsetDebugMsg(set, "add cons <%s> to reoptimization data\n", SCIPconsGetName(cons));
8163 #endif
8164 
8165  /* check memory */
8166  if( reopt->addedconsssize == 0 )
8167  {
8168  assert(reopt->addedconss == NULL);
8169 
8170  reopt->addedconsssize = 10;
8172  }
8173  else if( reopt->naddedconss == reopt->addedconsssize )
8174  {
8175  int newsize = SCIPsetCalcMemGrowSize(set, reopt->addedconsssize+1);
8176  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize, newsize) );
8177 
8178  /* clear the array */
8179  BMSclearMemoryArray(&reopt->addedconss[reopt->addedconsssize], newsize - reopt->addedconsssize); /*lint !e866 */
8180 
8181  reopt->addedconsssize = newsize;
8182  }
8183  assert(reopt->naddedconss < reopt->addedconsssize);
8184  assert(reopt->addedconss[reopt->naddedconss] == NULL);
8185 
8186  reopt->addedconss[reopt->naddedconss] = cons;
8187  reopt->consadded = TRUE;
8188  ++reopt->naddedconss;
8189 
8190  /* capture the constraint */
8191  SCIPconsCapture(cons);
8192 
8193  return SCIP_OKAY;
8194 }
8195 
8196 /** save global lower and upper bounds
8197  *
8198  * @note this method should only be called once, i.e., after fishing presolving of the first problem
8199  */
8201  SCIP_REOPT* reopt, /**< reoptimization data structure */
8202  SCIP_PROB* transprob, /**< transformed problem data */
8203  BMS_BLKMEM* blkmem /**< block memory */
8204  )
8205 {
8206  SCIP_VAR** vars;
8207  int nvars;
8208  int i;
8209 
8210  assert(reopt != NULL);
8211  assert(transprob != NULL);
8212  assert(reopt->glblb == NULL && reopt->glbub == NULL);
8213 
8214  nvars = SCIPprobGetNVars(transprob);
8215  vars = SCIPprobGetVars(transprob);
8216 
8217  /* create hashmaps */
8218  SCIP_CALL( SCIPhashmapCreate(&reopt->glbub, blkmem, nvars) );
8219  SCIP_CALL( SCIPhashmapCreate(&reopt->glblb, blkmem, nvars) );
8220 
8221  /* store the global bounds */
8222  for( i = 0; i < nvars; i++ )
8223  {
8224  assert(!SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8225  assert(!SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8226 
8227  SCIP_CALL( SCIPhashmapInsertReal(reopt->glblb, (void*)vars[i], SCIPvarGetLbGlobal(vars[i])) );
8228  SCIP_CALL( SCIPhashmapInsertReal(reopt->glbub, (void*)vars[i], SCIPvarGetUbGlobal(vars[i])) );
8229  }
8230 
8231  return SCIP_OKAY;
8232 }
8233 
8234 /** save active constraints
8235  *
8236  * @note this method can only called once, i.e., after fishing presolving of the first problem
8237  */
8239  SCIP_REOPT* reopt, /**< reoptimization data structure */
8240  SCIP_SET* set, /**< global SCIP settings */
8241  SCIP_PROB* transprob, /**< transformed problem data */
8242  BMS_BLKMEM* blkmem /**< block memory */
8243  )
8244 {
8245  SCIP_CONS** conss;
8246  int nconss;
8247  int i;
8248 
8249  assert(reopt != NULL);
8250  assert(transprob != NULL);
8251  assert(reopt->activeconss == NULL);
8252  assert(reopt->activeconssset == NULL);
8253  assert(reopt->nactiveconss == 0);
8254  assert(reopt->nmaxactiveconss == 0);
8255 
8256  conss = transprob->conss;
8257  nconss = transprob->nconss;
8258 
8259  SCIPsetDebugMsg(set, "save %d active conss\n", nconss);
8260 
8261  /* create hashset and array */
8262  SCIP_CALL( SCIPhashsetCreate(&reopt->activeconssset, blkmem, nconss) );
8263  SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, nconss) );
8264 
8265  for( i = 0; i < nconss; i++ )
8266  {
8267  assert(SCIPconsIsActive(conss[i]));
8268  assert(!SCIPhashsetExists(reopt->activeconssset, (void*)conss[i]));
8269 
8270  SCIPconsCapture(conss[i]);
8271  SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)conss[i]) );
8272  reopt->activeconss[reopt->nactiveconss++] = conss[i];
8273  }
8274 
8275  return SCIP_OKAY;
8276 }
8277 
8278 /** installs global lower and upper bounds */
8280  SCIP_REOPT* reopt, /**< reoptimization data structure */
8281  SCIP_SET* set, /**< global SCIP settings */
8282  SCIP_STAT* stat, /**< dynamic SCIP statistics */
8283  SCIP_PROB* transprob, /**< transformed problem data */
8284  SCIP_LP* lp, /**< current LP data */
8285  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8286  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8287  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8288  BMS_BLKMEM* blkmem /**< block memory */
8289  )
8290 {
8291  SCIP_VAR** vars;
8292  int nvars;
8293  int i;
8294 
8295  assert(reopt != NULL);
8296  assert(transprob != NULL);
8297  assert(reopt->glblb != NULL && reopt->glbub != NULL);
8298  assert(SCIPprobIsTransformed(transprob));
8299 
8300  nvars = SCIPprobGetNVars(transprob);
8301  vars = SCIPprobGetVars(transprob);
8302 
8303  /* install global lower and upper bounds */
8304  for( i = 0; i < nvars; i++ )
8305  {
8306  SCIP_Real lb;
8307  SCIP_Real ub;
8308 
8309  assert(SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8310  assert(SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8311 
8312  lb = SCIPhashmapGetImageReal(reopt->glblb, (void*)vars[i]);
8313  ub = SCIPhashmapGetImageReal(reopt->glbub, (void*)vars[i]);
8314  assert(lb < SCIP_INVALID && ub < SCIP_INVALID);
8315 
8316  /* reset the global bounds back */
8317  SCIP_CALL( SCIPvarChgLbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, lb) );
8318  SCIP_CALL( SCIPvarChgUbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, ub) );
8319 
8320  /* reset the local bounds back */
8321  SCIP_CALL( SCIPvarChgLbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, lb) );
8322  SCIP_CALL( SCIPvarChgUbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, ub) );
8323  }
8324 
8325  return SCIP_OKAY;
8326 }
8327 
8328 /** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
8330  SCIP_REOPT* reopt, /**< reoptimization data structure */
8331  SCIP_SET* set, /**< global SCIP settings */
8332  SCIP_STAT* stat /**< dynamic SCIP statistics */
8333  )
8334 {
8335  int i;
8336 
8337  assert(reopt != NULL);
8338  assert(reopt->activeconss != NULL || reopt->nmaxactiveconss == 0);
8339  assert(reopt->activeconssset != NULL || reopt->nmaxactiveconss == 0);
8340  assert(reopt->nmaxactiveconss >= 0);
8341 
8342  SCIPsetDebugMsg(set, "Reset %d active conss.\n", reopt->nactiveconss);
8343 
8344  /* loop over all storeed active constraints and reactivate deactivated constraints */
8345  for( i = 0; i < reopt->nactiveconss; i++ )
8346  {
8347  SCIP_CONS* cons;
8348 
8349  assert(reopt->activeconss != NULL);
8350  cons = reopt->activeconss[i];
8351  assert(cons != NULL);
8352  assert(SCIPhashsetExists(reopt->activeconssset, cons));
8353 
8354  /* it can happen that the constraint got globally deleted */
8355  if( SCIPconsIsDeleted(cons) )
8356  cons->deleted = FALSE;
8357 
8358  /* to ensure that the constraint will be added to all the data structures we need to deactivate the
8359  * constraint first.
8360  */
8361  if( SCIPconsIsActive(cons) )
8362  {
8363  SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
8364  }
8365  SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, TRUE) );
8366  }
8367 
8368  return SCIP_OKAY;
8369 }
8370 
8371 /** returns whether a constraint is necessary to ensure correctness and cannot be deleted */
8373  SCIP_REOPT* reopt, /**< reoptimization data structure */
8374  SCIP_CONS* cons /**< problem constraint */
8375  )
8376 {
8377  assert(reopt != NULL);
8378  assert(cons != NULL);
8379 
8380  /* the hashset is not initialized, we can delete all constraints */
8381  if( reopt->activeconss == NULL )
8382  return TRUE;
8383 
8384  return !SCIPhashsetExists(reopt->activeconssset, (void*)cons);
8385 }
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:6948
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:5158
void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
Definition: tree.c:7634
SCIP_RETCODE SCIPreoptApplyGlbConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: reopt.c:7660
#define DEFAULT_MEM_NODES
Definition: reopt.c:53
SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
Definition: set.c:4744
SCIP_Real SCIPreoptGetSimToPrevious(SCIP_REOPT *reopt)
Definition: reopt.c:5663
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6200
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:6292
#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:5965
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:7346
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:6258
internal methods for storing primal CIP solutions
static void resetStats(SCIP_REOPT *reopt)
Definition: reopt.c:4318
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:7784
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:17304
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:7394
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:6598
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:5714
int SCIPreoptGetNImprovingSols(SCIP_REOPT *reopt)
Definition: reopt.c:5473
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7452
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:4657
#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:5056
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:6455
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:5036
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7712
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:5328
void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
Definition: tree.c:7513
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:5381
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6065
SCIP_RETCODE SCIPreoptAddCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons)
Definition: reopt.c:8149
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:17160
int SCIPreoptGetNFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4996
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:8015
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:4852
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:5853
SCIP_Longint lastseennode
Definition: struct_reopt.h:145
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17225
#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:6723
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:7917
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:6312
#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:1719
#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:5186
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:8057
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5779
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:6409
void SCIPreoptResetSolMarks(SCIP_REOPT *reopt)
Definition: reopt.c:5792
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:5728
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:17545
#define SCIPdebugMessage
Definition: pub_message.h:87
int SCIPreoptGetNDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:6382
static SCIP_RETCODE dryBranch(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool *runagain, unsigned int id)
Definition: reopt.c:4343
#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:10181
SCIP_Bool SCIPreoptConsCanBeDeleted(SCIP_REOPT *reopt, SCIP_CONS *cons)
Definition: reopt.c:8372
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:4610
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6334
SCIP_SOL ** prevbestsols
Definition: struct_reopt.h:132
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7442
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17364
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:1726
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:4986
#define SCIPdebugMsg
Definition: scip_message.h:69
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13081
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:7786
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:8329
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:5916
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6294
int SCIPreoptGetNNodes(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:5813
SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
Definition: scip_solve.c:3584
#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:5681
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:7432
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:6240
SCIP_VAR * w
Definition: circlepacking.c:58
SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
Definition: tree.c:7472
SCIP_RETCODE SCIPreoptGetSolsRun(SCIP_REOPT *reopt, int run, SCIP_SOL **sols, int solssize, int *nsols)
Definition: reopt.c:5525
int SCIPreoptGetNRestartsGlobal(SCIP_REOPT *reopt)
Definition: reopt.c:4946
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:4976
#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:5046
int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5886
#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:4683
#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:2768
int SCIPreoptGetNSols(SCIP_REOPT *reopt)
Definition: reopt.c:5509
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
void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
Definition: tree.c:7537
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:6889
SCIP_Bool objhaschanged
Definition: struct_reopt.h:149
static int reoptGetNLeaves(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:4579
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:5076
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:5066
void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7823
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:101
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1723
#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:4013
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:7964
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:6686
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17555
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:7242
#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:7267
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17235
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:6222
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:6642
unsigned int * childids
Definition: struct_reopt.h:105
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17171
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:5345
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:3321
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:5304
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:7589
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:8279
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:6519
#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:6345
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17181
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:4135
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:5700
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:6402
#define SCIP_Bool
Definition: def.h:84
void SCIPreoptAddNImprovingSols(SCIP_REOPT *reopt, int nimprovingsols)
Definition: reopt.c:5483
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:6024
#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:5594
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:4247
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:3201
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9440
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:4804
SCIP_RETCODE SCIPsetGetIntParam(SCIP_SET *set, const char *name, int *value)
Definition: set.c:3167
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:460
void SCIPreoptnodeSetParentID(SCIP_REOPTNODE *reoptnode, unsigned int parentid)
Definition: reopt.c:5953
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:1755
#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:5494
unsigned int reoptnodessize
Definition: struct_reopt.h:126
SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5906
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:7952
SCIP_RETCODE SCIPreoptnodeAddBndchg(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real val, SCIP_BOUNDTYPE boundtype)
Definition: reopt.c:8029
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:6620
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:7326
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:118
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9417
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:1990
int SCIPreoptGetNRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:4956
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:4560
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17191
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:5896
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
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:16975
void SCIPreoptAddNCheckedSols(SCIP_REOPT *reopt, int ncheckedsols)
Definition: reopt.c:5462
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:8442
#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:6000
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:6827
unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
Definition: tree.c:7503
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:6666
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:4713
SCIP_RETCODE SCIPreoptnodeReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:7997
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:6276
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1945
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17370
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17434
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:7422
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:4900
int SCIPreoptnodeGetNDualBoundChgs(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5873
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:5104
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:8238
int SCIPreoptGetNTotalPrunedNodes(SCIP_REOPT *reopt)
Definition: reopt.c:5026
SCIP_RETCODE SCIPcutpoolAddRow(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_ROW *row)
Definition: cutpool.c:645
int SCIPreoptGetNTotalFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:5006
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:7482
SCIP_Real SCIPreoptGetSimToFirst(SCIP_REOPT *reopt)
Definition: reopt.c:5672
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:5016
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:5567
#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:5756
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:8200
int SCIPreoptGetNTotalRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:4966
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:7650
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:5744
void SCIPnodeGetConsProps(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nconspropvars, int conspropvarssize)
Definition: tree.c:7864
#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:6571
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:402
SCIP callable library.
int SCIPreoptGetNCheckedSols(SCIP_REOPT *reopt)
Definition: reopt.c:5452
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:5863
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:5416
memory allocation routines