Scippy

SCIP

Solving Constraint Integer Programs

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