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_copy.c
17  * @ingroup OTHER_CFILES
18  * @brief  public methods for problem copies
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 "blockmemshell/memory.h"
37 #include "scip/benders.h"
38 #include "scip/clock.h"
39 #include "scip/conflictstore.h"
40 #include "scip/cons.h"
41 #include "scip/cons_linear.h"
42 #include "scip/dcmp.h"
43 #include "scip/debug.h"
44 #include "scip/primal.h"
45 #include "scip/prob.h"
46 #include "scip/pub_cons.h"
47 #include "scip/pub_cutpool.h"
48 #include "scip/pub_implics.h"
49 #include "scip/pub_lp.h"
50 #include "scip/pub_message.h"
51 #include "scip/pub_misc.h"
52 #include "scip/pub_sol.h"
53 #include "scip/pub_var.h"
54 #include "scip/scip_branch.h"
55 #include "scip/scip_cons.h"
56 #include "scip/scip_copy.h"
57 #include "scip/scip_cut.h"
58 #include "scip/scip_general.h"
59 #include "scip/scip_mem.h"
60 #include "scip/scip_message.h"
61 #include "scip/scip_nodesel.h"
62 #include "scip/scip_numerics.h"
63 #include "scip/scip_param.h"
64 #include "scip/scip_pricer.h"
65 #include "scip/scip_prob.h"
66 #include "scip/scip_sol.h"
67 #include "scip/scip_solve.h"
68 #include "scip/scip_solvingstats.h"
69 #include "scip/scip_timing.h"
70 #include "scip/scip_var.h"
71 #include "scip/set.h"
72 #include "scip/stat.h"
73 #include "scip/struct_mem.h"
74 #include "scip/struct_scip.h"
75 #include "scip/struct_set.h"
76 #include "scip/struct_stat.h"
77 #include "scip/struct_var.h"
78 #include "scip/syncstore.h"
79 #include "scip/var.h"
80 
81 /** returns true if the @p cut matches the selection criterium for copying */
82 static
takeCut(SCIP * scip,SCIP_CUT * cut,char cutsel)83 SCIP_Bool takeCut(
84    SCIP*                 scip,               /**< SCIP data structure */
85    SCIP_CUT*             cut,                /**< a cut */
86    char                  cutsel              /**< cut selection for sub SCIPs  ('a'ge, activity 'q'uotient) */
87    )
88 {
89    SCIP_Bool takecut;
90 
91    assert(cut != NULL);
92 
93    if( !SCIProwIsInLP(SCIPcutGetRow(cut)) )
94       return FALSE;
95 
96    switch( cutsel )
97    {
98    case 'a':
99       takecut = (SCIPcutGetAge(cut) == 0);
100       break;
101    case 'q':
102       takecut = (SCIPcutGetLPActivityQuot(cut) >= scip->set->sepa_minactivityquot);
103       break;
104    default:
105       SCIPerrorMessage("unknown cut selection strategy %c, must be either 'a' or 'q'\n", cutsel);
106       SCIPABORT();
107       takecut = FALSE;  /*lint !e527*/
108       break;
109    }
110 
111    return takecut;
112 }
113 
114 /** copy active and tight cuts from one SCIP instance to linear constraints of another SCIP instance */
115 static
copyCuts(SCIP * sourcescip,SCIP * targetscip,SCIP_CUT ** cuts,int ncuts,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,int * ncutsadded)116 SCIP_RETCODE copyCuts(
117    SCIP*                 sourcescip,         /**< source SCIP data structure */
118    SCIP*                 targetscip,         /**< target SCIP data structure */
119    SCIP_CUT**            cuts,               /**< cuts to copy */
120    int                   ncuts,              /**< number of cuts to copy */
121    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
122                                               *   target variables, or NULL */
123    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
124                                               *   target constraints, or NULL */
125    SCIP_Bool             global,             /**< create a global or a local copy? */
126    int*                  ncutsadded          /**< pointer to store number of copied cuts */
127    )
128 {
129    int c;
130 
131    assert(sourcescip != NULL);
132    assert(targetscip != NULL);
133    assert(cuts != NULL || ncuts == 0);
134    assert(ncutsadded != NULL);
135 
136    for( c = 0; c < ncuts; ++c )
137    {
138       SCIP_ROW* row;
139       SCIP_Bool takecut;
140 
141       assert( cuts[c] != NULL ); /*lint !e613*/
142       row = SCIPcutGetRow(cuts[c]); /*lint !e613*/
143       assert(!SCIProwIsLocal(row));
144       assert(!SCIProwIsModifiable(row));
145 
146       /* in case of a restart, convert the cuts with a good LP activity quotient; in other cases, e.g., when heuristics
147        * copy cuts into subscips, take only currently active ones
148        */
149       if( sourcescip == targetscip )
150       {
151          assert( SCIPisInRestart(sourcescip) );
152          takecut = takeCut(sourcescip, cuts[c], sourcescip->set->sepa_cutselrestart); /*lint !e613*/
153       }
154       else
155          takecut = takeCut(sourcescip, cuts[c], sourcescip->set->sepa_cutselsubscip); /*lint !e613*/
156 
157       /* create a linear constraint out of the cut */
158       if( takecut )
159       {
160          char name[SCIP_MAXSTRLEN];
161          SCIP_CONS* cons;
162          SCIP_COL** cols;
163          SCIP_VAR** vars;
164          int ncols;
165          int i;
166 
167          cols = SCIProwGetCols(row);
168          ncols = SCIProwGetNNonz(row);
169 
170          /* get all variables of the row */
171          SCIP_CALL( SCIPallocBufferArray(targetscip, &vars, ncols) );
172          for( i = 0; i < ncols && takecut; ++i )
173          {
174             vars[i] = SCIPcolGetVar(cols[i]);
175             takecut = !SCIPvarIsRelaxationOnly(vars[i]);
176          }
177 
178          /* discard cut if it contains a variable which is invalid after a restart */
179          if( !takecut )
180          {
181             /* free temporary memory */
182             SCIPfreeBufferArray(targetscip, &vars);
183             continue;
184          }
185 
186          /* get corresponding variables in targetscip if necessary */
187          if( sourcescip != targetscip )
188          {
189             SCIP_Bool success;
190 
191             for( i = 0; i < ncols; ++i )
192             {
193                SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, vars[i], &vars[i], varmap, consmap, global, &success) );
194 
195                if( !success )
196                {
197                   SCIPdebugMsg(sourcescip, "Converting cuts to constraints failed.\n");
198 
199                   /* free temporary memory */
200                   SCIPfreeBufferArray(targetscip, &vars);
201                   return SCIP_OKAY;
202                }
203             }
204          }
205 
206          (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d", SCIProwGetName(row), SCIPgetNRuns(sourcescip));
207          SCIP_CALL( SCIPcreateConsLinear(targetscip, &cons, name, ncols, vars, SCIProwGetVals(row),
208                SCIProwGetLhs(row) - SCIProwGetConstant(row), SCIProwGetRhs(row) - SCIProwGetConstant(row),
209                TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) );
210          SCIP_CALL( SCIPaddCons(targetscip, cons) );
211 
212          SCIPdebugMsg(sourcescip, "Converted cut <%s> to constraint <%s>.\n", SCIProwGetName(row), SCIPconsGetName(cons));
213          SCIPdebugPrintCons(targetscip, cons, NULL);
214          SCIP_CALL( SCIPreleaseCons(targetscip, &cons) );
215 
216          /* free temporary memory */
217          SCIPfreeBufferArray(targetscip, &vars);
218 
219          ++(*ncutsadded);
220       }
221    }
222 
223    return SCIP_OKAY;
224 }
225 
226 /** copies plugins from sourcescip to targetscip; in case that a constraint handler which does not need constraints
227  *  cannot be copied, valid will return FALSE. All plugins can declare that, if their copy process failed, the
228  *  copied SCIP instance might not represent the same problem semantics as the original.
229  *  Note that in this case dual reductions might be invalid.
230  *
231  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
232  *        Also, 'passmessagehdlr' should be set to FALSE.
233  *
234  *  @note Do not change the source SCIP environment during the copying process
235  *
236  *  @note This method does not copy Benders' plugins. To this end, the method SCIPcopyBenders() must be called
237  *        separately.
238  *
239  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
240  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
241  *
242  *  @pre This method can be called if sourcescip is in one of the following stages:
243  *       - \ref SCIP_STAGE_PROBLEM
244  *       - \ref SCIP_STAGE_TRANSFORMED
245  *       - \ref SCIP_STAGE_INITPRESOLVE
246  *       - \ref SCIP_STAGE_PRESOLVING
247  *       - \ref SCIP_STAGE_EXITPRESOLVE
248  *       - \ref SCIP_STAGE_PRESOLVED
249  *       - \ref SCIP_STAGE_INITSOLVE
250  *       - \ref SCIP_STAGE_SOLVING
251  *       - \ref SCIP_STAGE_SOLVED
252  *
253  *  @pre This method can be called if targetscip is in one of the following stages:
254  *       - \ref SCIP_STAGE_INIT
255  *       - \ref SCIP_STAGE_FREE
256  *
257  *  @post After calling this method targetscip reaches one of the following stages depending on if and when the solution
258  *        process was interrupted:
259  *       - \ref SCIP_STAGE_PROBLEM
260  *
261  *  @note sourcescip stage does not get changed
262  *
263  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
264  */
SCIPcopyPlugins(SCIP * sourcescip,SCIP * targetscip,SCIP_Bool copyreaders,SCIP_Bool copypricers,SCIP_Bool copyconshdlrs,SCIP_Bool copyconflicthdlrs,SCIP_Bool copypresolvers,SCIP_Bool copyrelaxators,SCIP_Bool copyseparators,SCIP_Bool copypropagators,SCIP_Bool copyheuristics,SCIP_Bool copyeventhdlrs,SCIP_Bool copynodeselectors,SCIP_Bool copybranchrules,SCIP_Bool copydisplays,SCIP_Bool copydialogs,SCIP_Bool copytables,SCIP_Bool copynlpis,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)265 SCIP_RETCODE SCIPcopyPlugins(
266    SCIP*                 sourcescip,         /**< source SCIP data structure */
267    SCIP*                 targetscip,         /**< target SCIP data structure */
268    SCIP_Bool             copyreaders,        /**< should the file readers be copied */
269    SCIP_Bool             copypricers,        /**< should the variable pricers be copied */
270    SCIP_Bool             copyconshdlrs,      /**< should the constraint handlers be copied */
271    SCIP_Bool             copyconflicthdlrs,  /**< should the conflict handlers be copied */
272    SCIP_Bool             copypresolvers,     /**< should the presolvers be copied */
273    SCIP_Bool             copyrelaxators,     /**< should the relaxation handlers be copied */
274    SCIP_Bool             copyseparators,     /**< should the separators be copied */
275    SCIP_Bool             copypropagators,    /**< should the propagators be copied */
276    SCIP_Bool             copyheuristics,     /**< should the heuristics be copied */
277    SCIP_Bool             copyeventhdlrs,     /**< should the event handlers be copied */
278    SCIP_Bool             copynodeselectors,  /**< should the node selectors be copied */
279    SCIP_Bool             copybranchrules,    /**< should the branchrules be copied */
280    SCIP_Bool             copydisplays,       /**< should the display columns be copied */
281    SCIP_Bool             copydialogs,        /**< should the dialogs be copied */
282    SCIP_Bool             copytables,         /**< should the statistics tables be copied */
283    SCIP_Bool             copynlpis,          /**< should the NLPIs be copied */
284    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
285    SCIP_Bool*            valid               /**< pointer to store whether plugins, in particular all constraint
286                                               *   handlers which do not need constraints were validly copied */
287    )
288 {
289    assert(sourcescip != NULL);
290    assert(targetscip != NULL);
291    assert(sourcescip->set != NULL);
292    assert(targetscip->set != NULL);
293 
294    /* check stages for both, the source and the target SCIP data structure */
295    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyPlugins", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
296    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyPlugins", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
297 
298    /* passes the message handler of the source SCIP to the target SCIP, also if NULL */
299    if( passmessagehdlr )
300    {
301       SCIP_CALL( SCIPsetMessagehdlr(targetscip, SCIPgetMessagehdlr(sourcescip)) );
302    }
303 
304    SCIP_CALL( SCIPsetCopyPlugins(sourcescip->set, targetscip->set,
305          copyreaders, copypricers, copyconshdlrs, copyconflicthdlrs, copypresolvers, copyrelaxators, copyseparators, copypropagators,
306          copyheuristics, copyeventhdlrs, copynodeselectors, copybranchrules, copydisplays, copydialogs, copytables, copynlpis, valid) );
307 
308    return SCIP_OKAY;
309 }
310 
311 /** copies all Benders' decomposition plugins
312  *
313  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
314  *  @note the 'threadsafe' parameter should only be set to TRUE if you are absolutely certain that the source and target
315  *        SCIP instances will be solved in parallel. The usual case is to set this to FALSE, since thread safety
316  *        typically incurs a performance cost.
317  *
318  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
319  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
320  *
321  *  @pre This method can be called if sourcescip is in one of the following stages:
322  *       - \ref SCIP_STAGE_PROBLEM
323  *       - \ref SCIP_STAGE_TRANSFORMED
324  *       - \ref SCIP_STAGE_INITPRESOLVE
325  *       - \ref SCIP_STAGE_PRESOLVING
326  *       - \ref SCIP_STAGE_EXITPRESOLVE
327  *       - \ref SCIP_STAGE_PRESOLVED
328  *       - \ref SCIP_STAGE_INITSOLVE
329  *       - \ref SCIP_STAGE_SOLVING
330  *       - \ref SCIP_STAGE_SOLVED
331  *
332  *  @pre This method can be called if targetscip is in one of the following stages:
333  *       - \ref SCIP_STAGE_INIT
334  *       - \ref SCIP_STAGE_FREE
335  *       - \ref SCIP_STAGE_PROBLEM
336  *
337  *  @post After calling this method targetscip reaches one of the following stages depending on if and when the solution
338  *        process was interrupted:
339  *       - \ref SCIP_STAGE_PROBLEM
340  *
341  *  @note sourcescip stage does not get changed
342  *
343  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
344  */
SCIPcopyBenders(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_Bool threadsafe,SCIP_Bool * valid)345 SCIP_RETCODE SCIPcopyBenders(
346    SCIP*                 sourcescip,         /**< source SCIP data structure */
347    SCIP*                 targetscip,         /**< target SCIP data structure */
348    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
349                                               *   target variables; if NULL the transfer of cuts is not possible */
350    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
351                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
352    SCIP_Bool*            valid               /**< pointer to store whether all plugins were validly copied */
353    )
354 {
355    /* TODO: If the Benders' decomposition is not copied, then cons_benders needs to be deactivated. */
356    SCIP_Bool copybendersvalid;
357    int p;
358 
359    assert(sourcescip != NULL);
360    assert(targetscip != NULL);
361    assert(sourcescip != targetscip);
362    assert(sourcescip->set != NULL);
363    assert(targetscip->set != NULL);
364    assert(valid != NULL);
365 
366    /* check stages for both, the source and the target SCIP data structure */
367    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyBenders", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
368    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyBenders", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
369 
370    *valid = TRUE;
371 
372    if( sourcescip->set->benders != NULL )
373    {
374       for( p = sourcescip->set->nbenders - 1; p >= 0; --p )
375       {
376          copybendersvalid = FALSE;
377          SCIP_CALL( SCIPbendersCopyInclude(sourcescip->set->benders[p], sourcescip->set, targetscip->set, varmap,
378                threadsafe, &copybendersvalid) );
379          *valid = *valid && copybendersvalid;
380       }
381    }
382 
383    return SCIP_OKAY;
384 }
385 
386 /** create a problem by copying the problem data of the source SCIP */
387 static
copyProb(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool original,SCIP_Bool global,const char * name)388 SCIP_RETCODE copyProb(
389    SCIP*                 sourcescip,         /**< source SCIP data structure */
390    SCIP*                 targetscip,         /**< target SCIP data structure */
391    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
392                                               *   target variables, or NULL */
393    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
394                                               *   target constraints, or NULL  */
395    SCIP_Bool             original,           /**< should the original problem be copied? */
396    SCIP_Bool             global,             /**< create a global or a local copy? (set to TRUE for original copy) */
397    const char*           name                /**< problem name of target */
398    )
399 {
400    SCIP_PROB* sourceprob;
401    SCIP_HASHMAP* localvarmap;
402    SCIP_HASHMAP* localconsmap;
403    SCIP_Bool uselocalvarmap;
404    SCIP_Bool uselocalconsmap;
405 
406    assert(sourcescip != NULL);
407    assert(targetscip != NULL);
408    assert(!original || global);
409    assert(original || SCIPisTransformed(sourcescip));
410 
411    /* free old problem */
412    SCIP_CALL( SCIPfreeProb(targetscip) );
413    assert(targetscip->set->stage == SCIP_STAGE_INIT);
414 
415    uselocalvarmap = (varmap == NULL);
416    uselocalconsmap = (consmap == NULL);
417 
418    if( uselocalvarmap )
419    {
420       /* create the variable mapping hash map */
421       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
422    }
423    else
424       localvarmap = varmap;
425 
426    if( uselocalconsmap )
427    {
428       /* create the constraint mapping hash map */
429       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
430    }
431    else
432       localconsmap = consmap;
433 
434    /* switch stage to PROBLEM */
435    targetscip->set->stage = SCIP_STAGE_PROBLEM;
436 
437    if( original )
438       sourceprob = sourcescip->origprob;
439    else
440       sourceprob = sourcescip->transprob;
441 
442    /* create the statistics data structure */
443    SCIP_CALL( SCIPstatCreate(&targetscip->stat, targetscip->mem->probmem, targetscip->set, targetscip->transprob, targetscip->origprob, targetscip->messagehdlr) );
444    targetscip->stat->subscipdepth = sourcescip->stat->subscipdepth + 1;
445 
446    /* create the problem by copying the source problem */
447    SCIP_CALL( SCIPprobCopy(&targetscip->origprob, targetscip->mem->probmem, targetscip->set, name, sourcescip, sourceprob, localvarmap, localconsmap, global) );
448 
449    /* creating the solution candidates storage */
450    /**@todo copy solution of source SCIP as candidates for the target SCIP */
451    SCIP_CALL( SCIPprimalCreate(&targetscip->origprimal) );
452 
453    /* create conflict store to store conflict constraints */
454    SCIP_CALL( SCIPconflictstoreCreate(&targetscip->conflictstore, targetscip->set) );
455 
456    SCIP_CALL( SCIPdecompstoreCreate(&targetscip->decompstore, SCIPblkmem(targetscip), SCIP_DECOMPSTORE_CAPA) );
457 
458    if( uselocalvarmap )
459    {
460       /* free hash map */
461       SCIPhashmapFree(&localvarmap);
462    }
463 
464    if( uselocalconsmap )
465    {
466       /* free hash map */
467       SCIPhashmapFree(&localconsmap);
468    }
469 
470    return SCIP_OKAY;
471 }
472 
473 
474 /** create a problem by copying the problem data of the source SCIP
475  *
476  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
477  *  @note Do not change the source SCIP environment during the copying process
478  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
479  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
480  *
481  *  @pre This method can be called if sourcescip is in one of the following stages:
482  *       - \ref SCIP_STAGE_PROBLEM
483  *       - \ref SCIP_STAGE_TRANSFORMED
484  *       - \ref SCIP_STAGE_INITPRESOLVE
485  *       - \ref SCIP_STAGE_PRESOLVING
486  *       - \ref SCIP_STAGE_EXITPRESOLVE
487  *       - \ref SCIP_STAGE_PRESOLVED
488  *       - \ref SCIP_STAGE_INITSOLVE
489  *       - \ref SCIP_STAGE_SOLVING
490  *       - \ref SCIP_STAGE_SOLVED
491  *
492  *  @pre This method can be called if targetscip is in one of the following stages:
493  *       - \ref SCIP_STAGE_INIT
494  *       - \ref SCIP_STAGE_PROBLEM
495  *       - \ref SCIP_STAGE_TRANSFORMED
496  *       - \ref SCIP_STAGE_INITPRESOLVE
497  *       - \ref SCIP_STAGE_PRESOLVING
498  *       - \ref SCIP_STAGE_EXITPRESOLVE
499  *       - \ref SCIP_STAGE_PRESOLVED
500  *       - \ref SCIP_STAGE_INITSOLVE
501  *       - \ref SCIP_STAGE_SOLVING
502  *       - \ref SCIP_STAGE_SOLVED
503  *       - \ref SCIP_STAGE_FREE
504  *
505  *  @post After calling this method targetscip reaches one of the following stages depending on if and when the solution
506  *        process was interrupted:
507  *       - \ref SCIP_STAGE_PROBLEM
508  *
509  *  @note sourcescip stage does not get changed
510  *
511  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
512  */
SCIPcopyProb(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,const char * name)513 SCIP_RETCODE SCIPcopyProb(
514    SCIP*                 sourcescip,         /**< source SCIP data structure */
515    SCIP*                 targetscip,         /**< target SCIP data structure */
516    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
517                                               *   target variables, or NULL */
518    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
519                                               *   target constraints, or NULL */
520    SCIP_Bool             global,             /**< create a global or a local copy? */
521    const char*           name                /**< problem name of target */
522    )
523 {
524    assert(sourcescip != NULL);
525    assert(targetscip != NULL);
526 
527    /* check stages for both, the source and the target SCIP data structure */
528    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyProb", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
529    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyProb", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE) );
530 
531    SCIP_CALL( copyProb(sourcescip, targetscip, varmap, consmap, FALSE, global, name) );
532 
533    return SCIP_OKAY;
534 }
535 
536 /** create a problem by copying the original problem data of the source SCIP
537  *
538  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
539  *  @note Do not change the source SCIP environment during the copying process
540  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
541  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
542  *
543  *  @pre This method can be called if sourcescip is in one of the following stages:
544  *       - \ref SCIP_STAGE_PROBLEM
545  *       - \ref SCIP_STAGE_TRANSFORMED
546  *       - \ref SCIP_STAGE_INITPRESOLVE
547  *       - \ref SCIP_STAGE_PRESOLVING
548  *       - \ref SCIP_STAGE_EXITPRESOLVE
549  *       - \ref SCIP_STAGE_PRESOLVED
550  *       - \ref SCIP_STAGE_INITSOLVE
551  *       - \ref SCIP_STAGE_SOLVING
552  *       - \ref SCIP_STAGE_SOLVED
553  *
554  *  @pre This method can be called if targetscip is in one of the following stages:
555  *       - \ref SCIP_STAGE_INIT
556  *       - \ref SCIP_STAGE_FREE
557  *
558  *  @post After calling this method targetscip reaches one of the following stages depending on if and when the solution
559  *        process was interrupted:
560  *       - \ref SCIP_STAGE_PROBLEM
561  *
562  *  @note sourcescip stage does not get changed
563  *
564  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
565  */
SCIPcopyOrigProb(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * name)566 SCIP_RETCODE SCIPcopyOrigProb(
567    SCIP*                 sourcescip,         /**< source SCIP data structure */
568    SCIP*                 targetscip,         /**< target SCIP data structure */
569    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
570                                               *   target variables, or NULL */
571    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
572                                               *   target constraints, or NULL  */
573    const char*           name                /**< problem name of target */
574    )
575 {
576    assert(sourcescip != NULL);
577    assert(targetscip != NULL);
578 
579    /* check stages for both, the source and the target SCIP data structure */
580    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyOrigProb", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
581    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyOrigProb", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
582 
583    SCIP_CALL( copyProb(sourcescip, targetscip, varmap, consmap, TRUE, TRUE, name) );
584 
585    /* set the correct objective sense; necessary if we maximize in the original problem */
586    SCIP_CALL( SCIPsetObjsense(targetscip, SCIPgetObjsense(sourcescip)) );
587 
588    /* set the objective offset */
589    SCIP_CALL( SCIPaddOrigObjoffset(targetscip, SCIPgetOrigObjoffset(sourcescip)) );
590 
591    return SCIP_OKAY;
592 }
593 
594 /** enables constraint compression.
595  *
596  *  If constraint compression is enabled, fixed variables will be treated as constants
597  *  by all constraints that are copied after calling this method.
598  *
599  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
600  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
601  *
602  *  @pre This method can be called if scip is in one of the following stages:
603  *       - \ref SCIP_STAGE_PROBLEM
604  *
605  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
606  */
SCIPenableConsCompression(SCIP * scip)607 SCIP_RETCODE SCIPenableConsCompression(
608    SCIP*                 scip                /**< source SCIP data structure */
609    )
610 {
611    assert(scip != NULL);
612    assert(scip->origprob != NULL);
613 
614    /* check stage */
615    SCIP_CALL( SCIPcheckStage(scip, "SCIPenableConsCompression", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
616 
617    /* enable problem compression */
618    SCIPprobEnableConsCompression(scip->origprob);
619 
620    return SCIP_OKAY;
621 }
622 
623 /** is constraint compression enabled?
624  *
625  *  If constraint compression is enabled, fixed variables can be treated as constants
626  *  by all constraints that are copied after calling this method.
627  *
628  *  @return TRUE if problem constraint compression is enabled, otherwise FALSE
629  *
630  *  @pre This method can be called if scip is in one of the following stages:
631   *      - \ref SCIP_STAGE_PROBLEM
632   *      - \ref SCIP_STAGE_TRANSFORMING
633  *       - \ref SCIP_STAGE_TRANSFORMED
634  *       - \ref SCIP_STAGE_INITPRESOLVE
635  *       - \ref SCIP_STAGE_PRESOLVING
636  *       - \ref SCIP_STAGE_EXITPRESOLVE
637  *       - \ref SCIP_STAGE_PRESOLVED
638  *       - \ref SCIP_STAGE_INITSOLVE
639  *       - \ref SCIP_STAGE_SOLVING
640  *       - \ref SCIP_STAGE_SOLVED
641  *       - \ref SCIP_STAGE_EXITSOLVE
642  *       - \ref SCIP_STAGE_FREETRANS
643  *
644  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
645  */
SCIPisConsCompressionEnabled(SCIP * scip)646 SCIP_Bool SCIPisConsCompressionEnabled(
647    SCIP*                 scip                /**< source SCIP data structure */
648    )
649 {
650    assert(scip != NULL);
651    assert(scip->origprob != NULL);
652 
653    /* check stage */
654    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisConsCompressionEnabled", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
655 
656    /* is problem compression enabled */
657    return SCIPprobIsConsCompressionEnabled(scip->origprob) && SCIPgetStage(scip) == SCIP_STAGE_PROBLEM;
658 }
659 
660 /** returns copy of the source variable; if there already is a copy of the source variable in the variable hash map,
661  *  it is just returned as target variable; otherwise, if the variables it not marked as relaxation-only, a new variable
662  *  will be created and added to the target SCIP; this created variable is added to the variable hash map and returned as target variable;
663  *  relaxation-only variables are not copied and FALSE is returned in *success
664  *
665  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
666  *  @note Do not change the source SCIP environment during the copying process
667  *  @note if a new variable was created, this variable will be added to the target-SCIP, but it is not captured
668  *
669  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
670  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
671  *
672  *  @pre This method can be called if sourcescip is in one of the following stages:
673  *       - \ref SCIP_STAGE_PROBLEM
674  *       - \ref SCIP_STAGE_TRANSFORMED
675  *       - \ref SCIP_STAGE_INITPRESOLVE
676  *       - \ref SCIP_STAGE_PRESOLVING
677  *       - \ref SCIP_STAGE_EXITPRESOLVE
678  *       - \ref SCIP_STAGE_PRESOLVED
679  *       - \ref SCIP_STAGE_INITSOLVE
680  *       - \ref SCIP_STAGE_SOLVING
681  *       - \ref SCIP_STAGE_SOLVED
682  *
683  *  @pre This method can be called if targetscip is in one of the following stages:
684  *       - \ref SCIP_STAGE_PROBLEM
685  *       - \ref SCIP_STAGE_TRANSFORMED
686  *       - \ref SCIP_STAGE_INITPRESOLVE
687  *       - \ref SCIP_STAGE_PRESOLVING
688  *       - \ref SCIP_STAGE_EXITPRESOLVE
689  *       - \ref SCIP_STAGE_SOLVING
690  *
691  *  @note targetscip stage does not get changed
692  *
693  *  @note sourcescip stage does not get changed
694  *
695  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
696  */
SCIPgetVarCopy(SCIP * sourcescip,SCIP * targetscip,SCIP_VAR * sourcevar,SCIP_VAR ** targetvar,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,SCIP_Bool * success)697 SCIP_RETCODE SCIPgetVarCopy(
698    SCIP*                 sourcescip,         /**< source SCIP data structure */
699    SCIP*                 targetscip,         /**< target SCIP data structure */
700    SCIP_VAR*             sourcevar,          /**< source variable */
701    SCIP_VAR**            targetvar,          /**< pointer to store the target variable */
702    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables to the corresponding
703                                               *   target variables, or NULL */
704    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
705                                               *   target constraints, or NULL */
706    SCIP_Bool             global,             /**< should global or local bounds be used? */
707    SCIP_Bool*            success             /**< pointer to store whether the copying was successful or not */
708    )
709 {
710    SCIP_HASHMAP* localvarmap;
711    SCIP_HASHMAP* localconsmap;
712    SCIP_VAR* var;
713    SCIP_Bool uselocalvarmap;
714    SCIP_Bool uselocalconsmap;
715 
716    assert(sourcescip != NULL);
717    assert(targetscip != NULL);
718    assert(sourcevar != NULL);
719    assert(targetvar != NULL);
720    assert(sourcevar->scip == sourcescip);
721 
722    /* check stages for both, the source and the target SCIP data structure */
723    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPgetVarCopy", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
724    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPgetVarCopy", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
725 
726    uselocalvarmap = (varmap == NULL);
727    uselocalconsmap = (consmap == NULL);
728    *success = TRUE;
729 
730    /* try to retrieve copied variable from hashmap */
731    if( !uselocalvarmap )
732    {
733       *targetvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, sourcevar);
734       if( *targetvar != NULL )
735          return SCIP_OKAY;
736    }
737 
738    /* reject copying of relaxation-only variables */
739    if( SCIPvarIsRelaxationOnly(sourcevar) )
740    {
741       *success = FALSE;
742       *targetvar = NULL;
743    }
744 
745    /* if the target SCIP is already in solving stage we currently are not copying the variable!
746     * this has to be done because we cannot simply add variables to SCIP during solving and thereby enlarge the search
747     * space.
748     * unlike column generation we cannot assume here that the variable could be implicitly set to zero in all prior
749     * computations
750     */
751    if( SCIPgetStage(targetscip) > SCIP_STAGE_PROBLEM )
752    {
753       *success = FALSE;
754       *targetvar = NULL;
755 
756       return SCIP_OKAY;
757    }
758 
759    /* create the variable mapping hash map */
760    if( uselocalvarmap )
761    {
762       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
763    }
764    else
765       localvarmap = varmap;
766 
767    if( uselocalconsmap )
768    {
769       /* create the constraint mapping hash map */
770       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
771    }
772    else
773       localconsmap = consmap;
774 
775    /* if variable does not exist yet in target SCIP, create it */
776    switch( SCIPvarGetStatus(sourcevar) )
777    {
778    case SCIP_VARSTATUS_ORIGINAL:
779    case SCIP_VARSTATUS_COLUMN:
780    case SCIP_VARSTATUS_LOOSE:
781    case SCIP_VARSTATUS_FIXED:
782       SCIP_CALL( SCIPvarCopy(&var, targetscip->mem->probmem, targetscip->set, targetscip->stat,
783             sourcescip, sourcevar, localvarmap, localconsmap, global) );
784       break;
785 
786    case SCIP_VARSTATUS_AGGREGATED:
787    {
788       SCIP_CONS* cons;
789       char name[SCIP_MAXSTRLEN];
790 
791       SCIP_VAR* sourceaggrvar;
792       SCIP_VAR* targetaggrvar;
793       SCIP_Real aggrcoef;
794       SCIP_Real constant;
795 
796       /* get aggregation data */
797       sourceaggrvar = SCIPvarGetAggrVar(sourcevar);
798       aggrcoef = SCIPvarGetAggrScalar(sourcevar);
799       constant = SCIPvarGetAggrConstant(sourcevar);
800 
801       /* get copy of the aggregation variable */
802       SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, sourceaggrvar, &targetaggrvar, localvarmap, localconsmap, global, success) );
803       assert(*success);
804 
805       /* create copy of the aggregated variable */
806       SCIP_CALL( SCIPvarCopy(&var, targetscip->mem->probmem, targetscip->set, targetscip->stat,
807             sourcescip, sourcevar, localvarmap, localconsmap, global) );
808 
809       (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_aggr", SCIPvarGetName(sourcevar));
810 
811       /* add aggregation x = a*y + c as linear constraint x - a*y = c */
812       SCIP_CALL( SCIPcreateConsLinear(targetscip, &cons, name, 0, NULL, NULL, constant,
813             constant, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
814       SCIP_CALL( SCIPaddCoefLinear(targetscip, cons, var, 1.0) );
815       SCIP_CALL( SCIPaddCoefLinear(targetscip, cons, targetaggrvar, -aggrcoef) );
816 
817       SCIP_CALL( SCIPaddCons(targetscip, cons) );
818       SCIP_CALL( SCIPreleaseCons(targetscip, &cons) );
819 
820       break;
821    }
822    case SCIP_VARSTATUS_MULTAGGR:
823    {
824       SCIP_CONS* cons;
825       char name[SCIP_MAXSTRLEN];
826 
827       SCIP_VAR** sourceaggrvars;
828       SCIP_VAR** targetaggrvars;
829       SCIP_Real* aggrcoefs;
830       SCIP_Real constant;
831 
832       int naggrvars;
833       int i;
834 
835       /* get the active representation */
836       SCIP_CALL( SCIPflattenVarAggregationGraph(sourcescip, sourcevar) );
837 
838       /* get multi-aggregation data */
839       naggrvars = SCIPvarGetMultaggrNVars(sourcevar);
840       sourceaggrvars = SCIPvarGetMultaggrVars(sourcevar);
841       aggrcoefs = SCIPvarGetMultaggrScalars(sourcevar);
842       constant = SCIPvarGetMultaggrConstant(sourcevar);
843 
844       SCIP_CALL( SCIPallocBufferArray(targetscip, &targetaggrvars, naggrvars) );
845 
846       /* get copies of the active variables of the multi-aggregation */
847       for( i = 0; i < naggrvars; ++i )
848       {
849          SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, sourceaggrvars[i], &targetaggrvars[i], localvarmap, localconsmap, global, success) );
850          assert(*success);
851       }
852 
853       /* create copy of the multi-aggregated variable */
854       SCIP_CALL( SCIPvarCopy(&var, targetscip->mem->probmem, targetscip->set, targetscip->stat,
855             sourcescip, sourcevar, localvarmap, localconsmap, global) );
856 
857       (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_multaggr", SCIPvarGetName(sourcevar));
858 
859       /* add multi-aggregation x = a^T y + c as linear constraint a^T y - x = -c */
860       SCIP_CALL( SCIPcreateConsLinear(targetscip, &cons, name, naggrvars, targetaggrvars, aggrcoefs, -constant,
861             -constant, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
862       SCIP_CALL( SCIPaddCoefLinear(targetscip, cons, var, -1.0) );
863       SCIP_CALL( SCIPaddCons(targetscip, cons) );
864       SCIP_CALL( SCIPreleaseCons(targetscip, &cons) );
865 
866       SCIPfreeBufferArray(targetscip, &targetaggrvars);
867 
868       break;
869    }
870    case SCIP_VARSTATUS_NEGATED:
871    {
872       SCIP_VAR* sourcenegatedvar;
873       SCIP_VAR* targetnegatedvar;
874 
875       /* get negated source variable */
876       sourcenegatedvar = SCIPvarGetNegationVar(sourcevar);
877       assert(sourcenegatedvar != NULL);
878       assert(SCIPvarGetStatus(sourcenegatedvar) != SCIP_VARSTATUS_NEGATED);
879 
880       /* get copy of negated source variable */
881       SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, sourcenegatedvar, &targetnegatedvar, localvarmap, localconsmap, global, success) );
882       assert(*success);
883       assert(SCIPvarGetStatus(targetnegatedvar) != SCIP_VARSTATUS_NEGATED);
884 
885       /* get negation of copied negated source variable, this is the target variable */
886       SCIP_CALL( SCIPgetNegatedVar(targetscip, targetnegatedvar, targetvar) );
887       assert(SCIPvarGetStatus(*targetvar) == SCIP_VARSTATUS_NEGATED);
888 
889       /* free local hash maps if necessary */
890       if( uselocalvarmap )
891          SCIPhashmapFree(&localvarmap);
892 
893       if( uselocalconsmap )
894          SCIPhashmapFree(&localconsmap);
895 
896       /* we have to return right away, to avoid adding the negated variable to the problem since the "not negated"
897        * variable was already added */
898       return SCIP_OKAY;
899    }
900    default:
901       /* note that this is in an internal SCIP error since the variable status is only handled by the core */
902       SCIPerrorMessage("unknown variable status\n");
903       SCIPABORT();
904       return SCIP_ERROR; /*lint !e527*/
905    }
906 
907    /* add the (new) target variable to the target problem */
908    SCIP_CALL( SCIPaddVar(targetscip, var) );
909 
910    *targetvar = var;
911 
912    /* remove the variable capture which was done due to the creation of the variable */
913    SCIP_CALL( SCIPreleaseVar(targetscip, &var) );
914 
915    /* free local hash maps if necessary */
916    if( uselocalvarmap )
917       SCIPhashmapFree(&localvarmap);
918 
919    if( uselocalconsmap )
920       SCIPhashmapFree(&localconsmap);
921 
922    return SCIP_OKAY;
923 }
924 
925 /** copies all original or active variables from source-SCIP except those that are marked as relaxation-only, fixed, or aggregated
926  *  and adds these variable to the target-SCIP
927  *
928  *  the mapping between these variables are stored in the variable hashmap
929  *  target-SCIP has to be in problem creation stage
930  */
931 static
copyVars(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars,SCIP_Bool original,SCIP_Bool global)932 SCIP_RETCODE copyVars(
933    SCIP*                 sourcescip,         /**< source SCIP data structure */
934    SCIP*                 targetscip,         /**< target SCIP data structure */
935    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables to the corresponding
936                                               *   target variables, or NULL */
937    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
938                                               *   target constraints, or NULL */
939    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
940    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
941    int                   nfixedvars,         /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
942    SCIP_Bool             original,           /**< should original variables be copied? */
943    SCIP_Bool             global              /**< should global or local bounds be used? (for original=FALSE) */
944    )
945 {
946    SCIP_VAR** sourcevars;
947    SCIP_HASHMAP* localvarmap;
948    SCIP_HASHMAP* localconsmap;
949    SCIP_Bool uselocalvarmap;
950    SCIP_Bool uselocalconsmap;
951    int nsourcevars;
952 #ifndef NDEBUG
953    int nrelaxonlybinvars = 0;
954    int nrelaxonlyintvars = 0;
955    int nrelaxonlyimplvars = 0;
956    int nrelaxonlycontvars = 0;
957 #endif
958    int i;
959 
960    assert(sourcescip != NULL);
961    assert(targetscip != NULL);
962    assert(nfixedvars == 0 || fixedvars != NULL);
963    assert(nfixedvars == 0 || fixedvals != NULL);
964 
965    if( original )
966    {
967       /* get original variables of the source SCIP */
968       SCIP_CALL( SCIPgetOrigVarsData(sourcescip, &sourcevars, &nsourcevars, NULL, NULL, NULL, NULL) );
969    }
970    else
971    {
972       /* get active variables of the source SCIP */
973       SCIP_CALL( SCIPgetVarsData(sourcescip, &sourcevars, &nsourcevars, NULL, NULL, NULL, NULL) );
974    }
975 
976    uselocalvarmap = (varmap == NULL);
977    uselocalconsmap = (consmap == NULL);
978 
979    if( uselocalvarmap )
980    {
981       /* create the variable mapping hash map */
982       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
983    }
984    else
985       localvarmap = varmap;
986 
987    if( uselocalconsmap )
988    {
989       /* create the constraint mapping hash map */
990       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
991    }
992    else
993       localconsmap = consmap;
994 
995    /* create the variables of the target SCIP */
996    for( i = 0; i < nsourcevars; ++i )
997    {
998       SCIP_Bool success;
999       SCIP_VAR* targetvar;
1000 
1001       if( SCIPvarIsRelaxationOnly(sourcevars[i]) )
1002       {
1003 #ifndef NDEBUG
1004          switch( SCIPvarGetType(sourcevars[i]) )
1005          {
1006          case SCIP_VARTYPE_BINARY:
1007             nrelaxonlybinvars++;
1008             break;
1009          case SCIP_VARTYPE_INTEGER:
1010             nrelaxonlyintvars++;
1011             break;
1012          case SCIP_VARTYPE_IMPLINT:
1013             nrelaxonlyimplvars++;
1014             break;
1015          case SCIP_VARTYPE_CONTINUOUS:
1016             nrelaxonlycontvars++;
1017             break;
1018          default:
1019             SCIPerrorMessage("unknown variable type\n");
1020             return SCIP_INVALIDDATA;
1021          }
1022 #endif
1023          continue;
1024       }
1025 
1026       /* copy variable and add this copy to the target SCIP if the copying was valid */
1027       SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, sourcevars[i], &targetvar, localvarmap, localconsmap, global, &success) );
1028       assert(success);
1029       assert(targetvar != NULL);
1030    }
1031 
1032    /* fix the variables that should be fixed right away */
1033    for( i = 0; i < nfixedvars; ++i )
1034    {
1035       SCIP_VAR* targetvar;
1036       SCIP_Bool infeasible;
1037       SCIP_Bool fixed;
1038 
1039       if( SCIPvarIsRelaxationOnly(sourcevars[i]) )
1040          continue;
1041 
1042       /* retrieve target variable as image of the source variable */
1043       targetvar = (SCIP_VAR*) SCIPhashmapGetImage(localvarmap, (void *)fixedvars[i]);
1044       assert(targetvar != NULL);
1045 
1046       /* fix the variable to the specified value */
1047       infeasible = fixed = FALSE;
1048       SCIP_CALL( SCIPfixVar(targetscip, targetvar, fixedvals[i], &infeasible, &fixed) );
1049 
1050       assert(!infeasible);
1051       assert(fixed);
1052    }
1053 
1054    /* integer variables that are fixed to zero or one or have bounds [0,1] will be converted to binaries */
1055 #ifndef NDEBUG
1056    if( original )
1057    {
1058       /* TODO : account for integers converted to binaries
1059       assert(SCIPgetNOrigBinVars(sourcescip) == SCIPgetNOrigBinVars(targetscip));
1060       assert(SCIPgetNOrigIntVars(sourcescip) == SCIPgetNOrigIntVars(targetscip));
1061       assert(SCIPgetNOrigImplVars(sourcescip) == SCIPgetNOrigImplVars(targetscip));
1062       assert(SCIPgetNOrigContVars(sourcescip) == SCIPgetNOrigContVars(targetscip));
1063       */
1064    }
1065    else
1066    {
1067       SCIP_VAR** sourcefixedvars;
1068       int nsourcefixedvars;
1069       int nfixedbinvars;
1070       int nfixedintvars;
1071       int nfixedimplvars;
1072       int nfixedcontvars;
1073 
1074       sourcefixedvars = SCIPgetFixedVars(sourcescip);
1075       nsourcefixedvars = SCIPgetNFixedVars(sourcescip);
1076       nfixedbinvars = 0;
1077       nfixedintvars = 0;
1078       nfixedimplvars = 0;
1079       nfixedcontvars = 0;
1080 
1081       /* count number of fixed variables for all variable types */
1082       for( i = 0; i < nsourcefixedvars; ++i )
1083       {
1084          switch( SCIPvarGetType(sourcefixedvars[i]) )
1085          {
1086          case SCIP_VARTYPE_BINARY:
1087             nfixedbinvars++;
1088             break;
1089          case SCIP_VARTYPE_INTEGER:
1090             nfixedintvars++;
1091             break;
1092          case SCIP_VARTYPE_IMPLINT:
1093             nfixedimplvars++;
1094             break;
1095          case SCIP_VARTYPE_CONTINUOUS:
1096             nfixedcontvars++;
1097             break;
1098          default:
1099             SCIPerrorMessage("unknown variable type\n");
1100             return SCIP_INVALIDDATA;
1101          }
1102       }
1103       assert(nsourcefixedvars == nfixedbinvars + nfixedintvars + nfixedimplvars + nfixedcontvars);
1104       assert(SCIPgetNBinVars(sourcescip) <= SCIPgetNBinVars(targetscip) + nrelaxonlybinvars);
1105       assert(SCIPgetNIntVars(sourcescip) + SCIPgetNBinVars(sourcescip) <= SCIPgetNIntVars(targetscip) + nrelaxonlyintvars + SCIPgetNBinVars(targetscip) + nrelaxonlybinvars);
1106       assert(SCIPgetNIntVars(targetscip) + nrelaxonlyintvars + SCIPgetNBinVars(targetscip) + nrelaxonlybinvars <= SCIPgetNIntVars(sourcescip) + SCIPgetNBinVars(sourcescip) + nfixedbinvars + nfixedintvars );
1107       assert(SCIPgetNImplVars(sourcescip) <= SCIPgetNImplVars(targetscip) + nrelaxonlyimplvars);
1108       assert(SCIPgetNImplVars(targetscip) + nrelaxonlyimplvars <= SCIPgetNImplVars(sourcescip) + nfixedimplvars);
1109       assert(SCIPgetNContVars(sourcescip) <= SCIPgetNContVars(targetscip) + nrelaxonlycontvars);
1110       assert(SCIPgetNContVars(targetscip) + nrelaxonlycontvars <= SCIPgetNContVars(sourcescip) + nfixedcontvars);
1111    }
1112 #endif
1113 
1114    if( uselocalvarmap )
1115    {
1116       /* free hash map */
1117       SCIPhashmapFree(&localvarmap);
1118    }
1119 
1120    if( uselocalconsmap )
1121    {
1122       /* free hash map */
1123       SCIPhashmapFree(&localconsmap);
1124    }
1125 
1126    return SCIP_OKAY;
1127 }
1128 
1129 /** Copies all active (thus unfixed) variables from source-SCIP, except those that are marked as relaxation only,
1130  *  and adds these variable to the target-SCIP.
1131  *
1132  *  The mapping between these variables are stored in the variable hashmap.
1133  *
1134  *  The target-SCIP has to be in problem creation stage.
1135  *
1136  *  @note the variables are added to the target-SCIP but not captured
1137  *
1138  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
1139  *  @note Do not change the source SCIP environment during the copying process
1140  *
1141  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1142  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1143  *
1144  *  @pre This method can be called if sourcescip is in one of the following stages:
1145  *       - \ref SCIP_STAGE_PROBLEM
1146  *       - \ref SCIP_STAGE_TRANSFORMED
1147  *       - \ref SCIP_STAGE_INITPRESOLVE
1148  *       - \ref SCIP_STAGE_PRESOLVING
1149  *       - \ref SCIP_STAGE_EXITPRESOLVE
1150  *       - \ref SCIP_STAGE_PRESOLVED
1151  *       - \ref SCIP_STAGE_INITSOLVE
1152  *       - \ref SCIP_STAGE_SOLVING
1153  *       - \ref SCIP_STAGE_SOLVED
1154  *
1155  *  @pre This method can be called if targetscip is in one of the following stages:
1156  *       - \ref SCIP_STAGE_PROBLEM
1157  *
1158  *  @note sourcescip stage does not get changed
1159  *
1160  *  @note targetscip stage does not get changed
1161  *
1162  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
1163  */
SCIPcopyVars(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars,SCIP_Bool global)1164 SCIP_RETCODE SCIPcopyVars(
1165    SCIP*                 sourcescip,         /**< source SCIP data structure */
1166    SCIP*                 targetscip,         /**< target SCIP data structure */
1167    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables to the corresponding
1168                                               *   target variables, or NULL */
1169    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
1170                                               *   target constraints, or NULL */
1171    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
1172    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
1173    int                   nfixedvars,         /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
1174    SCIP_Bool             global              /**< should global or local bounds be used? */
1175    )
1176 {
1177    assert(sourcescip != NULL);
1178    assert(targetscip != NULL);
1179 
1180    /* check stages for both, the source and the target SCIP data structure */
1181    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1182    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyVars", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1183 
1184    SCIP_CALL( copyVars(sourcescip, targetscip, varmap, consmap, fixedvars, fixedvals, nfixedvars, FALSE, global) );
1185 
1186    return SCIP_OKAY;
1187 }
1188 
1189 /** copies all original variables from source-SCIP and adds these variable to the target-SCIP; the mapping between these
1190  *  variables are stored in the variable hashmap, target-SCIP has to be in problem creation stage, fixed and aggregated
1191  *  variables do not get copied
1192  *
1193  *  @note the variables are added to the target-SCIP but not captured
1194  *
1195  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
1196  *  @note Do not change the source SCIP environment during the copying process
1197  *
1198  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1199  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1200  *
1201  *  @pre This method can be called if sourcescip is in one of the following stages:
1202  *       - \ref SCIP_STAGE_PROBLEM
1203  *       - \ref SCIP_STAGE_TRANSFORMED
1204  *       - \ref SCIP_STAGE_INITPRESOLVE
1205  *       - \ref SCIP_STAGE_PRESOLVING
1206  *       - \ref SCIP_STAGE_EXITPRESOLVE
1207  *       - \ref SCIP_STAGE_PRESOLVED
1208  *       - \ref SCIP_STAGE_INITSOLVE
1209  *       - \ref SCIP_STAGE_SOLVING
1210  *       - \ref SCIP_STAGE_SOLVED
1211  *
1212  *  @pre This method can be called if targetscip is in one of the following stages:
1213  *       - \ref SCIP_STAGE_PROBLEM
1214  *
1215  *  @note sourcescip stage does not get changed
1216  *
1217  *  @note targetscip stage does not get changed
1218  *
1219  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
1220  */
SCIPcopyOrigVars(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars)1221 SCIP_RETCODE SCIPcopyOrigVars(
1222    SCIP*                 sourcescip,         /**< source SCIP data structure */
1223    SCIP*                 targetscip,         /**< target SCIP data structure */
1224    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables to the corresponding
1225                                               *   target variables, or NULL */
1226    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
1227                                               *   target constraints, or NULL */
1228    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
1229    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
1230    int                   nfixedvars          /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
1231    )
1232 {
1233    assert(sourcescip != NULL);
1234    assert(targetscip != NULL);
1235 
1236    /* check stages for both, the source and the target SCIP data structure */
1237    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyOrigVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1238    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyOrigVars", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1239 
1240    SCIP_CALL( copyVars(sourcescip, targetscip, varmap, consmap, fixedvars, fixedvals, nfixedvars, TRUE, TRUE) );
1241 
1242    return SCIP_OKAY;
1243 }
1244 
1245 /** merges the histories of variables from a source SCIP into a target SCIP. The two data structures should point to
1246  *  different SCIP instances.
1247  *
1248  *  @note the notion of source and target is inverted here; \p sourcescip usually denotes a copied SCIP instance, whereas
1249  *        \p targetscip denotes the original instance
1250  */
SCIPmergeVariableStatistics(SCIP * sourcescip,SCIP * targetscip,SCIP_VAR ** sourcevars,SCIP_VAR ** targetvars,int nvars)1251 SCIP_RETCODE SCIPmergeVariableStatistics(
1252    SCIP*                 sourcescip,         /**< source SCIP data structure */
1253    SCIP*                 targetscip,         /**< target SCIP data structure */
1254    SCIP_VAR**            sourcevars,         /**< source variables for history merge, NULL entries are ignored */
1255    SCIP_VAR**            targetvars,         /**< target variables for history merge, NULL entries are ignored */
1256    int                   nvars               /**< number of variables in both variable arrays */
1257    )
1258 {
1259    int i;
1260 
1261    /* check if target scip has been set to allow merging variable statistics */
1262    if( !targetscip->set->history_allowmerge )
1263       return SCIP_OKAY;
1264 
1265    assert(nvars == 0 || (sourcevars != NULL && targetvars != NULL));
1266    assert(sourcescip != targetscip);
1267 
1268    /* we do not want to copy statistics from a scip that has not really started solving */
1269    if( SCIPgetStage(sourcescip) < SCIP_STAGE_SOLVING )
1270       return SCIP_OKAY;
1271 
1272    /* if the transformation of the source was subject to scaling, the history information cannot be just copied */
1273    if( !SCIPsetIsEQ(targetscip->set, 1.0, SCIPgetOrigObjscale(sourcescip))
1274       || !SCIPsetIsEQ(targetscip->set, 0.0, SCIPgetOrigObjoffset(sourcescip)) )
1275       return SCIP_OKAY;
1276 
1277    /* merge histories of the targetSCIP-variables to the SCIP variables. */
1278    for( i = 0; i < nvars; ++i )
1279    {
1280       SCIP_VARSTATUS sourcevarstatus;
1281 
1282       if( sourcevars[i] == NULL || targetvars[i] == NULL )
1283          continue;
1284 
1285       assert(sourcevars[i]->scip == sourcescip);
1286       assert(targetvars[i]->scip == targetscip);
1287 
1288       sourcevarstatus = SCIPvarGetStatus(sourcevars[i]);
1289 
1290       /* depending on the variable status, we use either the transformed variable history or the history of the col itself */
1291       switch( sourcevarstatus )
1292       {
1293       case SCIP_VARSTATUS_ORIGINAL:
1294          assert(NULL != SCIPvarGetTransVar(sourcevars[i]));
1295          SCIPvarMergeHistories(targetvars[i], SCIPvarGetTransVar(sourcevars[i]), targetscip->stat);
1296          break;
1297       case SCIP_VARSTATUS_COLUMN:
1298          SCIPvarMergeHistories(targetvars[i], sourcevars[i], targetscip->stat);
1299          break;
1300       default:
1301          /* other variable status are currently not supported for the merging */
1302          break;
1303       }  /*lint !e788*/
1304    }
1305 
1306    return SCIP_OKAY;
1307 }
1308 
1309 /** provides values of a solution from a subscip according to the variable in the main scip
1310  *
1311  * Given a subscip solution, fills an array with solution values, matching the variables given by SCIPgetVars().
1312  * Variables that are relaxation-only in the master SCIP are set to 0 or the bound closest to 0. Such variables
1313  * are represented as NULL entry in the \p subvars array.
1314  */
1315 static
translateSubSol(SCIP * scip,SCIP * subscip,SCIP_SOL * subsol,SCIP_VAR ** subvars,SCIP_Real * solvals)1316 SCIP_RETCODE translateSubSol(
1317    SCIP*                 scip,               /**< SCIP data structure of the original problem */
1318    SCIP*                 subscip,            /**< SCIP data structure of the subproblem */
1319    SCIP_SOL*             subsol,             /**< solution of the subproblem */
1320    SCIP_VAR**            subvars,            /**< the variables from the subproblem in the same order as the main \p scip */
1321    SCIP_Real*            solvals             /**< array where to set values taken from subsol, must have length at least SCIPgetNVars(scip) */
1322    )
1323 {
1324    SCIP_VAR** vars;
1325    int nvars;
1326    int i;
1327 
1328    assert(scip != NULL);
1329    assert(subscip != NULL);
1330    assert(subsol != NULL);
1331    assert(subvars != NULL);
1332    assert(solvals != NULL);
1333 
1334    /* copy the solution */
1335    SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1336 
1337    /* copy the solution */
1338    for( i = 0; i < nvars; ++i )
1339    {
1340       if( subvars[i] != NULL )
1341          solvals[i] = SCIPgetSolVal(subscip, subsol, subvars[i]);
1342       else
1343          solvals[i] = MIN(MAX(0.0, SCIPvarGetLbLocal(vars[i])), SCIPvarGetUbLocal(vars[i]));  /*lint !e666*/
1344    }
1345 
1346    return SCIP_OKAY;
1347 }
1348 
1349 /** translates a solution from a subscip to the main scip
1350  *
1351  * Variables that are relaxation-only in the master SCIP are set to 0 or the bound closest to 0. Such variables
1352  * are represented as NULL entry in the \p subvars array.
1353  *
1354  * @note This method allocates a new solution of the main \p scip that needs to be freed by the user.
1355  */
SCIPtranslateSubSol(SCIP * scip,SCIP * subscip,SCIP_SOL * subsol,SCIP_HEUR * heur,SCIP_VAR ** subvars,SCIP_SOL ** newsol)1356 SCIP_RETCODE SCIPtranslateSubSol(
1357    SCIP*                 scip,               /**< SCIP data structure of the original problem */
1358    SCIP*                 subscip,            /**< SCIP data structure of the subproblem */
1359    SCIP_SOL*             subsol,             /**< solution of the subproblem */
1360    SCIP_HEUR*            heur,               /**< heuristic that found the solution */
1361    SCIP_VAR**            subvars,            /**< the variables from the subproblem in the same order as the main \p scip */
1362    SCIP_SOL**            newsol              /**< buffer to store pointer to created solution in main SCIP */
1363    )
1364 {
1365    SCIP_VAR** vars;
1366    int nvars;
1367    SCIP_Real* subsolvals;
1368 
1369    assert(scip != NULL);
1370    assert(subscip != NULL);
1371    assert(subsol != NULL);
1372    assert(subvars != NULL);
1373    assert(newsol != NULL);
1374 
1375    SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1376 
1377    SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
1378 
1379    /* get the solution values */
1380    SCIP_CALL( translateSubSol(scip, subscip, subsol, subvars, subsolvals) );
1381 
1382    /* create new solution for the original problem */
1383    SCIP_CALL( SCIPcreateSol(scip, newsol, heur) );
1384    SCIP_CALL( SCIPsetSolVals(scip, *newsol, nvars, vars, subsolvals) );
1385 
1386    SCIPfreeBufferArray(scip, &subsolvals);
1387 
1388    return SCIP_OKAY;
1389 }
1390 
1391 /** checks the solutions from the subscip and adds the first one that is found feasible to the master SCIP
1392  *
1393  * Variables that are relaxation-only in the master SCIP are set to 0 or the bound closest to 0. Such variables
1394  * are represented as NULL entry in the \p subvars array.
1395  */
SCIPtranslateSubSols(SCIP * scip,SCIP * subscip,SCIP_HEUR * heur,SCIP_VAR ** subvars,SCIP_Bool * success,int * solindex)1396 SCIP_RETCODE SCIPtranslateSubSols(
1397    SCIP*                 scip,               /**< the SCIP data structure */
1398    SCIP*                 subscip,            /**< SCIP data structure of the subproblem */
1399    SCIP_HEUR*            heur,               /**< heuristic that found the solution */
1400    SCIP_VAR**            subvars,            /**< the variables from the subproblem in the same order as the main \p scip */
1401    SCIP_Bool*            success,            /**< pointer to store, whether new solution was found */
1402    int*                  solindex            /**< pointer to store solution index of stored solution, or NULL if not of interest */
1403    )
1404 {
1405    SCIP_SOL* newsol = NULL;
1406    SCIP_SOL** subsols;
1407    int nsubsols;
1408    int i;
1409    SCIP_VAR** vars;
1410    int nvars;
1411    SCIP_Real* solvals;
1412 
1413    assert(scip != NULL);
1414    assert(subscip != NULL);
1415    assert(heur != NULL);
1416    assert(subvars != NULL);
1417    assert(success != NULL);
1418 
1419    *success = FALSE;
1420 
1421    /* check, whether a solution was found */
1422    if( SCIPgetNSols(subscip) == 0 )
1423       return SCIP_OKAY;
1424 
1425    SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1426 
1427    SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nvars) );
1428 
1429    /* check, whether a solution was found;
1430     * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
1431     */
1432    nsubsols = SCIPgetNSols(subscip);
1433    subsols = SCIPgetSols(subscip);
1434    for( i = 0; i < nsubsols; ++i )
1435    {
1436       /* better do not copy unbounded solutions as this will mess up the SCIP solution status */
1437       if( SCIPisInfinity(scip, -SCIPgetSolOrigObj(subscip, subsols[i])) )
1438          continue;
1439 
1440       if( newsol == NULL )
1441       {
1442          SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
1443          if( solindex != NULL )
1444             *solindex = SCIPsolGetIndex(newsol);
1445       }
1446 
1447       /* put values from subsol into newsol */
1448       SCIP_CALL( translateSubSol(scip, subscip, subsols[i], subvars, solvals) );
1449       SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, solvals) );
1450 
1451       /* check whether feasible */
1452       SCIP_CALL( SCIPcheckSol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
1453       if( *success )
1454       {
1455          /* if feasible, then there is a good chance that we can add it
1456           * we use SCIPaddSolFree to make sure that newsol is indeed added and not some copy, so *solindex stays valid
1457           */
1458          SCIP_CALL( SCIPaddSolFree(scip, &newsol, success) );
1459          if( *success )
1460          {
1461             SCIPdebugMsg(scip, "-> accepted solution of value %g\n", SCIPgetSolOrigObj(subscip, subsols[i]));
1462             break;
1463          }
1464          else
1465          {
1466             /* continue with next subsol
1467              * as we have used addSolFree, newsol should be NULL now
1468              */
1469             assert(newsol == NULL);
1470          }
1471       }
1472    }
1473 
1474    SCIPfreeBufferArray(scip, &solvals);
1475 
1476    if( newsol != NULL )
1477    {
1478       SCIP_CALL( SCIPfreeSol(scip, &newsol) );
1479    }
1480 
1481    return SCIP_OKAY;
1482 }
1483 
1484 /** returns copy of the source constraint; if there already is a copy of the source constraint in the constraint hash
1485  *  map, it is just returned as target constraint; elsewise a new constraint will be created; this created constraint is
1486  *  added to the constraint hash map and returned as target constraint; the variable map is used to map the variables of
1487  *  the source SCIP to the variables of the target SCIP
1488  *
1489  *  @warning If a constraint is marked to be checked for feasibility but not to be enforced, a LP or pseudo solution may
1490  *           be declared feasible even if it violates this particular constraint.  This constellation should only be
1491  *           used, if no LP or pseudo solution can violate the constraint -- e.g. if a local constraint is redundant due
1492  *           to the variable's local bounds.
1493  *
1494  *  @note The constraint is not added to the target SCIP. You can check whether a constraint is added by calling
1495  *        SCIPconsIsAdded(). (If you mix SCIPgetConsCopy() with SCIPcopyConss() you should pay attention to what you add
1496  *        explicitly and what is already added.)
1497  *
1498  *  @note The constraint is always captured, either during the creation of the copy or after finding the copy of the
1499  *        constraint in the constraint hash map
1500  *
1501  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
1502  *  @note Do not change the source SCIP environment during the copying process
1503  *
1504  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1505  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1506  *
1507  *  @pre This method can be called if sourcescip is in one of the following stages:
1508  *       - \ref SCIP_STAGE_PROBLEM
1509  *       - \ref SCIP_STAGE_TRANSFORMED
1510  *       - \ref SCIP_STAGE_INITPRESOLVE
1511  *       - \ref SCIP_STAGE_PRESOLVING
1512  *       - \ref SCIP_STAGE_EXITPRESOLVE
1513  *       - \ref SCIP_STAGE_PRESOLVED
1514  *       - \ref SCIP_STAGE_INITSOLVE
1515  *       - \ref SCIP_STAGE_SOLVING
1516  *       - \ref SCIP_STAGE_SOLVED
1517  *
1518  *  @pre This method can be called if targetscip is in one of the following stages:
1519  *       - \ref SCIP_STAGE_PROBLEM
1520  *       - \ref SCIP_STAGE_TRANSFORMING
1521  *       - \ref SCIP_STAGE_INITPRESOLVE
1522  *       - \ref SCIP_STAGE_PRESOLVING
1523  *       - \ref SCIP_STAGE_EXITPRESOLVE
1524  *       - \ref SCIP_STAGE_PRESOLVED
1525  *       - \ref SCIP_STAGE_SOLVING
1526  *       - \ref SCIP_STAGE_EXITSOLVE
1527  *
1528  *  @note sourcescip stage does not get changed
1529  *
1530  *  @note targetscip stage does not get changed
1531  *
1532  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
1533  */
SCIPgetConsCopy(SCIP * sourcescip,SCIP * targetscip,SCIP_CONS * sourcecons,SCIP_CONS ** targetcons,SCIP_CONSHDLR * sourceconshdlr,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * name,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_Bool global,SCIP_Bool * valid)1534 SCIP_RETCODE SCIPgetConsCopy(
1535    SCIP*                 sourcescip,         /**< source SCIP data structure */
1536    SCIP*                 targetscip,         /**< target SCIP data structure */
1537    SCIP_CONS*            sourcecons,         /**< source constraint of the source SCIP */
1538    SCIP_CONS**           targetcons,         /**< pointer to store the created target constraint */
1539    SCIP_CONSHDLR*        sourceconshdlr,     /**< source constraint handler for this constraint */
1540    SCIP_HASHMAP*         varmap,             /**< a SCIP_HASHMAP mapping variables of the source SCIP to the corresponding
1541                                               *   variables of the target SCIP, or NULL */
1542    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
1543                                               *   target constraints, or NULL */
1544    const char*           name,               /**< name of constraint, or NULL if the name of the source constraint should be used */
1545    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? */
1546    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing? */
1547    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing? */
1548    SCIP_Bool             check,              /**< should the constraint be checked for feasibility? */
1549    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing? */
1550    SCIP_Bool             local,              /**< is constraint only valid locally? */
1551    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)? */
1552    SCIP_Bool             dynamic,            /**< is constraint subject to aging? */
1553    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup? */
1554    SCIP_Bool             stickingatnode,     /**< should the constraint always be kept at the node where it was added, even
1555                                               *   if it may be moved to a more global node? */
1556    SCIP_Bool             global,             /**< create a global or a local copy? */
1557    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid or not */
1558    )
1559 {
1560    SCIP_HASHMAP* localvarmap;
1561    SCIP_HASHMAP* localconsmap;
1562    SCIP_Bool uselocalvarmap;
1563    SCIP_Bool uselocalconsmap;
1564 
1565    assert(targetcons != NULL);
1566    assert(sourceconshdlr != NULL);
1567 
1568    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPgetConsCopy", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1569    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPgetConsCopy", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE) );
1570 
1571    uselocalvarmap = (varmap == NULL);
1572    uselocalconsmap = (consmap == NULL);
1573 
1574    /* a variables map and a constraint map is needed to avoid infinite recursion */
1575    if( uselocalvarmap )
1576    {
1577       /* create the variable mapping hash map */
1578       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
1579    }
1580    else
1581       localvarmap = varmap;
1582 
1583    *targetcons = NULL;
1584    if( uselocalconsmap )
1585    {
1586       /* create local constraint mapping hash map */
1587       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
1588    }
1589    else
1590    {
1591       /* use global map and try to retrieve copied constraint */
1592       localconsmap = consmap;
1593       *targetcons = (SCIP_CONS*) SCIPhashmapGetImage(localconsmap, sourcecons);
1594    }
1595 
1596    if( *targetcons != NULL )
1597    {
1598       /* if found capture existing copy of the constraint */
1599       SCIP_CALL( SCIPcaptureCons(targetscip, *targetcons) );
1600       *valid = TRUE;
1601    }
1602    else
1603    {
1604       /* otherwise create a copy of the constraint */
1605       SCIP_CALL( SCIPconsCopy(targetcons, targetscip->set, name, sourcescip, sourceconshdlr, sourcecons, localvarmap, localconsmap,
1606             initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
1607 
1608       /* it is possible for the constraint handler to declare the copy valid although no target constraint was created */
1609       assert(*targetcons == NULL || *valid);
1610 
1611       /* if a target constraint was created */
1612       if( *targetcons != NULL && !uselocalconsmap )
1613       {
1614          /* insert constraint into mapping between source SCIP and the target SCIP */
1615          SCIP_CALL( SCIPhashmapInsert(consmap, sourcecons, *targetcons) );
1616       }
1617    }
1618 
1619    /* free locally allocated hash maps */
1620    if( uselocalvarmap )
1621    {
1622       SCIPhashmapFree(&localvarmap);
1623    }
1624 
1625    if( uselocalconsmap )
1626    {
1627       SCIPhashmapFree(&localconsmap);
1628    }
1629 
1630    return SCIP_OKAY;
1631 }
1632 
1633 /** copies constraints from the source-SCIP and adds these to the target-SCIP; for mapping the
1634  *  variables between the source and the target SCIP a hash map can be given; if the variable hash
1635  *  map is NULL or necessary variable mapping is missing, the required variables are created in the
1636  *  target-SCIP and added to the hash map, if not NULL; all variables which are created are added to
1637  *  the target-SCIP but not (user) captured; if the constraint hash map is not NULL the mapping
1638  *  between the constraints of the source and target-SCIP is stored
1639  *
1640  *  *valid is set to TRUE iff all constraints that are marked as checked or enforced were copied successfully.
1641  *  If other constraints could not be copied, *valid can still be set to TRUE.
1642  *
1643  *  @note the constraints are added to the target-SCIP but are not (user) captured in the target SCIP. (If you mix
1644  *        SCIPgetConsCopy() with SCIPcopyConss() you should pay attention to what you add explicitly and what is already
1645  *        added.) You can check whether a constraint is added by calling SCIPconsIsAdded().
1646  *
1647  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
1648  *  @note Do not change the source SCIP environment during the copying process
1649  *
1650  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1651  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1652  *
1653  *  @pre This method can be called if sourcescip is in one of the following stages:
1654  *       - \ref SCIP_STAGE_PROBLEM
1655  *       - \ref SCIP_STAGE_TRANSFORMED
1656  *       - \ref SCIP_STAGE_INITPRESOLVE
1657  *       - \ref SCIP_STAGE_PRESOLVING
1658  *       - \ref SCIP_STAGE_EXITPRESOLVE
1659  *       - \ref SCIP_STAGE_PRESOLVED
1660  *       - \ref SCIP_STAGE_INITSOLVE
1661  *       - \ref SCIP_STAGE_SOLVING
1662  *       - \ref SCIP_STAGE_SOLVED
1663  *
1664  *  @pre This method can be called if targetscip is in one of the following stages:
1665  *       - \ref SCIP_STAGE_PROBLEM
1666  *
1667  *  @note sourcescip stage does not get changed
1668  *
1669  *  @note targetscip stage does not get changed
1670  *
1671  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
1672  */
SCIPcopyConss(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,SCIP_Bool enablepricing,SCIP_Bool * valid)1673 SCIP_RETCODE SCIPcopyConss(
1674    SCIP*                 sourcescip,         /**< source SCIP data structure */
1675    SCIP*                 targetscip,         /**< target SCIP data structure */
1676    SCIP_HASHMAP*         varmap,             /**< a SCIP_HASHMAP mapping variables of the source SCIP to the corresponding
1677                                               *   variables of the target SCIP, or NULL */
1678    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
1679                                               *   target constraints, or NULL */
1680    SCIP_Bool             global,             /**< create a global or a local copy? */
1681    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance?
1682                                               *   If TRUE, the modifiable flag of constraints will be copied. */
1683    SCIP_Bool*            valid               /**< pointer to store whether all checked or enforced constraints were validly copied */
1684    )
1685 {
1686    SCIP_CONSHDLR** sourceconshdlrs;
1687    SCIP_HASHMAP* localvarmap;
1688    SCIP_HASHMAP* localconsmap;
1689    SCIP_Bool uselocalvarmap;
1690    SCIP_Bool uselocalconsmap;
1691    int nsourceconshdlrs;
1692    int i;
1693 
1694    assert(sourcescip != NULL);
1695    assert(targetscip != NULL);
1696    assert(valid      != NULL);
1697 
1698    /* check stages for both, the source and the target SCIP data structure */
1699    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1700    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyConss", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1701 
1702    /* check if we locally need to create a variable or constraint hash map */
1703    uselocalvarmap = (varmap == NULL);
1704    uselocalconsmap = (consmap == NULL);
1705 
1706    if( uselocalvarmap )
1707    {
1708       /* create the variable mapping hash map */
1709       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
1710    }
1711    else
1712       localvarmap = varmap;
1713 
1714    if( uselocalconsmap )
1715    {
1716       /* create the constraint mapping hash map */
1717       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
1718    }
1719    else
1720       localconsmap = consmap;
1721 
1722    nsourceconshdlrs = SCIPgetNConshdlrs(sourcescip);
1723    sourceconshdlrs = SCIPgetConshdlrs(sourcescip);
1724    assert(nsourceconshdlrs == 0 || sourceconshdlrs != NULL);
1725 
1726    *valid = TRUE;
1727 
1728    /* copy constraints: loop through all (source) constraint handlers */
1729    for( i = 0; i < nsourceconshdlrs; ++i )
1730    {
1731       SCIP_CONS** sourceconss;
1732       SCIP_CONS* targetcons;
1733       int nsourceconss;
1734       int c;
1735 
1736       assert(sourceconshdlrs[i] != NULL);
1737 
1738       /* constraint handlers have to explicitly set the valid pointer to TRUE for every single constraint */
1739 
1740       /* Get all active constraints for copying; this array contains all active constraints;
1741        * constraints are active if they are globally valid and not deleted after presolving OR they
1742        * were locally added during the search and we are currently in a node which belongs to the
1743        * corresponding subtree.
1744        */
1745       nsourceconss = SCIPconshdlrGetNActiveConss(sourceconshdlrs[i]);
1746       sourceconss = SCIPconshdlrGetConss(sourceconshdlrs[i]);
1747 
1748 #ifdef SCIP_DISABLED_CODE
1749       /* @todo using the following might reduce the number of copied constraints - check whether this is better */
1750       /* Get all checked constraints for copying; this included local constraints */
1751       if( !global )
1752       {
1753          nsourceconss = SCIPconshdlrGetNCheckConss(sourceconshdlrs[i]);
1754          sourceconss = SCIPconshdlrGetCheckConss(sourceconshdlrs[i]);
1755       }
1756 #endif
1757 
1758       assert(nsourceconss == 0 || sourceconss != NULL);
1759 
1760       if( nsourceconss > 0 )
1761       {
1762          SCIPdebugMsg(sourcescip, "Attempting to copy %d %s constraints\n", nsourceconss, SCIPconshdlrGetName(sourceconshdlrs[i]));
1763       }
1764 
1765       /* copy all constraints of one constraint handler */
1766       for( c = 0; c < nsourceconss; ++c )
1767       {
1768          SCIP_Bool singlevalid = FALSE;
1769          /* all constraints have to be active */
1770          assert(sourceconss[c] != NULL);
1771          assert(SCIPconsIsActive(sourceconss[c]));
1772          assert(!SCIPconsIsDeleted(sourceconss[c]));
1773 
1774          /* in case of copying the global problem we have to ignore the local constraints which are active */
1775          if( global && SCIPconsIsLocal(sourceconss[c]) )
1776          {
1777             SCIPdebugMsg(sourcescip, "did not copy local constraint <%s> when creating global copy\n", SCIPconsGetName(sourceconss[c]));
1778             continue;
1779          }
1780 
1781          /* use the copy constructor of the constraint handler and creates and captures the constraint if possible */
1782          targetcons = NULL;
1783          SCIP_CALL( SCIPgetConsCopy(sourcescip, targetscip, sourceconss[c], &targetcons, sourceconshdlrs[i], localvarmap, localconsmap, NULL,
1784                SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]),
1785                SCIPconsIsEnforced(sourceconss[c]), SCIPconsIsChecked(sourceconss[c]),
1786                SCIPconsIsPropagated(sourceconss[c]), FALSE, SCIPconsIsModifiable(sourceconss[c]),
1787                SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), FALSE, global, &singlevalid) );
1788 
1789          /* it is possible for a constraint handler to declare the copy valid, although no target constraint was created */
1790          assert(targetcons == NULL || singlevalid);
1791 
1792          /* add the copied constraint to target SCIP if the copying process created a constraint */
1793          if( targetcons != NULL )
1794          {
1795             if( !enablepricing )
1796                SCIPconsSetModifiable(targetcons, FALSE);
1797 
1798             /* add constraint to target SCIP */
1799             SCIP_CALL( SCIPaddCons(targetscip, targetcons) );
1800 
1801             /* add the conflict constraint to the store of targetscip */
1802             if( SCIPconsIsConflict(sourceconss[c]) )
1803             {
1804                /* add the constraint as a conflict to the conflict pool of targetscip */
1805                SCIP_CALL( SCIPconflictstoreAddConflict(targetscip->conflictstore, targetscip->mem->probmem, targetscip->set,
1806                      targetscip->stat, NULL, NULL, targetscip->reopt, targetcons, SCIP_CONFTYPE_UNKNOWN, FALSE, -SCIPinfinity(targetscip)) );
1807             }
1808 
1809             /* release constraint once for the creation capture */
1810             SCIP_CALL( SCIPreleaseCons(targetscip, &targetcons) );
1811          }
1812          else
1813          {
1814             /* if an enforced or checked constraint could not be copied, then the copy is not valid, i.e.,
1815              * the feasible set may be larger; for other constraints, it should be safe if they are omitted
1816              * from the copy
1817              */
1818             if( SCIPconsIsEnforced(sourceconss[c]) || SCIPconsIsChecked(sourceconss[c]) )
1819                *valid = FALSE;
1820             SCIPdebugMsg(sourcescip, "Constraint %s not copied, copy is %svalid\n",
1821                   SCIPconsGetName(sourceconss[c]), *valid ? "" : "not ");
1822          }
1823       }
1824    }
1825 
1826    if( uselocalvarmap )
1827    {
1828       /* free hash map */
1829       SCIPhashmapFree(&localvarmap);
1830    }
1831 
1832    if( uselocalconsmap )
1833    {
1834       /* free hash map */
1835       SCIPhashmapFree(&localconsmap);
1836    }
1837 
1838    return SCIP_OKAY;
1839 }
1840 
1841 /** copies all original constraints from the source-SCIP and adds these to the target-SCIP; for mapping the
1842  *  variables between the source and the target SCIP a hash map can be given; if the variable hash
1843  *  map is NULL or necessary variable mapping is missing, the required variables are created in the
1844  *  target-SCIP and added to the hash map, if not NULL; all variables which are created are added to
1845  *  the target-SCIP but not (user) captured; if the constraint hash map is not NULL the mapping
1846  *  between the constraints of the source and target-SCIP is stored
1847  *
1848  *  @note the constraints are added to the target-SCIP but are not (user) captured in the target SCIP. (If you mix
1849  *        SCIPgetConsCopy() with SCIPcopyConss() you should pay attention to what you add explicitly and what is already
1850  *        added.) You can check whether a constraint is added by calling SCIPconsIsAdded().
1851  *
1852  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
1853  *  @note Do not change the source SCIP environment during the copying process
1854  *
1855  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1856  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1857  *
1858  *  @pre This method can be called if sourcescip is in one of the following stages:
1859  *       - \ref SCIP_STAGE_PROBLEM
1860  *       - \ref SCIP_STAGE_TRANSFORMED
1861  *       - \ref SCIP_STAGE_INITPRESOLVE
1862  *       - \ref SCIP_STAGE_PRESOLVING
1863  *       - \ref SCIP_STAGE_EXITPRESOLVE
1864  *       - \ref SCIP_STAGE_PRESOLVED
1865  *       - \ref SCIP_STAGE_INITSOLVE
1866  *       - \ref SCIP_STAGE_SOLVING
1867  *       - \ref SCIP_STAGE_SOLVED
1868  *
1869  *  @pre This method can be called if targetscip is in one of the following stages:
1870  *       - \ref SCIP_STAGE_PROBLEM
1871  *
1872  *  @note sourcescip stage does not get changed
1873  *
1874  *  @note targetscip stage does not get changed
1875  *
1876  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
1877  */
SCIPcopyOrigConss(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool enablepricing,SCIP_Bool * valid)1878 SCIP_RETCODE SCIPcopyOrigConss(
1879    SCIP*                 sourcescip,         /**< source SCIP data structure */
1880    SCIP*                 targetscip,         /**< target SCIP data structure */
1881    SCIP_HASHMAP*         varmap,             /**< a SCIP_HASHMAP mapping variables of the source SCIP to the corresponding
1882                                               *   variables of the target SCIP, or NULL */
1883    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
1884                                               *   target constraints, or NULL */
1885    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance?
1886                                               *   If TRUE, the modifiable flag of constraints will be copied. */
1887    SCIP_Bool*            valid               /**< pointer to store whether all constraints were validly copied */
1888    )
1889 {
1890    SCIP_CONS** sourceconss;
1891    SCIP_HASHMAP* localvarmap;
1892    SCIP_HASHMAP* localconsmap;
1893    SCIP_Bool uselocalvarmap;
1894    SCIP_Bool uselocalconsmap;
1895    int nsourceconss;
1896    int c;
1897 
1898    assert(sourcescip != NULL);
1899    assert(targetscip != NULL);
1900    assert(valid      != NULL);
1901 
1902    /* check stages for both, the source and the target SCIP data structure */
1903    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyOrigConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1904    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyOrigConss", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1905 
1906    /* check if we locally need to create a variable or constraint hash map */
1907    uselocalvarmap = (varmap == NULL);
1908    uselocalconsmap = (consmap == NULL);
1909 
1910    if( uselocalvarmap )
1911    {
1912       /* create the variable mapping hash map */
1913       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
1914    }
1915    else
1916       localvarmap = varmap;
1917 
1918    if( uselocalconsmap )
1919    {
1920       /* create the constraint mapping hash map */
1921       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
1922    }
1923    else
1924       localconsmap = consmap;
1925 
1926    sourceconss = SCIPgetOrigConss(sourcescip);
1927    nsourceconss = SCIPgetNOrigConss(sourcescip);
1928 
1929    *valid = TRUE;
1930 
1931    SCIPdebugMsg(sourcescip, "Attempting to copy %d original constraints\n", nsourceconss);
1932 
1933    /* copy constraints: loop through all (source) constraint handlers */
1934    for( c = 0; c < nsourceconss; ++c )
1935    {
1936       SCIP_CONS* targetcons;
1937       SCIP_Bool success;
1938 
1939       /* constraint handlers have to explicitly set the success pointer to TRUE */
1940       success = FALSE;
1941 
1942       /* all constraints have to be active */
1943       assert(sourceconss[c] != NULL);
1944       assert(SCIPconsIsOriginal(sourceconss[c]));
1945 
1946       /* use the copy constructor of the constraint handler and creates and captures the constraint if possible */
1947       targetcons = NULL;
1948       SCIP_CALL( SCIPgetConsCopy(sourcescip, targetscip, sourceconss[c], &targetcons, SCIPconsGetHdlr(sourceconss[c]), localvarmap, localconsmap, NULL,
1949             SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]),
1950             SCIPconsIsEnforced(sourceconss[c]), SCIPconsIsChecked(sourceconss[c]),
1951             SCIPconsIsPropagated(sourceconss[c]), FALSE, SCIPconsIsModifiable(sourceconss[c]),
1952             SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), FALSE, TRUE, &success) );
1953 
1954       /* add the copied constraint to target SCIP if the copying process was valid */
1955       if( success )
1956       {
1957          assert(targetcons != NULL);
1958 
1959          if( !enablepricing )
1960             SCIPconsSetModifiable(targetcons, FALSE);
1961 
1962          /* add constraint to target SCIP */
1963          SCIP_CALL( SCIPaddCons(targetscip, targetcons) );
1964 
1965          /* release constraint once for the creation capture */
1966          SCIP_CALL( SCIPreleaseCons(targetscip, &targetcons) );
1967       }
1968       else
1969       {
1970          *valid = FALSE;
1971          SCIPdebugMsg(sourcescip, "failed to copy constraint %s\n", SCIPconsGetName(sourceconss[c]));
1972       }
1973    }
1974 
1975    if( uselocalvarmap )
1976    {
1977       /* free hash map */
1978       SCIPhashmapFree(&localvarmap);
1979    }
1980 
1981    if( uselocalconsmap )
1982    {
1983       /* free hash map */
1984       SCIPhashmapFree(&localconsmap);
1985    }
1986 
1987    return SCIP_OKAY;
1988 }
1989 
1990 
1991 /** convert all active cuts from cutpool to linear constraints
1992  *
1993  *  @note Do not change the source SCIP environment during the copying process
1994  *
1995  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1996  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1997  *
1998  *  @pre This method can be called if SCIP is in one of the following stages:
1999  *       - \ref SCIP_STAGE_PROBLEM
2000  *       - \ref SCIP_STAGE_INITPRESOLVE
2001  *       - \ref SCIP_STAGE_PRESOLVING
2002  *       - \ref SCIP_STAGE_EXITPRESOLVE
2003  *       - \ref SCIP_STAGE_PRESOLVED
2004  *       - \ref SCIP_STAGE_SOLVING
2005  *       - \ref SCIP_STAGE_EXITSOLVE
2006  *
2007  *  @note SCIP stage does not get changed
2008  *
2009  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2010  */
SCIPconvertCutsToConss(SCIP * scip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,int * ncutsadded)2011 SCIP_RETCODE SCIPconvertCutsToConss(
2012    SCIP*                 scip,               /**< SCIP data structure */
2013    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2014                                               *   target variables, or NULL */
2015    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2016                                               *   target constraints, or NULL */
2017    SCIP_Bool             global,             /**< create a global or a local copy? */
2018    int*                  ncutsadded          /**< pointer to store number of added cuts, or NULL */
2019    )
2020 {
2021    assert(scip != NULL);
2022    assert(scip->set != NULL);
2023 
2024    /* check stages for the SCIP data structure */
2025    SCIP_CALL( SCIPcheckStage(scip, "SCIPconvertCutsToConss", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE) );
2026 
2027    /* if we do not have any cuts, nothing can be converted */
2028    if( scip->set->stage < SCIP_STAGE_SOLVING )
2029       return SCIP_OKAY;
2030 
2031    /* create out of all active cuts in cutpool linear constraints in targetscip */
2032    SCIP_CALL( SCIPcopyCuts(scip, scip, varmap, consmap, global, ncutsadded) );
2033 
2034    return SCIP_OKAY;
2035 }
2036 
2037 /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip
2038  *
2039  *  Cuts that contain variables that are marked as relaxation-only are skipped.
2040  *
2041  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2042  *  @note Do not change the source SCIP environment during the copying process
2043  *
2044  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2045  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2046  *
2047  *  @pre This method can be called if sourcescip is in one of the following stages:
2048  *       - \ref SCIP_STAGE_PROBLEM
2049  *       - \ref SCIP_STAGE_TRANSFORMED
2050  *       - \ref SCIP_STAGE_INITPRESOLVE
2051  *       - \ref SCIP_STAGE_PRESOLVING
2052  *       - \ref SCIP_STAGE_EXITPRESOLVE
2053  *       - \ref SCIP_STAGE_PRESOLVED
2054  *       - \ref SCIP_STAGE_SOLVING
2055  *       - \ref SCIP_STAGE_SOLVED
2056  *       - \ref SCIP_STAGE_EXITSOLVE
2057  *
2058  *  @pre This method can be called if targetscip is in one of the following stages:
2059  *       - \ref SCIP_STAGE_PROBLEM
2060  *       - \ref SCIP_STAGE_INITPRESOLVE
2061  *       - \ref SCIP_STAGE_PRESOLVING
2062  *       - \ref SCIP_STAGE_EXITPRESOLVE
2063  *       - \ref SCIP_STAGE_PRESOLVED
2064  *       - \ref SCIP_STAGE_SOLVING
2065  *       - \ref SCIP_STAGE_EXITSOLVE
2066  *
2067  *  @note sourcescip stage does not get changed
2068  *
2069  *  @note targetscip stage does not get changed
2070  *
2071  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2072  */
SCIPcopyCuts(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,int * ncutsadded)2073 SCIP_RETCODE SCIPcopyCuts(
2074    SCIP*                 sourcescip,         /**< source SCIP data structure */
2075    SCIP*                 targetscip,         /**< target SCIP data structure */
2076    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2077                                               *   target variables, or NULL */
2078    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2079                                               *   target constraints, or NULL */
2080    SCIP_Bool             global,             /**< create a global or a local copy? */
2081    int*                  ncutsadded          /**< pointer to store number of copied cuts, or NULL */
2082    )
2083 {
2084    SCIP_CUT** cuts;
2085    int ncuts;
2086    int nlocalcutsadded;
2087 
2088    assert(sourcescip != NULL);
2089    assert(targetscip != NULL);
2090 
2091    /* check stages for both, the source and the target SCIP data structure */
2092    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyCuts", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2093    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyCuts", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE) );
2094 
2095    if ( ncutsadded != NULL )
2096       *ncutsadded = 0;
2097    nlocalcutsadded = 0;
2098 
2099    /* if we do not have any cuts, nothing can be converted */
2100    if( sourcescip->set->stage < SCIP_STAGE_SOLVING )
2101       return SCIP_OKAY;
2102 
2103    if( SCIPfindConshdlr(targetscip, "linear") == NULL )
2104    {
2105       SCIPdebugMsg(sourcescip, "No linear constraint handler available. Cannot convert cuts.\n");
2106       return SCIP_OKAY;
2107    }
2108 
2109    /* convert cut from global cut pool */
2110    cuts = SCIPgetPoolCuts(sourcescip);
2111    ncuts = SCIPgetNPoolCuts(sourcescip);
2112 
2113    SCIP_CALL( copyCuts(sourcescip, targetscip, cuts, ncuts, varmap, consmap, global, &nlocalcutsadded) );
2114 
2115    SCIPdebugMsg(sourcescip, "Converted %d active cuts to constraints.\n", nlocalcutsadded);
2116 
2117    /* convert delayed cuts from global delayed cut pool */
2118    cuts = SCIPgetDelayedPoolCuts(sourcescip);
2119    ncuts = SCIPgetNDelayedPoolCuts(sourcescip);
2120 
2121    SCIP_CALL( copyCuts(sourcescip, targetscip, cuts, ncuts, varmap, consmap, global, &nlocalcutsadded) );
2122 
2123    if( ncutsadded != NULL )
2124       *ncutsadded = nlocalcutsadded;
2125 
2126    SCIPdebugMsg(sourcescip, "Converted %d active cuts to constraints.\n", nlocalcutsadded);
2127 
2128    return SCIP_OKAY;
2129 }
2130 
2131 /** copies all active conflicts from the conflict pool of sourcescip and adds them as linear constraints to targetscip
2132  *
2133  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2134  *  @note Do not change the source SCIP environment during the copying process
2135  *
2136  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2137  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2138  *
2139  *  @pre This method can be called if sourcescip is in one of the following stages:
2140  *       - \ref SCIP_STAGE_PROBLEM
2141  *       - \ref SCIP_STAGE_TRANSFORMED
2142  *       - \ref SCIP_STAGE_INITPRESOLVE
2143  *       - \ref SCIP_STAGE_PRESOLVING
2144  *       - \ref SCIP_STAGE_EXITPRESOLVE
2145  *       - \ref SCIP_STAGE_PRESOLVED
2146  *       - \ref SCIP_STAGE_SOLVING
2147  *       - \ref SCIP_STAGE_SOLVED
2148  *       - \ref SCIP_STAGE_EXITSOLVE
2149  *
2150  *  @pre This method can be called if targetscip is in one of the following stages:
2151  *       - \ref SCIP_STAGE_PROBLEM
2152  *       - \ref SCIP_STAGE_INITPRESOLVE
2153  *       - \ref SCIP_STAGE_PRESOLVING
2154  *       - \ref SCIP_STAGE_EXITPRESOLVE
2155  *       - \ref SCIP_STAGE_PRESOLVED
2156  *       - \ref SCIP_STAGE_SOLVING
2157  *       - \ref SCIP_STAGE_EXITSOLVE
2158  *
2159  *  @note sourcescip stage does not change
2160  *
2161  *  @note targetscip stage does not change
2162  *
2163  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2164  */
SCIPcopyConflicts(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,SCIP_Bool enablepricing,SCIP_Bool * valid)2165 SCIP_RETCODE SCIPcopyConflicts(
2166    SCIP*                 sourcescip,         /**< source SCIP data structure */
2167    SCIP*                 targetscip,         /**< target SCIP data structure */
2168    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2169                                               *   target variables, or NULL */
2170    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2171                                               *   target constraints, or NULL */
2172    SCIP_Bool             global,             /**< create a global or a local copy? */
2173    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance?
2174                                               *   If TRUE, the modifiable flag of constraints will be copied. */
2175    SCIP_Bool*            valid               /**< pointer to store whether all constraints were validly copied */
2176    )
2177 {
2178    SCIP_CONS** sourceconfs;
2179    SCIP_HASHMAP* localvarmap;
2180    SCIP_HASHMAP* localconsmap;
2181    SCIP_Bool uselocalvarmap;
2182    SCIP_Bool uselocalconsmap;
2183    SCIP_Bool success;
2184    int sourceconfssize;
2185    int nsourceconfs;
2186    int c;
2187 
2188    assert(sourcescip != NULL);
2189    assert(targetscip != NULL);
2190 
2191    /* check stages for both, the source and the target SCIP data structure */
2192    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2193    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyConss", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
2194 
2195    /* check if we locally need to create a variable or constraint hash map */
2196    uselocalvarmap = (varmap == NULL);
2197    uselocalconsmap = (consmap == NULL);
2198 
2199    if( uselocalvarmap )
2200    {
2201       /* create the variable mapping hash map */
2202       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
2203    }
2204    else
2205       localvarmap = varmap;
2206 
2207    if( uselocalconsmap )
2208    {
2209       /* create the constraint mapping hash map */
2210       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
2211    }
2212    else
2213       localconsmap = consmap;
2214 
2215    /* get number of conflicts stored in the conflict pool */
2216    sourceconfssize = SCIPconflictstoreGetNConflictsInStore(sourcescip->conflictstore);
2217 
2218    /* allocate buffer */
2219    SCIP_CALL( SCIPallocBufferArray(sourcescip, &sourceconfs, sourceconfssize) );
2220 
2221    /* get all conflicts stored in the conflict pool */
2222    SCIP_CALL( SCIPconflictstoreGetConflicts(sourcescip->conflictstore, sourceconfs, sourceconfssize, &nsourceconfs) );
2223    assert(nsourceconfs <= sourceconfssize);
2224 
2225    /* copy conflicts */
2226    for( c = 0; c < nsourceconfs; ++c )
2227    {
2228       SCIP_CONS* targetcons;
2229 
2230       /* all constraints have to be active */
2231       assert(sourceconfs[c] != NULL);
2232       assert(SCIPconsIsActive(sourceconfs[c]));
2233       assert(!SCIPconsIsDeleted(sourceconfs[c]));
2234       assert(SCIPconsIsConflict(sourceconfs[c]));
2235 
2236       /* in case of copying the global problem we have to ignore the local constraints which are active */
2237       if( global && SCIPconsIsLocal(sourceconfs[c]) )
2238       {
2239          SCIPdebugMsg(sourcescip, "did not copy local constraint <%s> when creating global copy\n", SCIPconsGetName(sourceconfs[c]));
2240          continue;
2241       }
2242 
2243       /* use the copy constructor of the constraint handler and creates and captures the constraint if possible */
2244       targetcons = NULL;
2245       SCIP_CALL( SCIPgetConsCopy(sourcescip, targetscip, sourceconfs[c], &targetcons, SCIPconsGetHdlr(sourceconfs[c]),
2246             localvarmap, localconsmap, NULL, SCIPconsIsInitial(sourceconfs[c]), SCIPconsIsSeparated(sourceconfs[c]),
2247             SCIPconsIsEnforced(sourceconfs[c]), SCIPconsIsChecked(sourceconfs[c]),
2248             SCIPconsIsPropagated(sourceconfs[c]), FALSE, SCIPconsIsModifiable(sourceconfs[c]),
2249             SCIPconsIsDynamic(sourceconfs[c]), SCIPconsIsRemovable(sourceconfs[c]), FALSE, global, &success) );
2250 
2251       /* add the copied constraint to target SCIP if the copying process was valid */
2252       if( success )
2253       {
2254          assert(targetcons != NULL);
2255 
2256          if( !enablepricing )
2257             SCIPconsSetModifiable(targetcons, FALSE);
2258 
2259          /* add constraint to target SCIP */
2260          SCIP_CALL( SCIPaddCons(targetscip, targetcons) );
2261 
2262          /* release constraint once for the creation capture */
2263          SCIP_CALL( SCIPreleaseCons(targetscip, &targetcons) );
2264       }
2265       else
2266       {
2267          *valid = FALSE;
2268          SCIPdebugMsg(sourcescip, "failed to copy constraint %s\n", SCIPconsGetName(sourceconfs[c]));
2269       }
2270    }
2271 
2272    if( uselocalvarmap )
2273    {
2274       /* free hash map */
2275       SCIPhashmapFree(&localvarmap);
2276    }
2277 
2278    if( uselocalconsmap )
2279    {
2280       /* free hash map */
2281       SCIPhashmapFree(&localconsmap);
2282    }
2283 
2284    return SCIP_OKAY;
2285 }
2286 
2287 /** copies implications and cliques of sourcescip to targetscip
2288  *
2289  *  This function should be called for a targetscip in transformed stage. It can save time in presolving of the
2290  *  targetscip, since implications and cliques are copied.
2291  *
2292  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2293  *  @note Do not change the source SCIP environment during the copying process
2294  *
2295  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2296  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2297  *
2298  *  @pre This method can be called if sourcescip is in one of the following stages:
2299  *       - \ref SCIP_STAGE_TRANSFORMED
2300  *       - \ref SCIP_STAGE_INITPRESOLVE
2301  *       - \ref SCIP_STAGE_PRESOLVING
2302  *       - \ref SCIP_STAGE_EXITPRESOLVE
2303  *       - \ref SCIP_STAGE_PRESOLVED
2304  *       - \ref SCIP_STAGE_SOLVING
2305  *       - \ref SCIP_STAGE_SOLVED
2306  *       - \ref SCIP_STAGE_EXITSOLVE
2307  *
2308  *  @pre This method can be called if targetscip is in one of the following stages:
2309  *       - \ref SCIP_STAGE_TRANSFORMED
2310  *       - \ref SCIP_STAGE_INITPRESOLVE
2311  *       - \ref SCIP_STAGE_PRESOLVING
2312  *       - \ref SCIP_STAGE_EXITPRESOLVE
2313  *       - \ref SCIP_STAGE_PRESOLVED
2314  *       - \ref SCIP_STAGE_INITSOLVE
2315  *       - \ref SCIP_STAGE_SOLVING
2316  *
2317  *  @note sourcescip stage does not get changed
2318  *
2319  *  @note targetscip stage does not get changed
2320  *
2321  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2322  */
SCIPcopyImplicationsCliques(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool global,SCIP_Bool * infeasible,int * nbdchgs,int * ncopied)2323 SCIP_RETCODE SCIPcopyImplicationsCliques(
2324    SCIP*                 sourcescip,         /**< source SCIP data structure */
2325    SCIP*                 targetscip,         /**< target SCIP data structure */
2326    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2327                                               *   target variables, or NULL */
2328    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2329                                               *   target constraints, or NULL */
2330    SCIP_Bool             global,             /**< create a global or a local copy? */
2331    SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
2332    int*                  nbdchgs,            /**< pointer to store the number of performed bound changes, or NULL */
2333    int*                  ncopied             /**< pointer to store number of copied implications and cliques, or NULL */
2334    )
2335 {
2336    SCIP_CLIQUE** cliques;
2337    SCIP_VAR** sourcevars;
2338    SCIP_Bool success;
2339    int nvars;
2340    int nbinvars;
2341    int ncliques;
2342    int j;
2343    int c;
2344 
2345    assert( sourcescip != NULL );
2346    assert( targetscip != NULL );
2347    assert( sourcescip != targetscip );
2348    assert( infeasible != NULL );
2349 
2350    /* check stages for both, the source and the target SCIP data structure */
2351    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyImplicationsCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2352    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyImplicationsCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2353 
2354    if ( ncopied != NULL )
2355       *ncopied = 0;
2356    if ( nbdchgs != NULL )
2357       *nbdchgs = 0;
2358 
2359    /* get all active variables */
2360    SCIP_CALL( SCIPgetVarsData(sourcescip, &sourcevars, &nvars, &nbinvars, NULL, NULL, NULL) );
2361 
2362    /* stop if no possible variables for cliques exist */
2363    if ( nbinvars == 0 )
2364       return SCIP_OKAY;
2365 
2366    /* get cliques */
2367    ncliques = SCIPgetNCliques(sourcescip);
2368    if ( ncliques > 0 )
2369    {
2370       SCIP_VAR** targetclique;
2371 
2372       /* get space for target cliques */
2373       SCIP_CALL( SCIPallocBufferArray(targetscip, &targetclique, nvars) );
2374       cliques = SCIPgetCliques(sourcescip);
2375 
2376       /* loop through all cliques */
2377       for (c = 0; c < ncliques; ++c)
2378       {
2379          SCIP_VAR** cliquevars;
2380          SCIP_Bool* cliquevals;
2381          int cliquesize;
2382          int nboundchg = 0;
2383 
2384          assert( cliques[c] != NULL );
2385          cliquevals = SCIPcliqueGetValues(cliques[c]);
2386          cliquevars = SCIPcliqueGetVars(cliques[c]);
2387          cliquesize = SCIPcliqueGetNVars(cliques[c]);
2388 
2389          /* get target variables of clique */
2390          for (j = 0; j < cliquesize; ++j)
2391          {
2392             SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, cliquevars[j], &targetclique[j], varmap, consmap, global, &success) );
2393             if ( ! success )
2394             {
2395                SCIPdebugMsg(sourcescip, "Getting copy for variable <%s> failed.\n", SCIPvarGetName(cliquevars[j]));
2396                SCIPfreeBufferArray(targetscip, &targetclique);
2397                return SCIP_OKAY;
2398             }
2399          }
2400 
2401          /* create clique */
2402          SCIP_CALL( SCIPaddClique(targetscip, targetclique, cliquevals, cliquesize, SCIPcliqueIsEquation(cliques[c]),
2403                infeasible, &nboundchg) );
2404 
2405          if ( *infeasible )
2406          {
2407             SCIPfreeBufferArray(targetscip, &targetclique);
2408             return SCIP_OKAY;
2409          }
2410          if ( ncopied != NULL )
2411             ++(*ncopied);
2412          if ( nbdchgs != NULL )
2413             *nbdchgs += nboundchg;
2414       }
2415       SCIPfreeBufferArray(targetscip, &targetclique);
2416    }
2417 
2418    /* create binary implications */
2419    for (j = 0; j < nbinvars; ++j)
2420    {
2421       SCIP_VAR* sourcevar;
2422       SCIP_VAR* targetvar;
2423       SCIP_Bool d;
2424 
2425       sourcevar = sourcevars[j];
2426       SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, sourcevar, &targetvar, varmap, consmap, global, &success) );
2427       if ( ! success )
2428       {
2429          SCIPdebugMsg(sourcescip, "Getting copy for variable <%s> failed.\n", SCIPvarGetName(sourcevar));
2430          return SCIP_OKAY;
2431       }
2432 
2433       /* consider both possible implications */
2434       for (d = 0; d <= 1; ++d)
2435       {
2436          SCIP_BOUNDTYPE* impltypes;
2437          SCIP_VAR** implvars;
2438          SCIP_Real* implbounds;
2439          int nimpls;
2440          int l;
2441 
2442          nimpls = SCIPvarGetNImpls(sourcevar, d);
2443          if ( nimpls == 0 )
2444             continue;
2445 
2446          impltypes = SCIPvarGetImplTypes(sourcevar, d);
2447          implvars = SCIPvarGetImplVars(sourcevar, d);
2448          implbounds = SCIPvarGetImplBounds(sourcevar, d);
2449 
2450          /* create implications */
2451          for (l = 0; l < nimpls; ++l)
2452          {
2453             SCIP_VAR* implvar;
2454             int nboundchg = 0;
2455 
2456             SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, implvars[l], &implvar, varmap, consmap, global, &success) );
2457             if ( ! success )
2458             {
2459                SCIPdebugMsg(sourcescip, "Getting copy for variable <%s> failed.\n", SCIPvarGetName(implvars[l]));
2460                return SCIP_OKAY;
2461             }
2462 
2463             SCIP_CALL( SCIPaddVarImplication(targetscip, targetvar, d, implvar, impltypes[l], implbounds[l], infeasible, &nboundchg) );
2464             if ( *infeasible )
2465                return SCIP_OKAY;
2466             if ( ncopied != NULL )
2467                ++(*ncopied);
2468             if ( nbdchgs != NULL )
2469                *nbdchgs += nboundchg;
2470 	 }
2471       }
2472    }
2473 
2474    return SCIP_OKAY;
2475 }
2476 
2477 /** copies parameter settings from sourcescip to targetscip
2478  *
2479  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2480  *  @note Do not change the source SCIP environment during the copying process
2481  *
2482  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2483  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2484  *
2485  *  @pre This method can be called if sourcescip is in one of the following stages:
2486  *       - \ref SCIP_STAGE_PROBLEM
2487  *       - \ref SCIP_STAGE_TRANSFORMED
2488  *       - \ref SCIP_STAGE_INITPRESOLVE
2489  *       - \ref SCIP_STAGE_PRESOLVING
2490  *       - \ref SCIP_STAGE_EXITPRESOLVE
2491  *       - \ref SCIP_STAGE_PRESOLVED
2492  *       - \ref SCIP_STAGE_INITSOLVE
2493  *       - \ref SCIP_STAGE_SOLVING
2494  *       - \ref SCIP_STAGE_SOLVED
2495  *
2496  *  @pre This method can be called if targetscip is in one of the following stages:
2497  *       - \ref SCIP_STAGE_INIT
2498  *       - \ref SCIP_STAGE_PROBLEM
2499  *       - \ref SCIP_STAGE_FREE
2500  *
2501  *  @note sourcescip stage does not get changed
2502  *
2503  *  @note targetscip stage does not get changed
2504  *
2505  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2506  */
SCIPcopyParamSettings(SCIP * sourcescip,SCIP * targetscip)2507 SCIP_RETCODE SCIPcopyParamSettings(
2508    SCIP*                 sourcescip,         /**< source SCIP data structure */
2509    SCIP*                 targetscip          /**< target SCIP data structure */
2510    )
2511 {
2512    assert(sourcescip != NULL);
2513    assert(targetscip != NULL);
2514    assert(sourcescip->set != NULL);
2515    assert(targetscip->set != NULL);
2516 
2517    /* check stages for both, the source and the target SCIP data structure */
2518    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyParamSettings", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2519    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyParamSettings", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
2520 
2521    SCIP_CALL( SCIPsetCopyParams(sourcescip->set, targetscip->set, targetscip->messagehdlr) );
2522 
2523    return SCIP_OKAY;
2524 }
2525 
2526 /** gets depth of current scip instance (increased by each copy call)
2527  *
2528  *  @return Depth of subscip of SCIP is returned.
2529  *
2530  *  @pre This method can be called if SCIP is in one of the following stages:
2531  *       - \ref SCIP_STAGE_PROBLEM
2532  *       - \ref SCIP_STAGE_TRANSFORMING
2533  *       - \ref SCIP_STAGE_TRANSFORMED
2534  *       - \ref SCIP_STAGE_INITPRESOLVE
2535  *       - \ref SCIP_STAGE_PRESOLVING
2536  *       - \ref SCIP_STAGE_EXITPRESOLVE
2537  *       - \ref SCIP_STAGE_PRESOLVED
2538  *       - \ref SCIP_STAGE_INITSOLVE
2539  *       - \ref SCIP_STAGE_SOLVING
2540  *       - \ref SCIP_STAGE_SOLVED
2541  *       - \ref SCIP_STAGE_EXITSOLVE
2542  *       - \ref SCIP_STAGE_FREETRANS
2543  *
2544  *  @note SCIP stage does not get changed
2545  *
2546  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2547  */
SCIPgetSubscipDepth(SCIP * scip)2548 int SCIPgetSubscipDepth(
2549    SCIP*                 scip                /**< SCIP data structure */
2550    )
2551 {
2552    assert( scip != NULL );
2553    assert( scip->stat != NULL );
2554 
2555    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetSubscipDepth", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2556 
2557    return scip->stat->subscipdepth;
2558 }
2559 
2560 /** sets depth of scip instance
2561  *
2562  *  @pre This method can be called if SCIP is in one of the following stages:
2563  *       - \ref SCIP_STAGE_PROBLEM
2564  *
2565  *  @note SCIP stage does not get changed
2566  *
2567  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2568  */
SCIPsetSubscipDepth(SCIP * scip,int newdepth)2569 void SCIPsetSubscipDepth(
2570    SCIP*                 scip,               /**< SCIP data structure */
2571    int                   newdepth            /**< new subscip depth */
2572    )
2573 {
2574    assert( scip != NULL );
2575    assert( newdepth > 0 );
2576 
2577    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPsetSubscipDepth", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
2578 
2579    assert( scip->stat != NULL );
2580    scip->stat->subscipdepth = newdepth;
2581 }
2582 
2583 /** copies source SCIP data into target SCIP data structure
2584  *
2585  * distinguishes between
2586  * - local and global copies
2587  * - copies of the original or transformed problem
2588  *
2589  * Allows for constraint compression by specifying a number of source variables
2590  * and values that should be fixed in the copy.
2591  */
2592 static
doCopy(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * suffix,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars,SCIP_Bool useconscompression,SCIP_Bool global,SCIP_Bool original,SCIP_Bool enablepricing,SCIP_Bool threadsafe,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)2593 SCIP_RETCODE doCopy(
2594    SCIP*                 sourcescip,         /**< source SCIP data structure */
2595    SCIP*                 targetscip,         /**< target SCIP data structure */
2596    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2597                                               *   target variables, or NULL */
2598    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2599                                               *   target constraints, or NULL */
2600    const char*           suffix,             /**< optional suffix for problem name inside the target SCIP */
2601    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
2602    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
2603    int                   nfixedvars,         /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
2604    SCIP_Bool             useconscompression, /**< should constraint compression be used when constraints are created? */
2605    SCIP_Bool             global,             /**< create a global or a local copy? */
2606    SCIP_Bool             original,           /**< copy original or transformed problem? if TRUE, a copy using local bounds is not possible */
2607    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance? If TRUE, pricer
2608                                               *   plugins will be copied and activated, and the modifiable flag of
2609                                               *   constraints will be respected. If FALSE, valid will be set to FALSE, when
2610                                               *   there are pricers present */
2611    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
2612                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
2613    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
2614    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid or not, or NULL */
2615    )
2616 {
2617    SCIP_HASHMAP* localvarmap;
2618    SCIP_HASHMAP* localconsmap;
2619    SCIP_Real startcopytime;
2620    SCIP_Real copytime;
2621    SCIP_Bool uselocalvarmap;
2622    SCIP_Bool uselocalconsmap;
2623    SCIP_Bool consscopyvalid;
2624    SCIP_Bool benderscopyvalid;
2625    SCIP_Bool localvalid;
2626    SCIP_Bool msghdlrquiet;
2627    char name[SCIP_MAXSTRLEN];
2628 
2629    assert(sourcescip != NULL);
2630    assert(targetscip != NULL);
2631    assert(suffix != NULL);
2632 
2633    /* copy the original problem if we are in SCIP_STAGE_PROBLEM stage */
2634    if( SCIPgetStage(sourcescip) == SCIP_STAGE_PROBLEM )
2635       original = TRUE;
2636 
2637    /* global must be TRUE for the original problem */
2638    assert(global || !original);
2639 
2640    /* get time before start of copy procedure */
2641    startcopytime = SCIPclockGetTime(sourcescip->stat->copyclock);
2642 
2643    /* start time measuring */
2644    SCIPclockStart(sourcescip->stat->copyclock, sourcescip->set);
2645 
2646    /* copy all plugins */
2647    SCIP_CALL( SCIPcopyPlugins(sourcescip, targetscip, TRUE, enablepricing, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
2648          TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, passmessagehdlr, &localvalid) );
2649 
2650    /* in case there are active pricers and pricing is disabled, targetscip will not be a valid copy of sourcescip */
2651    if( ! enablepricing && SCIPgetNActivePricers(sourcescip) > 0 )
2652       localvalid = FALSE;
2653 
2654    SCIPdebugMsg(sourcescip, "Copying plugins was%s valid.\n", localvalid ? "" : " not");
2655 
2656    uselocalvarmap = (varmap == NULL);
2657    uselocalconsmap = (consmap == NULL);
2658 
2659    if( uselocalvarmap )
2660    {
2661       /* create the variable mapping hash map */
2662       SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(targetscip), SCIPgetNVars(sourcescip)) );
2663    }
2664    else
2665       localvarmap = varmap;
2666 
2667    if( uselocalconsmap )
2668    {
2669       /* create the constraint mapping hash map */
2670       SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(targetscip), SCIPgetNConss(sourcescip)) );
2671    }
2672    else
2673       localconsmap = consmap;
2674 
2675    /* construct name for the target SCIP using the source problem name and the given suffix string */
2676    (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%s", SCIPgetProbName(sourcescip), suffix);
2677 
2678    /* store the quiet state of the message handler, if existent */
2679    msghdlrquiet = SCIPmessagehdlrIsQuiet(targetscip->messagehdlr);
2680 
2681    /* explicitly suppress output when copying parameters */
2682    SCIPsetMessagehdlrQuiet(targetscip, TRUE);
2683 
2684    /* copy all settings */
2685    SCIP_CALL( SCIPcopyParamSettings(sourcescip, targetscip) );
2686 
2687    /* restore original quiet state */
2688    SCIPsetMessagehdlrQuiet(targetscip, msghdlrquiet);
2689 
2690    /* create problem in the target SCIP copying the source original or transformed problem data */
2691    if( original )
2692    {
2693       SCIP_CALL( SCIPcopyOrigProb(sourcescip, targetscip, localvarmap, localconsmap, name) );
2694    }
2695    else
2696    {
2697       SCIP_CALL( SCIPcopyProb(sourcescip, targetscip, localvarmap, localconsmap, global, name) );
2698    }
2699 
2700    /* copy original or transformed variables and perform fixings if needed */
2701    SCIP_CALL( copyVars(sourcescip, targetscip, localvarmap, localconsmap, fixedvars, fixedvals, nfixedvars, original, global) );
2702 
2703    /* if fixed variables are directly specified or inferred from local bounds, enable constraint compression */
2704    if( useconscompression && (nfixedvars > 0 || !global) )
2705    {
2706       SCIP_CALL( SCIPenableConsCompression(targetscip) );
2707 
2708       /* domain reductions yield a copy that is no longer guaranteed to be valid */
2709       localvalid = FALSE;
2710    }
2711 
2712    /* copy all (original) constraints */
2713    if( original )
2714    {
2715       SCIP_CALL( SCIPcopyOrigConss(sourcescip, targetscip, localvarmap, localconsmap, enablepricing, &consscopyvalid) );
2716    }
2717    else
2718    {
2719       SCIP_CALL( SCIPcopyConss(sourcescip, targetscip, localvarmap, localconsmap, global, enablepricing, &consscopyvalid) );
2720    }
2721 
2722    SCIPdebugMsg(sourcescip, "Copying constraints was%s valid.\n", consscopyvalid ? "" : " not");
2723 
2724    localvalid = localvalid && consscopyvalid;
2725 
2726    /* copy the Benders' decomposition plugins explicitly, because it requires the variable mapping hash map */
2727    SCIP_CALL( SCIPcopyBenders(sourcescip, targetscip, localvarmap, threadsafe, &benderscopyvalid) );
2728 
2729    SCIPdebugMsg(sourcescip, "Copying Benders' decomposition plugins was%s valid.\n", benderscopyvalid ? "" : " not");
2730 
2731    localvalid = localvalid && benderscopyvalid;
2732 
2733    if( uselocalvarmap )
2734    {
2735       /* free hash map */
2736       SCIPhashmapFree(&localvarmap);
2737    }
2738 
2739    if( uselocalconsmap )
2740    {
2741       /* free hash map */
2742       SCIPhashmapFree(&localconsmap);
2743    }
2744 
2745    /* stop time measuring */
2746    SCIPclockStop(sourcescip->stat->copyclock, sourcescip->set);
2747 
2748    /* get time after copying procedure */
2749    copytime = SCIPclockGetTime(sourcescip->stat->copyclock) - startcopytime;
2750 
2751    if( copytime > sourcescip->stat->maxcopytime )
2752       sourcescip->stat->maxcopytime = copytime;
2753    if( copytime < sourcescip->stat->mincopytime )
2754       sourcescip->stat->mincopytime = copytime;
2755 
2756    /* increase copy counter */
2757    ++(sourcescip->stat->ncopies);
2758 
2759    targetscip->concurrent = sourcescip->concurrent;
2760    SCIP_CALL( SCIPsyncstoreRelease(&targetscip->syncstore) );
2761    targetscip->syncstore = sourcescip->syncstore;
2762    SCIP_CALL( SCIPsyncstoreCapture(targetscip->syncstore) );
2763 
2764    /* return the information about a valid copy to the user */
2765    if( valid != NULL )
2766       *valid = localvalid;
2767 
2768    return SCIP_OKAY;
2769 }
2770 
2771 /** copies source SCIP to target SCIP; the copying process is done in the following order:
2772  *  1) copy the plugins
2773  *  2) copy the settings
2774  *  3) create problem data in target-SCIP and copy the problem data of the source-SCIP
2775  *  4) copy all active variables except those that are marked as relaxation-only
2776  *  5) copy all constraints
2777  *
2778  *  The source problem depends on the stage of the \p sourcescip - In SCIP_STAGE_PROBLEM, the original problem is copied,
2779  *  otherwise, the transformed problem is copied. For an explicit copy of the original problem, use SCIPcopyOrig().
2780  *
2781  *  @note all variables and constraints which are created in the target-SCIP are not (user) captured
2782  *
2783  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2784  *        Also, 'passmessagehdlr' should be set to FALSE.
2785  *  @note the 'threadsafe' parameter should only be set to TRUE if you are absolutely certain that the source and target
2786  *        SCIP instances will be solved in parallel. The usual case is to set this to FALSE, since thread safety
2787  *        typically incurs a performance cost.
2788  *  @note Do not change the source SCIP environment during the copying process
2789  *
2790  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2791  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2792  *
2793  *  @pre This method can be called if sourcescip is in one of the following stages:
2794  *       - \ref SCIP_STAGE_PROBLEM
2795  *       - \ref SCIP_STAGE_TRANSFORMED
2796  *       - \ref SCIP_STAGE_INITPRESOLVE
2797  *       - \ref SCIP_STAGE_PRESOLVING
2798  *       - \ref SCIP_STAGE_EXITPRESOLVE
2799  *       - \ref SCIP_STAGE_PRESOLVED
2800  *       - \ref SCIP_STAGE_INITSOLVE
2801  *       - \ref SCIP_STAGE_SOLVING
2802  *       - \ref SCIP_STAGE_SOLVED
2803  *
2804  *  @pre This method can be called if targetscip is in one of the following stages:
2805  *       - \ref SCIP_STAGE_INIT
2806  *       - \ref SCIP_STAGE_FREE
2807  *
2808  *  @note sourcescip stage does not get changed
2809  *
2810  *  @note targetscip stage does not get changed
2811  *
2812  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2813  */
SCIPcopy(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * suffix,SCIP_Bool global,SCIP_Bool enablepricing,SCIP_Bool threadsafe,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)2814 SCIP_RETCODE SCIPcopy(
2815    SCIP*                 sourcescip,         /**< source SCIP data structure */
2816    SCIP*                 targetscip,         /**< target SCIP data structure */
2817    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2818                                               *   target variables, or NULL */
2819    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2820                                               *   target constraints, or NULL */
2821    const char*           suffix,             /**< optional suffix for problem name inside the target SCIP */
2822    SCIP_Bool             global,             /**< create a global or a local copy? */
2823    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance? If TRUE, pricer
2824                                               *   plugins will be copied and activated, and the modifiable flag of
2825                                               *   constraints will be respected. If FALSE, valid will be set to FALSE, when
2826                                               *   there are pricers present */
2827    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
2828                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
2829    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
2830    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid, or NULL */
2831    )
2832 {
2833    SCIP_VAR** fixedvars = NULL;
2834    SCIP_Real* fixedvals = NULL;
2835    int nfixedvars = 0;
2836    SCIP_Bool original = FALSE;
2837    SCIP_Bool useconscompression = FALSE;
2838 
2839    assert(sourcescip != NULL);
2840    assert(targetscip != NULL);
2841    assert(suffix != NULL);
2842 
2843    /* check stages for both, the source and the target SCIP data structure */
2844    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopy", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2845    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopy", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
2846 
2847    /* copy source SCIP data into target SCIP data structure */
2848    SCIP_CALL( doCopy(sourcescip, targetscip, varmap, consmap, suffix, fixedvars, fixedvals, nfixedvars,
2849          useconscompression, global, original, enablepricing, threadsafe, passmessagehdlr, valid) );
2850 
2851    return SCIP_OKAY;
2852 }
2853 
2854 /** copies source SCIP to target SCIP but compresses constraints
2855  *
2856  *  constraint compression is performed by removing fixed variables immediately
2857  *  during constraint creation if the involved constraint handlers support
2858  *  compression
2859  *
2860  *  the copying process is done in the following order:
2861  *  1) copy the plugins
2862  *  2) copy the settings
2863  *  3) create problem data in target-SCIP and copy the problem data of the source-SCIP
2864  *  4) copy all active variables except those that are marked as relaxation-only
2865  *     a) fix all variable copies specified by \p fixedvars, \p fixedvals, and \p nfixedvars
2866  *     b) enable constraint compression
2867  *  5) copy all constraints
2868  *
2869  * The source problem depends on the stage of the \p sourcescip - In SCIP_STAGE_PROBLEM, the original problem is copied,
2870  * otherwise, the transformed problem is copied. For an explicit copy of the original problem, use SCIPcopyOrigConsCompression().
2871  *
2872  *  @note: in case that a combination of local bounds and explicit fixing values should be used,
2873  *         the fixing value of a variable is preferred if local bounds and fixing value disagree.
2874  *
2875  *  @note all variables and constraints which are created in the target-SCIP are not (user) captured
2876  *
2877  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2878  *        Also, 'passmessagehdlr' should be set to FALSE.
2879  *  @note the 'threadsafe' parameter should only be set to TRUE if you are absolutely certain that the source and target
2880  *        SCIP instances will be solved in parallel. The usual case is to set this to FALSE, since thread safety
2881  *        typically incurs a performance cost.
2882  *  @note Do not change the source SCIP environment during the copying process
2883  *
2884  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2885  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2886  *
2887  *  @pre This method can be called if sourcescip is in one of the following stages:
2888  *       - \ref SCIP_STAGE_PROBLEM
2889  *       - \ref SCIP_STAGE_TRANSFORMED
2890  *       - \ref SCIP_STAGE_INITPRESOLVE
2891  *       - \ref SCIP_STAGE_PRESOLVING
2892  *       - \ref SCIP_STAGE_EXITPRESOLVE
2893  *       - \ref SCIP_STAGE_PRESOLVED
2894  *       - \ref SCIP_STAGE_INITSOLVE
2895  *       - \ref SCIP_STAGE_SOLVING
2896  *       - \ref SCIP_STAGE_SOLVED
2897  *
2898  *  @pre This method can be called if targetscip is in one of the following stages:
2899  *       - \ref SCIP_STAGE_INIT
2900  *       - \ref SCIP_STAGE_FREE
2901  *
2902  *  @note sourcescip stage does not get changed
2903  *
2904  *  @note targetscip stage does not get changed
2905  *
2906  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2907  */
SCIPcopyConsCompression(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * suffix,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars,SCIP_Bool global,SCIP_Bool enablepricing,SCIP_Bool threadsafe,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)2908 SCIP_RETCODE SCIPcopyConsCompression(
2909    SCIP*                 sourcescip,         /**< source SCIP data structure */
2910    SCIP*                 targetscip,         /**< target SCIP data structure */
2911    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2912                                               *   target variables, or NULL */
2913    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2914                                               *   target constraints, or NULL */
2915    const char*           suffix,             /**< optional suffix for problem name inside the target SCIP */
2916    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
2917    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
2918    int                   nfixedvars,         /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
2919    SCIP_Bool             global,             /**< create a global or a local copy? */
2920    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance? If TRUE, pricer
2921                                               *   plugins will be copied and activated, and the modifiable flag of
2922                                               *   constraints will be respected. If FALSE, valid will be set to FALSE, when
2923                                               *   there are pricers present */
2924    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
2925                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
2926    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
2927    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid, or NULL */
2928    )
2929 {
2930    SCIP_Bool original = FALSE;
2931    SCIP_Bool useconscompression = TRUE;
2932 
2933    assert(sourcescip != NULL);
2934    assert(targetscip != NULL);
2935    assert(suffix != NULL);
2936 
2937    /* check stages for both, the source and the target SCIP data structure */
2938    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyConsCompression", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2939    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyConsCompression", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
2940 
2941    /* copy the source problem data */
2942    SCIP_CALL( doCopy(sourcescip, targetscip, varmap, consmap, suffix, fixedvars, fixedvals, nfixedvars,
2943          useconscompression, global, original, enablepricing, threadsafe, passmessagehdlr, valid) );
2944 
2945    return SCIP_OKAY;
2946 }
2947 
2948 
2949 /** copies source SCIP original problem to target SCIP; the copying process is done in the following order:
2950  *  1) copy the plugins
2951  *  2) copy the settings
2952  *  3) create problem data in target-SCIP and copy the original problem data of the source-SCIP
2953  *  4) copy all original variables
2954  *  5) copy all original constraints
2955  *
2956  *  @note all variables and constraints which are created in the target-SCIP are not (user) captured
2957  *
2958  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
2959  *        Also, 'passmessagehdlr' should be set to FALSE.
2960  *  @note the 'threadsafe' parameter should only be set to TRUE if you are absolutely certain that the source and target
2961  *        SCIP instances will be solved in parallel. The usual case is to set this to FALSE, since thread safety
2962  *        typically incurs a performance cost.
2963  *  @note Do not change the source SCIP environment during the copying process
2964  *
2965  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2966  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2967  *
2968  *  @pre This method can be called if sourcescip is in one of the following stages:
2969  *       - \ref SCIP_STAGE_PROBLEM
2970  *       - \ref SCIP_STAGE_TRANSFORMED
2971  *       - \ref SCIP_STAGE_INITPRESOLVE
2972  *       - \ref SCIP_STAGE_PRESOLVING
2973  *       - \ref SCIP_STAGE_EXITPRESOLVE
2974  *       - \ref SCIP_STAGE_PRESOLVED
2975  *       - \ref SCIP_STAGE_INITSOLVE
2976  *       - \ref SCIP_STAGE_SOLVING
2977  *       - \ref SCIP_STAGE_SOLVED
2978  *
2979  *  @pre This method can be called if targetscip is in one of the following stages:
2980  *       - \ref SCIP_STAGE_INIT
2981  *       - \ref SCIP_STAGE_FREE
2982  *
2983  *  @note sourcescip stage does not get changed
2984  *
2985  *  @note targetscip stage does not get changed
2986  *
2987  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
2988  */
SCIPcopyOrig(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * suffix,SCIP_Bool enablepricing,SCIP_Bool threadsafe,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)2989 SCIP_RETCODE SCIPcopyOrig(
2990    SCIP*                 sourcescip,         /**< source SCIP data structure */
2991    SCIP*                 targetscip,         /**< target SCIP data structure */
2992    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
2993                                               *   target variables, or NULL */
2994    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
2995                                               *   target constraints, or NULL */
2996    const char*           suffix,             /**< suffix which will be added to the names of the target SCIP, might be empty */
2997    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance? If TRUE, pricer
2998                                               *   plugins will be copied and activated, and the modifiable flag of
2999                                               *   constraints will be respected. If FALSE, valid will be set to FALSE, when
3000                                               *   there are pricers present */
3001    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
3002                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
3003    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
3004    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid, or NULL */
3005    )
3006 {
3007    SCIP_VAR** fixedvars = NULL;
3008    SCIP_Real* fixedvals = NULL;
3009    int nfixedvars = 0;
3010    SCIP_Bool global = TRUE;
3011    SCIP_Bool original = TRUE;
3012    SCIP_Bool useconscompression = FALSE;
3013 
3014    assert(sourcescip != NULL);
3015    assert(targetscip != NULL);
3016    assert(suffix != NULL);
3017 
3018    /* check stages for both, the source and the target SCIP data structure */
3019    SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyOrig", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
3020    SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyOrig", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
3021 
3022    SCIP_CALL( doCopy(sourcescip, targetscip, varmap, consmap, suffix, fixedvars, fixedvals, nfixedvars,
3023          useconscompression, global, original, enablepricing, threadsafe, passmessagehdlr, valid) );
3024 
3025    return SCIP_OKAY;
3026 }
3027 
3028 /** copies source SCIP original problem to target SCIP but compresses constraints
3029  *
3030  *  constraint compression is performed by removing fixed variables immediately
3031  *  during constraint creation if the involved constraint handlers support
3032  *  compression
3033  *
3034  *  the copying process is done in the following order:
3035  *  1) copy the plugins
3036  *  2) copy the settings
3037  *  3) create problem data in target-SCIP and copy the problem data of the source-SCIP
3038  *  4) copy all original variables
3039  *     a) fix all variable copies specified by \p fixedvars, \p fixedvals, and \p nfixedvars
3040  *     b) enable constraint compression
3041  *  5) copy all constraints
3042  *
3043  *  @note all variables and constraints which are created in the target-SCIP are not (user) captured
3044  *
3045  *  @note In a multi thread case, you need to lock the copying procedure from outside with a mutex.
3046  *        Also, 'passmessagehdlr' should be set to FALSE.
3047  *  @note the 'threadsafe' parameter should only be set to TRUE if you are absolutely certain that the source and target
3048  *        SCIP instances will be solved in parallel. The usual case is to set this to FALSE, since thread safety
3049  *        typically incurs a performance cost.
3050  *  @note Do not change the source SCIP environment during the copying process
3051  *
3052  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3053  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3054  *
3055  *  @pre This method can be called if sourcescip is in one of the following stages:
3056  *       - \ref SCIP_STAGE_PROBLEM
3057  *       - \ref SCIP_STAGE_TRANSFORMED
3058  *       - \ref SCIP_STAGE_INITPRESOLVE
3059  *       - \ref SCIP_STAGE_PRESOLVING
3060  *       - \ref SCIP_STAGE_EXITPRESOLVE
3061  *       - \ref SCIP_STAGE_PRESOLVED
3062  *       - \ref SCIP_STAGE_INITSOLVE
3063  *       - \ref SCIP_STAGE_SOLVING
3064  *       - \ref SCIP_STAGE_SOLVED
3065  *
3066  *  @pre This method can be called if targetscip is in one of the following stages:
3067  *       - \ref SCIP_STAGE_INIT
3068  *       - \ref SCIP_STAGE_FREE
3069  *
3070  *  @note sourcescip stage does not get changed
3071  *
3072  *  @note targetscip stage does not get changed
3073  *
3074  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3075  */
SCIPcopyOrigConsCompression(SCIP * sourcescip,SCIP * targetscip,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,const char * suffix,SCIP_VAR ** fixedvars,SCIP_Real * fixedvals,int nfixedvars,SCIP_Bool enablepricing,SCIP_Bool threadsafe,SCIP_Bool passmessagehdlr,SCIP_Bool * valid)3076 SCIP_RETCODE SCIPcopyOrigConsCompression(
3077    SCIP*                 sourcescip,         /**< source SCIP data structure */
3078    SCIP*                 targetscip,         /**< target SCIP data structure */
3079    SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
3080                                               *   target variables, or NULL */
3081    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
3082                                               *   target constraints, or NULL */
3083    const char*           suffix,             /**< optional suffix for problem name inside the target SCIP */
3084    SCIP_VAR**            fixedvars,          /**< source variables whose copies should be fixed in the target SCIP environment, or NULL */
3085    SCIP_Real*            fixedvals,          /**< array of fixing values for target SCIP variables, or NULL */
3086    int                   nfixedvars,         /**< number of source variables whose copies should be fixed in the target SCIP environment, or NULL */
3087    SCIP_Bool             enablepricing,      /**< should pricing be enabled in copied SCIP instance? If TRUE, pricer
3088                                               *   plugins will be copied and activated, and the modifiable flag of
3089                                               *   constraints will be respected. If FALSE, valid will be set to FALSE, when
3090                                               *   there are pricers present */
3091    SCIP_Bool             threadsafe,         /**< FALSE, if data can be safely shared between the source and target
3092                                               *   SCIP, otherwise TRUE. This is usually set to FALSE */
3093    SCIP_Bool             passmessagehdlr,    /**< should the message handler be passed */
3094    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid, or NULL */
3095    )
3096 {
3097    SCIP_Bool original = TRUE;
3098    SCIP_Bool global = TRUE;
3099    SCIP_Bool useconscompression = TRUE;
3100 
3101    assert(sourcescip != NULL);
3102    assert(targetscip != NULL);
3103    assert(suffix != NULL);
3104 
3105    /* check stages for both, the source and the target SCIP data structure */
3106     SCIP_CALL( SCIPcheckStage(sourcescip, "SCIPcopyOrigConsCompression", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
3107     SCIP_CALL( SCIPcheckStage(targetscip, "SCIPcopyOrigConsCompression", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) );
3108 
3109    /* copy the source problem data */
3110    SCIP_CALL( doCopy(sourcescip, targetscip, varmap, consmap, suffix, fixedvars, fixedvals, nfixedvars,
3111          useconscompression, global, original, enablepricing, threadsafe, passmessagehdlr, valid) );
3112 
3113    SCIP_CALL( SCIPsyncstoreRelease(&targetscip->syncstore) );
3114    targetscip->syncstore = sourcescip->syncstore;
3115    SCIP_CALL( SCIPsyncstoreCapture(targetscip->syncstore) );
3116 
3117    return SCIP_OKAY;
3118 }
3119 
3120 /** return updated time limit for a sub-SCIP */
3121 static
getCopyTimelimit(SCIP * sourcescip,SCIP_Real * timelimit)3122 SCIP_RETCODE getCopyTimelimit(
3123    SCIP*                 sourcescip,         /**< source SCIP data structure */
3124    SCIP_Real*            timelimit           /**< pointer to store sub-SCIP time limit */
3125    )
3126 {
3127    SCIP_CALL( SCIPgetRealParam(sourcescip, "limits/time", timelimit) );
3128    if( !SCIPisInfinity(sourcescip, *timelimit) )
3129       (*timelimit) -= SCIPgetSolvingTime(sourcescip);
3130 
3131    return SCIP_OKAY;
3132 }
3133 
3134 /** set updated time limit for a sub-SCIP */
3135 static
copySofttimelimit(SCIP * sourcescip,SCIP * targetscip)3136 SCIP_RETCODE copySofttimelimit(
3137    SCIP*                 sourcescip,         /**< source SCIP data structure */
3138    SCIP*                 targetscip          /**< target SCIP data structure */
3139    )
3140 {
3141    if( SCIPgetParam(targetscip, "limits/softtime") == NULL )
3142       return SCIP_OKAY;
3143    else
3144    {
3145       SCIP_Real timelimit = -1.0;
3146 
3147       SCIP_CALL( SCIPgetRealParam(sourcescip, "limits/softtime", &timelimit) );
3148       if( !SCIPisNegative(sourcescip, timelimit) )
3149       {
3150          timelimit -= SCIPgetSolvingTime(sourcescip);
3151          timelimit = MAX(0.0, timelimit);
3152       }
3153 
3154       SCIP_CALL( SCIPsetRealParam(targetscip, "limits/softtime", timelimit) );
3155    }
3156    return SCIP_OKAY;
3157 }
3158 
3159 /** return updated memory limit for a sub-SCIP */
3160 static
getCopyMemlimit(SCIP * sourcescip,SCIP_Real * memorylimit)3161 SCIP_RETCODE getCopyMemlimit(
3162    SCIP*                 sourcescip,         /**< source SCIP data structure */
3163    SCIP_Real*            memorylimit         /**< pointer to store sub-SCIP memory limit */
3164    )
3165 {
3166    SCIP_CALL( SCIPgetRealParam(sourcescip, "limits/memory", memorylimit) );
3167 
3168    /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
3169    if( !SCIPisInfinity(sourcescip, *memorylimit) )
3170       (*memorylimit) -= (SCIPgetMemUsed(sourcescip) + SCIPgetMemExternEstim(sourcescip))/1048576.0;
3171 
3172    return SCIP_OKAY;
3173 }
3174 
3175 /** checks if there is enough time and memory left for copying the sourcescip into a sub-SCIP and solve the sub-SCIP
3176  *
3177  *  This is the case if the time and memory limit that would be passed to the sub-SCIP are larger than 0.0
3178  *
3179  *  @pre This method can be called if sourcescip is in one of the following stages:
3180  *       - \ref SCIP_STAGE_PROBLEM
3181  *       - \ref SCIP_STAGE_TRANSFORMED
3182  *       - \ref SCIP_STAGE_INITPRESOLVE
3183  *       - \ref SCIP_STAGE_PRESOLVING
3184  *       - \ref SCIP_STAGE_EXITPRESOLVE
3185  *       - \ref SCIP_STAGE_PRESOLVED
3186  *       - \ref SCIP_STAGE_INITSOLVE
3187  *       - \ref SCIP_STAGE_SOLVING
3188  *       - \ref SCIP_STAGE_SOLVED
3189  *
3190  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3191  */
SCIPcheckCopyLimits(SCIP * sourcescip,SCIP_Bool * success)3192 SCIP_RETCODE SCIPcheckCopyLimits(
3193    SCIP*                 sourcescip,         /**< source SCIP data structure */
3194    SCIP_Bool*            success             /**< pointer to store whether there is time and memory left to copy the
3195                                               *   problem and run the sub-SCIP */
3196    )
3197 {
3198    SCIP_Real timelimit;
3199    SCIP_Real memorylimit;
3200 
3201    SCIP_CALL( getCopyTimelimit(sourcescip, &timelimit) );
3202    SCIP_CALL( getCopyMemlimit(sourcescip, &memorylimit) );
3203 
3204    *success = timelimit > 0.0 && memorylimit > 2.0 * SCIPgetMemExternEstim(sourcescip) / 1048576.0;
3205 
3206    return SCIP_OKAY;
3207 }
3208 
3209 /** copies limits from source SCIP to target SCIP
3210  *
3211  *  @note time and memory limit are reduced by the amount already spent in the source SCIP before installing the limit
3212  *        in the target SCIP
3213  *  @note all other limits are disabled and need to be enabled afterwards, if needed
3214  *
3215  *  @pre This method can be called if sourcescip is in one of the following stages:
3216  *       - \ref SCIP_STAGE_PROBLEM
3217  *       - \ref SCIP_STAGE_TRANSFORMED
3218  *       - \ref SCIP_STAGE_INITPRESOLVE
3219  *       - \ref SCIP_STAGE_PRESOLVING
3220  *       - \ref SCIP_STAGE_EXITPRESOLVE
3221  *       - \ref SCIP_STAGE_PRESOLVED
3222  *       - \ref SCIP_STAGE_INITSOLVE
3223  *       - \ref SCIP_STAGE_SOLVING
3224  *       - \ref SCIP_STAGE_SOLVED
3225  *
3226  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3227  */
SCIPcopyLimits(SCIP * sourcescip,SCIP * targetscip)3228 SCIP_RETCODE SCIPcopyLimits(
3229    SCIP*                 sourcescip,         /**< source SCIP data structure */
3230    SCIP*                 targetscip          /**< target SCIP data structure */
3231    )
3232 {
3233    SCIP_Real timelimit;
3234    SCIP_Real memorylimit;
3235 
3236    SCIP_CALL( getCopyTimelimit(sourcescip, &timelimit) );
3237    SCIP_CALL( getCopyMemlimit(sourcescip, &memorylimit) );
3238 
3239    /* avoid negative limits */
3240    if( timelimit < 0.0 )
3241       timelimit = 0.0;
3242    if( memorylimit < 0.0 )
3243       memorylimit = 0.0;
3244 
3245    /* set time and memory limit to the adjusted values */
3246    SCIP_CALL( SCIPsetRealParam(targetscip, "limits/time", timelimit) );
3247    SCIP_CALL( SCIPsetRealParam(targetscip, "limits/memory", memorylimit) );
3248 
3249    /* copy and adjust soft time limit (or disable it) */
3250    SCIP_CALL( copySofttimelimit(sourcescip, targetscip) );
3251 
3252    /* disable all other limits */
3253    SCIP_CALL( SCIPsetRealParam(targetscip, "limits/absgap", 0.0) );
3254    SCIP_CALL( SCIPsetIntParam(targetscip, "limits/bestsol", -1) );
3255    SCIP_CALL( SCIPsetRealParam(targetscip, "limits/gap", 0.0) );
3256    SCIP_CALL( SCIPsetLongintParam(targetscip, "limits/nodes", -1LL) );
3257    SCIP_CALL( SCIPsetIntParam(targetscip, "limits/restarts", -1) );
3258    SCIP_CALL( SCIPsetIntParam(targetscip, "limits/solutions", -1) );
3259    SCIP_CALL( SCIPsetLongintParam(targetscip, "limits/stallnodes", -1LL) );
3260    SCIP_CALL( SCIPsetLongintParam(targetscip, "limits/totalnodes", -1LL) );
3261 
3262    return SCIP_OKAY;
3263 }
3264 
3265 /** sets the working limits as well as common search parameters for the auxiliary problem
3266  *
3267  *  @note memory and time limits are not affected, and must be set using SCIPcopyLimits() instead
3268  */
SCIPsetCommonSubscipParams(SCIP * sourcescip,SCIP * subscip,SCIP_Longint nsubnodes,SCIP_Longint nstallnodes,int bestsollimit)3269 SCIP_RETCODE SCIPsetCommonSubscipParams(
3270    SCIP*                 sourcescip,         /**< source SCIP data structure */
3271    SCIP*                 subscip,            /**< target SCIP data structure, often a copy of \p sourcescip */
3272    SCIP_Longint          nsubnodes,          /**< nodelimit for subscip, or -1 for no limit */
3273    SCIP_Longint          nstallnodes,        /**< stall node limit for subscip, or -1 for no limit */
3274    int                   bestsollimit        /**< the limit on the number of best solutions found, or -1 for no limit */
3275    )
3276 {
3277    SCIP_Bool useuct;
3278 
3279    assert(sourcescip != NULL);
3280    assert(subscip != NULL);
3281 
3282    /* do not abort subproblem on CTRL-C */
3283    SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
3284 
3285 #ifdef SCIP_DEBUG
3286    /* for debugging, enable full output */
3287    SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
3288    SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
3289 #else
3290    /* disable statistic timing inside sub SCIP and output to console */
3291    SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
3292    SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
3293 #endif
3294 
3295    /* set limits for the subproblem */
3296    SCIP_CALL( SCIPcopyLimits(sourcescip, subscip) );
3297    SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nsubnodes) );
3298    SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
3299    SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", bestsollimit) );
3300 
3301    /* forbid recursive call of heuristics and separators solving subMIPs */
3302    SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
3303 
3304    /* disable cutting plane separation */
3305    SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );
3306 
3307    /* disable expensive presolving */
3308    SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );
3309 
3310    /* use best estimate node selection */
3311    if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
3312    {
3313       SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
3314    }
3315 
3316    /* activate uct node selection at the top of the tree */
3317    SCIP_CALL( SCIPgetBoolParam(sourcescip, "heuristics/useuctsubscip", &useuct) );
3318    if( useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
3319    {
3320       SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
3321    }
3322 
3323    /* use inference branching */
3324    if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
3325    {
3326       SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
3327    }
3328 
3329    /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
3330    if( !SCIPisParamFixed(subscip, "conflict/enable") )
3331    {
3332       SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
3333    }
3334    if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
3335    {
3336       SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
3337    }
3338    if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
3339    {
3340       SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
3341    }
3342 
3343    /* speed up sub-SCIP by not checking dual LP feasibility */
3344    SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
3345 
3346    /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
3347     * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
3348     * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
3349     * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
3350     * made for the original SCIP
3351     */
3352    if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
3353    {
3354       SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 500) );
3355    }
3356 
3357    return SCIP_OKAY;
3358 }
3359 
3360