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-2025 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"
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 */
75static
76SCIP_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) */
113static
114SCIP_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
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 {
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) */
138static
139SCIP_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
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 */
170static
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 */
191static
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 */
218static
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 */
254static
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 */
286static
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 */
366static
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 */
395static
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 */
482static
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 */
603static
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 */
679static
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 */
711static
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 */
743static
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 */
785static
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 */
813static
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 */
994static
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 */
1081static
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 */
1115static
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 */
1172static
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 */
1216static
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 */
1252static
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 */
1276static
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 */
1310static
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 */
1350static
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 propagations during current iteration; stop saving the bound changes if
1384 * we reach a branching decision based on a dual information
1385 */
1386static
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 npropprops;
1399 int naddedbndchgs;
1400
1401 assert(reopt != NULL);
1402 assert(blkmem != NULL);
1403 assert(node != NULL);
1404 assert(0 < id && id < reopt->reopttree->reoptnodessize);
1405 assert(reopt->reopttree->reoptnodes[id] != NULL );
1406
1407 /* get the number of all stored constraint and propagator propagations */
1408 SCIPnodeGetNDomchg(node, NULL, &nconsprops, &npropprops);
1409 nvars = reopt->reopttree->reoptnodes[id]->nvars;
1410
1411 if( nconsprops > 0 || npropprops > 0 )
1412 {
1413 /* check the memory */
1414 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, nvars + nconsprops + npropprops, 0, 0) );
1415
1417 &reopt->reopttree->reoptnodes[id]->vars[nvars],
1418 &reopt->reopttree->reoptnodes[id]->varbounds[nvars],
1419 &reopt->reopttree->reoptnodes[id]->varboundtypes[nvars],
1420 &naddedbndchgs,
1421 reopt->reopttree->reoptnodes[id]->varssize-nvars);
1422
1423 assert(nvars + naddedbndchgs <= reopt->reopttree->reoptnodes[id]->varssize);
1424
1425 reopt->reopttree->reoptnodes[id]->nvars += naddedbndchgs;
1426
1427 *transintoorig = TRUE;
1428 }
1429
1430 return SCIP_OKAY;
1431}
1432
1433/** save bound changes made after the first bound change based on dual information, e.g., mode by strong branching
1434 *
1435 * This method can be used during reoptimization. If we want to reconstruct a node containing dual bound changes we
1436 * have to split the node into the original one and at least one node representing the pruned part. All bound changes,
1437 * i.e., (constraint) propagation, made after the first bound change based on dual information are still valid for
1438 * the original node after changing the objective function. thus, we can store them for the following iterations.
1439 *
1440 * It should be noted, that these bound changes will be found by (constraint) propagation methods anyway after changing
1441 * the objective function. do not saving these information and find them again might be useful for conflict analysis.
1442 */
1443static
1445 SCIP_REOPT* reopt, /**< reoptimization data structure */
1446 SCIP_SET* set, /**< global SCIP settings */
1447 BMS_BLKMEM* blkmem, /**< block memory */
1448 SCIP_NODE* node, /**< node of the search tree */
1449 unsigned int id, /**< id of the node */
1450 SCIP_Bool* transintoorig /**< transform variables into originals */
1451 )
1452{
1453 int nbranchvars;
1454
1455 assert(reopt != NULL);
1456 assert(blkmem != NULL);
1457 assert(node != NULL);
1458 assert(0 < id && id < reopt->reopttree->reoptnodessize);
1459 assert(reopt->reopttree->reoptnodes[id] != NULL );
1460
1461 nbranchvars = 0;
1462
1463 /* allocate memory */
1464 if (reopt->reopttree->reoptnodes[id]->afterdualvarssize == 0)
1465 {
1466 assert(reopt->reopttree->reoptnodes[id]->afterdualvars == NULL );
1467 assert(reopt->reopttree->reoptnodes[id]->afterdualvarbounds == NULL );
1468 assert(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes == NULL );
1469
1470 /* allocate block memory for node information */
1473 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1475 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1477 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
1478 }
1479
1480 assert(reopt->reopttree->reoptnodes[id]->afterdualvarssize > 0);
1481 assert(reopt->reopttree->reoptnodes[id]->nafterdualvars >= 0);
1482
1487 &nbranchvars,
1489
1490 if( nbranchvars > reopt->reopttree->reoptnodes[id]->afterdualvarssize - reopt->reopttree->reoptnodes[id]->nafterdualvars )
1491 {
1492 int newsize = SCIPsetCalcMemGrowSize(set, reopt->reopttree->reoptnodes[id]->nafterdualvars + nbranchvars);
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
1505 &nbranchvars,
1507 }
1508
1509 /* the stored variables of this node need to be transformed into the original space */
1510 if( nbranchvars > 0 )
1511 *transintoorig = TRUE;
1512
1513 SCIPsetDebugMsg(set, " -> save %d bound changes after dual reductions\n", nbranchvars);
1514
1515 assert(reopt->reopttree->reoptnodes[id]->nafterdualvars + nbranchvars <= reopt->reopttree->reoptnodes[id]->afterdualvarssize); /* this should be the case */
1516
1517 reopt->reopttree->reoptnodes[id]->nafterdualvars += nbranchvars;
1518
1519 return SCIP_OKAY;
1520}
1521
1522/** store cuts that are active in the current LP */
1523static
1525 SCIP_REOPT* reopt, /**< reoptimization data structure */
1526 SCIP_SET* set, /**< global SCIP settings */
1527 BMS_BLKMEM* blkmem, /**< block memory */
1528 SCIP_LP* lp, /**< current LP */
1529 unsigned int id /**< id in the reopttree */
1530 )
1531{
1532 SCIP_ROW** lprows;
1533 int nlprows;
1534
1535 assert(reopt != NULL);
1536 assert(set != NULL);
1537 assert(lp != NULL);
1538 assert(blkmem != NULL);
1539
1540 lprows = SCIPlpGetRows(lp);
1541 nlprows = SCIPlpGetNRows(lp);
1542
1543 for( int r = 0; r < nlprows; ++r )
1544 {
1545 /* we can break if we reach the first row that is not part of the current LP */
1546 if( SCIProwGetLPPos(lprows[r]) == -1 )
1547 break;
1548
1549 /* currently we only want to store cuts generated by a seperator */
1550 if( SCIProwGetOrigintype(lprows[r]) == SCIP_ROWORIGINTYPE_SEPA && SCIProwGetAge(lprows[r]) <= set->reopt_maxcutage )
1551 {
1552 SCIP_VAR** cutvars;
1553 SCIP_COL** cols;
1554 SCIP_Real* cutvals;
1555 SCIP_Real lhs;
1556 SCIP_Real rhs;
1557 int ncutvars;
1558 SCIP_Bool storecut;
1559
1560 ncutvars = SCIProwGetNLPNonz(lprows[r]);
1561 lhs = SCIProwGetLhs(lprows[r]);
1562 rhs = SCIProwGetRhs(lprows[r]);
1563
1564 /* subtract row constant */
1565 if( !SCIPsetIsInfinity(set, -lhs) )
1566 lhs -= SCIProwGetConstant(lprows[r]);
1567 if( !SCIPsetIsInfinity(set, rhs) )
1568 rhs -= SCIProwGetConstant(lprows[r]);
1569
1570 cutvals = SCIProwGetVals(lprows[r]);
1571 cols = SCIProwGetCols(lprows[r]);
1572 storecut = TRUE;
1573
1574 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutvars, ncutvars) );
1575
1576 for( int c = 0; c < ncutvars; ++c )
1577 {
1578 SCIP_Real constant;
1579 SCIP_Real scalar;
1580
1581 cutvars[c] = SCIPcolGetVar(cols[c]);
1582 assert(cutvars[c] != NULL);
1583
1584 constant = 0.0;
1585 scalar = 1.0;
1586
1587 SCIP_CALL( SCIPvarGetOrigvarSum(&cutvars[c], &scalar, &constant) );
1588
1589 /* the cut contains an artificial variable that might not be present after modifying the problem */
1590 if( cutvars[c] != NULL )
1591 {
1592 storecut = FALSE;
1593 break;
1594 }
1595
1596 assert(cutvars[c] != NULL);
1597 assert(!SCIPsetIsZero(set, scalar));
1598
1599 /* subtract constant from sides */
1600 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, -lhs) )
1601 lhs -= constant;
1602 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, rhs) )
1603 rhs -= constant;
1604
1605 cutvals[c] = cutvals[c]/scalar;
1606 }
1607
1608 if( storecut )
1609 {
1610 /* add cut as a linear constraint */
1611 SCIP_CALL( SCIPreoptnodeAddCons(reopt->reopttree->reoptnodes[id], set, blkmem, cutvars, cutvals, NULL,
1612 lhs, rhs, ncutvars, REOPT_CONSTYPE_CUT, TRUE) );
1613 }
1614
1615 SCIPsetFreeBufferArray(set, &cutvars);
1616 }
1617 }
1618
1619 return SCIP_OKAY;
1620}
1621
1622/** transform variable and bounds back to the original space */
1623static
1625 SCIP_REOPT* reopt, /**< reoptimization data structure */
1626 unsigned int id /**< id of the node */
1627 )
1628{
1629 assert(reopt != NULL );
1630 assert(0 < id && id < reopt->reopttree->reoptnodessize);
1631 assert(reopt->reopttree->reoptnodes[id] != NULL );
1632
1633 /* transform branching variables and bound changes applied before the first dual reduction */
1634 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
1635 {
1636 SCIP_Real constant = 0.0;
1637 SCIP_Real scalar = 1.0;
1638
1639 if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]) )
1640 {
1641 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->vars[varnr], &scalar, &constant)) ;
1642 reopt->reopttree->reoptnodes[id]->varbounds[varnr] = (reopt->reopttree->reoptnodes[id]->varbounds[varnr] - constant) / scalar;
1643 }
1644 assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]));
1645 }
1646
1647 /* transform bound changes affected by dual reduction */
1648 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
1649 {
1650 SCIP_Real constant = 0.0;
1651 SCIP_Real scalar = 1.0;
1652
1653 if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]) )
1654 {
1655 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->afterdualvars[varnr], &scalar, &constant)) ;
1656 reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]
1657 = (reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr] - constant) / scalar;
1658 }
1659 assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]));
1660 }
1661
1662 return SCIP_OKAY;
1663}
1664
1665/** search the next node along the root path that was saved by reoptimization */
1666static
1668 SCIP_REOPT* reopt, /**< reoptimization data structure */
1669 SCIP_SET* set, /**< global SCIP settings */
1670 SCIP_NODE* node, /**< node of the search tree */
1671 SCIP_NODE** parent, /**< parent node within the search tree */
1672 unsigned int* parentid, /**< id of the parent node */
1673 int* nbndchgs /**< number of bound changes */
1674 )
1675{
1676 assert(reopt != NULL);
1677 assert(reopt->reopttree != NULL);
1678 assert(reopt->reopttree->reoptnodes != NULL);
1679
1680 (*nbndchgs) = 0;
1681 (*parent) = node;
1682
1683 /* look for a saved parent along the root-path */
1684 while( SCIPnodeGetDepth(*parent) != 0 )
1685 {
1686 int nbranchings = 0;
1687 int nconsprop = 0;
1688 int npropprops = 0;
1689
1690 if( set->reopt_saveprop )
1691 SCIPnodeGetNDomchg((*parent), &nbranchings, &nconsprop, &npropprops);
1692 else
1693 SCIPnodeGetNDomchg((*parent), &nbranchings, NULL, NULL);
1694
1695 (*nbndchgs) = (*nbndchgs) + nbranchings + nconsprop + npropprops;
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 */
1728static
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 */
1761static
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 */
1821static
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 */
1867static
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 */
1945static
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 */
1991static
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 */
2024static
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 */
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 */
2112static
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
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
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 */
2181static
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 {
2307 }
2308
2309 return SCIP_OKAY;
2310}
2311
2312/** transform a bounddisjunction constraint into reoptimization constraint data */
2313static
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 */
2382static
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 */
2476static
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 */
2602static
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
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 propagations */
2714 if( set->reopt_saveprop )
2715 {
2716 SCIP_CALL( updatePropagation(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 SCIPsetDebugMsg(set, " -> saved variables:\n");
2732 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
2733 {
2734 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
2736 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
2737 }
2738 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
2739 {
2740 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
2742 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
2743 }
2744#endif
2745
2746 /* update LPI state */
2747 switch( reopttype )
2748 {
2750 if( set->reopt_shrinkinner )
2751 {
2752 SCIP_CALL( shrinkNode(reopt, set, node, id, &shrank, blkmem) );
2753 }
2754 goto TRANSIT;
2755
2758 goto TRANSIT;
2759
2761 /* delete the whole subtree induced be the current node */
2762 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2763 goto PSEUDO;
2764
2766 goto PSEUDO;
2767
2769 /* delete the subtree */
2770 if( set->reopt_reducetofrontier )
2771 {
2772 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2773 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2774 }
2775 /* dive through all children and change the reopttype to PRUNED */
2776 else
2777 {
2779 }
2780 goto FEASIBLE;
2781
2783 /* delete the subtree */
2784 if( set->reopt_reducetofrontier )
2785 {
2786 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
2787 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2788 }
2789 /* dive through all children and change the reopttype to LEAF */
2790 else
2791 {
2793 }
2794
2795 /* increase number of reoptimized nodes that could be pruned */
2796 ++reopt->reopttree->ncutoffreoptnodes;
2798
2799 goto PRUNED;
2800
2801 default:
2802 break;
2803 } /*lint !e788*/
2804
2805 /* stop clock */
2806 SCIPclockStart(reopt->savingtime, set);
2807
2808 return SCIP_OKAY;
2809 }
2810
2811 /* get new IDs */
2812 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
2813
2814 /* the current node is the root node */
2815 if( isrootnode )
2816 {
2817 id = 0;
2818
2819 /* save local constraints
2820 * note: currently, there will be no constraint to save because all global constraints are added by calling
2821 * SCIPprobAddCons.
2822 */
2823 if (SCIPnodeGetNAddedConss(node) >= 1)
2824 {
2825 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
2826
2827 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
2828 }
2829
2830 /* store separated cuts
2831 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
2832 * local constraints, then cuts
2833 */
2834 if( set->reopt_usecuts )
2835 {
2836 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
2837 }
2838
2839 switch( reopttype )
2840 {
2842 /* ensure that no dual constraints are stored */
2843 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2844
2845 /* update the lowerbound */
2846 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2847 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2848
2849 goto TRANSIT;
2850
2853 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)reopttype;
2854 reopt->reopttree->reoptnodes[0]->dualreds = TRUE;
2855 reopt->reopttree->reoptnodes[0]->nvars = 0;
2856
2857 if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
2858 {
2859 /* delete the whole subtree induced be the current node */
2860 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2861 }
2862
2863 /* update the lowerbound */
2864 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2865 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2866
2867 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2868 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
2869 reopt->reopttree->reoptnodes[id]->lowerbound);
2870
2871 goto PSEUDO;
2872
2874 ++reopt->reopttree->ntotalfeasnodes;
2875 ++reopt->reopttree->nfeasnodes;
2876 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
2877 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
2878
2879 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2880 {
2881 /* delete the subtree */
2882 if( set->reopt_reducetofrontier )
2883 {
2884 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2885 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2886 }
2887 /* dive through all children and change the reopttype to LEAF */
2888 else
2889 {
2891 }
2892 }
2893 else
2894 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2895
2896 /* update the lowerbound */
2897 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2898 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2899
2900 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2901 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
2902 reopt->reopttree->reoptnodes[id]->lowerbound);
2903
2904 break;
2905
2907 ++reopt->reopttree->nprunednodes;
2908 ++reopt->reopttree->ntotalprunednodes;
2909 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
2910 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
2911
2912 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
2913 {
2914 /* delete the subtree */
2915 if( set->reopt_reducetofrontier )
2916 {
2917 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
2918 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2919 }
2920 /* dive through all children and change the reopttype to LEAF */
2921 else
2922 {
2924 }
2925 }
2926 else
2927 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
2928
2929 /* update the lowerbound if it was not set */
2930 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
2931 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
2932
2933 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
2934 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound:%g \n", reopttype,
2935 reopt->reopttree->reoptnodes[id]->lowerbound);
2936
2937 break;
2938
2939 default:
2940 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
2941 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
2942 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
2943 || reopttype == SCIP_REOPTTYPE_PRUNED
2944 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
2945 break;
2946 }/*lint !e788*/
2947
2948 /* reset the information of dual bound changes */
2949 reopt->currentnode = -1;
2950 if( reopt->dualreds != NULL )
2951 reopt->dualreds->nvars = 0;
2952
2953 /* stop clock */
2954 SCIPclockStop(reopt->savingtime, set);
2955
2956 return SCIP_OKAY;
2957 }
2958 else
2959 {
2960 int nbndchgdiff;
2961 SCIP_Bool transintoorig;
2962
2963 SCIPsetDebugMsg(set, "try to add node #%lld to the reopttree\n", SCIPnodeGetNumber(node));
2964 SCIPsetDebugMsg(set, " -> reopttype = %d\n", reopttype);
2965
2966 /* check if we really want to save this node:
2967 * 1. save the node if reopttype is at least SCIP_REOPTTYPE_INFSUBTREE
2968 * 2. save the node if the number of bound changes of this node
2969 * and the last saved node is at least a given number n
2970 */
2971
2972 /* get the ID of the last saved node or 0 for the root */
2973 SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &nbndchgdiff) );
2974
2975 if( (reopttype < SCIP_REOPTTYPE_INFSUBTREE && nbndchgdiff <= set->reopt_maxdiffofnodes)
2976 || reopt->reopttree->reoptnodes[parentid]->reopttype >= SCIP_REOPTTYPE_LEAF ) /*lint !e641*/
2977 {
2978 SCIPsetDebugMsg(set, " -> skip saving\n");
2979
2980 /* stop clock */
2981 SCIPclockStop(reopt->savingtime, set);
2982
2983 return SCIP_OKAY;
2984 }
2985
2986 /* check if there are free slots to store the node */
2987 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
2988
2990
2991 SCIPsetDebugMsg(set, " -> save at ID %u\n", id);
2992
2993 assert(reopt->reopttree->reoptnodes[id] == NULL
2994 || (reopt->reopttree->reoptnodes[id]->nvars == 0 && reopt->reopttree->reoptnodes[id]->nconss == 0));
2995 assert(id >= 1 && id < reopt->reopttree->reoptnodessize);
2996 assert(!isrootnode);
2997
2998 /* get memory for nodedata */
2999 assert(reopt->reopttree->reoptnodes[id] == NULL || reopt->reopttree->reoptnodes[id]->nvars == 0);
3000 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, id) );
3001 reopt->reopttree->reoptnodes[id]->parentID = parentid;
3002
3003 assert(parent != NULL );
3004 assert((SCIPnodeGetDepth(parent) == 0 && parentid == 0) || (SCIPnodeGetDepth(parent) >= 1 && parentid > 0));
3005 assert(id >= 1);
3006
3007 /* create the array of "child nodes" if they not exist */
3008 if( reopt->reopttree->reoptnodes[parentid]->childids == NULL
3009 || reopt->reopttree->reoptnodes[parentid]->allocchildmem == 0 )
3010 {
3011 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0, 2, 0) );
3012 }
3013
3014 /* add the new node as a "child node" of the last saved reoptminization node */
3015 SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, id) );
3016
3017 /* save branching path */
3018 SCIP_CALL( saveAncestorBranchings(reopt->reopttree, set, blkmem, node, parent, id, parentid) );
3019
3020 /* save bound changes after some dual reduction */
3021 if( saveafterdual )
3022 {
3023 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
3024 SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
3025 }
3026 else
3027 {
3028 SCIPsetDebugMsg(set, " -> skip saving bound changes after dual reductions.\n");
3029 }
3030
3031 /* transform all bounds of branched variables and ensure that they are original. */
3032 SCIP_CALL( transformIntoOrig(reopt, id) );
3033
3034 /* save pseudo-constraints (if one exists) */
3035 if (SCIPnodeGetNAddedConss(node) >= 1)
3036 {
3037 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
3038
3039 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
3040 }
3041
3042 /* store separated cuts
3043 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
3044 * local constraints, then cuts
3045 */
3046 if( set->reopt_usecuts )
3047 {
3048 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
3049 }
3050
3051 /* update the lowerbound if it was not set */
3052 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
3053 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
3054
3055 /* set ID */
3056 SCIPnodeSetReoptID(node, id);
3057
3058 /* set the REOPTTYPE */
3059 SCIPnodeSetReopttype(node, reopttype);
3060
3061 SCIPsetDebugMsg(set, "save node #%lld successful\n", SCIPnodeGetNumber(node));
3062 SCIPsetDebugMsg(set, " -> nvars: %d, ncons: %d, parentID: %u, reopttype: %d, lowerbound: %g\n",
3063 reopt->reopttree->reoptnodes[id]->nvars + reopt->reopttree->reoptnodes[id]->nafterdualvars,
3064 reopt->reopttree->reoptnodes[id]->nconss, reopt->reopttree->reoptnodes[id]->parentID,
3065 reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
3066#ifdef SCIP_MORE_DEBUG
3067 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
3068 {
3069 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
3071 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
3072 }
3073 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
3074 {
3075 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n",
3076 SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
3078 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
3079 }
3080#endif
3081 } /*lint !e438*/
3082
3083 switch( reopttype )
3084 {
3088 TRANSIT:
3089 if( !shrank )
3090 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
3091 else
3092 {
3093 SCIPnodeSetReoptID(node, 0);
3095 }
3096 break;
3097
3100 PSEUDO:
3101 assert(reopt->currentnode == SCIPnodeGetNumber(node));
3102
3103 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
3104 reopt->reopttree->reoptnodes[id]->dualreds = TRUE;
3105
3106 /* get all the dual information and decide if the constraint need
3107 * to be added next or after next */
3108 SCIP_CALL( collectDualInformation(reopt, set, blkmem, node, id, reopttype) );
3109
3110 break;
3111
3113 FEASIBLE:
3114 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
3115 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
3116 ++reopt->reopttree->nfeasnodes;
3117 ++reopt->reopttree->ntotalfeasnodes;
3118
3119 break;
3120
3122 PRUNED:
3123 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
3124 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
3125 ++reopt->reopttree->nprunednodes;
3126 ++reopt->reopttree->ntotalprunednodes;
3127
3128 break;
3129
3130 default:
3131 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
3132 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
3133 || reopttype == SCIP_REOPTTYPE_LEAF
3134 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
3135 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
3136 || reopttype == SCIP_REOPTTYPE_FEASIBLE
3137 || reopttype == SCIP_REOPTTYPE_PRUNED);
3138 break;
3139 } /*lint !e788*/
3140
3141 /* stop clock */
3142 SCIPclockStop(reopt->savingtime, set);
3143
3144 /* reset the information of dual bound changes */
3145 reopt->currentnode = -1;
3146 if( reopt->dualreds != NULL )
3147 reopt->dualreds->nvars = 0;
3148
3149 return SCIP_OKAY;
3150}
3151
3152/** delete the stored information about dual bound changes of the last focused node */
3153static
3155 SCIP_REOPT* reopt /**< reoptimization data structure */
3156 )
3157{
3158 assert(reopt != NULL);
3159
3160 if( reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
3161 {
3162 SCIPdebugMessage("delete %d dual variable information about node %lld\n", reopt->dualreds->nvars,
3163 reopt->currentnode);
3164 reopt->dualreds->nvars = 0;
3165 reopt->currentnode = -1;
3166 }
3167}
3168
3169/** delete the stored constraints that dual information at the given reoptimization node */
3170static
3172 SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
3173 BMS_BLKMEM* blkmem /**< block memory */
3174 )
3175{
3176 assert(reoptnode != NULL);
3177 assert(blkmem != NULL);
3178
3179 if( reoptnode->dualredscur != NULL )
3180 {
3181 SCIP_REOPTCONSDATA* reoptconsdata;
3182
3183 SCIPdebugMessage("reset dual information (current run)\n");
3184
3185 reoptconsdata = reoptnode->dualredscur;
3186
3187 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
3188 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
3189 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
3190 BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
3191 reoptnode->dualredscur = NULL;
3192 }
3193
3194 if( reoptnode->dualredsnex != NULL )
3195 {
3196 SCIP_REOPTCONSDATA* reoptconsdata;
3197
3198 SCIPdebugMessage("reset dual information (next run)\n");
3199
3200 reoptconsdata = reoptnode->dualredsnex;
3201
3202 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
3203 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
3204 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
3205 BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
3206 reoptnode->dualredsnex = NULL;
3207 }
3208
3209 reoptnode->dualreds = FALSE;
3210
3211 return SCIP_OKAY;
3212}
3213
3214
3215/** transform given set of variables, bounds and boundtypes into a global cut.
3216 *
3217 * @note: boundtypes can be NULL if all variables are binary or a MIP solution should be separated.
3218 * @note: continuous variables will be skiped if boundtypes is NULL
3219 */
3220static
3222 SCIP_REOPT* reopt, /**< reoptimization data structure */
3223 BMS_BLKMEM* blkmem, /**< block memory */
3224 SCIP_SET* set, /**< global SCIP settings */
3225 SCIP_VAR** vars, /**< variables of the cut */
3226 SCIP_Real* vals, /**< values of the cut */
3227 SCIP_BOUNDTYPE* boundtypes, /**< bounds of the cut */
3228 int nvars, /**< number of variables in the cut */
3229 int nbinvars, /**< number of binary variables */
3230 int nintvars /**< number of integer variables */
3231 )
3232{
3233 SCIP_REOPTCONSDATA* reoptconsdata;
3234 int nglbconss;
3235 int nvarsadded;
3236
3237 assert(reopt != NULL);
3238 assert(blkmem != NULL);
3239 assert(set != NULL);
3240 assert(vars != NULL);
3241 assert(vals != NULL);
3242 assert(nbinvars + nintvars == nvars);
3243
3244 nvarsadded = 0;
3245
3246 /* check whether we have enough memory allocated */
3247 SCIP_CALL( checkMemGlbCons(reopt, set, blkmem, 10) );
3248 nglbconss = reopt->nglbconss;
3249 reoptconsdata = NULL;
3250
3251 if( reopt->glbconss[nglbconss] == NULL )
3252 {
3253 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[nglbconss]) ); /*lint !e866*/
3254 reoptconsdata = reopt->glbconss[nglbconss];
3255
3256 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, (int)(nbinvars+2*nintvars)) );
3257 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, (int)(nbinvars+2*nintvars)) );
3258 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, (int)(nbinvars+2*nintvars)) );
3259 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
3260 reoptconsdata->nvars = 0;
3261 }
3262 else
3263 {
3264 assert(reopt->glbconss[nglbconss]->nvars == 0);
3265 assert(reopt->glbconss[nglbconss]->varssize > 0);
3266
3267 reoptconsdata = reopt->glbconss[nglbconss];
3268
3269 if( reoptconsdata->varssize < nbinvars+2*nintvars )
3270 {
3271 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize, \
3272 (int)(nbinvars+2*nintvars)) );
3273 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize, \
3274 (int)(nbinvars+2*nintvars)) );
3275 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize, \
3276 (int)(nbinvars+2*nintvars)) );
3277 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
3278 }
3279 }
3280 assert(reoptconsdata != NULL);
3281
3282 reoptconsdata->lhs = 1.0;
3283 reoptconsdata->rhs = SCIPsetInfinity(set);
3284 reoptconsdata->linear = FALSE;
3285 reoptconsdata->constype = REOPT_CONSTYPE_CUT;
3286
3287 for( int v = 0; v < nvars; ++v )
3288 {
3289 assert(nvarsadded < reoptconsdata->varssize);
3290 assert(vars[v] != NULL);
3291 assert(SCIPvarIsOriginal(vars[v]));
3292 assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsIntegral(set, vals[v]));
3293
3294 /* if no boundtypes are given we skip continuous variables, otherwise we would add trivial clauses:
3295 * a) x <= ub
3296 * b) lb <= x
3297 * c) (x <= val) or (x >= val)
3298 */
3299 if( boundtypes == NULL && SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
3300 continue;
3301
3302 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
3303 {
3304 reoptconsdata->vars[nvarsadded] = vars[v];
3305
3306 if( SCIPsetIsEQ(set, vals[v], 1.0) )
3307 {
3308 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3309 reoptconsdata->vals[nvarsadded] = 0.0;
3310 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3311 }
3312 else
3313 {
3314 assert(SCIPsetIsEQ(set, vals[v], 0.0));
3315 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
3316 reoptconsdata->vals[nvarsadded] = 1.0;
3317 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3318 }
3319 ++nvarsadded;
3320 }
3321 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS)
3322 {
3323 assert(boundtypes != NULL);
3324
3325 reoptconsdata->vals[nvarsadded] = vals[v];
3326 reoptconsdata->boundtypes[nvarsadded] = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
3327 ++nvarsadded;
3328 }
3329 else
3330 {
3331 SCIP_Real roundedval;
3332 SCIP_Real ubglb;
3333 SCIP_Real lbglb;
3334
3336
3337 reoptconsdata->vars[nvarsadded] = vars[v];
3338
3339 ubglb = SCIPvarGetUbGlobal(vars[v]);
3340 lbglb = SCIPvarGetLbGlobal(vars[v]);
3341
3342 /* case 1 : x == val == ub -> x <= ub-1
3343 * case 2 : x == val == lb -> x >= lb+1
3344 * case 3.1: x <= val < ub -> x >= y+1
3345 * case 3.2: x >= val > lb -> x <= y-1
3346 * case 4 : lb < x == val < ub -> (x <= y-1) or (x >= y+1)
3347 */
3348
3349 /* case 1 */
3350 if( SCIPsetIsEQ(set, vals[v], ubglb) )
3351 {
3352 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3353 reoptconsdata->vals[nvarsadded] = ubglb - 1.0;
3354 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3355 ++nvarsadded;
3356 }
3357 /* case 2 */
3358 else if( SCIPsetIsEQ(set, vals[v], lbglb) )
3359 {
3360 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
3361 reoptconsdata->vals[nvarsadded] = lbglb + 1.0;
3362 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3363 ++nvarsadded;
3364 }
3365 else if( boundtypes != NULL )
3366 {
3367 /* we round the solution value to get a 'clean' bound */
3368 assert(SCIPsetIsIntegral(set, vals[v]));
3369 roundedval = SCIPsetRound(set, vals[v]);
3370
3371 /* case 3.1 */
3372 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
3373 {
3374 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
3375 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3376 ++nvarsadded;
3377 }
3378 /* case 3.2 */
3379 else
3380 {
3381 assert(boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
3382 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
3383 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3384 ++nvarsadded;
3385 }
3386 }
3387 /* case 4: in this case we have to add two clauses: (x <= val-1) and (x >= val+1) */
3388 else
3389 {
3390 /* we round the solution value to get a 'clean' bound */
3391 assert(SCIPsetIsIntegral(set, vals[v]));
3392 roundedval = SCIPsetRound(set, vals[v]);
3393
3394 /* first clause: x <= val-1 */
3395 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
3396 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
3397 ++nvarsadded;
3398
3399 /* second clause: x >= val+1 */
3400 reoptconsdata->vars[nvarsadded] = vars[v];
3401 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
3402 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
3403 ++nvarsadded;
3404 }
3405 }
3406 }
3407 assert(nvars <= nvarsadded);
3408 assert(nvarsadded == nbinvars + 2 * nintvars);
3409
3410 reoptconsdata->nvars = nvarsadded;
3411 ++reopt->nglbconss;
3412
3413 return SCIP_OKAY;
3414}
3415
3416/** generate a global constraint to separate an infeasible subtree */
3417static
3419 SCIP_REOPT* reopt, /**< reoptimization data structure */
3420 SCIP_SET* set, /**< global SCIP settings */
3421 BMS_BLKMEM* blkmem, /**< block memory */
3422 SCIP_NODE* node, /**< node of the search tree */
3423 REOPT_CONSTYPE consttype /**< reopttype of the constraint */
3424 )
3425{
3426 assert(reopt != NULL);
3427 assert(node != NULL);
3428
3429 if( consttype == REOPT_CONSTYPE_INFSUBTREE )
3430 {
3431 SCIP_VAR** vars;
3432 SCIP_Real* vals;
3433 SCIP_BOUNDTYPE* boundtypes;
3434 int allocmem;
3435 int nbranchvars;
3436 int nbinvars;
3437 int nintvars;
3438
3439 /* allocate memory to store the infeasible path */
3440 allocmem = SCIPnodeGetDepth(node);
3441 SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, allocmem) );
3442 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, allocmem) );
3443 SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, allocmem) );
3444
3445 /* get the branching path */
3446 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
3447
3448 if( allocmem < nbranchvars )
3449 {
3450 SCIP_CALL( SCIPsetReallocBufferArray(set, &vars, nbranchvars) );
3451 SCIP_CALL( SCIPsetReallocBufferArray(set, &vals, nbranchvars) );
3452 SCIP_CALL( SCIPsetReallocBufferArray(set, &boundtypes, nbranchvars) );
3453 allocmem = nbranchvars;
3454
3455 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
3456 }
3457
3458 /* we count the number of binary and (impl) integer variables */
3459 nbinvars = 0;
3460 nintvars = 0;
3461 for( int v = 0; v < nbranchvars; ++v )
3462 {
3463 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
3464 ++nbinvars;
3466 ++nintvars;
3467 }
3468 assert(nbinvars + nintvars == nbranchvars);
3469
3470 SCIP_CALL( addGlobalCut(reopt, blkmem, set, vars, vals, boundtypes, nbranchvars, nbinvars, nintvars) );
3471 assert(!reopt->glbconss[reopt->nglbconss - 1]->linear);
3472
3473 /* free buffer */
3474 SCIPsetFreeBufferArray(set, &boundtypes);
3477 }
3478
3479 return SCIP_OKAY;
3480}
3481
3482
3483/** move all id of child nodes from reoptimization node stored at @p id1 to the node stored at @p id2 */
3484static
3486 SCIP_REOPTTREE* reopttree, /**< reopttree */
3487 SCIP_SET* set, /**< global SCIP settings */
3488 BMS_BLKMEM* blkmem, /**< block memory */
3489 unsigned int id1, /**< source id */
3490 unsigned int id2 /**< target id */
3491 )
3492{
3493 int nchilds_id1;
3494 int nchilds_id2;
3495
3496 assert(reopttree != NULL);
3497 assert(blkmem != NULL);
3498 assert(id1 < reopttree->reoptnodessize);
3499 assert(id2 < reopttree->reoptnodessize);
3500 assert(reopttree->reoptnodes[id1] != NULL);
3501 assert(reopttree->reoptnodes[id2] != NULL);
3502
3503 nchilds_id1 = reopttree->reoptnodes[id1]->nchilds;
3504 nchilds_id2 = reopttree->reoptnodes[id2]->nchilds;
3505
3506 /* ensure that the array storing the child id's is large enough */
3507 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id2], set, blkmem, 0, nchilds_id1+nchilds_id2, 0) );
3508 assert(reopttree->reoptnodes[id2]->allocchildmem >= nchilds_id1+nchilds_id2);
3509
3510 SCIPsetDebugMsg(set, "move %d IDs: %u -> %u\n", nchilds_id1, id1, id2);
3511
3512 /* move the ids */
3513 for( int c = 0; c < nchilds_id1; ++c )
3514 {
3515#ifdef SCIP_DEBUG
3516 {
3517 /* check that no id is added twice */
3518 for( int k = 0; k < nchilds_id2; ++k )
3519 assert(reopttree->reoptnodes[id2]->childids[k] != reopttree->reoptnodes[id1]->childids[c]);
3520 }
3521#endif
3522
3523 reopttree->reoptnodes[id2]->childids[nchilds_id2+c] = reopttree->reoptnodes[id1]->childids[c];
3524 }
3525
3526 /* update the number of childs */
3527 reopttree->reoptnodes[id1]->nchilds = 0;
3528 reopttree->reoptnodes[id2]->nchilds += nchilds_id1;
3529
3530 return SCIP_OKAY;
3531}
3532
3533/** change all bound changes along the root path */
3534static
3536 SCIP_REOPT* reopt, /**< reoptimization data structure */
3537 SCIP_SET* set, /**< global SCIP settings */
3538 SCIP_STAT* stat, /**< dynamic problem statistics */
3539 SCIP_PROB* transprob, /**< transformed problem */
3540 SCIP_PROB* origprob, /**< original problem */
3541 SCIP_TREE* tree, /**< search tree */
3542 SCIP_LP* lp, /**< current LP */
3543 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
3544 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3545 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
3546 BMS_BLKMEM* blkmem, /**< block memory */
3547 SCIP_NODE* node, /**< node of the branch and bound tree */
3548 unsigned int id, /**< id of stored node */
3549 SCIP_Bool afterdualbranching /**< convert all bound changes made directly after the first bound
3550 * changes based on dual information into normal branchings */
3551 )
3552{
3553 SCIP_REOPTTREE* reopttree;
3554 SCIP_REOPTNODE* reoptnode;
3555
3556 assert(reopt != NULL);
3557 assert(set != NULL);
3558 assert(stat != NULL);
3559 assert(transprob != NULL);
3560 assert(tree != NULL);
3561 assert(lp != NULL);
3562 assert(branchcand != NULL);
3563 assert(eventqueue != NULL);
3564 assert(cliquetable != NULL);
3565 assert(node != NULL);
3566 assert(blkmem != NULL);
3567
3568 reopttree = reopt->reopttree;
3569 assert(reopttree != NULL);
3570 assert(id < reopttree->reoptnodessize);
3571
3572 reoptnode = reopttree->reoptnodes[id];
3573 assert(reoptnode != NULL);
3574
3575 /* copy memory to ensure that only original variables are saved */
3576 if( reoptnode->nvars == 0 && reoptnode->nafterdualvars == 0)
3577 return SCIP_OKAY;
3578
3579 /* change the bounds along the branching path */
3580 for( int v = 0; v < reoptnode->nvars; ++v )
3581 {
3582 SCIP_VAR* var;
3583 SCIP_Real val;
3584 SCIP_BOUNDTYPE boundtype;
3585 SCIP_Real oldlb;
3586 SCIP_Real oldub;
3587 SCIP_Real newbound;
3588
3589 var = reoptnode->vars[v];
3590 val = reoptnode->varbounds[v];
3591 boundtype = reoptnode->varboundtypes[v];
3592
3593 assert(SCIPvarIsOriginal(var));
3594 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
3595 assert(SCIPvarIsTransformed(var));
3597
3598 oldlb = SCIPvarGetLbLocal(var);
3599 oldub = SCIPvarGetUbLocal(var);
3600 newbound = val;
3601
3602 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3603
3604 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3605 {
3606 SCIPvarAdjustLb(var, set, &newbound);
3607
3608 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3609 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3610 }
3611 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3612 {
3613 SCIPvarAdjustUb(var, set, &newbound);
3614
3615 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3616 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3617 }
3618#ifdef SCIP_MORE_DEBUG
3619 SCIPsetDebugMsg(set, " (path) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3620#endif
3621 }
3622
3623 if( afterdualbranching && reoptnode->nafterdualvars > 0 )
3624 {
3625 /* check the memory to convert this bound changes into 'normal' */
3626 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem,
3627 reoptnode->nvars + reoptnode->nafterdualvars, 0, 0) );
3628
3629 /* change the bounds */
3630 for( int v = 0; v < reoptnode->nafterdualvars; ++v )
3631 {
3632 SCIP_VAR* var;
3633 SCIP_Real val;
3634 SCIP_BOUNDTYPE boundtype;
3635 SCIP_Bool bndchgd;
3636 SCIP_Real oldlb;
3637 SCIP_Real oldub;
3638 SCIP_Real newbound;
3639
3640 var = reoptnode->afterdualvars[v];
3641 val = reoptnode->afterdualvarbounds[v];
3642 boundtype = reoptnode->afterdualvarboundtypes[v];
3643
3644 assert(SCIPvarIsOriginal(var));
3645 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
3646 assert(SCIPvarIsTransformed(var));
3648
3649 bndchgd = FALSE;
3650
3651 oldlb = SCIPvarGetLbLocal(var);
3652 oldub = SCIPvarGetUbLocal(var);
3653 newbound = val;
3654
3655 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3656 {
3657 SCIPvarAdjustLb(var, set, &newbound);
3658 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3659 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3660
3661 bndchgd = TRUE;
3662 }
3663 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3664 {
3665 SCIPvarAdjustUb(var, set, &newbound);
3666 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3667 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3668
3669 bndchgd = TRUE;
3670 }
3671
3672 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3673
3674#ifdef SCIP_MORE_DEBUG
3675 SCIPsetDebugMsg(set, " (prop) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3676#endif
3677 if( bndchgd )
3678 {
3679 int nvars;
3680
3681 nvars = reoptnode->nvars;
3682 reoptnode->vars[nvars] = reoptnode->afterdualvars[v];
3683 reoptnode->varbounds[nvars] = reoptnode->afterdualvarbounds[v];
3684 reoptnode->varboundtypes[nvars] = reoptnode->afterdualvarboundtypes[v];
3685 ++reoptnode->nvars;
3686 }
3687 }
3688
3689 /* free the afterdualvars, -bounds, and -boundtypes */
3690 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarboundtypes, reoptnode->afterdualvarssize);
3691 reoptnode->afterdualvarboundtypes = NULL;
3692
3693 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarbounds, reoptnode->afterdualvarssize);
3694 reoptnode->afterdualvarbounds = NULL;
3695
3696 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvars, reoptnode->afterdualvarssize);
3697 reoptnode->afterdualvars = NULL;
3698
3699 reoptnode->nafterdualvars = 0;
3700 reoptnode->afterdualvarssize = 0;
3701 }
3702
3703 return SCIP_OKAY;
3704}
3705
3706
3707/** add a constraint to ensure that at least one variable bound gets different */
3708static
3710 SCIP_REOPT* reopt, /**< reoptimization data structure */
3711 SCIP* scip, /**< SCIP data structure */
3712 SCIP_SET* set, /**< global SCIP settings */
3713 SCIP_STAT* stat, /**< dynamic problem statistics */
3714 BMS_BLKMEM* blkmem, /**< block memory */
3715 SCIP_PROB* transprob, /**< transformed problem */
3716 SCIP_PROB* origprob, /**< original problem */
3717 SCIP_TREE* tree, /**< search tree */
3718 SCIP_LP* lp, /**< current LP */
3719 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
3720 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3721 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3722 SCIP_NODE* node, /**< node corresponding to the pruned part */
3723 unsigned int id /**< id of stored node */
3724 )
3725{
3726 SCIP_CONS* cons;
3727 char name[SCIP_MAXSTRLEN];
3728
3729 assert(reopt != NULL);
3730 assert(reopt->reopttree != NULL);
3731 assert(id < reopt->reopttree->reoptnodessize);
3732 assert(reopt->reopttree->reoptnodes[id] != NULL);
3733 assert(reopt->reopttree->reoptnodes[id]->dualreds);
3734 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
3735 assert(scip != NULL);
3736 assert(set != NULL);
3737 assert(stat != NULL);
3738 assert(blkmem != NULL);
3739 assert(transprob != NULL);
3740 assert(origprob != NULL);
3741 assert(tree != NULL);
3742 assert(lp != NULL);
3743 assert(branchcand != NULL);
3744 assert(eventqueue != NULL);
3745 assert(node != NULL);
3746
3747 assert(reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS
3748 || reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
3749
3750#ifndef NDEBUG
3751 if( reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS )
3752 SCIPsetDebugMsg(set, " create a split-node #%lld\n", SCIPnodeGetNumber(node));
3753 else
3754 SCIPsetDebugMsg(set, " separate an infeasible subtree\n");
3755#endif
3756
3757 /* if the constraint consists of exactly one variable it can be interpreted
3758 * as a normal branching step, i.e., we can fix the variable to the negated bound */
3759 if( reopt->reopttree->reoptnodes[id]->dualredscur->nvars == 1 )
3760 {
3761 SCIP_REOPTCONSDATA* reoptconsdata;
3762 SCIP_VAR* var;
3763 SCIP_BOUNDTYPE boundtype;
3764 SCIP_Real oldlb;
3765 SCIP_Real oldub;
3766 SCIP_Real newbound;
3767
3768 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
3769 assert(!reoptconsdata->linear);
3770 assert(reoptconsdata->vars != NULL);
3771 assert(reoptconsdata->vals != NULL);
3772 assert(reoptconsdata->boundtypes != NULL);
3773
3774 var = reoptconsdata->vars[0];
3775 newbound = reoptconsdata->vals[0];
3776 boundtype = reoptconsdata->boundtypes[0];
3777
3778 assert(SCIPvarIsOriginal(var));
3779 SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
3780 assert(SCIPvarIsTransformed(var));
3781
3782 oldlb = SCIPvarGetLbLocal(var);
3783 oldub = SCIPvarGetUbLocal(var);
3784
3785 if( boundtype == SCIP_BOUNDTYPE_LOWER )
3786 {
3787 newbound = reoptconsdata->vals[0] - 1.0;
3788 /* if newbound > local upper bound, the variable cannot take the old value and we exit */
3789 if( SCIPisGT(scip, newbound, oldub) )
3790 return SCIP_OKAY;
3791 assert(SCIPisLE(scip, newbound, oldub));
3792 }
3793 else
3794 {
3795 newbound = reoptconsdata->vals[0] + 1.0;
3796 /* if newbound < local lower bound, the variable cannot take the old value and we exit */
3797 if( SCIPisLT(scip, newbound, oldlb) )
3798 return SCIP_OKAY;
3799 assert(SCIPisGE(scip, newbound, oldlb));
3800 }
3801 boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
3802 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
3803
3804 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
3805 {
3806 SCIPvarAdjustLb(var, set, &newbound);
3807 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3808 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
3809 }
3810 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
3811 {
3812 SCIPvarAdjustUb(var, set, &newbound);
3813 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
3814 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
3815 }
3816
3817 SCIPsetDebugMsg(set, " -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
3818 boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
3819 }
3820 else
3821 {
3822 SCIP_REOPTCONSDATA* reoptconsdata;
3823 SCIP_VAR** consvars;
3824 SCIP_Real consval;
3825 SCIP_BOUNDTYPE consboundtype;
3826 int nbinvars = 0;
3827#ifndef NDEBUG
3828 int nintvars = 0;
3829 int ncontvars = 0;
3830#endif
3831
3832 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
3833 assert(!reoptconsdata->linear);
3834 assert(reoptconsdata->vars != NULL);
3835 assert(reoptconsdata->vals != NULL);
3836 assert(reoptconsdata->boundtypes != NULL);
3837
3838 /* allocate buffer */
3839 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reoptconsdata->nvars) );
3840
3841 /* count number of binary, integer, and continuous variables */
3842 for( int v = 0; v < reoptconsdata->nvars; ++v )
3843 {
3844 switch ( SCIPvarGetType(reoptconsdata->vars[v]) )
3845 {
3847 ++nbinvars;
3848 break;
3851 if( SCIPisEQ(scip, SCIPvarGetLbLocal(reoptconsdata->vars[v]), 0.0)
3852 && SCIPisEQ(scip, SCIPvarGetUbLocal(reoptconsdata->vars[v]), 1.0) )
3853 ++nbinvars;
3854#ifndef NDEBUG
3855 else
3856 ++nintvars;
3857#endif
3858 break;
3860#ifndef NDEBUG
3861 ++ncontvars;
3862#endif
3863 break;
3864 default:
3865 SCIPerrorMessage("Variable <%s> has to be either binary, (implied) integer, or continuous.\n",
3866 SCIPvarGetName(reoptconsdata->vars[v]));
3867 return SCIP_INVALIDDATA;
3868 }
3869 }
3870
3871 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
3872 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
3873 else
3874 {
3875 assert(reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS);
3876 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
3877 }
3878
3879 /* case 1: all variables are binary, we use a logic-or constraint. */
3880 if( reoptconsdata->nvars == nbinvars )
3881 {
3882 for( int v = 0; v < reoptconsdata->nvars; ++v )
3883 {
3884 consvars[v] = reoptconsdata->vars[v];
3885 consval = reoptconsdata->vals[v];
3886 consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
3887
3888 assert(SCIPvarIsOriginal(consvars[v]));
3889 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
3890 assert(SCIPvarIsTransformed(consvars[v]));
3891 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3892
3893 if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
3894 {
3895 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
3896 assert(SCIPvarIsNegated(consvars[v]));
3897 }
3898 }
3899
3900 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reoptconsdata->nvars, consvars,
3902 }
3903 /* case 2: at least one variable is integer or continuous. we use a bounddisjunction constraint. */
3904 else
3905 {
3906 SCIP_Real* consvals;
3907 SCIP_BOUNDTYPE* consboundtypes;
3908
3909 assert(nintvars > 0 || ncontvars > 0);
3910
3911 /* alloc buffer memory */
3912 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, reoptconsdata->nvars) );
3913 SCIP_CALL( SCIPallocBufferArray(scip, &consboundtypes, reoptconsdata->nvars) );
3914
3915 /* iterate over all variables and transform them */
3916 for( int v = 0; v < reoptconsdata->nvars; ++v )
3917 {
3918 consvars[v] = reoptconsdata->vars[v];
3919 consvals[v] = reoptconsdata->vals[v];
3920 consboundtypes[v] = reoptconsdata->boundtypes[v];
3921
3922 /* we have to switch the bounds.
3923 * case 1: integer variable with bound x <= u is transformed to u+1 <= x
3924 * and l <= x is transformed to x <= l-1
3925 * case 2: continuous variable with bound x <= u is transformed to u <= x
3926 * and l <= x is transformed to x <= l
3927 */
3928 if( SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_BINARY
3929 || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_INTEGER
3930 || SCIPvarGetType(consvars[v]) == SCIP_VARTYPE_IMPLINT )
3931 {
3932 if( consboundtypes[v] == SCIP_BOUNDTYPE_UPPER )
3933 {
3934 consvals[v] += 1.0;
3935 assert(SCIPsetIsLE(set, consvals[v], SCIPvarGetUbGlobal(consvars[v])));
3936 }
3937 else
3938 {
3939 consvals[v] -= 1.0;
3940 assert(SCIPsetIsGE(set, consvals[v], SCIPvarGetLbGlobal(consvars[v])));
3941 }
3942 }
3943
3944 consboundtypes[v] = (SCIP_BOUNDTYPE)(1 - consboundtypes[v]); /*lint !e641*/
3945
3946 assert(SCIPvarIsOriginal(consvars[v]));
3947 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consvals[v], &consboundtypes[v]) );
3948 assert(SCIPvarIsTransformed(consvars[v]));
3949 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
3950 }
3951
3952 /* create the constraints and add them to the corresponding nodes */
3953 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, consvars, consboundtypes,
3954 consvals, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
3955
3956 /* free buffer memory */
3957 SCIPfreeBufferArray(scip, &consboundtypes);
3958 SCIPfreeBufferArray(scip, &consvals);
3959 }
3960
3961 SCIPsetDebugMsg(set, " -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
3962#ifdef SCIP_DEBUG_CONSS
3964#endif
3965
3966 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
3967 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3968
3969 /* free buffer */
3970 SCIPfreeBufferArray(scip, &consvars);
3971 }
3972
3973 return SCIP_OKAY;
3974}
3975
3976/** fix all bounds ad stored in dualredscur at the given node @p node_fix */
3977static
3979 SCIP_REOPT* reopt, /**< reoptimization data structure */
3980 SCIP_SET* set, /**< global SCIP settings */
3981 SCIP_STAT* stat, /**< dynamic problem statistics */
3982 SCIP_PROB* transprob, /**< transformed problem */
3983 SCIP_PROB* origprob, /**< original problem */
3984 SCIP_TREE* tree, /**< search tree */
3985 SCIP_LP* lp, /**< current LP */
3986 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
3987 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3988 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
3989 BMS_BLKMEM* blkmem, /**< block memory */
3990 SCIP_NODE* node, /**< node corresponding to the fixed part */
3991 unsigned int id, /**< id of stored node */
3992 SCIP_Bool updatedualconss /**< update constraint representing dual bound changes */
3993 )
3994{
3995 SCIP_REOPTTREE* reopttree;
3996 SCIP_REOPTNODE* reoptnode;
3997
3998 assert(reopt != NULL);
3999 assert(set != NULL);
4000 assert(stat != NULL);
4001 assert(transprob != NULL);
4002 assert(origprob != NULL);
4003 assert(tree != NULL);
4004 assert(lp != NULL);
4005 assert(branchcand != NULL);
4006 assert(eventqueue != NULL);
4007 assert(cliquetable != NULL);
4008 assert(node != NULL);
4009 assert(blkmem != NULL);
4010
4011 reopttree = reopt->reopttree;
4012 assert(reopttree != NULL);
4013 assert(0 < id && id < reopttree->reoptnodessize);
4014
4015 reoptnode = reopttree->reoptnodes[id];
4016 assert(reoptnode != NULL);
4017 assert(reoptnode->dualreds);
4018 assert(reoptnode->dualredscur != NULL);
4019
4020 /* ensure that the arrays to store the bound changes are large enough */
4021 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, reoptnode->nvars + reoptnode->dualredscur->nvars, 0, 0) );
4022
4023 for( int v = 0; v < reoptnode->dualredscur->nvars; ++v )
4024 {
4025 SCIP_VAR* var;
4026 SCIP_Real val;
4027 SCIP_BOUNDTYPE boundtype;
4028 SCIP_Bool bndchgd;
4029
4030 var = reoptnode->dualredscur->vars[v];
4031 val = reoptnode->dualredscur->vals[v];
4032 boundtype = reoptnode->dualredscur->boundtypes[v];
4033
4034 SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4035 assert(SCIPvarIsTransformedOrigvar(var));
4036
4037 bndchgd = FALSE;
4038
4039 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4040 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4041 {
4042 SCIPvarAdjustLb(var, set, &val);
4043 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4044 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4045
4046 bndchgd = TRUE;
4047 }
4048 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4049 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4050 {
4051 SCIPvarAdjustUb(var, set, &val);
4052 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4053 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4054
4055 bndchgd = TRUE;
4056 }
4057 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4058 {
4059 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4060 return SCIP_INVALIDDATA;
4061 }
4062#ifdef SCIP_MORE_DEBUG
4063 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4064#endif
4065 /* add variable and bound to branching path information, because we don't want to delete this data */
4066 if( bndchgd )
4067 {
4068 int pos;
4069 SCIP_Real constant;
4070 SCIP_Real scalar;
4071
4072 pos = reoptnode->nvars;
4073
4074 reoptnode->vars[pos] = var;
4075 scalar = 1.0;
4076 constant = 0.0;
4077 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
4078 assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
4079
4080 reoptnode->varbounds[pos] = reoptnode->dualredscur->vals[v];
4081 reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
4082 ++reoptnode->nvars;
4083 }
4084 }
4085
4086 if( updatedualconss )
4087 {
4088 /* delete dualredscur and move dualredsnex -> dualredscur */
4089 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
4090 }
4091
4092 return SCIP_OKAY;
4093}
4094
4095/** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
4096 * keep the first negbndchg-1 bound changes as stored in dualredscur and negate the negbndchg-th bound.
4097 */
4098static
4100 SCIP_REOPT* reopt, /**< reoptimization data structure */
4101 SCIP_SET* set, /**< global SCIP settings */
4102 SCIP_STAT* stat, /**< dynamic problem statistics */
4103 SCIP_PROB* transprob, /**< transformed problem */
4104 SCIP_PROB* origprob, /**< original problem */
4105 SCIP_TREE* tree, /**< search tree */
4106 SCIP_LP* lp, /**< current LP */
4107 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
4108 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4109 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
4110 BMS_BLKMEM* blkmem, /**< block memory */
4111 SCIP_NODE* node, /**< child node */
4112 unsigned int id, /**< id of the node */
4113 int* perm, /**< array of permuted indices */
4114 SCIP_VAR** vars, /**< variables */
4115 SCIP_Real* vals, /**< bounds */
4116 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes */
4117 int nvars, /**< number of variables */
4118 int negbndchg /**< index of the variable that should negated */
4119 )
4120{
4121 SCIP_VAR* var;
4122 SCIP_Real val;
4123 SCIP_BOUNDTYPE boundtype;
4124 int nbndchgs;
4125
4126 assert(reopt != NULL);
4127 assert(set != NULL);
4128 assert(stat != NULL);
4129 assert(transprob != NULL);
4130 assert(origprob != NULL);
4131 assert(tree != NULL);
4132 assert(lp != NULL);
4133 assert(branchcand != NULL);
4134 assert(eventqueue != NULL);
4135 assert(cliquetable != NULL);
4136 assert(node != NULL);
4137 assert(perm != NULL);
4138 assert(vars != NULL);
4139 assert(vals != NULL);
4140 assert(boundtypes != NULL);
4141 assert(nvars >= 0);
4142 assert(blkmem != NULL);
4143 assert(0 < id && id < reopt->reopttree->reoptnodessize);
4144
4145#ifndef NDEBUG
4146 {
4147 SCIP_REOPTTREE* reopttree;
4148 SCIP_REOPTNODE* reoptnode;
4149
4150 reopttree = reopt->reopttree;
4151 assert(reopttree != NULL);
4152
4153 reoptnode = reopttree->reoptnodes[id];
4154 assert(reoptnode != NULL);
4155 assert(reoptnode->dualreds);
4156 }
4157#endif
4158
4159 nbndchgs = MIN(negbndchg, nvars);
4160
4161 /* change the first nbndchg-1 bounds as stored in dualredscur and negate the negbndchg-th bound */
4162 for( int v = 0; v < nbndchgs; ++v )
4163 {
4164 var = vars[perm[v]];
4165 val = vals[perm[v]];
4166 boundtype = boundtypes[perm[v]];
4167
4168 SCIP_CALL(SCIPvarGetProbvarBound(&var, &val, &boundtype));
4169 assert(SCIPvarIsTransformedOrigvar(var));
4170
4171 /* negate the last bound change */
4172 if( v == nbndchgs-1 )
4173 {
4174 boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
4175 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_UPPER )
4176 val = val - 1.0;
4177 else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && boundtype == SCIP_BOUNDTYPE_LOWER )
4178 val = val + 1.0;
4179 }
4180
4181 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
4182 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
4183 {
4184 SCIPvarAdjustLb(var, set, &val);
4185 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4186 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
4187 }
4188 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
4189 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
4190 {
4191 SCIPvarAdjustUb(var, set, &val);
4192 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
4193 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
4194 }
4195 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
4196 {
4197 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
4198 return SCIP_INVALIDDATA;
4199 }
4200#ifdef SCIP_MORE_DEBUG
4201 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
4202#endif
4203 }
4204
4205 return SCIP_OKAY;
4206}
4207
4208/** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
4209static
4211 SCIP* scip, /**< SCIP data structure */
4212 SCIP_REOPT* reopt, /**< reoptimization data structure */
4213 SCIP_SET* set, /**< global SCIP settings */
4214 SCIP_STAT* stat, /**< dynamic problem statistics */
4215 BMS_BLKMEM* blkmem, /**< block memory */
4216 SCIP_NODE* node, /**< node of the branch and bound tree*/
4217 unsigned int id /**< id of stored node */
4218 )
4219{
4220 char name[SCIP_MAXSTRLEN];
4221
4222 assert(scip != NULL);
4223 assert(reopt != NULL);
4224 assert(reopt->reopttree != NULL);
4225 assert(set != NULL);
4226 assert(stat != NULL);
4227 assert(blkmem != NULL);
4228 assert(node != NULL);
4229 assert(0 < id && id < reopt->reopttree->reoptnodessize);
4230
4231 if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
4232 return SCIP_OKAY;
4233
4234 SCIPsetDebugMsg(set, " -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss,
4235 SCIPnodeGetNumber(node));
4236
4237 for( int c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; ++c )
4238 {
4239 SCIP_CONS* cons;
4240 SCIP_REOPTCONSDATA* reoptconsdata;
4241
4242 reoptconsdata = reopt->reopttree->reoptnodes[id]->conss[c];
4243 assert(reoptconsdata != NULL);
4244 assert(reoptconsdata->nvars > 0);
4245 assert(reoptconsdata->varssize >= reoptconsdata->nvars);
4246
4247 if( reoptconsdata->constype == REOPT_CONSTYPE_CUT )
4248 continue;
4249
4250 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
4251 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
4252 else if( reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS )
4253 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
4254 else
4255 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_unkn");
4256
4257 if( reoptconsdata->linear )
4258 {
4259 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->vals,
4260 reoptconsdata->lhs, reoptconsdata->rhs, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4261 }
4262 else
4263 {
4264 assert(reoptconsdata->boundtypes != NULL);
4265 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->boundtypes,
4266 reoptconsdata->vals, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
4267 }
4268#ifdef SCIP_DEBUG_CONSS
4270#endif
4271 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
4272 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
4273 }
4274
4275 return SCIP_OKAY;
4276}
4277
4278/** reset the internal statistics at the beginning of a new iteration */
4279static
4281 SCIP_REOPT* reopt /**< reoptimization data structure */
4282 )
4283{
4284 assert(reopt != NULL);
4285
4286 reopt->lastbranched = -1;
4287 reopt->currentnode = -1;
4288 reopt->lastseennode = -1;
4289 reopt->reopttree->nfeasnodes = 0;
4290 reopt->reopttree->ninfnodes = 0;
4291 reopt->reopttree->nprunednodes = 0;
4292 reopt->reopttree->ncutoffreoptnodes = 0;
4293
4294 if( reopt->dualreds != NULL )
4295 reopt->dualreds->nvars = 0;
4296}
4297
4298/** check the stored bound changes of all child nodes for redundancy and infeasibility
4299 *
4300 * Due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
4301 * child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
4302 * method we remove all redundant bound changes and delete infeasible child nodes.
4303 */
4304static
4306 SCIP_REOPT* reopt, /**< reoptimization data structure */
4307 SCIP_SET* set, /**< global SCIP settings */
4308 BMS_BLKMEM* blkmem, /**< block memory */
4309 SCIP_Bool* runagain, /**< pointer to store of this method should run again */
4310 unsigned int id /**< id of stored node */
4311 )
4312{
4313 SCIP_REOPTNODE* reoptnode;
4314 unsigned int* cutoffchilds;
4315 int ncutoffchilds = 0;
4316 unsigned int* redchilds;
4317 int nredchilds = 0;
4318 int c;
4319
4320 assert(reopt != NULL);
4321 assert(reopt->reopttree != NULL);
4322 assert(id < reopt->reopttree->reoptnodessize);
4323 assert(reopt->reopttree->reoptnodes != NULL);
4324 assert(reopt->reopttree->reoptnodes[id] != NULL);
4325
4326 reoptnode = reopt->reopttree->reoptnodes[id];
4327
4328 *runagain = FALSE;
4329
4330 SCIPsetDebugMsg(set, "start dry branching of node at ID %u\n", id);
4331
4332 /* allocate buffer arrays */
4333 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
4334 SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
4335
4336 /* iterate over all child nodes and check each bound changes
4337 * for redundancy and conflict */
4338 for( c = 0; c < reoptnode->nchilds; ++c )
4339 {
4340 SCIP_REOPTNODE* child;
4341 SCIP_Bool cutoff;
4342 SCIP_Bool redundant;
4343 int* redundantvars;
4344 int nredundantvars;
4345 unsigned int childid;
4346
4347 cutoff = FALSE;
4348 redundant = FALSE;
4349 nredundantvars = 0;
4350
4351 childid = reoptnode->childids[c];
4352 assert(childid < reopt->reopttree->reoptnodessize);
4353 child = reopt->reopttree->reoptnodes[childid];
4354 assert(child != NULL);
4355#ifdef SCIP_MORE_DEBUG
4356 SCIPsetDebugMsg(set, "-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
4357#endif
4358 if( child->nvars > 0 )
4359 {
4360 /* allocate buffer memory to store the redundant variables */
4361 SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
4362
4363 for( int v = 0; v < child->nvars && !cutoff; ++v )
4364 {
4365 SCIP_VAR* transvar;
4366 SCIP_Real transval;
4367 SCIP_BOUNDTYPE transbndtype;
4368 SCIP_Real ub;
4369 SCIP_Real lb;
4370
4371 transvar = child->vars[v];
4372 transval = child->varbounds[v];
4373 transbndtype = child->varboundtypes[v];
4374
4375 /* transform into the transformed space */
4376 SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
4377
4378 lb = SCIPvarGetLbLocal(transvar);
4379 ub = SCIPvarGetUbLocal(transvar);
4380
4381 /* check for infeasibility */
4382 if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
4383 {
4384 SCIPsetDebugMsg(set, " -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
4385 SCIPvarGetName(transvar), lb, transval);
4386
4387 cutoff = TRUE;
4388 break;
4389 }
4390
4391 /* check for redundancy */
4392 if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
4393 {
4394 SCIPsetDebugMsg(set, " -> <%s> is already fixed to %g -> redundant bound change\n",
4395 SCIPvarGetName(transvar), lb);
4396
4397 redundantvars[nredundantvars] = v;
4398 ++nredundantvars;
4399 }
4400 }
4401
4402 if( !cutoff && nredundantvars > 0 )
4403 {
4404 for( int v = 0; v < nredundantvars; ++v )
4405 {
4406 /* replace the redundant variable by the last stored variable */
4407 child->vars[redundantvars[v]] = child->vars[child->nvars-1];
4408 child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
4409 child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
4410 --child->nvars;
4411 }
4412 }
4413
4414 /* free buffer memory */
4415 SCIPsetFreeBufferArray(set, &redundantvars);
4416 }
4417 else if( child->nconss == 0 )
4418 {
4419 redundant = TRUE;
4420 SCIPsetDebugMsg(set, " -> redundant node found.\n");
4421 }
4422
4423 if( cutoff )
4424 {
4425 cutoffchilds[ncutoffchilds] = childid;
4426 ++ncutoffchilds;
4427 }
4428 else if( redundant )
4429 {
4430 redchilds[nredchilds] = childid;
4431 ++nredchilds;
4432 }
4433 }
4434
4435 SCIPsetDebugMsg(set, "-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
4436
4437 /* delete all nodes that can be cut off */
4438 while( ncutoffchilds > 0 )
4439 {
4440 /* delete the node and the induced subtree */
4441 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
4442
4443 /* find the position in the childid array */
4444 c = 0;
4445 while( c < reoptnode->nchilds && reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] )
4446 ++c;
4447 assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
4448
4449 /* replace the ID at position c by the last ID */
4450 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4451 --reoptnode->nchilds;
4452
4453 /* decrease the number of nodes to cutoff */
4454 --ncutoffchilds;
4455 }
4456
4457 /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
4458 while( nredchilds > 0 )
4459 {
4460 /* find the position in the childid array */
4461 c = 0;
4462 while( c < reoptnode->nchilds && reoptnode->childids[c] != redchilds[nredchilds-1] )
4463 ++c;
4464 assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
4465
4466 /* the node is a leaf and we can cutoff them */
4467 if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
4468 {
4469 /* delete the node and the induced subtree */
4470 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
4471
4472 /* replace the ID at position c by the last ID */
4473 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4474 --reoptnode->nchilds;
4475
4476 /* decrease the number of redundant nodes */
4477 --nredchilds;
4478 }
4479 else
4480 {
4481 int ncc;
4482
4483 /* replace the ID at position c by the last ID */
4484 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
4485 --reoptnode->nchilds;
4486
4487 ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
4488
4489 /* check the memory */
4490 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, 0, reoptnode->nchilds+ncc, 0) );
4491
4492 /* add all IDs of child nodes to the current node */
4493 for( int cc = 0; cc < ncc; ++cc )
4494 {
4495 reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
4496 ++reoptnode->nchilds;
4497 }
4498
4499 /* delete the redundant node */
4500 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
4501 SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, redchilds[nredchilds-1]) );
4502
4503 /* decrease the number of redundant nodes */
4504 --nredchilds;
4505
4506 /* update the flag to rerun this method */
4507 *runagain = TRUE;
4508 }
4509 }
4510
4511 /* free buffer arrays */
4512 SCIPsetFreeBufferArray(set, &redchilds);
4513 SCIPsetFreeBufferArray(set, &cutoffchilds);
4514
4515 return SCIP_OKAY;
4516}
4517
4518/** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
4519static
4521 SCIP_REOPTTREE* reopttree, /**< reopttree */
4522 unsigned int id /**< id of stored node */
4523 )
4524{
4525 int nnodes = 0;
4526
4527 assert(reopttree != NULL);
4528 assert(id < reopttree->reoptnodessize);
4529
4530 for( int i = 0; i < reopttree->reoptnodes[id]->nchilds; ++i )
4531 nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
4532
4533 return nnodes + 1;
4534}
4535
4536/** returns the number of leaf nodes of the induced subtree */
4537static
4539 SCIP_REOPT* reopt, /**< reoptimization data structure */
4540 unsigned int id /**< id of stored node */
4541 )
4542{
4543 int nleaves = 0;
4544
4545 assert(reopt != NULL);
4546 assert(id < reopt->reopttree->reoptnodessize);
4547 assert(reopt->reopttree->reoptnodes[id] != NULL);
4548
4549 /* iterate over all child nods and check whether they are leaves or not */
4550 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
4551 {
4552 unsigned int childid;
4553
4554 childid = reopt->reopttree->reoptnodes[id]->childids[i];
4555 assert(childid < reopt->reopttree->reoptnodessize);
4556
4557 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4558 ++nleaves;
4559 else
4560 nleaves += reoptGetNLeaves(reopt, childid);
4561 }
4562
4563 return nleaves;
4564}
4565
4566/** returns all leaves of the subtree induced by the node stored at @p id*/
4567static
4569 SCIP_REOPT* reopt, /**< reoptimization data structure*/
4570 unsigned int id, /**< id of stored node */
4571 unsigned int* leaves, /**< array of leave nodes */
4572 int leavessize, /**< size of leaves array */
4573 int* nleaves /**< pointer to store the number of leave nodes */
4574 )
4575{
4576 assert(reopt != NULL);
4577 assert(leavessize > 0 && leaves != NULL);
4578 assert((*nleaves) >= 0);
4579 assert(id < reopt->reopttree->reoptnodessize);
4580 assert(reopt->reopttree->reoptnodes[id] != NULL);
4581
4582 for( int i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
4583 {
4584 unsigned int childid;
4585
4586 assert(*nleaves <= leavessize);
4587
4588 childid = reopt->reopttree->reoptnodes[id]->childids[i];
4589 assert(childid < reopt->reopttree->reoptnodessize);
4590
4591 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
4592 {
4593 leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
4594 ++l;
4595 ++(*nleaves);
4596 }
4597 else
4598 {
4599 int nleaves2 = 0;
4600
4601 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
4602 l += nleaves2;
4603 (*nleaves) += nleaves2;
4604 }
4605 }
4606
4607 return SCIP_OKAY;
4608}
4609
4610/** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
4611static
4613 SCIP_REOPT* reopt, /**< reoptimization data structure */
4614 SCIP_SET* set, /**< global SCIP settings */
4615 BMS_BLKMEM* blkmem, /**< block memory */
4616 SCIP_Bool softreset /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
4617 )
4618{
4619 assert(reopt != NULL);
4620 assert(set != NULL);
4621 assert(blkmem != NULL);
4622
4623 /* clear the tree */
4624 SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
4625 assert(reopt->reopttree->nreoptnodes == 0);
4626
4627 /* reset the dual constraint */
4628 if( reopt->dualreds != NULL )
4629 reopt->dualreds->nvars = 0;
4630
4631 reopt->currentnode = -1;
4632
4633 return SCIP_OKAY;
4634}
4635
4636/** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
4637static
4639 SCIP_REOPT* reopt, /**< reoptimization data structure */
4640 SCIP_SET* set, /**< global SCIP settings */
4641 BMS_BLKMEM* blkmem /**< block memory */
4642 )
4643{
4644 assert(reopt != NULL);
4645 assert(reopt->reopttree != NULL);
4646 assert(set != NULL);
4647 assert(blkmem != NULL);
4648
4649 /* clear the tree */
4650 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
4651 assert(reopt->reopttree->nreoptnodes == 0);
4652
4653 /* allocate memory for the root node */
4654 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
4655
4656 reopt->nglbrestarts += 1;
4657
4658 if( reopt->firstrestart == -1 )
4659 reopt->firstrestart = reopt->run;
4660
4661 reopt->lastrestart = reopt->run;
4662
4663 return SCIP_OKAY;
4664}
4665
4666/** save the new objective function */
4667static
4669 SCIP_REOPT* reopt, /**< reoptimization data */
4670 SCIP_SET* set, /**< global SCIP settings */
4671 BMS_BLKMEM* blkmem, /**< block memory */
4672 SCIP_VAR** origvars, /**< original problem variables */
4673 int norigvars /**< number of original problem variables */
4674 )
4675{
4676 int probidx;
4677
4678 assert(reopt != NULL);
4679 assert(set != NULL);
4680 assert(blkmem != NULL);
4681 assert(origvars != NULL);
4682 assert(norigvars >= 0);
4683
4684 /* check memory */
4685 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
4686
4687 /* get memory and check whether we have to resize all previous objectives */
4688 if( reopt->nobjvars < norigvars )
4689 {
4690 for( int i = 0; i < reopt->run-1; ++i )
4691 {
4692 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], norigvars) ); /*lint !e866*/
4693 for( int v = reopt->nobjvars-1; v < norigvars; ++v )
4694 reopt->objs[i][v] = 0.0;
4695 }
4696 reopt->nobjvars = norigvars;
4697 }
4698 SCIP_ALLOC( BMSallocClearMemoryArray(&reopt->objs[reopt->run-1], reopt->nobjvars) ); /*lint !e866*/
4699
4700 /* save coefficients */
4701 for( int v = 0; v < norigvars; ++v )
4702 {
4703 assert(SCIPvarIsOriginal(origvars[v]));
4704
4705 probidx = SCIPvarGetIndex(origvars[v]);
4706
4707 /* it can happen that the index is greater than the number of problem variables,
4708 * i.e., not all created variables were added
4709 */
4710 if( probidx >= reopt->nobjvars )
4711 {
4712 int newsize = SCIPsetCalcMemGrowSize(set, probidx+1);
4713 for( int i = 0; i < reopt->run; ++i )
4714 {
4715 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], newsize) ); /*lint !e866*/
4716 for( int j = reopt->nobjvars; j < newsize; ++j )
4717 reopt->objs[i][j] = 0.0;
4718 }
4719 reopt->nobjvars = newsize;
4720 }
4721 assert(0 <= probidx && probidx < reopt->nobjvars);
4722
4723 reopt->objs[reopt->run-1][probidx] = SCIPvarGetObj(origvars[v]);
4724
4725 /* update flag to remember if the objective function has changed */
4726 if( !reopt->objhaschanged && reopt->run >= 2
4727 && ! SCIPsetIsEQ(set, reopt->objs[reopt->run-2][probidx], reopt->objs[reopt->run-1][probidx]) )
4728 reopt->objhaschanged = TRUE;
4729
4730 /* mark this objective as the first non empty */
4731 if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][probidx] != 0 )
4732 reopt->firstobj = reopt->run-1;
4733 }
4734
4735 /* calculate similarity to last objective */
4736 if( reopt->run-1 >= 1 )
4737 {
4738 /* calculate similarity to last objective */
4739 reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, origvars, norigvars);
4740
4741 if( reopt->simtolastobj == SCIP_INVALID ) /*lint !e777*/
4742 return SCIP_INVALIDRESULT;
4743
4744 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "new objective has similarity of %g compared to previous.\n",
4745 reopt->simtolastobj);
4746 }
4747
4748 SCIPsetDebugMsg(set, "saved obj for run %d.\n", reopt->run);
4749
4750 return SCIP_OKAY;
4751}
4752
4753/** orders the variable by inference score */
4754static
4756 SCIP_SET* set, /**< global SCIP settings */
4757 SCIP_STAT* stat, /**< dynamic problem statistics */
4758 int* perm, /**< array of indices that need to be permuted */
4759 SCIP_VAR** vars, /**< variable array to permute */
4760 SCIP_Real* bounds, /**< bound array to permute in the same order */
4761 SCIP_BOUNDTYPE* boundtypes, /**< boundtype array to permute in the same order */
4762 int nvars /**< number of variables */
4763 )
4764{
4765 SCIP_Real* infscore;
4766
4767 assert(set != NULL);
4768 assert(perm != NULL);
4769 assert(vars != NULL);
4770 assert(bounds != NULL);
4771 assert(boundtypes != NULL);
4772 assert(nvars >= 0);
4773
4774 /* allocate buffer for the scores */
4775 SCIP_CALL( SCIPsetAllocBufferArray(set, &infscore, nvars) );
4776
4777 for( int v = 0; v < nvars; ++v )
4778 {
4779 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
4780 {
4781 infscore[v] = 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4782 + 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4783 }
4784 else
4785 {
4786 infscore[v] = 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
4787 + 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
4788 }
4789 }
4790
4791 /* permute indices by inference score */
4792 SCIPsortDownRealInt(infscore, perm, nvars);
4793
4794 /* free buffer */
4795 SCIPsetFreeBufferArray(set, &infscore);
4796
4797 return SCIP_OKAY;
4798}
4799
4800/** create a global constraint to separate the given solution */
4801static
4803 SCIP_REOPT* reopt, /**< reoptimization data structure */
4804 BMS_BLKMEM* blkmem, /**< block memory */
4805 SCIP_SET* set, /**< global SCIP settings */
4806 SCIP_STAT* stat, /**< dynamic SCIP statistics */
4807 SCIP_SOL* sol, /**< solution to separate */
4808 SCIP_VAR** vars, /**< array of original problem variables */
4809 int nvars /**< number of original problem variables */
4810 )
4811{
4812 SCIP_VAR** origvars;
4813 SCIP_Real* vals;
4814 int nintvars;
4815 int nbinvars;
4816 int w;
4817
4818 assert(reopt != NULL);
4819 assert(sol != NULL);
4820 assert(blkmem != NULL);
4821 assert(set != NULL);
4822 assert(stat != NULL);
4823 assert(vars != NULL);
4824 assert(nvars != 0);
4825 assert(SCIPsolIsOriginal(sol));
4826
4827 /* allocate buffer memory */
4828 SCIP_CALL( SCIPsetAllocBufferArray(set, &origvars, nvars) );
4829 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
4830
4831 nbinvars = 0;
4832 nintvars = 0;
4833 w = 0;
4834
4835 /* get the solution values of the variables */
4836 for( int v = 0; v < nvars; ++v )
4837 {
4838 assert(SCIPvarIsOriginal(vars[v]));
4839 assert(nbinvars + nintvars == w);
4840
4841 /* we do not want to create cuts for continous variables */
4842 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4843 continue;
4844
4845 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
4846 ++nbinvars;
4848 ++nintvars;
4849
4850 origvars[v] = vars[v];
4851 assert(origvars[v] != NULL);
4852 assert(SCIPvarIsOriginal(origvars[v]));
4853
4854 vals[w] = SCIPsolGetVal(sol, set, stat, origvars[v]);
4855 ++w;
4856 }
4857
4858 SCIP_CALL( addGlobalCut(reopt, blkmem, set, origvars, vals, NULL, w, nbinvars, nintvars) );
4859
4860 /* free buffer memory */
4862 SCIPsetFreeBufferArray(set, &origvars);
4863
4864 return SCIP_OKAY;
4865}
4866
4867/*
4868 * public methods
4869 */
4870
4871/* ---------------- methods of general reoptimization ---------------- */
4872
4873/* In debug mode, the following methods are implemented as function calls to ensure
4874 * type validity.
4875 * In optimized mode, the methods are implemented as defines to improve performance.
4876 * However, we want to have them in the library anyways, so we have to undef the defines.
4877 */
4878
4879#undef SCIPreoptGetNRestartsGlobal
4880#undef SCIPreoptGetNRestartsLocal
4881#undef SCIPreoptGetNTotalRestartsLocal
4882#undef SCIPreoptGetFirstRestarts
4883#undef SCIPreoptGetLastRestarts
4884#undef SCIPreoptGetNFeasNodes
4885#undef SCIPreoptGetNTotalFeasNodes
4886#undef SCIPreoptGetNPrunedNodes
4887#undef SCIPreoptGetNTotalPrunedNodes
4888#undef SCIPreoptGetNCutoffReoptnodes
4889#undef SCIPreoptGetNTotalCutoffReoptnodes
4890#undef SCIPreoptGetNInfNodes
4891#undef SCIPreoptGetNTotalInfNodes
4892#undef SCIPreoptGetNInfSubtrees
4893
4894
4895/** returns the number of global restarts */
4897 SCIP_REOPT* reopt /**< reoptimization data structure */
4898 )
4899{
4900 assert(reopt != NULL);
4901
4902 return reopt->nglbrestarts;
4903}
4904
4905/** returns the number of local restarts in the current run */
4907 SCIP_REOPT* reopt /**< reoptimization data structure */
4908 )
4909{
4910 assert(reopt != NULL);
4911
4912 return reopt->nlocrestarts;
4913}
4914
4915/** returns the number of local restarts over all runs */
4917 SCIP_REOPT* reopt /**< reoptimization data structure */
4918 )
4919{
4920 assert(reopt != NULL);
4921
4922 return reopt->ntotallocrestarts;
4923}
4924
4925/** returns the number of iteration with the first global restarts */
4927 SCIP_REOPT* reopt /**< reoptimization data structure */
4928 )
4929{
4930 assert(reopt != NULL);
4931
4932 return reopt->firstrestart;
4933}
4934
4935/** returns the number of iteration with the last global restarts */
4937 SCIP_REOPT* reopt /**< reoptimization data structure */
4938 )
4939{
4940 assert(reopt != NULL);
4941
4942 return reopt->lastrestart;
4943}
4944
4945/** returns the number of stored nodes providing an improving feasible LP solution in the current run */
4947 SCIP_REOPT* reopt /**< reoptimization data structure */
4948 )
4949{
4950 assert(reopt != NULL);
4951
4952 return reopt->reopttree->nfeasnodes;
4953}
4954
4955/** returns the number of stored nodes providing an improving feasible LP solution over all runs */
4957 SCIP_REOPT* reopt /**< reoptimization data structure */
4958 )
4959{
4960 assert(reopt != NULL);
4961
4962 return reopt->reopttree->ntotalfeasnodes;
4963}
4964
4965/** returns the number of stored nodes that exceeded the cutoff bound in the current run */
4967 SCIP_REOPT* reopt /**< reoptimization data structure */
4968 )
4969{
4970 assert(reopt != NULL);
4971
4972 return reopt->reopttree->nprunednodes;
4973}
4974
4975/** returns the number of stored nodes that exceeded the cutoff bound over all runs */
4977 SCIP_REOPT* reopt /**< reoptimization data structure */
4978 )
4979{
4980 assert(reopt != NULL);
4981
4982 return reopt->reopttree->ntotalprunednodes;
4983}
4984
4985/** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
4987 SCIP_REOPT* reopt /**< reoptimization data structure */
4988 )
4989{
4990 assert(reopt != NULL);
4991
4992 return reopt->reopttree->ncutoffreoptnodes;
4993}
4994
4995/** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
4997 SCIP_REOPT* reopt /**< reoptimization data structure */
4998 )
4999{
5000 assert(reopt != NULL);
5001
5002 return reopt->reopttree->ntotalcutoffreoptnodes;
5003}
5004
5005/** returns the number of stored nodes with an infeasible LP in the current run */
5007 SCIP_REOPT* reopt /**< reoptimization data structure */
5008 )
5009{
5010 assert(reopt != NULL);
5011
5012 return reopt->reopttree->ninfnodes;
5013}
5014
5015/** returns the number of stored nodes with an infeasible LP over all runs */
5017 SCIP_REOPT* reopt /**< reoptimization data structure */
5018 )
5019{
5020 assert(reopt != NULL);
5021
5022 return reopt->reopttree->ntotalinfnodes;
5023}
5024
5025/** constructor for the reoptimization data */
5027 SCIP_REOPT** reopt, /**< pointer to reoptimization data structure */
5028 SCIP_SET* set, /**< global SCIP settings */
5029 BMS_BLKMEM* blkmem /**< block memory */
5030 )
5031{
5032 SCIP_EVENTHDLR* eventhdlr;
5033
5034 assert(reopt != NULL);
5035
5036 SCIP_ALLOC( BMSallocMemory(reopt) );
5037 (*reopt)->runsize = DEFAULT_MEM_RUN;
5038 (*reopt)->run = 0;
5039 (*reopt)->simtolastobj = -2.0;
5040 (*reopt)->simtofirstobj = -2.0;
5041 (*reopt)->firstobj = -1;
5042 (*reopt)->currentnode = -1;
5043 (*reopt)->lastbranched = -1;
5044 (*reopt)->dualreds = NULL;
5045 (*reopt)->glbconss = NULL;
5046 (*reopt)->nglbconss = 0;
5047 (*reopt)->allocmemglbconss = 0;
5048 (*reopt)->ncheckedsols = 0;
5049 (*reopt)->nimprovingsols = 0;
5050 (*reopt)->noptsolsbyreoptsol = 0;
5051 (*reopt)->nglbrestarts = 0;
5052 (*reopt)->nlocrestarts = 0;
5053 (*reopt)->ntotallocrestarts = 0;
5054 (*reopt)->firstrestart = -1;
5055 (*reopt)->lastrestart = 0;
5056 (*reopt)->nobjvars = 0;
5057 (*reopt)->objhaschanged = FALSE;
5058 (*reopt)->consadded = FALSE;
5059 (*reopt)->addedconss = NULL;
5060 (*reopt)->naddedconss = 0;
5061 (*reopt)->addedconsssize = 0;
5062 (*reopt)->glblb = NULL;
5063 (*reopt)->glbub = NULL;
5064 (*reopt)->nactiveconss = 0;
5065 (*reopt)->nmaxactiveconss = 0;
5066 (*reopt)->activeconss = NULL;
5067 (*reopt)->activeconssset = NULL;
5068
5069 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize) );
5070 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
5071 SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
5072
5073 for( int i = 0; i < (*reopt)->runsize; ++i )
5074 {
5075 (*reopt)->objs[i] = NULL;
5076 (*reopt)->prevbestsols[i] = NULL;
5077 (*reopt)->varhistory[i] = NULL;
5078 }
5079
5080 /* clocks */
5081 SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
5082
5083 /* create and initialize SCIP_SOLTREE */
5084 SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
5085 SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
5086
5087 /* create and initialize SCIP_REOPTTREE */
5088 SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
5089 SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
5090
5091 /* create a random number generator */
5092 SCIP_CALL( SCIPrandomCreate(&(*reopt)->randnumgen, blkmem, SCIPsetInitializeRandomSeed(set, DEFAULT_RANDSEED)) );
5093
5094 /* create event handler for node events */
5095 eventhdlr = NULL;
5096
5097 /* include event handler into SCIP */
5099 eventInitsolReopt, eventExitsolReopt, NULL, eventExecReopt, NULL) );
5100 SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
5101 assert(eventhdlr != NULL);
5102
5103 return SCIP_OKAY;
5104}
5105
5106/* release all variables and constraints captured during reoptimization */
5108 SCIP_REOPT* reopt, /**< pointer to reoptimization data structure */
5109 SCIP_SET* set, /**< global SCIP settings */
5110 BMS_BLKMEM* blkmem /**< block memory */
5111 )
5112{
5113 /* release all added constraints and free the data */
5114 if( reopt->addedconss != NULL )
5115 {
5116 for( int c = 0; c < reopt->naddedconss; ++c )
5117 {
5118 assert(reopt->addedconss[c] != NULL);
5119
5120 SCIP_CALL( SCIPconsRelease(&reopt->addedconss[c], blkmem, set) );
5121 }
5122
5123 BMSfreeBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize);
5124 reopt->naddedconss = 0;
5125 reopt->addedconsssize = 0;
5126 }
5127
5128 SCIP_CALL( cleanActiveConss(reopt, set, blkmem) );
5129
5130 return SCIP_OKAY;
5131}
5132
5133/** frees reoptimization data */
5135 SCIP_REOPT** reopt, /**< reoptimization data structure */
5136 SCIP_SET* set, /**< global SCIP settings */
5137 SCIP_PRIMAL* origprimal, /**< original primal */
5138 BMS_BLKMEM* blkmem /**< block memory */
5139 )
5140{
5141 assert(reopt != NULL);
5142 assert(*reopt != NULL);
5143 assert(set != NULL);
5144 assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
5145 assert(blkmem != NULL);
5146
5147 /* free random number generator */
5148 SCIPrandomFree(&(*reopt)->randnumgen, blkmem);
5149
5150 /* free reopttree */
5151 SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
5152
5153 /* free solutions and variable histories */
5154 if( set->stage >= SCIP_STAGE_PROBLEM )
5155 {
5156 for( int p = (*reopt)->run-1; p >= 0; --p )
5157 {
5158 if( (*reopt)->soltree->sols[p] != NULL )
5159 {
5160 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
5161 (*reopt)->soltree->sols[p] = NULL;
5162 }
5163
5164 if( set->reopt_storevarhistory && (*reopt)->varhistory[p] != NULL )
5165 {
5166 for( int v = SCIPgetNOrigVars(set->scip)-1; v >= 0; --v )
5167 {
5168 SCIPhistoryFree(&(*reopt)->varhistory[p][v], blkmem);
5169 }
5170
5171 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory[p], SCIPgetNOrigVars(set->scip));
5172 (*reopt)->varhistory[p] = NULL;
5173 }
5174
5175 /* we have to free all optimal solution separatly, because those solutions are not stored in the
5176 * solution reopt_sepabestsol = TRUE
5177 */
5178 if( set->reopt_sepabestsol && (*reopt)->prevbestsols[p] != NULL )
5179 {
5180 SCIP_CALL( SCIPsolFree(&(*reopt)->prevbestsols[p], blkmem, origprimal) );
5181 }
5182
5183 if( (*reopt)->objs[p] != NULL )
5184 {
5185 BMSfreeMemoryArray(&(*reopt)->objs[p]);
5186 }
5187 }
5188 }
5189
5190 /* free solution tree */
5191 SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
5192
5193 if( (*reopt)->dualreds != NULL )
5194 {
5195 if( (*reopt)->dualreds->varssize > 0 )
5196 {
5197 assert(!(*reopt)->dualreds->linear);
5198
5199 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->boundtypes, (*reopt)->dualreds->varssize);
5200 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vals, (*reopt)->dualreds->varssize);
5201 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vars, (*reopt)->dualreds->varssize);
5202 BMSfreeBlockMemory(blkmem, &(*reopt)->dualreds);
5203 (*reopt)->dualreds = NULL;
5204 }
5205 }
5206
5207 if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
5208 {
5209 /* free all constraint */
5210 for( int c = 0; c < (*reopt)->allocmemglbconss; ++c )
5211 {
5212 if( (*reopt)->glbconss[c] != NULL )
5213 {
5214 if( (*reopt)->glbconss[c]->varssize > 0 )
5215 {
5216 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->boundtypes, (*reopt)->glbconss[c]->varssize);
5217 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
5218 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
5219 (*reopt)->glbconss[c]->varssize = 0;
5220 }
5221 BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
5222 --(*reopt)->nglbconss;
5223 }
5224 }
5225 assert((*reopt)->nglbconss == 0);
5226
5227 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
5228 (*reopt)->allocmemglbconss = 0;
5229 }
5230
5231 /* clocks */
5232 SCIPclockFree(&(*reopt)->savingtime);
5233
5234 /* the hashmap need not to be exist, e.g., if the problem was solved during presolving */
5235 if( (*reopt)->activeconssset != NULL )
5236 {
5237 SCIPhashsetFree(&(*reopt)->activeconssset, blkmem);
5238 }
5239 BMSfreeBlockMemoryArrayNull(blkmem, &(*reopt)->activeconss, (*reopt)->nmaxactiveconss);
5240
5241 if( (*reopt)->glblb != NULL )
5242 {
5243 SCIPhashmapFree(&(*reopt)->glblb);
5244 SCIPhashmapFree(&(*reopt)->glbub);
5245 (*reopt)->glblb = NULL;
5246 (*reopt)->glbub = NULL;
5247 }
5248 else
5249 assert((*reopt)->glbub == NULL);
5250
5251 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize);
5252 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
5253 BMSfreeMemoryArray(&(*reopt)->objs);
5254 BMSfreeMemory(reopt);
5255
5256 return SCIP_OKAY;
5257}
5258
5259/** returns the number of constraints added by the reoptimization plug-in */
5261 SCIP_REOPT* reopt, /**< reoptimization data structure */
5262 SCIP_NODE* node /**< node of the search tree */
5263 )
5264{
5265 unsigned int id;
5266
5267 assert(reopt != NULL);
5268 assert(node != NULL);
5269
5270 id = SCIPnodeGetReoptID(node);
5271 assert(id < reopt->reopttree->reoptnodessize);
5272
5273 /* set the id to -1 if the node is not part of the reoptimization tree */
5274 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5275 return SCIPnodeGetNAddedConss(node);
5276
5277 if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
5278 return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
5279 else
5280 return SCIPnodeGetNAddedConss(node);
5281}
5282
5283/** add a solution to the solution tree */
5285 SCIP_REOPT* reopt, /**< reoptimization data */
5286 SCIP_SET* set, /**< global SCIP settings */
5287 SCIP_STAT* stat, /**< dynamic problem statistics */
5288 SCIP_PRIMAL* origprimal, /**< original primal */
5289 BMS_BLKMEM* blkmem, /**< block memory */
5290 SCIP_SOL* sol, /**< solution to add */
5291 SCIP_Bool bestsol, /**< is the current solution an optimal solution? */
5292 SCIP_Bool* added, /**< pointer to store the information if the soltion was added */
5293 SCIP_VAR** vars, /**< variable array */
5294 int nvars, /**< number of variables */
5295 int run /**< number of the current run (1,2,...) */
5296 )
5297{
5298 SCIP_SOLNODE* solnode = NULL;
5299 SCIP_HEUR* heur;
5300 int insertpos;
5301
5302 assert(reopt != NULL);
5303 assert(set != NULL);
5304 assert(sol != NULL);
5305 assert(run > 0);
5306
5307 assert(reopt->soltree->sols[run-1] != NULL);
5308
5309 /* if the solution was found by reoptsols the solutions is already stored */
5310 heur = SCIPsolGetHeur(sol);
5311 if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
5312 ++reopt->noptsolsbyreoptsol;
5313 else if( bestsol )
5314 reopt->noptsolsbyreoptsol = 0;
5315
5316 /* check memory */
5317 SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1]+1, run-1) );
5318
5319 /* add solution to solution tree */
5320 SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
5321
5322 if( (*added) )
5323 {
5324 assert(solnode != NULL);
5325
5326 /* add solution */
5327 insertpos = reopt->soltree->nsols[run-1];
5328 reopt->soltree->sols[run-1][insertpos] = solnode;
5329 ++reopt->soltree->nsols[run-1];
5330 assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
5331 }
5332
5333 return SCIP_OKAY;
5334}
5335
5336/** we want to store the optimal solution of each run in a separate array */
5338 SCIP_REOPT* reopt, /**< reoptimization data structure */
5339 SCIP_SOL* sol, /**< solution to add */
5340 BMS_BLKMEM* blkmem, /**< block memory */
5341 SCIP_SET* set, /**< global SCIP settings */
5342 SCIP_STAT* stat, /**< dynamic problem statistics */
5343 SCIP_PRIMAL* origprimal, /**< original primal */
5344 SCIP_VAR** vars, /**< original problem variables */
5345 int nvars /**< number of original problem variables */
5346 )
5347{
5348 SCIP_SOL* solcopy;
5349
5350 assert(reopt != NULL);
5351 assert(reopt->run-1 >= 0);
5352 assert(sol != NULL);
5353 assert(blkmem != NULL);
5354 assert(set != NULL);
5355 assert(stat != NULL);
5356 assert(origprimal != NULL);
5357
5358 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
5359 reopt->prevbestsols[reopt->run-1] = solcopy;
5360
5361 /* store a global constraint that cutsoff the solution */
5362 if( set->reopt_sepabestsol )
5363 {
5364 SCIP_CALL( separateSolution(reopt, blkmem, set, stat, sol, vars, nvars) );
5365 }
5366
5367 return SCIP_OKAY;
5368}
5369
5370/** add a new iteration after changing the objective function */
5372 SCIP_REOPT* reopt, /**< reoptimization data sturcture */
5373 SCIP_SET* set, /**< global SCIP settings */
5374 BMS_BLKMEM* blkmem, /**< block memory */
5375 SCIP_VAR** origvars, /**< original problem variables */
5376 int norigvars, /**< number of original variables */
5377 int size /**< number of expected solutions */
5378 )
5379{
5380 assert(reopt != NULL);
5381 assert(set != NULL);
5382 assert(blkmem != NULL);
5383 assert(origvars != NULL);
5384
5385 /* increase number of runs */
5386 ++reopt->run;
5387
5388 /* check memory */
5389 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
5390
5391 /* allocate memory */
5392 reopt->soltree->solssize[reopt->run-1] = size;
5393 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
5394
5395 /* reset flag */
5396 reopt->objhaschanged = FALSE;
5397
5398 /* save the objective function */
5399 SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, origvars, norigvars) );
5400
5401 resetStats(reopt);
5402
5403 return SCIP_OKAY;
5404}
5405
5406/** get the number of checked solutions during the reoptimization process */
5408 SCIP_REOPT* reopt /**< reoptimization data structure */
5409 )
5410{
5411 assert(reopt != NULL);
5412
5413 return reopt->ncheckedsols;
5414}
5415
5416/** update the number of checked solutions during the reoptimization process */
5418 SCIP_REOPT* reopt, /**< reoptimization data structure */
5419 int ncheckedsols /**< number of updated solutions */
5420 )
5421{
5422 assert(reopt != NULL);
5423
5424 reopt->ncheckedsols += ncheckedsols;
5425}
5426
5427/** get the number of checked solutions during the reoptimization process */
5429 SCIP_REOPT* reopt /**< reoptimization data structure */
5430 )
5431{
5432 assert(reopt != NULL);
5433
5434 return reopt->nimprovingsols;
5435}
5436
5437/** update the number of checked solutions during the reoptimization process */
5439 SCIP_REOPT* reopt, /**< reoptimization data structure */
5440 int nimprovingsols /**< number of improving solutions */
5441 )
5442{
5443 assert(reopt != NULL);
5444
5445 reopt->nimprovingsols += nimprovingsols;
5446}
5447
5448/** returns number of solutions stored in the solution tree of a given run */
5450 SCIP_REOPT* reopt, /**< reoptimization data structure */
5451 int run /**< number of the run (1,2,..) */
5452 )
5453{
5454 assert(reopt != NULL);
5455 assert(0 < run && run <= reopt->runsize);
5456
5457 if( reopt->soltree->sols[run-1] == NULL )
5458 return 0;
5459 else
5460 return reopt->soltree->nsols[run-1];
5461}
5462
5463/** returns number of all solutions of all runs */
5465 SCIP_REOPT* reopt /**< reoptimization data structure */
5466 )
5467{
5468 int nsols = 0;
5469
5470 assert(reopt != NULL);
5471
5472 for( int r = 0; r < reopt->run; ++r )
5473 nsols += reopt->soltree->nsols[r];
5474
5475 return nsols;
5476}
5477
5478/** return the stored solutions of a given run */
5480 SCIP_REOPT* reopt, /**< reoptimization data structure */
5481 int run, /**< number of the run (1,2,...) */
5482 SCIP_SOL** sols, /**< array of solutions to fill */
5483 int solssize, /**< length of the array */
5484 int* nsols /**< pointer to store the number of added solutions */
5485 )
5486{
5487 assert(reopt != NULL);
5488 assert(run > 0 && run <= reopt->run);
5489 assert(sols != NULL);
5490
5491 assert(solssize > 0);
5492 assert(nsols != NULL);
5493 *nsols = 0;
5494
5495 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
5496 {
5497 if( !reopt->soltree->sols[run-1][s]->updated )
5498 ++(*nsols);
5499 }
5500
5501 if( solssize < (*nsols) )
5502 return SCIP_OKAY;
5503
5504 (*nsols) = 0;
5505 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
5506 {
5507 if( !reopt->soltree->sols[run-1][s]->updated )
5508 {
5509 sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
5510 reopt->soltree->sols[run-1][s]->updated = TRUE;
5511 ++(*nsols);
5512 }
5513 }
5514
5515 return SCIP_OKAY;
5516}
5517
5518/** returns the number of saved solutions overall runs */
5520 SCIP_REOPT* reopt /**< reoptimization data structure */
5521 )
5522{
5523 int nsavedsols = 0;
5524
5525 assert(reopt != NULL);
5526 assert(reopt->soltree->root != NULL);
5527
5528 if( reopt->soltree->root->child != NULL )
5529 nsavedsols = soltreeNInducedSols(reopt->soltree->root);
5530
5531 return nsavedsols;
5532}
5533
5534/** check if the reoptimization process should be (locally) restarted.
5535 *
5536 * First, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
5537 * the similarity again. we trigger a restart if
5538 * 1. the objective function has changed too much
5539 * 2. the number of stored nodes is exceeded
5540 * 3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
5541 * prove the optimality and this can be probably faster by solving from scratch)
5542 *
5543 * If the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
5544 * that are already fixed by bounding.
5545 */
5547 SCIP_REOPT* reopt, /**< reoptimization data structure */
5548 SCIP_SET* set, /**< global SCIP settings */
5549 BMS_BLKMEM* blkmem, /**< block memory */
5550 SCIP_NODE* node, /**< current node of the branch and bound tree (or NULL) */
5551 SCIP_VAR** transvars, /**< transformed problem variables */
5552 int ntransvars, /**< number of transformed problem variables */
5553 SCIP_Bool* restart /**< pointer to store if the reoptimization process should be restarted */
5554 )
5555{
5556 SCIP_Real sim = 1.0;
5557
5558 assert(reopt != NULL);
5559 assert(set != NULL);
5560 assert(blkmem != NULL);
5561 assert(transvars != NULL);
5562 assert(ntransvars >= 0);
5563 assert(restart != NULL);
5564
5565 *restart = FALSE;
5566
5567 /* check if the whole reoptimization process should start from scratch */
5568 if( node == NULL )
5569 {
5570 /* compute the similarity to the objective function of the first run after restarting */
5571 if( reopt->run > 1 && set->reopt_objsimdelay > -1.0 )
5572 {
5573 sim = reoptSimilarity(reopt, set, reopt->run-1, MAX(0, reopt->lastrestart-1), transvars, ntransvars);
5574
5575 if( sim == SCIP_INVALID ) /*lint !e777*/
5576 return SCIP_INVALIDRESULT;
5577 }
5578
5579 /* check similarity */
5580 if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
5581 {
5582 SCIPsetDebugMsg(set, "-> restart reoptimization (objective functions are not similar enough)\n");
5583 *restart = TRUE;
5584 }
5585 /* check size of the reoptimization tree */
5586 else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
5587 {
5588 SCIPsetDebugMsg(set, "-> restart reoptimization (node limit reached)\n");
5589 *restart = TRUE;
5590 }
5591 /* check if the tree was only needed to prove optimality */
5592 else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
5593 {
5594 SCIPsetDebugMsg(set, "-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
5595 reopt->noptsolsbyreoptsol);
5596 reopt->noptsolsbyreoptsol = 0;
5597 *restart = TRUE;
5598 }
5599
5600 if( *restart )
5601 {
5602 /* trigger a restart */
5603 SCIP_CALL( reoptRestart(reopt, set, blkmem) );
5604 }
5605 }
5606 /* check for a local restart, ie, start the solving process of an inner node from scatch */
5607 else
5608 {
5609 SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
5610 }
5611 return SCIP_OKAY;
5612}
5613
5614/** returns the similarity to the previous objective function, if no exist return -2.0 */
5616 SCIP_REOPT* reopt /**< reoptimization data structure */
5617 )
5618{
5619 assert(reopt != NULL);
5620 return reopt->simtolastobj;
5621}
5622
5623/** returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
5625 SCIP_REOPT* reopt /**< reoptimization data structure */
5626 )
5627{
5628 assert(reopt != NULL);
5629 return reopt->simtofirstobj;
5630}
5631
5632/** return the similarity between two of objective functions of two given runs */
5634 SCIP_REOPT* reopt, /**< reoptimization data structure */
5635 SCIP_SET* set, /**< global SCIP settings */
5636 int run1, /**< number of the first run */
5637 int run2, /**< number of the second run */
5638 SCIP_VAR** origvars, /**< original problem variables */
5639 int norigvars /**< number of original problem variables */
5640 )
5641{
5642 assert(reopt != NULL);
5643 assert(run1 > 0 && run1 <= reopt->run);
5644 assert(run2 > 0 && run2 <= reopt->run);
5645 assert(origvars != NULL);
5646 assert(norigvars >= 0);
5647
5648 return reoptSimilarity(reopt, set, run1-1, run2-1, origvars, norigvars);
5649}
5650
5651/** returns the best solution of the last run */
5653 SCIP_REOPT* reopt /**< reoptimization data structure */
5654 )
5655{
5656 assert(reopt != NULL);
5657 assert(reopt->prevbestsols != NULL);
5658
5659 if( reopt->run-2 < 0 )
5660 return NULL;
5661 else
5662 return reopt->prevbestsols[reopt->run-2];
5663}
5664
5665/** returns the node of the reoptimization tree corresponding to the unique @p id */
5667 SCIP_REOPT* reopt, /**< reoptimization data structure */
5668 unsigned int id /**< unique id */
5669 )
5670{
5671 assert(reopt != NULL);
5672 assert(reopt->reopttree != NULL);
5673 assert(id < reopt->reopttree->reoptnodessize);
5674 assert(reopt->reopttree->reoptnodes[id] != NULL);
5675
5676 return reopt->reopttree->reoptnodes[id];
5677}
5678
5679/** returns the coefficient of variable with index @p idx in run @p run */
5681 SCIP_REOPT* reopt, /**< reoptimization data structure */
5682 int run, /**< number of the run (1,2,...) */
5683 int idx /**< index of original variable */
5684 )
5685{
5686 assert(reopt != NULL);
5687 assert(0 < run && run <= reopt->runsize);
5688
5689 return reopt->objs[run-1][idx];
5690}
5691
5692/** return the best solution of a given run.
5693 *
5694 * @note the returned solution is part of the original space.
5695 */
5697 SCIP_REOPT* reopt, /**< reoptimization data structure */
5698 int run /**< number of the run (1,2,...) */
5699 )
5700{
5701 assert(reopt != NULL);
5702 assert(0 < run && run <= reopt->run);
5703
5704 return reopt->prevbestsols[run-1];
5705}
5706
5707/** reset solving specific parameters */
5709 SCIP_REOPT* reopt, /**< reoptimization data structure */
5710 SCIP_SET* set, /**< global SCIP settings */
5711 BMS_BLKMEM* blkmem /**< block memory */
5712 )
5713{
5714 assert(reopt != NULL);
5715 assert(set != NULL);
5716 assert(blkmem != NULL);
5717
5718 /* clean addedconss array */
5719 for( int c = 0; c < reopt->naddedconss; ++c )
5720 {
5721 SCIP_CONS* cons;
5722
5723 cons = reopt->addedconss[c];
5724 assert(cons != NULL);
5725
5726#ifdef SCIP_MORE_DEBUG
5727 SCIPsetDebugMsg(set, "release cons <%s> from reoptimization data\n", SCIPconsGetName(cons));
5728#endif
5729
5730 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5731 reopt->addedconss[c] = NULL;
5732 }
5733
5734 reopt->naddedconss = 0;
5735 reopt->consadded = FALSE;
5736 reopt->objhaschanged = FALSE;
5737
5738 return SCIP_OKAY;
5739}
5740
5741/** reset marks of stored solutions to not updated */
5743 SCIP_REOPT* reopt /**< reoptimization data structure */
5744 )
5745{
5746 SCIP_SOLNODE* child;
5747
5748 assert(reopt != NULL);
5749 assert(reopt->soltree != NULL);
5750 assert(reopt->soltree->root != NULL);
5751
5752 child = reopt->soltree->root->child;
5753
5754 /* traverse through the list */
5755 while( child != NULL )
5756 {
5757 soltreeResetMarks(child);
5758 child = child->sibling;
5759 }
5760}
5761
5762/** returns the number of stored nodes in the subtree induced by @p node */
5764 SCIP_REOPT* reopt, /**< reoptimization data structure */
5765 SCIP_NODE* node /**< node of the search tree */
5766 )
5767{
5768 unsigned int id;
5769
5770 assert(reopt != NULL);
5771
5772 if( node == NULL || SCIPnodeGetDepth(node) == 0 )
5773 return reopt->reopttree->nreoptnodes;
5774
5775 id = SCIPnodeGetReoptID(node);
5776 assert(id < reopt->reopttree->reoptnodessize);
5777
5778 /* set the id to -1 if the node is not part of the reoptimization tree */
5779 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
5780 return 0;
5781
5782 assert(0 < id && id < reopt->reopttree->reoptnodessize);
5783
5784 return reopttreeGetNNodes(reopt->reopttree, id);
5785}
5786
5787/* ---------------- methods of general reoptimization nodes ---------------- */
5788
5789/** In debug mode, the following methods are implemented as function calls to ensure
5790 * type validity.
5791 * In optimized mode, the methods are implemented as defines to improve performance.
5792 * However, we want to have them in the library anyways, so we have to undef the defines.
5793 */
5794
5795#undef SCIPreoptnodeGetNVars
5796#undef SCIPreoptnodeGetNConss
5797#undef SCIPreoptnodeGetNDualBoundChgs
5798#undef SCIPreoptnodeGetNChildren
5799#undef SCIPreoptnodeGetLowerbound
5800#undef SCIPreoptnodeGetType
5801
5802/** returns the number of bound changes stored in the reopttree at ID id */
5804 SCIP_REOPTNODE* reoptnode /**< node of the reopttree */
5805 )
5806{
5807 assert(reoptnode != NULL);
5808
5809 return reoptnode->nvars + reoptnode->nafterdualvars;
5810}
5811
5812/** returns the number of bound changes at the node stored at ID id */
5814 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5815 )
5816{
5817 assert(reoptnode != NULL);
5818
5819 return reoptnode->nconss;
5820}
5821
5822/** returns the number of stored bound changes based on dual information in the reopttree at ID id */
5824 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5825 )
5826{
5827 assert(reoptnode != NULL);
5828
5829 if( reoptnode->dualredscur == NULL )
5830 return 0;
5831 else
5832 return reoptnode->dualredscur->nvars;
5833}
5834
5835/** returns the number of child nodes of @p reoptnode */
5837 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5838 )
5839{
5840 assert(reoptnode != NULL);
5841
5842 return reoptnode->nchilds;
5843}
5844
5845/** return the lower bound stored at @p ID id */
5847 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5848 )
5849{
5850 assert(reoptnode != NULL);
5851
5852 return reoptnode->lowerbound;
5853}
5854
5855/** returns the type of the @p reoptnode */
5857 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
5858 )
5859{
5860 assert(reoptnode != NULL);
5861
5862 return (SCIP_REOPTTYPE)reoptnode->reopttype;
5863}
5864
5865/** returns all added constraints at ID id */
5867 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
5868 SCIP_VAR*** vars, /**< 2-dim array of variables */
5869 SCIP_Real** bounds, /**< 2-dim array of bounds */
5870 SCIP_BOUNDTYPE** boundtypes, /**< 2-dim array of boundtypes */
5871 int mem, /**< allocated memory for constraints */
5872 int* nconss, /**< pointer to store the number of constraints */
5873 int* nvars /**< pointer to store the number of variables */
5874 )
5875{
5876 assert(reoptnode != NULL);
5877 assert(vars != NULL);
5878 assert(bounds != NULL);
5879 assert(boundtypes != NULL);
5880 assert(nvars != NULL);
5881 assert(nconss != NULL);
5882
5883 (*nconss) = reoptnode->nconss;
5884
5885 if( mem < *nconss )
5886 return;
5887
5888 for( int c = 0; c < *nconss; ++c )
5889 {
5890 assert(vars[c] != NULL);
5891 assert(bounds[c] != NULL);
5892
5893 vars[c] = reoptnode->conss[c]->vars;
5894 bounds[c] = reoptnode->conss[c]->vals;
5895 boundtypes[c] = reoptnode->conss[c]->boundtypes;
5896 nvars[c] = reoptnode->conss[c]->nvars;
5897 }
5898}
5899
5900/** set the parent id */
5902 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
5903 unsigned int parentid /**< id of the parent node */
5904 )
5905{
5906 assert(reoptnode != NULL);
5907 assert(parentid <= 536870911); /* id can be at most 2^29 - 1 */
5908
5909 reoptnode->parentID = parentid;
5910}
5911
5912/** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
5914 SCIP_REOPT* reopt, /**< reoptimization data structure */
5915 SCIP_NODE* node /**< node of the search tree (or NULL) */
5916 )
5917{
5918 int nleaves = 0;
5919 unsigned int id;
5920
5921 assert(reopt != NULL);
5922
5923 id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
5924 assert(id < reopt->reopttree->reoptnodessize);
5925
5926 /* return if the node is not part of the reoptimization tree */
5927 if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
5928 return nleaves;
5929
5930 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
5931 {
5932 unsigned int childid;
5933
5934 childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
5935 assert(childid < reopt->reopttree->reoptnodessize);
5936
5937 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
5938 ++nleaves;
5939 else
5940 nleaves += reoptGetNLeaves(reopt, childid);
5941 }
5942
5943 return nleaves;
5944}
5945
5946/** save information that given node is infeasible */
5948 SCIP_REOPT* reopt, /**< reoptimization data structure */
5949 SCIP_SET* set, /**< global SCIP settings */
5950 BMS_BLKMEM* blkmem, /**< block memory */
5951 SCIP_NODE* node /**< node of the search tree */
5952 )
5953{
5954 assert(reopt != NULL);
5955 assert(set != NULL);
5956 assert(blkmem != NULL);
5957 assert(node != NULL);
5958
5959 if( set->reopt_sepaglbinfsubtrees )
5960 {
5961 SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_CUT) );
5962 }
5963
5964 ++reopt->reopttree->ninfnodes;
5965 ++reopt->reopttree->ntotalinfnodes;
5966
5967 return SCIP_OKAY;
5968}
5969
5970/** check the reason for cut off a node and if necessary store the node */
5972 SCIP_REOPT* reopt, /**< reoptimization data structure */
5973 SCIP_SET* set, /**< global SCIP settings */
5974 BMS_BLKMEM* blkmem, /**< block memory */
5975 SCIP_NODE* node, /**< node of the search tree */
5976 SCIP_EVENTTYPE eventtype, /**< eventtype */
5977 SCIP_LP* lp, /**< LP data */
5978 SCIP_LPSOLSTAT lpsolstat, /**< solution status of the LP */
5979 SCIP_Bool isrootnode, /**< the node is the root */
5980 SCIP_Bool isfocusnode, /**< the node is the current focus node */
5981 SCIP_Real lowerbound, /**< lower bound of the node */
5982 int effectiverootdepth /**< effective root depth */
5983 )
5984{
5985 SCIP_Bool strongbranched;
5986
5987 assert(reopt != NULL);
5988 assert(set != NULL);
5989 assert(blkmem != NULL);
5990 assert(lp != NULL);
5991 assert(node != NULL);
5992 assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
5993
5994 if( reopt->lastseennode == SCIPnodeGetNumber(node) )
5995 return SCIP_OKAY;
5996
5997 /* we do not want to store probing node */
5999 return SCIP_OKAY;
6000
6001 reopt->lastseennode = SCIPnodeGetNumber(node);
6002
6003 SCIPsetDebugMsg(set, "catch event %" SCIP_EVENTTYPE_FORMAT " for node %lld (type:%d)\n", eventtype, SCIPnodeGetNumber(node), SCIPnodeGetType(node));
6004
6005 /* case 1: the current node is the root node
6006 * we can skip if the root is (in)feasible or branched w/o bound
6007 * changes based on dual information.
6008 *
6009 * case 2: we need to store the current node if it contains
6010 * bound changes based on dual information or is a leave node
6011 */
6012 if( isrootnode )
6013 {
6014 if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
6015 {
6016 goto CHECK;
6017 }
6018 else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
6019 {
6020 /* store or update the information */
6021 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6022 }
6023 else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
6024 {
6025 /* delete saved dual information which would lead to split the node in a further iteration */
6026 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6027
6028 /* store or update the information */
6029 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6030 }
6031 else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
6032 {
6033 /* delete saved dual information which would lead to split the node in a further iteration */
6034 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
6035
6037 {
6038 SCIP_Real cutoffbound = SCIPlpGetCutoffbound(lp);
6039 lowerbound = MIN(lowerbound, cutoffbound);
6040 }
6041
6042 /* store or update the information */
6043 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
6044 isrootnode, lowerbound) );
6045 }
6046
6047 assert(reopt->currentnode == -1);
6048 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6049
6050 return SCIP_OKAY;
6051 }
6052
6053 CHECK:
6054
6055 if( effectiverootdepth == SCIPnodeGetDepth(node) )
6056 strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
6057 else
6058 strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
6059
6060 SCIPsetDebugMsg(set, "check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
6061 SCIPsetDebugMsg(set, " -> focusnode : %s\n", isfocusnode ? "yes" : "no");
6062 SCIPsetDebugMsg(set, " -> depth : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
6063 SCIPsetDebugMsg(set, " -> strong branched : %s\n", strongbranched ? "yes" : "no");
6064 SCIPsetDebugMsg(set, " -> LP lpsolstat : %d\n", lpsolstat);
6065
6066 switch( eventtype )
6067 {
6069 /* current node has to be the eventnode */
6070 assert(isfocusnode);
6071
6072 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_FEASIBLE);
6073
6074 /* delete strong branching information of some exists */
6075 deleteLastDualBndchgs(reopt);
6076
6077 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
6078 break;
6079
6081 /* We have to check if the current node is the event node.
6082 * if the current node is not the event node, we have to save this node, else we have to
6083 * look at LP lpsolstat and decide.
6084 */
6085 if( isfocusnode )
6086 {
6087 /* An after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
6088 * because the node is already branched we have all children and can delete this node.
6089 */
6090 if( SCIPnodeGetNumber(node) == reopt->lastbranched )
6091 {
6092 deleteLastDualBndchgs(reopt);
6093 break;
6094 }
6095
6096 /* If the node is strong branched, we possibly detect an infeasible subtree;
6097 * otherwise, the whole node is either infeasible or exceeds the cutoff bound.
6098 */
6099 if( strongbranched )
6100 {
6101 /* 1. the LP is infeasible: the (sub-)node is infeasible and can be discarded
6102 * because the LP proves infeasibility. We have to store an infeasible subtree separated by a constraint.
6103 * 2. the LP exceeds the objective limit or was not solved, we have to store the node and can delete the
6104 * strong branching information
6105 */
6106 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6107 {
6108 /* add a dummy variable, because the bound changes were not global in the sense of effective root depth */
6109 if( SCIPnodeGetDepth(node) > effectiverootdepth )
6110 {
6111 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6112 }
6113
6114 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6115 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_INFSUBTREE);
6116
6117 /* save the node as a strong branched node */
6118 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
6119 }
6120 else
6121 {
6122 assert( lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
6123
6124 /* delete strong branching information if some exists */
6125 deleteLastDualBndchgs(reopt);
6126
6127 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6128 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6129 }
6130 }
6131 else
6132 {
6133 /* 1. the LP is infeasible: the whole node is infeasible and can be discarded
6134 * 2. the LP was not solved or exceeds the objective limit, we have to store the node
6135 */
6136 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
6137 {
6138 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
6139 SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
6140 }
6141 else
6142 {
6143 assert(lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED || lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
6144 || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
6145
6146 if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6147 {
6148 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6149 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6150 }
6151 else
6152 {
6153 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6154 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6155 }
6156 }
6157 }
6158 }
6159 else
6160 {
6161 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
6162
6163 /* if the node was created by branch_nodereopt, nothing happens */
6164 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
6165 }
6166 break;
6167
6169 /* current node has to be the eventnode */
6170 assert(isfocusnode);
6171
6172 reopt->lastbranched = SCIPnodeGetNumber(node);
6173
6174 /* we have to check the depth of the current node. if the depth is equal to the effective
6175 * root depth, then all information about bound changes based on dual information already exists,
6176 * else we have to look at the domchg-data-structure.
6177 */
6178 if (SCIPnodeGetDepth(node) == effectiverootdepth)
6179 {
6180 /* Save the node if there are added constraints, because this means the node is a copy create by the
6181 * reoptimization plug-in and contains at least one logic-or-constraint */
6182 if( strongbranched )
6183 {
6184 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6185 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
6186 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6187 }
6188 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6189 {
6190 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6191 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6192 }
6193 else
6194 {
6195 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
6196 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6197 }
6198 }
6199 else
6200 {
6201 /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
6202 *
6203 * we have to do this in the following order:
6204 * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
6205 * on dual information.
6206 * 2) save or update the node.
6207 */
6208 if( strongbranched )
6209 {
6210 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
6211 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
6212 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
6213 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
6214 }
6215 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
6216 {
6217 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
6218 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
6219 }
6220 else
6221 {
6222 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
6223 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
6224 }
6225 }
6226 break;
6227
6228 default:
6229 break;
6230 }
6231
6232 assert(reopt->currentnode == -1);
6233 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6234
6235 return SCIP_OKAY; /*lint !e438*/
6236}
6237
6238/** store bound change based on dual information */
6240 SCIP_REOPT* reopt, /**< reoptimization data structure */
6241 SCIP_SET* set, /**< global SCIP settings */
6242 BMS_BLKMEM* blkmem, /**< block memory */
6243 SCIP_NODE* node, /**< node of the search tree */
6244 SCIP_VAR* var, /**< variable */
6245 SCIP_Real newval, /**< new bound */
6246 SCIP_Real oldval /**< old bound */
6247 )
6248{
6249 SCIP_Real constant = 0.0;
6250 SCIP_Real scalar = 1.0;
6251
6252 assert(reopt != NULL);
6253 assert(node != NULL);
6254
6255 /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
6256 * In that case, all bound changes were not global and we can find them within the
6257 * domchg data structure.
6258 * Otherwise, we allocate memory and store the information.
6259 */
6260 if( var != NULL )
6261 {
6262 SCIP_BOUNDTYPE boundtype;
6263 int resizelength;
6264 int allocmem;
6265
6266 if( SCIPsetFindBranchrule(set, "relpscost") != NULL )
6267 {
6268 SCIP_CALL( SCIPsetGetIntParam(set, "branching/relpscost/maxlookahead", &resizelength) );
6269 }
6270 else
6271 resizelength = 1;
6272
6273 if( reopt->dualreds == NULL || reopt->dualreds->varssize == 0 )
6274 allocmem = DEFAULT_MEM_DUALCONS;
6275 else
6276 allocmem = reopt->dualreds->nvars + resizelength;
6277
6278 /* allocate memory of necessary */
6279 SCIP_CALL( checkMemDualCons(reopt, set, blkmem, allocmem) );
6280
6281 assert(reopt->dualreds->varssize > 0);
6282 assert(reopt->dualreds->nvars >= 0);
6283 assert(reopt->currentnode == -1 || reopt->dualreds->nvars > 0);
6284 assert((reopt->dualreds->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
6285 || reopt->dualreds->nvars == 0);
6286
6287 reopt->currentnode = SCIPnodeGetNumber(node);
6288
6289 /* transform into the original space and then save the bound change */
6290 SCIP_CALL(SCIPvarGetOrigvarSum(&var, &scalar, &constant));
6291 newval = (newval - constant) / scalar;
6292 oldval = (oldval - constant) / scalar;
6293
6294 assert(SCIPvarIsOriginal(var));
6295
6296 if( SCIPsetIsEQ(set, oldval, newval) )
6297 {
6298 SCIPerrorMessage("cannot store equal bounds: old = %g, new = %g\n", oldval, newval);
6299 return SCIP_INVALIDDATA;
6300 }
6301
6302 if( SCIPsetIsLT(set, newval, oldval) )
6303 boundtype = SCIP_BOUNDTYPE_UPPER;
6304 else
6305 boundtype = SCIP_BOUNDTYPE_LOWER;
6306
6307 reopt->dualreds->vars[reopt->dualreds->nvars] = var;
6308 reopt->dualreds->vals[reopt->dualreds->nvars] = newval;
6309 reopt->dualreds->boundtypes[reopt->dualreds->nvars] = boundtype;
6310 ++reopt->dualreds->nvars;
6311
6312 SCIPsetDebugMsg(set, ">> store %s bound change of <%s>: %g -> %g\n",
6313 (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), SCIPvarGetName(var), oldval, newval);
6314
6315 reopt->dualreds->linear = FALSE;
6316 }
6317 else
6318 {
6319 assert(reopt->currentnode == -1);
6320 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
6321
6322 reopt->currentnode = SCIPnodeGetNumber(node);
6323 }
6324
6325 return SCIP_OKAY;
6326}
6327
6328/** returns the number of bound changes based on dual information */
6330 SCIP_REOPT* reopt, /**< reoptimization data structure */
6331 SCIP_NODE* node /**< node of the search tree */
6332 )
6333{
6334 int ndualbndchgs = 0;
6335
6336 assert(reopt != NULL);
6337 assert(node != NULL);
6338
6339 if( SCIPnodeGetNumber(node) == reopt->currentnode )
6340 {
6341 assert(reopt->dualreds != NULL);
6342 ndualbndchgs = reopt->dualreds->nvars;
6343 }
6344
6345 return ndualbndchgs;
6346}
6347
6348/** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
6350 SCIP_REOPT* reopt, /**< reoptimization data structure */
6351 SCIP_SET* set, /**< global SCIP settings */
6352 BMS_BLKMEM* blkmem, /**< block memory */
6353 SCIP_NODE* node, /**< node of the search tree */
6354 unsigned int* childs, /**< array to store the child ids */
6355 int childssize, /**< size of the childs array */
6356 int* nchilds /**< pointer to store the number of child nodes */
6357 )
6358{
6359 SCIP_Bool runagain;
6360 unsigned int id;
6361
6362 assert(reopt != NULL);
6363 assert(childssize > 0 && childs != NULL);
6364 assert(nchilds != NULL);
6365
6366 (*nchilds) = 0;
6367
6368 if( node == NULL )
6369 id = 0;
6370 else
6371 {
6372 id = SCIPnodeGetReoptID(node);
6373 assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
6374 }
6375
6376 assert(id < reopt->reopttree->reoptnodessize);
6377 assert(reopt->reopttree->reoptnodes[id] != NULL);
6378
6379 /* check if there are redundant bound changes or infeasible nodes */
6380 runagain = TRUE;
6381 while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6382 {
6383 SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
6384 }
6385
6386 /* return the list of child nodes if some exists; otherwise return NULL */
6387 if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
6388 {
6389 (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
6390
6391 if( childssize < *nchilds )
6392 return SCIP_OKAY;
6393
6394 for( int c = 0; c < *nchilds; ++c )
6395 childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
6396 }
6397
6398 return SCIP_OKAY;
6399}
6400
6401/** returns all leaves of the subtree induced by @p node */
6403 SCIP_REOPT* reopt, /**< reoptimization data */
6404 SCIP_NODE* node, /**< node of the search tree */
6405 unsigned int* leaves, /**< array to the the ids */
6406 int leavessize, /**< size of leaves array */
6407 int* nleaves /**< pointer to store the number of leave node */
6408 )
6409{
6410 unsigned int id;
6411
6412 assert(reopt != NULL);
6413 assert(leavessize > 0 && leaves != NULL);
6414 assert((*nleaves) >= 0);
6415
6416 /* if the given node is we start from the root */
6417 if( node == NULL )
6418 id = 0;
6419 else
6420 id = SCIPnodeGetReoptID(node);
6421
6422 /* return if the node is not part of the reoptimization tree */
6423 if( id == 0 && node != NULL )
6424 {
6425 (*nleaves) = 0;
6426 return SCIP_OKAY;
6427 }
6428
6429 assert(id < reopt->reopttree->reoptnodessize);
6430 assert(reopt->reopttree->reoptnodes[id] != NULL);
6431
6432 for( int i = 0; i < leavessize; ++i )
6433 leaves[i] = 0;
6434
6435 /* we traverse through all child nodes of the given node an collect all leave nodes of the subtrees induced by them */
6436 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
6437 {
6438 unsigned int childid;
6439
6440 assert(*nleaves + 1 <= leavessize);
6441
6442 childid = reopt->reopttree->reoptnodes[id]->childids[i];
6443 assert(childid < reopt->reopttree->reoptnodessize);
6444
6445 /* the node is already a leave */
6446 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
6447 {
6448 leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
6449 ++(*nleaves);
6450 }
6451 /* go into the tree induced by the current child node */
6452 else
6453 {
6454 int nleaves2 = 0;
6455
6456 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
6457 (*nleaves) += nleaves2;
6458 }
6459 }
6460
6461 return SCIP_OKAY;
6462}
6463
6464/** add all unprocessed nodes to the reoptimization tree */
6466 SCIP_REOPT* reopt, /**< reoptimization data structure */
6467 SCIP_SET* set, /**< global SCIP settings */
6468 SCIP_LP* lp, /**< current LP */
6469 BMS_BLKMEM* blkmem, /**< block memory */
6470 SCIP_NODE** leaves, /**< array of open leave nodes */
6471 int nleaves, /**< number of open leave nodes */
6472 SCIP_NODE** childs, /**< array of open children nodes */
6473 int nchilds, /**< number of open leave nodes */
6474 SCIP_NODE** siblings, /**< array of open sibling nodes */
6475 int nsiblings /**< number of open leave nodes */
6476 )
6477{
6478 assert(reopt != NULL);
6479 assert(set != NULL);
6480 assert(blkmem != NULL);
6481 assert(nleaves >= 0);
6482 assert(nleaves == 0 || leaves != NULL);
6483 assert(nchilds >= 0);
6484 assert(nchilds == 0 || childs != NULL);
6485 assert(nsiblings >= 0);
6486 assert(nsiblings == 0 || siblings != NULL);
6487
6488 SCIPsetDebugMsg(set, "save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
6489
6490 /* save open leaves */
6491 for( int n = 0; n < nleaves; ++n )
6492 {
6493 SCIP_CALL( addNode(reopt, set, lp, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6494 SCIPnodeGetLowerbound(leaves[n])) );
6495 }
6496
6497 /* save open children */
6498 for( int n = 0; n < nchilds; ++n )
6499 {
6500 SCIP_CALL( addNode(reopt, set, lp, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6501 SCIPnodeGetLowerbound(childs[n])) );
6502 }
6503
6504 /* save open siblings */
6505 for( int n = 0; n < nsiblings; ++n )
6506 {
6507 SCIP_CALL( addNode(reopt, set, lp, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
6508 SCIPnodeGetLowerbound(siblings[n])) );
6509 }
6510
6511 return SCIP_OKAY;
6512}
6513
6514/** merges the variable history of the current run with the stored history */
6516 SCIP_REOPT* reopt, /**< reoptimization data structure */
6517 SCIP_SET* set, /**< global SCIP settings */
6518 SCIP_STAT* stat, /**< dynamic problem statistics */
6519 SCIP_VAR** vars, /**< original problem variables */
6520 int nvars /**< number of original problem variables */
6521 )
6522{
6523 SCIP_VAR* transvar;
6524 SCIP_Real avginference[2];
6525 SCIP_Real avgcutoff[2];
6526 SCIP_Real bestsim;
6527 int bestrun;
6528 int idx;
6529
6530 assert(reopt != NULL);
6531 assert(stat != NULL);
6532 assert(nvars >= 0);
6533
6534 if( !set->reopt_storevarhistory )
6535 return SCIP_OKAY;
6536
6537 SCIPsetDebugMsg(set, "start merging variable histories:\n");
6538
6539 bestrun = reopt->run-2;
6540 bestsim = reopt->simtolastobj;
6541
6542 /* find the run with the most similar objective */
6543 for( int r = reopt->run-3; r >= 0 && reopt->objhaschanged && set->reopt_usepscost; --r )
6544 {
6545 SCIP_Real sim;
6546 sim = reoptSimilarity(reopt, set, r, reopt->run-1, vars, nvars);
6547
6548 if( sim == SCIP_INVALID ) /*lint !e777*/
6549 return SCIP_INVALIDRESULT;
6550
6551 if( SCIPsetIsGT(set, sim, bestsim) )
6552 {
6553 bestsim = sim;
6554 bestrun = r;
6555 }
6556 }
6557 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "run %d has best similarity=%g\n", bestrun, bestsim);
6558
6559 /* iterate through all variables and scale the histories */
6560 for( int v = 0; v < nvars; ++v )
6561 {
6562 assert(SCIPvarIsOriginal(vars[v]));
6563
6564 transvar = SCIPvarGetTransVar(vars[v]);
6565 assert(transvar != NULL);
6566
6567 /* skip variable that are not active */
6568 if( !SCIPvarIsActive(transvar) )
6569 continue;
6570
6571 idx = SCIPvarGetIndex(vars[v]);
6572 assert(0 <= idx && idx <= nvars);
6573
6574 /* set the updated history for both directions */
6575 for( int d = 0; d <= 1; ++d )
6576 {
6577 if( set->reopt_usepscost && !SCIPsetIsZero(set, reopt->varhistory[bestrun][idx]->pscostcount[d])
6578 && SCIPsetIsGT(set, bestsim, 0.985) ) /* 0.985 is a magic number determined in some experiments */
6579 {
6580 transvar->history->pscostcount[d] = 1.0;
6581 transvar->history->pscostweightedmean[d] = reopt->varhistory[bestrun][idx]->pscostweightedmean[d];
6582 transvar->history->pscostvariance[d] = 0.0;
6583 SCIPsetDebugMsg(set, "-> <%s> pscosts %4s: count=%g weightedmean=%g variance=%g\n", SCIPvarGetName(transvar),
6584 (d == 0 ? "down" : "up"), transvar->history->pscostcount[d], transvar->history->pscostweightedmean[d],
6585 transvar->history->pscostvariance[d]);
6586 }
6587
6589
6590 /* inference score */
6591 avginference[d] = SCIPhistoryGetAvgInferences(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6592 SCIPhistoryIncInferenceSum(transvar->history, (SCIP_BRANCHDIR)d, avginference[d]);
6593
6594 /* cutoff score */
6595 avgcutoff[d] = SCIPhistoryGetAvgCutoffs(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
6596 SCIPhistoryIncCutoffSum(transvar->history, (SCIP_BRANCHDIR)d, avgcutoff[d]);
6597
6598 SCIPsetDebugMsg(set, "-> <%s> %4s scores: inf=%g cutoff=%g\n", SCIPvarGetName(transvar),
6599 (d == 0 ? "down" : "up"), avginference[d], avgcutoff[d]);
6600 }
6601 }
6602
6603 return SCIP_OKAY;
6604}
6605
6606/** updates the variable history */
6608 SCIP_REOPT* reopt, /**< reoptimization data structure */
6609 SCIP_SET* set, /**< global SCIP settings */
6610 SCIP_STAT* stat, /**< dynamic problem statistics */
6611 BMS_BLKMEM* blkmem, /**< block memory */
6612 SCIP_VAR** vars, /**< original variable array */
6613 int nvars /**< number of original variables */
6614 )
6615{
6616 assert(reopt != NULL);
6617 assert(stat != NULL);
6618 assert(blkmem != NULL);
6619 assert(nvars >= 0);
6620
6621 if( !set->reopt_storevarhistory )
6622 return SCIP_OKAY;
6623
6624 SCIPsetDebugMsg(set, "updating variable history\n");
6625
6626 if( reopt->varhistory[reopt->run-1] == NULL )
6627 {
6628 /* allocate memory */
6629 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->varhistory[reopt->run-1], nvars) );
6630
6631 for( int v = 0; v < nvars; ++v )
6632 {
6633 SCIP_CALL( SCIPhistoryCreate(&(reopt->varhistory[reopt->run-1][v]), blkmem) );
6634 }
6635 }
6636
6637 /* update the history and scale them */
6638 for( int v = 0; v < nvars; ++v )
6639 {
6640 SCIP_VAR* transvar;
6641 int idx;
6642
6643 assert(SCIPvarIsOriginal(vars[v]));
6644 idx = SCIPvarGetIndex(vars[v]);
6645 assert(idx >= 0 && idx < nvars);
6646
6647 transvar = SCIPvarGetTransVar(vars[v]);
6648 assert(transvar != NULL);
6649
6650 if( !SCIPvarIsActive(transvar) )
6651 continue;
6652
6653 /* we store the complete history */
6654 SCIPhistoryReset(reopt->varhistory[reopt->run-1][idx]);
6655 SCIPhistoryUnite(reopt->varhistory[reopt->run-1][idx], transvar->history, FALSE);
6656 }
6657
6658 return SCIP_OKAY;
6659}
6660
6661/** reset the complete tree and set the given search frontier */
6663 SCIP_REOPT* reopt, /**< reoptimization data structure */
6664 SCIP_SET* set, /**< global SCIP settings */
6665 BMS_BLKMEM* blkmem, /**< block memory */
6666 SCIP_REOPTNODE** representatives, /**< array of representatives */
6667 int nrepresentatives, /**< number of representatives */
6668 SCIP_Bool* success /**< pointer to store if the method was successful */
6669 )
6670{
6671 SCIP_REOPTTREE* reopttree;
6672 unsigned int id;
6673
6674 assert(reopt != NULL);
6675 assert(set != NULL);
6676 assert(blkmem != NULL);
6677 assert(representatives != NULL);
6678 assert(nrepresentatives > 0);
6679
6680 reopttree = reopt->reopttree;
6681
6682 /* reset the current search tree */
6683 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
6684 assert(reopttree->nreoptnodes == 0);
6685
6686 /* create a new root node */
6687 id = 0;
6688 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6689
6690 /* set the reopttype */
6691 reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6692
6693 /* add all representatives */
6694 for( int r = 0; r < nrepresentatives; ++r )
6695 {
6696 /* get an empty slot*/
6697 id = SCIPqueueRemoveUInt(reopttree->openids);
6698 assert(1 <= id && id < reopttree->reoptnodessize);
6699 assert(reopttree->reoptnodes[id] == NULL);
6700
6701 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6702 assert(reopttree->reoptnodes[id] != NULL);
6703
6704 /* set the new node
6705 * 1. copy all variables, bounds, and boundtypes
6706 * 2. copy all constraints
6707 * 3. set the parent relation
6708 */
6709 if( representatives[r]->nvars > 0 )
6710 {
6711 assert(representatives[r]->nvars <= representatives[r]->varssize);
6712
6713 for( int v = 0; v < representatives[r]->nvars; ++v )
6714 {
6715 SCIP_CALL( SCIPreoptnodeAddBndchg(reopttree->reoptnodes[id], set, blkmem, representatives[r]->vars[v],
6716 representatives[r]->varbounds[v], representatives[r]->varboundtypes[v]) );
6717 }
6718 }
6719
6720 if( representatives[r]->nconss > 0 )
6721 {
6722 assert(representatives[r]->nconss <= representatives[r]->consssize);
6723
6724 for( int c = 0; c < representatives[r]->nconss; ++c )
6725 {
6726 SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], set, blkmem, representatives[r]->conss[c]->vars,
6727 representatives[r]->conss[c]->vals, representatives[r]->conss[c]->boundtypes,
6728 representatives[r]->conss[c]->lhs, representatives[r]->conss[c]->rhs,
6729 representatives[r]->conss[c]->nvars, representatives[r]->conss[c]->constype,
6730 representatives[r]->conss[c]->linear) );
6731 }
6732 }
6733
6734 reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
6735
6736 assert(reopttree->reoptnodes[id]->parentID == 0);
6737 assert(reopttree->reoptnodes[id]->nvars >= 0);
6738 assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
6739 assert(reopttree->reoptnodes[id]->nconss >= 0);
6740
6741 /* set the reopttype */
6742 if( reopttree->reoptnodes[id]->nconss == 0 )
6743 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
6744 else
6745 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
6746
6747 /* add the representative as a child of the root */
6748 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
6749 }
6750
6751 SCIPsetDebugMsg(set, "-> new tree consists of %d nodes, the root has %d child nodes.\n",
6752 reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
6753
6754 (*success) = TRUE;
6755
6756 return SCIP_OKAY;
6757}
6758
6759/** transforms a set of dual reductions into a linear constraint */
6760static
6762 SCIP_REOPT* reopt, /**< reoptimization data structure */
6763 SCIP_SET* set, /**< global SCIP settings */
6764 BMS_BLKMEM* blkmem, /**< block memory */
6765 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
6766 * pruned by the dual reductions */
6767 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
6768 )
6769{
6770 assert(reopt != NULL);
6771 assert(set != NULL);
6772 assert(blkmem != NULL);
6773 assert(consdata != NULL);
6774 assert(dualreds != NULL);
6775
6776 /* we have to transform the set of bound changes into a linear constraint */
6777 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6778 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &consdata->vals, dualreds->nvars) );
6779 consdata->boundtypes = NULL;
6780
6781 consdata->varssize = dualreds->nvars;
6782 consdata->nvars = dualreds->nvars;
6783 consdata->constype = REOPT_CONSTYPE_DUALREDS;
6784 consdata->linear = TRUE;
6785
6786 /* set lhs and rhs */
6787 consdata->lhs = 1.0;
6788 consdata->rhs = SCIPsetInfinity(set);
6789
6790 for( int v = 0; v < consdata->nvars; ++v )
6791 {
6792 assert(consdata->vars[v] != NULL);
6793
6794 /* the bound is 0.0, the variable has to appear with a coefficient +1.0 in the constraint, sides do not change */
6795 if( SCIPsetIsEQ(set, dualreds->vals[v], 0.0) )
6796 {
6797 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
6798 consdata->vals[v] = 1.0;
6799 }
6800 /* the bound is 1.0, the variable has to appear with a coefficient -1.0 in the constraint, we subtract -1.0 from lhs
6801 * logicor: sum x_i + ~y_i >= 1
6802 * <==> sum x_i + (1-y_i) >= 1
6803 * <==> sum x_i - y_i >= 0
6804 */
6805 else
6806 {
6807 assert(SCIPsetIsEQ(set, dualreds->vals[v], 1.0));
6808 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6809
6810 consdata->vals[v] = -1.0;
6811 consdata->lhs -= 1.0;
6812 }
6813 }
6814
6815 return SCIP_OKAY;
6816}
6817
6818
6819/** transforms a set of dual reductions into a bounddisjuction constraint */
6820static
6822 SCIP_REOPT* reopt, /**< reoptimization data structure */
6823 SCIP_SET* set, /**< global SCIP settings */
6824 BMS_BLKMEM* blkmem, /**< block memory */
6825 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
6826 * pruned by the dual reductions */
6827 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
6828 )
6829{
6830 assert(reopt != NULL);
6831 assert(set != NULL);
6832 assert(blkmem != NULL);
6833 assert(consdata != NULL);
6834 assert(dualreds != NULL);
6835
6836 /* we have to transform the set of bound changes into a linear constraint */
6837 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
6838 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, dualreds->vals, dualreds->nvars) );
6839 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->boundtypes, dualreds->boundtypes, dualreds->nvars) );
6840
6841 consdata->varssize = dualreds->nvars;
6842 consdata->nvars = dualreds->nvars;
6843 consdata->constype = REOPT_CONSTYPE_DUALREDS;
6844 consdata->linear = FALSE;
6845
6846 /* set lhs and rhs */
6847 consdata->lhs = SCIP_UNKNOWN;
6848 consdata->rhs = SCIP_UNKNOWN;
6849
6850 for( int v = 0; v < consdata->nvars; ++v )
6851 {
6852 SCIP_Real glbbd;
6853
6854 assert(consdata->vars[v] != NULL);
6855
6856 /* we do the followung to transformations:
6857 * (a) x <= val ==> (x >= val+1)
6858 * (b) x >= val ==> (x <= val-1)
6859 */
6860 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
6861 {
6862 glbbd = SCIPvarGetUbGlobal(consdata->vars[v]);
6863 consdata->vals[v] = MIN(consdata->vals[v]+1.0, glbbd);
6864 }
6865 else
6866 {
6867 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
6868 glbbd = SCIPvarGetLbGlobal(consdata->vars[v]);
6869 consdata->vals[v] = MAX(glbbd, consdata->vals[v]-1.0);
6870 }
6871 consdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - consdata->boundtypes[v]); /*lint !e656*/
6872 }
6873
6874 return SCIP_OKAY;
6875}
6876
6877/** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
6879 SCIP_REOPT* reopt, /**< reoptimization data structure */
6880 SCIP_TREE* tree, /**< branch and bound tree */
6881 SCIP_SET* set, /**< global SCIP settings */
6882 SCIP_STAT* stat, /**< dynamic SCIP statistics */
6883 BMS_BLKMEM* blkmem, /**< block memory */
6884 int* ncreatedchilds, /**< pointer to store the number of created nodes */
6885 int* naddedconss /**< pointer to store the number added constraints */
6886 )
6887{
6888 SCIP_REOPTTREE* reopttree;
6889 SCIP_REOPTNODE** reoptnodes;
6890 SCIP_REOPTCONSDATA* consdata;
6891 SCIP_VAR** vars;
6892 SCIP_Real* bounds;
6893 SCIP_BOUNDTYPE* boundtypes;
6894 int* perm = NULL;
6895 unsigned int id;
6896 int nbndchgs;
6897 int nchilds;
6898 int nvars = 0;
6899 int v;
6900
6901 assert(reopt != NULL);
6902 assert(set != NULL);
6903 assert(stat != NULL);
6904 assert(blkmem != NULL);
6905
6906 reopttree = reopt->reopttree;
6907 assert(reopttree != NULL);
6908
6909 reoptnodes = reopttree->reoptnodes;
6910 assert(reoptnodes != NULL);
6911 assert(reoptnodes[0] != NULL);
6912 assert(reoptnodes[0]->dualreds);
6913 assert(reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
6914
6915 nchilds = reoptnodes[0]->nchilds;
6916
6917 assert(reoptnodes[0]->dualredscur != NULL);
6918 nbndchgs = reoptnodes[0]->dualredscur->nvars;
6919
6920 (*ncreatedchilds) = 0;
6921 (*naddedconss) = 0;
6922
6923 /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
6924
6925 /* ensure that two free slots are available */
6926 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
6927 id = SCIPqueueRemoveUInt(reopttree->openids);
6928
6929 assert(0 < id && id < reopt->reopttree->reoptnodessize);
6930 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
6931
6932 /* 1. create the node
6933 * 2. add all bound changes
6934 * 3. move all child nodes to id
6935 * 4. add id as a child of the root node
6936 */
6937 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
6938 reoptnodes[id]->parentID = 0;
6939 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
6940
6941 /* check memory */
6942 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0) );
6943 assert(reoptnodes[id]->varssize >= nbndchgs);
6944 assert(reoptnodes[id]->nvars == 0);
6945 assert(reoptnodes[id]->vars != NULL);
6946 assert(reoptnodes[id]->varbounds != NULL);
6947 assert(reoptnodes[id]->varboundtypes != NULL);
6948
6949 /* create a permutation array */
6950 if( !set->reopt_usesplitcons )
6951 {
6952 assert(perm == NULL);
6953 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nbndchgs) );
6954 }
6955
6956 /* copy bounds */
6957 for( v = 0; v < nbndchgs; ++v )
6958 {
6959 reoptnodes[id]->vars[v] = reoptnodes[0]->dualredscur->vars[v];
6960 reoptnodes[id]->varbounds[v] = reoptnodes[0]->dualredscur->vals[v];
6961 reoptnodes[id]->varboundtypes[v] = reoptnodes[0]->dualredscur->boundtypes[v];
6962 ++reoptnodes[id]->nvars;
6963
6964 /* fill a permutation array */
6965 if( !set->reopt_usesplitcons )
6966 perm[v] = v; /*lint !e613*/
6967 }
6968 assert(reoptnodes[id]->nvars == reoptnodes[0]->dualredscur->nvars);
6969
6970 /* move the children */
6971 SCIP_CALL( reoptMoveIDs(reopttree, set, blkmem, 0, id) );
6972 assert(reoptnodes[0]->nchilds == 0);
6973
6974 /* add the new reoptimization node as a child of the root node */
6975 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
6976
6977 ++(*ncreatedchilds);
6978
6979 if( set->reopt_usesplitcons )
6980 {
6981 int nbinvars = 0;
6982#ifndef NDEBUG
6983 int nintvars = 0;
6984 int ncontvars = 0;
6985#endif
6986
6987 assert(*ncreatedchilds == 1);
6988
6989 /* ensure that there is a free slots */
6990 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
6991 id = SCIPqueueRemoveUInt(reopttree->openids);
6992 assert(0 < id && id < reopt->reopttree->reoptnodessize);
6993
6994 /* 1. create the node
6995 * 2. add the constraint to ensure that at least one
6996 * variable gets different
6997 * 3. add id as a child of the root node
6998 */
6999 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7000 reoptnodes[id]->parentID = 0;
7001 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
7002
7003 /* check memory for added constraints */
7004 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, 0, 0, 1) );
7005
7006 /* create the constraint */
7007 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnodes[id]->conss[0]) );
7008 consdata = reoptnodes[id]->conss[0];
7009
7010 /* count number of binary, integer, and continuous varibales */
7011 for( v = 0; v < nbndchgs; ++v )
7012 {
7013 switch( SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]) ) {
7015 ++nbinvars;
7016 break;
7019#ifndef NDEBUG
7020 ++nintvars;
7021#endif
7022 break;
7024#ifndef NDEBUG
7025 ++ncontvars;
7026#endif
7027 break;
7028 default:
7029 SCIPerrorMessage("Cannot handle vartype %d\n", SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]));
7030 return SCIP_INVALIDDATA;
7031 }
7032 }
7033
7034 /* we create a linear constraint, since all variables are binary */
7035 if( nbinvars == nbndchgs )
7036 {
7037 SCIP_CALL( transformDualredsToLinear(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7038 }
7039 /* we create a bounddisjunction constraint, since at least one variable is (implicit) integer or continuous */
7040 else
7041 {
7042 assert(nintvars > 0 || ncontvars > 0);
7043 SCIP_CALL( transformDualredsToBounddisjunction(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
7044 }
7045 ++reoptnodes[id]->nconss;
7046
7047 /* add id as a child of the root node */
7048 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7049 ++(*ncreatedchilds);
7050
7051 ++(*naddedconss);
7052 }
7053 else
7054 {
7055 assert(*ncreatedchilds == 1);
7056 assert(perm != NULL);
7057
7058 vars = reoptnodes[0]->dualredscur->vars;
7059 bounds = reoptnodes[0]->dualredscur->vals;
7060 boundtypes = reoptnodes[0]->dualredscur->boundtypes;
7061 nvars = reoptnodes[0]->dualredscur->nvars;
7062 assert(perm[0] == 0 && perm[nvars-1] == nvars-1);
7063
7064 /* calculate the order of the variables */
7065 switch (set->reopt_varorderinterdiction)
7066 {
7067 /* default order */
7068 case 'd':
7069 break;
7070
7071 /* inference order */
7072 case 'i':
7073 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7074 break;
7075
7076 /* random order */
7077 case 'r':
7078 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7079 break;
7080
7081 default:
7082 return SCIP_INVALIDDATA;
7083 }
7084
7085 /* create nvars nodes in the fashion of interdiction branching */
7086 for( int c = 0; c < nvars; ++c )
7087 {
7088 /* ensure that two free slots are available */
7089 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
7090 id = SCIPqueueRemoveUInt(reopttree->openids);
7091
7092 assert(0 < id && id < reopt->reopttree->reoptnodessize);
7093 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
7094
7095 /* 1. create the node
7096 * 2. fix the first v bound changes to vals[v] and v+1 to vals[v] +/- 1 (depending on the bound- and vartype)
7097 * 4. add the ID id as a child of the root node
7098 */
7099 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
7100 reoptnodes[id]->parentID = 0;
7101 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7102
7103 /* check memory */
7104 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, c+1, 0, 0) );
7105 assert(reoptnodes[id]->varssize >= perm[c]+1);
7106 assert(reoptnodes[id]->nvars == 0);
7107 assert(reoptnodes[id]->vars != NULL);
7108 assert(reoptnodes[id]->varbounds != NULL);
7109 assert(reoptnodes[id]->varboundtypes != NULL);
7110
7111 /* the permutation is the identity */
7112 if( set->reopt_varorderinterdiction == 'd' )
7113 {
7114 /* copy first c bound changes */
7115 for( v = 0; v < c; ++v )
7116 {
7117 reoptnodes[id]->vars[v] = vars[v];
7118 reoptnodes[id]->varbounds[v] = bounds[v];
7119 reoptnodes[id]->varboundtypes[v] = boundtypes[v];
7120 }
7121 }
7122 else
7123 {
7124 /* copy first c bound changes */
7125 for( v = 0; v < c; ++v )
7126 {
7127 reoptnodes[id]->vars[v] = vars[perm[v]];
7128 reoptnodes[id]->varbounds[v] = bounds[perm[v]];
7129 reoptnodes[id]->varboundtypes[v] = boundtypes[perm[v]];
7130 }
7131 }
7132 reoptnodes[id]->nvars += c;
7133
7134 /* set bound change v+1 (= c) to vals[v] +/- 1 (depending on the bound- and vartype) */
7135 assert(v == c);
7136 reoptnodes[id]->vars[c] = vars[perm[c]];
7137 reoptnodes[id]->varbounds[c] = bounds[perm[c]];
7138 if( SCIPvarGetType(vars[perm[c]]) != SCIP_VARTYPE_CONTINUOUS )
7139 {
7140 if( boundtypes[perm[c]] == SCIP_BOUNDTYPE_LOWER )
7141 reoptnodes[id]->varbounds[c] -= 1.0;
7142 else
7143 reoptnodes[id]->varbounds[c] += 1.0;
7144 }
7145 reoptnodes[id]->varboundtypes[c] = (boundtypes[perm[c]] == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
7146 ++reoptnodes[id]->nvars;
7147
7148 /* add dummy1 as a child of the root node */
7149 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
7150
7151 ++(*ncreatedchilds);
7152 }
7153
7154 assert(*ncreatedchilds == nvars+1);
7155
7157 perm = NULL;
7158 }
7159 assert(perm == NULL);
7160
7161 /* free the current dualredscur and assign dualredsnex */
7162 assert(reoptnodes[0]->dualredscur->vars != NULL);
7163 assert(reoptnodes[0]->dualredscur->vals != NULL);
7164 assert(reoptnodes[0]->dualredscur->boundtypes != NULL);
7165
7166 /* free the current dualredscur and assign dualredsnex */
7167 SCIP_CALL( reoptnodeUpdateDualConss(reoptnodes[0], blkmem) );
7168
7169 /* change the reopttype of the root node */
7171
7172 return SCIP_OKAY;
7173}
7174
7175/** reset the stored information abound bound changes based on dual information */
7177 SCIP_REOPT* reopt, /**< reoptimization data structure */
7178 SCIP_NODE* node, /**< node of the search tree */
7179 BMS_BLKMEM* blkmem /**< block memory */
7180 )
7181{
7182 unsigned int id;
7183
7184 assert(reopt != NULL);
7185 assert(node != NULL);
7186
7187 id = SCIPnodeGetReoptID(node);
7188 assert(id < reopt->reopttree->reoptnodessize);
7189
7190 /* return if the node is not part of the reoptimization tree */
7191 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7192 return SCIP_OKAY;
7193
7194 /* reset the dual constraint */
7195 SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
7196
7197 return SCIP_OKAY;
7198}
7199
7200/** return the branching path stored of the given node in the reoptimization tree */
7202 SCIP_REOPT* reopt, /**< reoptimization data structure */
7203 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
7204 SCIP_VAR** vars, /**< array for variables */
7205 SCIP_Real* vals, /**< array for values */
7206 SCIP_BOUNDTYPE* boundtypes, /**< array for bound types */
7207 int varssize, /**< size of arrays vars, vals, and boundtypes */
7208 int* nbndchgs, /**< pointer to store the number of bound changes */
7209 int* nbndchgsafterdual /**< pointer to store the number of bound changes applied after
7210 * the first dual reduction at the given node */
7211 )
7212{
7213 int v;
7214 int nvars2;
7215 int nafterdualvars2;
7216
7217 assert(reopt != NULL);
7218 assert(reoptnode != NULL);
7219 assert(vars != NULL);
7220 assert(vals != NULL);
7221 assert(boundtypes != NULL);
7222
7223 (*nbndchgs) = reoptnode->nvars;
7224 (*nbndchgsafterdual) = reoptnode->nafterdualvars;
7225
7226 /* return if the size of the given array is not large enough */
7227 if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
7228 return;
7229
7230 /* add all bound changes made by branching (including dual reductions) */
7231 for( v = 0; v < *nbndchgs; ++v )
7232 {
7233 vars[v] = reoptnode->vars[v];
7234 vals[v] = reoptnode->varbounds[v];
7235 boundtypes[v] = reoptnode->varboundtypes[v];
7236 }
7237
7238 /* add all bound changes made applied after a dual reduction */
7239 for( ; v < *nbndchgs + *nbndchgsafterdual; ++v )
7240 {
7241 vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
7242 vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
7243 boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
7244 }
7245
7246 /* go along the root path within the reoptimization tree */
7247 if( reoptnode->parentID != 0 )
7248 {
7249 SCIP_REOPTNODE* parent;
7250
7251 parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
7252 SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
7253
7254 (*nbndchgs) += nvars2;
7255 (*nbndchgsafterdual) += nafterdualvars2;
7256 }
7257}
7258
7259/** delete a node stored in the reoptimization tree */
7261 SCIP_REOPT* reopt, /**< reoptimization data structure */
7262 SCIP_SET* set, /**< global SCIP settings */
7263 unsigned int id, /**< id of a stored node */
7264 BMS_BLKMEM* blkmem /**< block memory */
7265 )
7266{
7267 assert(reopt != NULL);
7268 assert(reopt->reopttree != NULL);
7269 assert(id < reopt->reopttree->reoptnodessize);
7270 assert(reopt->reopttree->reoptnodes[id] != NULL);
7271 assert(blkmem != NULL);
7272
7273 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
7275
7276 return SCIP_OKAY;
7277}
7278
7279/** reactivate the given @p reoptnode and split them into several nodes if necessary */
7281 SCIP_REOPT* reopt, /**< reoptimization data structure */
7282 SCIP* scip, /**< SCIP data structure */
7283 SCIP_SET* set, /**< global SCIP settings */
7284 SCIP_STAT* stat, /**< dynamic problem statistics */
7285 SCIP_PROB* transprob, /**< transformed problem */
7286 SCIP_PROB* origprob, /**< original problem */
7287 SCIP_TREE* tree, /**< branching tree */
7288 SCIP_LP* lp, /**< current LP */
7289 SCIP_BRANCHCAND* branchcand, /**< branching candidate */
7290 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7291 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
7292 BMS_BLKMEM* blkmem, /**< block memory */
7293 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree to reactivate */
7294 unsigned int id, /**< id of the node to reactivate */
7295 SCIP_Real estimate, /**< estimate of the child nodes that should be created */
7296 SCIP_NODE** childnodes, /**< array to store the created child nodes */
7297 int* ncreatedchilds, /**< pointer to store number of created child nodes */
7298 int* naddedconss, /**< pointer to store number of generated constraints */
7299 int childnodessize, /**< available size of childnodes array */
7300 SCIP_Bool* success /**< pointer store the result */
7301 )
7302{
7303 assert(reopt != NULL);
7304 assert(scip != NULL);
7305 assert(set != NULL);
7306 assert(stat != NULL);
7307 assert(transprob != NULL);
7308 assert(origprob != NULL);
7309 assert(tree != NULL);
7310 assert(lp != NULL);
7311 assert(branchcand != NULL);
7312 assert(eventqueue != NULL);
7313 assert(cliquetable != NULL);
7314 assert(blkmem != NULL);
7315 assert(reoptnode != NULL);
7316 assert(childnodes != NULL);
7317 assert(reopt->reopttree != NULL);
7318 assert(id < reopt->reopttree->reoptnodessize);
7319 assert(success != NULL);
7320
7321 SCIPsetDebugMsg(set, "reactivating node at id %u:\n", id);
7322
7323 *success = FALSE;
7324
7325 /* check if we need to split the node */
7326 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
7327 || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7328 {
7329 assert(reoptnode->dualreds);
7330
7331 /* we want use a constraint to split the node into two disjoint node */
7332 if( set->reopt_usesplitcons )
7333 {
7334 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
7335 {
7336 assert(reoptnode->dualredscur != NULL);
7337 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
7338 (*ncreatedchilds) = 1;
7339 }
7340 else
7341 {
7342 assert(reoptnode->dualredscur != NULL);
7343 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7344 (*ncreatedchilds) = 2;
7345 }
7346
7347 /* in both cases we add exactly one constraint */
7348 (*naddedconss) = 1;
7349
7350 if( childnodessize < *ncreatedchilds )
7351 return SCIP_OKAY;
7352
7353 /* generate the nodes */
7354 for( int c = 0; c < *ncreatedchilds; ++c )
7355 {
7356 /* create the child node */
7357 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7358
7359 /* change all bounds; convert the bound changes after the first based on dual reductions into branching
7360 * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
7361 * changes anyway.
7362 */
7363 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7364 cliquetable, blkmem, childnodes[c], id, c == 1) );
7365
7366 /* add all local constraints */
7367 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7368
7369 /* we can use the old lowerbound if the objective function has not changed */
7370 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7371 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7372
7373 if( c == 0 )
7374 {
7375 /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
7377
7378 /* add the constraint to the node */
7379 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7380 SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
7381 eventqueue, cliquetable, childnodes[c], id) );
7382
7383 /* fixBounds() does the same, but in this case we go not into it */
7384 if( reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE )
7385 {
7386 assert(reoptnode->dualredscur->nvars > 0);
7387 assert(reoptnode->dualredscur->varssize > 0);
7388
7389 /* delete dualredscur and move dualredsnex -> dualredscur */
7390 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
7391 }
7392
7393 /* the added constraint could be deleted due to propagation, thus, we store the node in the reoptimization
7394 * tree. the node has to stored anyway, because of the constraint representing the dual reductions
7395 */
7396 SCIP_CALL( addNode(reopt, set, lp, blkmem, childnodes[c], SCIP_REOPTTYPE_LOGICORNODE, FALSE, FALSE,
7397 -SCIPsetInfinity(set)) );
7398 }
7399 else
7400 {
7401 /* if we reach this lines of code, the current node represents the original node including all bound
7402 * changes based in dual information.
7403 */
7404 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
7405 if( reoptnode->nconss == 0 )
7407 else
7409
7410 /* fix all bound changes based on dual information and convert them into branchings */
7411 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
7412 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7413 blkmem, childnodes[c], id, TRUE) );
7414
7415 /* set the unique id the id of the original node */
7416 SCIPnodeSetReoptID(childnodes[c], id);
7417 }
7418 }
7419
7420 /* reset the stored dual constraints */
7422
7423 /* set the reoptimization type */
7424 if( reopt->reopttree->reoptnodes[id]->dualreds )
7425 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7426 else
7427 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7428
7429 *success = TRUE;
7430 }
7431 else
7432 {
7433 SCIP_VAR** vars;
7434 SCIP_Real* bounds;
7435 SCIP_BOUNDTYPE* boundtypes;
7436 int* perm = NULL;
7437 int nvars;
7438
7439 vars = reoptnode->dualredscur->vars;
7440 bounds = reoptnode->dualredscur->vals;
7441 boundtypes = reoptnode->dualredscur->boundtypes;
7442 nvars = reoptnode->dualredscur->nvars;
7443
7444 *ncreatedchilds = nvars+1;
7445 *naddedconss = 0;
7446
7447 /* check if there is enough memory allocated */
7448 if( childnodessize < *ncreatedchilds )
7449 return SCIP_OKAY;
7450
7451 /* create and fill permutation array */
7452 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nvars) );
7453 for( int c = 0; c < nvars; ++c )
7454 perm[c] = c;
7455
7456 /* calculate the order of the variables */
7457 switch (set->reopt_varorderinterdiction)
7458 {
7459 /* default order */
7460 case 'd':
7461 break;
7462
7463 /* inference order */
7464 case 'i':
7465 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
7466 break;
7467
7468 /* random order */
7469 case 'r':
7470 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
7471 break;
7472
7473 default:
7474 return SCIP_INVALIDDATA;
7475 }
7476
7477 assert(reopt->reopttree->reoptnodes[id] != NULL);
7478 reoptnode = reopt->reopttree->reoptnodes[id];
7479
7480 /* enough that the node need to split */
7481 assert(reoptnode->dualreds);
7482
7483 /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
7484 * we need to do this in the reverse order because we want to transform the bound changes based on dual information
7485 * into branching decisions at nodes[0].
7486 */
7487 for( int c = nvars; c >= 0; --c )
7488 {
7489 /* create the child node */
7490 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
7491
7492#ifdef SCIP_MORE_DEBUG
7493 SCIPsetDebugMsg(set, " change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
7494#endif
7495
7496 /* change all bounds */
7497 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7498 cliquetable, blkmem, childnodes[c], id, FALSE) );
7499
7500 /* reconstruct the original node and the pruned part, respectively */
7501 if( c == 0 )
7502 {
7503 /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
7504 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7505 blkmem, childnodes[c], id, TRUE) );
7506
7507 /* set the reopttype of the node */
7509
7510 /* set the unique id */
7511 SCIPnodeSetReoptID(childnodes[c], id);
7512 }
7513 else
7514 {
7515 /* fix the first c bound changes and negate the (c+1)th */
7516 SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cliquetable,
7517 blkmem, childnodes[c], id, perm, vars, bounds, boundtypes, nvars, c) );
7518 }
7519
7520 /* add all local constraints */
7521 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
7522
7523 /* we can use the old lowerbound if the objective function has not changed */
7524 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7525 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7526 }
7527
7528 /* free buffer array */
7530
7531 /* reset the stored dual constraints */
7533
7534 /* set the reoptimization type to transit */
7535 if( reopt->reopttree->reoptnodes[id]->dualreds )
7536 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
7537 else
7538 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
7539
7540 *success = TRUE;
7541 }
7542 }
7543 else
7544 {
7545 /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
7546 (*ncreatedchilds) = 1;
7547 (*naddedconss) = 0;
7548
7549 if( childnodessize < *ncreatedchilds )
7550 return SCIP_OKAY;
7551
7552 /* create the child node */
7553 SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
7554
7555 /* change all bounds */
7556 assert(reoptnode->nafterdualvars == 0);
7557 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
7558 cliquetable, blkmem, childnodes[0], id, FALSE) );
7559
7560 /* add all local constraints */
7561 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
7562
7563 /* we can use the old lowerbound if the objective function has not changed */
7564 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
7565 SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
7566
7567 /* set the reopttype */
7568 assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
7569 && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
7570 SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
7571
7572 /* set the unique id */
7573 SCIPnodeSetReoptID(childnodes[0], id);
7574
7575 *success = TRUE;
7576 }
7577
7578 return SCIP_OKAY;
7579}
7580
7581/** returns the time needed to store the nodes for reoptimization */
7583 SCIP_REOPT* reopt /**< reoptimization data structure */
7584 )
7585{
7586 assert(reopt != NULL);
7587
7588 return SCIPclockGetTime(reopt->savingtime);
7589}
7590
7591/** add the stored constraints globally to the problem */
7593 SCIP* scip, /**< SCIP data structure */
7594 SCIP_REOPT* reopt, /**< reoptimization data structure */
7595 SCIP_SET* set, /**< global SCIP settings */
7596 SCIP_STAT* stat, /**< dynamic problem statistics */
7597 BMS_BLKMEM* blkmem /**< block memory */
7598 )
7599{
7600 char name[SCIP_MAXSTRLEN];
7601
7602 assert(scip != NULL);
7603 assert(reopt != NULL);
7604 assert(set != NULL);
7605 assert(stat != NULL);
7606 assert(blkmem != NULL);
7607
7608 if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
7609 return SCIP_OKAY;
7610
7611 for( int c = reopt->nglbconss-1; c >= 0; --c )
7612 {
7613 SCIP_CONS* cons;
7614 SCIP_VAR** consvars;
7615 int nbinvars;
7616 int nintvars;
7617
7618 assert(reopt->glbconss[c] != NULL);
7619 assert(reopt->glbconss[c]->nvars > 0);
7620
7621 cons = NULL;
7622 consvars = NULL;
7623 nbinvars = 0;
7624 nintvars = 0;
7625
7626 /* check if we can use a logic-or or if we have to use a bounddisjuction constraint */
7627 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
7628 {
7629 if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_BINARY )
7630 ++nbinvars;
7631 else if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_INTEGER
7632 || SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_IMPLINT )
7633 ++nintvars;
7634 else
7635 {
7636 SCIPerrorMessage("Expected variable type binary or (impl.) integer for variable <%s> in global constraint at pos. %d.\n",
7637 SCIPvarGetName(reopt->glbconss[c]->vars[v]), c);
7638 return SCIP_INVALIDDATA;
7639 }
7640 }
7641
7642 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "glb_%s_%d_%d", reopt->glbconss[c]->constype == REOPT_CONSTYPE_CUT ? "cut" : "inf", reopt->run, c);
7643
7644 /* @todo use active representatives */
7645
7646 /* all variables are binary, we can create a logic-or constraint */
7647 if( nbinvars == reopt->glbconss[c]->nvars )
7648 {
7649 SCIPsetDebugMsg(set, "-> add logic-or constraints with %d binvars\n", nbinvars);
7650
7651 /* allocate buffer */
7652 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
7653
7654 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
7655 {
7656 consvars[v] = reopt->glbconss[c]->vars[v];
7657 assert(SCIPvarIsOriginal(consvars[v]));
7658
7659 /* negate the variable if it was fixed to 1 */
7660 if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 0.0) )
7661 {
7662 assert(reopt->glbconss[c]->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
7663 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
7664 }
7665 }
7666
7667 /* create the logic-or constraint */
7668 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->glbconss[c]->nvars,
7669 consvars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7670
7671 /* free buffer */
7672 SCIPfreeBufferArray(scip, &consvars);
7673 }
7674 /* not all variables are binary, we need a bounddisjunction constraint */
7675 else
7676 {
7677 assert(reopt->glbconss[c]->nvars == nbinvars + 2*nintvars);
7678
7679 SCIPsetDebugMsg(set, "-> add bounddisjuction constraints with %d binvars, %d intvars\n", nbinvars, (int) (2*nintvars));
7680
7681 /* create the bounddisjuction constraint */
7682 SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, name, reopt->glbconss[c]->nvars, reopt->glbconss[c]->vars,
7683 reopt->glbconss[c]->boundtypes, reopt->glbconss[c]->vals) );
7684 }
7685
7686#ifdef SCIP_DEBUG_CONSS
7688#endif
7689
7690 SCIP_CALL( SCIPaddCons(scip, cons) );
7691
7692 /* remember the constraint for re-activation */
7693 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)cons));
7694 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)cons) );
7695 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, reopt->nactiveconss + 1) );
7696 assert(reopt->nactiveconss < reopt->nmaxactiveconss);
7697 reopt->activeconss[reopt->nactiveconss++] = cons;
7698
7699 /* don't release the constraint because we would need to capture the constraint anyway */
7700
7701 /* mark the constraint as empty */
7702 reopt->glbconss[c]->nvars = 0;
7703 }
7704
7705 SCIPsetDebugMsg(set, "added %d gobal constraints\n", reopt->nglbconss);
7706
7707 /* reset number of global constraints */
7708 reopt->nglbconss = 0;
7709
7710 return SCIP_OKAY;
7711}
7712
7713/** add the stored cuts to the separation storage */
7715 SCIP_REOPT* reopt, /**< reoptimization data structure */
7716 SCIP_NODE* node, /**< current focus node */
7717 SCIP_SEPASTORE* sepastore, /**< separation storage */
7718 SCIP_CUTPOOL* cutpool, /**< global cutpool */
7719 BMS_BLKMEM* blkmem, /**< block memory */
7720 SCIP_SET* set, /**< global SCIP settings */
7721 SCIP_STAT* stat, /**< dynamic problem statistics */
7722 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7723 SCIP_EVENTFILTER* eventfilter, /**< event filter */
7724 SCIP_LP* lp, /**< current LP */
7725 SCIP_Bool root /**< bool whether the current node is the root */
7726 )
7727{
7728 SCIP_REOPTNODE* reoptnode;
7729 SCIP_Bool infeasible;
7730 unsigned int id;
7731 int ncuts;
7732
7733 assert(reopt != NULL);
7734 assert(node != NULL);
7735 assert(sepastore != NULL);
7736 assert(blkmem != NULL);
7737 assert(set != NULL);
7738 assert(stat != NULL);
7739 assert(eventqueue != NULL);
7740 assert(eventfilter != NULL);
7741 assert(lp != NULL);
7742
7743 id = SCIPnodeGetReoptID(node);
7744 assert(id < reopt->reopttree->reoptnodessize);
7745
7746 /* skip nodes that are node part of the reoptimization tree */
7747 if( id == 0 && SCIPnodeGetDepth(node) > 0 )
7748 return SCIP_OKAY;
7749
7750 reoptnode = reopt->reopttree->reoptnodes[id];
7751 assert(reoptnode != NULL);
7752
7753 ncuts = 0;
7754 for( int c = reoptnode->nconss-1; c >= 0; --c )
7755 {
7756 SCIP_REOPTCONSDATA* cons;
7757
7758 cons = reoptnode->conss[c];
7759 assert(cons != NULL);
7760
7761 if( cons->constype == REOPT_CONSTYPE_CUT )
7762 {
7763 SCIP_ROW* cut;
7764 SCIP_COL** cols;
7765 SCIP_Real* vals;
7766 char cutname[SCIP_MAXSTRLEN];
7767 int ncols;
7768
7769 SCIP_CALL( SCIPsetAllocBufferArray(set, &cols, cons->nvars) );
7770 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, cons->nvars) );
7771
7772 ncols = 0;
7773 for( int v = 0; v < cons->nvars; ++v )
7774 {
7775 SCIP_VAR* transvar;
7776
7777 assert(SCIPvarIsOriginal(cons->vars[v]));
7778
7779 transvar = SCIPvarGetTransVar(cons->vars[v]);
7780 assert(transvar != NULL);
7781 assert(SCIPvarGetStatus(transvar) == SCIP_VARSTATUS_COLUMN);
7782
7783 vals[ncols] = cons->vals[v];
7784 cols[ncols] = SCIPvarGetCol(transvar);
7785 assert(cols[ncols] != NULL);
7786
7787 ++ncols;
7788 }
7789 assert(ncols == cons->nvars);
7790
7791 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "reoptcut_%d_%d", id, ncuts);
7792 infeasible = FALSE;
7793
7794 if( id == 0 )
7795 {
7796 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7798 SCIP_CALL( SCIPcutpoolAddRow(cutpool, blkmem, set, stat, lp, cut) );
7799
7800 SCIPsetDebugMsg(set, "add cut <%s> of size %d to cutpool, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7801 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7802 }
7803 else
7804 {
7805 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
7807 SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, FALSE, root,
7808 &infeasible) );
7809
7810 SCIPsetDebugMsg(set, "add cut <%s> of size %d to sepastore, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
7811 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
7812 }
7813
7814 SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
7815
7816 if( infeasible )
7817 SCIPsetDebugMsg(set, "cut %d stored at node %" SCIP_LONGINT_FORMAT " (id: %u) is infeasible.\n", c, SCIPnodeGetNumber(node), id);
7818 else
7819 ++ncuts;
7820
7823
7824 BMSfreeBlockMemoryArrayNull(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
7825 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
7826 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
7827 BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866*/
7828 --reoptnode->nconss;
7829 }
7830 else
7831 {
7832#ifndef NDEBUG
7833 for( int i = c-1; i >= 0; --i )
7834 assert(reoptnode->conss[i]->constype != REOPT_CONSTYPE_CUT);
7835#endif
7836 break;
7837 }
7838 }
7839
7840 return SCIP_OKAY;
7841}
7842
7843/** check if the LP of the given node should be solved or not */
7845 SCIP_REOPT* reopt, /**< reoptimization data structure */
7846 SCIP_SET* set, /**< global SCIP settings */
7847 SCIP_NODE* node /**< node of the current search tree */
7848 )
7849{
7850 unsigned int id;
7851
7852 assert(reopt != NULL);
7853 assert(node != NULL);
7854
7855 /* get the ID */
7856 id = SCIPnodeGetReoptID(node);
7857 assert(id < reopt->reopttree->reoptnodessize);
7858
7859 /* return if the node is not part of the reoptimization tree */
7860 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
7861 return TRUE;
7862
7863 /* return always true if the parameter is set to 1.0 */
7864 if( SCIPsetIsGE(set, set->reopt_objsimrootlp, 1.0) )
7865 return TRUE;
7866
7867 /* current node is the root */
7868 if( id == 0 )
7869 {
7870 if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
7871 {
7872 /* the objective function has changed only slightly */
7873 if( SCIPsetIsGE(set, reopt->simtolastobj, set->reopt_objsimrootlp) )
7874 return FALSE;
7875 }
7876 }
7877 else
7878 {
7879 /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
7880 if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
7881 {
7882 assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
7883 return FALSE;
7884 }
7885 }
7886
7887 return TRUE;
7888}
7889
7890/** initialize an empty node */
7892 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
7893 SCIP_SET* set /**< global SCIP settings */
7894 )
7895{
7896 assert(reoptnode != NULL);
7897 assert(set != NULL);
7898
7899 reoptnode->conss = NULL;
7900 reoptnode->nconss = 0;
7901 reoptnode->consssize = 0;
7902 reoptnode->childids = NULL;
7903 reoptnode->allocchildmem = 0;
7904 reoptnode->nchilds = 0;
7905 reoptnode->nvars = 0;
7906 reoptnode->nafterdualvars = 0;
7907 reoptnode->parentID = 0;
7908 reoptnode->dualreds = FALSE;
7909 reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
7910 reoptnode->varssize = 0;
7911 reoptnode->afterdualvarssize = 0;
7912 reoptnode->vars = NULL;
7913 reoptnode->varbounds = NULL;
7914 reoptnode->varboundtypes = NULL;
7915 reoptnode->afterdualvars = NULL;
7916 reoptnode->afterdualvarbounds = NULL;
7917 reoptnode->afterdualvarboundtypes = NULL;
7918 reoptnode->dualredscur = NULL;
7919 reoptnode->dualredsnex = NULL;
7920 reoptnode->lowerbound = -SCIPsetInfinity(set);
7921}
7922
7923/** reset the given reoptimization node */
7925 SCIP_REOPT* reopt, /**< reoptimization data structure */
7926 SCIP_SET* set, /**< global SCIP settings */
7927 BMS_BLKMEM* blkmem, /**< block memory */
7928 SCIP_REOPTNODE* reoptnode /**< reoptimization node */
7929 )
7930{
7931 assert(reopt != NULL);
7932 assert(set != NULL);
7933 assert(blkmem != NULL);
7934 assert(reoptnode != NULL);
7935
7936 SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
7937
7938 return SCIP_OKAY;
7939}
7940
7941/** delete the given reoptimization node */
7943 SCIP_REOPTNODE** reoptnode, /**< pointer of reoptnode */
7944 BMS_BLKMEM* blkmem /**< block memory */
7945 )
7946{
7947 assert(reoptnode != NULL);
7948 assert(blkmem != NULL);
7949
7950 SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
7951
7952 return SCIP_OKAY;
7953}
7954
7955/** add a variable to a given reoptnode */
7957 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
7958 SCIP_SET* set, /**< global SCIP settings */
7959 BMS_BLKMEM* blkmem, /**< block memory */
7960 SCIP_VAR* var, /**< variable to add */
7961 SCIP_Real val, /**< value of the variable */
7962 SCIP_BOUNDTYPE boundtype /**< boundtype of the variable */
7963 )
7964{
7965 int nvars;
7966
7967 assert(reoptnode != NULL);
7968 assert(var != NULL);
7969 assert(blkmem != NULL);
7970
7971 nvars = reoptnode->nvars;
7972
7973 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, nvars + 1, 0, 0) );
7974
7975 reoptnode->vars[nvars] = var;
7976 reoptnode->varbounds[nvars] = val;
7977 reoptnode->varboundtypes[nvars] = boundtype;
7978 ++reoptnode->nvars;
7979
7980 return SCIP_OKAY;
7981}
7982
7983/** add a constraint to a given reoptnode */
7985 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
7986 SCIP_SET* set, /**< global SCIP settings */
7987 BMS_BLKMEM* blkmem, /**< block memory */
7988 SCIP_VAR** vars, /**< variables which are part of the constraint */
7989 SCIP_Real* bounds, /**< bounds of the variables */
7990 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes of the variables (or NULL is the constraint is a cut) */
7991 SCIP_Real lhs, /**< lhs of the constraint */
7992 SCIP_Real rhs, /**< rhs of the constraint */
7993 int nvars, /**< number of variables */
7994 REOPT_CONSTYPE constype, /**< type of the constraint */
7995 SCIP_Bool linear /**< the given constraint has a linear representation */
7996 )
7997{
7998 int nconss;
7999
8000 assert(reoptnode != NULL);
8001 assert(set != NULL);
8002 assert(vars != NULL);
8003 assert(bounds != NULL);
8004 assert(constype == REOPT_CONSTYPE_CUT || boundtypes != NULL);
8005 assert(nvars > 0);
8006 assert(blkmem != NULL);
8007
8008 /* the constraint can be interpreted as a normal bound change */
8009 if( nvars == 1 && constype != REOPT_CONSTYPE_CUT )
8010 {
8011 assert(constype == REOPT_CONSTYPE_DUALREDS || constype == REOPT_CONSTYPE_INFSUBTREE);
8012
8013 SCIPsetDebugMsg(set, "-> constraint has size 1 -> save as normal bound change.\n");
8014
8015 if( SCIPvarGetType(vars[0]) == SCIP_VARTYPE_BINARY )
8016 {
8017 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], 1-bounds[0],
8018 1-bounds[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
8019 }
8020 else
8021 {
8022 SCIP_Real newbound;
8023 SCIP_BOUNDTYPE newboundtype;
8024
8025 assert(SCIPvarGetType(vars[0]) == SCIP_VARTYPE_INTEGER);
8026 assert(boundtypes != NULL);
8027
8028 if( boundtypes[0] == SCIP_BOUNDTYPE_UPPER )
8029 {
8030 newbound = bounds[0] + 1.0;
8031 assert(SCIPsetIsLE(set, newbound, SCIPvarGetUbLocal(vars[0])));
8032
8033 newboundtype = SCIP_BOUNDTYPE_LOWER;
8034 }
8035 else
8036 {
8037 newbound = bounds[0] - 1.0;
8038 assert(SCIPsetIsGE(set, newbound, SCIPvarGetLbLocal(vars[0])));
8039
8040 newboundtype = SCIP_BOUNDTYPE_UPPER;
8041 }
8042
8043 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], newbound, newboundtype) );
8044 }
8045 }
8046 else
8047 {
8048 nconss = reoptnode->nconss;
8049
8050 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, 0, 0, nconss+1) );
8051
8052 /* create the constraint */
8053 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
8054 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, vars, nvars) );
8055 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, bounds, nvars) );
8056 if( boundtypes != NULL )
8057 {
8058 assert(!linear);
8059 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->boundtypes, boundtypes, nvars) );
8060 }
8061 else
8062 reoptnode->conss[nconss]->boundtypes = NULL;
8063
8064 reoptnode->conss[nconss]->varssize = nvars;
8065 reoptnode->conss[nconss]->nvars = nvars;
8066 reoptnode->conss[nconss]->lhs = lhs;
8067 reoptnode->conss[nconss]->rhs = rhs;
8068 reoptnode->conss[nconss]->constype = constype;
8069 reoptnode->conss[nconss]->linear = linear;
8070 ++reoptnode->nconss;
8071 }
8072 return SCIP_OKAY;
8073}
8074
8075/** add a constraint to the reoptimization data structure */
8077 SCIP_REOPT* reopt, /**< reoptimization data structure */
8078 SCIP_SET* set, /**< global SCIP settings */
8079 BMS_BLKMEM* blkmem, /**< block memory */
8080 SCIP_CONS* cons /**< constraint to add */
8081 )
8082{
8083 assert(reopt != NULL);
8084 assert(set != NULL);
8085 assert(blkmem != NULL);
8086 assert(cons != NULL);
8087
8088#ifdef SCIP_MORE_DEBUG
8089 SCIPsetDebugMsg(set, "add cons <%s> to reoptimization data\n", SCIPconsGetName(cons));
8090#endif
8091
8092 /* check memory */
8093 if( reopt->addedconsssize == 0 )
8094 {
8095 assert(reopt->addedconss == NULL);
8096
8097 reopt->addedconsssize = 10;
8099 }
8100 else if( reopt->naddedconss == reopt->addedconsssize )
8101 {
8102 int newsize = SCIPsetCalcMemGrowSize(set, reopt->addedconsssize+1);
8103 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize, newsize) );
8104
8105 /* clear the array */
8106 BMSclearMemoryArray(&reopt->addedconss[reopt->addedconsssize], newsize - reopt->addedconsssize); /*lint !e866 */
8107
8108 reopt->addedconsssize = newsize;
8109 }
8110 assert(reopt->naddedconss < reopt->addedconsssize);
8111 assert(reopt->addedconss[reopt->naddedconss] == NULL);
8112
8113 reopt->addedconss[reopt->naddedconss] = cons;
8114 reopt->consadded = TRUE;
8115 ++reopt->naddedconss;
8116
8117 /* capture the constraint */
8118 SCIPconsCapture(cons);
8119
8120 return SCIP_OKAY;
8121}
8122
8123/** save global lower and upper bounds
8124 *
8125 * @note this method should only be called once, i.e., after fishing presolving of the first problem
8126 */
8128 SCIP_REOPT* reopt, /**< reoptimization data structure */
8129 SCIP_PROB* transprob, /**< transformed problem data */
8130 BMS_BLKMEM* blkmem /**< block memory */
8131 )
8132{
8133 SCIP_VAR** vars;
8134 int nvars;
8135
8136 assert(reopt != NULL);
8137 assert(transprob != NULL);
8138 assert(reopt->glblb == NULL && reopt->glbub == NULL);
8139
8140 nvars = SCIPprobGetNVars(transprob);
8141 vars = SCIPprobGetVars(transprob);
8142
8143 /* create hashmaps */
8144 SCIP_CALL( SCIPhashmapCreate(&reopt->glbub, blkmem, nvars) );
8145 SCIP_CALL( SCIPhashmapCreate(&reopt->glblb, blkmem, nvars) );
8146
8147 /* store the global bounds */
8148 for( int i = 0; i < nvars; ++i )
8149 {
8150 if( SCIPvarIsRelaxationOnly(vars[i]) )
8151 continue;
8152
8153 assert(!SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8154 assert(!SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8155
8156 SCIP_CALL( SCIPhashmapInsertReal(reopt->glblb, (void*)vars[i], SCIPvarGetLbGlobal(vars[i])) );
8157 SCIP_CALL( SCIPhashmapInsertReal(reopt->glbub, (void*)vars[i], SCIPvarGetUbGlobal(vars[i])) );
8158 }
8159
8160 return SCIP_OKAY;
8161}
8162
8163/** save active constraints
8164 *
8165 * @note this method can only called once, i.e., after fishing presolving of the first problem
8166 */
8168 SCIP_REOPT* reopt, /**< reoptimization data structure */
8169 SCIP_SET* set, /**< global SCIP settings */
8170 SCIP_PROB* transprob, /**< transformed problem data */
8171 BMS_BLKMEM* blkmem /**< block memory */
8172 )
8173{
8174 SCIP_CONS** conss;
8175 int nconss;
8176
8177 assert(reopt != NULL);
8178 assert(transprob != NULL);
8179 assert(reopt->activeconss == NULL);
8180 assert(reopt->activeconssset == NULL);
8181 assert(reopt->nactiveconss == 0);
8182 assert(reopt->nmaxactiveconss == 0);
8183
8184 conss = SCIPprobGetConss(transprob);
8185 nconss = SCIPprobGetNConss(transprob);
8186
8187 SCIPsetDebugMsg(set, "save %d active conss\n", nconss);
8188
8189 /* create hashset and array */
8190 SCIP_CALL( SCIPhashsetCreate(&reopt->activeconssset, blkmem, nconss) );
8191 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, nconss) );
8192
8193 for( int i = 0; i < nconss; ++i )
8194 {
8195 assert(SCIPconsIsActive(conss[i]));
8196 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)conss[i]));
8197
8198 SCIPconsCapture(conss[i]);
8199 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)conss[i]) );
8200 reopt->activeconss[reopt->nactiveconss++] = conss[i];
8201 }
8202
8203 return SCIP_OKAY;
8204}
8205
8206/** installs global lower and upper bounds */
8208 SCIP_REOPT* reopt, /**< reoptimization data structure */
8209 SCIP_SET* set, /**< global SCIP settings */
8210 SCIP_STAT* stat, /**< dynamic SCIP statistics */
8211 SCIP_PROB* transprob, /**< transformed problem data */
8212 SCIP_LP* lp, /**< current LP data */
8213 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8214 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8215 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8216 BMS_BLKMEM* blkmem /**< block memory */
8217 )
8218{
8219 SCIP_VAR** vars;
8220 int nvars;
8221
8222 assert(reopt != NULL);
8223 assert(transprob != NULL);
8224 assert(reopt->glblb != NULL && reopt->glbub != NULL);
8225 assert(SCIPprobIsTransformed(transprob));
8226
8227 nvars = SCIPprobGetNVars(transprob);
8228 vars = SCIPprobGetVars(transprob);
8229
8230 /* install global lower and upper bounds */
8231 for( int i = 0; i < nvars; ++i )
8232 {
8233 SCIP_Real lb;
8234 SCIP_Real ub;
8235
8236 if( SCIPvarIsRelaxationOnly(vars[i]) )
8237 continue;
8238
8239 assert(SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
8240 assert(SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
8241
8242 lb = SCIPhashmapGetImageReal(reopt->glblb, (void*)vars[i]);
8243 ub = SCIPhashmapGetImageReal(reopt->glbub, (void*)vars[i]);
8244 assert(lb < SCIP_INVALID && ub < SCIP_INVALID);
8245
8246 /* reset the global bounds back */
8247 SCIP_CALL( SCIPvarChgLbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, lb) );
8248 SCIP_CALL( SCIPvarChgUbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, ub) );
8249
8250 /* reset the local bounds back */
8251 SCIP_CALL( SCIPvarChgLbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, lb) );
8252 SCIP_CALL( SCIPvarChgUbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, ub) );
8253 }
8254
8255 return SCIP_OKAY;
8256}
8257
8258/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
8260 SCIP_REOPT* reopt, /**< reoptimization data structure */
8261 SCIP_SET* set, /**< global SCIP settings */
8262 SCIP_STAT* stat /**< dynamic SCIP statistics */
8263 )
8264{
8265 assert(reopt != NULL);
8266 assert(reopt->activeconss != NULL || reopt->nmaxactiveconss == 0);
8267 assert(reopt->activeconssset != NULL || reopt->nmaxactiveconss == 0);
8268 assert(reopt->nmaxactiveconss >= 0);
8269
8270 SCIPsetDebugMsg(set, "Reset %d active conss.\n", reopt->nactiveconss);
8271
8272 /* loop over all storeed active constraints and reactivate deactivated constraints */
8273 for( int i = 0; i < reopt->nactiveconss; ++i )
8274 {
8275 SCIP_CONS* cons;
8276
8277 assert(reopt->activeconss != NULL);
8278 cons = reopt->activeconss[i];
8279 assert(cons != NULL);
8280 assert(SCIPhashsetExists(reopt->activeconssset, cons));
8281
8282 /* it can happen that the constraint got globally deleted */
8283 if( SCIPconsIsDeleted(cons) )
8284 cons->deleted = FALSE;
8285
8286 /* to ensure that the constraint will be added to all the data structures we need to deactivate the
8287 * constraint first.
8288 */
8289 if( SCIPconsIsActive(cons) )
8290 {
8291 SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
8292 }
8293 SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, TRUE) );
8294 }
8295
8296 return SCIP_OKAY;
8297}
8298
8299/** returns whether a constraint is necessary to ensure correctness and cannot be deleted */
8301 SCIP_REOPT* reopt, /**< reoptimization data structure */
8302 SCIP_CONS* cons /**< problem constraint */
8303 )
8304{
8305 assert(reopt != NULL);
8306 assert(cons != NULL);
8307
8308 /* the hashset is not initialized, we can delete all constraints */
8309 if( reopt->activeconss == NULL )
8310 return TRUE;
8311
8312 return !SCIPhashsetExists(reopt->activeconssset, (void*)cons);
8313}
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_Real * r
Definition: circlepacking.c:59
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:438
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:185
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:170
internal methods for clocks and timing issues
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6273
SCIP_RETCODE SCIPconsDeactivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat)
Definition: cons.c:6919
SCIP_RETCODE SCIPconsGetNVars(SCIP_CONS *cons, SCIP_SET *set, int *nvars, SCIP_Bool *success)
Definition: cons.c:6400
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6285
SCIP_RETCODE SCIPconsActivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool focusnode)
Definition: cons.c:6877
internal methods for constraints and constraint handlers
constraint handler for bound disjunction constraints
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
Constraint handler for the set partitioning / packing / covering constraints .
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
internal methods for storing cuts in a cut pool
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:238
#define SCIP_ALLOC(x)
Definition: def.h:380
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define SQR(x)
Definition: def.h:213
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:234
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:369
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
internal methods for managing events
#define nnodes
Definition: gastrans.c:74
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetBoundsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
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)
SCIP_BOUNDTYPE * SCIPgetBoundtypesBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9606
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9629
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)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
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)
SCIP_VAR ** SCIPgetVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
@ SCIP_SETPPCTYPE_PARTITIONING
Definition: cons_setppc.h:87
@ SCIP_SETPPCTYPE_COVERING
Definition: cons_setppc.h:89
@ SCIP_SETPPCTYPE_PACKING
Definition: cons_setppc.h:88
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2432
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3110
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3303
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3230
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3076
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3425
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3792
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3819
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:4018
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3802
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3761
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3324
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10150
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17071
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4216
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8253
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8362
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8294
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8233
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:361
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:407
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1218
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1242
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1453
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7900
void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE reopttype)
Definition: tree.c:7581
void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
Definition: tree.c:7612
void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7937
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7521
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7551
void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
Definition: tree.c:7636
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7531
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7826
int SCIPnodeGetNAddedConss(SCIP_NODE *node)
Definition: tree.c:1732
void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
Definition: tree.c:1702
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7541
SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
Definition: tree.c:7571
unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
Definition: tree.c:7602
SCIP_RETCODE SCIPaddReoptDualBndchg(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_Real oldbound)
Definition: scip_solve.c:3108
SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
Definition: scip_solve.c:3493
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17321
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17267
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17331
int SCIProwGetAge(SCIP_ROW *row)
Definition: lp.c:17400
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:17256
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17530
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17287
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17277
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17460
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2804
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2721
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetEffectiveRootDepth(SCIP *scip)
Definition: scip_tree.c:127
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12792
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12487
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17807
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17766
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17556
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18162
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17579
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17944
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17602
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18106
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17776
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17786
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17437
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12879
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18152
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17592
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17724
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17566
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18096
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17796
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:1250
unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
Definition: misc.c:1167
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:1020
SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
Definition: misc.c:1108
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:996
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:1031
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1237
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10878
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:665
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:691
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:607
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:623
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:591
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:66
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:113
internal methods for branching and inference history
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13114
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:5106
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition: lp.c:10188
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:17641
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17651
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5348
internal methods for LP management
methods for block memory pools and memory buffers
memory allocation routines
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryNull(mem, ptr)
Definition: memory.h:466
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:455
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:125
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:10093
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:10077
internal miscellaneous methods
internal methods for collecting primal CIP solutions and primal informations
SCIP_CONS ** SCIPprobGetConss(SCIP_PROB *prob)
Definition: prob.c:2491
int SCIPprobGetNConss(SCIP_PROB *prob)
Definition: prob.c:2482
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2401
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2446
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2336
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
#define SCIPdebugMessage
Definition: pub_message.h:96
static SCIP_RETCODE reoptMoveIDs(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id1, unsigned int id2)
Definition: reopt.c:3485
SCIP_RETCODE SCIPreoptUpdateVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars)
Definition: reopt.c:6607
static SCIP_RETCODE changeReopttypeOfSubtree(SCIP_REOPTTREE *reopttree, unsigned int id, SCIP_REOPTTYPE reopttype)
Definition: reopt.c:1946
int SCIPreoptGetNDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:6329
SCIP_RETCODE SCIPreoptSaveActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
Definition: reopt.c:8167
static int soltreeNInducedSols(SCIP_SOLNODE *solnode)
Definition: reopt.c:367
int SCIPreoptGetNTotalPrunedNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4976
SCIP_RETCODE SCIPreoptnodeReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:7924
SCIP_RETCODE SCIPreoptAddRun(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars, int size)
Definition: reopt.c:5371
SCIP_RETCODE SCIPreoptAddCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons)
Definition: reopt.c:8076
int SCIPreoptGetNTotalFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4956
void SCIPreoptAddNCheckedSols(SCIP_REOPT *reopt, int ncheckedsols)
Definition: reopt.c:5417
static SCIP_RETCODE ensureSolsSize(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int num, int runidx)
Definition: reopt.c:192
static SCIP_RETCODE reopttreeDeleteNode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id, SCIP_Bool softreset)
Definition: reopt.c:680
int SCIPreoptGetFirstRestarts(SCIP_REOPT *reopt)
Definition: reopt.c:4926
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:1444
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:5284
int SCIPreoptGetNTotalRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:4916
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:5971
static SCIP_RETCODE transformDualredsToBounddisjunction(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTCONSDATA *consdata, SCIP_REOPTCONSDATA *dualreds)
Definition: reopt.c:6821
static SCIP_RETCODE transformIntoOrig(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:1624
static SCIP_RETCODE saveLocalConssData(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id)
Definition: reopt.c:2383
int SCIPreoptGetNImprovingSols(SCIP_REOPT *reopt)
Definition: reopt.c:5428
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:3221
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 shrinkNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node, unsigned int id, SCIP_Bool *shrank, BMS_BLKMEM *blkmem)
Definition: reopt.c:1868
static void deleteLastDualBndchgs(SCIP_REOPT *reopt)
Definition: reopt.c:3154
SCIP_RETCODE SCIPreoptAddInfNode(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node)
Definition: reopt.c:5947
static SCIP_RETCODE clearReoptnodes(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
Definition: reopt.c:1217
static SCIP_RETCODE reoptResetTree(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
Definition: reopt.c:4612
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:7714
static SCIP_RETCODE reopttreeCheckMemory(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:255
SCIP_SOL * SCIPreoptGetLastBestSol(SCIP_REOPT *reopt)
Definition: reopt.c:5652
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:4802
SCIP_RETCODE SCIPreoptnodeAddBndchg(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real val, SCIP_BOUNDTYPE boundtype)
Definition: reopt.c:7956
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:7984
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:6878
#define DEFAULT_MEM_DUALCONS
Definition: reopt.c:64
static SCIP_RETCODE createSolTree(SCIP_SOLTREE *soltree, BMS_BLKMEM *blkmem)
Definition: reopt.c:712
SCIP_RETCODE SCIPreoptGetSolsRun(SCIP_REOPT *reopt, int run, SCIP_SOL **sols, int solssize, int *nsols)
Definition: reopt.c:5479
static SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
Definition: reopt.c:139
static void resetStats(SCIP_REOPT *reopt)
Definition: reopt.c:4280
static SCIP_RETCODE reoptRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:4638
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:3978
SCIP_Bool SCIPreoptConsCanBeDeleted(SCIP_REOPT *reopt, SCIP_CONS *cons)
Definition: reopt.c:8300
static SCIP_RETCODE freeReoptTree(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:1253
int SCIPreoptGetNPrunedNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4966
int SCIPreoptGetNFeasNodes(SCIP_REOPT *reopt)
Definition: reopt.c:4946
static SCIP_RETCODE reoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:483
static int reoptGetNLeaves(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:4538
static SCIP_RETCODE saveGlobalCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, REOPT_CONSTYPE consttype)
Definition: reopt.c:3418
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
SCIP_RETCODE SCIPreoptDeleteNode(SCIP_REOPT *reopt, SCIP_SET *set, unsigned int id, BMS_BLKMEM *blkmem)
Definition: reopt.c:7260
SCIP_Real SCIPreoptnodeGetLowerbound(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5846
static SCIP_RETCODE reoptnodeReset(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:604
int SCIPreoptGetNRestartsLocal(SCIP_REOPT *reopt)
Definition: reopt.c:4906
SCIP_RETCODE SCIPreoptReleaseData(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:5107
#define DEFAULT_MEM_VAR
Definition: reopt.c:61
SCIP_RETCODE SCIPreoptResetDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node, BMS_BLKMEM *blkmem)
Definition: reopt.c:7176
void SCIPreoptResetSolMarks(SCIP_REOPT *reopt)
Definition: reopt.c:5742
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:4755
static SCIP_RETCODE freeSolTree(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
Definition: reopt.c:786
int SCIPreoptGetNSols(SCIP_REOPT *reopt)
Definition: reopt.c:5464
int SCIPreoptGetNSolsRun(SCIP_REOPT *reopt, int run)
Definition: reopt.c:5449
void SCIPreoptnodeSetParentID(SCIP_REOPTNODE *reoptnode, unsigned int parentid)
Definition: reopt.c:5901
SCIP_Real SCIPreoptGetSimToFirst(SCIP_REOPT *reopt)
Definition: reopt.c:5624
static SCIP_RETCODE saveConsBounddisjuction(SCIP_REOPTCONSDATA *reoptconsdata, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons, SCIP_Bool *success)
Definition: reopt.c:2314
static SCIP_RETCODE reoptAddChild(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int parentid, unsigned int childid)
Definition: reopt.c:1729
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:7280
#define DEFAULT_MEM_VARAFTERDUAL
Definition: reopt.c:60
int SCIPreoptGetNSavedSols(SCIP_REOPT *reopt)
Definition: reopt.c:5519
#define DEFAULT_MEM_NODES
Definition: reopt.c:62
SCIP_Real SCIPreoptGetOldObjCoef(SCIP_REOPT *reopt, int run, int idx)
Definition: reopt.c:5680
static void soltreeResetMarks(SCIP_SOLNODE *node)
Definition: reopt.c:1082
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
static SCIP_RETCODE cleanActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:1351
static SCIP_DECL_EVENTEXEC(eventExecReopt)
Definition: reopt.c:76
int SCIPreoptGetNCheckedSols(SCIP_REOPT *reopt)
Definition: reopt.c:5407
static SCIP_RETCODE reoptGetLeaves(SCIP_REOPT *reopt, unsigned int id, unsigned int *leaves, int leavessize, int *nleaves)
Definition: reopt.c:4568
static SCIP_RETCODE getLastSavedNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node, SCIP_NODE **parent, unsigned int *parentid, int *nbndchgs)
Definition: reopt.c:1667
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
static SCIP_RETCODE storeCuts(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_LP *lp, unsigned int id)
Definition: reopt.c:1524
static SCIP_RETCODE transformDualredsToLinear(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTCONSDATA *consdata, SCIP_REOPTCONSDATA *dualreds)
Definition: reopt.c:6761
SCIP_RETCODE SCIPreoptFree(SCIP_REOPT **reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
Definition: reopt.c:5134
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:4210
int SCIPreoptnodeGetNConss(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5813
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
void SCIPreoptnodeGetConss(SCIP_REOPTNODE *reoptnode, SCIP_VAR ***vars, SCIP_Real **bounds, SCIP_BOUNDTYPE **boundtypes, int mem, int *nconss, int *nvars)
Definition: reopt.c:5866
static SCIP_RETCODE checkMemGlbCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int mem)
Definition: reopt.c:1311
int SCIPreoptGetLastRestarts(SCIP_REOPT *reopt)
Definition: reopt.c:4936
static SCIP_RETCODE reoptnodeResetDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:3171
static SCIP_RETCODE createReopttree(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:1173
int SCIPreoptnodeGetNVars(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5803
static SCIP_RETCODE ensureActiveconssSize(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int num)
Definition: reopt.c:171
int SCIPreoptGetNTotalCutoffReoptnodes(SCIP_REOPT *reopt)
Definition: reopt.c:4996
static int reopttreeGetNNodes(SCIP_REOPTTREE *reopttree, unsigned int id)
Definition: reopt.c:4520
static SCIP_RETCODE createReoptnode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id)
Definition: reopt.c:1116
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:7201
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:5337
SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5856
int SCIPreoptGetNNodes(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:5763
static SCIP_RETCODE moveChildrenUp(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int nodeid, unsigned int parentid)
Definition: reopt.c:1762
SCIP_Real SCIPreoptGetSavingtime(SCIP_REOPT *reopt)
Definition: reopt.c:7582
SCIP_RETCODE SCIPreoptResetActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat)
Definition: reopt.c:8259
SCIP_RETCODE SCIPreoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:7942
SCIP_RETCODE SCIPreoptCreate(SCIP_REOPT **reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:5026
int SCIPreoptGetNTotalInfNodes(SCIP_REOPT *reopt)
Definition: reopt.c:5016
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:6239
#define DEFAULT_RANDSEED
Definition: reopt.c:66
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 collectDualInformation(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_REOPTTYPE reopttype)
Definition: reopt.c:2477
SCIP_Real SCIPreoptGetSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int run1, int run2, SCIP_VAR **origvars, int norigvars)
Definition: reopt.c:5633
static SCIP_RETCODE ensureRunSize(SCIP_REOPT *reopt, SCIP_SET *set, int num, BMS_BLKMEM *blkmem)
Definition: reopt.c:219
static SCIP_RETCODE dryBranch(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool *runagain, unsigned int id)
Definition: reopt.c:4305
static SCIP_RETCODE soltreefreeNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SOLNODE **solnode)
Definition: reopt.c:744
SCIP_RETCODE SCIPreoptGetLeaves(SCIP_REOPT *reopt, SCIP_NODE *node, unsigned int *leaves, int leavessize, int *nleaves)
Definition: reopt.c:6402
static SCIP_RETCODE updatePropagation(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool *transintoorig)
Definition: reopt.c:1387
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
int SCIPreoptGetNAddedConss(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:5260
SCIP_RETCODE SCIPreoptMergeVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **vars, int nvars)
Definition: reopt.c:6515
static SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
Definition: reopt.c:114
static SCIP_RETCODE checkMemDualCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int size)
Definition: reopt.c:1277
#define EVENTHDLR_DESC
Definition: reopt.c:70
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:4099
SCIP_RETCODE SCIPreoptSaveGlobalBounds(SCIP_REOPT *reopt, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
Definition: reopt.c:8127
SCIP_REOPTNODE * SCIPreoptGetReoptnode(SCIP_REOPT *reopt, unsigned int id)
Definition: reopt.c:5666
void SCIPreoptAddNImprovingSols(SCIP_REOPT *reopt, int nimprovingsols)
Definition: reopt.c:5438
static SCIP_RETCODE reoptnodeUpdateDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
Definition: reopt.c:1992
SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
Definition: reopt.c:7844
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:5546
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:3709
int SCIPreoptGetNCutoffReoptnodes(SCIP_REOPT *reopt)
Definition: reopt.c:4986
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:8207
static SCIP_RETCODE reoptSaveNewObj(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars)
Definition: reopt.c:4668
int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5836
SCIP_RETCODE SCIPreoptApplyGlbConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: reopt.c:7592
SCIP_RETCODE SCIPreoptApplyCompression(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE **representatives, int nrepresentatives, SCIP_Bool *success)
Definition: reopt.c:6662
#define DEFAULT_MEM_RUN
Definition: reopt.c:63
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:3535
int SCIPreoptnodeGetNDualBoundChgs(SCIP_REOPTNODE *reoptnode)
Definition: reopt.c:5823
SCIP_Real SCIPreoptGetSimToPrevious(SCIP_REOPT *reopt)
Definition: reopt.c:5615
SCIP_RETCODE SCIPreoptReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: reopt.c:5708
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:6349
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
#define EVENTHDLR_NAME
Definition: reopt.c:69
int SCIPreoptGetNRestartsGlobal(SCIP_REOPT *reopt)
Definition: reopt.c:4896
SCIP_RETCODE SCIPreoptSaveOpenNodes(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_NODE **leaves, int nleaves, SCIP_NODE **childs, int nchilds, SCIP_NODE **siblings, int nsiblings)
Definition: reopt.c:6465
static SCIP_RETCODE saveConsLinear(SCIP_REOPTCONSDATA *reoptconsdata, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons, SCIP_Bool *success)
Definition: reopt.c:2182
SCIP_SOL * SCIPreoptGetBestSolRun(SCIP_REOPT *reopt, int run)
Definition: reopt.c:5696
void SCIPreoptnodeInit(SCIP_REOPTNODE *reoptnode, SCIP_SET *set)
Definition: reopt.c:7891
int SCIPreoptGetNLeaves(SCIP_REOPT *reopt, SCIP_NODE *node)
Definition: reopt.c:5913
int SCIPreoptGetNInfNodes(SCIP_REOPT *reopt)
Definition: reopt.c:5006
data structures and methods for collecting reoptimization information
SCIP callable library.
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
internal methods for storing separated cuts
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6641
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6257
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6221
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6619
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6064
SCIP_RETCODE SCIPsetGetIntParam(SCIP_SET *set, const char *name, int *value)
Definition: set.c:3137
SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
Definition: set.c:4729
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6239
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6199
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6275
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6344
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6311
SCIP_BRANCHRULE * SCIPsetFindBranchrule(SCIP_SET *set, const char *name)
Definition: set.c:4885
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6685
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6408
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5764
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6333
unsigned int SCIPsetInitializeRandomSeed(SCIP_SET *set, unsigned int initialseedvalue)
Definition: set.c:7393
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
#define SCIPsetDebugMsg
Definition: set.h:1784
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1752
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:801
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1372
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
internal methods for storing primal CIP solutions
unsigned int deleted
Definition: struct_cons.h:91
SCIP_Real pscostweightedmean[2]
SCIP_Real pscostvariance[2]
SCIP_Real pscostcount[2]
SCIP_VAR ** afterdualvars
Definition: struct_reopt.h:97
SCIP_REOPTCONSDATA * dualredscur
Definition: struct_reopt.h:98
SCIP_REOPTCONSDATA * dualredsnex
Definition: struct_reopt.h:99
SCIP_BOUNDTYPE * afterdualvarboundtypes
Definition: struct_reopt.h:101
SCIP_BOUNDTYPE * varboundtypes
Definition: struct_reopt.h:100
unsigned int * childids
Definition: struct_reopt.h:114
SCIP_Bool dualreds
Definition: struct_reopt.h:105
SCIP_VAR ** vars
Definition: struct_reopt.h:96
SCIP_Real * afterdualvarbounds
Definition: struct_reopt.h:103
SCIP_REOPTCONSDATA ** conss
Definition: struct_reopt.h:95
SCIP_Real lowerbound
Definition: struct_reopt.h:104
unsigned int parentID
Definition: struct_reopt.h:116
unsigned int reopttype
Definition: struct_reopt.h:117
SCIP_Real * varbounds
Definition: struct_reopt.h:102
SCIP_QUEUE * openids
Definition: struct_reopt.h:124
unsigned int reoptnodessize
Definition: struct_reopt.h:135
SCIP_REOPTNODE ** reoptnodes
Definition: struct_reopt.h:123
int ntotalcutoffreoptnodes
Definition: struct_reopt.h:133
int firstrestart
Definition: struct_reopt.h:182
int nimprovingsols
Definition: struct_reopt.h:178
SCIP_REOPTCONSDATA ** glbconss
Definition: struct_reopt.h:144
SCIP_Bool consadded
Definition: struct_reopt.h:159
int nactiveconss
Definition: struct_reopt.h:160
SCIP_SOL ** prevbestsols
Definition: struct_reopt.h:141
SCIP_REOPTTREE * reopttree
Definition: struct_reopt.h:146
SCIP_REOPTCONSDATA * dualreds
Definition: struct_reopt.h:145
int nglbrestarts
Definition: struct_reopt.h:179
SCIP_SOLTREE * soltree
Definition: struct_reopt.h:147
SCIP_Longint lastbranched
Definition: struct_reopt.h:153
int nlocrestarts
Definition: struct_reopt.h:181
int ntotallocrestarts
Definition: struct_reopt.h:180
int noptsolsbyreoptsol
Definition: struct_reopt.h:174
int nmaxactiveconss
Definition: struct_reopt.h:162
SCIP_RANDNUMGEN * randnumgen
Definition: struct_reopt.h:148
SCIP_CLOCK * savingtime
Definition: struct_reopt.h:149
SCIP_HASHMAP * glblb
Definition: struct_reopt.h:165
SCIP_Longint lastseennode
Definition: struct_reopt.h:154
SCIP_CONS ** activeconss
Definition: struct_reopt.h:161
SCIP_Longint currentnode
Definition: struct_reopt.h:170
SCIP_HASHSET * activeconssset
Definition: struct_reopt.h:167
SCIP_HISTORY *** varhistory
Definition: struct_reopt.h:143
SCIP_Bool objhaschanged
Definition: struct_reopt.h:158
SCIP_Real simtofirstobj
Definition: struct_reopt.h:152
SCIP_Real ** objs
Definition: struct_reopt.h:142
int addedconsssize
Definition: struct_reopt.h:156
SCIP_CONS ** addedconss
Definition: struct_reopt.h:150
int ncheckedsols
Definition: struct_reopt.h:177
SCIP_HASHMAP * glbub
Definition: struct_reopt.h:166
int allocmemglbconss
Definition: struct_reopt.h:176
SCIP_Real simtolastobj
Definition: struct_reopt.h:151
SCIP_SOL * sol
Definition: struct_reopt.h:53
SCIP_VAR * var
Definition: struct_reopt.h:63
SCIP_Real value
Definition: struct_reopt.h:59
SCIP_SOLNODE * child
Definition: struct_reopt.h:55
SCIP_SOLNODE * father
Definition: struct_reopt.h:54
SCIP_SOLNODE * sibling
Definition: struct_reopt.h:58
SCIP_Bool updated
Definition: struct_reopt.h:60
SCIP_SOLNODE * root
Definition: struct_reopt.h:71
SCIP_SOLNODE *** sols
Definition: struct_reopt.h:70
int * solssize
Definition: struct_reopt.h:72
SCIP_HISTORY * history
Definition: struct_var.h:250
Definition: heur_padm.c:135
void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
Definition: tree.c:7748
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2517
void SCIPnodeGetPropsAfterDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nvars, int varssize)
Definition: tree.c:8061
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8573
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:1036
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:2118
int SCIPnodeGetNDualBndchgs(SCIP_NODE *node)
Definition: tree.c:7703
void SCIPnodeGetPropsBeforeDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *npropvars, int propvarssize)
Definition: tree.c:7979
internal methods for branch and bound tree
@ SCIP_CLOCKTYPE_DEFAULT
Definition: type_clock.h:43
#define SCIP_EVENTTYPE_NODEFEASIBLE
Definition: type_event.h:93
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:120
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:94
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:95
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:51
@ SCIP_ROWORIGINTYPE_REOPT
Definition: type_lp.h:76
@ SCIP_ROWORIGINTYPE_SEPA
Definition: type_lp.h:75
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:42
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:46
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:61
@ SCIP_VERBLEVEL_NORMAL
Definition: type_message.h:60
@ SCIP_REOPTTYPE_INFSUBTREE
Definition: type_reopt.h:60
@ SCIP_REOPTTYPE_LOGICORNODE
Definition: type_reopt.h:62
@ SCIP_REOPTTYPE_PRUNED
Definition: type_reopt.h:64
@ SCIP_REOPTTYPE_FEASIBLE
Definition: type_reopt.h:65
@ SCIP_REOPTTYPE_LEAF
Definition: type_reopt.h:63
@ SCIP_REOPTTYPE_TRANSIT
Definition: type_reopt.h:59
@ SCIP_REOPTTYPE_STRBRANCHED
Definition: type_reopt.h:61
@ SCIP_REOPTTYPE_NONE
Definition: type_reopt.h:58
enum SCIP_ReoptType SCIP_REOPTTYPE
Definition: type_reopt.h:67
struct SCIP_ReoptConsData SCIP_REOPTCONSDATA
Definition: type_reopt.h:51
@ REOPT_CONSTYPE_DUALREDS
Definition: type_reopt.h:72
@ REOPT_CONSTYPE_INFSUBTREE
Definition: type_reopt.h:71
@ REOPT_CONSTYPE_CUT
Definition: type_reopt.h:73
@ REOPT_CONSTYPE_UNKNOWN
Definition: type_reopt.h:74
enum Reopt_ConsType REOPT_CONSTYPE
Definition: type_reopt.h:76
@ SCIP_INVALIDRESULT
Definition: type_retcode.h:53
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INIT
Definition: type_set.h:44
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_NODETYPE_PROBINGNODE
Definition: type_tree.h:42
@ SCIP_NODETYPE_FOCUSNODE
Definition: type_tree.h:41
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition: type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6514
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:7182
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:7330
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16085
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:7977
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5914
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6531
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:8104
internal methods for problem variables