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