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