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