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