Scippy

SCIP

Solving Constraint Integer Programs

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