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