1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file scip_prob.c
17 * @ingroup OTHER_CFILES
18 * @brief public methods for global and local (sub)problems
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 * @author Gerald Gamrath
22 * @author Leona Gottwald
23 * @author Stefan Heinz
24 * @author Gregor Hendel
25 * @author Thorsten Koch
26 * @author Alexander Martin
27 * @author Marc Pfetsch
28 * @author Michael Winkler
29 * @author Kati Wolter
30 *
31 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32 */
33
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36 #include "blockmemshell/memory.h"
37 #include "scip/benders.h"
38 #include "scip/clock.h"
39 #include "scip/concurrent.h"
40 #include "scip/conflictstore.h"
41 #include "scip/cons.h"
42 #include "scip/dcmp.h"
43 #include "scip/debug.h"
44 #include "scip/lp.h"
45 #include "scip/pricer.h"
46 #include "scip/pricestore.h"
47 #include "scip/primal.h"
48 #include "scip/prob.h"
49 #include "scip/pub_cons.h"
50 #include "scip/pub_event.h"
51 #include "scip/pub_message.h"
52 #include "scip/pub_misc.h"
53 #include "scip/pub_reader.h"
54 #include "scip/pub_sol.h"
55 #include "scip/pub_tree.h"
56 #include "scip/pub_var.h"
57 #include "scip/reader.h"
58 #include "scip/reopt.h"
59 #include "scip/scip_cons.h"
60 #include "scip/scip_general.h"
61 #include "scip/scip_mem.h"
62 #include "scip/scip_numerics.h"
63 #include "scip/scip_param.h"
64 #include "scip/scip_prob.h"
65 #include "scip/scip_randnumgen.h"
66 #include "scip/scip_sol.h"
67 #include "scip/scip_solve.h"
68 #include "scip/scip_solvingstats.h"
69 #include "scip/scip_timing.h"
70 #include "scip/scip_var.h"
71 #include "scip/set.h"
72 #include "scip/stat.h"
73 #include "scip/struct_cons.h"
74 #include "scip/struct_lp.h"
75 #include "scip/struct_mem.h"
76 #include "scip/struct_primal.h"
77 #include "scip/struct_prob.h"
78 #include "scip/struct_scip.h"
79 #include "scip/struct_set.h"
80 #include "scip/struct_stat.h"
81 #include "scip/struct_var.h"
82 #include "scip/syncstore.h"
83 #include "scip/tree.h"
84 #include <stdio.h>
85 #include <string.h>
86
87 /** creates empty problem and initializes all solving data structures (the objective sense is set to MINIMIZE)
88 * If the problem type requires the use of variable pricers, these pricers should be added to the problem with calls
89 * to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
90 *
91 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
92 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
93 *
94 * @pre This method can be called if @p scip is in one of the following stages:
95 * - \ref SCIP_STAGE_INIT
96 * - \ref SCIP_STAGE_PROBLEM
97 * - \ref SCIP_STAGE_TRANSFORMED
98 * - \ref SCIP_STAGE_PRESOLVING
99 * - \ref SCIP_STAGE_PRESOLVED
100 * - \ref SCIP_STAGE_SOLVING
101 * - \ref SCIP_STAGE_SOLVED
102 * - \ref SCIP_STAGE_FREE
103 *
104 * @post After calling this method, \SCIP reaches the following stage:
105 * - \ref SCIP_STAGE_PROBLEM
106 */
SCIPcreateProb(SCIP * scip,const char * name,SCIP_DECL_PROBDELORIG ((* probdelorig)),SCIP_DECL_PROBTRANS ((* probtrans)),SCIP_DECL_PROBDELTRANS ((* probdeltrans)),SCIP_DECL_PROBINITSOL ((* probinitsol)),SCIP_DECL_PROBEXITSOL ((* probexitsol)),SCIP_DECL_PROBCOPY ((* probcopy)),SCIP_PROBDATA * probdata)107 SCIP_RETCODE SCIPcreateProb(
108 SCIP* scip, /**< SCIP data structure */
109 const char* name, /**< problem name */
110 SCIP_DECL_PROBDELORIG ((*probdelorig)), /**< frees user data of original problem */
111 SCIP_DECL_PROBTRANS ((*probtrans)), /**< creates user data of transformed problem by transforming original user data */
112 SCIP_DECL_PROBDELTRANS((*probdeltrans)), /**< frees user data of transformed problem */
113 SCIP_DECL_PROBINITSOL ((*probinitsol)), /**< solving process initialization method of transformed data */
114 SCIP_DECL_PROBEXITSOL ((*probexitsol)), /**< solving process deinitialization method of transformed data */
115 SCIP_DECL_PROBCOPY ((*probcopy)), /**< copies user data if you want to copy it to a subscip, or NULL */
116 SCIP_PROBDATA* probdata /**< user problem data set by the reader */
117 )
118 {
119 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateProb", TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
120
121 /* free old problem */
122 SCIP_CALL( SCIPfreeProb(scip) );
123 assert(scip->set->stage == SCIP_STAGE_INIT);
124
125 /* switch stage to PROBLEM */
126 scip->set->stage = SCIP_STAGE_PROBLEM;
127
128 SCIP_CALL( SCIPstatCreate(&scip->stat, scip->mem->probmem, scip->set, NULL, NULL, scip->messagehdlr) );
129
130 SCIP_CALL( SCIPprobCreate(&scip->origprob, scip->mem->probmem, scip->set, name,
131 probdelorig, probtrans, probdeltrans, probinitsol, probexitsol, probcopy, probdata, FALSE) );
132
133 /* create solution pool for original solution candidates */
134 SCIP_CALL( SCIPprimalCreate(&scip->origprimal) );
135
136 /* create conflict pool for storing conflict constraints */
137 SCIP_CALL( SCIPconflictstoreCreate(&scip->conflictstore, scip->set) );
138
139 /* initialize reoptimization structure, if needed */
140 SCIP_CALL( SCIPenableReoptimization(scip, scip->set->reopt_enable) );
141
142 SCIP_CALL( SCIPdecompstoreCreate(&scip->decompstore, SCIPblkmem(scip), SCIP_DECOMPSTORE_CAPA) );
143
144 return SCIP_OKAY;
145 }
146
147 /** creates empty problem and initializes all solving data structures (the objective sense is set to MINIMIZE)
148 * all callback methods will be set to NULL and can be set afterwards, if needed, via SCIPsetProbDelorig(),
149 * SCIPsetProbTrans(), SCIPsetProbDeltrans(), SCIPsetProbInitsol(), SCIPsetProbExitsol(), and
150 * SCIPsetProbCopy()
151 * If the problem type requires the use of variable pricers, these pricers should be added to the problem with calls
152 * to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
153 *
154 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
155 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
156 *
157 * @pre This method can be called if @p scip is in one of the following stages:
158 * - \ref SCIP_STAGE_INIT
159 * - \ref SCIP_STAGE_PROBLEM
160 * - \ref SCIP_STAGE_TRANSFORMED
161 * - \ref SCIP_STAGE_PRESOLVING
162 * - \ref SCIP_STAGE_PRESOLVED
163 * - \ref SCIP_STAGE_SOLVING
164 * - \ref SCIP_STAGE_SOLVED
165 * - \ref SCIP_STAGE_FREE
166 *
167 * @post After calling this method, \SCIP reaches the following stage:
168 * - \ref SCIP_STAGE_PROBLEM
169 */
SCIPcreateProbBasic(SCIP * scip,const char * name)170 SCIP_RETCODE SCIPcreateProbBasic(
171 SCIP* scip, /**< SCIP data structure */
172 const char* name /**< problem name */
173 )
174 {
175 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateProbBasic", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
176
177 SCIP_CALL( SCIPcreateProb(scip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
178
179 return SCIP_OKAY;
180 }
181
182 /** sets callback to free user data of original problem
183 *
184 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
185 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
186 *
187 * @pre This method can be called if @p scip is in one of the following stages:
188 * - \ref SCIP_STAGE_PROBLEM
189 */
SCIPsetProbDelorig(SCIP * scip,SCIP_DECL_PROBDELORIG ((* probdelorig)))190 SCIP_RETCODE SCIPsetProbDelorig(
191 SCIP* scip, /**< SCIP data structure */
192 SCIP_DECL_PROBDELORIG ((*probdelorig)) /**< frees user data of original problem */
193 )
194 {
195 assert(scip != NULL);
196 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbDelorig", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
197
198 SCIPprobSetDelorig(scip->origprob, probdelorig);
199
200 return SCIP_OKAY;
201 }
202
203 /** sets callback to create user data of transformed problem by transforming original user data
204 *
205 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
206 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
207 *
208 * @pre This method can be called if @p scip is in one of the following stages:
209 * - \ref SCIP_STAGE_PROBLEM
210 */
SCIPsetProbTrans(SCIP * scip,SCIP_DECL_PROBTRANS ((* probtrans)))211 SCIP_RETCODE SCIPsetProbTrans(
212 SCIP* scip, /**< SCIP data structure */
213 SCIP_DECL_PROBTRANS ((*probtrans)) /**< creates user data of transformed problem by transforming original user data */
214 )
215 {
216 assert(scip != NULL);
217 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbTrans", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
218
219 SCIPprobSetTrans(scip->origprob, probtrans);
220
221 return SCIP_OKAY;
222 }
223
224 /** sets callback to free user data of transformed problem
225 *
226 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
227 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
228 *
229 * @pre This method can be called if @p scip is in one of the following stages:
230 * - \ref SCIP_STAGE_PROBLEM
231 */
SCIPsetProbDeltrans(SCIP * scip,SCIP_DECL_PROBDELTRANS ((* probdeltrans)))232 SCIP_RETCODE SCIPsetProbDeltrans(
233 SCIP* scip, /**< SCIP data structure */
234 SCIP_DECL_PROBDELTRANS((*probdeltrans)) /**< frees user data of transformed problem */
235 )
236 {
237 assert(scip != NULL);
238 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbDeltrans", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
239
240 SCIPprobSetDeltrans(scip->origprob, probdeltrans);
241
242 return SCIP_OKAY;
243 }
244
245 /** sets solving process initialization callback of transformed data
246 *
247 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
248 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
249 *
250 * @pre This method can be called if @p scip is in one of the following stages:
251 * - \ref SCIP_STAGE_PROBLEM
252 */
SCIPsetProbInitsol(SCIP * scip,SCIP_DECL_PROBINITSOL ((* probinitsol)))253 SCIP_RETCODE SCIPsetProbInitsol(
254 SCIP* scip, /**< SCIP data structure */
255 SCIP_DECL_PROBINITSOL ((*probinitsol)) /**< solving process initialization method of transformed data */
256 )
257 {
258 assert(scip != NULL);
259
260 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbInitsol", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
261
262 SCIPprobSetInitsol(scip->origprob, probinitsol);
263
264 return SCIP_OKAY;
265 }
266
267 /** sets solving process deinitialization callback of transformed data
268 *
269 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
270 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
271 *
272 * @pre This method can be called if @p scip is in one of the following stages:
273 * - \ref SCIP_STAGE_PROBLEM
274 */
SCIPsetProbExitsol(SCIP * scip,SCIP_DECL_PROBEXITSOL ((* probexitsol)))275 SCIP_RETCODE SCIPsetProbExitsol(
276 SCIP* scip, /**< SCIP data structure */
277 SCIP_DECL_PROBEXITSOL ((*probexitsol)) /**< solving process deinitialization method of transformed data */
278 )
279 {
280 assert(scip != NULL);
281 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbExitsol", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
282
283 SCIPprobSetExitsol(scip->origprob, probexitsol);
284
285 return SCIP_OKAY;
286 }
287
288 /** sets callback to copy user data to a subscip
289 *
290 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
291 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
292 *
293 * @pre This method can be called if @p scip is in one of the following stages:
294 * - \ref SCIP_STAGE_PROBLEM
295 */
SCIPsetProbCopy(SCIP * scip,SCIP_DECL_PROBCOPY ((* probcopy)))296 SCIP_RETCODE SCIPsetProbCopy(
297 SCIP* scip, /**< SCIP data structure */
298 SCIP_DECL_PROBCOPY ((*probcopy)) /**< copies user data if you want to copy it to a subscip, or NULL */
299 )
300 {
301 assert(scip != NULL);
302 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbCopy", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
303
304 SCIPprobSetCopy(scip->origprob, probcopy);
305
306 return SCIP_OKAY;
307 }
308
309 /** reads problem from file and initializes all solving data structures
310 *
311 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
312 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
313 *
314 * @pre This method can be called if @p scip is in one of the following stages:
315 * - \ref SCIP_STAGE_INIT
316 * - \ref SCIP_STAGE_PROBLEM
317 * - \ref SCIP_STAGE_TRANSFORMED
318 * - \ref SCIP_STAGE_INITPRESOLVE
319 * - \ref SCIP_STAGE_PRESOLVING
320 * - \ref SCIP_STAGE_EXITPRESOLVE
321 * - \ref SCIP_STAGE_PRESOLVED
322 * - \ref SCIP_STAGE_SOLVING
323 * - \ref SCIP_STAGE_EXITSOLVE
324 *
325 * @post After the method was called, \SCIP is in one of the following stages:
326 * - \ref SCIP_STAGE_INIT if reading failed (usually, when a SCIP_READERROR occurs)
327 * - \ref SCIP_STAGE_PROBLEM if the problem file was successfully read
328 */
SCIPreadProb(SCIP * scip,const char * filename,const char * extension)329 SCIP_RETCODE SCIPreadProb(
330 SCIP* scip, /**< SCIP data structure */
331 const char* filename, /**< problem file name */
332 const char* extension /**< extension of the desired file reader,
333 * or NULL if file extension should be used */
334 )
335 {
336 SCIP_RETCODE retcode;
337 SCIP_RESULT result;
338 SCIP_Bool usevartable;
339 SCIP_Bool useconstable;
340 int i;
341 char* tmpfilename;
342 char* fileextension;
343
344 assert(scip != NULL);
345 assert(filename != NULL);
346
347 SCIP_CALL( SCIPcheckStage(scip, "SCIPreadProb", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
348
349 SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
350 SCIP_CALL( SCIPgetBoolParam(scip, "misc/useconstable", &useconstable) );
351
352 if( !usevartable || !useconstable )
353 {
354 SCIPerrorMessage("Cannot read problem if vartable or constable is disabled. Make sure parameters 'misc/usevartable' and 'misc/useconstable' are set to TRUE.\n");
355 return SCIP_READERROR;
356 }
357
358 /* try all readers until one could read the file */
359 result = SCIP_DIDNOTRUN;
360
361 /* copy filename */
362 SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpfilename, filename, (int)strlen(filename)+1) );
363
364 fileextension = NULL;
365 if( extension == NULL )
366 {
367 /* get extension from filename */
368 SCIPsplitFilename(tmpfilename, NULL, NULL, &fileextension, NULL);
369 }
370
371 for( i = 0; i < scip->set->nreaders && result == SCIP_DIDNOTRUN; ++i )
372 {
373 retcode = SCIPreaderRead(scip->set->readers[i], scip->set, filename,
374 extension != NULL ? extension : fileextension, &result);
375
376 /* check for reader errors */
377 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
378 goto TERMINATE;
379 SCIP_CALL( retcode );
380 }
381
382 switch( result )
383 {
384 case SCIP_DIDNOTRUN:
385 retcode = SCIP_PLUGINNOTFOUND;
386 break;
387 case SCIP_SUCCESS:
388 if( scip->origprob != NULL )
389 {
390 SCIP_Real readingtime;
391
392 SCIPmessagePrintVerbInfo(scip->messagehdlr, scip->set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
393 "original problem has %d variables (%d bin, %d int, %d impl, %d cont) and %d constraints\n",
394 scip->origprob->nvars, scip->origprob->nbinvars, scip->origprob->nintvars,
395 scip->origprob->nimplvars, scip->origprob->ncontvars,
396 scip->origprob->nconss);
397
398 /* in full verbose mode we will also print the number of constraints per constraint handler */
399 if( scip->set->disp_verblevel == SCIP_VERBLEVEL_FULL )
400 {
401 int* nconss;
402 int c;
403 int h;
404
405 SCIP_CALL( SCIPallocClearBufferArray(scip, &nconss, scip->set->nconshdlrs) );
406
407 /* loop over all constraints and constraint-handlers to count for each type the amount of original
408 * constraints
409 */
410 for( c = scip->origprob->nconss - 1; c >= 0; --c )
411 {
412 for( h = scip->set->nconshdlrs - 1; h >= 0; --h )
413 {
414 if( scip->origprob->conss[c]->conshdlr == scip->set->conshdlrs[h] )
415 {
416 ++(nconss[h]);
417 break;
418 }
419 }
420 /* constraint handler should be found */
421 assert(h >= 0);
422 }
423
424 /* loop over all constraints handlers for printing the number of original constraints */
425 for( h = 0; h < scip->set->nconshdlrs; ++h )
426 {
427 if( nconss[h] > 0 )
428 {
429 SCIPmessagePrintVerbInfo(scip->messagehdlr, scip->set->disp_verblevel, SCIP_VERBLEVEL_FULL,
430 "%7d constraints of type <%s>\n", nconss[h], SCIPconshdlrGetName(scip->set->conshdlrs[h]));
431 }
432 }
433
434 SCIPfreeBufferArray(scip, &nconss);
435 }
436
437 /* in case the permutation seed is different to 0, permute the original problem */
438 if( scip->set->random_permutationseed > 0 )
439 {
440 SCIP_Bool permuteconss;
441 SCIP_Bool permutevars;
442 int permutationseed;
443
444 permuteconss = scip->set->random_permuteconss;
445 permutevars = scip->set->random_permutevars;
446 permutationseed = scip->set->random_permutationseed;
447
448 SCIP_CALL( SCIPpermuteProb(scip, (unsigned int)permutationseed, permuteconss, permutevars, permutevars, permutevars, permutevars) );
449 }
450
451 /* get reading time */
452 readingtime = SCIPgetReadingTime(scip);
453
454 /* display timing statistics */
455 SCIPmessagePrintVerbInfo(scip->messagehdlr, scip->set->disp_verblevel, SCIP_VERBLEVEL_FULL,
456 "Reading Time: %.2f\n", readingtime);
457 }
458 retcode = SCIP_OKAY;
459 break;
460 default:
461 assert(i < scip->set->nreaders);
462 SCIPerrorMessage("invalid result code <%d> from reader <%s> reading file <%s>\n",
463 result, SCIPreaderGetName(scip->set->readers[i]), filename);
464 retcode = SCIP_READERROR;
465 } /*lint !e788*/
466
467 TERMINATE:
468 /* free buffer array */
469 SCIPfreeBufferArray(scip, &tmpfilename);
470
471 /* check if reading time should belong to solving time */
472 if( scip->set->time_reading )
473 {
474 SCIP_Real readingtime;
475
476 /* get reading time */
477 readingtime = SCIPgetReadingTime(scip);
478
479 /* add reading time to solving time */
480 SCIPclockSetTime(scip->stat->solvingtime, readingtime);
481 }
482
483 return retcode;
484 }
485
486 /** write original or transformed problem */
487 static
writeProblem(SCIP * scip,const char * filename,const char * extension,SCIP_Bool transformed,SCIP_Bool genericnames)488 SCIP_RETCODE writeProblem(
489 SCIP* scip, /**< SCIP data structure */
490 const char* filename, /**< output file (or NULL for standard output) */
491 const char* extension, /**< extension of the desired file reader,
492 * or NULL if file extension should be used */
493 SCIP_Bool transformed, /**< output the transformed problem? */
494 SCIP_Bool genericnames /**< using generic variable and constraint names? */
495 )
496 {
497 SCIP_RETCODE retcode;
498 char* tmpfilename;
499 char* fileextension;
500 char* compression;
501 FILE* file;
502
503 assert(scip != NULL );
504
505 fileextension = NULL;
506 compression = NULL;
507 file = NULL;
508 tmpfilename = NULL;
509
510 if( filename != NULL && filename[0] != '\0' )
511 {
512 int success;
513
514 file = fopen(filename, "w");
515 if( file == NULL )
516 {
517 SCIPerrorMessage("cannot create file <%s> for writing\n", filename);
518 SCIPprintSysError(filename);
519 return SCIP_FILECREATEERROR;
520 }
521
522 /* get extension from filename,
523 * if an error occurred, close the file before returning */
524 if( BMSduplicateMemoryArray(&tmpfilename, filename, strlen(filename)+1) == NULL )
525 {
526 (void) fclose(file);
527 SCIPerrorMessage("Error <%d> in function call\n", SCIP_NOMEMORY);
528 return SCIP_NOMEMORY;
529 }
530
531 SCIPsplitFilename(tmpfilename, NULL, NULL, &fileextension, &compression);
532
533 if( compression != NULL )
534 {
535 SCIPmessagePrintWarning(scip->messagehdlr, "currently it is not possible to write files with any compression\n");
536 BMSfreeMemoryArray(&tmpfilename);
537 (void) fclose(file);
538 return SCIP_FILECREATEERROR;
539 }
540
541 if( extension == NULL && fileextension == NULL )
542 {
543 SCIPmessagePrintWarning(scip->messagehdlr, "filename <%s> has no file extension, select default <cip> format for writing\n", filename);
544 }
545
546 if( transformed )
547 retcode = SCIPprintTransProblem(scip, file, extension != NULL ? extension : fileextension, genericnames);
548 else
549 retcode = SCIPprintOrigProblem(scip, file, extension != NULL ? extension : fileextension, genericnames);
550
551 BMSfreeMemoryArray(&tmpfilename);
552
553 success = fclose(file);
554 if( success != 0 )
555 {
556 SCIPerrorMessage("An error occurred while closing file <%s>\n", filename);
557 return SCIP_FILECREATEERROR;
558 }
559 }
560 else
561 {
562 /* print to stdout */
563 if( transformed )
564 retcode = SCIPprintTransProblem(scip, NULL, extension, genericnames);
565 else
566 retcode = SCIPprintOrigProblem(scip, NULL, extension, genericnames);
567 }
568
569 /* check for write errors */
570 if( retcode == SCIP_WRITEERROR || retcode == SCIP_PLUGINNOTFOUND )
571 return retcode;
572 else
573 {
574 SCIP_CALL( retcode );
575 }
576
577 return SCIP_OKAY;
578 }
579
580 /** writes original problem to file
581 *
582 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
583 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
584 *
585 * @pre This method can be called if @p scip is in one of the following stages:
586 * - \ref SCIP_STAGE_PROBLEM
587 * - \ref SCIP_STAGE_TRANSFORMING
588 * - \ref SCIP_STAGE_TRANSFORMED
589 * - \ref SCIP_STAGE_INITPRESOLVE
590 * - \ref SCIP_STAGE_PRESOLVING
591 * - \ref SCIP_STAGE_EXITPRESOLVE
592 * - \ref SCIP_STAGE_PRESOLVED
593 * - \ref SCIP_STAGE_INITSOLVE
594 * - \ref SCIP_STAGE_SOLVING
595 * - \ref SCIP_STAGE_SOLVED
596 * - \ref SCIP_STAGE_EXITSOLVE
597 * - \ref SCIP_STAGE_FREETRANS
598 */
SCIPwriteOrigProblem(SCIP * scip,const char * filename,const char * extension,SCIP_Bool genericnames)599 SCIP_RETCODE SCIPwriteOrigProblem(
600 SCIP* scip, /**< SCIP data structure */
601 const char* filename, /**< output file (or NULL for standard output) */
602 const char* extension, /**< extension of the desired file reader,
603 * or NULL if file extension should be used */
604 SCIP_Bool genericnames /**< using generic variable and constraint names? */
605 )
606 {
607 SCIP_RETCODE retcode;
608
609 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteOrigProblem", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
610
611 assert( scip != NULL );
612 assert( scip->origprob != NULL );
613
614 retcode = writeProblem(scip, filename, extension, FALSE, genericnames);
615
616 /* check for write errors */
617 if( retcode == SCIP_FILECREATEERROR || retcode == SCIP_WRITEERROR || retcode == SCIP_PLUGINNOTFOUND )
618 return retcode;
619 else
620 {
621 SCIP_CALL( retcode );
622 }
623
624 return SCIP_OKAY;
625 }
626
627 /** writes transformed problem which are valid in the current node to file
628 *
629 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
630 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
631 *
632 * @pre This method can be called if @p scip is in one of the following stages:
633 * - \ref SCIP_STAGE_TRANSFORMED
634 * - \ref SCIP_STAGE_INITPRESOLVE
635 * - \ref SCIP_STAGE_PRESOLVING
636 * - \ref SCIP_STAGE_EXITPRESOLVE
637 * - \ref SCIP_STAGE_PRESOLVED
638 * - \ref SCIP_STAGE_INITSOLVE
639 * - \ref SCIP_STAGE_SOLVING
640 * - \ref SCIP_STAGE_SOLVED
641 * - \ref SCIP_STAGE_EXITSOLVE
642 *
643 * @note If you want the write all constraints (including the once which are redundant for example), you need to set
644 * the parameter <write/allconss> to TRUE
645 */
SCIPwriteTransProblem(SCIP * scip,const char * filename,const char * extension,SCIP_Bool genericnames)646 SCIP_RETCODE SCIPwriteTransProblem(
647 SCIP* scip, /**< SCIP data structure */
648 const char* filename, /**< output file (or NULL for standard output) */
649 const char* extension, /**< extension of the desired file reader,
650 * or NULL if file extension should be used */
651 SCIP_Bool genericnames /**< using generic variable and constraint names? */
652 )
653 {
654 SCIP_RETCODE retcode;
655
656 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteTransProblem", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
657
658 assert( scip != NULL );
659 assert( scip->transprob != NULL );
660
661 retcode = writeProblem(scip, filename, extension, TRUE, genericnames);
662
663 /* check for write errors */
664 if( retcode == SCIP_FILECREATEERROR || retcode == SCIP_WRITEERROR || retcode == SCIP_PLUGINNOTFOUND )
665 return retcode;
666 else
667 {
668 SCIP_CALL( retcode );
669 }
670
671 return SCIP_OKAY;
672 }
673
674 /** frees problem and solution process data
675 *
676 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
677 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
678 *
679 * @pre This method can be called if @p scip is in one of the following stages:
680 * - \ref SCIP_STAGE_INIT
681 * - \ref SCIP_STAGE_PROBLEM
682 * - \ref SCIP_STAGE_TRANSFORMED
683 * - \ref SCIP_STAGE_PRESOLVING
684 * - \ref SCIP_STAGE_PRESOLVED
685 * - \ref SCIP_STAGE_SOLVING
686 * - \ref SCIP_STAGE_SOLVED
687 * - \ref SCIP_STAGE_FREE
688 *
689 * @post After this method was called, SCIP is in the following stage:
690 * - \ref SCIP_STAGE_INIT
691 */
SCIPfreeProb(SCIP * scip)692 SCIP_RETCODE SCIPfreeProb(
693 SCIP* scip /**< SCIP data structure */
694 )
695 {
696 SCIP_Bool transsolorig;
697
698 SCIP_CALL( SCIPcheckStage(scip, "SCIPfreeProb", TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
699
700 /* if we free the problem, we do not have to transfer transformed solutions to the original space, so temporarily disable it */
701 transsolorig = scip->set->misc_transsolsorig;
702 scip->set->misc_transsolsorig = FALSE;
703
704 SCIP_CALL( SCIPfreeTransform(scip) );
705 /* for some reason the free transform can generate events caught in the globalbnd eventhander
706 * which requires the concurrent so it must be freed afterwards this happened o instance fiber
707 */
708 SCIP_CALL( SCIPfreeConcurrent(scip) );
709
710 assert(scip->set->stage == SCIP_STAGE_INIT || scip->set->stage == SCIP_STAGE_PROBLEM);
711 scip->set->misc_transsolsorig = transsolorig;
712
713 if( scip->set->stage == SCIP_STAGE_PROBLEM )
714 {
715 int i;
716
717 /* free concsolvers and deinitialize the syncstore */
718 if( scip->set->nconcsolvers > 0 )
719 {
720 assert(SCIPsyncstoreIsInitialized(scip->syncstore));
721
722 SCIP_CALL( SCIPsetFreeConcsolvers(scip->set) );
723 SCIP_CALL( SCIPsyncstoreExit(scip->syncstore) );
724 }
725
726 /* deactivate all pricers */
727 for( i = scip->set->nactivepricers-1; i >= 0; --i )
728 {
729 SCIP_CALL( SCIPpricerDeactivate(scip->set->pricers[i], scip->set) );
730 }
731 assert(scip->set->nactivepricers == 0);
732
733 /* deactivate all Benders' decomposition */
734 for( i = scip->set->nactivebenders-1; i >= 0; --i )
735 {
736 SCIP_CALL( SCIPbendersDeactivate(scip->set->benders[i], scip->set) );
737 }
738 assert(scip->set->nactivebenders == 0);
739
740 /* free all debug data */
741 SCIP_CALL( SCIPdebugFreeDebugData(scip->set) );
742
743 /* free original primal solution candidate pool, original problem and problem statistics data structures */
744 if( scip->reopt != NULL )
745 {
746 SCIP_CALL( SCIPreoptFree(&scip->reopt, scip->set, scip->origprimal, scip->mem->probmem) );
747 }
748 SCIPdecompstoreFree(&scip->decompstore, SCIPblkmem(scip));
749 SCIP_CALL( SCIPconflictstoreFree(&scip->conflictstore, scip->mem->probmem, scip->set, scip->stat, scip->reopt) );
750 SCIP_CALL( SCIPprimalFree(&scip->origprimal, scip->mem->probmem) );
751 SCIP_CALL( SCIPprobFree(&scip->origprob, scip->messagehdlr, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->lp) );
752 SCIP_CALL( SCIPstatFree(&scip->stat, scip->mem->probmem) );
753
754 /* readers */
755 for( i = 0; i < scip->set->nreaders; ++i )
756 {
757 SCIP_CALL( SCIPreaderResetReadingTime(scip->set->readers[i]) );
758 }
759
760 /* switch stage to INIT */
761 scip->set->stage = SCIP_STAGE_INIT;
762 }
763 assert(scip->set->stage == SCIP_STAGE_INIT);
764
765 return SCIP_OKAY;
766 }
767
768 /** permutes parts of the problem data structure
769 *
770 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
771 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
772 *
773 * @pre This method can be called if @p scip is in one of the following stages:
774 * - \ref SCIP_STAGE_PROBLEM
775 * - \ref SCIP_STAGE_TRANSFORMED
776 *
777 * @todo This need to be changed to use the new random number generator implemented in random.c
778 */
SCIPpermuteProb(SCIP * scip,unsigned int randseed,SCIP_Bool permuteconss,SCIP_Bool permutebinvars,SCIP_Bool permuteintvars,SCIP_Bool permuteimplvars,SCIP_Bool permutecontvars)779 SCIP_RETCODE SCIPpermuteProb(
780 SCIP* scip, /**< SCIP data structure */
781 unsigned int randseed, /**< seed value for random generator */
782 SCIP_Bool permuteconss, /**< should the list of constraints in each constraint handler be permuted? */
783 SCIP_Bool permutebinvars, /**< should the list of binary variables be permuted? */
784 SCIP_Bool permuteintvars, /**< should the list of integer variables be permuted? */
785 SCIP_Bool permuteimplvars, /**< should the list of implicit integer variables be permuted? */
786 SCIP_Bool permutecontvars /**< should the list of continuous integer variables be permuted? */
787 )
788 {
789 SCIP_VAR** vars;
790 SCIP_CONSHDLR** conshdlrs;
791 SCIP_RANDNUMGEN* randnumgen;
792 SCIP_Bool permuted;
793 int nconshdlrs;
794 int nbinvars;
795 int nintvars;
796 int nimplvars;
797 int nvars;
798 int j;
799
800 assert(scip != NULL);
801 SCIP_CALL( SCIPcheckStage(scip, "SCIPpermuteProb", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
802
803 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, &nimplvars, NULL) );
804
805 assert(nvars == 0 || vars != NULL);
806 assert(nvars == nbinvars+nintvars+nimplvars+SCIPgetNContVars(scip));
807
808 conshdlrs = SCIPgetConshdlrs(scip);
809 nconshdlrs = SCIPgetNConshdlrs(scip);
810 assert(nconshdlrs == 0 || conshdlrs != NULL);
811
812 /* create a random number generator */
813 SCIP_CALL( SCIPcreateRandom(scip, &randnumgen, randseed, TRUE) );
814
815 /* The constraint handler should not be permuted since they are called w.r.t. to certain properties; besides
816 * that the "conshdlrs" array should stay in the order as it is since this array is used to copy the plugins for
817 * sub-SCIPs and contains the dependencies between the constraint handlers; for example the linear constraint
818 * handler stays in front of all constraint handler which can upgrade a linear constraint (such as logicor,
819 * setppc, and knapsack).
820 */
821
822 permuted = FALSE;
823
824 /* for each constraint handler, permute its constraints */
825 if( permuteconss )
826 {
827 int i;
828
829 /* we must only permute active constraints */
830 if( SCIPisTransformed(scip) && !SCIPprobIsPermuted(scip->transprob) )
831 {
832 /* loop over all constraint handlers */
833 for( i = 0; i < nconshdlrs; ++i )
834 {
835 SCIP_CONS** conss;
836 int nconss;
837
838 conss = SCIPconshdlrGetConss(conshdlrs[i]);
839 nconss = SCIPconshdlrGetNActiveConss(conshdlrs[i]);
840
841 assert(nconss == 0 || conss != NULL);
842
843 SCIPrandomPermuteArray(randnumgen, (void**)conss, 0, nconss);
844
845 /* readjust the mapping of constraints to array positions */
846 for( j = 0; j < nconss; ++j )
847 conss[j]->consspos = j;
848
849 permuted = TRUE;
850 }
851 }
852 else if( !SCIPisTransformed(scip) && !SCIPprobIsPermuted(scip->origprob) )
853 {
854 SCIP_CONS** conss = scip->origprob->conss;
855 int nconss = scip->origprob->nconss;
856
857 SCIPrandomPermuteArray(randnumgen, (void**)conss, 0, nconss);
858
859 for( j = 0; j < nconss; ++j )
860 {
861 assert(conss[j]->consspos == -1);
862 conss[j]->addarraypos = j;
863 }
864
865 permuted = TRUE;
866 }
867 }
868
869 /* permute binary variables */
870 if( permutebinvars && !SCIPprobIsPermuted(scip->origprob) )
871 {
872 SCIPrandomPermuteArray(randnumgen, (void**)vars, 0, nbinvars);
873
874 /* readjust the mapping of variables to array positions */
875 for( j = 0; j < nbinvars; ++j )
876 vars[j]->probindex = j;
877
878 permuted = TRUE;
879 }
880
881 /* permute general integer variables */
882 if( permuteintvars && !SCIPprobIsPermuted(scip->origprob) )
883 {
884 SCIPrandomPermuteArray(randnumgen, (void**)vars, nbinvars, nbinvars+nintvars);
885
886 /* readjust the mapping of variables to array positions */
887 for( j = nbinvars; j < nbinvars+nintvars; ++j )
888 vars[j]->probindex = j;
889
890 permuted = TRUE;
891 }
892
893 /* permute general integer variables */
894 if( permuteimplvars && !SCIPprobIsPermuted(scip->origprob) )
895 {
896 SCIPrandomPermuteArray(randnumgen, (void**)vars, nbinvars+nintvars, nbinvars+nintvars+nimplvars);
897
898 /* readjust the mapping of variables to array positions */
899 for( j = nbinvars+nintvars; j < nbinvars+nintvars+nimplvars; ++j )
900 vars[j]->probindex = j;
901
902 permuted = TRUE;
903 }
904
905 /* permute general integer variables */
906 if( permutecontvars && !SCIPprobIsPermuted(scip->origprob) )
907 {
908 SCIPrandomPermuteArray(randnumgen, (void**)vars, nbinvars+nintvars+nimplvars, nvars);
909
910 /* readjust the mapping of variables to array positions */
911 for( j = nbinvars+nintvars+nimplvars; j < nvars; ++j )
912 vars[j]->probindex = j;
913
914 permuted = TRUE;
915 }
916
917 if( permuted && SCIPisTransformed(scip) )
918 {
919 assert(!SCIPprobIsPermuted(scip->transprob));
920
921 /* mark tranformed problem as permuted */
922 SCIPprobMarkPermuted(scip->transprob);
923
924 SCIPmessagePrintVerbInfo(scip->messagehdlr, scip->set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
925 "permute transformed problem using random seed %u\n", randseed);
926 }
927 else if( permuted && !SCIPisTransformed(scip) )
928 {
929 assert(!SCIPprobIsPermuted(scip->origprob));
930
931 /* mark original problem as permuted */
932 SCIPprobMarkPermuted(scip->origprob);
933
934 SCIPmessagePrintVerbInfo(scip->messagehdlr, scip->set->disp_verblevel, SCIP_VERBLEVEL_HIGH,
935 "permute original problem using random seed %u\n", randseed);
936 }
937
938 /* free random number generator */
939 SCIPfreeRandom(scip, &randnumgen);
940
941 return SCIP_OKAY;
942 }
943
944 /** gets user problem data
945 *
946 * @return a SCIP_PROBDATA pointer, or NULL if no problem data was allocated
947 *
948 * @pre This method can be called if @p scip is in one of the following stages:
949 * - \ref SCIP_STAGE_PROBLEM
950 * - \ref SCIP_STAGE_TRANSFORMING
951 * - \ref SCIP_STAGE_TRANSFORMED
952 * - \ref SCIP_STAGE_INITPRESOLVE
953 * - \ref SCIP_STAGE_PRESOLVING
954 * - \ref SCIP_STAGE_EXITPRESOLVE
955 * - \ref SCIP_STAGE_PRESOLVED
956 * - \ref SCIP_STAGE_INITSOLVE
957 * - \ref SCIP_STAGE_SOLVING
958 * - \ref SCIP_STAGE_SOLVED
959 * - \ref SCIP_STAGE_EXITSOLVE
960 * - \ref SCIP_STAGE_FREETRANS
961 */
SCIPgetProbData(SCIP * scip)962 SCIP_PROBDATA* SCIPgetProbData(
963 SCIP* scip /**< SCIP data structure */
964 )
965 {
966 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetProbData", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
967
968 switch( scip->set->stage )
969 {
970 case SCIP_STAGE_PROBLEM:
971 return SCIPprobGetData(scip->origprob);
972
973 case SCIP_STAGE_TRANSFORMING:
974 case SCIP_STAGE_TRANSFORMED:
975 case SCIP_STAGE_INITPRESOLVE:
976 case SCIP_STAGE_PRESOLVING:
977 case SCIP_STAGE_EXITPRESOLVE:
978 case SCIP_STAGE_PRESOLVED:
979 case SCIP_STAGE_INITSOLVE:
980 case SCIP_STAGE_SOLVING:
981 case SCIP_STAGE_SOLVED:
982 case SCIP_STAGE_EXITSOLVE:
983 case SCIP_STAGE_FREETRANS:
984 return SCIPprobGetData(scip->transprob);
985
986 default:
987 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
988 SCIPABORT();
989 return NULL; /*lint !e527*/
990 } /*lint !e788*/
991 }
992
993 /** sets user problem data
994 *
995 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
996 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
997 *
998 * @pre This method can be called if @p scip is in one of the following stages:
999 * - \ref SCIP_STAGE_PROBLEM
1000 * - \ref SCIP_STAGE_TRANSFORMING
1001 * - \ref SCIP_STAGE_TRANSFORMED
1002 * - \ref SCIP_STAGE_INITPRESOLVE
1003 * - \ref SCIP_STAGE_PRESOLVING
1004 * - \ref SCIP_STAGE_EXITPRESOLVE
1005 * - \ref SCIP_STAGE_PRESOLVED
1006 * - \ref SCIP_STAGE_INITSOLVE
1007 * - \ref SCIP_STAGE_SOLVING
1008 * - \ref SCIP_STAGE_SOLVED
1009 * - \ref SCIP_STAGE_EXITSOLVE
1010 * - \ref SCIP_STAGE_FREETRANS
1011 */
SCIPsetProbData(SCIP * scip,SCIP_PROBDATA * probdata)1012 SCIP_RETCODE SCIPsetProbData(
1013 SCIP* scip, /**< SCIP data structure */
1014 SCIP_PROBDATA* probdata /**< user problem data to use */
1015 )
1016 {
1017 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbData", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1018
1019 switch( scip->set->stage )
1020 {
1021 case SCIP_STAGE_PROBLEM:
1022 SCIPprobSetData(scip->origprob, probdata);
1023 return SCIP_OKAY;
1024
1025 case SCIP_STAGE_TRANSFORMING:
1026 case SCIP_STAGE_TRANSFORMED:
1027 case SCIP_STAGE_INITPRESOLVE:
1028 case SCIP_STAGE_PRESOLVING:
1029 case SCIP_STAGE_EXITPRESOLVE:
1030 case SCIP_STAGE_PRESOLVED:
1031 case SCIP_STAGE_INITSOLVE:
1032 case SCIP_STAGE_SOLVING:
1033 case SCIP_STAGE_SOLVED:
1034 case SCIP_STAGE_EXITSOLVE:
1035 case SCIP_STAGE_FREETRANS:
1036 SCIPprobSetData(scip->transprob, probdata);
1037 return SCIP_OKAY;
1038
1039 case SCIP_STAGE_INIT:
1040 case SCIP_STAGE_FREE:
1041 default:
1042 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1043 return SCIP_INVALIDCALL;
1044 }
1045 }
1046
1047 /** returns name of the current problem instance
1048 *
1049 * @return name of the current problem instance
1050 *
1051 * @pre This method can be called if @p scip is in one of the following stages:
1052 * - \ref SCIP_STAGE_PROBLEM
1053 * - \ref SCIP_STAGE_TRANSFORMING
1054 * - \ref SCIP_STAGE_TRANSFORMED
1055 * - \ref SCIP_STAGE_INITPRESOLVE
1056 * - \ref SCIP_STAGE_PRESOLVING
1057 * - \ref SCIP_STAGE_EXITPRESOLVE
1058 * - \ref SCIP_STAGE_PRESOLVED
1059 * - \ref SCIP_STAGE_INITSOLVE
1060 * - \ref SCIP_STAGE_SOLVING
1061 * - \ref SCIP_STAGE_SOLVED
1062 * - \ref SCIP_STAGE_EXITSOLVE
1063 * - \ref SCIP_STAGE_FREETRANS
1064 */
SCIPgetProbName(SCIP * scip)1065 const char* SCIPgetProbName(
1066 SCIP* scip /**< SCIP data structure */
1067 )
1068 {
1069 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetProbName", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1070
1071 return SCIPprobGetName(scip->origprob);
1072 }
1073
1074 /** sets name of the current problem instance
1075 *
1076 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1077 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1078 *
1079 * @pre This method can be called if @p scip is in one of the following stages:
1080 * - \ref SCIP_STAGE_PROBLEM
1081 * - \ref SCIP_STAGE_TRANSFORMING
1082 * - \ref SCIP_STAGE_TRANSFORMED
1083 * - \ref SCIP_STAGE_INITPRESOLVE
1084 * - \ref SCIP_STAGE_PRESOLVING
1085 * - \ref SCIP_STAGE_EXITPRESOLVE
1086 * - \ref SCIP_STAGE_PRESOLVED
1087 * - \ref SCIP_STAGE_INITSOLVE
1088 * - \ref SCIP_STAGE_SOLVING
1089 * - \ref SCIP_STAGE_SOLVED
1090 * - \ref SCIP_STAGE_EXITSOLVE
1091 * - \ref SCIP_STAGE_FREETRANS
1092 */
SCIPsetProbName(SCIP * scip,const char * name)1093 SCIP_RETCODE SCIPsetProbName(
1094 SCIP* scip, /**< SCIP data structure */
1095 const char* name /**< name to be set */
1096 )
1097 {
1098 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetProbName", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1099
1100 return SCIPprobSetName(scip->origprob, name);
1101 }
1102
1103 /** changes the objective function of the original problem.
1104 *
1105 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1106 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1107 *
1108 * @pre This method can be called if @p scip is in one of the following stages:
1109 * - \ref SCIP_STAGE_PROBLEM
1110 * - \ref SCIP_STAGE_PRESOLVED
1111 *
1112 * @note This method should be only used to change the objective function during two reoptimization runs and is only
1113 * recommended to an experienced user.
1114 *
1115 * @note All variables not given in \p vars array are assumed to have an objective coefficient of zero.
1116 */
SCIPchgReoptObjective(SCIP * scip,SCIP_OBJSENSE objsense,SCIP_VAR ** vars,SCIP_Real * coefs,int nvars)1117 SCIP_RETCODE SCIPchgReoptObjective(
1118 SCIP* scip, /**< SCIP data structure */
1119 SCIP_OBJSENSE objsense, /**< new objective function */
1120 SCIP_VAR** vars, /**< original problem variables */
1121 SCIP_Real* coefs, /**< objective coefficients */
1122 int nvars /**< variables in vars array */
1123 )
1124 {
1125 SCIP_VAR** origvars;
1126 int norigvars;
1127 int i;
1128
1129 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgReoptObjective", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1130
1131 assert(nvars == 0 || vars != NULL);
1132 assert(nvars == 0 || coefs != NULL);
1133
1134 origvars = scip->origprob->vars;
1135 norigvars = scip->origprob->nvars;
1136
1137 #ifdef SCIP_MORE_DEBUG
1138 SCIPdebugMsg(scip, "objective function need to be set:\n");
1139 for( i = 0; i < nvars; i++ )
1140 {
1141 if( !SCIPisZero(scip, coefs[i]) )
1142 SCIPdebugMsg(scip, "%s%g <%s> ", SCIPisPositive(scip, coefs[i]) ? "+" : "", coefs[i], SCIPvarGetName(vars[i]));
1143 }
1144 SCIPdebugMsg(scip, "\n");
1145 #endif
1146
1147 /* Set all coefficients of original variables to 0, since we will add the new objective coefficients later. */
1148 for( i = 0; i < norigvars; i++ )
1149 {
1150 SCIP_CALL( SCIPchgVarObj(scip, origvars[i], 0.0) );
1151 }
1152
1153 if( scip->set->stage >= SCIP_STAGE_TRANSFORMED )
1154 {
1155 /* In order to avoid numerical troubles, also explicitly set all transformed objective coefficients to 0. */
1156 for( i = 0; i < scip->transprob->nvars; i++ )
1157 {
1158 SCIP_CALL( SCIPchgVarObj(scip, scip->transprob->vars[i], 0.0) );
1159 }
1160 }
1161
1162 /* reset objective data of original problem */
1163 scip->origprob->objscale = 1.0;
1164 scip->origprob->objsense = objsense;
1165 scip->origprob->objoffset = 0.0;
1166 scip->origprob->objisintegral = FALSE;
1167
1168 if( scip->set->stage >= SCIP_STAGE_TRANSFORMED )
1169 {
1170 /* reset objective data of transformed problem */
1171 scip->transprob->objscale = 1.0;
1172 scip->transprob->objsense = objsense;
1173 scip->transprob->objoffset = 0.0;
1174 scip->transprob->objisintegral = FALSE;
1175 }
1176
1177 /* set new objective values */
1178 for( i = 0; i < nvars; ++i )
1179 {
1180 if( !SCIPvarIsOriginal(vars[i]) )
1181 {
1182 SCIPerrorMessage("Cannot handle variable <%s> (status: %d) in SCIPchgReoptObjective().\n",
1183 SCIPvarGetName(vars[i]), SCIPvarGetStatus(vars[i]));
1184 return SCIP_INVALIDDATA;
1185 }
1186
1187 /* Add coefficients because this gets transferred to the transformed problem (the coefficients were set to 0 above). */
1188 SCIP_CALL( SCIPaddVarObj(scip, vars[i], coefs[i]) );
1189 }
1190
1191 #ifdef SCIP_MORE_DEBUG
1192 SCIPdebugMsg(scip, "new objective function:\n");
1193 for( i = 0; i < norigvars; i++ )
1194 {
1195 SCIP_Real objval = SCIPvarGetObj(origvars[i]);
1196 if( !SCIPisZero(scip, objval) )
1197 SCIPdebugMsg(scip, "%s%g <%s> ", SCIPisPositive(scip, objval) ? "+" : "", objval, SCIPvarGetName(origvars[i]));
1198 }
1199 SCIPdebugMsg(scip, "\n");
1200 #endif
1201
1202 return SCIP_OKAY;
1203 }
1204
1205 /** returns objective sense of original problem
1206 *
1207 * @return objective sense of original problem
1208 *
1209 * @pre This method can be called if @p scip is in one of the following stages:
1210 * - \ref SCIP_STAGE_PROBLEM
1211 * - \ref SCIP_STAGE_TRANSFORMING
1212 * - \ref SCIP_STAGE_TRANSFORMED
1213 * - \ref SCIP_STAGE_INITPRESOLVE
1214 * - \ref SCIP_STAGE_PRESOLVING
1215 * - \ref SCIP_STAGE_EXITPRESOLVE
1216 * - \ref SCIP_STAGE_PRESOLVED
1217 * - \ref SCIP_STAGE_INITSOLVE
1218 * - \ref SCIP_STAGE_SOLVING
1219 * - \ref SCIP_STAGE_SOLVED
1220 * - \ref SCIP_STAGE_EXITSOLVE
1221 * - \ref SCIP_STAGE_FREETRANS
1222 */
SCIPgetObjsense(SCIP * scip)1223 SCIP_OBJSENSE SCIPgetObjsense(
1224 SCIP* scip /**< SCIP data structure */
1225 )
1226 {
1227 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetObjsense", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1228
1229 return scip->origprob->objsense;
1230 }
1231
1232 /** sets objective sense of problem
1233 *
1234 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1235 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1236 *
1237 * @pre This method can be called if @p scip is in one of the following stages:
1238 * - \ref SCIP_STAGE_PROBLEM
1239 */
SCIPsetObjsense(SCIP * scip,SCIP_OBJSENSE objsense)1240 SCIP_RETCODE SCIPsetObjsense(
1241 SCIP* scip, /**< SCIP data structure */
1242 SCIP_OBJSENSE objsense /**< new objective sense */
1243 )
1244 {
1245 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetObjsense", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1246
1247 if( objsense != SCIP_OBJSENSE_MAXIMIZE && objsense != SCIP_OBJSENSE_MINIMIZE )
1248 {
1249 SCIPerrorMessage("invalid objective sense\n");
1250 return SCIP_INVALIDDATA;
1251 }
1252
1253 SCIPprobSetObjsense(scip->origprob, objsense);
1254
1255 return SCIP_OKAY;
1256 }
1257
1258 /** adds offset of objective function
1259 *
1260 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1261 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1262 *
1263 * @pre This method can be called if @p scip is in one of the following stages:
1264 * - \ref SCIP_STAGE_PRESOLVING
1265 */
SCIPaddObjoffset(SCIP * scip,SCIP_Real addval)1266 SCIP_RETCODE SCIPaddObjoffset(
1267 SCIP* scip, /**< SCIP data structure */
1268 SCIP_Real addval /**< value to add to objective offset */
1269 )
1270 {
1271 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddObjoffset", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1272
1273 SCIPprobAddObjoffset(scip->transprob, addval);
1274 SCIP_CALL( SCIPprimalUpdateObjoffset(scip->primal, SCIPblkmem(scip), scip->set, scip->stat, scip->eventfilter,
1275 scip->eventqueue, scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp) );
1276
1277 return SCIP_OKAY;
1278 }
1279
1280 /** adds offset of objective function to original problem and to all existing solution in original space
1281 *
1282 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1283 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1284 *
1285 * @pre This method can be called if @p scip is in one of the following stages:
1286 * - \ref SCIP_STAGE_PROBLEM
1287 */
SCIPaddOrigObjoffset(SCIP * scip,SCIP_Real addval)1288 SCIP_RETCODE SCIPaddOrigObjoffset(
1289 SCIP* scip, /**< SCIP data structure */
1290 SCIP_Real addval /**< value to add to objective offset */
1291 )
1292 {
1293 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddOrigObjoffset", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1294
1295 scip->origprob->objoffset += addval;
1296 SCIPprimalAddOrigObjoffset(scip->origprimal, scip->set, addval);
1297
1298 return SCIP_OKAY;
1299 }
1300
1301 /** returns the objective offset of the original problem
1302 *
1303 * @return the objective offset of the original problem
1304 *
1305 * @pre This method can be called if @p scip is in one of the following stages:
1306 * - \ref SCIP_STAGE_PROBLEM
1307 * - \ref SCIP_STAGE_TRANSFORMING
1308 * - \ref SCIP_STAGE_TRANSFORMED
1309 * - \ref SCIP_STAGE_INITPRESOLVE
1310 * - \ref SCIP_STAGE_PRESOLVING
1311 * - \ref SCIP_STAGE_EXITPRESOLVE
1312 * - \ref SCIP_STAGE_PRESOLVED
1313 * - \ref SCIP_STAGE_INITSOLVE
1314 * - \ref SCIP_STAGE_SOLVING
1315 * - \ref SCIP_STAGE_SOLVED
1316 */
SCIPgetOrigObjoffset(SCIP * scip)1317 SCIP_Real SCIPgetOrigObjoffset(
1318 SCIP* scip /**< SCIP data structure */
1319 )
1320 {
1321 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetOrigObjoffset", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1322
1323 return scip->origprob->objoffset;
1324 }
1325
1326 /** returns the objective scale of the original problem
1327 *
1328 * @return the objective scale of the original problem
1329 *
1330 * @pre This method can be called if @p scip is in one of the following stages:
1331 * - \ref SCIP_STAGE_PROBLEM
1332 * - \ref SCIP_STAGE_TRANSFORMING
1333 * - \ref SCIP_STAGE_TRANSFORMED
1334 * - \ref SCIP_STAGE_INITPRESOLVE
1335 * - \ref SCIP_STAGE_PRESOLVING
1336 * - \ref SCIP_STAGE_EXITPRESOLVE
1337 * - \ref SCIP_STAGE_PRESOLVED
1338 * - \ref SCIP_STAGE_INITSOLVE
1339 * - \ref SCIP_STAGE_SOLVING
1340 * - \ref SCIP_STAGE_SOLVED
1341 */
SCIPgetOrigObjscale(SCIP * scip)1342 SCIP_Real SCIPgetOrigObjscale(
1343 SCIP* scip /**< SCIP data structure */
1344 )
1345 {
1346 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetOrigObjscale", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1347
1348 return scip->origprob->objscale;
1349 }
1350
1351 /** returns the objective offset of the transformed problem
1352 *
1353 * @return the objective offset of the transformed problem
1354 *
1355 * @pre This method can be called if @p scip is in one of the following stages:
1356 * - \ref SCIP_STAGE_TRANSFORMED
1357 * - \ref SCIP_STAGE_INITPRESOLVE
1358 * - \ref SCIP_STAGE_PRESOLVING
1359 * - \ref SCIP_STAGE_EXITPRESOLVE
1360 * - \ref SCIP_STAGE_PRESOLVED
1361 * - \ref SCIP_STAGE_INITSOLVE
1362 * - \ref SCIP_STAGE_SOLVING
1363 * - \ref SCIP_STAGE_SOLVED
1364 */
SCIPgetTransObjoffset(SCIP * scip)1365 SCIP_Real SCIPgetTransObjoffset(
1366 SCIP* scip /**< SCIP data structure */
1367 )
1368 {
1369 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetTransObjoffset", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1370
1371 return scip->transprob->objoffset;
1372 }
1373
1374 /** returns the objective scale of the transformed problem
1375 *
1376 * @return the objective scale of the transformed problem
1377 *
1378 * @pre This method can be called if @p scip is in one of the following stages:
1379 * - \ref SCIP_STAGE_TRANSFORMED
1380 * - \ref SCIP_STAGE_INITPRESOLVE
1381 * - \ref SCIP_STAGE_PRESOLVING
1382 * - \ref SCIP_STAGE_EXITPRESOLVE
1383 * - \ref SCIP_STAGE_PRESOLVED
1384 * - \ref SCIP_STAGE_INITSOLVE
1385 * - \ref SCIP_STAGE_SOLVING
1386 * - \ref SCIP_STAGE_SOLVED
1387 */
SCIPgetTransObjscale(SCIP * scip)1388 SCIP_Real SCIPgetTransObjscale(
1389 SCIP* scip /**< SCIP data structure */
1390 )
1391 {
1392 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetTransObjscale", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1393
1394 return scip->transprob->objscale;
1395 }
1396
1397 /** sets limit on objective function, such that only solutions better than this limit are accepted
1398 *
1399 * @note SCIP will only look for solutions with a strictly better objective value, thus, e.g., prune
1400 * all branch-and-bound nodes with dual bound equal or worse to the objective limit.
1401 * However, SCIP will also collect solutions with objective value worse than the objective limit and
1402 * use them to run improvement heuristics on them.
1403 * @note If SCIP can prove that there exists no solution with a strictly better objective value, the solving status
1404 * will normally be infeasible (the objective limit is interpreted as part of the problem).
1405 * The only exception is that by chance, SCIP found a solution with the same objective value and thus
1406 * proved the optimality of this solution, resulting in solution status optimal.
1407 *
1408 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1409 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1410 *
1411 * @pre This method can be called if @p scip is in one of the following stages:
1412 * - \ref SCIP_STAGE_PROBLEM
1413 * - \ref SCIP_STAGE_TRANSFORMED
1414 * - \ref SCIP_STAGE_INITPRESOLVE
1415 * - \ref SCIP_STAGE_PRESOLVING
1416 * - \ref SCIP_STAGE_EXITPRESOLVE
1417 * - \ref SCIP_STAGE_PRESOLVED
1418 * - \ref SCIP_STAGE_SOLVING
1419 */
SCIPsetObjlimit(SCIP * scip,SCIP_Real objlimit)1420 SCIP_RETCODE SCIPsetObjlimit(
1421 SCIP* scip, /**< SCIP data structure */
1422 SCIP_Real objlimit /**< new primal objective limit */
1423 )
1424 {
1425 SCIP_Real oldobjlimit;
1426
1427 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetObjlimit", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1428
1429 switch( scip->set->stage )
1430 {
1431 case SCIP_STAGE_PROBLEM:
1432 SCIPprobSetObjlim(scip->origprob, objlimit);
1433 break;
1434 case SCIP_STAGE_PRESOLVED:
1435 oldobjlimit = SCIPprobGetObjlim(scip->origprob, scip->set);
1436 assert(oldobjlimit == SCIPprobGetObjlim(scip->transprob, scip->set)); /*lint !e777*/
1437 if( SCIPtransformObj(scip, objlimit) > SCIPprobInternObjval(scip->transprob, scip->origprob, scip->set, oldobjlimit) && ! scip->set->reopt_enable)
1438 {
1439 SCIPerrorMessage("cannot relax objective limit from %.15g to %.15g in presolved stage.\n", oldobjlimit, objlimit);
1440 return SCIP_INVALIDDATA;
1441 }
1442 SCIPprobSetObjlim(scip->origprob, objlimit);
1443 SCIPprobSetObjlim(scip->transprob, objlimit);
1444 SCIP_CALL( SCIPprimalUpdateObjlimit(scip->primal, scip->mem->probmem, scip->set, scip->stat, scip->eventfilter,
1445 scip->eventqueue, scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp) );
1446 break;
1447
1448 case SCIP_STAGE_TRANSFORMED:
1449 case SCIP_STAGE_INITPRESOLVE:
1450 case SCIP_STAGE_PRESOLVING:
1451 case SCIP_STAGE_EXITPRESOLVE:
1452 case SCIP_STAGE_SOLVING:
1453 oldobjlimit = SCIPprobGetObjlim(scip->origprob, scip->set);
1454 assert(oldobjlimit == SCIPprobGetObjlim(scip->transprob, scip->set)); /*lint !e777*/
1455 if( SCIPtransformObj(scip, objlimit) > SCIPprobInternObjval(scip->transprob, scip->origprob, scip->set, oldobjlimit) )
1456 {
1457 SCIPerrorMessage("cannot relax objective limit from %.15g to %.15g after problem was transformed.\n", oldobjlimit, objlimit);
1458 return SCIP_INVALIDDATA;
1459 }
1460 SCIPprobSetObjlim(scip->origprob, objlimit);
1461 SCIPprobSetObjlim(scip->transprob, objlimit);
1462 SCIP_CALL( SCIPprimalUpdateObjlimit(scip->primal, scip->mem->probmem, scip->set, scip->stat, scip->eventfilter,
1463 scip->eventqueue, scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp) );
1464 break;
1465
1466 default:
1467 SCIPerrorMessage("method is not callable in SCIP stage <%d>\n", scip->set->stage);
1468 return SCIP_INVALIDCALL;
1469 } /*lint !e788*/
1470
1471 return SCIP_OKAY;
1472 }
1473
1474 /** returns current limit on objective function
1475 *
1476 * @return the current objective limit of the original problem
1477 *
1478 * @pre This method can be called if @p scip is in one of the following stages:
1479 * - \ref SCIP_STAGE_PROBLEM
1480 * - \ref SCIP_STAGE_TRANSFORMING
1481 * - \ref SCIP_STAGE_TRANSFORMED
1482 * - \ref SCIP_STAGE_INITPRESOLVE
1483 * - \ref SCIP_STAGE_PRESOLVING
1484 * - \ref SCIP_STAGE_EXITPRESOLVE
1485 * - \ref SCIP_STAGE_PRESOLVED
1486 * - \ref SCIP_STAGE_INITSOLVE
1487 * - \ref SCIP_STAGE_SOLVING
1488 * - \ref SCIP_STAGE_SOLVED
1489 */
SCIPgetObjlimit(SCIP * scip)1490 SCIP_Real SCIPgetObjlimit(
1491 SCIP* scip /**< SCIP data structure */
1492 )
1493 {
1494 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetObjlimit", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1495
1496 return SCIPprobGetObjlim(scip->origprob, scip->set);
1497 }
1498
1499 /** informs SCIP, that the objective value is always integral in every feasible solution
1500 *
1501 * @return \ref SCIP_OKAY is returned if everything worked. otherwise a suitable error code is passed. see \ref
1502 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1503 *
1504 * @pre This method can be called if @p scip is in one of the following stages:
1505 * - \ref SCIP_STAGE_PROBLEM
1506 * - \ref SCIP_STAGE_TRANSFORMING
1507 * - \ref SCIP_STAGE_INITPRESOLVE
1508 * - \ref SCIP_STAGE_EXITPRESOLVE
1509 * - \ref SCIP_STAGE_SOLVING
1510 *
1511 * @note This function should be used to inform SCIP that the objective function is integral, helping to improve the
1512 * performance. This is useful when using column generation. If no column generation (pricing) is used, SCIP
1513 * automatically detects whether the objective function is integral or can be scaled to be integral. However, in
1514 * any case, the user has to make sure that no variable is added during the solving process that destroys this
1515 * property.
1516 */
SCIPsetObjIntegral(SCIP * scip)1517 SCIP_RETCODE SCIPsetObjIntegral(
1518 SCIP* scip /**< SCIP data structure */
1519 )
1520 {
1521 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetObjIntegral", FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1522
1523 switch( scip->set->stage )
1524 {
1525 case SCIP_STAGE_PROBLEM:
1526 SCIPprobSetObjIntegral(scip->origprob);
1527 return SCIP_OKAY;
1528
1529 case SCIP_STAGE_TRANSFORMING:
1530 case SCIP_STAGE_PRESOLVING:
1531 case SCIP_STAGE_PRESOLVED:
1532 case SCIP_STAGE_SOLVING:
1533 SCIPprobSetObjIntegral(scip->transprob);
1534 return SCIP_OKAY;
1535
1536 default:
1537 SCIPerrorMessage("method is not callable in SCIP stage <%d>\n", scip->set->stage);
1538 return SCIP_INVALIDCALL;
1539 } /*lint !e788*/
1540 }
1541
1542 /** returns whether the objective value is known to be integral in every feasible solution
1543 *
1544 * @return TRUE, if objective value is known to be always integral, otherwise FALSE
1545 *
1546 * @pre This method can be called if @p scip is in one of the following stages:
1547 * - \ref SCIP_STAGE_PROBLEM
1548 * - \ref SCIP_STAGE_TRANSFORMING
1549 * - \ref SCIP_STAGE_INITPRESOLVE
1550 * - \ref SCIP_STAGE_PRESOLVING
1551 * - \ref SCIP_STAGE_EXITPRESOLVE
1552 * - \ref SCIP_STAGE_PRESOLVED
1553 * - \ref SCIP_STAGE_SOLVING
1554 *
1555 * @note If no pricing is performed, SCIP automatically detects whether the objective function is integral or can be
1556 * scaled to be integral, helping to improve performance. This function returns the result. Otherwise
1557 * SCIPsetObjIntegral() can be used to inform SCIP. However, in any case, the user has to make sure that no
1558 * variable is added during the solving process that destroys this property.
1559 */
SCIPisObjIntegral(SCIP * scip)1560 SCIP_Bool SCIPisObjIntegral(
1561 SCIP* scip /**< SCIP data structure */
1562 )
1563 {
1564 int v;
1565
1566 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisObjIntegral", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1567
1568 switch( scip->set->stage )
1569 {
1570 case SCIP_STAGE_PROBLEM:
1571 /* if the user explicitly added the information that there is an integral objective, return TRUE */
1572 if( SCIPprobIsObjIntegral(scip->origprob) )
1573 return TRUE;
1574
1575 /* if there exist unknown variables, we cannot conclude that the objective value is always integral */
1576 if ( scip->set->nactivepricers != 0 )
1577 return FALSE;
1578
1579 /* if the objective value offset is fractional, the value itself is possibly fractional */
1580 if ( ! SCIPisIntegral(scip, scip->origprob->objoffset) )
1581 return FALSE;
1582
1583 /* scan through the variables */
1584 for (v = 0; v < scip->origprob->nvars; ++v)
1585 {
1586 SCIP_Real obj;
1587
1588 /* get objective value of variable */
1589 obj = SCIPvarGetObj(scip->origprob->vars[v]);
1590
1591 /* check, if objective value is non-zero */
1592 if ( ! SCIPisZero(scip, obj) )
1593 {
1594 /* if variable's objective value is fractional, the problem's objective value may also be fractional */
1595 if ( ! SCIPisIntegral(scip, obj) )
1596 break;
1597
1598 /* if variable with non-zero objective value is continuous, the problem's objective value may be fractional */
1599 if ( SCIPvarGetType(scip->origprob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
1600 break;
1601 }
1602 }
1603
1604 /* we do not store the result, since we assume that the original problem might be changed */
1605 if ( v == scip->origprob->nvars )
1606 return TRUE;
1607 return FALSE;
1608
1609 case SCIP_STAGE_TRANSFORMING:
1610 case SCIP_STAGE_INITPRESOLVE:
1611 case SCIP_STAGE_PRESOLVING:
1612 case SCIP_STAGE_EXITPRESOLVE:
1613 case SCIP_STAGE_PRESOLVED:
1614 case SCIP_STAGE_SOLVING:
1615 return SCIPprobIsObjIntegral(scip->transprob);
1616
1617 default:
1618 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1619 SCIPABORT();
1620 return FALSE; /*lint !e527*/
1621 } /*lint !e788*/
1622 }
1623
1624 /** returns the Euclidean norm of the objective function vector (available only for transformed problem)
1625 *
1626 * @return the Euclidean norm of the transformed objective function vector
1627 *
1628 * @pre This method can be called if @p scip is in one of the following stages:
1629 * - \ref SCIP_STAGE_TRANSFORMED
1630 * - \ref SCIP_STAGE_INITPRESOLVE
1631 * - \ref SCIP_STAGE_PRESOLVING
1632 * - \ref SCIP_STAGE_EXITPRESOLVE
1633 * - \ref SCIP_STAGE_PRESOLVED
1634 * - \ref SCIP_STAGE_INITSOLVE
1635 * - \ref SCIP_STAGE_SOLVING
1636 * - \ref SCIP_STAGE_SOLVED
1637 * - \ref SCIP_STAGE_EXITSOLVE
1638 */
SCIPgetObjNorm(SCIP * scip)1639 SCIP_Real SCIPgetObjNorm(
1640 SCIP* scip /**< SCIP data structure */
1641 )
1642 {
1643 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetObjNorm", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1644
1645 if( scip->lp->objsqrnormunreliable )
1646 SCIPlpRecalculateObjSqrNorm(scip->set, scip->lp);
1647 assert(!scip->lp->objsqrnormunreliable);
1648
1649 return SCIPlpGetObjNorm(scip->lp);
1650 }
1651
1652 /** adds variable to the problem
1653 *
1654 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1655 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1656 *
1657 * @pre This method can be called if @p scip is in one of the following stages:
1658 * - \ref SCIP_STAGE_PROBLEM
1659 * - \ref SCIP_STAGE_TRANSFORMING
1660 * - \ref SCIP_STAGE_INITPRESOLVE
1661 * - \ref SCIP_STAGE_PRESOLVING
1662 * - \ref SCIP_STAGE_EXITPRESOLVE
1663 * - \ref SCIP_STAGE_PRESOLVED
1664 * - \ref SCIP_STAGE_SOLVING
1665 */
SCIPaddVar(SCIP * scip,SCIP_VAR * var)1666 SCIP_RETCODE SCIPaddVar(
1667 SCIP* scip, /**< SCIP data structure */
1668 SCIP_VAR* var /**< variable to add */
1669 )
1670 {
1671 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVar", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1672
1673 /* avoid inserting the same variable twice */
1674 if( SCIPvarGetProbindex(var) != -1 )
1675 return SCIP_OKAY;
1676
1677 /* insert the negation variable x instead of the negated variable x' in x' = offset - x */
1678 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
1679 {
1680 assert(SCIPvarGetNegationVar(var) != NULL);
1681 SCIP_CALL( SCIPaddVar(scip, SCIPvarGetNegationVar(var)) );
1682 return SCIP_OKAY;
1683 }
1684
1685 switch( scip->set->stage )
1686 {
1687 case SCIP_STAGE_PROBLEM:
1688 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL )
1689 {
1690 SCIPerrorMessage("cannot add transformed variables to original problem\n");
1691 return SCIP_INVALIDDATA;
1692 }
1693 SCIP_CALL( SCIPprobAddVar(scip->origprob, scip->mem->probmem, scip->set, scip->lp, scip->branchcand,
1694 scip->eventfilter, scip->eventqueue, var) );
1695 return SCIP_OKAY;
1696
1697 case SCIP_STAGE_TRANSFORMING:
1698 case SCIP_STAGE_INITPRESOLVE:
1699 case SCIP_STAGE_PRESOLVING:
1700 case SCIP_STAGE_EXITPRESOLVE:
1701 case SCIP_STAGE_PRESOLVED:
1702 case SCIP_STAGE_SOLVING:
1703 /* check variable's status */
1704 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
1705 {
1706 SCIPerrorMessage("cannot add original variables to transformed problem\n");
1707 return SCIP_INVALIDDATA;
1708 }
1709 else if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
1710 {
1711 SCIPerrorMessage("cannot add fixed or aggregated variables to transformed problem\n");
1712 return SCIP_INVALIDDATA;
1713 }
1714 SCIP_CALL( SCIPprobAddVar(scip->transprob, scip->mem->probmem, scip->set, scip->lp,
1715 scip->branchcand, scip->eventfilter, scip->eventqueue, var) );
1716 return SCIP_OKAY;
1717
1718 default:
1719 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1720 return SCIP_INVALIDCALL;
1721 } /*lint !e788*/
1722 }
1723
1724 /** adds variable to the problem and uses it as pricing candidate to enter the LP
1725 *
1726 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1727 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1728 *
1729 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
1730 */
SCIPaddPricedVar(SCIP * scip,SCIP_VAR * var,SCIP_Real score)1731 SCIP_RETCODE SCIPaddPricedVar(
1732 SCIP* scip, /**< SCIP data structure */
1733 SCIP_VAR* var, /**< variable to add */
1734 SCIP_Real score /**< pricing score of variable (the larger, the better the variable) */
1735 )
1736 {
1737 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddPricedVar", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1738
1739 /* insert the negation variable x instead of the negated variable x' in x' = offset - x */
1740 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
1741 {
1742 assert(SCIPvarGetNegationVar(var) != NULL);
1743 SCIP_CALL( SCIPaddPricedVar(scip, SCIPvarGetNegationVar(var), score) );
1744 return SCIP_OKAY;
1745 }
1746
1747 /* add variable to problem if not yet inserted */
1748 if( SCIPvarGetProbindex(var) == -1 )
1749 {
1750 /* check variable's status */
1751 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
1752 {
1753 SCIPerrorMessage("cannot add original variables to transformed problem\n");
1754 return SCIP_INVALIDDATA;
1755 }
1756 else if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
1757 {
1758 SCIPerrorMessage("cannot add fixed or aggregated variables to transformed problem\n");
1759 return SCIP_INVALIDDATA;
1760 }
1761 SCIP_CALL( SCIPprobAddVar(scip->transprob, scip->mem->probmem, scip->set, scip->lp,
1762 scip->branchcand, scip->eventfilter, scip->eventqueue, var) );
1763 }
1764
1765 /* add variable to pricing storage */
1766 SCIP_CALL( SCIPpricestoreAddVar(scip->pricestore, scip->mem->probmem, scip->set, scip->eventqueue, scip->lp, var, score,
1767 (SCIPtreeGetCurrentDepth(scip->tree) == 0)) );
1768
1769 return SCIP_OKAY;
1770 }
1771
1772 /** removes variable from the problem
1773 *
1774 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1775 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1776 *
1777 * @pre This method can be called if @p scip is in one of the following stages:
1778 * - \ref SCIP_STAGE_PROBLEM
1779 * - \ref SCIP_STAGE_TRANSFORMING
1780 * - \ref SCIP_STAGE_TRANSFORMED
1781 * - \ref SCIP_STAGE_PRESOLVING
1782 * - \ref SCIP_STAGE_FREETRANS
1783 */
SCIPdelVar(SCIP * scip,SCIP_VAR * var,SCIP_Bool * deleted)1784 SCIP_RETCODE SCIPdelVar(
1785 SCIP* scip, /**< SCIP data structure */
1786 SCIP_VAR* var, /**< variable to delete */
1787 SCIP_Bool* deleted /**< pointer to store whether marking variable to be deleted was successful */
1788 )
1789 {
1790 assert(scip != NULL);
1791 assert(var != NULL);
1792 assert(deleted != NULL);
1793
1794 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelVar", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE) );
1795
1796 switch( scip->set->stage )
1797 {
1798 case SCIP_STAGE_PROBLEM:
1799 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL )
1800 {
1801 SCIPerrorMessage("cannot remove transformed variables from original problem\n");
1802 return SCIP_INVALIDDATA;
1803 }
1804 SCIP_CALL( SCIPprobDelVar(scip->origprob, scip->mem->probmem, scip->set, scip->eventqueue, var, deleted) );
1805
1806 /* delete the variables from the problems that were marked to be deleted */
1807 SCIP_CALL( SCIPprobPerformVarDeletions(scip->origprob, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->cliquetable, scip->lp, scip->branchcand) );
1808
1809 return SCIP_OKAY;
1810
1811 case SCIP_STAGE_TRANSFORMING:
1812 case SCIP_STAGE_TRANSFORMED:
1813 case SCIP_STAGE_PRESOLVING:
1814 /* check variable's status */
1815 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL )
1816 {
1817 SCIPerrorMessage("cannot remove original variables from transformed problem\n");
1818 return SCIP_INVALIDDATA;
1819 }
1820 else if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
1821 {
1822 SCIPerrorMessage("cannot remove fixed or aggregated variables from transformed problem\n");
1823 return SCIP_INVALIDDATA;
1824 }
1825
1826 SCIP_CALL( SCIPprobDelVar(scip->transprob, scip->mem->probmem, scip->set, scip->eventqueue, var, deleted) );
1827
1828 return SCIP_OKAY;
1829 case SCIP_STAGE_FREETRANS:
1830 /* in FREETRANS stage, we don't need to remove the variable, because the transformed problem is freed anyways */
1831 *deleted = FALSE;
1832
1833 return SCIP_OKAY;
1834 default:
1835 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1836 return SCIP_INVALIDCALL;
1837 } /*lint !e788*/
1838 }
1839
1840 /** gets variables of the problem along with the numbers of different variable types; data may become invalid after
1841 * calls to SCIPchgVarType(), SCIPfixVar(), SCIPaggregateVars(), and SCIPmultiaggregateVar()
1842 *
1843 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1844 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1845 *
1846 * @pre This method can be called if @p scip is in one of the following stages:
1847 * - \ref SCIP_STAGE_PROBLEM
1848 * - \ref SCIP_STAGE_TRANSFORMED
1849 * - \ref SCIP_STAGE_INITPRESOLVE
1850 * - \ref SCIP_STAGE_PRESOLVING
1851 * - \ref SCIP_STAGE_EXITPRESOLVE
1852 * - \ref SCIP_STAGE_PRESOLVED
1853 * - \ref SCIP_STAGE_INITSOLVE
1854 * - \ref SCIP_STAGE_SOLVING
1855 * - \ref SCIP_STAGE_SOLVED
1856 * - \ref SCIP_STAGE_EXITSOLVE
1857 *
1858 * @note Variables in the vars array are ordered: binaries first, then integers, implicit integers and continuous last.
1859 */
SCIPgetVarsData(SCIP * scip,SCIP_VAR *** vars,int * nvars,int * nbinvars,int * nintvars,int * nimplvars,int * ncontvars)1860 SCIP_RETCODE SCIPgetVarsData(
1861 SCIP* scip, /**< SCIP data structure */
1862 SCIP_VAR*** vars, /**< pointer to store variables array or NULL if not needed */
1863 int* nvars, /**< pointer to store number of variables or NULL if not needed */
1864 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
1865 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
1866 int* nimplvars, /**< pointer to store number of implicit integral vars or NULL if not needed */
1867 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
1868 )
1869 {
1870 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsData", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1871
1872 switch( scip->set->stage )
1873 {
1874 case SCIP_STAGE_PROBLEM:
1875 if( vars != NULL )
1876 *vars = scip->origprob->vars;
1877 if( nvars != NULL )
1878 *nvars = scip->origprob->nvars;
1879 if( nbinvars != NULL )
1880 *nbinvars = scip->origprob->nbinvars;
1881 if( nintvars != NULL )
1882 *nintvars = scip->origprob->nintvars;
1883 if( nimplvars != NULL )
1884 *nimplvars = scip->origprob->nimplvars;
1885 if( ncontvars != NULL )
1886 *ncontvars = scip->origprob->ncontvars;
1887 return SCIP_OKAY;
1888
1889 case SCIP_STAGE_TRANSFORMED:
1890 case SCIP_STAGE_INITPRESOLVE:
1891 case SCIP_STAGE_PRESOLVING:
1892 case SCIP_STAGE_EXITPRESOLVE:
1893 case SCIP_STAGE_PRESOLVED:
1894 case SCIP_STAGE_INITSOLVE:
1895 case SCIP_STAGE_SOLVING:
1896 case SCIP_STAGE_SOLVED:
1897 case SCIP_STAGE_EXITSOLVE:
1898 if( vars != NULL )
1899 *vars = scip->transprob->vars;
1900 if( nvars != NULL )
1901 *nvars = scip->transprob->nvars;
1902 if( nbinvars != NULL )
1903 *nbinvars = scip->transprob->nbinvars;
1904 if( nintvars != NULL )
1905 *nintvars = scip->transprob->nintvars;
1906 if( nimplvars != NULL )
1907 *nimplvars = scip->transprob->nimplvars;
1908 if( ncontvars != NULL )
1909 *ncontvars = scip->transprob->ncontvars;
1910 return SCIP_OKAY;
1911
1912 default:
1913 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1914 return SCIP_INVALIDCALL;
1915 } /*lint !e788*/
1916 }
1917
1918 /** gets array with active problem variables
1919 *
1920 * @return array with active problem variables
1921 *
1922 * @pre This method can be called if @p scip is in one of the following stages:
1923 * - \ref SCIP_STAGE_PROBLEM
1924 * - \ref SCIP_STAGE_TRANSFORMED
1925 * - \ref SCIP_STAGE_INITPRESOLVE
1926 * - \ref SCIP_STAGE_PRESOLVING
1927 * - \ref SCIP_STAGE_EXITPRESOLVE
1928 * - \ref SCIP_STAGE_PRESOLVED
1929 * - \ref SCIP_STAGE_INITSOLVE
1930 * - \ref SCIP_STAGE_SOLVING
1931 * - \ref SCIP_STAGE_SOLVED
1932 * - \ref SCIP_STAGE_EXITSOLVE
1933 *
1934 * @note Variables in the array are ordered: binaries first, then integers, implicit integers and continuous last.
1935 *
1936 * @warning If your are using the methods which add or change bound of variables (e.g., SCIPchgVarType(), SCIPfixVar(),
1937 * SCIPaggregateVars(), and SCIPmultiaggregateVar()), it can happen that the internal variable array (which is
1938 * accessed via this method) gets resized and/or resorted. This can invalid the data pointer which is returned
1939 * by this method.
1940 */
SCIPgetVars(SCIP * scip)1941 SCIP_VAR** SCIPgetVars(
1942 SCIP* scip /**< SCIP data structure */
1943 )
1944 {
1945 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1946
1947 switch( scip->set->stage )
1948 {
1949 case SCIP_STAGE_PROBLEM:
1950 return scip->origprob->vars;
1951
1952 case SCIP_STAGE_TRANSFORMED:
1953 case SCIP_STAGE_INITPRESOLVE:
1954 case SCIP_STAGE_PRESOLVING:
1955 case SCIP_STAGE_EXITPRESOLVE:
1956 case SCIP_STAGE_PRESOLVED:
1957 case SCIP_STAGE_INITSOLVE:
1958 case SCIP_STAGE_SOLVING:
1959 case SCIP_STAGE_SOLVED:
1960 case SCIP_STAGE_EXITSOLVE:
1961 return scip->transprob->vars;
1962
1963 default:
1964 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1965 SCIPABORT();
1966 return NULL; /*lint !e527*/
1967 } /*lint !e788*/
1968 }
1969
1970 /** gets number of active problem variables
1971 *
1972 * @return the number of active problem variables
1973 *
1974 * @pre This method can be called if @p scip is in one of the following stages:
1975 * - \ref SCIP_STAGE_PROBLEM
1976 * - \ref SCIP_STAGE_TRANSFORMED
1977 * - \ref SCIP_STAGE_INITPRESOLVE
1978 * - \ref SCIP_STAGE_PRESOLVING
1979 * - \ref SCIP_STAGE_EXITPRESOLVE
1980 * - \ref SCIP_STAGE_PRESOLVED
1981 * - \ref SCIP_STAGE_INITSOLVE
1982 * - \ref SCIP_STAGE_SOLVING
1983 * - \ref SCIP_STAGE_SOLVED
1984 * - \ref SCIP_STAGE_EXITSOLVE
1985 */
SCIPgetNVars(SCIP * scip)1986 int SCIPgetNVars(
1987 SCIP* scip /**< SCIP data structure */
1988 )
1989 {
1990 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1991
1992 switch( scip->set->stage )
1993 {
1994 case SCIP_STAGE_PROBLEM:
1995 return scip->origprob->nvars;
1996
1997 case SCIP_STAGE_TRANSFORMED:
1998 case SCIP_STAGE_INITPRESOLVE:
1999 case SCIP_STAGE_PRESOLVING:
2000 case SCIP_STAGE_EXITPRESOLVE:
2001 case SCIP_STAGE_PRESOLVED:
2002 case SCIP_STAGE_INITSOLVE:
2003 case SCIP_STAGE_SOLVING:
2004 case SCIP_STAGE_SOLVED:
2005 case SCIP_STAGE_EXITSOLVE:
2006 return scip->transprob->nvars;
2007
2008 default:
2009 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2010 SCIPABORT();
2011 return 0; /*lint !e527*/
2012 } /*lint !e788*/
2013 }
2014
2015 /** gets number of binary active problem variables
2016 *
2017 * @return the number of binary active problem variables
2018 *
2019 * @pre This method can be called if @p scip is in one of the following stages:
2020 * - \ref SCIP_STAGE_PROBLEM
2021 * - \ref SCIP_STAGE_TRANSFORMED
2022 * - \ref SCIP_STAGE_INITPRESOLVE
2023 * - \ref SCIP_STAGE_PRESOLVING
2024 * - \ref SCIP_STAGE_EXITPRESOLVE
2025 * - \ref SCIP_STAGE_PRESOLVED
2026 * - \ref SCIP_STAGE_INITSOLVE
2027 * - \ref SCIP_STAGE_SOLVING
2028 * - \ref SCIP_STAGE_SOLVED
2029 * - \ref SCIP_STAGE_EXITSOLVE
2030 */
SCIPgetNBinVars(SCIP * scip)2031 int SCIPgetNBinVars(
2032 SCIP* scip /**< SCIP data structure */
2033 )
2034 {
2035 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNBinVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2036
2037 switch( scip->set->stage )
2038 {
2039 case SCIP_STAGE_PROBLEM:
2040 return scip->origprob->nbinvars;
2041
2042 case SCIP_STAGE_TRANSFORMED:
2043 case SCIP_STAGE_INITPRESOLVE:
2044 case SCIP_STAGE_PRESOLVING:
2045 case SCIP_STAGE_EXITPRESOLVE:
2046 case SCIP_STAGE_PRESOLVED:
2047 case SCIP_STAGE_INITSOLVE:
2048 case SCIP_STAGE_SOLVING:
2049 case SCIP_STAGE_SOLVED:
2050 case SCIP_STAGE_EXITSOLVE:
2051 return scip->transprob->nbinvars;
2052
2053 default:
2054 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2055 SCIPABORT();
2056 return 0; /*lint !e527*/
2057 } /*lint !e788*/
2058 }
2059
2060 /** gets number of integer active problem variables
2061 *
2062 * @return the number of integer active problem variables
2063 *
2064 * @pre This method can be called if @p scip is in one of the following stages:
2065 * - \ref SCIP_STAGE_PROBLEM
2066 * - \ref SCIP_STAGE_TRANSFORMED
2067 * - \ref SCIP_STAGE_INITPRESOLVE
2068 * - \ref SCIP_STAGE_PRESOLVING
2069 * - \ref SCIP_STAGE_EXITPRESOLVE
2070 * - \ref SCIP_STAGE_PRESOLVED
2071 * - \ref SCIP_STAGE_INITSOLVE
2072 * - \ref SCIP_STAGE_SOLVING
2073 * - \ref SCIP_STAGE_SOLVED
2074 * - \ref SCIP_STAGE_EXITSOLVE
2075 */
SCIPgetNIntVars(SCIP * scip)2076 int SCIPgetNIntVars(
2077 SCIP* scip /**< SCIP data structure */
2078 )
2079 {
2080 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNIntVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2081
2082 switch( scip->set->stage )
2083 {
2084 case SCIP_STAGE_PROBLEM:
2085 return scip->origprob->nintvars;
2086
2087 case SCIP_STAGE_TRANSFORMED:
2088 case SCIP_STAGE_INITPRESOLVE:
2089 case SCIP_STAGE_PRESOLVING:
2090 case SCIP_STAGE_EXITPRESOLVE:
2091 case SCIP_STAGE_PRESOLVED:
2092 case SCIP_STAGE_INITSOLVE:
2093 case SCIP_STAGE_SOLVING:
2094 case SCIP_STAGE_SOLVED:
2095 case SCIP_STAGE_EXITSOLVE:
2096 return scip->transprob->nintvars;
2097
2098 default:
2099 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2100 SCIPABORT();
2101 return 0; /*lint !e527*/
2102 } /*lint !e788*/
2103 }
2104
2105 /** gets number of implicit integer active problem variables
2106 *
2107 * @return the number of implicit integer active problem variables
2108 *
2109 * @pre This method can be called if @p scip is in one of the following stages:
2110 * - \ref SCIP_STAGE_PROBLEM
2111 * - \ref SCIP_STAGE_TRANSFORMED
2112 * - \ref SCIP_STAGE_INITPRESOLVE
2113 * - \ref SCIP_STAGE_PRESOLVING
2114 * - \ref SCIP_STAGE_EXITPRESOLVE
2115 * - \ref SCIP_STAGE_PRESOLVED
2116 * - \ref SCIP_STAGE_INITSOLVE
2117 * - \ref SCIP_STAGE_SOLVING
2118 * - \ref SCIP_STAGE_SOLVED
2119 * - \ref SCIP_STAGE_EXITSOLVE
2120 */
SCIPgetNImplVars(SCIP * scip)2121 int SCIPgetNImplVars(
2122 SCIP* scip /**< SCIP data structure */
2123 )
2124 {
2125 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNImplVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2126
2127 switch( scip->set->stage )
2128 {
2129 case SCIP_STAGE_PROBLEM:
2130 return scip->origprob->nimplvars;
2131
2132 case SCIP_STAGE_TRANSFORMED:
2133 case SCIP_STAGE_INITPRESOLVE:
2134 case SCIP_STAGE_PRESOLVING:
2135 case SCIP_STAGE_EXITPRESOLVE:
2136 case SCIP_STAGE_PRESOLVED:
2137 case SCIP_STAGE_INITSOLVE:
2138 case SCIP_STAGE_SOLVING:
2139 case SCIP_STAGE_SOLVED:
2140 case SCIP_STAGE_EXITSOLVE:
2141 return scip->transprob->nimplvars;
2142
2143 default:
2144 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2145 SCIPABORT();
2146 return 0; /*lint !e527*/
2147 } /*lint !e788*/
2148 }
2149
2150 /** gets number of continuous active problem variables
2151 *
2152 * @return the number of continuous active problem variables
2153 *
2154 * @pre This method can be called if @p scip is in one of the following stages:
2155 * - \ref SCIP_STAGE_PROBLEM
2156 * - \ref SCIP_STAGE_TRANSFORMED
2157 * - \ref SCIP_STAGE_INITPRESOLVE
2158 * - \ref SCIP_STAGE_PRESOLVING
2159 * - \ref SCIP_STAGE_EXITPRESOLVE
2160 * - \ref SCIP_STAGE_PRESOLVED
2161 * - \ref SCIP_STAGE_INITSOLVE
2162 * - \ref SCIP_STAGE_SOLVING
2163 * - \ref SCIP_STAGE_SOLVED
2164 * - \ref SCIP_STAGE_EXITSOLVE
2165 */
SCIPgetNContVars(SCIP * scip)2166 int SCIPgetNContVars(
2167 SCIP* scip /**< SCIP data structure */
2168 )
2169 {
2170 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNContVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
2171
2172 switch( scip->set->stage )
2173 {
2174 case SCIP_STAGE_PROBLEM:
2175 return scip->origprob->ncontvars;
2176
2177 case SCIP_STAGE_TRANSFORMED:
2178 case SCIP_STAGE_INITPRESOLVE:
2179 case SCIP_STAGE_PRESOLVING:
2180 case SCIP_STAGE_EXITPRESOLVE:
2181 case SCIP_STAGE_PRESOLVED:
2182 case SCIP_STAGE_INITSOLVE:
2183 case SCIP_STAGE_SOLVING:
2184 case SCIP_STAGE_SOLVED:
2185 case SCIP_STAGE_EXITSOLVE:
2186 return scip->transprob->ncontvars;
2187
2188 default:
2189 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2190 SCIPABORT();
2191 return 0; /*lint !e527*/
2192 } /*lint !e788*/
2193 }
2194
2195
2196 /** gets number of active problem variables with a non-zero objective coefficient
2197 *
2198 * @note In case of the original problem the number of variables is counted. In case of the transformed problem the
2199 * number of variables is just returned since it is stored internally
2200 *
2201 * @return the number of active problem variables with a non-zero objective coefficient
2202 *
2203 * @pre This method can be called if @p scip is in one of the following stages:
2204 * - \ref SCIP_STAGE_PROBLEM
2205 * - \ref SCIP_STAGE_TRANSFORMED
2206 * - \ref SCIP_STAGE_INITPRESOLVE
2207 * - \ref SCIP_STAGE_PRESOLVING
2208 * - \ref SCIP_STAGE_EXITPRESOLVE
2209 * - \ref SCIP_STAGE_PRESOLVED
2210 * - \ref SCIP_STAGE_INITSOLVE
2211 * - \ref SCIP_STAGE_SOLVING
2212 * - \ref SCIP_STAGE_SOLVED
2213 */
SCIPgetNObjVars(SCIP * scip)2214 int SCIPgetNObjVars(
2215 SCIP* scip /**< SCIP data structure */
2216 )
2217 {
2218 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNObjVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2219
2220 switch( scip->set->stage )
2221 {
2222 case SCIP_STAGE_PROBLEM:
2223 return SCIPprobGetNObjVars(scip->origprob, scip->set);
2224
2225 case SCIP_STAGE_TRANSFORMED:
2226 case SCIP_STAGE_INITPRESOLVE:
2227 case SCIP_STAGE_PRESOLVING:
2228 case SCIP_STAGE_EXITPRESOLVE:
2229 case SCIP_STAGE_PRESOLVED:
2230 case SCIP_STAGE_INITSOLVE:
2231 case SCIP_STAGE_SOLVING:
2232 case SCIP_STAGE_SOLVED:
2233 return SCIPprobGetNObjVars(scip->transprob, scip->set);
2234
2235 default:
2236 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2237 SCIPABORT();
2238 return 0; /*lint !e527*/
2239 } /*lint !e788*/
2240 }
2241
2242
2243 /** gets array with fixed and aggregated problem variables; data may become invalid after
2244 * calls to SCIPfixVar(), SCIPaggregateVars(), and SCIPmultiaggregateVar()
2245 *
2246 * @return an array with fixed and aggregated problem variables; data may become invalid after
2247 * calls to SCIPfixVar(), SCIPaggregateVars(), and SCIPmultiaggregateVar()
2248 *
2249 * @pre This method can be called if @p scip is in one of the following stages:
2250 * - \ref SCIP_STAGE_PROBLEM
2251 * - \ref SCIP_STAGE_TRANSFORMED
2252 * - \ref SCIP_STAGE_INITPRESOLVE
2253 * - \ref SCIP_STAGE_PRESOLVING
2254 * - \ref SCIP_STAGE_EXITPRESOLVE
2255 * - \ref SCIP_STAGE_PRESOLVED
2256 * - \ref SCIP_STAGE_INITSOLVE
2257 * - \ref SCIP_STAGE_SOLVING
2258 * - \ref SCIP_STAGE_SOLVED
2259 */
SCIPgetFixedVars(SCIP * scip)2260 SCIP_VAR** SCIPgetFixedVars(
2261 SCIP* scip /**< SCIP data structure */
2262 )
2263 {
2264 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetFixedVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2265
2266 switch( scip->set->stage )
2267 {
2268 case SCIP_STAGE_PROBLEM:
2269 return NULL;
2270
2271 case SCIP_STAGE_TRANSFORMED:
2272 case SCIP_STAGE_INITPRESOLVE:
2273 case SCIP_STAGE_PRESOLVING:
2274 case SCIP_STAGE_EXITPRESOLVE:
2275 case SCIP_STAGE_PRESOLVED:
2276 case SCIP_STAGE_INITSOLVE:
2277 case SCIP_STAGE_SOLVING:
2278 case SCIP_STAGE_SOLVED:
2279 return scip->transprob->fixedvars;
2280
2281 default:
2282 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2283 SCIPABORT();
2284 return NULL; /*lint !e527*/
2285 } /*lint !e788*/
2286 }
2287
2288 /** gets number of fixed or aggregated problem variables
2289 *
2290 * @return the number of fixed or aggregated problem variables
2291 *
2292 * @pre This method can be called if @p scip is in one of the following stages:
2293 * - \ref SCIP_STAGE_PROBLEM
2294 * - \ref SCIP_STAGE_TRANSFORMED
2295 * - \ref SCIP_STAGE_INITPRESOLVE
2296 * - \ref SCIP_STAGE_PRESOLVING
2297 * - \ref SCIP_STAGE_EXITPRESOLVE
2298 * - \ref SCIP_STAGE_PRESOLVED
2299 * - \ref SCIP_STAGE_INITSOLVE
2300 * - \ref SCIP_STAGE_SOLVING
2301 * - \ref SCIP_STAGE_SOLVED
2302 */
SCIPgetNFixedVars(SCIP * scip)2303 int SCIPgetNFixedVars(
2304 SCIP* scip /**< SCIP data structure */
2305 )
2306 {
2307 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNFixedVars", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2308
2309 switch( scip->set->stage )
2310 {
2311 case SCIP_STAGE_PROBLEM:
2312 return 0;
2313
2314 case SCIP_STAGE_TRANSFORMED:
2315 case SCIP_STAGE_INITPRESOLVE:
2316 case SCIP_STAGE_PRESOLVING:
2317 case SCIP_STAGE_EXITPRESOLVE:
2318 case SCIP_STAGE_PRESOLVED:
2319 case SCIP_STAGE_INITSOLVE:
2320 case SCIP_STAGE_SOLVING:
2321 case SCIP_STAGE_SOLVED:
2322 return scip->transprob->nfixedvars;
2323
2324 default:
2325 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2326 SCIPABORT();
2327 return 0; /*lint !e527*/
2328 } /*lint !e788*/
2329 }
2330
2331 /** gets variables of the original problem along with the numbers of different variable types; data may become invalid
2332 * after a call to SCIPchgVarType()
2333 *
2334 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2335 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2336 *
2337 * @pre This method can be called if @p scip is in one of the following stages:
2338 * - \ref SCIP_STAGE_PROBLEM
2339 * - \ref SCIP_STAGE_TRANSFORMING
2340 * - \ref SCIP_STAGE_TRANSFORMED
2341 * - \ref SCIP_STAGE_INITPRESOLVE
2342 * - \ref SCIP_STAGE_PRESOLVING
2343 * - \ref SCIP_STAGE_EXITPRESOLVE
2344 * - \ref SCIP_STAGE_PRESOLVED
2345 * - \ref SCIP_STAGE_INITSOLVE
2346 * - \ref SCIP_STAGE_SOLVING
2347 * - \ref SCIP_STAGE_SOLVED
2348 * - \ref SCIP_STAGE_EXITSOLVE
2349 * - \ref SCIP_STAGE_FREETRANS
2350 */
SCIPgetOrigVarsData(SCIP * scip,SCIP_VAR *** vars,int * nvars,int * nbinvars,int * nintvars,int * nimplvars,int * ncontvars)2351 SCIP_RETCODE SCIPgetOrigVarsData(
2352 SCIP* scip, /**< SCIP data structure */
2353 SCIP_VAR*** vars, /**< pointer to store variables array or NULL if not needed */
2354 int* nvars, /**< pointer to store number of variables or NULL if not needed */
2355 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
2356 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
2357 int* nimplvars, /**< pointer to store number of implicit integral vars or NULL if not needed */
2358 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
2359 )
2360 {
2361 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetOrigVarsData", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2362
2363 if( vars != NULL )
2364 *vars = scip->origprob->vars;
2365 if( nvars != NULL )
2366 *nvars = scip->origprob->nvars;
2367 if( nbinvars != NULL )
2368 *nbinvars = scip->origprob->nbinvars;
2369 if( nintvars != NULL )
2370 *nintvars = scip->origprob->nintvars;
2371 if( nimplvars != NULL )
2372 *nimplvars = scip->origprob->nimplvars;
2373 if( ncontvars != NULL )
2374 *ncontvars = scip->origprob->ncontvars;
2375
2376 return SCIP_OKAY;
2377 }
2378
2379 /** gets array with original problem variables; data may become invalid after
2380 * a call to SCIPchgVarType()
2381 *
2382 * @return an array with original problem variables; data may become invalid after
2383 * a call to SCIPchgVarType()
2384 *
2385 * @pre This method can be called if @p scip is in one of the following stages:
2386 * - \ref SCIP_STAGE_PROBLEM
2387 * - \ref SCIP_STAGE_TRANSFORMING
2388 * - \ref SCIP_STAGE_TRANSFORMED
2389 * - \ref SCIP_STAGE_INITPRESOLVE
2390 * - \ref SCIP_STAGE_PRESOLVING
2391 * - \ref SCIP_STAGE_EXITPRESOLVE
2392 * - \ref SCIP_STAGE_PRESOLVED
2393 * - \ref SCIP_STAGE_INITSOLVE
2394 * - \ref SCIP_STAGE_SOLVING
2395 * - \ref SCIP_STAGE_SOLVED
2396 * - \ref SCIP_STAGE_EXITSOLVE
2397 * - \ref SCIP_STAGE_FREETRANS
2398 */
SCIPgetOrigVars(SCIP * scip)2399 SCIP_VAR** SCIPgetOrigVars(
2400 SCIP* scip /**< SCIP data structure */
2401 )
2402 {
2403 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetOrigVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2404
2405 return scip->origprob->vars;
2406 }
2407
2408 /** gets number of original problem variables
2409 *
2410 * @return the number of original problem variables
2411 *
2412 * @pre This method can be called if @p scip is in one of the following stages:
2413 * - \ref SCIP_STAGE_PROBLEM
2414 * - \ref SCIP_STAGE_TRANSFORMING
2415 * - \ref SCIP_STAGE_TRANSFORMED
2416 * - \ref SCIP_STAGE_INITPRESOLVE
2417 * - \ref SCIP_STAGE_PRESOLVING
2418 * - \ref SCIP_STAGE_EXITPRESOLVE
2419 * - \ref SCIP_STAGE_PRESOLVED
2420 * - \ref SCIP_STAGE_INITSOLVE
2421 * - \ref SCIP_STAGE_SOLVING
2422 * - \ref SCIP_STAGE_SOLVED
2423 * - \ref SCIP_STAGE_EXITSOLVE
2424 * - \ref SCIP_STAGE_FREETRANS
2425 */
SCIPgetNOrigVars(SCIP * scip)2426 int SCIPgetNOrigVars(
2427 SCIP* scip /**< SCIP data structure */
2428 )
2429 {
2430 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2431
2432 return scip->origprob->nvars;
2433 }
2434
2435 /** gets number of binary variables in the original problem
2436 *
2437 * @return the number of binary variables in the original problem
2438 *
2439 * @pre This method can be called if @p scip is in one of the following stages:
2440 * - \ref SCIP_STAGE_PROBLEM
2441 * - \ref SCIP_STAGE_TRANSFORMING
2442 * - \ref SCIP_STAGE_TRANSFORMED
2443 * - \ref SCIP_STAGE_INITPRESOLVE
2444 * - \ref SCIP_STAGE_PRESOLVING
2445 * - \ref SCIP_STAGE_EXITPRESOLVE
2446 * - \ref SCIP_STAGE_PRESOLVED
2447 * - \ref SCIP_STAGE_INITSOLVE
2448 * - \ref SCIP_STAGE_SOLVING
2449 * - \ref SCIP_STAGE_SOLVED
2450 * - \ref SCIP_STAGE_EXITSOLVE
2451 * - \ref SCIP_STAGE_FREETRANS
2452 */
SCIPgetNOrigBinVars(SCIP * scip)2453 int SCIPgetNOrigBinVars(
2454 SCIP* scip /**< SCIP data structure */
2455 )
2456 {
2457 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigBinVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2458
2459 return scip->origprob->nbinvars;
2460 }
2461
2462 /** gets the number of integer variables in the original problem
2463 *
2464 * @return the number of integer variables in the original problem
2465 *
2466 * @pre This method can be called if @p scip is in one of the following stages:
2467 * - \ref SCIP_STAGE_PROBLEM
2468 * - \ref SCIP_STAGE_TRANSFORMING
2469 * - \ref SCIP_STAGE_TRANSFORMED
2470 * - \ref SCIP_STAGE_INITPRESOLVE
2471 * - \ref SCIP_STAGE_PRESOLVING
2472 * - \ref SCIP_STAGE_EXITPRESOLVE
2473 * - \ref SCIP_STAGE_PRESOLVED
2474 * - \ref SCIP_STAGE_INITSOLVE
2475 * - \ref SCIP_STAGE_SOLVING
2476 * - \ref SCIP_STAGE_SOLVED
2477 * - \ref SCIP_STAGE_EXITSOLVE
2478 * - \ref SCIP_STAGE_FREETRANS
2479 */
SCIPgetNOrigIntVars(SCIP * scip)2480 int SCIPgetNOrigIntVars(
2481 SCIP* scip /**< SCIP data structure */
2482 )
2483 {
2484 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigIntVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2485
2486 return scip->origprob->nintvars;
2487 }
2488
2489 /** gets number of implicit integer variables in the original problem
2490 *
2491 * @return the number of implicit integer variables in the original problem
2492 *
2493 * @pre This method can be called if @p scip is in one of the following stages:
2494 * - \ref SCIP_STAGE_PROBLEM
2495 * - \ref SCIP_STAGE_TRANSFORMING
2496 * - \ref SCIP_STAGE_TRANSFORMED
2497 * - \ref SCIP_STAGE_INITPRESOLVE
2498 * - \ref SCIP_STAGE_PRESOLVING
2499 * - \ref SCIP_STAGE_EXITPRESOLVE
2500 * - \ref SCIP_STAGE_PRESOLVED
2501 * - \ref SCIP_STAGE_INITSOLVE
2502 * - \ref SCIP_STAGE_SOLVING
2503 * - \ref SCIP_STAGE_SOLVED
2504 * - \ref SCIP_STAGE_EXITSOLVE
2505 * - \ref SCIP_STAGE_FREETRANS
2506 */
SCIPgetNOrigImplVars(SCIP * scip)2507 int SCIPgetNOrigImplVars(
2508 SCIP* scip /**< SCIP data structure */
2509 )
2510 {
2511 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigImplVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2512
2513 return scip->origprob->nimplvars;
2514 }
2515
2516 /** gets number of continuous variables in the original problem
2517 *
2518 * @return the number of continuous variables in the original problem
2519 *
2520 * @pre This method can be called if @p scip is in one of the following stages:
2521 * - \ref SCIP_STAGE_PROBLEM
2522 * - \ref SCIP_STAGE_TRANSFORMING
2523 * - \ref SCIP_STAGE_TRANSFORMED
2524 * - \ref SCIP_STAGE_INITPRESOLVE
2525 * - \ref SCIP_STAGE_PRESOLVING
2526 * - \ref SCIP_STAGE_EXITPRESOLVE
2527 * - \ref SCIP_STAGE_PRESOLVED
2528 * - \ref SCIP_STAGE_INITSOLVE
2529 * - \ref SCIP_STAGE_SOLVING
2530 * - \ref SCIP_STAGE_SOLVED
2531 * - \ref SCIP_STAGE_EXITSOLVE
2532 * - \ref SCIP_STAGE_FREETRANS
2533 */
SCIPgetNOrigContVars(SCIP * scip)2534 int SCIPgetNOrigContVars(
2535 SCIP* scip /**< SCIP data structure */
2536 )
2537 {
2538 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigContVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2539
2540 return scip->origprob->ncontvars;
2541 }
2542
2543 /** gets number of all problem variables created during creation and solving of problem;
2544 * this includes also variables that were deleted in the meantime
2545 *
2546 * @return the number of all problem variables created during creation and solving of problem;
2547 * this includes also variables that were deleted in the meantime
2548 *
2549 * @pre This method can be called if @p scip is in one of the following stages:
2550 * - \ref SCIP_STAGE_PROBLEM
2551 * - \ref SCIP_STAGE_TRANSFORMING
2552 * - \ref SCIP_STAGE_TRANSFORMED
2553 * - \ref SCIP_STAGE_INITPRESOLVE
2554 * - \ref SCIP_STAGE_PRESOLVING
2555 * - \ref SCIP_STAGE_EXITPRESOLVE
2556 * - \ref SCIP_STAGE_PRESOLVED
2557 * - \ref SCIP_STAGE_INITSOLVE
2558 * - \ref SCIP_STAGE_SOLVING
2559 * - \ref SCIP_STAGE_SOLVED
2560 * - \ref SCIP_STAGE_EXITSOLVE
2561 * - \ref SCIP_STAGE_FREETRANS
2562 */
SCIPgetNTotalVars(SCIP * scip)2563 int SCIPgetNTotalVars(
2564 SCIP* scip /**< SCIP data structure */
2565 )
2566 {
2567 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNTotalVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2568
2569 assert(scip->stat != NULL);
2570
2571 switch( scip->set->stage )
2572 {
2573 case SCIP_STAGE_PROBLEM:
2574 case SCIP_STAGE_TRANSFORMING:
2575 case SCIP_STAGE_TRANSFORMED:
2576 case SCIP_STAGE_INITPRESOLVE:
2577 case SCIP_STAGE_PRESOLVING:
2578 case SCIP_STAGE_EXITPRESOLVE:
2579 case SCIP_STAGE_PRESOLVED:
2580 case SCIP_STAGE_INITSOLVE:
2581 case SCIP_STAGE_SOLVING:
2582 case SCIP_STAGE_SOLVED:
2583 case SCIP_STAGE_EXITSOLVE:
2584 case SCIP_STAGE_FREETRANS:
2585 return scip->stat->nvaridx;
2586
2587 default:
2588 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2589 SCIPABORT();
2590 return 0; /*lint !e527*/
2591 } /*lint !e788*/
2592 }
2593
2594
2595 /** gets variables of the original or transformed problem along with the numbers of different variable types;
2596 * the returned problem space (original or transformed) corresponds to the given solution;
2597 * data may become invalid after calls to SCIPchgVarType(), SCIPfixVar(), SCIPaggregateVars(), and
2598 * SCIPmultiaggregateVar()
2599 *
2600 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2601 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2602 *
2603 * @pre This method can be called if @p scip is in one of the following stages:
2604 * - \ref SCIP_STAGE_PROBLEM
2605 * - \ref SCIP_STAGE_TRANSFORMED
2606 * - \ref SCIP_STAGE_INITPRESOLVE
2607 * - \ref SCIP_STAGE_PRESOLVING
2608 * - \ref SCIP_STAGE_EXITPRESOLVE
2609 * - \ref SCIP_STAGE_PRESOLVED
2610 * - \ref SCIP_STAGE_INITSOLVE
2611 * - \ref SCIP_STAGE_SOLVING
2612 * - \ref SCIP_STAGE_SOLVED
2613 */
SCIPgetSolVarsData(SCIP * scip,SCIP_SOL * sol,SCIP_VAR *** vars,int * nvars,int * nbinvars,int * nintvars,int * nimplvars,int * ncontvars)2614 SCIP_RETCODE SCIPgetSolVarsData(
2615 SCIP* scip, /**< SCIP data structure */
2616 SCIP_SOL* sol, /**< primal solution that selects the problem space, NULL for current solution */
2617 SCIP_VAR*** vars, /**< pointer to store variables array or NULL if not needed */
2618 int* nvars, /**< pointer to store number of variables or NULL if not needed */
2619 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
2620 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
2621 int* nimplvars, /**< pointer to store number of implicit integral vars or NULL if not needed */
2622 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
2623 )
2624 {
2625 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetSolVarsData", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2626
2627 if( scip->set->stage == SCIP_STAGE_PROBLEM || (sol != NULL && SCIPsolIsOriginal(sol)) )
2628 {
2629 if( vars != NULL )
2630 *vars = scip->origprob->vars;
2631 if( nvars != NULL )
2632 *nvars = scip->origprob->nvars;
2633 if( nbinvars != NULL )
2634 *nbinvars = scip->origprob->nbinvars;
2635 if( nintvars != NULL )
2636 *nintvars = scip->origprob->nintvars;
2637 if( nimplvars != NULL )
2638 *nimplvars = scip->origprob->nimplvars;
2639 if( ncontvars != NULL )
2640 *ncontvars = scip->origprob->ncontvars;
2641 }
2642 else
2643 {
2644 if( vars != NULL )
2645 *vars = scip->transprob->vars;
2646 if( nvars != NULL )
2647 *nvars = scip->transprob->nvars;
2648 if( nbinvars != NULL )
2649 *nbinvars = scip->transprob->nbinvars;
2650 if( nintvars != NULL )
2651 *nintvars = scip->transprob->nintvars;
2652 if( nimplvars != NULL )
2653 *nimplvars = scip->transprob->nimplvars;
2654 if( ncontvars != NULL )
2655 *ncontvars = scip->transprob->ncontvars;
2656 }
2657
2658 return SCIP_OKAY;
2659 }
2660
2661 /** returns variable of given name in the problem, or NULL if not existing
2662 *
2663 * @return variable of given name in the problem, or NULL if not existing
2664 *
2665 * @pre This method can be called if @p scip is in one of the following stages:
2666 * - \ref SCIP_STAGE_PROBLEM
2667 * - \ref SCIP_STAGE_TRANSFORMING
2668 * - \ref SCIP_STAGE_TRANSFORMED
2669 * - \ref SCIP_STAGE_INITPRESOLVE
2670 * - \ref SCIP_STAGE_PRESOLVING
2671 * - \ref SCIP_STAGE_EXITPRESOLVE
2672 * - \ref SCIP_STAGE_PRESOLVED
2673 * - \ref SCIP_STAGE_INITSOLVE
2674 * - \ref SCIP_STAGE_SOLVING
2675 * - \ref SCIP_STAGE_SOLVED
2676 * - \ref SCIP_STAGE_EXITSOLVE
2677 * - \ref SCIP_STAGE_FREETRANS
2678 */
SCIPfindVar(SCIP * scip,const char * name)2679 SCIP_VAR* SCIPfindVar(
2680 SCIP* scip, /**< SCIP data structure */
2681 const char* name /**< name of variable to find */
2682 )
2683 {
2684 SCIP_VAR* var;
2685
2686 assert(name != NULL);
2687
2688 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfindVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2689
2690 switch( scip->set->stage )
2691 {
2692 case SCIP_STAGE_PROBLEM:
2693 return SCIPprobFindVar(scip->origprob, name);
2694
2695 case SCIP_STAGE_TRANSFORMING:
2696 case SCIP_STAGE_TRANSFORMED:
2697 case SCIP_STAGE_INITPRESOLVE:
2698 case SCIP_STAGE_PRESOLVING:
2699 case SCIP_STAGE_EXITPRESOLVE:
2700 case SCIP_STAGE_PRESOLVED:
2701 case SCIP_STAGE_INITSOLVE:
2702 case SCIP_STAGE_SOLVING:
2703 case SCIP_STAGE_SOLVED:
2704 case SCIP_STAGE_EXITSOLVE:
2705 case SCIP_STAGE_FREETRANS:
2706 var = SCIPprobFindVar(scip->transprob, name);
2707 if( var == NULL )
2708 return SCIPprobFindVar(scip->origprob, name);
2709 else
2710 return var;
2711
2712 default:
2713 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2714 SCIPABORT();
2715 return NULL; /*lint !e527*/
2716 } /*lint !e788*/
2717 }
2718
2719 /** returns TRUE iff all potential variables exist in the problem, and FALSE, if there may be additional variables,
2720 * that will be added in pricing and improve the objective value
2721 *
2722 * @return TRUE, if all potential variables exist in the problem; FALSE, otherwise
2723 *
2724 * @pre This method can be called if @p scip is in one of the following stages:
2725 * - \ref SCIP_STAGE_TRANSFORMING
2726 * - \ref SCIP_STAGE_TRANSFORMED
2727 * - \ref SCIP_STAGE_INITPRESOLVE
2728 * - \ref SCIP_STAGE_PRESOLVING
2729 * - \ref SCIP_STAGE_EXITPRESOLVE
2730 * - \ref SCIP_STAGE_PRESOLVED
2731 * - \ref SCIP_STAGE_INITSOLVE
2732 * - \ref SCIP_STAGE_SOLVING
2733 * - \ref SCIP_STAGE_SOLVED
2734 * - \ref SCIP_STAGE_EXITSOLVE
2735 * - \ref SCIP_STAGE_FREETRANS
2736 */
SCIPallVarsInProb(SCIP * scip)2737 SCIP_Bool SCIPallVarsInProb(
2738 SCIP* scip /**< SCIP data structure */
2739 )
2740 {
2741 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPallVarsInProb", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2742
2743 return (scip->set->nactivepricers == 0);
2744 }
2745
2746 /** adds constraint to the problem; if constraint is only valid locally, it is added to the local subproblem of the
2747 * current node (and all of its subnodes); otherwise it is added to the global problem;
2748 * if a local constraint is added at the root node, it is automatically upgraded into a global constraint
2749 *
2750 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2751 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2752 *
2753 * @pre This method can be called if @p scip is in one of the following stages:
2754 * - \ref SCIP_STAGE_PROBLEM
2755 * - \ref SCIP_STAGE_TRANSFORMED
2756 * - \ref SCIP_STAGE_INITPRESOLVE
2757 * - \ref SCIP_STAGE_PRESOLVING
2758 * - \ref SCIP_STAGE_EXITPRESOLVE
2759 * - \ref SCIP_STAGE_PRESOLVED
2760 * - \ref SCIP_STAGE_INITSOLVE
2761 * - \ref SCIP_STAGE_SOLVING
2762 * - \ref SCIP_STAGE_EXITSOLVE
2763 */
SCIPaddCons(SCIP * scip,SCIP_CONS * cons)2764 SCIP_RETCODE SCIPaddCons(
2765 SCIP* scip, /**< SCIP data structure */
2766 SCIP_CONS* cons /**< constraint to add */
2767 )
2768 {
2769 assert(cons != NULL);
2770
2771 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddCons", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE) );
2772
2773 switch( scip->set->stage )
2774 {
2775 case SCIP_STAGE_PROBLEM:
2776 {
2777 SCIP_CALL( SCIPprobAddCons(scip->origprob, scip->set, scip->stat, cons) );
2778
2779 if( scip->set->reopt_enable )
2780 {
2781 SCIP_CALL( SCIPreoptAddCons(scip->reopt, scip->set, scip->mem->probmem, cons) );
2782 }
2783 }
2784 return SCIP_OKAY;
2785
2786 case SCIP_STAGE_TRANSFORMED:
2787 SCIP_CALL( SCIPprobAddCons(scip->transprob, scip->set, scip->stat, cons) );
2788 return SCIP_OKAY;
2789
2790 case SCIP_STAGE_INITPRESOLVE:
2791 case SCIP_STAGE_PRESOLVING:
2792 case SCIP_STAGE_EXITPRESOLVE:
2793 case SCIP_STAGE_PRESOLVED:
2794 case SCIP_STAGE_INITSOLVE:
2795 case SCIP_STAGE_SOLVING:
2796 assert( SCIPtreeGetCurrentDepth(scip->tree) >= 0 || scip->set->stage == SCIP_STAGE_PRESOLVED
2797 || scip->set->stage == SCIP_STAGE_INITSOLVE );
2798 if( SCIPtreeGetCurrentDepth(scip->tree) <= SCIPtreeGetEffectiveRootDepth(scip->tree) )
2799 SCIPconsSetLocal(cons, FALSE);
2800 if( SCIPconsIsGlobal(cons) )
2801 {
2802 SCIP_CALL( SCIPprobAddCons(scip->transprob, scip->set, scip->stat, cons) );
2803 }
2804 else
2805 {
2806 assert(SCIPtreeGetCurrentDepth(scip->tree) > SCIPtreeGetEffectiveRootDepth(scip->tree));
2807 SCIP_CALL( SCIPnodeAddCons(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
2808 scip->tree, cons) );
2809 }
2810 return SCIP_OKAY;
2811
2812 case SCIP_STAGE_EXITSOLVE:
2813 SCIP_CALL( SCIPprobAddCons(scip->transprob, scip->set, scip->stat, cons) );
2814 return SCIP_OKAY;
2815
2816 default:
2817 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2818 return SCIP_INVALIDCALL;
2819 } /*lint !e788*/
2820 }
2821
2822 /** globally removes constraint from all subproblems; removes constraint from the constraint set change data of the
2823 * node, where it was added, or from the problem, if it was a problem constraint
2824 *
2825 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2826 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2827 *
2828 * @pre This method can be called if @p scip is in one of the following stages:
2829 * - \ref SCIP_STAGE_PROBLEM
2830 * - \ref SCIP_STAGE_INITPRESOLVE
2831 * - \ref SCIP_STAGE_PRESOLVING
2832 * - \ref SCIP_STAGE_EXITPRESOLVE
2833 * - \ref SCIP_STAGE_INITSOLVE
2834 * - \ref SCIP_STAGE_SOLVING
2835 * - \ref SCIP_STAGE_EXITSOLVE
2836 */
SCIPdelCons(SCIP * scip,SCIP_CONS * cons)2837 SCIP_RETCODE SCIPdelCons(
2838 SCIP* scip, /**< SCIP data structure */
2839 SCIP_CONS* cons /**< constraint to delete */
2840 )
2841 {
2842 assert(cons != NULL);
2843
2844 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelCons", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE) );
2845
2846 switch( scip->set->stage )
2847 {
2848 case SCIP_STAGE_PROBLEM:
2849 assert(cons->addconssetchg == NULL);
2850 SCIP_CALL( SCIPconsDelete(cons, scip->mem->probmem, scip->set, scip->stat, scip->origprob, scip->reopt) );
2851 return SCIP_OKAY;
2852
2853 /* only added constraints can be removed in (de-)initialization process of presolving, otherwise the reduction
2854 * might be wrong
2855 */
2856 case SCIP_STAGE_INITPRESOLVE:
2857 case SCIP_STAGE_EXITPRESOLVE:
2858 assert(SCIPconsIsAdded(cons));
2859 /*lint -fallthrough*/
2860
2861 case SCIP_STAGE_PRESOLVING:
2862 case SCIP_STAGE_INITSOLVE:
2863 case SCIP_STAGE_SOLVING:
2864 case SCIP_STAGE_EXITSOLVE:
2865 SCIP_CALL( SCIPconsDelete(cons, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->reopt) );
2866 return SCIP_OKAY;
2867
2868 default:
2869 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2870 return SCIP_INVALIDCALL;
2871 } /*lint !e788*/
2872 }
2873
2874 /** returns original constraint of given name in the problem, or NULL if not existing
2875 *
2876 * @return original constraint of given name in the problem, or NULL if not existing
2877 *
2878 * @pre This method can be called if @p scip is in one of the following stages:
2879 * - \ref SCIP_STAGE_PROBLEM
2880 * - \ref SCIP_STAGE_TRANSFORMING
2881 * - \ref SCIP_STAGE_TRANSFORMED
2882 * - \ref SCIP_STAGE_INITPRESOLVE
2883 * - \ref SCIP_STAGE_PRESOLVING
2884 * - \ref SCIP_STAGE_EXITPRESOLVE
2885 * - \ref SCIP_STAGE_PRESOLVED
2886 * - \ref SCIP_STAGE_INITSOLVE
2887 * - \ref SCIP_STAGE_SOLVING
2888 * - \ref SCIP_STAGE_SOLVED
2889 * - \ref SCIP_STAGE_EXITSOLVE
2890 * - \ref SCIP_STAGE_FREETRANS
2891 */
SCIPfindOrigCons(SCIP * scip,const char * name)2892 SCIP_CONS* SCIPfindOrigCons(
2893 SCIP* scip, /**< SCIP data structure */
2894 const char* name /**< name of constraint to find */
2895 )
2896 {
2897 assert(name != NULL);
2898
2899 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfindOrigCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2900
2901 switch( scip->set->stage )
2902 {
2903 case SCIP_STAGE_PROBLEM:
2904 case SCIP_STAGE_TRANSFORMING:
2905 case SCIP_STAGE_TRANSFORMED:
2906 case SCIP_STAGE_INITPRESOLVE:
2907 case SCIP_STAGE_PRESOLVING:
2908 case SCIP_STAGE_EXITPRESOLVE:
2909 case SCIP_STAGE_PRESOLVED:
2910 case SCIP_STAGE_SOLVING:
2911 case SCIP_STAGE_SOLVED:
2912 case SCIP_STAGE_EXITSOLVE:
2913 case SCIP_STAGE_FREETRANS:
2914 return SCIPprobFindCons(scip->origprob, name);
2915
2916 default:
2917 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2918 SCIPABORT();
2919 return NULL; /*lint !e527*/
2920 } /*lint !e788*/
2921 }
2922
2923 /** returns constraint of given name in the problem, or NULL if not existing
2924 *
2925 * @return constraint of given name in the problem, or NULL if not existing
2926 *
2927 * @pre This method can be called if @p scip is in one of the following stages:
2928 * - \ref SCIP_STAGE_PROBLEM
2929 * - \ref SCIP_STAGE_TRANSFORMING
2930 * - \ref SCIP_STAGE_TRANSFORMED
2931 * - \ref SCIP_STAGE_INITPRESOLVE
2932 * - \ref SCIP_STAGE_PRESOLVING
2933 * - \ref SCIP_STAGE_EXITPRESOLVE
2934 * - \ref SCIP_STAGE_PRESOLVED
2935 * - \ref SCIP_STAGE_INITSOLVE
2936 * - \ref SCIP_STAGE_SOLVING
2937 * - \ref SCIP_STAGE_SOLVED
2938 * - \ref SCIP_STAGE_EXITSOLVE
2939 * - \ref SCIP_STAGE_FREETRANS
2940 */
SCIPfindCons(SCIP * scip,const char * name)2941 SCIP_CONS* SCIPfindCons(
2942 SCIP* scip, /**< SCIP data structure */
2943 const char* name /**< name of constraint to find */
2944 )
2945 {
2946 SCIP_CONS* cons;
2947
2948 assert(name != NULL);
2949
2950 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfindCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
2951
2952 switch( scip->set->stage )
2953 {
2954 case SCIP_STAGE_PROBLEM:
2955 return SCIPprobFindCons(scip->origprob, name);
2956
2957 case SCIP_STAGE_TRANSFORMING:
2958 case SCIP_STAGE_TRANSFORMED:
2959 case SCIP_STAGE_INITPRESOLVE:
2960 case SCIP_STAGE_PRESOLVING:
2961 case SCIP_STAGE_EXITPRESOLVE:
2962 case SCIP_STAGE_PRESOLVED:
2963 case SCIP_STAGE_SOLVING:
2964 case SCIP_STAGE_SOLVED:
2965 case SCIP_STAGE_EXITSOLVE:
2966 case SCIP_STAGE_FREETRANS:
2967 cons = SCIPprobFindCons(scip->transprob, name);
2968 if( cons == NULL )
2969 return SCIPprobFindCons(scip->origprob, name);
2970 else
2971 return cons;
2972
2973 default:
2974 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
2975 SCIPABORT();
2976 return NULL; /*lint !e527*/
2977 } /*lint !e788*/
2978 }
2979
2980 /** gets number of upgraded constraints
2981 *
2982 * @return number of upgraded constraints
2983 *
2984 * @pre This method can be called if @p scip is in one of the following stages:
2985 * - \ref SCIP_STAGE_PROBLEM
2986 * - \ref SCIP_STAGE_TRANSFORMED
2987 * - \ref SCIP_STAGE_INITPRESOLVE
2988 * - \ref SCIP_STAGE_PRESOLVING
2989 * - \ref SCIP_STAGE_PRESOLVED
2990 * - \ref SCIP_STAGE_EXITPRESOLVE
2991 * - \ref SCIP_STAGE_SOLVING
2992 * - \ref SCIP_STAGE_SOLVED
2993 */
SCIPgetNUpgrConss(SCIP * scip)2994 int SCIPgetNUpgrConss(
2995 SCIP* scip /**< SCIP data structure */
2996 )
2997 {
2998 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNUpgrConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
2999
3000 switch( scip->set->stage )
3001 {
3002 case SCIP_STAGE_PROBLEM:
3003 return 0;
3004
3005 case SCIP_STAGE_TRANSFORMED:
3006 case SCIP_STAGE_INITPRESOLVE:
3007 case SCIP_STAGE_PRESOLVING:
3008 case SCIP_STAGE_EXITPRESOLVE:
3009 case SCIP_STAGE_PRESOLVED:
3010 case SCIP_STAGE_SOLVING:
3011 case SCIP_STAGE_SOLVED:
3012 return scip->stat->npresolupgdconss;
3013
3014 default:
3015 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3016 SCIPABORT();
3017 return 0; /*lint !e527*/
3018 } /*lint !e788*/
3019 }
3020
3021 /** gets total number of globally valid constraints currently in the problem
3022 *
3023 * @return total number of globally valid constraints currently in the problem
3024 *
3025 * @pre This method can be called if @p scip is in one of the following stages:
3026 * - \ref SCIP_STAGE_PROBLEM
3027 * - \ref SCIP_STAGE_TRANSFORMED
3028 * - \ref SCIP_STAGE_INITPRESOLVE
3029 * - \ref SCIP_STAGE_PRESOLVING
3030 * - \ref SCIP_STAGE_EXITPRESOLVE
3031 * - \ref SCIP_STAGE_PRESOLVED
3032 * - \ref SCIP_STAGE_INITSOLVE
3033 * - \ref SCIP_STAGE_SOLVING
3034 * - \ref SCIP_STAGE_SOLVED
3035 */
SCIPgetNConss(SCIP * scip)3036 int SCIPgetNConss(
3037 SCIP* scip /**< SCIP data structure */
3038 )
3039 {
3040 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
3041
3042 switch( scip->set->stage )
3043 {
3044 case SCIP_STAGE_PROBLEM:
3045 return scip->origprob->nconss;
3046
3047 case SCIP_STAGE_TRANSFORMED:
3048 case SCIP_STAGE_INITPRESOLVE:
3049 case SCIP_STAGE_PRESOLVING:
3050 case SCIP_STAGE_EXITPRESOLVE:
3051 case SCIP_STAGE_PRESOLVED:
3052 case SCIP_STAGE_INITSOLVE:
3053 case SCIP_STAGE_SOLVING:
3054 case SCIP_STAGE_SOLVED:
3055 return scip->transprob->nconss;
3056
3057 default:
3058 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3059 SCIPABORT();
3060 return 0; /*lint !e527*/
3061 } /*lint !e788*/
3062 }
3063
3064 /** gets array of globally valid constraints currently in the problem
3065 *
3066 * @return array of globally valid constraints currently in the problem
3067 *
3068 * @pre This method can be called if @p scip is in one of the following stages:
3069 * - \ref SCIP_STAGE_PROBLEM
3070 * - \ref SCIP_STAGE_TRANSFORMED
3071 * - \ref SCIP_STAGE_INITPRESOLVE
3072 * - \ref SCIP_STAGE_PRESOLVING
3073 * - \ref SCIP_STAGE_EXITPRESOLVE
3074 * - \ref SCIP_STAGE_PRESOLVED
3075 * - \ref SCIP_STAGE_INITSOLVE
3076 * - \ref SCIP_STAGE_SOLVING
3077 * - \ref SCIP_STAGE_SOLVED
3078 *
3079 * @warning If your are using the method SCIPaddCons(), it can happen that the internal constraint array (which is
3080 * accessed via this method) gets resized. This can invalid the pointer which is returned by this method.
3081 */
SCIPgetConss(SCIP * scip)3082 SCIP_CONS** SCIPgetConss(
3083 SCIP* scip /**< SCIP data structure */
3084 )
3085 {
3086 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetConss", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
3087
3088 switch( scip->set->stage )
3089 {
3090 case SCIP_STAGE_PROBLEM:
3091 return scip->origprob->conss;
3092
3093 case SCIP_STAGE_TRANSFORMED:
3094 case SCIP_STAGE_INITPRESOLVE:
3095 case SCIP_STAGE_PRESOLVING:
3096 case SCIP_STAGE_EXITPRESOLVE:
3097 case SCIP_STAGE_PRESOLVED:
3098 case SCIP_STAGE_INITSOLVE:
3099 case SCIP_STAGE_SOLVING:
3100 case SCIP_STAGE_SOLVED:
3101 return scip->transprob->conss;
3102
3103 default:
3104 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3105 SCIPABORT();
3106 return NULL; /*lint !e527*/
3107 } /*lint !e788*/
3108 }
3109
3110 /** gets total number of constraints in the original problem
3111 *
3112 * @return total number of constraints in the original problem
3113 *
3114 * @pre This method can be called if @p scip is in one of the following stages:
3115 * - \ref SCIP_STAGE_PROBLEM
3116 * - \ref SCIP_STAGE_TRANSFORMING
3117 * - \ref SCIP_STAGE_TRANSFORMED
3118 * - \ref SCIP_STAGE_INITPRESOLVE
3119 * - \ref SCIP_STAGE_PRESOLVING
3120 * - \ref SCIP_STAGE_EXITPRESOLVE
3121 * - \ref SCIP_STAGE_PRESOLVED
3122 * - \ref SCIP_STAGE_INITSOLVE
3123 * - \ref SCIP_STAGE_SOLVING
3124 * - \ref SCIP_STAGE_SOLVED
3125 * - \ref SCIP_STAGE_EXITSOLVE
3126 * - \ref SCIP_STAGE_FREETRANS
3127 */
SCIPgetNOrigConss(SCIP * scip)3128 int SCIPgetNOrigConss(
3129 SCIP* scip /**< SCIP data structure */
3130 )
3131 {
3132 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNOrigConss", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
3133
3134 return scip->origprob->nconss;
3135 }
3136
3137 /** gets array of constraints in the original problem
3138 *
3139 * @return array of constraints in the original problem
3140 *
3141 * @pre This method can be called if @p scip is in one of the following stages:
3142 * - \ref SCIP_STAGE_PROBLEM
3143 * - \ref SCIP_STAGE_TRANSFORMING
3144 * - \ref SCIP_STAGE_TRANSFORMED
3145 * - \ref SCIP_STAGE_INITPRESOLVE
3146 * - \ref SCIP_STAGE_PRESOLVING
3147 * - \ref SCIP_STAGE_EXITPRESOLVE
3148 * - \ref SCIP_STAGE_PRESOLVED
3149 * - \ref SCIP_STAGE_INITSOLVE
3150 * - \ref SCIP_STAGE_SOLVING
3151 * - \ref SCIP_STAGE_SOLVED
3152 * - \ref SCIP_STAGE_EXITSOLVE
3153 * - \ref SCIP_STAGE_FREETRANS
3154 */
SCIPgetOrigConss(SCIP * scip)3155 SCIP_CONS** SCIPgetOrigConss(
3156 SCIP* scip /**< SCIP data structure */
3157 )
3158 {
3159 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetOrigConss", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
3160
3161 return scip->origprob->conss;
3162 }
3163
3164 /** computes the number of check constraint in the current node (loop over all constraint handler and cumulates the
3165 * number of check constraints)
3166 *
3167 * @return returns the number of check constraints
3168 *
3169 * @pre This method can be called if @p scip is in one of the following stages:
3170 * - \ref SCIP_STAGE_TRANSFORMED
3171 * - \ref SCIP_STAGE_INITPRESOLVE
3172 * - \ref SCIP_STAGE_PRESOLVING
3173 * - \ref SCIP_STAGE_EXITPRESOLVE
3174 * - \ref SCIP_STAGE_PRESOLVED
3175 * - \ref SCIP_STAGE_INITSOLVE
3176 * - \ref SCIP_STAGE_SOLVING
3177 */
SCIPgetNCheckConss(SCIP * scip)3178 int SCIPgetNCheckConss(
3179 SCIP* scip /**< SCIP data structure */
3180 )
3181 {
3182 SCIP_CONSHDLR** conshdlrs;
3183 int nconshdlrs;
3184 int ncheckconss;
3185 int c;
3186
3187 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCheckConss", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3188
3189 nconshdlrs = SCIPgetNConshdlrs(scip);
3190 conshdlrs = SCIPgetConshdlrs(scip);
3191 assert(conshdlrs != NULL);
3192
3193 ncheckconss = 0;
3194
3195 /* loop over all constraint handler and collect the number of constraints which need to be checked */
3196 for( c = 0; c < nconshdlrs; ++c )
3197 {
3198 assert(conshdlrs[c] != NULL);
3199 ncheckconss += SCIPconshdlrGetNCheckConss(conshdlrs[c]);
3200 }
3201
3202 return ncheckconss;
3203 }
3204
3205 /*
3206 * local subproblem methods
3207 */
3208
3209 /** adds a conflict to a given node or globally to the problem if @p node == NULL.
3210 *
3211 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3212 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3213 *
3214 * @pre this method can be called in one of the following stages of the SCIP solving process:
3215 * - \ref SCIP_STAGE_INITPRESOLVE
3216 * - \ref SCIP_STAGE_PRESOLVING
3217 * - \ref SCIP_STAGE_EXITPRESOLVE
3218 * - \ref SCIP_STAGE_SOLVING
3219 *
3220 * @note this method will release the constraint
3221 */
SCIPaddConflict(SCIP * scip,SCIP_NODE * node,SCIP_CONS * cons,SCIP_NODE * validnode,SCIP_CONFTYPE conftype,SCIP_Bool iscutoffinvolved)3222 SCIP_RETCODE SCIPaddConflict(
3223 SCIP* scip, /**< SCIP data structure */
3224 SCIP_NODE* node, /**< node to add conflict (or NULL if global) */
3225 SCIP_CONS* cons, /**< constraint representing the conflict */
3226 SCIP_NODE* validnode, /**< node at whichaddConf the constraint is valid (or NULL) */
3227 SCIP_CONFTYPE conftype, /**< type of the conflict */
3228 SCIP_Bool iscutoffinvolved /**< is a cutoff bound involved in this conflict */
3229 )
3230 {
3231 SCIP_Real primalbound;
3232
3233 assert(scip != NULL);
3234 assert(cons != NULL);
3235 assert(scip->conflictstore != NULL);
3236 assert(conftype != SCIP_CONFTYPE_BNDEXCEEDING || iscutoffinvolved);
3237
3238 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddConflict", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3239
3240 if( iscutoffinvolved )
3241 primalbound = SCIPgetCutoffbound(scip);
3242 else
3243 primalbound = -SCIPinfinity(scip);
3244
3245 /* add a global conflict */
3246 if( node == NULL )
3247 {
3248 SCIP_CALL( SCIPaddCons(scip, cons) );
3249 }
3250 /* add a local conflict */
3251 else
3252 {
3253 SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
3254 }
3255
3256 if( node == NULL || SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE )
3257 {
3258 /* add the conflict to the conflict store */
3259 SCIP_CALL( SCIPconflictstoreAddConflict(scip->conflictstore, scip->mem->probmem, scip->set, scip->stat, scip->tree,
3260 scip->transprob, scip->reopt, cons, conftype, iscutoffinvolved, primalbound) );
3261 }
3262
3263 /* mark constraint to be a conflict */
3264 SCIPconsMarkConflict(cons);
3265
3266 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3267
3268 return SCIP_OKAY;
3269 }
3270
3271 /** tries to remove conflicts depending on an old cutoff bound if the improvement of the new incumbent is good enough
3272 *
3273 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3274 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3275 *
3276 * @pre this method can be called in one of the following stages of the SCIP solving process:
3277 * - \ref SCIP_STAGE_PRESOLVING
3278 * - \ref SCIP_STAGE_SOLVING
3279 */
SCIPclearConflictStore(SCIP * scip,SCIP_EVENT * event)3280 SCIP_RETCODE SCIPclearConflictStore(
3281 SCIP* scip, /**< SCIP data structure */
3282 SCIP_EVENT* event /**< event data */
3283 )
3284 {
3285 assert(scip != NULL);
3286 assert(event != NULL);
3287 assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_BESTSOLFOUND);
3288 assert(SCIPeventGetSol(event) != NULL);
3289
3290 SCIP_CALL( SCIPcheckStage(scip, "SCIPclearConflictStore", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3291
3292 SCIP_CALL( SCIPconflictstoreCleanNewIncumbent(scip->conflictstore, scip->set, scip->stat, scip->mem->probmem,
3293 scip->transprob, scip->reopt, scip->primal->cutoffbound) );
3294
3295 return SCIP_OKAY;
3296 }
3297
3298 /** adds constraint to the given node (and all of its subnodes), even if it is a global constraint;
3299 * It is sometimes desirable to add the constraint to a more local node (i.e., a node of larger depth) even if
3300 * the constraint is also valid higher in the tree, for example, if one wants to produce a constraint which is
3301 * only active in a small part of the tree although it is valid in a larger part.
3302 * In this case, one should pass the more global node where the constraint is valid as "validnode".
3303 * Note that the same constraint cannot be added twice to the branching tree with different "validnode" parameters.
3304 * If the constraint is valid at the same node as it is inserted (the usual case), one should pass NULL as "validnode".
3305 * If the "validnode" is the root node, it is automatically upgraded into a global constraint, but still only added to
3306 * the given node. If a local constraint is added to the root node, it is added to the global problem instead.
3307 *
3308 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3309 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3310 *
3311 * @pre this method can be called in one of the following stages of the SCIP solving process:
3312 * - \ref SCIP_STAGE_INITPRESOLVE
3313 * - \ref SCIP_STAGE_PRESOLVING
3314 * - \ref SCIP_STAGE_EXITPRESOLVE
3315 * - \ref SCIP_STAGE_SOLVING
3316 */
SCIPaddConsNode(SCIP * scip,SCIP_NODE * node,SCIP_CONS * cons,SCIP_NODE * validnode)3317 SCIP_RETCODE SCIPaddConsNode(
3318 SCIP* scip, /**< SCIP data structure */
3319 SCIP_NODE* node, /**< node to add constraint to */
3320 SCIP_CONS* cons, /**< constraint to add */
3321 SCIP_NODE* validnode /**< node at which the constraint is valid, or NULL */
3322 )
3323 {
3324 assert(cons != NULL);
3325 assert(node != NULL);
3326
3327 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddConsNode", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3328
3329 if( validnode != NULL )
3330 {
3331 int validdepth;
3332
3333 validdepth = SCIPnodeGetDepth(validnode);
3334 if( validdepth > SCIPnodeGetDepth(node) )
3335 {
3336 SCIPerrorMessage("cannot add constraint <%s> valid in depth %d to a node of depth %d\n",
3337 SCIPconsGetName(cons), validdepth, SCIPnodeGetDepth(node));
3338 return SCIP_INVALIDDATA;
3339 }
3340 if( cons->validdepth != -1 && cons->validdepth != validdepth )
3341 {
3342 SCIPerrorMessage("constraint <%s> is already marked to be valid in depth %d - cannot mark it to be valid in depth %d\n",
3343 SCIPconsGetName(cons), cons->validdepth, validdepth);
3344 return SCIP_INVALIDDATA;
3345 }
3346 if( validdepth <= SCIPtreeGetEffectiveRootDepth(scip->tree) )
3347 SCIPconsSetLocal(cons, FALSE);
3348 else
3349 cons->validdepth = validdepth;
3350 }
3351
3352 if( SCIPnodeGetDepth(node) <= SCIPtreeGetEffectiveRootDepth(scip->tree) )
3353 {
3354 SCIPconsSetLocal(cons, FALSE);
3355 SCIP_CALL( SCIPprobAddCons(scip->transprob, scip->set, scip->stat, cons) );
3356 }
3357 else
3358 {
3359 SCIP_CALL( SCIPnodeAddCons(node, scip->mem->probmem, scip->set, scip->stat, scip->tree, cons) );
3360 }
3361
3362 return SCIP_OKAY;
3363 }
3364
3365 /** adds constraint locally to the current node (and all of its subnodes), even if it is a global constraint;
3366 * It is sometimes desirable to add the constraint to a more local node (i.e., a node of larger depth) even if
3367 * the constraint is also valid higher in the tree, for example, if one wants to produce a constraint which is
3368 * only active in a small part of the tree although it is valid in a larger part.
3369 *
3370 * If the constraint is valid at the same node as it is inserted (the usual case), one should pass NULL as "validnode".
3371 * If the "validnode" is the root node, it is automatically upgraded into a global constraint, but still only added to
3372 * the given node. If a local constraint is added to the root node, it is added to the global problem instead.
3373 *
3374 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3375 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3376 *
3377 * @pre this method can be called in one of the following stages of the SCIP solving process:
3378 * - \ref SCIP_STAGE_INITPRESOLVE
3379 * - \ref SCIP_STAGE_PRESOLVING
3380 * - \ref SCIP_STAGE_EXITPRESOLVE
3381 * - \ref SCIP_STAGE_SOLVING
3382 *
3383 * @note The same constraint cannot be added twice to the branching tree with different "validnode" parameters. This is
3384 * the case due to internal data structures and performance issues. In such a case you should try to realize your
3385 * issue using the method SCIPdisableCons() and SCIPenableCons() and control these via the event system of SCIP.
3386 */
SCIPaddConsLocal(SCIP * scip,SCIP_CONS * cons,SCIP_NODE * validnode)3387 SCIP_RETCODE SCIPaddConsLocal(
3388 SCIP* scip, /**< SCIP data structure */
3389 SCIP_CONS* cons, /**< constraint to add */
3390 SCIP_NODE* validnode /**< node at which the constraint is valid, or NULL */
3391 )
3392 {
3393 assert(cons != NULL);
3394
3395 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddConsLocal", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3396
3397 SCIP_CALL( SCIPaddConsNode(scip, SCIPtreeGetCurrentNode(scip->tree), cons, validnode) );
3398
3399 return SCIP_OKAY;
3400 }
3401
3402 /** disables constraint's separation, enforcing, and propagation capabilities at the given node (and all subnodes);
3403 * if the method is called at the root node, the constraint is globally deleted from the problem;
3404 * the constraint deletion is being remembered at the given node, s.t. after leaving the node's subtree, the constraint
3405 * is automatically enabled again, and after entering the node's subtree, it is automatically disabled;
3406 * this may improve performance because redundant checks on this constraint are avoided, but it consumes memory;
3407 * alternatively, use SCIPdisableCons()
3408 *
3409 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3410 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3411 *
3412 * @pre this method can be called in one of the following stages of the SCIP solving process:
3413 * - \ref SCIP_STAGE_INITPRESOLVE
3414 * - \ref SCIP_STAGE_PRESOLVING
3415 * - \ref SCIP_STAGE_EXITPRESOLVE
3416 * - \ref SCIP_STAGE_SOLVING
3417 */
SCIPdelConsNode(SCIP * scip,SCIP_NODE * node,SCIP_CONS * cons)3418 SCIP_RETCODE SCIPdelConsNode(
3419 SCIP* scip, /**< SCIP data structure */
3420 SCIP_NODE* node, /**< node to disable constraint in */
3421 SCIP_CONS* cons /**< constraint to locally delete */
3422 )
3423 {
3424 assert(cons != NULL);
3425
3426 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelConsNode", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3427
3428 /* only added constraints can be removed in (de-)initialization process of presolving, otherwise the reduction
3429 * might be wrong
3430 */
3431 if( scip->set->stage == SCIP_STAGE_INITPRESOLVE || scip->set->stage == SCIP_STAGE_EXITPRESOLVE )
3432 assert(SCIPconsIsAdded(cons));
3433
3434 if( SCIPnodeGetDepth(node) <= SCIPtreeGetEffectiveRootDepth(scip->tree) )
3435 {
3436 SCIP_CALL( SCIPconsDelete(cons, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->reopt) );
3437 }
3438 else
3439 {
3440 SCIP_CALL( SCIPnodeDelCons(node, scip->mem->probmem, scip->set, scip->stat, scip->tree, cons) );
3441 }
3442
3443 return SCIP_OKAY;
3444 }
3445
3446 /** disables constraint's separation, enforcing, and propagation capabilities at the current node (and all subnodes);
3447 * if the method is called during problem modification or at the root node, the constraint is globally deleted from
3448 * the problem;
3449 * the constraint deletion is being remembered at the current node, s.t. after leaving the current subtree, the
3450 * constraint is automatically enabled again, and after reentering the current node's subtree, it is automatically
3451 * disabled again;
3452 * this may improve performance because redundant checks on this constraint are avoided, but it consumes memory;
3453 * alternatively, use SCIPdisableCons()
3454 *
3455 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3456 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3457 *
3458 * @pre this method can be called in one of the following stages of the SCIP solving process:
3459 * - \ref SCIP_STAGE_PROBLEM
3460 * - \ref SCIP_STAGE_INITPRESOLVE
3461 * - \ref SCIP_STAGE_PRESOLVING
3462 * - \ref SCIP_STAGE_EXITPRESOLVE
3463 * - \ref SCIP_STAGE_SOLVING
3464 *
3465 * @note SCIP stage does not get changed
3466 *
3467 */
SCIPdelConsLocal(SCIP * scip,SCIP_CONS * cons)3468 SCIP_RETCODE SCIPdelConsLocal(
3469 SCIP* scip, /**< SCIP data structure */
3470 SCIP_CONS* cons /**< constraint to locally delete */
3471 )
3472 {
3473 SCIP_NODE* node;
3474
3475 assert(cons != NULL);
3476
3477 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelConsLocal", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3478
3479 switch( scip->set->stage )
3480 {
3481 case SCIP_STAGE_PROBLEM:
3482 assert(cons->addconssetchg == NULL);
3483 SCIP_CALL( SCIPconsDelete(cons, scip->mem->probmem, scip->set, scip->stat, scip->origprob, scip->reopt) );
3484 return SCIP_OKAY;
3485
3486 /* only added constraints can be removed in (de-)initialization process of presolving, otherwise the reduction
3487 * might be wrong
3488 */
3489 case SCIP_STAGE_INITPRESOLVE:
3490 case SCIP_STAGE_EXITPRESOLVE:
3491 assert(SCIPconsIsAdded(cons));
3492 /*lint -fallthrough*/
3493
3494 case SCIP_STAGE_PRESOLVING:
3495 case SCIP_STAGE_SOLVING:
3496 node = SCIPtreeGetCurrentNode(scip->tree);
3497
3498 if( SCIPnodeGetDepth(node) <= SCIPtreeGetEffectiveRootDepth(scip->tree) )
3499 {
3500 SCIP_CALL( SCIPconsDelete(cons, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->reopt) );
3501 }
3502 else
3503 {
3504 SCIP_CALL( SCIPnodeDelCons(node, scip->mem->probmem, scip->set, scip->stat, scip->tree, cons) );
3505 }
3506 return SCIP_OKAY;
3507
3508 default:
3509 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3510 return SCIP_INVALIDCALL;
3511 } /*lint !e788*/
3512 }
3513
3514 /** gets estimate of best primal solution w.r.t. original problem contained in current subtree
3515 *
3516 * @return estimate of best primal solution w.r.t. original problem contained in current subtree
3517 *
3518 * @pre this method can be called in one of the following stages of the SCIP solving process:
3519 * - \ref SCIP_STAGE_SOLVING
3520 */
SCIPgetLocalOrigEstimate(SCIP * scip)3521 SCIP_Real SCIPgetLocalOrigEstimate(
3522 SCIP* scip /**< SCIP data structure */
3523 )
3524 {
3525 SCIP_NODE* node;
3526
3527 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetLocalOrigEstimate", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3528
3529 node = SCIPtreeGetCurrentNode(scip->tree);
3530 return node != NULL ? SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, SCIPnodeGetEstimate(node)) : SCIP_INVALID;
3531 }
3532
3533 /** gets estimate of best primal solution w.r.t. transformed problem contained in current subtree
3534 *
3535 * @return estimate of best primal solution w.r.t. transformed problem contained in current subtree
3536 *
3537 * @pre this method can be called in one of the following stages of the SCIP solving process:
3538 * - \ref SCIP_STAGE_SOLVING
3539 */
SCIPgetLocalTransEstimate(SCIP * scip)3540 SCIP_Real SCIPgetLocalTransEstimate(
3541 SCIP* scip /**< SCIP data structure */
3542 )
3543 {
3544 SCIP_NODE* node;
3545
3546 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetLocalTransEstimate", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3547
3548 node = SCIPtreeGetCurrentNode(scip->tree);
3549
3550 return node != NULL ? SCIPnodeGetEstimate(node) : SCIP_INVALID;
3551 }
3552
3553 /** gets dual bound of current node
3554 *
3555 * @return dual bound of current node
3556 *
3557 * @pre this method can be called in one of the following stages of the SCIP solving process:
3558 * - \ref SCIP_STAGE_SOLVING
3559 */
SCIPgetLocalDualbound(SCIP * scip)3560 SCIP_Real SCIPgetLocalDualbound(
3561 SCIP* scip /**< SCIP data structure */
3562 )
3563 {
3564 SCIP_NODE* node;
3565
3566 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetLocalDualbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3567
3568 node = SCIPtreeGetCurrentNode(scip->tree);
3569 return node != NULL ? SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, SCIPnodeGetLowerbound(node)) : SCIP_INVALID;
3570 }
3571
3572 /** gets lower bound of current node in transformed problem
3573 *
3574 * @return lower bound of current node in transformed problem
3575 *
3576 * @pre this method can be called in one of the following stages of the SCIP solving process:
3577 * - \ref SCIP_STAGE_SOLVING
3578 */
SCIPgetLocalLowerbound(SCIP * scip)3579 SCIP_Real SCIPgetLocalLowerbound(
3580 SCIP* scip /**< SCIP data structure */
3581 )
3582 {
3583 SCIP_NODE* node;
3584
3585 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetLocalLowerbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3586
3587 node = SCIPtreeGetCurrentNode(scip->tree);
3588
3589 return node != NULL ? SCIPnodeGetLowerbound(node) : SCIP_INVALID;
3590 }
3591
3592 /** gets dual bound of given node
3593 *
3594 * @return dual bound of a given node
3595 *
3596 * @pre this method can be called in one of the following stages of the SCIP solving process:
3597 * - \ref SCIP_STAGE_SOLVING
3598 */
SCIPgetNodeDualbound(SCIP * scip,SCIP_NODE * node)3599 SCIP_Real SCIPgetNodeDualbound(
3600 SCIP* scip, /**< SCIP data structure */
3601 SCIP_NODE* node /**< node to get dual bound for */
3602 )
3603 {
3604 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNodeDualbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3605
3606 return SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, SCIPnodeGetLowerbound(node));
3607 }
3608
3609 /** gets lower bound of given node in transformed problem
3610 *
3611 * @return lower bound of given node in transformed problem
3612 *
3613 * @pre this method can be called in one of the following stages of the SCIP solving process:
3614 * - \ref SCIP_STAGE_SOLVING
3615 */
SCIPgetNodeLowerbound(SCIP * scip,SCIP_NODE * node)3616 SCIP_Real SCIPgetNodeLowerbound(
3617 SCIP* scip, /**< SCIP data structure */
3618 SCIP_NODE* node /**< node to get dual bound for */
3619 )
3620 {
3621 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNodeLowerbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3622
3623 return SCIPnodeGetLowerbound(node);
3624 }
3625
3626 /** if given value is tighter (larger for minimization, smaller for maximization) than the current node's dual bound (in
3627 * original problem space), sets the current node's dual bound to the new value
3628 *
3629 * @note the given new bound has to be a dual bound, i.e., it has to be valid for the original problem.
3630 *
3631 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3632 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3633 *
3634 * @pre this method can be called in one of the following stages of the SCIP solving process:
3635 * - \ref SCIP_STAGE_PROBLEM
3636 * - \ref SCIP_STAGE_PRESOLVING
3637 * - \ref SCIP_STAGE_PRESOLVED
3638 * - \ref SCIP_STAGE_SOLVING
3639 */
SCIPupdateLocalDualbound(SCIP * scip,SCIP_Real newbound)3640 SCIP_RETCODE SCIPupdateLocalDualbound(
3641 SCIP* scip, /**< SCIP data structure */
3642 SCIP_Real newbound /**< new dual bound for the node (if it's tighter than the old one) */
3643 )
3644 {
3645 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateLocalDualbound", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3646
3647 switch( scip->set->stage )
3648 {
3649 case SCIP_STAGE_PROBLEM:
3650 /* since no root node, for which we could update the dual bound, has been create yet, update the dual bound stored in
3651 * the problem data
3652 */
3653 SCIPprobUpdateDualbound(scip->origprob, newbound);
3654 break;
3655
3656 case SCIP_STAGE_PRESOLVING:
3657 case SCIP_STAGE_PRESOLVED:
3658 /* since no root node, for which we could update the dual bound, has been create yet, update the dual bound stored in
3659 * the problem data
3660 */
3661 SCIPprobUpdateDualbound(scip->transprob, SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, newbound));
3662 break;
3663
3664 case SCIP_STAGE_SOLVING:
3665 SCIP_CALL( SCIPupdateNodeLowerbound(scip, SCIPtreeGetCurrentNode(scip->tree), SCIPprobInternObjval(scip->transprob, scip->origprob, scip->set, newbound)) );
3666 break;
3667
3668 default:
3669 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3670 SCIPABORT();
3671 return SCIP_INVALIDCALL; /*lint !e527*/
3672 } /*lint !e788*/
3673
3674 return SCIP_OKAY;
3675 }
3676
3677 /** if given value is larger than the current node's lower bound (in transformed problem), sets the current node's
3678 * lower bound to the new value
3679 *
3680 * @note the given new bound has to be a lower bound, i.e., it has to be valid for the transformed problem.
3681 *
3682 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3683 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3684 *
3685 * @pre this method can be called in one of the following stages of the SCIP solving process:
3686 * - \ref SCIP_STAGE_PRESOLVING
3687 * - \ref SCIP_STAGE_PRESOLVED
3688 * - \ref SCIP_STAGE_SOLVING
3689 */
SCIPupdateLocalLowerbound(SCIP * scip,SCIP_Real newbound)3690 SCIP_RETCODE SCIPupdateLocalLowerbound(
3691 SCIP* scip, /**< SCIP data structure */
3692 SCIP_Real newbound /**< new lower bound for the node (if it's larger than the old one) */
3693 )
3694 {
3695 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateLocalLowerbound", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3696
3697 switch( scip->set->stage )
3698 {
3699 case SCIP_STAGE_PRESOLVING:
3700 case SCIP_STAGE_PRESOLVED:
3701 /* since no root node, for which we could update the lower bound, has been created yet, update the dual bound stored
3702 * in the problem data
3703 */
3704 SCIPprobUpdateDualbound(scip->transprob, SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, newbound));
3705 break;
3706
3707 case SCIP_STAGE_SOLVING:
3708 SCIP_CALL( SCIPupdateNodeLowerbound(scip, SCIPtreeGetCurrentNode(scip->tree), newbound) );
3709 break;
3710
3711 default:
3712 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
3713 SCIPABORT();
3714 return SCIP_INVALIDCALL; /*lint !e527*/
3715 } /*lint !e788*/
3716
3717 return SCIP_OKAY;
3718 }
3719
3720 /** if given value is tighter (larger for minimization, smaller for maximization) than the node's dual bound,
3721 * sets the node's dual bound to the new value
3722 *
3723 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3724 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3725 *
3726 * @pre this method can be called in one of the following stages of the SCIP solving process:
3727 * - \ref SCIP_STAGE_SOLVING
3728 */
SCIPupdateNodeDualbound(SCIP * scip,SCIP_NODE * node,SCIP_Real newbound)3729 SCIP_RETCODE SCIPupdateNodeDualbound(
3730 SCIP* scip, /**< SCIP data structure */
3731 SCIP_NODE* node, /**< node to update dual bound for */
3732 SCIP_Real newbound /**< new dual bound for the node (if it's tighter than the old one) */
3733 )
3734 {
3735 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateNodeDualbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3736
3737 SCIP_CALL( SCIPupdateNodeLowerbound(scip, node, SCIPprobInternObjval(scip->transprob, scip->origprob, scip->set, newbound)) );
3738
3739 return SCIP_OKAY;
3740 }
3741
3742 /** if given value is larger than the node's lower bound (in transformed problem), sets the node's lower bound
3743 * to the new value
3744 *
3745 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3746 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3747 *
3748 * @pre this method can be called in one of the following stages of the SCIP solving process:
3749 * - \ref SCIP_STAGE_SOLVING
3750 */
SCIPupdateNodeLowerbound(SCIP * scip,SCIP_NODE * node,SCIP_Real newbound)3751 SCIP_RETCODE SCIPupdateNodeLowerbound(
3752 SCIP* scip, /**< SCIP data structure */
3753 SCIP_NODE* node, /**< node to update lower bound for */
3754 SCIP_Real newbound /**< new lower bound for the node (if it's larger than the old one) */
3755 )
3756 {
3757 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateNodeLowerbound", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3758
3759 SCIPnodeUpdateLowerbound(node, scip->stat, scip->set, scip->tree, scip->transprob, scip->origprob, newbound);
3760
3761 /* if lowerbound exceeds the cutoffbound the node will be marked to be cutoff
3762 *
3763 * If the node is an inner node (,not a child node,) we need to cutoff the node manually if we exceed the
3764 * cutoffbound. This is only relevant if a user updates the lower bound; in the main solving process of SCIP the
3765 * lowerbound is only changed before branching and the given node is always a child node. Therefore, we only check
3766 * for a cutoff here in the user function instead of in SCIPnodeUpdateLowerbound().
3767 */
3768 if( SCIPisGE(scip, newbound, scip->primal->cutoffbound) )
3769 {
3770 SCIP_CALL( SCIPnodeCutoff(node, scip->set, scip->stat, scip->tree, scip->transprob, scip->origprob, scip->reopt,
3771 scip->lp, scip->mem->probmem) );
3772 }
3773
3774 return SCIP_OKAY;
3775 }
3776
3777 /** change the node selection priority of the given child
3778 *
3779 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3780 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3781 *
3782 * @pre this method can be called in one of the following stages of the SCIP solving process:
3783 * - \ref SCIP_STAGE_SOLVING
3784 */
SCIPchgChildPrio(SCIP * scip,SCIP_NODE * child,SCIP_Real priority)3785 SCIP_RETCODE SCIPchgChildPrio(
3786 SCIP* scip, /**< SCIP data structure */
3787 SCIP_NODE* child, /**< child to update the node selection priority */
3788 SCIP_Real priority /**< node selection priority value */
3789 )
3790 {
3791 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgChildPrio", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3792
3793 if( SCIPnodeGetType(child) != SCIP_NODETYPE_CHILD )
3794 return SCIP_INVALIDDATA;
3795
3796 SCIPchildChgNodeselPrio(scip->tree, child, priority);
3797
3798 return SCIP_OKAY;
3799 }
3800