1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file scip_reopt.c
17 * @ingroup OTHER_CFILES
18 * @brief public methods for reoptimization
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 * @author Gerald Gamrath
22 * @author Leona Gottwald
23 * @author Stefan Heinz
24 * @author Gregor Hendel
25 * @author Thorsten Koch
26 * @author Alexander Martin
27 * @author Marc Pfetsch
28 * @author Michael Winkler
29 * @author Kati Wolter
30 *
31 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32 */
33
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36 #include "scip/debug.h"
37 #include "scip/pub_message.h"
38 #include "scip/pub_reopt.h"
39 #include "scip/pub_tree.h"
40 #include "scip/reopt.h"
41 #include "scip/scip_mem.h"
42 #include "scip/scip_reopt.h"
43 #include "scip/scip_tree.h"
44 #include "scip/struct_mem.h"
45 #include "scip/struct_prob.h"
46 #include "scip/struct_scip.h"
47 #include "scip/struct_set.h"
48 #include "scip/struct_stat.h"
49
50 /** return the ids of child nodes stored in the reoptimization tree
51 *
52 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
53 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
54 *
55 * @pre This method can be called if @p scip is in one of the following stages:
56 * - \ref SCIP_STAGE_PRESOLVED
57 * - \ref SCIP_STAGE_SOLVING
58 * - \ref SCIP_STAGE_SOLVED
59 */
SCIPgetReoptChildIDs(SCIP * scip,SCIP_NODE * node,unsigned int * ids,int idssize,int * nids)60 SCIP_RETCODE SCIPgetReoptChildIDs(
61 SCIP* scip, /**< SCIP data structure */
62 SCIP_NODE* node, /**< node of the search tree */
63 unsigned int* ids, /**< array of ids */
64 int idssize, /**< allocated memory */
65 int* nids /**< number of child nodes */
66 )
67 {
68 assert(scip != NULL);
69
70 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetReoptChildIDs", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
71
72 (*nids) = 0;
73
74 if( !scip->set->reopt_enable )
75 return SCIP_OKAY;
76
77 SCIP_CALL( SCIPreoptGetChildIDs(scip->reopt, scip->set, scip->mem->probmem, node, ids, idssize, nids) );
78
79 return SCIP_OKAY;
80 }
81
82 /** return the ids of all leave nodes store in the reoptimization tree induced by the given node
83 *
84 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
85 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
86 *
87 * @pre This method can be called if @p scip is in one of the following stages:
88 * - \ref SCIP_STAGE_PRESOLVED
89 * - \ref SCIP_STAGE_SOLVING
90 * - \ref SCIP_STAGE_SOLVED
91 */
SCIPgetReoptLeaveIDs(SCIP * scip,SCIP_NODE * node,unsigned int * ids,int idssize,int * nids)92 SCIP_RETCODE SCIPgetReoptLeaveIDs(
93 SCIP* scip, /**< SCIP data structure */
94 SCIP_NODE* node, /**< node of the search tree */
95 unsigned int* ids, /**< array of ids */
96 int idssize, /**< size of ids array */
97 int* nids /**< number of child nodes */
98 )
99 {
100 assert(scip != NULL);
101
102 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetReoptLeaveIDs", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
103
104 (*nids) = 0;
105
106 if( idssize == 0 || !scip->set->reopt_enable )
107 return SCIP_OKAY;
108
109 SCIP_CALL( SCIPreoptGetLeaves(scip->reopt, node, ids, idssize, nids) );
110
111 return SCIP_OKAY;
112 }
113
114 /** returns the number of nodes in the reoptimization tree induced by @p node; if @p node == NULL the method
115 * returns the number of nodes of the whole reoptimization tree.
116 */
SCIPgetNReoptnodes(SCIP * scip,SCIP_NODE * node)117 int SCIPgetNReoptnodes(
118 SCIP* scip, /**< SCIP data structure */
119 SCIP_NODE* node /**< node of the search tree */
120 )
121 {
122 assert(scip != NULL);
123 assert(scip->set->reopt_enable);
124 assert(scip->reopt != NULL);
125
126 return SCIPreoptGetNNodes(scip->reopt, node);
127 }
128
129 /** returns the number of leaf nodes of the subtree induced by @p node; if @p node == NULL, the method
130 * returns the number of leaf nodes of the whole reoptimization tree.
131 */
SCIPgetNReoptLeaves(SCIP * scip,SCIP_NODE * node)132 int SCIPgetNReoptLeaves(
133 SCIP* scip, /**< SCIP data structure */
134 SCIP_NODE* node /**< node of the search tree */
135 )
136 {
137 assert(scip != NULL);
138 assert(scip->set->reopt_enable);
139 assert(scip->reopt != NULL);
140
141 return SCIPreoptGetNLeaves(scip->reopt, node);
142 }
143
144 /** gets the node of the reoptimization tree corresponding to the unique @p id */
SCIPgetReoptnode(SCIP * scip,unsigned int id)145 SCIP_REOPTNODE* SCIPgetReoptnode(
146 SCIP* scip, /**< SCIP data structure */
147 unsigned int id /**< unique id */
148 )
149 {
150 assert(scip != NULL);
151 assert(scip->set->reopt_enable);
152 assert(scip->reopt != NULL);
153
154 return SCIPreoptGetReoptnode(scip->reopt, id);
155 }
156
157 /** add a variable bound change to a given reoptnode
158 *
159 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
160 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
161 *
162 * @pre This method can be called if @p scip is in one of the following stages:
163 * - \ref SCIP_STAGE_PRESOLVED
164 * - \ref SCIP_STAGE_SOLVING
165 * - \ref SCIP_STAGE_SOLVED
166 */
SCIPaddReoptnodeBndchg(SCIP * scip,SCIP_REOPTNODE * reoptnode,SCIP_VAR * var,SCIP_Real bound,SCIP_BOUNDTYPE boundtype)167 SCIP_RETCODE SCIPaddReoptnodeBndchg(
168 SCIP* scip, /**< SCIP data structure */
169 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
170 SCIP_VAR* var, /**< variable pointer */
171 SCIP_Real bound, /**< variable bound to add */
172 SCIP_BOUNDTYPE boundtype /**< bound type of the variable value */
173 )
174 {
175 assert(scip != NULL);
176 assert(reoptnode != NULL);
177 assert(scip->set->reopt_enable);
178 assert(scip->reopt != NULL);
179
180 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddReoptnodeBndchg", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
181
182 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, scip->set, scip->mem->probmem, var, bound, boundtype) );
183
184 return SCIP_OKAY;
185 }
186
187 /** set the @p representation as the new search frontier
188 *
189 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
190 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
191 *
192 * @pre This method can be called if @p scip is in one of the following stages:
193 * - \ref SCIP_STAGE_PRESOLVED
194 */
SCIPsetReoptCompression(SCIP * scip,SCIP_REOPTNODE ** representation,int nrepresentatives,SCIP_Bool * success)195 SCIP_RETCODE SCIPsetReoptCompression(
196 SCIP* scip, /**< SCIP data structure */
197 SCIP_REOPTNODE** representation, /**< array of representatives */
198 int nrepresentatives, /**< number of representatives */
199 SCIP_Bool* success /**< pointer to store the result */
200 )
201 {
202 assert(scip != NULL);
203 assert(representation != NULL);
204 assert(nrepresentatives > 0);
205 assert(scip->set->reopt_enable);
206 assert(scip->reopt != NULL);
207
208 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetReoptCompression", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
209
210 SCIP_CALL( SCIPreoptApplyCompression(scip->reopt, scip->set, scip->mem->probmem, representation, nrepresentatives, success) );
211
212 return SCIP_OKAY;
213 }
214
215 /** add stored constraint to a reoptimization node
216 *
217 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
218 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
219 *
220 * @pre This method can be called if @p scip is in one of the following stages:
221 * - \ref SCIP_STAGE_PRESOLVED
222 */
SCIPaddReoptnodeCons(SCIP * scip,SCIP_REOPTNODE * reoptnode,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_BOUNDTYPE * boundtypes,SCIP_Real lhs,SCIP_Real rhs,int nvars,REOPT_CONSTYPE constype,SCIP_Bool linear)223 SCIP_RETCODE SCIPaddReoptnodeCons(
224 SCIP* scip, /**< SCIP data structure */
225 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
226 SCIP_VAR** vars, /**< array of variables */
227 SCIP_Real* vals, /**< array of variable bounds */
228 SCIP_BOUNDTYPE* boundtypes, /**< array of variable boundtypes */
229 SCIP_Real lhs, /**< lhs of the constraint */
230 SCIP_Real rhs, /**< rhs of the constraint */
231 int nvars, /**< number of variables */
232 REOPT_CONSTYPE constype, /**< type of the constraint */
233 SCIP_Bool linear /**< the given constraint has a linear representation */
234 )
235 {
236 assert(scip != NULL);
237 assert(reoptnode != NULL);
238 assert(vars != NULL);
239 assert(vals != NULL);
240 assert(nvars >= 0);
241
242 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddReoptnodeCons", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
243
244 SCIP_CALL( SCIPreoptnodeAddCons(reoptnode, scip->set, scip->mem->probmem, vars, vals, boundtypes, lhs, rhs, nvars,
245 constype, linear) );
246
247 return SCIP_OKAY;
248 }
249
250 /** return the branching path stored in the reoptree at ID id */
SCIPgetReoptnodePath(SCIP * scip,SCIP_REOPTNODE * reoptnode,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_BOUNDTYPE * boundtypes,int mem,int * nvars,int * nafterdualvars)251 void SCIPgetReoptnodePath(
252 SCIP* scip, /**< SCIP data structure */
253 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
254 SCIP_VAR** vars, /**< array of variables */
255 SCIP_Real* vals, /**< array of variable bounds */
256 SCIP_BOUNDTYPE* boundtypes, /**< array of bound types */
257 int mem, /**< allocated memory */
258 int* nvars, /**< number of variables */
259 int* nafterdualvars /**< number of variables directly after the first based on dual information */
260 )
261 {
262 assert(scip != NULL);
263 assert(vars != NULL);
264 assert(vals != NULL);
265 assert(boundtypes != NULL);
266 assert(scip->set->reopt_enable);
267 assert(scip->reopt != NULL);
268
269 SCIPreoptnodeGetPath(scip->reopt, reoptnode, vars, vals, boundtypes, mem, nvars, nafterdualvars);
270 }
271
272 /** initialize a set of empty reoptimization nodes
273 *
274 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
275 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
276 *
277 * @pre This method can be called if @p scip is in one of the following stages:
278 * - \ref SCIP_STAGE_PRESOLVED
279 */
SCIPinitRepresentation(SCIP * scip,SCIP_REOPTNODE ** representatives,int nrepresentatives)280 SCIP_RETCODE SCIPinitRepresentation(
281 SCIP* scip, /**< SCIP data structure */
282 SCIP_REOPTNODE** representatives, /**< array of representatives */
283 int nrepresentatives /**< number of representatives */
284 )
285 {
286 int r;
287
288 assert(scip != NULL);
289 assert(representatives != NULL);
290
291 SCIP_CALL( SCIPcheckStage(scip, "SCIPinitRepresentation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
292
293 for( r = 0; r < nrepresentatives; r++ )
294 {
295 SCIP_CALL( SCIPallocBlockMemory(scip, &representatives[r]) ); /*lint !e866*/
296 SCIPreoptnodeInit(representatives[r], scip->set);
297 }
298
299 return SCIP_OKAY;
300 }
301
302 /** reset a set of initialized reoptimization nodes
303 *
304 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
305 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
306 *
307 * @pre This method can be called if @p scip is in one of the following stages:
308 * - \ref SCIP_STAGE_PRESOLVED
309 */
SCIPresetRepresentation(SCIP * scip,SCIP_REOPTNODE ** representatives,int nrepresentatives)310 SCIP_RETCODE SCIPresetRepresentation(
311 SCIP* scip, /**< SCIP data structure */
312 SCIP_REOPTNODE** representatives, /**< array of representatives */
313 int nrepresentatives /**< number of representatives */
314 )
315 {
316 int r;
317
318 assert(scip != NULL);
319 assert(representatives != NULL);
320
321 SCIP_CALL( SCIPcheckStage(scip, "SCIPresetRepresentation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
322
323 for( r = 0; r < nrepresentatives; r++ )
324 {
325 SCIP_CALL( SCIPreoptnodeReset(scip->reopt, scip->set, scip->mem->probmem, representatives[r]) );
326 }
327
328 return SCIP_OKAY;
329 }
330
331 /** free a set of initialized reoptimization nodes
332 *
333 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
334 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
335 *
336 * @pre This method can be called if @p scip is in one of the following stages:
337 * - \ref SCIP_STAGE_PRESOLVED
338 */
SCIPfreeRepresentation(SCIP * scip,SCIP_REOPTNODE ** representatives,int nrepresentatives)339 SCIP_RETCODE SCIPfreeRepresentation(
340 SCIP* scip, /**< SCIP data structure */
341 SCIP_REOPTNODE** representatives, /**< array of representatives */
342 int nrepresentatives /**< number of representatives */
343 )
344 {
345 int r;
346
347 assert(scip != NULL);
348 assert(representatives != NULL);
349
350 SCIP_CALL( SCIPcheckStage(scip, "SCIPfreeRepresentation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
351
352 for( r = 0; r < nrepresentatives; r++ )
353 {
354 if( representatives[r] != NULL )
355 {
356 SCIP_CALL( SCIPreoptnodeDelete(&representatives[r], scip->mem->probmem) );
357 assert(representatives[r] == NULL);
358 }
359 }
360
361 return SCIP_OKAY;
362 }
363
364 /** reactivate the given @p reoptnode and split them into several nodes if necessary
365 *
366 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
367 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
368 *
369 * @pre This method can be called if @p scip is in one of the following stages:
370 * - \ref SCIP_STAGE_SOLVING
371 * - \ref SCIP_STAGE_SOLVED
372 */
SCIPapplyReopt(SCIP * scip,SCIP_REOPTNODE * reoptnode,unsigned int id,SCIP_Real estimate,SCIP_NODE ** childnodes,int * ncreatedchilds,int * naddedconss,int childnodessize,SCIP_Bool * success)373 SCIP_RETCODE SCIPapplyReopt(
374 SCIP* scip, /**< SCIP data structure */
375 SCIP_REOPTNODE* reoptnode, /**< node to reactivate */
376 unsigned int id, /**< unique id of the reoptimization node */
377 SCIP_Real estimate, /**< estimate of the child nodes that should be created */
378 SCIP_NODE** childnodes, /**< array to store the created child nodes */
379 int* ncreatedchilds, /**< pointer to store number of created child nodes */
380 int* naddedconss, /**< pointer to store number of generated constraints */
381 int childnodessize, /**< available size of childnodes array */
382 SCIP_Bool* success /**< pointer store the result*/
383 )
384 {
385 assert(scip != NULL);
386 assert(reoptnode != NULL);
387
388 SCIP_CALL( SCIPcheckStage(scip, "SCIPapplyReopt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
389
390 SCIP_CALL( SCIPreoptApply(scip->reopt, scip, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree,
391 scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, scip->mem->probmem, reoptnode, id, estimate,
392 childnodes, ncreatedchilds, naddedconss, childnodessize, success) );
393
394 return SCIP_OKAY;
395 }
396
397 /** return the similarity between two objective functions */
SCIPgetReoptSimilarity(SCIP * scip,int run1,int run2)398 SCIP_Real SCIPgetReoptSimilarity(
399 SCIP* scip, /**< SCIP data structure */
400 int run1, /**< number of run */
401 int run2 /**< number of run */
402 )
403 {
404 assert(scip != NULL);
405 assert(run1 > 0 && run1 <= scip->stat->nreoptruns);
406 assert(run2 > 0 && run2 <= scip->stat->nreoptruns);
407
408 if( (run1 == scip->stat->nreoptruns && run2 == run1-1) || (run2 == scip->stat->nreoptruns && run1 == run2-1) )
409 return SCIPreoptGetSimToPrevious(scip->reopt);
410 else
411 return SCIPreoptGetSimilarity(scip->reopt, scip->set, run1, run2, scip->origprob->vars, scip->origprob->nvars);
412 }
413
414 /** returns if a node should be reoptimized */
SCIPreoptimizeNode(SCIP * scip,SCIP_NODE * node)415 SCIP_Bool SCIPreoptimizeNode(
416 SCIP* scip, /**< SCIP data structure */
417 SCIP_NODE* node /**< node of the search tree */
418 )
419 {
420 assert(scip != NULL);
421 assert(node != NULL);
422
423 if( scip->set->reopt_enable )
424 {
425 SCIP_REOPTNODE* reoptnode;
426 unsigned int id;
427
428 assert(scip->reopt != NULL);
429
430 id = SCIPnodeGetReoptID(node);
431
432 if( id == 0 && node != SCIPgetRootNode(scip) )
433 return FALSE;
434 else
435 {
436 reoptnode = SCIPgetReoptnode(scip, id);
437 assert(reoptnode != NULL);
438
439 return SCIPreoptnodeGetNChildren(reoptnode) > 0;
440 }
441 }
442 else
443 return FALSE;
444 }
445
446 /** deletes the given reoptimization node
447 *
448 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
449 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
450 *
451 * @pre This method can be called if @p scip is in one of the following stages:
452 * - \ref SCIP_STAGE_TRANSFORMED
453 * - \ref SCIP_STAGE_SOLVING
454 */
SCIPdeleteReoptnode(SCIP * scip,SCIP_REOPTNODE ** reoptnode)455 SCIP_RETCODE SCIPdeleteReoptnode(
456 SCIP* scip, /**< SCIP data structure */
457 SCIP_REOPTNODE** reoptnode /**< node of the reoptimization tree */
458 )
459 {
460 assert(scip != NULL);
461 assert(scip->set->reopt_enable);
462 assert(scip->reopt != NULL);
463 assert((*reoptnode) != NULL);
464
465 SCIP_CALL( SCIPcheckStage(scip, "SCIPdeleteReoptnode", FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
466
467 SCIP_CALL( SCIPreoptnodeDelete(reoptnode, scip->mem->probmem) );
468
469 return SCIP_OKAY;
470 }
471
472 /** splits the root into several nodes and moves the child nodes of the root to one of the created nodes
473 *
474 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
475 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
476 *
477 * @pre This method can be called if @p scip is in one of the following stages:
478 * - \ref SCIP_STAGE_SOLVING
479 */
SCIPsplitReoptRoot(SCIP * scip,int * ncreatedchilds,int * naddedconss)480 SCIP_RETCODE SCIPsplitReoptRoot(
481 SCIP* scip, /**< SCIP data structure */
482 int* ncreatedchilds, /**< pointer to store the number of created nodes */
483 int* naddedconss /**< pointer to store the number added constraints */
484 )
485 {
486 assert(scip != NULL);
487 assert(scip->set->reopt_enable);
488 assert(scip->reopt != NULL);
489
490 SCIP_CALL( SCIPcheckStage(scip, "SCIPsplitReoptRoot", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
491
492 SCIP_CALL( SCIPreoptSplitRoot(scip->reopt, scip->tree, scip->set, scip->stat, scip->mem->probmem, ncreatedchilds,
493 naddedconss) );
494
495 return SCIP_OKAY;
496 }
497
498 /** remove the stored information about bound changes based in dual information
499 *
500 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
501 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
502 *
503 * @pre This method can be called if @p scip is in one of the following stages:
504 * - \ref SCIP_STAGE_SOLVING
505 * - \ref SCIP_STAGE_SOLVED
506 */
SCIPresetReoptnodeDualcons(SCIP * scip,SCIP_NODE * node)507 SCIP_RETCODE SCIPresetReoptnodeDualcons(
508 SCIP* scip, /**< SCIP data structure */
509 SCIP_NODE* node /**< node of the search tree */
510 )
511 {
512 assert(scip != NULL);
513 assert(scip->set->reopt_enable);
514 assert(node != NULL);
515
516 SCIP_CALL( SCIPcheckStage(scip, "SCIPresetReoptnodeDualcons", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
517
518 SCIP_CALL( SCIPreoptResetDualBndchgs(scip->reopt, node, scip->mem->probmem) );
519
520 return SCIP_OKAY;
521 }
522