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, ©bendersvalid) );
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