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_var.c
17  * @ingroup OTHER_CFILES
18  * @brief  public methods for SCIP variables
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 "lpi/lpi.h"
38 #include "scip/branch.h"
39 #include "scip/clock.h"
40 #include "scip/conflict.h"
41 #include "scip/debug.h"
42 #include "scip/history.h"
43 #include "scip/implics.h"
44 #include "scip/lp.h"
45 #include "scip/prob.h"
46 #include "scip/pub_cons.h"
47 #include "scip/pub_implics.h"
48 #include "scip/pub_lp.h"
49 #include "scip/pub_message.h"
50 #include "scip/pub_misc.h"
51 #include "scip/pub_tree.h"
52 #include "scip/pub_var.h"
53 #include "scip/relax.h"
54 #include "scip/scip_general.h"
55 #include "scip/scip_lp.h"
56 #include "scip/scip_mem.h"
57 #include "scip/scip_message.h"
58 #include "scip/scip_numerics.h"
59 #include "scip/scip_prob.h"
60 #include "scip/scip_probing.h"
61 #include "scip/scip_sol.h"
62 #include "scip/scip_solvingstats.h"
63 #include "scip/scip_tree.h"
64 #include "scip/scip_var.h"
65 #include "scip/set.h"
66 #include "scip/sol.h"
67 #include "scip/solve.h"
68 #include "scip/stat.h"
69 #include "scip/struct_lp.h"
70 #include "scip/struct_mem.h"
71 #include "scip/struct_primal.h"
72 #include "scip/struct_prob.h"
73 #include "scip/struct_scip.h"
74 #include "scip/struct_set.h"
75 #include "scip/struct_stat.h"
76 #include "scip/struct_tree.h"
77 #include "scip/struct_var.h"
78 #include "scip/tree.h"
79 #include "scip/var.h"
80 #include <ctype.h>
81 
82 
83 /** creates and captures problem variable; if variable is of integral type, fractional bounds are automatically rounded;
84  *  an integer variable with bounds zero and one is automatically converted into a binary variable;
85  *
86  *  @warning When doing column generation and the original problem is a maximization problem, notice that SCIP will
87  *           transform the problem into a minimization problem by multiplying the objective function by -1.  Thus, the
88  *           original objective function value of variables created during the solving process has to be multiplied by
89  *           -1, too.
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_PROBLEM
96  *       - \ref SCIP_STAGE_TRANSFORMING
97  *       - \ref SCIP_STAGE_INITPRESOLVE
98  *       - \ref SCIP_STAGE_PRESOLVING
99  *       - \ref SCIP_STAGE_EXITPRESOLVE
100  *       - \ref SCIP_STAGE_PRESOLVED
101  *       - \ref SCIP_STAGE_SOLVING
102  *
103  *  @note the variable gets captured, hence at one point you have to release it using the method SCIPreleaseVar()
104  */
SCIPcreateVar(SCIP * scip,SCIP_VAR ** var,const char * name,SCIP_Real lb,SCIP_Real ub,SCIP_Real obj,SCIP_VARTYPE vartype,SCIP_Bool initial,SCIP_Bool removable,SCIP_DECL_VARDELORIG ((* vardelorig)),SCIP_DECL_VARTRANS ((* vartrans)),SCIP_DECL_VARDELTRANS ((* vardeltrans)),SCIP_DECL_VARCOPY ((* varcopy)),SCIP_VARDATA * vardata)105 SCIP_RETCODE SCIPcreateVar(
106    SCIP*                 scip,               /**< SCIP data structure */
107    SCIP_VAR**            var,                /**< pointer to variable object */
108    const char*           name,               /**< name of variable, or NULL for automatic name creation */
109    SCIP_Real             lb,                 /**< lower bound of variable */
110    SCIP_Real             ub,                 /**< upper bound of variable */
111    SCIP_Real             obj,                /**< objective function value */
112    SCIP_VARTYPE          vartype,            /**< type of variable */
113    SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
114    SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
115    SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable, or NULL */
116    SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data, or NULL */
117    SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable, or NULL */
118    SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
119    SCIP_VARDATA*         vardata             /**< user data for this specific variable */
120    )
121 {
122    assert(var != NULL);
123    assert(lb <= ub);
124 
125    SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateVar", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
126 
127    /* forbid infinite objective function values */
128    if( SCIPisInfinity(scip, REALABS(obj)) )
129    {
130       SCIPerrorMessage("invalid objective function value: value is infinite\n");
131       return SCIP_INVALIDDATA;
132    }
133 
134    switch( scip->set->stage )
135    {
136    case SCIP_STAGE_PROBLEM:
137       SCIP_CALL( SCIPvarCreateOriginal(var, scip->mem->probmem, scip->set, scip->stat,
138             name, lb, ub, obj, vartype, initial, removable, vardelorig, vartrans, vardeltrans, varcopy, vardata) );
139       break;
140 
141    case SCIP_STAGE_TRANSFORMING:
142    case SCIP_STAGE_INITPRESOLVE:
143    case SCIP_STAGE_PRESOLVING:
144    case SCIP_STAGE_EXITPRESOLVE:
145    case SCIP_STAGE_PRESOLVED:
146    case SCIP_STAGE_SOLVING:
147       SCIP_CALL( SCIPvarCreateTransformed(var, scip->mem->probmem, scip->set, scip->stat,
148             name, lb, ub, obj, vartype, initial, removable, vardelorig, vartrans, vardeltrans, varcopy, vardata) );
149       break;
150 
151    default:
152       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
153       return SCIP_INVALIDCALL;
154    }  /*lint !e788*/
155 
156    return SCIP_OKAY;
157 }
158 
159 /** creates and captures problem variable with optional callbacks and variable data set to NULL, which can be set
160  *  afterwards using SCIPvarSetDelorigData(), SCIPvarSetTransData(),
161  *  SCIPvarSetDeltransData(), SCIPvarSetCopy(), and SCIPvarSetData(); sets variable flags initial=TRUE
162  *  and removable = FALSE, which can be adjusted by using SCIPvarSetInitial() and SCIPvarSetRemovable(), resp.;
163  *  if variable is of integral type, fractional bounds are automatically rounded;
164  *  an integer variable with bounds zero and one is automatically converted into a binary variable;
165  *
166  *  @warning When doing column generation and the original problem is a maximization problem, notice that SCIP will
167  *           transform the problem into a minimization problem by multiplying the objective function by -1.  Thus, the
168  *           original objective function value of variables created during the solving process has to be multiplied by
169  *           -1, too.
170  *
171  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
172  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
173  *
174  *  @pre This method can be called if @p scip is in one of the following stages:
175  *       - \ref SCIP_STAGE_PROBLEM
176  *       - \ref SCIP_STAGE_TRANSFORMING
177  *       - \ref SCIP_STAGE_INITPRESOLVE
178  *       - \ref SCIP_STAGE_PRESOLVING
179  *       - \ref SCIP_STAGE_EXITPRESOLVE
180  *       - \ref SCIP_STAGE_PRESOLVED
181  *       - \ref SCIP_STAGE_SOLVING
182  *
183  *  @note the variable gets captured, hence at one point you have to release it using the method SCIPreleaseVar()
184  */
SCIPcreateVarBasic(SCIP * scip,SCIP_VAR ** var,const char * name,SCIP_Real lb,SCIP_Real ub,SCIP_Real obj,SCIP_VARTYPE vartype)185 SCIP_RETCODE SCIPcreateVarBasic(
186    SCIP*                 scip,               /**< SCIP data structure */
187    SCIP_VAR**            var,                /**< pointer to variable object */
188    const char*           name,               /**< name of variable, or NULL for automatic name creation */
189    SCIP_Real             lb,                 /**< lower bound of variable */
190    SCIP_Real             ub,                 /**< upper bound of variable */
191    SCIP_Real             obj,                /**< objective function value */
192    SCIP_VARTYPE          vartype             /**< type of variable */
193    )
194 {
195    SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateVarBasic", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
196 
197    SCIP_CALL( SCIPcreateVar(scip, var, name, lb, ub, obj, vartype, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
198 
199    return SCIP_OKAY;
200 }
201 
202 /** outputs the variable name to the file stream
203  *
204  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
205  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
206  *
207  *  @pre This method can be called if @p scip is in one of the following stages:
208  *       - \ref SCIP_STAGE_PROBLEM
209  *       - \ref SCIP_STAGE_TRANSFORMING
210  *       - \ref SCIP_STAGE_TRANSFORMED
211  *       - \ref SCIP_STAGE_INITPRESOLVE
212  *       - \ref SCIP_STAGE_PRESOLVING
213  *       - \ref SCIP_STAGE_EXITPRESOLVE
214  *       - \ref SCIP_STAGE_PRESOLVED
215  *       - \ref SCIP_STAGE_INITSOLVE
216  *       - \ref SCIP_STAGE_SOLVING
217  *       - \ref SCIP_STAGE_SOLVED
218  *       - \ref SCIP_STAGE_EXITSOLVE
219  *       - \ref SCIP_STAGE_FREETRANS
220  */
SCIPwriteVarName(SCIP * scip,FILE * file,SCIP_VAR * var,SCIP_Bool type)221 SCIP_RETCODE SCIPwriteVarName(
222    SCIP*                 scip,               /**< SCIP data structure */
223    FILE*                 file,               /**< output file, or NULL for stdout */
224    SCIP_VAR*             var,                /**< variable to output */
225    SCIP_Bool             type                /**< should the variable type be also posted */
226    )
227 {
228    assert(scip != NULL);
229    assert(var != NULL);
230 
231    SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarName", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
232 
233    /* print variable name */
234    if( SCIPvarIsNegated(var) )
235    {
236       SCIP_VAR* negatedvar;
237 
238       SCIP_CALL( SCIPgetNegatedVar(scip, var, &negatedvar) );
239       SCIPinfoMessage(scip, file, "<~%s>", SCIPvarGetName(negatedvar));
240    }
241    else
242    {
243       SCIPinfoMessage(scip, file, "<%s>", SCIPvarGetName(var));
244    }
245 
246    if( type )
247    {
248       /* print variable type */
249       SCIPinfoMessage(scip, file, "[%c]",
250          SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ? SCIP_VARTYPE_BINARY_CHAR :
251          SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER ? SCIP_VARTYPE_INTEGER_CHAR :
252          SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT ? SCIP_VARTYPE_IMPLINT_CHAR : SCIP_VARTYPE_CONTINUOUS_CHAR);
253    }
254 
255    return SCIP_OKAY;
256 }
257 
258 /** print the given list of variables to output stream separated by the given delimiter character;
259  *
260  *  i. e. the variables x1, x2, ..., xn with given delimiter ',' are written as: \<x1\>, \<x2\>, ..., \<xn\>;
261  *
262  *  the method SCIPparseVarsList() can parse such a string
263  *
264  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
265  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
266  *
267  *  @pre This method can be called if @p scip is in one of the following stages:
268  *       - \ref SCIP_STAGE_PROBLEM
269  *       - \ref SCIP_STAGE_TRANSFORMING
270  *       - \ref SCIP_STAGE_TRANSFORMED
271  *       - \ref SCIP_STAGE_INITPRESOLVE
272  *       - \ref SCIP_STAGE_PRESOLVING
273  *       - \ref SCIP_STAGE_EXITPRESOLVE
274  *       - \ref SCIP_STAGE_PRESOLVED
275  *       - \ref SCIP_STAGE_INITSOLVE
276  *       - \ref SCIP_STAGE_SOLVING
277  *       - \ref SCIP_STAGE_SOLVED
278  *       - \ref SCIP_STAGE_EXITSOLVE
279  *       - \ref SCIP_STAGE_FREETRANS
280  *
281  *  @note The printing process is done via the message handler system.
282  */
SCIPwriteVarsList(SCIP * scip,FILE * file,SCIP_VAR ** vars,int nvars,SCIP_Bool type,char delimiter)283 SCIP_RETCODE SCIPwriteVarsList(
284    SCIP*                 scip,               /**< SCIP data structure */
285    FILE*                 file,               /**< output file, or NULL for stdout */
286    SCIP_VAR**            vars,               /**< variable array to output */
287    int                   nvars,              /**< number of variables */
288    SCIP_Bool             type,               /**< should the variable type be also posted */
289    char                  delimiter           /**< character which is used for delimitation */
290    )
291 {
292    int v;
293 
294    SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsList", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
295 
296    for( v = 0; v < nvars; ++v )
297    {
298       if( v > 0 )
299       {
300          SCIPinfoMessage(scip, file, "%c", delimiter);
301       }
302 
303       /* print variable name */
304       SCIP_CALL( SCIPwriteVarName(scip, file, vars[v], type) );
305    }
306 
307    return SCIP_OKAY;
308 }
309 
310 /** print the given variables and coefficients as linear sum in the following form
311  *  c1 \<x1\> + c2 \<x2\>   ... + cn \<xn\>
312  *
313  *  This string can be parsed by the method SCIPparseVarsLinearsum().
314  *
315  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
316  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
317  *
318  *  @pre This method can be called if @p scip is in one of the following stages:
319  *       - \ref SCIP_STAGE_PROBLEM
320  *       - \ref SCIP_STAGE_TRANSFORMING
321  *       - \ref SCIP_STAGE_TRANSFORMED
322  *       - \ref SCIP_STAGE_INITPRESOLVE
323  *       - \ref SCIP_STAGE_PRESOLVING
324  *       - \ref SCIP_STAGE_EXITPRESOLVE
325  *       - \ref SCIP_STAGE_PRESOLVED
326  *       - \ref SCIP_STAGE_INITSOLVE
327  *       - \ref SCIP_STAGE_SOLVING
328  *       - \ref SCIP_STAGE_SOLVED
329  *       - \ref SCIP_STAGE_EXITSOLVE
330  *       - \ref SCIP_STAGE_FREETRANS
331  *
332  *  @note The printing process is done via the message handler system.
333  */
SCIPwriteVarsLinearsum(SCIP * scip,FILE * file,SCIP_VAR ** vars,SCIP_Real * vals,int nvars,SCIP_Bool type)334 SCIP_RETCODE SCIPwriteVarsLinearsum(
335    SCIP*                 scip,               /**< SCIP data structure */
336    FILE*                 file,               /**< output file, or NULL for stdout */
337    SCIP_VAR**            vars,               /**< variable array to output */
338    SCIP_Real*            vals,               /**< array of coefficients or NULL if all coefficients are 1.0 */
339    int                   nvars,              /**< number of variables */
340    SCIP_Bool             type                /**< should the variable type be also posted */
341    )
342 {
343    int v;
344 
345    SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsLinearsum", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
346 
347    for( v = 0; v < nvars; ++v )
348    {
349       if( vals != NULL )
350       {
351          if( vals[v] == 1.0 )
352          {
353             if( v > 0 )
354                SCIPinfoMessage(scip, file, " +");
355          }
356          else if( vals[v] == -1.0 )
357             SCIPinfoMessage(scip, file, " -");
358          else
359             SCIPinfoMessage(scip, file, " %+.15g", vals[v]);
360       }
361       else if( nvars > 0 )
362          SCIPinfoMessage(scip, file, " +");
363 
364       /* print variable name */
365       SCIP_CALL( SCIPwriteVarName(scip, file, vars[v], type) );
366    }
367 
368    return SCIP_OKAY;
369 }
370 
371 /** print the given monomials as polynomial in the following form
372  *  c1 \<x11\>^e11 \<x12\>^e12 ... \<x1n\>^e1n + c2 \<x21\>^e21 \<x22\>^e22 ... + ... + cn \<xn1\>^en1 ...
373  *
374  *  This string can be parsed by the method SCIPparseVarsPolynomial().
375  *
376  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
377  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
378  *
379  *  @pre This method can be called if @p scip is in one of the following stages:
380  *       - \ref SCIP_STAGE_PROBLEM
381  *       - \ref SCIP_STAGE_TRANSFORMING
382  *       - \ref SCIP_STAGE_TRANSFORMED
383  *       - \ref SCIP_STAGE_INITPRESOLVE
384  *       - \ref SCIP_STAGE_PRESOLVING
385  *       - \ref SCIP_STAGE_EXITPRESOLVE
386  *       - \ref SCIP_STAGE_PRESOLVED
387  *       - \ref SCIP_STAGE_INITSOLVE
388  *       - \ref SCIP_STAGE_SOLVING
389  *       - \ref SCIP_STAGE_SOLVED
390  *       - \ref SCIP_STAGE_EXITSOLVE
391  *       - \ref SCIP_STAGE_FREETRANS
392  *
393  *  @note The printing process is done via the message handler system.
394  */
SCIPwriteVarsPolynomial(SCIP * scip,FILE * file,SCIP_VAR *** monomialvars,SCIP_Real ** monomialexps,SCIP_Real * monomialcoefs,int * monomialnvars,int nmonomials,SCIP_Bool type)395 SCIP_RETCODE SCIPwriteVarsPolynomial(
396    SCIP*                 scip,               /**< SCIP data structure */
397    FILE*                 file,               /**< output file, or NULL for stdout */
398    SCIP_VAR***           monomialvars,       /**< arrays with variables for each monomial */
399    SCIP_Real**           monomialexps,       /**< arrays with variable exponents, or NULL if always 1.0 */
400    SCIP_Real*            monomialcoefs,      /**< array with monomial coefficients */
401    int*                  monomialnvars,      /**< array with number of variables for each monomial */
402    int                   nmonomials,         /**< number of monomials */
403    SCIP_Bool             type                /**< should the variable type be also posted */
404    )
405 {
406    int i;
407    int v;
408 
409    assert(scip != NULL);
410    assert(monomialvars  != NULL || nmonomials == 0);
411    assert(monomialcoefs != NULL || nmonomials == 0);
412    assert(monomialnvars != NULL || nmonomials == 0);
413 
414    SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsPolynomial", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
415 
416    if( nmonomials == 0 )
417    {
418       SCIPinfoMessage(scip, file, " 0 ");
419       return SCIP_OKAY;
420    }
421 
422    for( i = 0; i < nmonomials; ++i )
423    {
424       if( monomialcoefs[i] == 1.0 ) /*lint !e613*/
425       {
426          if( i > 0 )
427             SCIPinfoMessage(scip, file, " +");
428       }
429       else if( monomialcoefs[i] == -1.0 ) /*lint !e613*/
430          SCIPinfoMessage(scip, file, " -");
431       else
432          SCIPinfoMessage(scip, file, " %+.15g", monomialcoefs[i]); /*lint !e613*/
433 
434       assert(monomialvars[i] != NULL || monomialnvars[i] == 0); /*lint !e613*/
435 
436       for( v = 0; v < monomialnvars[i]; ++v ) /*lint !e613*/
437       {
438          SCIP_CALL( SCIPwriteVarName(scip, file, monomialvars[i][v], type) ); /*lint !e613*/
439          if( monomialexps != NULL && monomialexps[i] != NULL && monomialexps[i][v] != 1.0 )
440          {
441             SCIPinfoMessage(scip, file, "^%.15g", monomialexps[i][v]);
442          }
443       }
444    }
445 
446    return SCIP_OKAY;
447 }
448 
449 /** parses variable information (in cip format) out of a string; if the parsing process was successful a variable is
450  *  created and captured; if variable is of integral type, fractional bounds are automatically rounded; an integer
451  *  variable with bounds zero and one is automatically converted into a binary variable
452  *
453  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
454  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
455  *
456  *  @pre This method can be called if @p scip is in one of the following stages:
457  *       - \ref SCIP_STAGE_PROBLEM
458  *       - \ref SCIP_STAGE_TRANSFORMING
459  *       - \ref SCIP_STAGE_INITPRESOLVE
460  *       - \ref SCIP_STAGE_PRESOLVING
461  *       - \ref SCIP_STAGE_EXITPRESOLVE
462  *       - \ref SCIP_STAGE_PRESOLVED
463  *       - \ref SCIP_STAGE_SOLVING
464  */
SCIPparseVar(SCIP * scip,SCIP_VAR ** var,const char * str,SCIP_Bool initial,SCIP_Bool removable,SCIP_DECL_VARCOPY ((* varcopy)),SCIP_DECL_VARDELORIG ((* vardelorig)),SCIP_DECL_VARTRANS ((* vartrans)),SCIP_DECL_VARDELTRANS ((* vardeltrans)),SCIP_VARDATA * vardata,char ** endptr,SCIP_Bool * success)465 SCIP_RETCODE SCIPparseVar(
466    SCIP*                 scip,               /**< SCIP data structure */
467    SCIP_VAR**            var,                /**< pointer to store the problem variable */
468    const char*           str,                /**< string to parse */
469    SCIP_Bool             initial,            /**< should var's column be present in the initial root LP? */
470    SCIP_Bool             removable,          /**< is var's column removable from the LP (due to aging or cleanup)? */
471    SCIP_DECL_VARCOPY     ((*varcopy)),       /**< copies variable data if wanted to subscip, or NULL */
472    SCIP_DECL_VARDELORIG  ((*vardelorig)),    /**< frees user data of original variable */
473    SCIP_DECL_VARTRANS    ((*vartrans)),      /**< creates transformed user data by transforming original user data */
474    SCIP_DECL_VARDELTRANS ((*vardeltrans)),   /**< frees user data of transformed variable */
475    SCIP_VARDATA*         vardata,            /**< user data for this specific variable */
476    char**                endptr,             /**< pointer to store the final string position if successful */
477    SCIP_Bool*            success             /**< pointer store if the paring process was successful */
478    )
479 {
480    assert(var != NULL);
481 
482    SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVar", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
483 
484    switch( scip->set->stage )
485    {
486    case SCIP_STAGE_PROBLEM:
487       SCIP_CALL( SCIPvarParseOriginal(var, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat,
488             str, initial, removable, varcopy, vardelorig, vartrans, vardeltrans, vardata, endptr, success) );
489       break;
490 
491    case SCIP_STAGE_TRANSFORMING:
492    case SCIP_STAGE_INITPRESOLVE:
493    case SCIP_STAGE_PRESOLVING:
494    case SCIP_STAGE_EXITPRESOLVE:
495    case SCIP_STAGE_PRESOLVED:
496    case SCIP_STAGE_SOLVING:
497       SCIP_CALL( SCIPvarParseTransformed(var, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat,
498             str, initial, removable, varcopy, vardelorig, vartrans, vardeltrans, vardata, endptr, success) );
499       break;
500 
501    default:
502       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
503       return SCIP_INVALIDCALL;
504    }  /*lint !e788*/
505 
506    return SCIP_OKAY;
507 }
508 
509 /** parses the given string for a variable name and stores the variable in the corresponding pointer if such a variable
510  *  exits and returns the position where the parsing stopped
511  *
512  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
513  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
514  *
515  *  @pre This method can be called if @p scip is in one of the following stages:
516  *       - \ref SCIP_STAGE_PROBLEM
517  *       - \ref SCIP_STAGE_TRANSFORMING
518  *       - \ref SCIP_STAGE_INITPRESOLVE
519  *       - \ref SCIP_STAGE_PRESOLVING
520  *       - \ref SCIP_STAGE_EXITPRESOLVE
521  *       - \ref SCIP_STAGE_PRESOLVED
522  *       - \ref SCIP_STAGE_SOLVING
523  */
SCIPparseVarName(SCIP * scip,const char * str,SCIP_VAR ** var,char ** endptr)524 SCIP_RETCODE SCIPparseVarName(
525    SCIP*                 scip,               /**< SCIP data structure */
526    const char*           str,                /**< string to parse */
527    SCIP_VAR**            var,                /**< pointer to store the problem variable, or NULL if it does not exit */
528    char**                endptr              /**< pointer to store the final string position if successful */
529    )
530 {
531    char varname[SCIP_MAXSTRLEN];
532 
533    assert(str != NULL);
534    assert(var != NULL);
535    assert(endptr != NULL);
536 
537    SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarName", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
538 
539    SCIPstrCopySection(str, '<', '>', varname, SCIP_MAXSTRLEN, endptr);
540    assert(*endptr != NULL);
541 
542    if( *varname == '\0' )
543    {
544       SCIPerrorMessage("invalid variable name string given: could not find '<'\n");
545       return SCIP_INVALIDDATA;
546    }
547 
548    /* check if we have a negated variable */
549    if( *varname == '~' )
550    {
551       SCIPdebugMsg(scip, "parsed negated variable name <%s>\n", &varname[1]);
552 
553       /* search for the variable and ignore '~' */
554       (*var) = SCIPfindVar(scip, &varname[1]);
555 
556       if( *var  != NULL )
557       {
558          SCIP_CALL( SCIPgetNegatedVar(scip, *var, var) );
559       }
560    }
561    else
562    {
563       SCIPdebugMsg(scip, "parsed variable name <%s>\n", varname);
564 
565       /* search for the variable */
566       (*var) = SCIPfindVar(scip, varname);
567    }
568 
569    str = *endptr;
570 
571    /* skip additional variable type marker */
572    if( *str == '[' && (str[1] == SCIP_VARTYPE_BINARY_CHAR || str[1] == SCIP_VARTYPE_INTEGER_CHAR ||
573        str[1] == SCIP_VARTYPE_IMPLINT_CHAR || str[1] == SCIP_VARTYPE_CONTINUOUS_CHAR )  && str[2] == ']' )
574       (*endptr) += 3;
575 
576    return SCIP_OKAY;
577 }
578 
579 /** parse the given string as variable list (here ',' is the delimiter)) (\<x1\>, \<x2\>, ..., \<xn\>) (see
580  *  SCIPwriteVarsList() ); if it was successful, the pointer success is set to TRUE
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_INITPRESOLVE
589  *       - \ref SCIP_STAGE_PRESOLVING
590  *       - \ref SCIP_STAGE_EXITPRESOLVE
591  *       - \ref SCIP_STAGE_PRESOLVED
592  *       - \ref SCIP_STAGE_SOLVING
593  *
594  *  @note The pointer success in only set to FALSE in the case that a variable with a parsed variable name does not exist.
595  *
596  *  @note If the number of (parsed) variables is greater than the available slots in the variable array, nothing happens
597  *        except that the required size is stored in the corresponding integer; the reason for this approach is that we
598  *        cannot reallocate memory, since we do not know how the memory has been allocated (e.g., by a C++ 'new' or SCIP
599  *        memory functions).
600  */
SCIPparseVarsList(SCIP * scip,const char * str,SCIP_VAR ** vars,int * nvars,int varssize,int * requiredsize,char ** endptr,char delimiter,SCIP_Bool * success)601 SCIP_RETCODE SCIPparseVarsList(
602    SCIP*                 scip,               /**< SCIP data structure */
603    const char*           str,                /**< string to parse */
604    SCIP_VAR**            vars,               /**< array to store the parsed variable */
605    int*                  nvars,              /**< pointer to store number of parsed variables */
606    int                   varssize,           /**< size of the variable array */
607    int*                  requiredsize,       /**< pointer to store the required array size for the active variables */
608    char**                endptr,             /**< pointer to store the final string position if successful */
609    char                  delimiter,          /**< character which is used for delimitation */
610    SCIP_Bool*            success             /**< pointer to store the whether the parsing was successful or not */
611    )
612 {
613    SCIP_VAR** tmpvars;
614    SCIP_VAR* var;
615    int ntmpvars = 0;
616    int v;
617 
618    assert( nvars != NULL );
619    assert( requiredsize != NULL );
620    assert( endptr != NULL );
621    assert( success != NULL );
622 
623    SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsList", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
624 
625    /* allocate buffer memory for temporary storing the parsed variables */
626    SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, varssize) );
627 
628    (*success) = TRUE;
629 
630    do
631    {
632       *endptr = (char*)str;
633 
634       /* parse variable name */
635       SCIP_CALL( SCIPparseVarName(scip, str, &var, endptr) );
636 
637       if( var == NULL )
638       {
639          SCIPdebugMsg(scip, "variable with name <%s> does not exist\n", SCIPvarGetName(var));
640          (*success) = FALSE;
641          break;
642       }
643 
644       /* store the variable in the tmp array */
645       if( ntmpvars < varssize )
646          tmpvars[ntmpvars] = var;
647 
648       ntmpvars++;
649 
650       str = *endptr;
651 
652       while( isspace((unsigned char)*str) )
653          str++;
654    }
655    while( *str == delimiter );
656 
657    *endptr = (char*)str;
658 
659    /* if all variable name searches were successful and the variable array has enough slots, copy the collected variables */
660    if( (*success) && ntmpvars <= varssize )
661    {
662       for( v = 0; v < ntmpvars; ++v )
663          vars[v] = tmpvars[v];
664 
665       (*nvars) = ntmpvars;
666    }
667    else
668       (*nvars) = 0;
669 
670    (*requiredsize) = ntmpvars;
671 
672    /* free buffer arrays */
673    SCIPfreeBufferArray(scip, &tmpvars);
674 
675    return SCIP_OKAY;
676 }
677 
678 /** parse the given string as linear sum of variables and coefficients (c1 \<x1\> + c2 \<x2\> + ... + cn \<xn\>)
679  *  (see SCIPwriteVarsLinearsum() ); if it was successful, the pointer success is set to TRUE
680  *
681  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
682  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
683  *
684  *  @pre This method can be called if @p scip is in one of the following stages:
685  *       - \ref SCIP_STAGE_PROBLEM
686  *       - \ref SCIP_STAGE_TRANSFORMING
687  *       - \ref SCIP_STAGE_INITPRESOLVE
688  *       - \ref SCIP_STAGE_PRESOLVING
689  *       - \ref SCIP_STAGE_EXITPRESOLVE
690  *       - \ref SCIP_STAGE_PRESOLVED
691  *       - \ref SCIP_STAGE_SOLVING
692  *
693  *  @note The pointer success in only set to FALSE in the case that a variable with a parsed variable name does not exist.
694  *
695  *  @note If the number of (parsed) variables is greater than the available slots in the variable array, nothing happens
696  *        except that the required size is stored in the corresponding integer; the reason for this approach is that we
697  *        cannot reallocate memory, since we do not know how the memory has been allocated (e.g., by a C++ 'new' or SCIP
698  *        memory functions).
699  */
SCIPparseVarsLinearsum(SCIP * scip,const char * str,SCIP_VAR ** vars,SCIP_Real * vals,int * nvars,int varssize,int * requiredsize,char ** endptr,SCIP_Bool * success)700 SCIP_RETCODE SCIPparseVarsLinearsum(
701    SCIP*                 scip,               /**< SCIP data structure */
702    const char*           str,                /**< string to parse */
703    SCIP_VAR**            vars,               /**< array to store the parsed variables */
704    SCIP_Real*            vals,               /**< array to store the parsed coefficients */
705    int*                  nvars,              /**< pointer to store number of parsed variables */
706    int                   varssize,           /**< size of the variable array */
707    int*                  requiredsize,       /**< pointer to store the required array size for the active variables */
708    char**                endptr,             /**< pointer to store the final string position if successful */
709    SCIP_Bool*            success             /**< pointer to store the whether the parsing was successful or not */
710    )
711 {
712    SCIP_VAR*** monomialvars;
713    SCIP_Real** monomialexps;
714    SCIP_Real*  monomialcoefs;
715    int*        monomialnvars;
716    int         nmonomials;
717 
718    SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsLinearsum", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
719 
720    assert(scip != NULL);
721    assert(str != NULL);
722    assert(vars != NULL || varssize == 0);
723    assert(vals != NULL || varssize == 0);
724    assert(nvars != NULL);
725    assert(requiredsize != NULL);
726    assert(endptr != NULL);
727    assert(success != NULL);
728 
729    *requiredsize = 0;
730 
731    SCIP_CALL( SCIPparseVarsPolynomial(scip, str, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, &nmonomials, endptr, success) );
732 
733    if( !*success )
734    {
735       assert(nmonomials == 0); /* SCIPparseVarsPolynomial should have freed all buffers, so no need to call free here */
736       return SCIP_OKAY;
737    }
738 
739    /* check if linear sum is just "0" */
740    if( nmonomials == 1 && monomialnvars[0] == 0 && monomialcoefs[0] == 0.0 )
741    {
742       *nvars = 0;
743       *requiredsize = 0;
744 
745       SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials);
746 
747       return SCIP_OKAY;
748    }
749 
750    *nvars = nmonomials;
751    *requiredsize = nmonomials;
752 
753    /* if we have enough slots in the variables array, copy variables over */
754    if( varssize >= nmonomials )
755    {
756       int v;
757 
758       for( v = 0; v < nmonomials; ++v )
759       {
760          if( monomialnvars[v] == 0 )
761          {
762             SCIPerrorMessage("constant in linear sum\n");
763             *success = FALSE;
764             break;
765          }
766          if( monomialnvars[v] > 1 || monomialexps[v][0] != 1.0 )
767          {
768             SCIPerrorMessage("nonlinear monomial in linear sum\n");
769             *success = FALSE;
770             break;
771          }
772          assert(monomialnvars[v]   == 1);
773          assert(monomialvars[v][0] != NULL);
774          assert(monomialexps[v][0] == 1.0);
775 
776          vars[v] = monomialvars[v][0]; /*lint !e613*/
777          vals[v] = monomialcoefs[v]; /*lint !e613*/
778       }
779    }
780 
781    SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials);
782 
783    return SCIP_OKAY;
784 }
785 
786 /** parse the given string as polynomial of variables and coefficients
787  *  (c1 \<x11\>^e11 \<x12\>^e12 ... \<x1n\>^e1n + c2 \<x21\>^e21 \<x22\>^e22 ... + ... + cn \<xn1\>^en1 ...)
788  *  (see SCIPwriteVarsPolynomial()); if it was successful, the pointer success is set to TRUE
789  *
790  *  The user has to call SCIPfreeParseVarsPolynomialData(scip, monomialvars, monomialexps,
791  *  monomialcoefs, monomialnvars, *nmonomials) short after SCIPparseVarsPolynomial to free all the
792  *  allocated memory again.  Do not keep the arrays created by SCIPparseVarsPolynomial around, since
793  *  they use buffer memory that is intended for short term use only.
794  *
795  *  Parsing is stopped at the end of string (indicated by the \\0-character) or when no more monomials
796  *  are recognized.
797  *
798  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
799  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
800  *
801  *  @pre This method can be called if @p scip is in one of the following stages:
802  *       - \ref SCIP_STAGE_PROBLEM
803  *       - \ref SCIP_STAGE_TRANSFORMING
804  *       - \ref SCIP_STAGE_INITPRESOLVE
805  *       - \ref SCIP_STAGE_PRESOLVING
806  *       - \ref SCIP_STAGE_EXITPRESOLVE
807  *       - \ref SCIP_STAGE_PRESOLVED
808  *       - \ref SCIP_STAGE_SOLVING
809  */
SCIPparseVarsPolynomial(SCIP * scip,const char * str,SCIP_VAR **** monomialvars,SCIP_Real *** monomialexps,SCIP_Real ** monomialcoefs,int ** monomialnvars,int * nmonomials,char ** endptr,SCIP_Bool * success)810 SCIP_RETCODE SCIPparseVarsPolynomial(
811    SCIP*                 scip,               /**< SCIP data structure */
812    const char*           str,                /**< string to parse */
813    SCIP_VAR****          monomialvars,       /**< pointer to store arrays with variables for each monomial */
814    SCIP_Real***          monomialexps,       /**< pointer to store arrays with variable exponents */
815    SCIP_Real**           monomialcoefs,      /**< pointer to store array with monomial coefficients */
816    int**                 monomialnvars,      /**< pointer to store array with number of variables for each monomial */
817    int*                  nmonomials,         /**< pointer to store number of parsed monomials */
818    char**                endptr,             /**< pointer to store the final string position if successful */
819    SCIP_Bool*            success             /**< pointer to store the whether the parsing was successful or not */
820    )
821 {
822    typedef enum
823    {
824       SCIPPARSEPOLYNOMIAL_STATE_BEGIN,       /* we are at the beginning of a monomial */
825       SCIPPARSEPOLYNOMIAL_STATE_INTERMED,    /* we are in between the factors of a monomial */
826       SCIPPARSEPOLYNOMIAL_STATE_COEF,        /* we parse the coefficient of a monomial */
827       SCIPPARSEPOLYNOMIAL_STATE_VARS,        /* we parse monomial variables */
828       SCIPPARSEPOLYNOMIAL_STATE_EXPONENT,    /* we parse the exponent of a variable */
829       SCIPPARSEPOLYNOMIAL_STATE_END,         /* we are at the end the polynomial */
830       SCIPPARSEPOLYNOMIAL_STATE_ERROR        /* a parsing error occured */
831    } SCIPPARSEPOLYNOMIAL_STATES;
832 
833    SCIPPARSEPOLYNOMIAL_STATES state;
834    int monomialssize;
835 
836    /* data of currently parsed monomial */
837    int varssize;
838    int nvars;
839    SCIP_VAR** vars;
840    SCIP_Real* exponents;
841    SCIP_Real coef;
842 
843    assert(scip != NULL);
844    assert(str != NULL);
845    assert(monomialvars != NULL);
846    assert(monomialexps != NULL);
847    assert(monomialnvars != NULL);
848    assert(monomialcoefs != NULL);
849    assert(nmonomials != NULL);
850    assert(endptr != NULL);
851    assert(success != NULL);
852 
853    SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsPolynomial", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
854 
855    *success = FALSE;
856    *nmonomials = 0;
857    monomialssize = 0;
858    *monomialvars = NULL;
859    *monomialexps = NULL;
860    *monomialcoefs = NULL;
861    *monomialnvars = NULL;
862 
863    /* initialize state machine */
864    state = SCIPPARSEPOLYNOMIAL_STATE_BEGIN;
865    varssize = 0;
866    nvars = 0;
867    vars = NULL;
868    exponents = NULL;
869    coef = SCIP_INVALID;
870 
871    SCIPdebugMsg(scip, "parsing polynomial from '%s'\n", str);
872 
873    while( *str && state != SCIPPARSEPOLYNOMIAL_STATE_END && state != SCIPPARSEPOLYNOMIAL_STATE_ERROR )
874    {
875       /* skip white space */
876       while( isspace((unsigned char)*str) )
877          str++;
878 
879       assert(state != SCIPPARSEPOLYNOMIAL_STATE_END);
880 
881       switch( state )
882       {
883       case SCIPPARSEPOLYNOMIAL_STATE_BEGIN:
884       {
885          if( coef != SCIP_INVALID  ) /*lint !e777*/
886          {
887             SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars);
888             /* push previous monomial */
889             if( monomialssize <= *nmonomials )
890             {
891                monomialssize = SCIPcalcMemGrowSize(scip, *nmonomials+1);
892 
893                SCIP_CALL( SCIPreallocBufferArray(scip, monomialvars,  monomialssize) );
894                SCIP_CALL( SCIPreallocBufferArray(scip, monomialexps,  monomialssize) );
895                SCIP_CALL( SCIPreallocBufferArray(scip, monomialnvars, monomialssize) );
896                SCIP_CALL( SCIPreallocBufferArray(scip, monomialcoefs, monomialssize) );
897             }
898 
899             if( nvars > 0 )
900             {
901                SCIP_CALL( SCIPduplicateBufferArray(scip, &(*monomialvars)[*nmonomials], vars, nvars) ); /*lint !e866*/
902                SCIP_CALL( SCIPduplicateBufferArray(scip, &(*monomialexps)[*nmonomials], exponents, nvars) ); /*lint !e866*/
903             }
904             else
905             {
906                (*monomialvars)[*nmonomials] = NULL;
907                (*monomialexps)[*nmonomials] = NULL;
908             }
909             (*monomialcoefs)[*nmonomials] = coef;
910             (*monomialnvars)[*nmonomials] = nvars;
911             ++*nmonomials;
912 
913             nvars = 0;
914             coef = SCIP_INVALID;
915          }
916 
917          if( *str == '<' )
918          {
919             /* there seem to come a variable at the beginning of a monomial
920              * so assume the coefficient is 1.0
921              */
922             state = SCIPPARSEPOLYNOMIAL_STATE_VARS;
923             coef = 1.0;
924          }
925          else if( *str == '-' || *str == '+' || isdigit(*str) )
926             state = SCIPPARSEPOLYNOMIAL_STATE_COEF;
927          else
928             state = SCIPPARSEPOLYNOMIAL_STATE_END;
929 
930          break;
931       }
932 
933       case SCIPPARSEPOLYNOMIAL_STATE_INTERMED:
934       {
935          if( *str == '<' )
936          {
937             /* there seem to come another variable */
938             state = SCIPPARSEPOLYNOMIAL_STATE_VARS;
939          }
940          else if( *str == '-' || *str == '+' || isdigit(*str) )
941          {
942             /* there seem to come a coefficient, which means the next monomial */
943             state = SCIPPARSEPOLYNOMIAL_STATE_BEGIN;
944          }
945          else /* since we cannot detect the symbols we stop parsing the polynomial */
946             state = SCIPPARSEPOLYNOMIAL_STATE_END;
947 
948          break;
949       }
950 
951       case SCIPPARSEPOLYNOMIAL_STATE_COEF:
952       {
953          if( *str == '+' && !isdigit(str[1]) )
954          {
955             /* only a plus sign, without number */
956             coef =  1.0;
957             ++str;
958          }
959          else if( *str == '-' && !isdigit(str[1]) )
960          {
961             /* only a minus sign, without number */
962             coef = -1.0;
963             ++str;
964          }
965          else if( SCIPstrToRealValue(str, &coef, endptr) )
966          {
967             str = *endptr;
968          }
969          else
970          {
971             SCIPerrorMessage("could not parse number in the beginning of '%s'\n", str);
972             state = SCIPPARSEPOLYNOMIAL_STATE_ERROR;
973             break;
974          }
975 
976          /* after the coefficient we go into the intermediate state, i.e., expecting next variables */
977          state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED;  /*lint !e838*/
978 
979          break;
980       }
981 
982       case SCIPPARSEPOLYNOMIAL_STATE_VARS:
983       {
984          SCIP_VAR* var;
985 
986          assert(*str == '<');
987 
988          /* parse variable name */
989          SCIP_CALL( SCIPparseVarName(scip, str, &var, endptr) );
990 
991          /* check if variable name was parsed */
992          if( *endptr == str )
993          {
994             state = SCIPPARSEPOLYNOMIAL_STATE_END;
995             break;
996          }
997 
998          if( var == NULL )
999          {
1000             SCIPerrorMessage("did not find variable in the beginning of %s\n", str);
1001             state = SCIPPARSEPOLYNOMIAL_STATE_ERROR;
1002             break;
1003          }
1004 
1005          /* add variable to vars array */
1006          if( nvars + 1 > varssize )
1007          {
1008             varssize = SCIPcalcMemGrowSize(scip, nvars+1);
1009             SCIP_CALL( SCIPreallocBufferArray(scip, &vars,      varssize) );
1010             SCIP_CALL( SCIPreallocBufferArray(scip, &exponents, varssize) );
1011          }
1012          assert(vars != NULL);
1013          assert(exponents != NULL);
1014 
1015          vars[nvars] = var;
1016          exponents[nvars] = 1.0;
1017          ++nvars;
1018 
1019          str = *endptr;
1020 
1021          if( *str == '^' )
1022             state = SCIPPARSEPOLYNOMIAL_STATE_EXPONENT;
1023          else
1024             state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED;
1025 
1026          break;
1027       }
1028 
1029       case SCIPPARSEPOLYNOMIAL_STATE_EXPONENT:
1030       {
1031          assert(*str == '^');
1032          assert(nvars > 0); /* we should be in a monomial that has already a variable */
1033          assert(exponents != NULL);
1034          ++str;
1035 
1036          if( !SCIPstrToRealValue(str, &exponents[nvars-1], endptr) )
1037          {
1038             SCIPerrorMessage("could not parse number in the beginning of '%s'\n", str);
1039             state = SCIPPARSEPOLYNOMIAL_STATE_ERROR;
1040             break;
1041          }
1042          str = *endptr;
1043 
1044          /* after the exponent we go into the intermediate state, i.e., expecting next variables */
1045          state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED;  /*lint !e838*/
1046          break;
1047       }
1048 
1049       case SCIPPARSEPOLYNOMIAL_STATE_END:
1050       case SCIPPARSEPOLYNOMIAL_STATE_ERROR:
1051       default:
1052          SCIPerrorMessage("unexpected state\n");
1053          return SCIP_READERROR;
1054       }
1055    }
1056 
1057    /* set end pointer */
1058    *endptr = (char*)str;
1059 
1060    /* check state at end of string */
1061    switch( state )
1062    {
1063    case SCIPPARSEPOLYNOMIAL_STATE_BEGIN:
1064    case SCIPPARSEPOLYNOMIAL_STATE_END:
1065    case SCIPPARSEPOLYNOMIAL_STATE_INTERMED:
1066    {
1067       if( coef != SCIP_INVALID ) /*lint !e777*/
1068       {
1069          /* push last monomial */
1070          SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars);
1071          if( monomialssize <= *nmonomials )
1072          {
1073             monomialssize = *nmonomials+1;
1074             SCIP_CALL( SCIPreallocBufferArray(scip, monomialvars,  monomialssize) );
1075             SCIP_CALL( SCIPreallocBufferArray(scip, monomialexps,  monomialssize) );
1076             SCIP_CALL( SCIPreallocBufferArray(scip, monomialnvars, monomialssize) );
1077             SCIP_CALL( SCIPreallocBufferArray(scip, monomialcoefs, monomialssize) );
1078          }
1079 
1080          if( nvars > 0 )
1081          {
1082             /* shrink vars and exponents array to needed size and take over ownership */
1083             SCIP_CALL( SCIPreallocBufferArray(scip, &vars,      nvars) );
1084             SCIP_CALL( SCIPreallocBufferArray(scip, &exponents, nvars) );
1085             (*monomialvars)[*nmonomials] = vars;
1086             (*monomialexps)[*nmonomials] = exponents;
1087             vars = NULL;
1088             exponents = NULL;
1089          }
1090          else
1091          {
1092             (*monomialvars)[*nmonomials] = NULL;
1093             (*monomialexps)[*nmonomials] = NULL;
1094          }
1095          (*monomialcoefs)[*nmonomials] = coef;
1096          (*monomialnvars)[*nmonomials] = nvars;
1097          ++*nmonomials;
1098       }
1099 
1100       *success = TRUE;
1101       break;
1102    }
1103 
1104    case SCIPPARSEPOLYNOMIAL_STATE_COEF:
1105    case SCIPPARSEPOLYNOMIAL_STATE_VARS:
1106    case SCIPPARSEPOLYNOMIAL_STATE_EXPONENT:
1107    {
1108       SCIPerrorMessage("unexpected parsing state at end of polynomial string\n");
1109    }
1110    /*lint -fallthrough*/
1111    case SCIPPARSEPOLYNOMIAL_STATE_ERROR:
1112       assert(!*success);
1113       break;
1114    }
1115 
1116    /* free memory to store current monomial, if still existing */
1117    SCIPfreeBufferArrayNull(scip, &vars);
1118    SCIPfreeBufferArrayNull(scip, &exponents);
1119 
1120    if( *success && *nmonomials > 0 )
1121    {
1122       /* shrink arrays to required size, so we do not need to keep monomialssize around */
1123       assert(*nmonomials <= monomialssize);
1124       SCIP_CALL( SCIPreallocBufferArray(scip, monomialvars,  *nmonomials) );
1125       SCIP_CALL( SCIPreallocBufferArray(scip, monomialexps,  *nmonomials) );
1126       SCIP_CALL( SCIPreallocBufferArray(scip, monomialnvars, *nmonomials) );
1127       SCIP_CALL( SCIPreallocBufferArray(scip, monomialcoefs, *nmonomials) );
1128 
1129       /* SCIPwriteVarsPolynomial(scip, NULL, *monomialvars, *monomialexps, *monomialcoefs, *monomialnvars, *nmonomials, FALSE); */
1130    }
1131    else
1132    {
1133       /* in case of error, cleanup all data here */
1134       SCIPfreeParseVarsPolynomialData(scip, monomialvars, monomialexps, monomialcoefs, monomialnvars, *nmonomials);
1135       *nmonomials = 0;
1136    }
1137 
1138    return SCIP_OKAY;
1139 }
1140 
1141 /** frees memory allocated when parsing a polynomial from a string
1142  *
1143  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1144  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1145  *
1146  *  @pre This method can be called if @p scip is in one of the following stages:
1147  *       - \ref SCIP_STAGE_PROBLEM
1148  *       - \ref SCIP_STAGE_TRANSFORMING
1149  *       - \ref SCIP_STAGE_INITPRESOLVE
1150  *       - \ref SCIP_STAGE_PRESOLVING
1151  *       - \ref SCIP_STAGE_EXITPRESOLVE
1152  *       - \ref SCIP_STAGE_PRESOLVED
1153  *       - \ref SCIP_STAGE_SOLVING
1154  */
SCIPfreeParseVarsPolynomialData(SCIP * scip,SCIP_VAR **** monomialvars,SCIP_Real *** monomialexps,SCIP_Real ** monomialcoefs,int ** monomialnvars,int nmonomials)1155 void SCIPfreeParseVarsPolynomialData(
1156    SCIP*                 scip,               /**< SCIP data structure */
1157    SCIP_VAR****          monomialvars,       /**< pointer to store arrays with variables for each monomial */
1158    SCIP_Real***          monomialexps,       /**< pointer to store arrays with variable exponents */
1159    SCIP_Real**           monomialcoefs,      /**< pointer to store array with monomial coefficients */
1160    int**                 monomialnvars,      /**< pointer to store array with number of variables for each monomial */
1161    int                   nmonomials          /**< pointer to store number of parsed monomials */
1162    )
1163 {
1164    int i;
1165 
1166    assert(scip != NULL);
1167    assert(monomialvars  != NULL);
1168    assert(monomialexps  != NULL);
1169    assert(monomialcoefs != NULL);
1170    assert(monomialnvars != NULL);
1171    assert((*monomialvars  != NULL) == (nmonomials > 0));
1172    assert((*monomialexps  != NULL) == (nmonomials > 0));
1173    assert((*monomialcoefs != NULL) == (nmonomials > 0));
1174    assert((*monomialnvars != NULL) == (nmonomials > 0));
1175 
1176    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfreeParseVarsPolynomialData", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1177 
1178    if( nmonomials == 0 )
1179       return;
1180 
1181    for( i = nmonomials - 1; i >= 0; --i )
1182    {
1183       SCIPfreeBufferArrayNull(scip, &(*monomialexps)[i]);
1184       SCIPfreeBufferArrayNull(scip, &(*monomialvars)[i]);
1185    }
1186 
1187    SCIPfreeBufferArray(scip, monomialcoefs);
1188    SCIPfreeBufferArray(scip, monomialnvars);
1189    SCIPfreeBufferArray(scip, monomialexps);
1190    SCIPfreeBufferArray(scip, monomialvars);
1191 }
1192 
1193 /** increases usage counter of variable
1194  *
1195  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1196  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1197  *
1198  *  @pre This method can be called if @p scip is in one of the following stages:
1199  *       - \ref SCIP_STAGE_PROBLEM
1200  *       - \ref SCIP_STAGE_TRANSFORMING
1201  *       - \ref SCIP_STAGE_TRANSFORMED
1202  *       - \ref SCIP_STAGE_INITPRESOLVE
1203  *       - \ref SCIP_STAGE_PRESOLVING
1204  *       - \ref SCIP_STAGE_EXITPRESOLVE
1205  *       - \ref SCIP_STAGE_PRESOLVED
1206  *       - \ref SCIP_STAGE_INITSOLVE
1207  *       - \ref SCIP_STAGE_SOLVING
1208  *       - \ref SCIP_STAGE_SOLVED
1209  *       - \ref SCIP_STAGE_EXITSOLVE
1210  */
SCIPcaptureVar(SCIP * scip,SCIP_VAR * var)1211 SCIP_RETCODE SCIPcaptureVar(
1212    SCIP*                 scip,               /**< SCIP data structure */
1213    SCIP_VAR*             var                 /**< variable to capture */
1214    )
1215 {
1216    SCIP_CALL( SCIPcheckStage(scip, "SCIPcaptureVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1217    assert(var->scip == scip);
1218 
1219    SCIPvarCapture(var);
1220 
1221    return SCIP_OKAY;
1222 }
1223 
1224 /** decreases usage counter of variable, if the usage pointer reaches zero the variable gets freed
1225  *
1226  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1227  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1228  *
1229  *  @pre This method can be called if @p scip is in one of the following stages:
1230  *       - \ref SCIP_STAGE_PROBLEM
1231  *       - \ref SCIP_STAGE_TRANSFORMING
1232  *       - \ref SCIP_STAGE_TRANSFORMED
1233  *       - \ref SCIP_STAGE_INITPRESOLVE
1234  *       - \ref SCIP_STAGE_PRESOLVING
1235  *       - \ref SCIP_STAGE_EXITPRESOLVE
1236  *       - \ref SCIP_STAGE_PRESOLVED
1237  *       - \ref SCIP_STAGE_INITSOLVE
1238  *       - \ref SCIP_STAGE_SOLVING
1239  *       - \ref SCIP_STAGE_SOLVED
1240  *       - \ref SCIP_STAGE_EXITSOLVE
1241  *       - \ref SCIP_STAGE_FREETRANS
1242  *
1243  *  @note the pointer of the variable will be NULLed
1244  */
SCIPreleaseVar(SCIP * scip,SCIP_VAR ** var)1245 SCIP_RETCODE SCIPreleaseVar(
1246    SCIP*                 scip,               /**< SCIP data structure */
1247    SCIP_VAR**            var                 /**< pointer to variable */
1248    )
1249 {
1250    assert(var != NULL);
1251    assert(*var != NULL);
1252    assert((*var)->scip == scip);
1253 
1254    SCIP_CALL( SCIPcheckStage(scip, "SCIPreleaseVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1255 
1256    switch( scip->set->stage )
1257    {
1258    case SCIP_STAGE_PROBLEM:
1259       SCIP_CALL( SCIPvarRelease(var, scip->mem->probmem, scip->set, scip->eventqueue, scip->lp) );
1260       return SCIP_OKAY;
1261 
1262    case SCIP_STAGE_TRANSFORMING:
1263    case SCIP_STAGE_TRANSFORMED:
1264    case SCIP_STAGE_INITPRESOLVE:
1265    case SCIP_STAGE_PRESOLVING:
1266    case SCIP_STAGE_EXITPRESOLVE:
1267    case SCIP_STAGE_PRESOLVED:
1268    case SCIP_STAGE_INITSOLVE:
1269    case SCIP_STAGE_SOLVING:
1270    case SCIP_STAGE_SOLVED:
1271    case SCIP_STAGE_EXITSOLVE:
1272    case SCIP_STAGE_FREETRANS:
1273       if( !SCIPvarIsTransformed(*var) && (*var)->nuses == 1 )
1274       {
1275          SCIPerrorMessage("cannot release last use of original variable while the transformed problem exists\n");
1276          return SCIP_INVALIDCALL;
1277       }
1278       SCIP_CALL( SCIPvarRelease(var, scip->mem->probmem, scip->set, scip->eventqueue, scip->lp) );
1279       return SCIP_OKAY;
1280 
1281    default:
1282       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
1283       return SCIP_INVALIDCALL;
1284    }  /*lint !e788*/
1285 }
1286 
1287 /** changes the name of a variable
1288  *
1289  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1290  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1291  *
1292  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PROBLEM
1293  *
1294  *  @note to get the current name of a variable, use SCIPvarGetName() from pub_var.h
1295  */
SCIPchgVarName(SCIP * scip,SCIP_VAR * var,const char * name)1296 SCIP_RETCODE SCIPchgVarName(
1297    SCIP*                 scip,               /**< SCIP data structure */
1298    SCIP_VAR*             var,                /**< variable */
1299    const char*           name                /**< new name of constraint */
1300    )
1301 {
1302    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarName", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1303    assert( var->scip == scip );
1304 
1305    if( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM )
1306    {
1307       SCIPerrorMessage("variable names can only be changed in problem creation stage\n");
1308       SCIPABORT();
1309       return SCIP_INVALIDCALL; /*lint !e527*/
1310    }
1311 
1312    /* remove variable's name from the namespace if the variable was already added */
1313    if( SCIPvarGetProbindex(var) != -1 )
1314    {
1315       SCIP_CALL( SCIPprobRemoveVarName(scip->origprob, var) );
1316    }
1317 
1318    /* change variable name */
1319    SCIP_CALL( SCIPvarChgName(var, SCIPblkmem(scip), name) );
1320 
1321    /* add variable's name to the namespace if the variable was already added */
1322    if( SCIPvarGetProbindex(var) != -1 )
1323    {
1324       SCIP_CALL( SCIPprobAddVarName(scip->origprob, var) );
1325    }
1326 
1327    return SCIP_OKAY;
1328 }
1329 
1330 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
1331  *  a new transformed variable for this variable is created
1332  *
1333  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1334  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1335  *
1336  *  @pre This method can be called if @p scip is in one of the following stages:
1337  *       - \ref SCIP_STAGE_TRANSFORMING
1338  *       - \ref SCIP_STAGE_TRANSFORMED
1339  *       - \ref SCIP_STAGE_INITPRESOLVE
1340  *       - \ref SCIP_STAGE_PRESOLVING
1341  *       - \ref SCIP_STAGE_EXITPRESOLVE
1342  *       - \ref SCIP_STAGE_PRESOLVED
1343  *       - \ref SCIP_STAGE_INITSOLVE
1344  *       - \ref SCIP_STAGE_SOLVING
1345  */
SCIPtransformVar(SCIP * scip,SCIP_VAR * var,SCIP_VAR ** transvar)1346 SCIP_RETCODE SCIPtransformVar(
1347    SCIP*                 scip,               /**< SCIP data structure */
1348    SCIP_VAR*             var,                /**< variable to get/create transformed variable for */
1349    SCIP_VAR**            transvar            /**< pointer to store the transformed variable */
1350    )
1351 {
1352    assert(transvar != NULL);
1353 
1354    SCIP_CALL( SCIPcheckStage(scip, "SCIPtransformVar", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1355 
1356    if( SCIPvarIsTransformed(var) )
1357    {
1358       *transvar = var;
1359       SCIPvarCapture(*transvar);
1360    }
1361    else
1362    {
1363       SCIP_CALL( SCIPvarTransform(var, scip->mem->probmem, scip->set, scip->stat, scip->origprob->objsense, transvar) );
1364    }
1365 
1366    return SCIP_OKAY;
1367 }
1368 
1369 /** gets and captures transformed variables for an array of variables;
1370  *  if a variable of the array is not yet transformed, a new transformed variable for this variable is created;
1371  *  it is possible to call this method with vars == transvars
1372  *
1373  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1374  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1375  *
1376  *  @pre This method can be called if @p scip is in one of the following stages:
1377  *       - \ref SCIP_STAGE_TRANSFORMING
1378  *       - \ref SCIP_STAGE_TRANSFORMED
1379  *       - \ref SCIP_STAGE_INITPRESOLVE
1380  *       - \ref SCIP_STAGE_PRESOLVING
1381  *       - \ref SCIP_STAGE_EXITPRESOLVE
1382  *       - \ref SCIP_STAGE_PRESOLVED
1383  *       - \ref SCIP_STAGE_INITSOLVE
1384  *       - \ref SCIP_STAGE_SOLVING
1385  */
SCIPtransformVars(SCIP * scip,int nvars,SCIP_VAR ** vars,SCIP_VAR ** transvars)1386 SCIP_RETCODE SCIPtransformVars(
1387    SCIP*                 scip,               /**< SCIP data structure */
1388    int                   nvars,              /**< number of variables to get/create transformed variables for */
1389    SCIP_VAR**            vars,               /**< array with variables to get/create transformed variables for */
1390    SCIP_VAR**            transvars           /**< array to store the transformed variables */
1391    )
1392 {
1393    int v;
1394 
1395    assert(nvars == 0 || vars != NULL);
1396    assert(nvars == 0 || transvars != NULL);
1397 
1398    SCIP_CALL( SCIPcheckStage(scip, "SCIPtransformVars", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1399 
1400    for( v = 0; v < nvars; ++v )
1401    {
1402       if( SCIPvarIsTransformed(vars[v]) )
1403       {
1404          transvars[v] = vars[v];
1405          SCIPvarCapture(transvars[v]);
1406       }
1407       else
1408       {
1409          SCIP_CALL( SCIPvarTransform(vars[v], scip->mem->probmem, scip->set, scip->stat, scip->origprob->objsense,
1410                &transvars[v]) );
1411       }
1412    }
1413 
1414    return SCIP_OKAY;
1415 }
1416 
1417 /** gets corresponding transformed variable of a given variable;
1418  *  returns NULL as transvar, if transformed variable is not yet existing
1419  *
1420  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1421  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1422  *
1423  *  @pre This method can be called if @p scip is in one of the following stages:
1424  *       - \ref SCIP_STAGE_TRANSFORMING
1425  *       - \ref SCIP_STAGE_TRANSFORMED
1426  *       - \ref SCIP_STAGE_INITPRESOLVE
1427  *       - \ref SCIP_STAGE_PRESOLVING
1428  *       - \ref SCIP_STAGE_EXITPRESOLVE
1429  *       - \ref SCIP_STAGE_PRESOLVED
1430  *       - \ref SCIP_STAGE_INITSOLVE
1431  *       - \ref SCIP_STAGE_SOLVING
1432  *       - \ref SCIP_STAGE_SOLVED
1433  *       - \ref SCIP_STAGE_EXITSOLVE
1434  *       - \ref SCIP_STAGE_FREETRANS
1435  */
SCIPgetTransformedVar(SCIP * scip,SCIP_VAR * var,SCIP_VAR ** transvar)1436 SCIP_RETCODE SCIPgetTransformedVar(
1437    SCIP*                 scip,               /**< SCIP data structure */
1438    SCIP_VAR*             var,                /**< variable to get transformed variable for */
1439    SCIP_VAR**            transvar            /**< pointer to store the transformed variable */
1440    )
1441 {
1442    assert(transvar != NULL);
1443 
1444    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetTransformedVar", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1445 
1446    if( SCIPvarIsTransformed(var) )
1447       *transvar = var;
1448    else
1449    {
1450       SCIP_CALL( SCIPvarGetTransformed(var, scip->mem->probmem, scip->set, scip->stat, transvar) );
1451    }
1452 
1453    return SCIP_OKAY;
1454 }
1455 
1456 /** gets corresponding transformed variables for an array of variables;
1457  *  stores NULL in a transvars slot, if the transformed variable is not yet existing;
1458  *  it is possible to call this method with vars == transvars, but remember that variables that are not
1459  *  yet transformed will be replaced with NULL
1460  *
1461  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1462  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1463  *
1464  *  @pre This method can be called if @p scip is in one of the following stages:
1465  *       - \ref SCIP_STAGE_TRANSFORMING
1466  *       - \ref SCIP_STAGE_TRANSFORMED
1467  *       - \ref SCIP_STAGE_INITPRESOLVE
1468  *       - \ref SCIP_STAGE_PRESOLVING
1469  *       - \ref SCIP_STAGE_EXITPRESOLVE
1470  *       - \ref SCIP_STAGE_PRESOLVED
1471  *       - \ref SCIP_STAGE_INITSOLVE
1472  *       - \ref SCIP_STAGE_SOLVING
1473  *       - \ref SCIP_STAGE_SOLVED
1474  *       - \ref SCIP_STAGE_EXITSOLVE
1475  *       - \ref SCIP_STAGE_FREETRANS
1476  */
SCIPgetTransformedVars(SCIP * scip,int nvars,SCIP_VAR ** vars,SCIP_VAR ** transvars)1477 SCIP_RETCODE SCIPgetTransformedVars(
1478    SCIP*                 scip,               /**< SCIP data structure */
1479    int                   nvars,              /**< number of variables to get transformed variables for */
1480    SCIP_VAR**            vars,               /**< array with variables to get transformed variables for */
1481    SCIP_VAR**            transvars           /**< array to store the transformed variables */
1482    )
1483 {
1484    int v;
1485 
1486    assert(nvars == 0 || vars != NULL);
1487    assert(nvars == 0 || transvars != NULL);
1488 
1489    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetTransformedVars", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1490 
1491    for( v = 0; v < nvars; ++v )
1492    {
1493       if( SCIPvarIsTransformed(vars[v]) )
1494          transvars[v] = vars[v];
1495       else
1496       {
1497          SCIP_CALL( SCIPvarGetTransformed(vars[v], scip->mem->probmem, scip->set, scip->stat, &transvars[v]) );
1498       }
1499    }
1500 
1501    return SCIP_OKAY;
1502 }
1503 
1504 /** gets negated variable x' = lb + ub - x of variable x; negated variable is created, if not yet existing;
1505  *  in difference to \ref SCIPcreateVar, the negated variable must not be released (unless captured explicitly)
1506  *
1507  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1508  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1509  *
1510  *  @pre This method can be called if @p scip is in one of the following stages:
1511  *       - \ref SCIP_STAGE_PROBLEM
1512  *       - \ref SCIP_STAGE_TRANSFORMING
1513  *       - \ref SCIP_STAGE_TRANSFORMED
1514  *       - \ref SCIP_STAGE_INITPRESOLVE
1515  *       - \ref SCIP_STAGE_PRESOLVING
1516  *       - \ref SCIP_STAGE_EXITPRESOLVE
1517  *       - \ref SCIP_STAGE_PRESOLVED
1518  *       - \ref SCIP_STAGE_INITSOLVE
1519  *       - \ref SCIP_STAGE_SOLVING
1520  *       - \ref SCIP_STAGE_SOLVED
1521  *       - \ref SCIP_STAGE_EXITSOLVE
1522  *       - \ref SCIP_STAGE_FREETRANS
1523  */
SCIPgetNegatedVar(SCIP * scip,SCIP_VAR * var,SCIP_VAR ** negvar)1524 SCIP_RETCODE SCIPgetNegatedVar(
1525    SCIP*                 scip,               /**< SCIP data structure */
1526    SCIP_VAR*             var,                /**< variable to get negated variable for */
1527    SCIP_VAR**            negvar              /**< pointer to store the negated variable */
1528    )
1529 {
1530    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetNegatedVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1531    assert( var->scip == scip );
1532 
1533    SCIP_CALL( SCIPvarNegate(var, scip->mem->probmem, scip->set, scip->stat, negvar) );
1534 
1535    return SCIP_OKAY;
1536 }
1537 
1538 /** gets negated variables x' = lb + ub - x of variables x; negated variables are created, if not yet existing
1539  *
1540  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1541  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1542  *
1543  *  @pre This method can be called if @p scip is in one of the following stages:
1544  *       - \ref SCIP_STAGE_PROBLEM
1545  *       - \ref SCIP_STAGE_TRANSFORMING
1546  *       - \ref SCIP_STAGE_TRANSFORMED
1547  *       - \ref SCIP_STAGE_INITPRESOLVE
1548  *       - \ref SCIP_STAGE_PRESOLVING
1549  *       - \ref SCIP_STAGE_EXITPRESOLVE
1550  *       - \ref SCIP_STAGE_PRESOLVED
1551  *       - \ref SCIP_STAGE_INITSOLVE
1552  *       - \ref SCIP_STAGE_SOLVING
1553  *       - \ref SCIP_STAGE_SOLVED
1554  *       - \ref SCIP_STAGE_EXITSOLVE
1555  *       - \ref SCIP_STAGE_FREETRANS
1556  */
SCIPgetNegatedVars(SCIP * scip,int nvars,SCIP_VAR ** vars,SCIP_VAR ** negvars)1557 SCIP_RETCODE SCIPgetNegatedVars(
1558    SCIP*                 scip,               /**< SCIP data structure */
1559    int                   nvars,              /**< number of variables to get negated variables for */
1560    SCIP_VAR**            vars,               /**< array of variables to get negated variables for */
1561    SCIP_VAR**            negvars             /**< array to store the negated variables */
1562    )
1563 {
1564    int v;
1565 
1566    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetNegatedVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1567 
1568    for( v = 0; v < nvars; ++v )
1569    {
1570       SCIP_CALL( SCIPvarNegate(vars[v], scip->mem->probmem, scip->set, scip->stat, &(negvars[v])) );
1571    }
1572 
1573    return SCIP_OKAY;
1574 }
1575 
1576 /** gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or
1577  *  multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable
1578  *
1579  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1580  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1581  *
1582  *  @pre This method can be called if @p scip is in one of the following stages:
1583  *       - \ref SCIP_STAGE_PROBLEM
1584  *       - \ref SCIP_STAGE_TRANSFORMED
1585  *       - \ref SCIP_STAGE_INITPRESOLVE
1586  *       - \ref SCIP_STAGE_PRESOLVING
1587  *       - \ref SCIP_STAGE_EXITPRESOLVE
1588  *       - \ref SCIP_STAGE_PRESOLVED
1589  *       - \ref SCIP_STAGE_INITSOLVE
1590  *       - \ref SCIP_STAGE_SOLVING
1591  *       - \ref SCIP_STAGE_SOLVED
1592  *       - \ref SCIP_STAGE_EXITSOLVE
1593  */
SCIPgetBinvarRepresentative(SCIP * scip,SCIP_VAR * var,SCIP_VAR ** repvar,SCIP_Bool * negated)1594 SCIP_RETCODE SCIPgetBinvarRepresentative(
1595    SCIP*                 scip,               /**< SCIP data structure */
1596    SCIP_VAR*             var,                /**< binary variable to get binary representative for */
1597    SCIP_VAR**            repvar,             /**< pointer to store the binary representative */
1598    SCIP_Bool*            negated             /**< pointer to store whether the negation of an active variable was returned */
1599    )
1600 {
1601    assert(scip != NULL);
1602    assert(var != NULL);
1603    assert(repvar != NULL);
1604    assert(negated != NULL);
1605    assert(var->scip == scip);
1606 
1607    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetBinvarRepresentative", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1608 
1609    /* get the active representative of the given variable */
1610    *repvar = var;
1611    *negated = FALSE;
1612    SCIP_CALL( SCIPvarGetProbvarBinary(repvar, negated) );
1613 
1614    /* negate the representative, if it corresponds to the negation of the given variable */
1615    if( *negated )
1616    {
1617       SCIP_CALL( SCIPgetNegatedVar(scip, *repvar, repvar) );
1618    }
1619 
1620    return SCIP_OKAY;
1621 }
1622 
1623 /** gets binary variables that are equal to the given binary variables, and which are either active, fixed, or
1624  *  multi-aggregated, or the negated variables of active, fixed, or multi-aggregated variables
1625  *
1626  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1627  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1628  *
1629  *  @pre This method can be called if @p scip is in one of the following stages:
1630  *       - \ref SCIP_STAGE_PROBLEM
1631  *       - \ref SCIP_STAGE_TRANSFORMED
1632  *       - \ref SCIP_STAGE_INITPRESOLVE
1633  *       - \ref SCIP_STAGE_PRESOLVING
1634  *       - \ref SCIP_STAGE_EXITPRESOLVE
1635  *       - \ref SCIP_STAGE_PRESOLVED
1636  *       - \ref SCIP_STAGE_INITSOLVE
1637  *       - \ref SCIP_STAGE_SOLVING
1638  *       - \ref SCIP_STAGE_SOLVED
1639  *       - \ref SCIP_STAGE_EXITSOLVE
1640  */
SCIPgetBinvarRepresentatives(SCIP * scip,int nvars,SCIP_VAR ** vars,SCIP_VAR ** repvars,SCIP_Bool * negated)1641 SCIP_RETCODE SCIPgetBinvarRepresentatives(
1642    SCIP*                 scip,               /**< SCIP data structure */
1643    int                   nvars,              /**< number of binary variables to get representatives for */
1644    SCIP_VAR**            vars,               /**< binary variables to get binary representatives for */
1645    SCIP_VAR**            repvars,            /**< array to store the binary representatives */
1646    SCIP_Bool*            negated             /**< array to store whether the negation of an active variable was returned */
1647    )
1648 {
1649    int v;
1650 
1651    assert(scip != NULL);
1652    assert(vars != NULL || nvars == 0);
1653    assert(repvars != NULL || nvars == 0);
1654    assert(negated != NULL || nvars == 0);
1655 
1656    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetBinvarRepresentatives", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
1657 
1658    if( nvars == 0 )
1659       return SCIP_OKAY;
1660 
1661    /* get the active representative of the given variable */
1662    BMScopyMemoryArray(repvars, vars, nvars);
1663    BMSclearMemoryArray(negated, nvars);
1664    SCIP_CALL( SCIPvarsGetProbvarBinary(&repvars, &negated, nvars) );
1665 
1666    /* negate the representatives, if they correspond to the negation of the given variables */
1667    for( v = nvars - 1; v >= 0; --v )
1668       if( negated[v] )
1669       {
1670          SCIP_CALL( SCIPgetNegatedVar(scip, repvars[v], &(repvars[v])) );
1671       }
1672 
1673    return SCIP_OKAY;
1674 }
1675 
1676 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on
1677  *
1678  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1679  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1680  *
1681  *  @pre This method can be called if @p scip is in one of the following stages:
1682  *       - \ref SCIP_STAGE_INITPRESOLVE
1683  *       - \ref SCIP_STAGE_PRESOLVING
1684  *       - \ref SCIP_STAGE_EXITPRESOLVE
1685  *       - \ref SCIP_STAGE_PRESOLVED
1686  *       - \ref SCIP_STAGE_INITSOLVE
1687  *       - \ref SCIP_STAGE_SOLVING
1688  *       - \ref SCIP_STAGE_SOLVED
1689  */
SCIPflattenVarAggregationGraph(SCIP * scip,SCIP_VAR * var)1690 SCIP_RETCODE SCIPflattenVarAggregationGraph(
1691    SCIP*                 scip,               /**< SCIP data structure */
1692    SCIP_VAR*             var                 /**< problem variable */
1693    )
1694 {
1695    assert( scip != NULL );
1696    assert( var != NULL );
1697    SCIP_CALL( SCIPcheckStage(scip, "SCIPflattenVarAggregationGraph", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
1698 
1699    SCIP_CALL( SCIPvarFlattenAggregationGraph(var, scip->mem->probmem, scip->set, scip->eventqueue) );
1700 
1701    return SCIP_OKAY;
1702 }
1703 
1704 /** Transforms a given linear sum of variables, that is a_1*x_1 + ... + a_n*x_n + c into a corresponding linear sum of
1705  *  active variables, that is b_1*y_1 + ... + b_m*y_m + d.
1706  *
1707  *  If the number of needed active variables is greater than the available slots in the variable array, nothing happens
1708  *  except that the required size is stored in the corresponding variable (requiredsize). Otherwise, the active variable
1709  *  representation is stored in the variable array, scalar array and constant.
1710  *
1711  *  The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been
1712  *  allocated (e.g., by a C++ 'new' or SCIP functions).
1713  *
1714  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1715  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1716  *
1717  *  @pre This method can be called if @p scip is in one of the following stages:
1718  *       - \ref SCIP_STAGE_TRANSFORMED
1719  *       - \ref SCIP_STAGE_INITPRESOLVE
1720  *       - \ref SCIP_STAGE_PRESOLVING
1721  *       - \ref SCIP_STAGE_EXITPRESOLVE
1722  *       - \ref SCIP_STAGE_PRESOLVED
1723  *       - \ref SCIP_STAGE_INITSOLVE
1724  *       - \ref SCIP_STAGE_SOLVING
1725  *       - \ref SCIP_STAGE_SOLVED
1726  *       - \ref SCIP_STAGE_EXITSOLVE
1727  *       - \ref SCIP_STAGE_FREETRANS
1728  *
1729  *  @note The resulting linear sum is stored into the given variable array, scalar array, and constant. That means the
1730  *        given entries are overwritten.
1731  *
1732  *  @note That method can be used to convert a single variables into variable space of active variables. Therefore call
1733  *        the method with the linear sum 1.0*x + 0.0.
1734  */
SCIPgetProbvarLinearSum(SCIP * scip,SCIP_VAR ** vars,SCIP_Real * scalars,int * nvars,int varssize,SCIP_Real * constant,int * requiredsize,SCIP_Bool mergemultiples)1735 SCIP_RETCODE SCIPgetProbvarLinearSum(
1736    SCIP*                 scip,               /**< SCIP data structure */
1737    SCIP_VAR**            vars,               /**< variable array x_1, ..., x_n in the linear sum which will be
1738                                               *   overwritten by the variable array y_1, ..., y_m in the linear sum
1739                                               *   w.r.t. active variables */
1740    SCIP_Real*            scalars,            /**< scalars a_1, ..., a_n in linear sum which will be overwritten to the
1741                                               *   scalars b_1, ..., b_m in the linear sum of the active variables  */
1742    int*                  nvars,              /**< pointer to number of variables in the linear sum which will be
1743                                               *   overwritten by the number of variables in the linear sum corresponding
1744                                               *   to the active variables */
1745    int                   varssize,           /**< available slots in vars and scalars array which is needed to check if
1746                                               *   the array are large enough for the linear sum w.r.t. active
1747                                               *   variables */
1748    SCIP_Real*            constant,           /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c which
1749                                               *   will chnage to constant d in the linear sum b_1*y_1 + ... + b_m*y_m +
1750                                               *   d w.r.t. the active variables */
1751    int*                  requiredsize,       /**< pointer to store the required array size for the linear sum w.r.t. the
1752                                               *   active variables */
1753    SCIP_Bool             mergemultiples      /**< should multiple occurrences of a var be replaced by a single coeff? */
1754    )
1755 {
1756    assert( scip != NULL );
1757    assert( nvars != NULL );
1758    assert( vars != NULL || *nvars == 0 );
1759    assert( scalars != NULL || *nvars == 0 );
1760    assert( constant != NULL );
1761    assert( requiredsize != NULL );
1762    assert( *nvars <= varssize );
1763 
1764    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarLinearSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1765    SCIP_CALL( SCIPvarGetActiveRepresentatives(scip->set, vars, scalars, nvars, varssize, constant, requiredsize, mergemultiples) );
1766 
1767    return SCIP_OKAY;
1768 }
1769 
1770 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
1771  *  multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
1772  *  "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
1773  *  with only one active variable (this can happen due to fixings after the multi-aggregation),
1774  *  is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
1775  *
1776  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1777  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1778  *
1779  *  @pre This method can be called if @p scip is in one of the following stages:
1780  *       - \ref SCIP_STAGE_TRANSFORMED
1781  *       - \ref SCIP_STAGE_INITPRESOLVE
1782  *       - \ref SCIP_STAGE_PRESOLVING
1783  *       - \ref SCIP_STAGE_EXITPRESOLVE
1784  *       - \ref SCIP_STAGE_PRESOLVED
1785  *       - \ref SCIP_STAGE_INITSOLVE
1786  *       - \ref SCIP_STAGE_SOLVING
1787  *       - \ref SCIP_STAGE_SOLVED
1788  *       - \ref SCIP_STAGE_EXITSOLVE
1789  *       - \ref SCIP_STAGE_FREETRANS
1790  */
SCIPgetProbvarSum(SCIP * scip,SCIP_VAR ** var,SCIP_Real * scalar,SCIP_Real * constant)1791 SCIP_RETCODE SCIPgetProbvarSum(
1792    SCIP*                 scip,               /**< SCIP data structure */
1793    SCIP_VAR**            var,                /**< pointer to problem variable x in sum a*x + c */
1794    SCIP_Real*            scalar,             /**< pointer to scalar a in sum a*x + c */
1795    SCIP_Real*            constant            /**< pointer to constant c in sum a*x + c */
1796    )
1797 {
1798    assert(scip != NULL);
1799    assert(var != NULL);
1800    assert(scalar != NULL);
1801    assert(constant != NULL);
1802 
1803    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1804    SCIP_CALL( SCIPvarGetProbvarSum(var, scip->set, scalar, constant) );
1805 
1806    return SCIP_OKAY;
1807 }
1808 
1809 /** return for given variables all their active counterparts; all active variables will be pairwise different
1810  *  @note It does not hold that the first output variable is the active variable for the first input variable.
1811  *
1812  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
1813  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
1814  *
1815  *  @pre This method can be called if @p scip is in one of the following stages:
1816  *       - \ref SCIP_STAGE_TRANSFORMED
1817  *       - \ref SCIP_STAGE_INITPRESOLVE
1818  *       - \ref SCIP_STAGE_PRESOLVING
1819  *       - \ref SCIP_STAGE_EXITPRESOLVE
1820  *       - \ref SCIP_STAGE_PRESOLVED
1821  *       - \ref SCIP_STAGE_INITSOLVE
1822  *       - \ref SCIP_STAGE_SOLVING
1823  *       - \ref SCIP_STAGE_SOLVED
1824  *       - \ref SCIP_STAGE_EXITSOLVE
1825  *       - \ref SCIP_STAGE_FREETRANS
1826  */
SCIPgetActiveVars(SCIP * scip,SCIP_VAR ** vars,int * nvars,int varssize,int * requiredsize)1827 SCIP_RETCODE SCIPgetActiveVars(
1828    SCIP*                 scip,               /**< SCIP data structure */
1829    SCIP_VAR**            vars,               /**< variable array with given variables and as output all active
1830 					      *   variables, if enough slots exist
1831 					      */
1832    int*                  nvars,              /**< number of given variables, and as output number of active variables,
1833 					      *   if enough slots exist
1834 					      */
1835    int                   varssize,           /**< available slots in vars array */
1836    int*                  requiredsize        /**< pointer to store the required array size for the active variables */
1837    )
1838 {
1839    assert(scip != NULL);
1840    assert(nvars != NULL);
1841    assert(vars != NULL || *nvars == 0);
1842    assert(varssize >= *nvars);
1843    assert(requiredsize != NULL);
1844 
1845    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetActiveVars", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
1846    SCIP_CALL( SCIPvarsGetActiveVars(scip->set, vars, nvars, varssize, requiredsize) );
1847 
1848    return SCIP_OKAY;
1849 }
1850 
1851 /** returns the reduced costs of the variable in the current node's LP relaxation;
1852  *  the current node has to have a feasible LP.
1853  *
1854  *  returns SCIP_INVALID if the variable is active but not in the current LP;
1855  *  returns 0 if the variable has been aggregated out or fixed in presolving.
1856  *
1857  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
1858  *
1859  *  @note The return value of this method should be used carefully if the dual feasibility check was explictely disabled.
1860  */
SCIPgetVarRedcost(SCIP * scip,SCIP_VAR * var)1861 SCIP_Real SCIPgetVarRedcost(
1862    SCIP*                 scip,               /**< SCIP data structure */
1863    SCIP_VAR*             var                 /**< variable to get reduced costs, should be a column in current node LP */
1864    )
1865 {
1866    assert( scip != NULL );
1867    assert( var != NULL );
1868    assert( var->scip == scip );
1869 
1870    switch( SCIPvarGetStatus(var) )
1871    {
1872    case SCIP_VARSTATUS_ORIGINAL:
1873       if( var->data.original.transvar == NULL )
1874          return SCIP_INVALID;
1875       return SCIPgetVarRedcost(scip, var->data.original.transvar);
1876 
1877    case SCIP_VARSTATUS_COLUMN:
1878       return SCIPgetColRedcost(scip, SCIPvarGetCol(var));
1879 
1880    case SCIP_VARSTATUS_LOOSE:
1881       return SCIP_INVALID;
1882 
1883    case SCIP_VARSTATUS_FIXED:
1884    case SCIP_VARSTATUS_AGGREGATED:
1885    case SCIP_VARSTATUS_MULTAGGR:
1886    case SCIP_VARSTATUS_NEGATED:
1887       return 0.0;
1888 
1889    default:
1890       SCIPerrorMessage("unknown variable status\n");
1891       SCIPABORT();
1892       return 0.0; /*lint !e527*/
1893    }
1894 }
1895 
1896 /** returns the implied reduced costs of the variable in the current node's LP relaxation;
1897  *  the current node has to have a feasible LP.
1898  *
1899  *  returns SCIP_INVALID if the variable is active but not in the current LP;
1900  *  returns 0 if the variable has been aggregated out or fixed in presolving.
1901  *
1902  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
1903  *
1904  *  @note The return value of this method should be used carefully if the dual feasibility check was explictely disabled.
1905  */
SCIPgetVarImplRedcost(SCIP * scip,SCIP_VAR * var,SCIP_Bool varfixing)1906 SCIP_Real SCIPgetVarImplRedcost(
1907    SCIP*                 scip,               /**< SCIP data structure */
1908    SCIP_VAR*             var,                /**< variable to get reduced costs, should be a column in current node LP */
1909    SCIP_Bool             varfixing           /**< FALSE if for x == 0, TRUE for x == 1 */
1910    )
1911 {
1912    assert( scip != NULL );
1913    assert( var != NULL );
1914    assert( var->scip == scip );
1915 
1916    switch( SCIPvarGetStatus(var) )
1917    {
1918    case SCIP_VARSTATUS_ORIGINAL:
1919       if( var->data.original.transvar == NULL )
1920          return SCIP_INVALID;
1921       return SCIPgetVarImplRedcost(scip, var->data.original.transvar, varfixing);
1922 
1923    case SCIP_VARSTATUS_COLUMN:
1924       return SCIPvarGetImplRedcost(var, scip->set, varfixing, scip->stat, scip->transprob, scip->lp);
1925 
1926    case SCIP_VARSTATUS_LOOSE:
1927       return SCIP_INVALID;
1928 
1929    case SCIP_VARSTATUS_FIXED:
1930    case SCIP_VARSTATUS_AGGREGATED:
1931    case SCIP_VARSTATUS_MULTAGGR:
1932    case SCIP_VARSTATUS_NEGATED:
1933       return 0.0;
1934 
1935    default:
1936       SCIPerrorMessage("unknown variable status\n");
1937       SCIPABORT();
1938       return 0.0; /*lint !e527*/
1939    }
1940 }
1941 
1942 
1943 /** returns the Farkas coefficient of the variable in the current node's LP relaxation;
1944  *  the current node has to have an infeasible LP.
1945  *
1946  *  returns SCIP_INVALID if the variable is active but not in the current LP;
1947  *  returns 0 if the variable has been aggregated out or fixed in presolving.
1948  *
1949  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
1950  */
SCIPgetVarFarkasCoef(SCIP * scip,SCIP_VAR * var)1951 SCIP_Real SCIPgetVarFarkasCoef(
1952    SCIP*                 scip,               /**< SCIP data structure */
1953    SCIP_VAR*             var                 /**< variable to get reduced costs, should be a column in current node LP */
1954    )
1955 {
1956    assert(scip != NULL);
1957    assert(var != NULL);
1958    assert(var->scip == scip);
1959 
1960    switch( SCIPvarGetStatus(var) )
1961    {
1962    case SCIP_VARSTATUS_ORIGINAL:
1963       if( var->data.original.transvar == NULL )
1964          return SCIP_INVALID;
1965       return SCIPgetVarFarkasCoef(scip,var->data.original.transvar);
1966 
1967    case SCIP_VARSTATUS_COLUMN:
1968       return SCIPgetColFarkasCoef(scip,SCIPvarGetCol(var));
1969 
1970    case SCIP_VARSTATUS_LOOSE:
1971       return SCIP_INVALID;
1972 
1973    case SCIP_VARSTATUS_FIXED:
1974    case SCIP_VARSTATUS_AGGREGATED:
1975    case SCIP_VARSTATUS_MULTAGGR:
1976    case SCIP_VARSTATUS_NEGATED:
1977       return 0.0;
1978 
1979    default:
1980       SCIPerrorMessage("unknown variable status\n");
1981       SCIPABORT();
1982       return 0.0; /*lint !e527*/
1983    }
1984 }
1985 
1986 /** returns lower bound of variable directly before or after the bound change given by the bound change index
1987  *  was applied
1988  */
SCIPgetVarLbAtIndex(SCIP * scip,SCIP_VAR * var,SCIP_BDCHGIDX * bdchgidx,SCIP_Bool after)1989 SCIP_Real SCIPgetVarLbAtIndex(
1990    SCIP*                 scip,               /**< SCIP data structure */
1991    SCIP_VAR*             var,                /**< problem variable */
1992    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
1993    SCIP_Bool             after               /**< should the bound change with given index be included? */
1994    )
1995 {
1996    SCIP_VARSTATUS varstatus;
1997    SCIP_BDCHGINFO* bdchginfo;
1998    assert(var != NULL);
1999 
2000    varstatus = SCIPvarGetStatus(var);
2001 
2002    /* get bounds of attached variables */
2003    switch( varstatus )
2004    {
2005    case SCIP_VARSTATUS_ORIGINAL:
2006       assert(var->data.original.transvar != NULL);
2007       return SCIPgetVarLbAtIndex(scip, var->data.original.transvar, bdchgidx, after);
2008 
2009    case SCIP_VARSTATUS_COLUMN:
2010    case SCIP_VARSTATUS_LOOSE:
2011       if( bdchgidx == NULL )
2012          return SCIPvarGetLbLocal(var);
2013       else
2014       {
2015          bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
2016          if( bdchginfo != NULL )
2017             return SCIPbdchginfoGetNewbound(bdchginfo);
2018          else
2019             return var->glbdom.lb;
2020       }
2021 
2022    case SCIP_VARSTATUS_FIXED:
2023       return var->glbdom.lb;
2024 
2025    case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
2026       assert(var->data.aggregate.var != NULL);
2027       if( var->data.aggregate.scalar > 0.0 )
2028       {
2029          SCIP_Real lb;
2030 
2031          lb = SCIPgetVarLbAtIndex(scip, var->data.aggregate.var, bdchgidx, after);
2032 
2033          /* a > 0 -> get lower bound of y */
2034          if( SCIPisInfinity(scip, -lb) )
2035             return -SCIPinfinity(scip);
2036          else if( SCIPisInfinity(scip, lb) )
2037             return SCIPinfinity(scip);
2038          else
2039             return var->data.aggregate.scalar * lb + var->data.aggregate.constant;
2040       }
2041       else if( var->data.aggregate.scalar < 0.0 )
2042       {
2043          SCIP_Real ub;
2044 
2045          ub = SCIPgetVarUbAtIndex(scip, var->data.aggregate.var, bdchgidx, after);
2046 
2047          /* a < 0 -> get upper bound of y */
2048          if( SCIPisInfinity(scip, -ub) )
2049             return SCIPinfinity(scip);
2050          else if( SCIPisInfinity(scip, ub) )
2051             return -SCIPinfinity(scip);
2052          else
2053             return var->data.aggregate.scalar * ub + var->data.aggregate.constant;
2054       }
2055       else
2056       {
2057          SCIPerrorMessage("scalar is zero in aggregation\n");
2058          SCIPABORT();
2059          return SCIP_INVALID; /*lint !e527*/
2060       }
2061 
2062    case SCIP_VARSTATUS_MULTAGGR:
2063       /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
2064       if ( var->data.multaggr.nvars == 1 )
2065       {
2066          assert(var->data.multaggr.vars != NULL);
2067          assert(var->data.multaggr.scalars != NULL);
2068          assert(var->data.multaggr.vars[0] != NULL);
2069 
2070          if( var->data.multaggr.scalars[0] > 0.0 )
2071          {
2072             SCIP_Real lb;
2073 
2074             lb = SCIPgetVarLbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after);
2075 
2076             /* a > 0 -> get lower bound of y */
2077             if( SCIPisInfinity(scip, -lb) )
2078                return -SCIPinfinity(scip);
2079             else if( SCIPisInfinity(scip, lb) )
2080                return SCIPinfinity(scip);
2081             else
2082                return var->data.multaggr.scalars[0] * lb + var->data.multaggr.constant;
2083          }
2084          else if( var->data.multaggr.scalars[0] < 0.0 )
2085          {
2086             SCIP_Real ub;
2087 
2088             ub = SCIPgetVarUbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after);
2089 
2090             /* a < 0 -> get upper bound of y */
2091             if( SCIPisInfinity(scip, -ub) )
2092                return SCIPinfinity(scip);
2093             else if( SCIPisInfinity(scip, ub) )
2094                return -SCIPinfinity(scip);
2095             else
2096                return var->data.multaggr.scalars[0] * ub + var->data.multaggr.constant;
2097          }
2098          else
2099          {
2100             SCIPerrorMessage("scalar is zero in multi-aggregation\n");
2101             SCIPABORT();
2102             return SCIP_INVALID; /*lint !e527*/
2103          }
2104       }
2105       SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
2106       SCIPABORT();
2107       return SCIP_INVALID; /*lint !e527*/
2108 
2109    case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
2110       assert(var->negatedvar != NULL);
2111       assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
2112       assert(var->negatedvar->negatedvar == var);
2113       return var->data.negate.constant - SCIPgetVarUbAtIndex(scip, var->negatedvar, bdchgidx, after);
2114 
2115    default:
2116       SCIPerrorMessage("unknown variable status\n");
2117       SCIPABORT();
2118       return SCIP_INVALID; /*lint !e527*/
2119    }
2120 }
2121 
2122 /** returns upper bound of variable directly before or after the bound change given by the bound change index
2123  *  was applied
2124  */
SCIPgetVarUbAtIndex(SCIP * scip,SCIP_VAR * var,SCIP_BDCHGIDX * bdchgidx,SCIP_Bool after)2125 SCIP_Real SCIPgetVarUbAtIndex(
2126    SCIP*                 scip,               /**< SCIP data structure */
2127    SCIP_VAR*             var,                /**< problem variable */
2128    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
2129    SCIP_Bool             after               /**< should the bound change with given index be included? */
2130    )
2131 {
2132    SCIP_VARSTATUS varstatus;
2133    SCIP_BDCHGINFO* bdchginfo;
2134    assert(var != NULL);
2135 
2136    varstatus = SCIPvarGetStatus(var);
2137 
2138    /* get bounds of attached variables */
2139    switch( varstatus )
2140    {
2141    case SCIP_VARSTATUS_ORIGINAL:
2142       assert(var->data.original.transvar != NULL);
2143       return SCIPgetVarUbAtIndex(scip, var->data.original.transvar, bdchgidx, after);
2144 
2145    case SCIP_VARSTATUS_COLUMN:
2146    case SCIP_VARSTATUS_LOOSE:
2147       if( bdchgidx == NULL )
2148          return SCIPvarGetUbLocal(var);
2149       else
2150       {
2151          bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
2152          if( bdchginfo != NULL )
2153             return SCIPbdchginfoGetNewbound(bdchginfo);
2154          else
2155             return var->glbdom.ub;
2156       }
2157 
2158    case SCIP_VARSTATUS_FIXED:
2159       return var->glbdom.ub;
2160 
2161    case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  ->  y = (x-c)/a */
2162       assert(var->data.aggregate.var != NULL);
2163       if( var->data.aggregate.scalar > 0.0 )
2164       {
2165          SCIP_Real ub;
2166 
2167          ub = SCIPgetVarUbAtIndex(scip, var->data.aggregate.var, bdchgidx, after);
2168 
2169          /* a > 0 -> get lower bound of y */
2170          if( SCIPisInfinity(scip, -ub) )
2171             return -SCIPinfinity(scip);
2172          else if( SCIPisInfinity(scip, ub) )
2173             return SCIPinfinity(scip);
2174          else
2175             return var->data.aggregate.scalar * ub + var->data.aggregate.constant;
2176       }
2177       else if( var->data.aggregate.scalar < 0.0 )
2178       {
2179          SCIP_Real lb;
2180 
2181          lb = SCIPgetVarLbAtIndex(scip, var->data.aggregate.var, bdchgidx, after);
2182 
2183          /* a < 0 -> get upper bound of y */
2184          if ( SCIPisInfinity(scip, -lb) )
2185             return SCIPinfinity(scip);
2186          else if ( SCIPisInfinity(scip, lb) )
2187             return -SCIPinfinity(scip);
2188          else
2189             return var->data.aggregate.scalar * lb + var->data.aggregate.constant;
2190       }
2191       else
2192       {
2193          SCIPerrorMessage("scalar is zero in aggregation\n");
2194          SCIPABORT();
2195          return SCIP_INVALID; /*lint !e527*/
2196       }
2197 
2198    case SCIP_VARSTATUS_MULTAGGR:
2199       /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
2200       if ( var->data.multaggr.nvars == 1 )
2201       {
2202          assert(var->data.multaggr.vars != NULL);
2203          assert(var->data.multaggr.scalars != NULL);
2204          assert(var->data.multaggr.vars[0] != NULL);
2205 
2206          if( var->data.multaggr.scalars[0] > 0.0 )
2207          {
2208             SCIP_Real ub;
2209 
2210             ub = SCIPgetVarUbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after);
2211 
2212             /* a > 0 -> get lower bound of y */
2213             if ( SCIPisInfinity(scip, -ub) )
2214                return -SCIPinfinity(scip);
2215             else if ( SCIPisInfinity(scip, ub) )
2216                return SCIPinfinity(scip);
2217             else
2218                return var->data.multaggr.scalars[0] * ub + var->data.multaggr.constant;
2219          }
2220          else if( var->data.multaggr.scalars[0] < 0.0 )
2221          {
2222             SCIP_Real lb;
2223 
2224             lb = SCIPgetVarLbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after);
2225 
2226             /* a < 0 -> get upper bound of y */
2227             if ( SCIPisInfinity(scip, -lb) )
2228                return SCIPinfinity(scip);
2229             else if ( SCIPisInfinity(scip, lb) )
2230                return -SCIPinfinity(scip);
2231             else
2232                return var->data.multaggr.scalars[0] * lb + var->data.multaggr.constant;
2233          }
2234          else
2235          {
2236             SCIPerrorMessage("scalar is zero in multi-aggregation\n");
2237             SCIPABORT();
2238             return SCIP_INVALID; /*lint !e527*/
2239          }
2240       }
2241       SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
2242       SCIPABORT();
2243       return SCIP_INVALID; /*lint !e527*/
2244 
2245    case SCIP_VARSTATUS_NEGATED: /* x' = offset - x  ->  x = offset - x' */
2246       assert(var->negatedvar != NULL);
2247       assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED);
2248       assert(var->negatedvar->negatedvar == var);
2249       return var->data.negate.constant - SCIPgetVarLbAtIndex(scip, var->negatedvar, bdchgidx, after);
2250 
2251    default:
2252       SCIPerrorMessage("unknown variable status\n");
2253       SCIPABORT();
2254       return SCIP_INVALID; /*lint !e527*/
2255    }
2256 }
2257 
2258 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
2259  *  was applied
2260  */
SCIPgetVarBdAtIndex(SCIP * scip,SCIP_VAR * var,SCIP_BOUNDTYPE boundtype,SCIP_BDCHGIDX * bdchgidx,SCIP_Bool after)2261 SCIP_Real SCIPgetVarBdAtIndex(
2262    SCIP*                 scip,               /**< SCIP data structure */
2263    SCIP_VAR*             var,                /**< problem variable */
2264    SCIP_BOUNDTYPE        boundtype,          /**< type of bound: lower or upper bound */
2265    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
2266    SCIP_Bool             after               /**< should the bound change with given index be included? */
2267    )
2268 {
2269    if( boundtype == SCIP_BOUNDTYPE_LOWER )
2270       return SCIPgetVarLbAtIndex(scip, var, bdchgidx, after);
2271    else
2272    {
2273       assert(boundtype == SCIP_BOUNDTYPE_UPPER);
2274       return SCIPgetVarUbAtIndex(scip, var, bdchgidx, after);
2275    }
2276 }
2277 
2278 /** returns whether the binary variable was fixed at the time given by the bound change index */
SCIPgetVarWasFixedAtIndex(SCIP * scip,SCIP_VAR * var,SCIP_BDCHGIDX * bdchgidx,SCIP_Bool after)2279 SCIP_Bool SCIPgetVarWasFixedAtIndex(
2280    SCIP*                 scip,               /**< SCIP data structure */
2281    SCIP_VAR*             var,                /**< problem variable */
2282    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index representing time on path to current node */
2283    SCIP_Bool             after               /**< should the bound change with given index be included? */
2284    )
2285 {
2286    assert(var != NULL);
2287    assert(SCIPvarIsBinary(var));
2288 
2289    /* check the current bounds first in order to decide at which bound change information we have to look
2290     * (which is expensive because we have to follow the aggregation tree to the active variable)
2291     */
2292    return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPgetVarLbAtIndex(scip, var, bdchgidx, after) > 0.5)
2293       || (SCIPvarGetUbLocal(var) < 0.5 && SCIPgetVarUbAtIndex(scip, var, bdchgidx, after) < 0.5));
2294 }
2295 
2296 /** gets solution value for variable in current node
2297  *
2298  *  @return solution value for variable in current node
2299  *
2300  *  @pre This method can be called if @p scip is in one of the following stages:
2301  *       - \ref SCIP_STAGE_PRESOLVED
2302  *       - \ref SCIP_STAGE_SOLVING
2303  */
SCIPgetVarSol(SCIP * scip,SCIP_VAR * var)2304 SCIP_Real SCIPgetVarSol(
2305    SCIP*                 scip,               /**< SCIP data structure */
2306    SCIP_VAR*             var                 /**< variable to get solution value for */
2307    )
2308 {
2309    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2310    assert( var->scip == scip );
2311 
2312    return SCIPvarGetSol(var, SCIPtreeHasCurrentNodeLP(scip->tree));
2313 }
2314 
2315 /** gets solution values of multiple variables in current node
2316  *
2317  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2318  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2319  *
2320  *  @pre This method can be called if @p scip is in one of the following stages:
2321  *       - \ref SCIP_STAGE_PRESOLVED
2322  *       - \ref SCIP_STAGE_SOLVING
2323  */
SCIPgetVarSols(SCIP * scip,int nvars,SCIP_VAR ** vars,SCIP_Real * vals)2324 SCIP_RETCODE SCIPgetVarSols(
2325    SCIP*                 scip,               /**< SCIP data structure */
2326    int                   nvars,              /**< number of variables to get solution value for */
2327    SCIP_VAR**            vars,               /**< array with variables to get value for */
2328    SCIP_Real*            vals                /**< array to store solution values of variables */
2329    )
2330 {
2331    int v;
2332 
2333    assert(nvars == 0 || vars != NULL);
2334    assert(nvars == 0 || vals != NULL);
2335 
2336    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarSols", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2337 
2338    if( SCIPtreeHasCurrentNodeLP(scip->tree) )
2339    {
2340       for( v = 0; v < nvars; ++v )
2341          vals[v] = SCIPvarGetLPSol(vars[v]);
2342    }
2343    else
2344    {
2345       for( v = 0; v < nvars; ++v )
2346          vals[v] = SCIPvarGetPseudoSol(vars[v]);
2347    }
2348 
2349    return SCIP_OKAY;
2350 }
2351 
2352 /** sets the solution value of all variables in the global relaxation solution to zero
2353  *
2354  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2355  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2356  *
2357  *  @pre This method can be called if @p scip is in one of the following stages:
2358  *       - \ref SCIP_STAGE_PRESOLVED
2359  *       - \ref SCIP_STAGE_SOLVING
2360  */
SCIPclearRelaxSolVals(SCIP * scip,SCIP_RELAX * relax)2361 SCIP_RETCODE SCIPclearRelaxSolVals(
2362    SCIP*                 scip,               /**< SCIP data structure */
2363    SCIP_RELAX*           relax               /**< relaxator data structure */
2364    )
2365 {
2366    SCIP_VAR** vars;
2367    int nvars;
2368    int v;
2369 
2370    assert(scip != NULL);
2371 
2372    SCIP_CALL( SCIPcheckStage(scip, "SCIPclearRelaxSolVals", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2373 
2374    /* update the responsible relax pointer */
2375    SCIPrelaxationSetSolRelax(scip->relaxation, relax);
2376 
2377    /* the relaxation solution is already cleared */
2378    if( SCIPrelaxationIsSolZero(scip->relaxation) )
2379       return SCIP_OKAY;
2380 
2381    SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2382 
2383    for( v = 0; v < nvars; v++ )
2384    {
2385       SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, 0.0, FALSE) );
2386    }
2387 
2388    SCIPrelaxationSetSolObj(scip->relaxation, 0.0);
2389    SCIPrelaxationSetSolZero(scip->relaxation, TRUE);
2390 
2391    return SCIP_OKAY;
2392 }
2393 
2394 /** sets the value of the given variable in the global relaxation solution;
2395  *  this solution can be filled by the relaxation handlers  and can be used by heuristics and for separation;
2396  *  You can use SCIPclearRelaxSolVals() to set all values to zero, initially;
2397  *  after setting all solution values, you have to call SCIPmarkRelaxSolValid()
2398  *  to inform SCIP that the stored solution is valid
2399  *
2400  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2401  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2402  *
2403  *  @pre This method can be called if @p scip is in one of the following stages:
2404  *       - \ref SCIP_STAGE_PRESOLVED
2405  *       - \ref SCIP_STAGE_SOLVING
2406  *
2407  *  @note This method incrementally updates the objective value of the relaxation solution. If the whole solution
2408  *        should be updated, using SCIPsetRelaxSolVals() instead or calling SCIPclearRelaxSolVals() before setting
2409  *        the first value to reset the solution and the objective value to 0 may help the numerics.
2410  */
SCIPsetRelaxSolVal(SCIP * scip,SCIP_RELAX * relax,SCIP_VAR * var,SCIP_Real val)2411 SCIP_RETCODE SCIPsetRelaxSolVal(
2412    SCIP*                 scip,               /**< SCIP data structure */
2413    SCIP_RELAX*           relax,              /**< relaxator data structure */
2414    SCIP_VAR*             var,                /**< variable to set value for */
2415    SCIP_Real             val                 /**< solution value of variable */
2416    )
2417 {
2418    assert(scip != NULL);
2419 
2420    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolVal", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2421 
2422    SCIP_CALL( SCIPvarSetRelaxSol(var, scip->set, scip->relaxation, val, TRUE) );
2423 
2424    if( val != 0.0 )
2425       SCIPrelaxationSetSolZero(scip->relaxation, FALSE);
2426    SCIPrelaxationSetSolValid(scip->relaxation, FALSE, FALSE);
2427    SCIPrelaxationSetSolRelax(scip->relaxation, relax);
2428 
2429    return SCIP_OKAY;
2430 }
2431 
2432 /** sets the values of the given variables in the global relaxation solution and informs SCIP about the validity
2433  *  and whether the solution can be enforced via linear cuts;
2434  *  this solution can be filled by the relaxation handlers  and can be used by heuristics and for separation;
2435  *  the solution is automatically cleared, s.t. all other variables get value 0.0
2436  *
2437  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2438  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2439  *
2440  *  @pre This method can be called if @p scip is in one of the following stages:
2441  *       - \ref SCIP_STAGE_PRESOLVED
2442  *       - \ref SCIP_STAGE_SOLVING
2443  */
SCIPsetRelaxSolVals(SCIP * scip,SCIP_RELAX * relax,int nvars,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_Bool includeslp)2444 SCIP_RETCODE SCIPsetRelaxSolVals(
2445    SCIP*                 scip,               /**< SCIP data structure */
2446    SCIP_RELAX*           relax,              /**< relaxator data structure */
2447    int                   nvars,              /**< number of variables to set relaxation solution value for */
2448    SCIP_VAR**            vars,               /**< array with variables to set value for */
2449    SCIP_Real*            vals,               /**< array with solution values of variables */
2450    SCIP_Bool             includeslp          /**< does the relaxator contain all cuts in the LP? */
2451    )
2452 {
2453    int v;
2454 
2455    assert(scip != NULL);
2456    assert(nvars == 0 || vars != NULL);
2457    assert(nvars == 0 || vals != NULL);
2458 
2459    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolVals", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2460 
2461    SCIP_CALL( SCIPclearRelaxSolVals(scip, relax) );
2462 
2463    for( v = 0; v < nvars; v++ )
2464    {
2465       SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, vals[v], TRUE) );
2466    }
2467 
2468    SCIPrelaxationSetSolZero(scip->relaxation, FALSE);
2469    SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp);
2470    SCIPrelaxationSetSolRelax(scip->relaxation, relax);
2471 
2472    return SCIP_OKAY;
2473 }
2474 
2475 /** sets the values of the variables in the global relaxation solution to the values in the given primal solution
2476  *  and informs SCIP about the validity and whether the solution can be enforced via linear cuts;
2477  *  the relaxation solution can be filled by the relaxation handlers and might be used by heuristics and for separation
2478  *
2479  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2480  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2481  *
2482  *  @pre This method can be called if @p scip is in one of the following stages:
2483  *       - \ref SCIP_STAGE_PRESOLVED
2484  *       - \ref SCIP_STAGE_SOLVING
2485  */
SCIPsetRelaxSolValsSol(SCIP * scip,SCIP_RELAX * relax,SCIP_SOL * sol,SCIP_Bool includeslp)2486 SCIP_RETCODE SCIPsetRelaxSolValsSol(
2487    SCIP*                 scip,               /**< SCIP data structure */
2488    SCIP_RELAX*           relax,              /**< relaxator data structure */
2489    SCIP_SOL*             sol,                /**< primal relaxation solution */
2490    SCIP_Bool             includeslp          /**< does the relaxator contain all cuts in the LP? */
2491    )
2492 {
2493    SCIP_VAR** vars;
2494    SCIP_Real* vals;
2495    int nvars;
2496    int v;
2497 
2498    assert(scip != NULL);
2499 
2500    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolValsSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2501 
2502    SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2503 
2504    /* alloc buffer array for solution values of the variables and get the values */
2505    SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
2506    SCIP_CALL( SCIPgetSolVals(scip, sol, nvars, vars, vals) );
2507 
2508    SCIP_CALL( SCIPclearRelaxSolVals(scip, relax) );
2509 
2510    for( v = 0; v < nvars; v++ )
2511    {
2512       SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, vals[v], FALSE) );
2513    }
2514 
2515    SCIPrelaxationSetSolObj(scip->relaxation, SCIPsolGetObj(sol, scip->set, scip->transprob, scip->origprob));
2516 
2517    SCIPrelaxationSetSolZero(scip->relaxation, FALSE);
2518    SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp);
2519    SCIPrelaxationSetSolRelax(scip->relaxation, relax);
2520 
2521    SCIPfreeBufferArray(scip, &vals);
2522 
2523    return SCIP_OKAY;
2524 }
2525 
2526 /** returns whether the relaxation solution is valid
2527  *
2528  *  @return TRUE, if the relaxation solution is valid; FALSE, otherwise
2529  *
2530  *  @pre This method can be called if @p scip is in one of the following stages:
2531  *       - \ref SCIP_STAGE_PRESOLVED
2532  *       - \ref SCIP_STAGE_SOLVING
2533  */
SCIPisRelaxSolValid(SCIP * scip)2534 SCIP_Bool SCIPisRelaxSolValid(
2535    SCIP*                 scip                /**< SCIP data structure */
2536    )
2537 {
2538    assert(scip != NULL);
2539 
2540    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisRelaxSolValid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2541 
2542    return SCIPrelaxationIsSolValid(scip->relaxation);
2543 }
2544 
2545 /** informs SCIP that the relaxation solution is valid and whether the relaxation can be enforced through linear cuts
2546  *
2547  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2548  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2549  *
2550  *  @pre This method can be called if @p scip is in one of the following stages:
2551  *       - \ref SCIP_STAGE_PRESOLVED
2552  *       - \ref SCIP_STAGE_SOLVING
2553  */
SCIPmarkRelaxSolValid(SCIP * scip,SCIP_RELAX * relax,SCIP_Bool includeslp)2554 SCIP_RETCODE SCIPmarkRelaxSolValid(
2555    SCIP*                 scip,               /**< SCIP data structure */
2556    SCIP_RELAX*           relax,              /**< relaxator data structure that set the current relaxation solution */
2557    SCIP_Bool             includeslp          /**< does the relaxator contain all cuts in the LP? */
2558    )
2559 {
2560    assert(scip != NULL);
2561 
2562    SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkRelaxSolValid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2563 
2564    SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp);
2565    SCIPrelaxationSetSolRelax(scip->relaxation, relax);
2566 
2567    return SCIP_OKAY;
2568 }
2569 
2570 /** informs SCIP, that the relaxation solution is invalid
2571  *
2572  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2573  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2574  *
2575  *  @pre This method can be called if @p scip is in one of the following stages:
2576  *       - \ref SCIP_STAGE_PRESOLVED
2577  *       - \ref SCIP_STAGE_SOLVING
2578  */
SCIPmarkRelaxSolInvalid(SCIP * scip)2579 SCIP_RETCODE SCIPmarkRelaxSolInvalid(
2580    SCIP*                 scip                /**< SCIP data structure */
2581    )
2582 {
2583    assert(scip != NULL);
2584 
2585    SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkRelaxSolInvalid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2586 
2587    SCIPrelaxationSetSolValid(scip->relaxation, FALSE, FALSE);
2588 
2589    return SCIP_OKAY;
2590 }
2591 
2592 /** gets the relaxation solution value of the given variable
2593  *
2594  *  @return the relaxation solution value of the given variable
2595  *
2596  *  @pre This method can be called if @p scip is in one of the following stages:
2597  *       - \ref SCIP_STAGE_PRESOLVED
2598  *       - \ref SCIP_STAGE_SOLVING
2599  */
SCIPgetRelaxSolVal(SCIP * scip,SCIP_VAR * var)2600 SCIP_Real SCIPgetRelaxSolVal(
2601    SCIP*                 scip,               /**< SCIP data structure */
2602    SCIP_VAR*             var                 /**< variable to get value for */
2603    )
2604 {
2605    assert(scip != NULL);
2606    assert(var != NULL);
2607    assert(var->scip == scip);
2608 
2609    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetRelaxSolVal", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2610 
2611    if( !SCIPrelaxationIsSolValid(scip->relaxation) )
2612    {
2613       SCIPerrorMessage("Relaxation Solution is not valid!\n");
2614       SCIPABORT();
2615       return SCIP_INVALID; /*lint !e527*/
2616    }
2617 
2618    return SCIPvarGetRelaxSol(var, scip->set);
2619 }
2620 
2621 /** gets the relaxation solution objective value
2622  *
2623  *  @return the objective value of the relaxation solution
2624  *
2625  *  @pre This method can be called if @p scip is in one of the following stages:
2626  *       - \ref SCIP_STAGE_PRESOLVED
2627  *       - \ref SCIP_STAGE_SOLVING
2628  */
SCIPgetRelaxSolObj(SCIP * scip)2629 SCIP_Real SCIPgetRelaxSolObj(
2630    SCIP*                 scip                /**< SCIP data structure */
2631    )
2632 {
2633    assert(scip != NULL);
2634 
2635    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetRelaxSolObj", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2636 
2637    if( !SCIPrelaxationIsSolValid(scip->relaxation) )
2638    {
2639       SCIPerrorMessage("Relaxation Solution is not valid!\n");
2640       SCIPABORT();
2641       return SCIP_INVALID; /*lint !e527*/
2642    }
2643 
2644    return SCIPrelaxationGetSolObj(scip->relaxation);
2645 }
2646 
2647 /** determine which branching direction should be evaluated first by strong branching
2648  *
2649  *  @return TRUE iff strong branching should first evaluate the down child
2650  *
2651  */
SCIPisStrongbranchDownFirst(SCIP * scip,SCIP_VAR * var)2652 SCIP_Bool SCIPisStrongbranchDownFirst(
2653    SCIP*                 scip,               /**< SCIP data structure */
2654    SCIP_VAR*             var                 /**< variable to determine the branching direction on */
2655    )
2656 {
2657    switch( scip->set->branch_firstsbchild )
2658    {
2659       case 'u':
2660          return FALSE;
2661       case 'd':
2662          return TRUE;
2663       case 'a':
2664          return (SCIPvarGetNLocksDown(var) > SCIPvarGetNLocksUp(var));
2665       default:
2666          assert(scip->set->branch_firstsbchild == 'h');
2667          return (SCIPgetVarAvgCutoffs(scip, var, SCIP_BRANCHDIR_DOWNWARDS) > SCIPgetVarAvgCutoffs(scip, var, SCIP_BRANCHDIR_UPWARDS));
2668    }
2669 }
2670 
2671 /** start strong branching - call before any strong branching
2672  *
2673  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2674  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2675  *
2676  *  @pre This method can be called if @p scip is in one of the following stages:
2677  *       - \ref SCIP_STAGE_PRESOLVED
2678  *       - \ref SCIP_STAGE_SOLVING
2679  *
2680  *  @note if propagation is enabled, strong branching is not done directly on the LP, but probing nodes are created
2681  *        which allow to perform propagation but also creates some overhead
2682  */
SCIPstartStrongbranch(SCIP * scip,SCIP_Bool enablepropagation)2683 SCIP_RETCODE SCIPstartStrongbranch(
2684    SCIP*                 scip,               /**< SCIP data structure */
2685    SCIP_Bool             enablepropagation   /**< should propagation be done before solving the strong branching LP? */
2686    )
2687 {
2688    assert( scip != NULL );
2689    SCIP_CALL( SCIPcheckStage(scip, "SCIPstartStrongbranch", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2690 
2691    assert(!SCIPinProbing(scip));
2692 
2693    SCIPdebugMsg(scip, "starting strong branching mode%s: lpcount=%" SCIP_LONGINT_FORMAT "\n", enablepropagation ? " with propagation" : "", scip->stat->lpcount - scip->stat->nsbdivinglps);
2694 
2695    /* start probing mode to allow propagation before solving the strong branching LPs; if no propagation should be done,
2696     * start the strong branching mode in the LP interface
2697     */
2698    if( enablepropagation )
2699    {
2700       if( SCIPtreeProbing(scip->tree) )
2701       {
2702          SCIPerrorMessage("cannot start strong branching with propagation while in probing mode\n");
2703          return SCIP_INVALIDCALL;
2704       }
2705 
2706       if( scip->lp != NULL && SCIPlpDiving(scip->lp) )
2707       {
2708          SCIPerrorMessage("cannot start strong branching with propagation while in diving mode\n");
2709          return SCIP_INVALIDCALL;
2710       }
2711 
2712       /* other then in SCIPstartProbing(), we do not disable collecting variable statistics during strong branching;
2713        * we cannot disable it, because the pseudo costs would not be updated, otherwise,
2714        * and reliability branching would end up doing strong branching all the time
2715        */
2716       SCIP_CALL( SCIPtreeStartProbing(scip->tree, scip->mem->probmem, scip->set, scip->lp, scip->relaxation, scip->transprob, TRUE) );
2717 
2718       /* inform the LP that the current probing mode is used for strong branching */
2719       SCIPlpStartStrongbranchProbing(scip->lp);
2720    }
2721    else
2722    {
2723       SCIP_CALL( SCIPlpStartStrongbranch(scip->lp) );
2724    }
2725 
2726    /* reset local strong branching info */
2727    scip->stat->lastsblpsolstats[0] = scip->stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED;
2728 
2729    return SCIP_OKAY;
2730 }
2731 
2732 /** end strong branching - call after any strong branching
2733  *
2734  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2735  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2736  *
2737  *  @pre This method can be called if @p scip is in one of the following stages:
2738  *       - \ref SCIP_STAGE_PRESOLVED
2739  *       - \ref SCIP_STAGE_SOLVING
2740  */
SCIPendStrongbranch(SCIP * scip)2741 SCIP_RETCODE SCIPendStrongbranch(
2742    SCIP*                 scip                /**< SCIP data structure */
2743    )
2744 {
2745    assert( scip != NULL );
2746 
2747    SCIP_CALL( SCIPcheckStage(scip, "SCIPendStrongbranch", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2748 
2749    /* depending on whether the strong branching mode was started with propagation enabled or not, we end the strong
2750     * branching probing mode or the LP strong branching mode
2751     */
2752    if( SCIPtreeProbing(scip->tree) )
2753    {
2754       SCIP_NODE* node;
2755       SCIP_DOMCHG* domchg;
2756       SCIP_VAR** boundchgvars;
2757       SCIP_Real* bounds;
2758       SCIP_BOUNDTYPE* boundtypes;
2759       int nboundchgs;
2760       int nbnds;
2761       int i;
2762 
2763       /* collect all bound changes deducted during probing, which were applied at the probing root and apply them to the
2764        * focusnode
2765        */
2766       node = SCIPgetCurrentNode(scip);
2767       assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
2768       assert(SCIPgetProbingDepth(scip) == 0);
2769 
2770       domchg = SCIPnodeGetDomchg(node);
2771       nboundchgs = SCIPdomchgGetNBoundchgs(domchg);
2772 
2773       SCIP_CALL( SCIPallocBufferArray(scip, &boundchgvars, nboundchgs) );
2774       SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nboundchgs) );
2775       SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nboundchgs) );
2776 
2777       for( i = 0, nbnds = 0; i < nboundchgs; ++i )
2778       {
2779          SCIP_BOUNDCHG* boundchg;
2780 
2781          boundchg = SCIPdomchgGetBoundchg(domchg, i);
2782 
2783          /* ignore redundant bound changes */
2784          if( SCIPboundchgIsRedundant(boundchg) )
2785             continue;
2786 
2787          boundchgvars[nbnds] = SCIPboundchgGetVar(boundchg);
2788          bounds[nbnds] = SCIPboundchgGetNewbound(boundchg);
2789          boundtypes[nbnds] = SCIPboundchgGetBoundtype(boundchg);
2790          ++nbnds;
2791       }
2792 
2793       SCIPdebugMsg(scip, "ending strong branching with probing: %d bound changes collected\n", nbnds);
2794 
2795       /* inform the LP that the probing mode is not used for strong branching anymore */
2796       SCIPlpEndStrongbranchProbing(scip->lp);
2797 
2798       /* switch back from probing to normal operation mode and restore variables and constraints to focus node */
2799       SCIP_CALL( SCIPtreeEndProbing(scip->tree, scip->reopt, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat,
2800          scip->transprob, scip->origprob, scip->lp, scip->relaxation, scip->primal,
2801          scip->branchcand, scip->eventqueue, scip->eventfilter, scip->cliquetable) );
2802 
2803       /* apply the collected bound changes */
2804       for( i = 0; i < nbnds; ++i )
2805       {
2806          if( boundtypes[i] == SCIP_BOUNDTYPE_LOWER )
2807          {
2808             SCIPdebugMsg(scip, "apply probing lower bound change <%s> >= %.9g\n", SCIPvarGetName(boundchgvars[i]), bounds[i]);
2809             SCIP_CALL( SCIPchgVarLb(scip, boundchgvars[i], bounds[i]) );
2810          }
2811          else
2812          {
2813             SCIPdebugMsg(scip, "apply probing upper bound change <%s> <= %.9g\n", SCIPvarGetName(boundchgvars[i]), bounds[i]);
2814             SCIP_CALL( SCIPchgVarUb(scip, boundchgvars[i], bounds[i]) );
2815          }
2816       }
2817 
2818       SCIPfreeBufferArray(scip, &boundtypes);
2819       SCIPfreeBufferArray(scip, &bounds);
2820       SCIPfreeBufferArray(scip, &boundchgvars);
2821    }
2822    else
2823    {
2824       SCIPdebugMsg(scip, "ending strong branching\n");
2825 
2826       SCIP_CALL( SCIPlpEndStrongbranch(scip->lp) );
2827    }
2828 
2829    return SCIP_OKAY;
2830 }
2831 
2832 /** analyze the strong branching for the given variable; that includes conflict analysis for infeasible branches and
2833  *  storing of root reduced cost information
2834  */
2835 static
analyzeStrongbranch(SCIP * scip,SCIP_VAR * var,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict)2836 SCIP_RETCODE analyzeStrongbranch(
2837    SCIP*                 scip,               /**< SCIP data structure */
2838    SCIP_VAR*             var,                /**< variable to analyze */
2839    SCIP_Bool*            downinf,            /**< pointer to store whether the downwards branch is infeasible, or NULL */
2840    SCIP_Bool*            upinf,              /**< pointer to store whether the upwards branch is infeasible, or NULL */
2841    SCIP_Bool*            downconflict,       /**< pointer to store whether a conflict constraint was created for an
2842                                               *   infeasible downwards branch, or NULL */
2843    SCIP_Bool*            upconflict          /**< pointer to store whether a conflict constraint was created for an
2844                                               *   infeasible upwards branch, or NULL */
2845    )
2846 {
2847    SCIP_COL* col;
2848    SCIP_Bool downcutoff;
2849    SCIP_Bool upcutoff;
2850 
2851    col = SCIPvarGetCol(var);
2852    assert(col != NULL);
2853 
2854    downcutoff = col->sbdownvalid && SCIPsetIsGE(scip->set, col->sbdown, scip->lp->cutoffbound);
2855    upcutoff = col->sbupvalid && SCIPsetIsGE(scip->set, col->sbup, scip->lp->cutoffbound);
2856 
2857    if( downinf != NULL )
2858       *downinf = downcutoff;
2859    if( upinf != NULL )
2860       *upinf = upcutoff;
2861 
2862    /* analyze infeasible strong branching sub problems:
2863     * because the strong branching's bound change is necessary for infeasibility, it cannot be undone;
2864     * therefore, infeasible strong branchings on non-binary variables will not produce a valid conflict constraint
2865     */
2866    if( scip->set->conf_enable && scip->set->conf_usesb && scip->set->nconflicthdlrs > 0
2867       && SCIPvarIsBinary(var) && SCIPtreeGetCurrentDepth(scip->tree) > 0 )
2868    {
2869       if( (downcutoff && SCIPsetFeasCeil(scip->set, col->primsol-1.0) >= col->lb - 0.5)
2870          || (upcutoff && SCIPsetFeasFloor(scip->set, col->primsol+1.0) <= col->ub + 0.5) )
2871       {
2872          assert(downconflict != NULL);
2873          assert(upconflict   != NULL);
2874          SCIP_CALL( SCIPconflictAnalyzeStrongbranch(scip->conflict, scip->conflictstore, scip->mem->probmem, scip->set, scip->stat,
2875                scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, col, downconflict, upconflict) );
2876       }
2877    }
2878 
2879    /* the strong branching results can be used to strengthen the root reduced cost information which is used for example
2880     * to propagate against the cutoff bound
2881     *
2882     * @note Ignore the results if the LP solution of the down (up) branch LP is smaller which should not happened by
2883     *       theory but can arise due to numerical issues.
2884     */
2885    if( SCIPtreeGetCurrentDepth(scip->tree) == 0 && SCIPvarIsBinary(var) && SCIPlpIsDualReliable(scip->lp) )
2886    {
2887       SCIP_Real lpobjval;
2888 
2889       assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL);
2890 
2891       lpobjval =  SCIPlpGetObjval(scip->lp, scip->set, scip->transprob);
2892 
2893       if( col->sbdownvalid && SCIPsetFeasCeil(scip->set, col->primsol-1.0) >= col->lb - 0.5 && lpobjval < col->sbdown )
2894          SCIPvarUpdateBestRootSol(var, scip->set, SCIPvarGetUbGlobal(var), -(col->sbdown - lpobjval), lpobjval);
2895       if( col->sbupvalid && SCIPsetFeasFloor(scip->set, col->primsol+1.0) <= col->ub + 0.5 && lpobjval < col->sbup )
2896          SCIPvarUpdateBestRootSol(var, scip->set, SCIPvarGetLbGlobal(var), col->sbup - lpobjval,  lpobjval);
2897    }
2898 
2899    return SCIP_OKAY;
2900 }
2901 
2902 /** gets strong branching information on column variable with fractional value
2903  *
2904  *  Before calling this method, the strong branching mode must have been activated by calling SCIPstartStrongbranch();
2905  *  after strong branching was done for all candidate variables, the strong branching mode must be ended by
2906  *  SCIPendStrongbranch(). Since this method does not apply domain propagation before strongbranching,
2907  *  propagation should not be enabled in the SCIPstartStrongbranch() call.
2908  *
2909  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
2910  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
2911  *
2912  *  @pre This method can be called if @p scip is in one of the following stages:
2913  *       - \ref SCIP_STAGE_PRESOLVED
2914  *       - \ref SCIP_STAGE_SOLVING
2915  */
SCIPgetVarStrongbranchFrac(SCIP * scip,SCIP_VAR * var,int itlim,SCIP_Bool idempotent,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict,SCIP_Bool * lperror)2916 SCIP_RETCODE SCIPgetVarStrongbranchFrac(
2917    SCIP*                 scip,               /**< SCIP data structure */
2918    SCIP_VAR*             var,                /**< variable to get strong branching values for */
2919    int                   itlim,              /**< iteration limit for strong branchings */
2920    SCIP_Bool             idempotent,         /**< should scip's state remain the same after the call (statistics, column states...), or should it be updated ? */
2921    SCIP_Real*            down,               /**< stores dual bound after branching column down */
2922    SCIP_Real*            up,                 /**< stores dual bound after branching column up */
2923    SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
2924                                               *   otherwise, it can only be used as an estimate value */
2925    SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
2926                                               *   otherwise, it can only be used as an estimate value */
2927    SCIP_Bool*            downinf,            /**< pointer to store whether the downwards branch is infeasible, or NULL */
2928    SCIP_Bool*            upinf,              /**< pointer to store whether the upwards branch is infeasible, or NULL */
2929    SCIP_Bool*            downconflict,       /**< pointer to store whether a conflict constraint was created for an
2930                                               *   infeasible downwards branch, or NULL */
2931    SCIP_Bool*            upconflict,         /**< pointer to store whether a conflict constraint was created for an
2932                                               *   infeasible upwards branch, or NULL */
2933    SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred or the
2934                                               *   solving process should be stopped (e.g., due to a time limit) */
2935    )
2936 {
2937    SCIP_COL* col;
2938    SCIP_Real localdown;
2939    SCIP_Real localup;
2940    SCIP_Bool localdownvalid;
2941    SCIP_Bool localupvalid;
2942 
2943    assert(scip != NULL);
2944    assert(var != NULL);
2945    assert(lperror != NULL);
2946    assert(!SCIPtreeProbing(scip->tree)); /* we should not be in strong branching with propagation mode */
2947    assert(var->scip == scip);
2948 
2949    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchFrac", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2950 
2951    if( downvalid != NULL )
2952       *downvalid = FALSE;
2953    if( upvalid != NULL )
2954       *upvalid = FALSE;
2955    if( downinf != NULL )
2956       *downinf = FALSE;
2957    if( upinf != NULL )
2958       *upinf = FALSE;
2959    if( downconflict != NULL )
2960       *downconflict = FALSE;
2961    if( upconflict != NULL )
2962       *upconflict = FALSE;
2963 
2964    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
2965    {
2966       SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
2967       return SCIP_INVALIDDATA;
2968    }
2969 
2970    col = SCIPvarGetCol(var);
2971    assert(col != NULL);
2972 
2973    if( !SCIPcolIsInLP(col) )
2974    {
2975       SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
2976       return SCIP_INVALIDDATA;
2977    }
2978 
2979    /* check if the solving process should be aborted */
2980    if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
2981    {
2982       /* mark this as if the LP failed */
2983       *lperror = TRUE;
2984       return SCIP_OKAY;
2985    }
2986 
2987    /* call strong branching for column with fractional value */
2988    SCIP_CALL( SCIPcolGetStrongbranch(col, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent,
2989          &localdown, &localup, &localdownvalid, &localupvalid, lperror) );
2990 
2991    /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
2992     * declare the sub nodes infeasible
2993     */
2994    if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
2995    {
2996       if( !idempotent ) /*lint !e774*/
2997       {
2998          SCIP_CALL( analyzeStrongbranch(scip, var, downinf, upinf, downconflict, upconflict) );
2999       }
3000       else
3001       {
3002          if( downinf != NULL )
3003             *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound);
3004          if( upinf != NULL )
3005             *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound);
3006       }
3007    }
3008 
3009    if( down != NULL )
3010       *down = localdown;
3011    if( up != NULL )
3012       *up = localup;
3013    if( downvalid != NULL )
3014       *downvalid = localdownvalid;
3015    if( upvalid != NULL )
3016       *upvalid = localupvalid;
3017 
3018    return SCIP_OKAY;
3019 }
3020 
3021 /** create, solve, and evaluate a single strong branching child (for strong branching with propagation) */
3022 static
performStrongbranchWithPropagation(SCIP * scip,SCIP_VAR * var,SCIP_Bool down,SCIP_Bool firstchild,SCIP_Bool propagate,SCIP_Real newbound,int itlim,int maxproprounds,SCIP_Real * value,SCIP_Bool * valid,SCIP_Longint * ndomreductions,SCIP_Bool * conflict,SCIP_Bool * lperror,SCIP_VAR ** vars,int nvars,SCIP_Real * newlbs,SCIP_Real * newubs,SCIP_Bool * foundsol,SCIP_Bool * cutoff)3023 SCIP_RETCODE performStrongbranchWithPropagation(
3024    SCIP*                 scip,               /**< SCIP data structure */
3025    SCIP_VAR*             var,                /**< variable to get strong branching values for */
3026    SCIP_Bool             down,               /**< do we regard the down child? */
3027    SCIP_Bool             firstchild,         /**< is this the first of the two strong branching children? */
3028    SCIP_Bool             propagate,          /**< should domain propagation be performed? */
3029    SCIP_Real             newbound,           /**< new bound to apply at the strong branching child */
3030    int                   itlim,              /**< iteration limit for strong branchings */
3031    int                   maxproprounds,      /**< maximum number of propagation rounds (-1: no limit, -2: parameter
3032                                               *   settings) */
3033    SCIP_Real*            value,              /**< stores dual bound for strong branching child */
3034    SCIP_Bool*            valid,              /**< stores whether the returned value is a valid dual bound, or NULL;
3035                                               *   otherwise, it can only be used as an estimate value */
3036    SCIP_Longint*         ndomreductions,     /**< pointer to store the number of domain reductions found, or NULL */
3037    SCIP_Bool*            conflict,           /**< pointer to store whether a conflict constraint was created for an
3038                                               *   infeasible strong branching child, or NULL */
3039    SCIP_Bool*            lperror,            /**< pointer to store whether an unresolved LP error occurred or the
3040                                               *   solving process should be stopped (e.g., due to a time limit) */
3041    SCIP_VAR**            vars,               /**< active problem variables */
3042    int                   nvars,              /**< number of active problem variables */
3043    SCIP_Real*            newlbs,             /**< array to store valid lower bounds for all active variables, or NULL */
3044    SCIP_Real*            newubs,             /**< array to store valid upper bounds for all active variables, or NULL */
3045    SCIP_Bool*            foundsol,           /**< pointer to store whether a primal solution was found during strong branching */
3046    SCIP_Bool*            cutoff              /**< pointer to store whether the strong branching child is infeasible */
3047    )
3048 {
3049    SCIP_Longint ndomreds;
3050 
3051    assert(value != NULL);
3052    assert(foundsol != NULL);
3053    assert(cutoff != NULL);
3054    assert(lperror != NULL);
3055    assert(valid != NULL ? !(*valid) : TRUE);
3056 
3057    *foundsol = FALSE;
3058    *cutoff = FALSE;
3059    *lperror = FALSE;
3060 
3061    /* check whether the strong branching child is already infeasible due to the bound change */
3062    if( down )
3063    {
3064       /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the
3065        * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3066        * are valid for and were already applied at the probing root
3067        */
3068       if( newbound < SCIPvarGetLbLocal(var) - 0.5 )
3069       {
3070          *value = SCIPinfinity(scip);
3071 
3072          if( valid != NULL )
3073             *valid = TRUE;
3074 
3075          /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3076          if( conflict != NULL )
3077             *conflict = TRUE;
3078 
3079          *cutoff = TRUE;
3080 
3081          return SCIP_OKAY;
3082       }
3083    }
3084    else
3085    {
3086       /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the
3087        * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3088        * are valid for and were already applied at the probing root
3089        */
3090       if( newbound > SCIPvarGetUbLocal(var) + 0.5 )
3091       {
3092          *value = SCIPinfinity(scip);
3093 
3094          if( valid != NULL )
3095             *valid = TRUE;
3096 
3097          /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3098          if( conflict != NULL )
3099             *conflict = TRUE;
3100 
3101          *cutoff = TRUE;
3102 
3103          return SCIP_OKAY;
3104       }
3105    }
3106 
3107    /* we need to ensure that we can create at least one new probing node without exceeding the maximal tree depth */
3108    if( SCIP_MAXTREEDEPTH > SCIPtreeGetProbingDepth(scip->tree) )
3109    {
3110       /* create a new probing node for the strong branching child and apply the new bound for the variable */
3111       SCIP_CALL( SCIPnewProbingNode(scip) );
3112 
3113       if( down )
3114       {
3115          assert(SCIPisGE(scip, newbound, SCIPvarGetLbLocal(var)));
3116          if( SCIPisLT(scip, newbound, SCIPvarGetUbLocal(var)) )
3117          {
3118             SCIP_CALL( SCIPchgVarUbProbing(scip, var, newbound) );
3119          }
3120       }
3121       else
3122       {
3123          assert(SCIPisLE(scip, newbound, SCIPvarGetUbLocal(var)));
3124          if( SCIPisGT(scip, newbound, SCIPvarGetLbLocal(var)) )
3125          {
3126             SCIP_CALL( SCIPchgVarLbProbing(scip, var, newbound) );
3127          }
3128       }
3129    }
3130    else
3131    {
3132       if( valid != NULL )
3133          *valid = FALSE;
3134 
3135       *cutoff = FALSE;
3136 
3137       if( conflict != NULL )
3138          *conflict = FALSE;
3139 
3140       return SCIP_OKAY;
3141    }
3142 
3143    /* propagate domains at the probing node */
3144    if( propagate )
3145    {
3146       /* start time measuring */
3147       SCIPclockStart(scip->stat->strongpropclock, scip->set);
3148 
3149       ndomreds = 0;
3150       SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, cutoff, &ndomreds) );
3151 
3152       /* store number of domain reductions in strong branching */
3153       if( down )
3154          SCIPstatAdd(scip->stat, scip->set, nsbdowndomchgs, ndomreds);
3155       else
3156          SCIPstatAdd(scip->stat, scip->set, nsbupdomchgs, ndomreds);
3157 
3158       if( ndomreductions != NULL )
3159          *ndomreductions = ndomreds;
3160 
3161       /* stop time measuring */
3162       SCIPclockStop(scip->stat->strongpropclock, scip->set);
3163 
3164       if( *cutoff )
3165       {
3166          *value = SCIPinfinity(scip);
3167 
3168          if( valid != NULL )
3169             *valid = TRUE;
3170 
3171          SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible during propagation\n",
3172             down ? "down" : "up", SCIPvarGetName(var));
3173       }
3174    }
3175 
3176    /* if propagation did not already detect infeasibility, solve the probing LP */
3177    if( !(*cutoff) )
3178    {
3179       SCIP_CALL( SCIPsolveProbingLP(scip, itlim, lperror, cutoff) );
3180       assert(SCIPisLPRelax(scip));
3181 
3182       if( *cutoff )
3183       {
3184          assert(!(*lperror));
3185 
3186          *value = SCIPinfinity(scip);
3187 
3188          if( valid != NULL )
3189             *valid = TRUE;
3190 
3191          SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible in LP solving: status=%d\n",
3192             down ? "down" : "up", SCIPvarGetName(var), SCIPgetLPSolstat(scip));
3193       }
3194       else if( !(*lperror) )
3195       {
3196          /* save the lp solution status */
3197          scip->stat->lastsblpsolstats[down ? 0 : 1] = SCIPgetLPSolstat(scip);
3198 
3199          switch( SCIPgetLPSolstat(scip) )
3200          {
3201          case SCIP_LPSOLSTAT_OPTIMAL:
3202          {
3203             *value = SCIPgetLPObjval(scip);
3204             assert(SCIPisLT(scip, *value, SCIPgetCutoffbound(scip)));
3205 
3206             SCIPdebugMsg(scip, "probing LP solved to optimality, objective value: %16.9g\n", *value);
3207 
3208             if( valid != NULL )
3209                *valid = TRUE;
3210 
3211             /* check the strong branching LP solution for feasibility */
3212             SCIP_CALL( SCIPtryStrongbranchLPSol(scip, foundsol, cutoff) );
3213             break;
3214          }
3215          case SCIP_LPSOLSTAT_ITERLIMIT:
3216             ++scip->stat->nsbtimesiterlimhit;
3217             /*lint -fallthrough*/
3218          case SCIP_LPSOLSTAT_TIMELIMIT:
3219          {
3220             /* use LP value as estimate */
3221             SCIP_LPI* lpi;
3222             SCIP_Real objval;
3223             SCIP_Real looseobjval;
3224 
3225             SCIPdebugMsg(scip, "probing LP hit %s limit\n", SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_ITERLIMIT ? "iteration" : "time");
3226 
3227             /* we access the LPI directly, because when a time limit was hit, we cannot access objective value and dual
3228              * feasibility using the SCIPlp... methods; we should try to avoid direct calls to the LPI, but this is rather
3229              * uncritical here, because we are immediately after the SCIPsolveProbingLP() call, because we access the LPI
3230              * read-only, and we check SCIPlpiWasSolved() first
3231              */
3232             SCIP_CALL( SCIPgetLPI(scip, &lpi) );
3233 
3234             if( SCIPlpiWasSolved(lpi) )
3235             {
3236                SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
3237                looseobjval = SCIPlpGetLooseObjval(scip->lp, scip->set, scip->transprob);
3238 
3239                /* the infinity value in the LPI should not be smaller than SCIP's infinity value */
3240                assert(!SCIPlpiIsInfinity(lpi, objval) || SCIPisInfinity(scip, objval));
3241 
3242                /* we use SCIP's infinity value here because a value larger than this is counted as infeasible by SCIP */
3243                if( SCIPisInfinity(scip, objval) )
3244                   *value = SCIPinfinity(scip);
3245                else if( SCIPisInfinity(scip, -looseobjval) )
3246                   *value = -SCIPinfinity(scip);
3247                else
3248                   *value = objval + looseobjval;
3249 
3250                if( SCIPlpiIsDualFeasible(lpi) )
3251                {
3252                   if( valid != NULL )
3253                      *valid = TRUE;
3254 
3255                   if( SCIPisGE(scip, *value, SCIPgetCutoffbound(scip)) )
3256                      *cutoff = TRUE;
3257                }
3258             }
3259             break;
3260          }
3261          case SCIP_LPSOLSTAT_ERROR:
3262          case SCIP_LPSOLSTAT_UNBOUNDEDRAY:
3263             *lperror = TRUE;
3264             break;
3265          case SCIP_LPSOLSTAT_NOTSOLVED: /* should only be the case for *cutoff = TRUE or *lperror = TRUE */
3266          case SCIP_LPSOLSTAT_OBJLIMIT: /* in this case, *cutoff should be TRUE and we should not get here */
3267          case SCIP_LPSOLSTAT_INFEASIBLE: /* in this case, *cutoff should be TRUE and we should not get here */
3268          default:
3269             SCIPerrorMessage("invalid LP solution status <%d>\n", SCIPgetLPSolstat(scip));
3270             return SCIP_INVALIDDATA;
3271          }  /*lint !e788*/
3272       }
3273 
3274       /* If columns are missing in the LP, the cutoff flag may be wrong. Therefore, we need to set it and the valid pointer
3275        * to false here.
3276        */
3277       if( (*cutoff) && !SCIPallColsInLP(scip) )
3278       {
3279          *cutoff = FALSE;
3280       }
3281 
3282 #ifndef NDEBUG
3283       if( *lperror )
3284       {
3285          SCIPdebugMsg(scip, "error during strong branching probing LP solving: status=%d\n", SCIPgetLPSolstat(scip));
3286       }
3287 #endif
3288    }
3289 
3290    /* if the subproblem was feasible, we store the local bounds of the variables after propagation and (possibly)
3291     * conflict analysis
3292     * @todo do this after propagation? should be able to get valid bounds more often, but they might be weaker
3293     */
3294    if( !(*cutoff) && newlbs != NULL)
3295    {
3296       int v;
3297 
3298       assert(newubs != NULL);
3299 
3300       /* initialize the newlbs and newubs to the current local bounds */
3301       if( firstchild )
3302       {
3303          for( v = 0; v < nvars; ++v )
3304          {
3305             newlbs[v] = SCIPvarGetLbLocal(vars[v]);
3306             newubs[v] = SCIPvarGetUbLocal(vars[v]);
3307          }
3308       }
3309       /* update newlbs and newubs: take the weaker of the already stored bounds and the current local bounds */
3310       else
3311       {
3312          for( v = 0; v < nvars; ++v )
3313          {
3314             SCIP_Real lb = SCIPvarGetLbLocal(vars[v]);
3315             SCIP_Real ub = SCIPvarGetUbLocal(vars[v]);
3316 
3317             newlbs[v] = MIN(newlbs[v], lb);
3318             newubs[v] = MAX(newubs[v], ub);
3319          }
3320       }
3321    }
3322 
3323    /* revert all changes at the probing node */
3324    SCIP_CALL( SCIPbacktrackProbing(scip, 0) );
3325 
3326    return SCIP_OKAY;
3327 }
3328 
3329 /** gets strong branching information with previous domain propagation on column variable
3330  *
3331  *  Before calling this method, the strong branching mode must have been activated by calling SCIPstartStrongbranch();
3332  *  after strong branching was done for all candidate variables, the strong branching mode must be ended by
3333  *  SCIPendStrongbranch(). Since this method applies domain propagation before strongbranching, propagation has to be be
3334  *  enabled in the SCIPstartStrongbranch() call.
3335  *
3336  *  Before solving the strong branching LP, domain propagation can be performed. The number of propagation rounds
3337  *  can be specified by the parameter @p maxproprounds.
3338  *
3339  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3340  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3341  *
3342  *  @pre This method can be called if @p scip is in one of the following stages:
3343  *       - \ref SCIP_STAGE_PRESOLVED
3344  *       - \ref SCIP_STAGE_SOLVING
3345  *
3346  *  @warning When using this method, LP banching candidates and solution values must be copied beforehand, because
3347  *           they are updated w.r.t. the strong branching LP solution.
3348  */
SCIPgetVarStrongbranchWithPropagation(SCIP * scip,SCIP_VAR * var,SCIP_Real solval,SCIP_Real lpobjval,int itlim,int maxproprounds,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Longint * ndomredsdown,SCIP_Longint * ndomredsup,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict,SCIP_Bool * lperror,SCIP_Real * newlbs,SCIP_Real * newubs)3349 SCIP_RETCODE SCIPgetVarStrongbranchWithPropagation(
3350    SCIP*                 scip,               /**< SCIP data structure */
3351    SCIP_VAR*             var,                /**< variable to get strong branching values for */
3352    SCIP_Real             solval,             /**< value of the variable in the current LP solution */
3353    SCIP_Real             lpobjval,           /**< LP objective value of the current LP solution */
3354    int                   itlim,              /**< iteration limit for strong branchings */
3355    int                   maxproprounds,      /**< maximum number of propagation rounds (-1: no limit, -2: parameter
3356                                               *   settings) */
3357    SCIP_Real*            down,               /**< stores dual bound after branching column down */
3358    SCIP_Real*            up,                 /**< stores dual bound after branching column up */
3359    SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
3360                                               *   otherwise, it can only be used as an estimate value */
3361    SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
3362                                               *   otherwise, it can only be used as an estimate value */
3363    SCIP_Longint*         ndomredsdown,       /**< pointer to store the number of domain reductions down, or NULL */
3364    SCIP_Longint*         ndomredsup,         /**< pointer to store the number of domain reductions up, or NULL */
3365    SCIP_Bool*            downinf,            /**< pointer to store whether the downwards branch is infeasible, or NULL */
3366    SCIP_Bool*            upinf,              /**< pointer to store whether the upwards branch is infeasible, or NULL */
3367    SCIP_Bool*            downconflict,       /**< pointer to store whether a conflict constraint was created for an
3368                                               *   infeasible downwards branch, or NULL */
3369    SCIP_Bool*            upconflict,         /**< pointer to store whether a conflict constraint was created for an
3370                                               *   infeasible upwards branch, or NULL */
3371    SCIP_Bool*            lperror,            /**< pointer to store whether an unresolved LP error occurred or the
3372                                               *   solving process should be stopped (e.g., due to a time limit) */
3373    SCIP_Real*            newlbs,             /**< array to store valid lower bounds for all active variables, or NULL */
3374    SCIP_Real*            newubs              /**< array to store valid upper bounds for all active variables, or NULL */
3375    )
3376 {
3377    SCIP_COL* col;
3378    SCIP_VAR** vars;
3379    SCIP_Longint oldniters;
3380    SCIP_Real newub;
3381    SCIP_Real newlb;
3382    SCIP_Bool propagate;
3383    SCIP_Bool cutoff;
3384    SCIP_Bool downchild;
3385    SCIP_Bool firstchild;
3386    SCIP_Bool foundsol;
3387    SCIP_Bool downvalidlocal;
3388    SCIP_Bool upvalidlocal;
3389    SCIP_Bool allcolsinlp;
3390    SCIP_Bool enabledconflict;
3391    int oldnconflicts;
3392    int nvars;
3393 
3394    assert(scip != NULL);
3395    assert(var != NULL);
3396    assert(SCIPvarIsIntegral(var));
3397    assert(down != NULL);
3398    assert(up != NULL);
3399    assert(lperror != NULL);
3400    assert((newlbs != NULL) == (newubs != NULL));
3401    assert(SCIPinProbing(scip));
3402    assert(var->scip == scip);
3403 
3404    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchWithPropagation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3405 
3406    /* check whether propagation should be performed */
3407    propagate = (maxproprounds != 0 && maxproprounds != -3);
3408 
3409    /* Check, if all existing columns are in LP.
3410     * If this is not the case, we may still return that the up and down dual bounds are valid, because the branching
3411     * rule should not apply them otherwise.
3412     * However, we must not set the downinf or upinf pointers to TRUE based on the dual bound, because we cannot
3413     * guarantee that this node can be cut off.
3414     */
3415    allcolsinlp = SCIPallColsInLP(scip);
3416 
3417    /* if maxproprounds is -2, change it to 0, which for the following calls means using the parameter settings */
3418    if( maxproprounds == -2 )
3419       maxproprounds = 0;
3420 
3421    *down = lpobjval;
3422    *up = lpobjval;
3423    if( downvalid != NULL )
3424       *downvalid = FALSE;
3425    if( upvalid != NULL )
3426       *upvalid = FALSE;
3427    if( downinf != NULL )
3428       *downinf = FALSE;
3429    if( upinf != NULL )
3430       *upinf = FALSE;
3431    if( downconflict != NULL )
3432       *downconflict = FALSE;
3433    if( upconflict != NULL )
3434       *upconflict = FALSE;
3435    if( ndomredsdown != NULL )
3436       *ndomredsdown = 0;
3437    if( ndomredsup != NULL )
3438       *ndomredsup = 0;
3439 
3440    *lperror = FALSE;
3441 
3442    vars = SCIPgetVars(scip);
3443    nvars = SCIPgetNVars(scip);
3444 
3445    scip->stat->lastsblpsolstats[0] = scip->stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED;
3446 
3447    /* check if the solving process should be aborted */
3448    if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3449    {
3450       /* mark this as if the LP failed */
3451       *lperror = TRUE;
3452       return SCIP_OKAY;
3453    }
3454 
3455    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
3456    {
3457       SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3458       return SCIP_INVALIDDATA;
3459    }
3460 
3461    col = SCIPvarGetCol(var);
3462    assert(col != NULL);
3463 
3464    if( !SCIPcolIsInLP(col) )
3465    {
3466       SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3467       return SCIP_INVALIDDATA;
3468    }
3469 
3470    newlb = SCIPfeasFloor(scip, solval + 1.0);
3471    newub = SCIPfeasCeil(scip, solval - 1.0);
3472 
3473    SCIPdebugMsg(scip, "strong branching on var <%s>: solval=%g, lb=%g, ub=%g\n", SCIPvarGetName(var), solval,
3474       SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
3475 
3476    /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the
3477     * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3478     * are valid for and were already applied at the probing root
3479     */
3480    if( newlb > SCIPvarGetUbLocal(var) + 0.5 )
3481    {
3482       *up = SCIPinfinity(scip);
3483 
3484       if( upinf != NULL )
3485          *upinf = TRUE;
3486 
3487       if( upvalid != NULL )
3488          *upvalid = TRUE;
3489 
3490       /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3491       if( upconflict != NULL )
3492          *upconflict = TRUE;
3493 
3494       SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3495          *down, *up, FALSE, TRUE, 0LL, INT_MAX);
3496 
3497       /* we do not regard the down branch; its valid pointer stays set to FALSE */
3498       return SCIP_OKAY;
3499    }
3500 
3501    /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the
3502     * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3503     * are valid for and were already applied at the probing root
3504     */
3505    if( newub < SCIPvarGetLbLocal(var) - 0.5 )
3506    {
3507       *down = SCIPinfinity(scip);
3508 
3509       if( downinf != NULL )
3510          *downinf = TRUE;
3511 
3512       if( downvalid != NULL )
3513          *downvalid = TRUE;
3514 
3515       /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3516       if( downconflict != NULL )
3517          *downconflict = TRUE;
3518 
3519       SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3520          *down, *up, TRUE, FALSE, 0LL, INT_MAX);
3521 
3522       /* we do not regard the up branch; its valid pointer stays set to FALSE */
3523       return SCIP_OKAY;
3524    }
3525 
3526    /* We now do strong branching by creating the two potential child nodes as probing nodes and solving them one after
3527     * the other. We will stop when the first child is detected infeasible, saving the effort we would need for the
3528     * second child. Since empirically, the up child tends to be infeasible more often, we do strongbranching first on
3529     * the up branch.
3530     */
3531    oldniters = scip->stat->nsbdivinglpiterations;
3532    firstchild = TRUE;
3533    cutoff = FALSE;
3534 
3535    /* switch conflict analysis according to usesb parameter */
3536    enabledconflict = scip->set->conf_enable;
3537    scip->set->conf_enable = (scip->set->conf_enable && scip->set->conf_usesb);
3538 
3539    /* @todo: decide the branch to look at first based on the cutoffs in previous calls? */
3540    downchild = SCIPisStrongbranchDownFirst(scip, var);
3541 
3542    downvalidlocal = FALSE;
3543    upvalidlocal = FALSE;
3544 
3545    do
3546    {
3547       oldnconflicts = SCIPconflictGetNConflicts(scip->conflict);
3548 
3549       if( downchild )
3550       {
3551          SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild, propagate, newub, itlim, maxproprounds,
3552                down, &downvalidlocal, ndomredsdown, downconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) );
3553 
3554          /* check whether a new solutions rendered the previous child infeasible */
3555          if( foundsol && !firstchild && allcolsinlp )
3556          {
3557             if( SCIPisGE(scip, *up, SCIPgetCutoffbound(scip)) )
3558             {
3559                if( upinf != NULL )
3560                   *upinf = TRUE;
3561             }
3562          }
3563 
3564          /* check for infeasibility */
3565          if( cutoff )
3566          {
3567             if( downinf != NULL )
3568                *downinf = TRUE;
3569 
3570             if( downconflict != NULL &&
3571                (SCIPvarGetLbLocal(var) > newub + 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts) )
3572             {
3573                *downconflict = TRUE;
3574             }
3575 
3576             if( !scip->set->branch_forceall )
3577             {
3578                /* if this is the first call, we do not regard the up branch, its valid pointer is initially set to FALSE */
3579                break;
3580             }
3581          }
3582       }
3583       else
3584       {
3585          SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild, propagate, newlb, itlim, maxproprounds,
3586                up, &upvalidlocal, ndomredsup, upconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) );
3587 
3588          /* check whether a new solutions rendered the previous child infeasible */
3589          if( foundsol && !firstchild && allcolsinlp )
3590          {
3591             if( SCIPisGE(scip, *down, SCIPgetCutoffbound(scip)) )
3592             {
3593                if( downinf != NULL )
3594                   *downinf = TRUE;
3595             }
3596          }
3597 
3598          /* check for infeasibility */
3599          if( cutoff )
3600          {
3601             if( upinf != NULL )
3602                *upinf = TRUE;
3603 
3604             assert(upinf == NULL || (*upinf) == TRUE);
3605 
3606             if( upconflict != NULL &&
3607                (SCIPvarGetUbLocal(var) < newlb - 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts) )
3608             {
3609                *upconflict = TRUE;
3610             }
3611 
3612             if( !scip->set->branch_forceall )
3613             {
3614                /* if this is the first call, we do not regard the down branch, its valid pointer is initially set to FALSE */
3615                break;
3616             }
3617          }
3618       }
3619 
3620       downchild = !downchild;
3621       firstchild = !firstchild;
3622    }
3623    while( !firstchild );
3624 
3625    /* set strong branching information in column */
3626    if( *lperror )
3627    {
3628       SCIPcolInvalidateStrongbranchData(col, scip->set, scip->stat, scip->lp);
3629    }
3630    else
3631    {
3632       SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3633          *down, *up, downvalidlocal, upvalidlocal, scip->stat->nsbdivinglpiterations - oldniters, itlim);
3634    }
3635 
3636    if( downvalid != NULL )
3637       *downvalid = downvalidlocal;
3638    if( upvalid != NULL )
3639       *upvalid = upvalidlocal;
3640 
3641    scip->set->conf_enable = enabledconflict;
3642 
3643    return SCIP_OKAY;   /*lint !e438*/
3644 }
3645 
3646 /** gets strong branching information on column variable x with integral LP solution value (val); that is, the down branch
3647  *  is (val -1.0) and the up brach ins (val +1.0)
3648  *
3649  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3650  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3651  *
3652  *  @pre This method can be called if @p scip is in one of the following stages:
3653  *       - \ref SCIP_STAGE_PRESOLVED
3654  *       - \ref SCIP_STAGE_SOLVING
3655  *
3656  *  @note If the integral LP solution value is the lower or upper bound of the variable, the corresponding branch will be
3657  *        marked as infeasible. That is, the valid pointer and the infeasible pointer are set to TRUE.
3658  */
SCIPgetVarStrongbranchInt(SCIP * scip,SCIP_VAR * var,int itlim,SCIP_Bool idempotent,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict,SCIP_Bool * lperror)3659 SCIP_RETCODE SCIPgetVarStrongbranchInt(
3660    SCIP*                 scip,               /**< SCIP data structure */
3661    SCIP_VAR*             var,                /**< variable to get strong branching values for */
3662    int                   itlim,              /**< iteration limit for strong branchings */
3663    SCIP_Bool             idempotent,         /**< should scip's state remain the same after the call (statistics, column states...), or should it be updated ? */
3664    SCIP_Real*            down,               /**< stores dual bound after branching column down */
3665    SCIP_Real*            up,                 /**< stores dual bound after branching column up */
3666    SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
3667                                               *   otherwise, it can only be used as an estimate value */
3668    SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
3669                                               *   otherwise, it can only be used as an estimate value */
3670    SCIP_Bool*            downinf,            /**< pointer to store whether the downwards branch is infeasible, or NULL */
3671    SCIP_Bool*            upinf,              /**< pointer to store whether the upwards branch is infeasible, or NULL */
3672    SCIP_Bool*            downconflict,       /**< pointer to store whether a conflict constraint was created for an
3673                                               *   infeasible downwards branch, or NULL */
3674    SCIP_Bool*            upconflict,         /**< pointer to store whether a conflict constraint was created for an
3675                                               *   infeasible upwards branch, or NULL */
3676    SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred or the
3677                                               *   solving process should be stopped (e.g., due to a time limit) */
3678    )
3679 {
3680    SCIP_COL* col;
3681    SCIP_Real localdown;
3682    SCIP_Real localup;
3683    SCIP_Bool localdownvalid;
3684    SCIP_Bool localupvalid;
3685 
3686    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3687 
3688    assert(lperror != NULL);
3689    assert(var->scip == scip);
3690 
3691    if( downvalid != NULL )
3692       *downvalid = FALSE;
3693    if( upvalid != NULL )
3694       *upvalid = FALSE;
3695    if( downinf != NULL )
3696       *downinf = FALSE;
3697    if( upinf != NULL )
3698       *upinf = FALSE;
3699    if( downconflict != NULL )
3700       *downconflict = FALSE;
3701    if( upconflict != NULL )
3702       *upconflict = FALSE;
3703 
3704    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
3705    {
3706       SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3707       return SCIP_INVALIDDATA;
3708    }
3709 
3710    col = SCIPvarGetCol(var);
3711    assert(col != NULL);
3712 
3713    if( !SCIPcolIsInLP(col) )
3714    {
3715       SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3716       return SCIP_INVALIDDATA;
3717    }
3718 
3719    /* check if the solving process should be aborted */
3720    if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3721    {
3722       /* mark this as if the LP failed */
3723       *lperror = TRUE;
3724       return SCIP_OKAY;
3725    }
3726 
3727    /* call strong branching for column */
3728    SCIP_CALL( SCIPcolGetStrongbranch(col, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent,
3729          &localdown, &localup, &localdownvalid, &localupvalid, lperror) );
3730 
3731    /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3732     * declare the sub nodes infeasible
3733     */
3734    if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3735    {
3736       if( !idempotent ) /*lint !e774*/
3737       {
3738          SCIP_CALL( analyzeStrongbranch(scip, var, downinf, upinf, downconflict, upconflict) );
3739       }
3740       else
3741       {
3742          if( downinf != NULL )
3743             *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound);
3744          if( upinf != NULL )
3745             *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound);
3746       }
3747    }
3748 
3749    if( down != NULL )
3750       *down = localdown;
3751    if( up != NULL )
3752       *up = localup;
3753    if( downvalid != NULL )
3754       *downvalid = localdownvalid;
3755    if( upvalid != NULL )
3756       *upvalid = localupvalid;
3757 
3758    return SCIP_OKAY;
3759 }
3760 
3761 /** gets strong branching information on column variables with fractional values
3762  *
3763  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3764  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3765  *
3766  *  @pre This method can be called if @p scip is in one of the following stages:
3767  *       - \ref SCIP_STAGE_PRESOLVED
3768  *       - \ref SCIP_STAGE_SOLVING
3769  */
SCIPgetVarsStrongbranchesFrac(SCIP * scip,SCIP_VAR ** vars,int nvars,int itlim,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict,SCIP_Bool * lperror)3770 SCIP_RETCODE SCIPgetVarsStrongbranchesFrac(
3771    SCIP*                 scip,               /**< SCIP data structure */
3772    SCIP_VAR**            vars,               /**< variables to get strong branching values for */
3773    int                   nvars,              /**< number of variables */
3774    int                   itlim,              /**< iteration limit for strong branchings */
3775    SCIP_Real*            down,               /**< stores dual bounds after branching variables down */
3776    SCIP_Real*            up,                 /**< stores dual bounds after branching variables up */
3777    SCIP_Bool*            downvalid,          /**< stores whether the returned down values are valid dual bounds, or NULL;
3778                                               *   otherwise, they can only be used as an estimate value */
3779    SCIP_Bool*            upvalid,            /**< stores whether the returned up values are valid dual bounds, or NULL;
3780                                               *   otherwise, they can only be used as an estimate value */
3781    SCIP_Bool*            downinf,            /**< array to store whether the downward branches are infeasible, or NULL */
3782    SCIP_Bool*            upinf,              /**< array to store whether the upward branches are infeasible, or NULL */
3783    SCIP_Bool*            downconflict,       /**< array to store whether conflict constraints were created for
3784                                               *   infeasible downward branches, or NULL */
3785    SCIP_Bool*            upconflict,         /**< array to store whether conflict constraints were created for
3786                                               *   infeasible upward branches, or NULL */
3787    SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred or the
3788                                               *   solving process should be stopped (e.g., due to a time limit) */
3789    )
3790 {
3791    SCIP_COL** cols;
3792    int j;
3793 
3794    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesFrac", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3795 
3796    assert( lperror != NULL );
3797    assert( vars != NULL );
3798 
3799    /* set up data */
3800    cols = NULL;
3801    SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) );
3802    assert(cols != NULL);
3803    for( j = 0; j < nvars; ++j )
3804    {
3805       SCIP_VAR* var;
3806       SCIP_COL* col;
3807 
3808       if( downvalid != NULL )
3809          downvalid[j] = FALSE;
3810       if( upvalid != NULL )
3811          upvalid[j] = FALSE;
3812       if( downinf != NULL )
3813          downinf[j] = FALSE;
3814       if( upinf != NULL )
3815          upinf[j] = FALSE;
3816       if( downconflict != NULL )
3817          downconflict[j] = FALSE;
3818       if( upconflict != NULL )
3819          upconflict[j] = FALSE;
3820 
3821       var = vars[j];
3822       assert( var != NULL );
3823       if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
3824       {
3825          SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3826          SCIPfreeBufferArray(scip, &cols);
3827          return SCIP_INVALIDDATA;
3828       }
3829 
3830       col = SCIPvarGetCol(var);
3831       assert(col != NULL);
3832       cols[j] = col;
3833 
3834       if( !SCIPcolIsInLP(col) )
3835       {
3836          SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3837          SCIPfreeBufferArray(scip, &cols);
3838          return SCIP_INVALIDDATA;
3839       }
3840    }
3841 
3842    /* check if the solving process should be aborted */
3843    if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3844    {
3845       /* mark this as if the LP failed */
3846       *lperror = TRUE;
3847    }
3848    else
3849    {
3850       /* call strong branching for columns with fractional value */
3851       SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim,
3852             down, up, downvalid, upvalid, lperror) );
3853 
3854       /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3855        * declare the sub nodes infeasible
3856        */
3857       if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3858       {
3859          for( j = 0; j < nvars; ++j )
3860          {
3861             SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL,
3862                   (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL,
3863                   (upconflict != NULL) ? (&(upconflict[j])) : NULL) );
3864          }
3865       }
3866    }
3867    SCIPfreeBufferArray(scip, &cols);
3868 
3869    return SCIP_OKAY;
3870 }
3871 
3872 /** gets strong branching information on column variables with integral values
3873  *
3874  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3875  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3876  *
3877  *  @pre This method can be called if @p scip is in one of the following stages:
3878  *       - \ref SCIP_STAGE_PRESOLVED
3879  *       - \ref SCIP_STAGE_SOLVING
3880  */
SCIPgetVarsStrongbranchesInt(SCIP * scip,SCIP_VAR ** vars,int nvars,int itlim,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Bool * downinf,SCIP_Bool * upinf,SCIP_Bool * downconflict,SCIP_Bool * upconflict,SCIP_Bool * lperror)3881 SCIP_RETCODE SCIPgetVarsStrongbranchesInt(
3882    SCIP*                 scip,               /**< SCIP data structure */
3883    SCIP_VAR**            vars,               /**< variables to get strong branching values for */
3884    int                   nvars,              /**< number of variables */
3885    int                   itlim,              /**< iteration limit for strong branchings */
3886    SCIP_Real*            down,               /**< stores dual bounds after branching variables down */
3887    SCIP_Real*            up,                 /**< stores dual bounds after branching variables up */
3888    SCIP_Bool*            downvalid,          /**< stores whether the returned down values are valid dual bounds, or NULL;
3889                                               *   otherwise, they can only be used as an estimate value */
3890    SCIP_Bool*            upvalid,            /**< stores whether the returned up values are valid dual bounds, or NULL;
3891                                               *   otherwise, they can only be used as an estimate value */
3892    SCIP_Bool*            downinf,            /**< array to store whether the downward branches are infeasible, or NULL */
3893    SCIP_Bool*            upinf,              /**< array to store whether the upward branches are infeasible, or NULL */
3894    SCIP_Bool*            downconflict,       /**< array to store whether conflict constraints were created for
3895                                               *   infeasible downward branches, or NULL */
3896    SCIP_Bool*            upconflict,         /**< array to store whether conflict constraints were created for
3897                                               *   infeasible upward branches, or NULL */
3898    SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error occurred or the
3899                                               *   solving process should be stopped (e.g., due to a time limit) */
3900    )
3901 {
3902    SCIP_COL** cols;
3903    int j;
3904 
3905    assert(lperror != NULL);
3906 
3907    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3908 
3909    assert( vars != NULL );
3910 
3911    /* set up data */
3912    cols = NULL;
3913    SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) );
3914    assert(cols != NULL);
3915    for( j = 0; j < nvars; ++j )
3916    {
3917       SCIP_VAR* var;
3918       SCIP_COL* col;
3919 
3920       if( downvalid != NULL )
3921          downvalid[j] = FALSE;
3922       if( upvalid != NULL )
3923          upvalid[j] = FALSE;
3924       if( downinf != NULL )
3925          downinf[j] = FALSE;
3926       if( upinf != NULL )
3927          upinf[j] = FALSE;
3928       if( downconflict != NULL )
3929          downconflict[j] = FALSE;
3930       if( upconflict != NULL )
3931          upconflict[j] = FALSE;
3932 
3933       var = vars[j];
3934       assert( var != NULL );
3935       if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
3936       {
3937          SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3938          SCIPfreeBufferArray(scip, &cols);
3939          return SCIP_INVALIDDATA;
3940       }
3941 
3942       col = SCIPvarGetCol(var);
3943       assert(col != NULL);
3944       cols[j] = col;
3945 
3946       if( !SCIPcolIsInLP(col) )
3947       {
3948          SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3949          SCIPfreeBufferArray(scip, &cols);
3950          return SCIP_INVALIDDATA;
3951       }
3952    }
3953 
3954    /* check if the solving process should be aborted */
3955    if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3956    {
3957       /* mark this as if the LP failed */
3958       *lperror = TRUE;
3959    }
3960    else
3961    {
3962       /* call strong branching for columns */
3963       SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim,
3964             down, up, downvalid, upvalid, lperror) );
3965 
3966       /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3967        * declare the sub nodes infeasible
3968        */
3969       if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3970       {
3971          for( j = 0; j < nvars; ++j )
3972          {
3973             SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL,
3974                   (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL,
3975                   (upconflict != NULL) ? (&(upconflict[j])) : NULL) );
3976          }
3977       }
3978    }
3979    SCIPfreeBufferArray(scip, &cols);
3980 
3981    return SCIP_OKAY;
3982 }
3983 
3984 /** get LP solution status of last strong branching call (currently only works for strong branching with propagation) */
SCIPgetLastStrongbranchLPSolStat(SCIP * scip,SCIP_BRANCHDIR branchdir)3985 SCIP_LPSOLSTAT SCIPgetLastStrongbranchLPSolStat(
3986    SCIP*                 scip,               /**< SCIP data structure */
3987    SCIP_BRANCHDIR        branchdir           /**< branching direction for which LP solution status is requested */
3988    )
3989 {
3990    assert(NULL != scip);
3991    assert(branchdir == SCIP_BRANCHDIR_DOWNWARDS || branchdir == SCIP_BRANCHDIR_UPWARDS);
3992 
3993    return scip->stat->lastsblpsolstats[branchdir == SCIP_BRANCHDIR_DOWNWARDS ? 0 : 1];
3994 }
3995 
3996 /** gets strong branching information on COLUMN variable of the last SCIPgetVarStrongbranch() call;
3997  *  returns values of SCIP_INVALID, if strong branching was not yet called on the given variable;
3998  *  keep in mind, that the returned old values may have nothing to do with the current LP solution
3999  *
4000  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4001  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4002  *
4003  *  @pre This method can be called if @p scip is in one of the following stages:
4004  *       - \ref SCIP_STAGE_SOLVING
4005  *       - \ref SCIP_STAGE_SOLVED
4006  */
SCIPgetVarStrongbranchLast(SCIP * scip,SCIP_VAR * var,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,SCIP_Real * solval,SCIP_Real * lpobjval)4007 SCIP_RETCODE SCIPgetVarStrongbranchLast(
4008    SCIP*                 scip,               /**< SCIP data structure */
4009    SCIP_VAR*             var,                /**< variable to get last strong branching values for */
4010    SCIP_Real*            down,               /**< stores dual bound after branching column down */
4011    SCIP_Real*            up,                 /**< stores dual bound after branching column up */
4012    SCIP_Bool*            downvalid,          /**< stores whether the returned down value is a valid dual bound, or NULL;
4013                                               *   otherwise, it can only be used as an estimate value */
4014    SCIP_Bool*            upvalid,            /**< stores whether the returned up value is a valid dual bound, or NULL;
4015                                               *   otherwise, it can only be used as an estimate value */
4016    SCIP_Real*            solval,             /**< stores LP solution value of variable at the last strong branching call, or NULL */
4017    SCIP_Real*            lpobjval            /**< stores LP objective value at last strong branching call, or NULL */
4018    )
4019 {
4020    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLast", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
4021 
4022    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
4023    {
4024       SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable\n");
4025       return SCIP_INVALIDDATA;
4026    }
4027 
4028    SCIPcolGetStrongbranchLast(SCIPvarGetCol(var), down, up, downvalid, upvalid, solval, lpobjval);
4029 
4030    return SCIP_OKAY;
4031 }
4032 
4033 /** sets strong branching information for a column variable
4034  *
4035  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4036  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4037  *
4038  *  @pre This method can be called if @p scip is in one of the following stages:
4039  *       - \ref SCIP_STAGE_SOLVING
4040  */
SCIPsetVarStrongbranchData(SCIP * scip,SCIP_VAR * var,SCIP_Real lpobjval,SCIP_Real primsol,SCIP_Real down,SCIP_Real up,SCIP_Bool downvalid,SCIP_Bool upvalid,SCIP_Longint iter,int itlim)4041 SCIP_RETCODE SCIPsetVarStrongbranchData(
4042    SCIP*                 scip,               /**< SCIP data structure */
4043    SCIP_VAR*             var,                /**< variable to set last strong branching values for */
4044    SCIP_Real             lpobjval,           /**< objective value of the current LP */
4045    SCIP_Real             primsol,            /**< primal solution value of the column in the current LP */
4046    SCIP_Real             down,               /**< dual bound after branching column down */
4047    SCIP_Real             up,                 /**< dual bound after branching column up */
4048    SCIP_Bool             downvalid,          /**< is the returned down value a valid dual bound? */
4049    SCIP_Bool             upvalid,            /**< is the returned up value a valid dual bound? */
4050    SCIP_Longint          iter,               /**< total number of strong branching iterations */
4051    int                   itlim               /**< iteration limit applied to the strong branching call */
4052    )
4053 {
4054    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetVarStrongbranchData", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4055 
4056    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
4057    {
4058       SCIPerrorMessage("cannot set strong branching information on non-COLUMN variable\n");
4059       return SCIP_INVALIDDATA;
4060    }
4061 
4062    SCIPcolSetStrongbranchData(SCIPvarGetCol(var), scip->set, scip->stat, scip->lp, lpobjval, primsol,
4063       down, up, downvalid, upvalid, iter, itlim);
4064 
4065    return SCIP_OKAY;
4066 }
4067 
4068 /** rounds the current solution and tries it afterwards; if feasible, adds it to storage
4069  *
4070  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4071  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4072  *
4073  *  @pre This method can be called if @p scip is in one of the following stages:
4074  *       - \ref SCIP_STAGE_SOLVING
4075  */
SCIPtryStrongbranchLPSol(SCIP * scip,SCIP_Bool * foundsol,SCIP_Bool * cutoff)4076 SCIP_RETCODE SCIPtryStrongbranchLPSol(
4077    SCIP*                 scip,               /**< SCIP data structure */
4078    SCIP_Bool*            foundsol,           /**< stores whether solution was feasible and good enough to keep */
4079    SCIP_Bool*            cutoff              /**< stores whether solution was cutoff due to exceeding the cutoffbound */
4080    )
4081 {
4082    assert(scip != NULL);
4083    assert(foundsol != NULL);
4084    assert(cutoff != NULL);
4085 
4086    SCIP_CALL( SCIPcheckStage(scip, "SCIPtryStrongbranchLPSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4087 
4088    if( scip->set->branch_checksbsol )
4089    {
4090       SCIP_SOL* sol;
4091       SCIP_Bool rounded = TRUE;
4092       SCIP_Real value = SCIPgetLPObjval(scip);
4093       SCIP_Longint oldnbestsolsfound = scip->primal->nbestsolsfound;
4094 
4095       /* start clock for strong branching solutions */
4096       SCIPclockStart(scip->stat->sbsoltime, scip->set);
4097 
4098       SCIP_CALL( SCIPcreateLPSol(scip, &sol, NULL) );
4099       SCIPsolSetStrongbranching(sol);
4100 
4101       /* try to round the strong branching solution */
4102       if( scip->set->branch_roundsbsol )
4103       {
4104          SCIP_CALL( SCIProundSol(scip, sol, &rounded) );
4105       }
4106 
4107       /* check the solution for feasibility if rounding worked well (or was not tried) */
4108       if( rounded )
4109       {
4110          SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, TRUE, FALSE, foundsol) );
4111       }
4112       else
4113       {
4114          SCIP_CALL( SCIPfreeSol(scip, &sol) );
4115       }
4116 
4117       if( *foundsol )
4118       {
4119          SCIPdebugMsg(scip, "found new solution in strong branching\n");
4120 
4121          scip->stat->nsbsolsfound++;
4122 
4123          if( scip->primal->nbestsolsfound != oldnbestsolsfound )
4124          {
4125             scip->stat->nsbbestsolsfound++;
4126          }
4127 
4128          if( SCIPisGE(scip, value, SCIPgetCutoffbound(scip)) )
4129             *cutoff = TRUE;
4130       }
4131 
4132       /* stop clock for strong branching solutions */
4133       SCIPclockStop(scip->stat->sbsoltime, scip->set);
4134    }
4135    return SCIP_OKAY;
4136 }
4137 
4138 
4139 /** gets node number of the last node in current branch and bound run, where strong branching was used on the
4140  *  given variable, or -1 if strong branching was never applied to the variable in current run
4141  *
4142  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4143  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4144  *
4145  *  @pre This method can be called if @p scip is in one of the following stages:
4146  *       - \ref SCIP_STAGE_TRANSFORMING
4147  *       - \ref SCIP_STAGE_TRANSFORMED
4148  *       - \ref SCIP_STAGE_INITPRESOLVE
4149  *       - \ref SCIP_STAGE_PRESOLVING
4150  *       - \ref SCIP_STAGE_EXITPRESOLVE
4151  *       - \ref SCIP_STAGE_PRESOLVED
4152  *       - \ref SCIP_STAGE_INITSOLVE
4153  *       - \ref SCIP_STAGE_SOLVING
4154  *       - \ref SCIP_STAGE_SOLVED
4155  *       - \ref SCIP_STAGE_EXITSOLVE
4156  */
SCIPgetVarStrongbranchNode(SCIP * scip,SCIP_VAR * var)4157 SCIP_Longint SCIPgetVarStrongbranchNode(
4158    SCIP*                 scip,               /**< SCIP data structure */
4159    SCIP_VAR*             var                 /**< variable to get last strong branching node for */
4160    )
4161 {
4162    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchNode", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4163 
4164    assert( var->scip == scip );
4165 
4166    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
4167       return -1;
4168 
4169    return SCIPcolGetStrongbranchNode(SCIPvarGetCol(var));
4170 }
4171 
4172 /** if strong branching was already applied on the variable at the current node, returns the number of LPs solved after
4173  *  the LP where the strong branching on this variable was applied;
4174  *  if strong branching was not yet applied on the variable at the current node, returns INT_MAX
4175  *
4176  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4177  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4178  *
4179  *  @pre This method can be called if @p scip is in one of the following stages:
4180  *       - \ref SCIP_STAGE_TRANSFORMING
4181  *       - \ref SCIP_STAGE_TRANSFORMED
4182  *       - \ref SCIP_STAGE_INITPRESOLVE
4183  *       - \ref SCIP_STAGE_PRESOLVING
4184  *       - \ref SCIP_STAGE_EXITPRESOLVE
4185  *       - \ref SCIP_STAGE_PRESOLVED
4186  *       - \ref SCIP_STAGE_INITSOLVE
4187  *       - \ref SCIP_STAGE_SOLVING
4188  *       - \ref SCIP_STAGE_SOLVED
4189  *       - \ref SCIP_STAGE_EXITSOLVE
4190  */
SCIPgetVarStrongbranchLPAge(SCIP * scip,SCIP_VAR * var)4191 SCIP_Longint SCIPgetVarStrongbranchLPAge(
4192    SCIP*                 scip,               /**< SCIP data structure */
4193    SCIP_VAR*             var                 /**< variable to get strong branching LP age for */
4194    )
4195 {
4196    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLPAge", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4197 
4198    assert( var->scip == scip );
4199 
4200    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
4201       return SCIP_LONGINT_MAX;
4202 
4203    return SCIPcolGetStrongbranchLPAge(SCIPvarGetCol(var), scip->stat);
4204 }
4205 
4206 /** gets number of times, strong branching was applied in current run on the given variable
4207  *
4208  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4209  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4210  *
4211  *  @pre This method can be called if @p scip is in one of the following stages:
4212  *       - \ref SCIP_STAGE_TRANSFORMING
4213  *       - \ref SCIP_STAGE_TRANSFORMED
4214  *       - \ref SCIP_STAGE_INITPRESOLVE
4215  *       - \ref SCIP_STAGE_PRESOLVING
4216  *       - \ref SCIP_STAGE_EXITPRESOLVE
4217  *       - \ref SCIP_STAGE_PRESOLVED
4218  *       - \ref SCIP_STAGE_INITSOLVE
4219  *       - \ref SCIP_STAGE_SOLVING
4220  *       - \ref SCIP_STAGE_SOLVED
4221  *       - \ref SCIP_STAGE_EXITSOLVE
4222  */
SCIPgetVarNStrongbranchs(SCIP * scip,SCIP_VAR * var)4223 int SCIPgetVarNStrongbranchs(
4224    SCIP*                 scip,               /**< SCIP data structure */
4225    SCIP_VAR*             var                 /**< variable to get last strong branching node for */
4226    )
4227 {
4228    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarNStrongbranchs", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4229 
4230    assert( var->scip == scip );
4231 
4232    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
4233       return 0;
4234 
4235    return SCIPcolGetNStrongbranchs(SCIPvarGetCol(var));
4236 }
4237 
4238 /** adds given values to lock numbers of type @p locktype of variable for rounding
4239  *
4240  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4241  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4242  *
4243  *  @pre This method can be called if @p scip is in one of the following stages:
4244  *       - \ref SCIP_STAGE_PROBLEM
4245  *       - \ref SCIP_STAGE_TRANSFORMING
4246  *       - \ref SCIP_STAGE_TRANSFORMED
4247  *       - \ref SCIP_STAGE_INITPRESOLVE
4248  *       - \ref SCIP_STAGE_PRESOLVING
4249  *       - \ref SCIP_STAGE_EXITPRESOLVE
4250  *       - \ref SCIP_STAGE_PRESOLVED
4251  *       - \ref SCIP_STAGE_INITSOLVE
4252  *       - \ref SCIP_STAGE_SOLVING
4253  *       - \ref SCIP_STAGE_EXITSOLVE
4254  *       - \ref SCIP_STAGE_FREETRANS
4255  */
SCIPaddVarLocksType(SCIP * scip,SCIP_VAR * var,SCIP_LOCKTYPE locktype,int nlocksdown,int nlocksup)4256 SCIP_RETCODE SCIPaddVarLocksType(
4257    SCIP*                 scip,               /**< SCIP data structure */
4258    SCIP_VAR*             var,                /**< problem variable */
4259    SCIP_LOCKTYPE         locktype,           /**< type of the variable locks */
4260    int                   nlocksdown,         /**< modification in number of rounding down locks */
4261    int                   nlocksup            /**< modification in number of rounding up locks */
4262    )
4263 {
4264    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocksType", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4265 
4266    assert( var->scip == scip );
4267 
4268    switch( scip->set->stage )
4269    {
4270    case SCIP_STAGE_PROBLEM:
4271       assert(!SCIPvarIsTransformed(var));
4272       /*lint -fallthrough*/
4273    case SCIP_STAGE_TRANSFORMING:
4274    case SCIP_STAGE_TRANSFORMED:
4275    case SCIP_STAGE_INITPRESOLVE:
4276    case SCIP_STAGE_PRESOLVING:
4277    case SCIP_STAGE_EXITPRESOLVE:
4278    case SCIP_STAGE_PRESOLVED:
4279    case SCIP_STAGE_INITSOLVE:
4280    case SCIP_STAGE_SOLVING:
4281    case SCIP_STAGE_EXITSOLVE:
4282    case SCIP_STAGE_FREETRANS:
4283       SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, locktype, nlocksdown, nlocksup) );
4284       return SCIP_OKAY;
4285 
4286    default:
4287       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4288       return SCIP_INVALIDCALL;
4289    }  /*lint !e788*/
4290 }
4291 
4292 /** adds given values to lock numbers of variable for rounding
4293  *
4294  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4295  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4296  *
4297  *  @pre This method can be called if @p scip is in one of the following stages:
4298  *       - \ref SCIP_STAGE_PROBLEM
4299  *       - \ref SCIP_STAGE_TRANSFORMING
4300  *       - \ref SCIP_STAGE_TRANSFORMED
4301  *       - \ref SCIP_STAGE_INITPRESOLVE
4302  *       - \ref SCIP_STAGE_PRESOLVING
4303  *       - \ref SCIP_STAGE_EXITPRESOLVE
4304  *       - \ref SCIP_STAGE_PRESOLVED
4305  *       - \ref SCIP_STAGE_INITSOLVE
4306  *       - \ref SCIP_STAGE_SOLVING
4307  *       - \ref SCIP_STAGE_EXITSOLVE
4308  *       - \ref SCIP_STAGE_FREETRANS
4309  *
4310  *  @note This method will always add variable locks of type model
4311  *
4312  *  @note It is recommented to use SCIPaddVarLocksType()
4313  */
SCIPaddVarLocks(SCIP * scip,SCIP_VAR * var,int nlocksdown,int nlocksup)4314 SCIP_RETCODE SCIPaddVarLocks(
4315    SCIP*                 scip,               /**< SCIP data structure */
4316    SCIP_VAR*             var,                /**< problem variable */
4317    int                   nlocksdown,         /**< modification in number of rounding down locks */
4318    int                   nlocksup            /**< modification in number of rounding up locks */
4319    )
4320 {
4321    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocks", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4322 
4323    SCIP_CALL( SCIPaddVarLocksType(scip, var, SCIP_LOCKTYPE_MODEL, nlocksdown, nlocksup) );
4324 
4325    return SCIP_OKAY;
4326 }
4327 
4328 /** add locks of variable with respect to the lock status of the constraint and its negation;
4329  *  this method should be called whenever the lock status of a variable in a constraint changes, for example if
4330  *  the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were
4331  *  added or removed
4332  *
4333  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4334  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4335  *
4336  *  @pre This method can be called if @p scip is in one of the following stages:
4337  *       - \ref SCIP_STAGE_PROBLEM
4338  *       - \ref SCIP_STAGE_TRANSFORMING
4339  *       - \ref SCIP_STAGE_INITPRESOLVE
4340  *       - \ref SCIP_STAGE_PRESOLVING
4341  *       - \ref SCIP_STAGE_EXITPRESOLVE
4342  *       - \ref SCIP_STAGE_INITSOLVE
4343  *       - \ref SCIP_STAGE_SOLVING
4344  *       - \ref SCIP_STAGE_EXITSOLVE
4345  *       - \ref SCIP_STAGE_FREETRANS
4346  */
SCIPlockVarCons(SCIP * scip,SCIP_VAR * var,SCIP_CONS * cons,SCIP_Bool lockdown,SCIP_Bool lockup)4347 SCIP_RETCODE SCIPlockVarCons(
4348    SCIP*                 scip,               /**< SCIP data structure */
4349    SCIP_VAR*             var,                /**< problem variable */
4350    SCIP_CONS*            cons,               /**< constraint */
4351    SCIP_Bool             lockdown,           /**< should the rounding be locked in downwards direction? */
4352    SCIP_Bool             lockup              /**< should the rounding be locked in upwards direction? */
4353    )
4354 {
4355    int nlocksdown[NLOCKTYPES];
4356    int nlocksup[NLOCKTYPES];
4357    int i;
4358 
4359    SCIP_CALL( SCIPcheckStage(scip, "SCIPlockVarCons", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4360 
4361    assert( var->scip == scip );
4362 
4363    for( i = 0; i < NLOCKTYPES; i++ )
4364    {
4365       nlocksdown[i] = 0;
4366       nlocksup[i] = 0;
4367 
4368       if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4369       {
4370          if( lockdown )
4371             ++nlocksdown[i];
4372          if( lockup )
4373             ++nlocksup[i];
4374       }
4375       if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4376       {
4377          if( lockdown )
4378             ++nlocksup[i];
4379          if( lockup )
4380             ++nlocksdown[i];
4381       }
4382    }
4383 
4384    switch( scip->set->stage )
4385    {
4386    case SCIP_STAGE_PROBLEM:
4387       assert(!SCIPvarIsTransformed(var));
4388       /*lint -fallthrough*/
4389    case SCIP_STAGE_TRANSFORMING:
4390    case SCIP_STAGE_TRANSFORMED:
4391    case SCIP_STAGE_INITPRESOLVE:
4392    case SCIP_STAGE_PRESOLVING:
4393    case SCIP_STAGE_EXITPRESOLVE:
4394    case SCIP_STAGE_INITSOLVE:
4395    case SCIP_STAGE_SOLVING:
4396    case SCIP_STAGE_EXITSOLVE:
4397    case SCIP_STAGE_FREETRANS:
4398       for( i = 0; i < NLOCKTYPES; i++ )
4399       {
4400          if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4401             continue;
4402 
4403          SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4404       }
4405       return SCIP_OKAY;
4406 
4407    default:
4408       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4409       return SCIP_INVALIDCALL;
4410    }  /*lint !e788*/
4411 }
4412 
4413 /** remove locks of type @p locktype of variable with respect to the lock status of the constraint and its negation;
4414  *  this method should be called whenever the lock status of a variable in a constraint changes, for example if
4415  *  the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were
4416  *  added or removed
4417  *
4418  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4419  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4420  *
4421  *  @pre This method can be called if @p scip is in one of the following stages:
4422  *       - \ref SCIP_STAGE_PROBLEM
4423  *       - \ref SCIP_STAGE_TRANSFORMING
4424  *       - \ref SCIP_STAGE_INITPRESOLVE
4425  *       - \ref SCIP_STAGE_PRESOLVING
4426  *       - \ref SCIP_STAGE_EXITPRESOLVE
4427  *       - \ref SCIP_STAGE_INITSOLVE
4428  *       - \ref SCIP_STAGE_SOLVING
4429  *       - \ref SCIP_STAGE_EXITSOLVE
4430  *       - \ref SCIP_STAGE_FREETRANS
4431  */
SCIPunlockVarCons(SCIP * scip,SCIP_VAR * var,SCIP_CONS * cons,SCIP_Bool lockdown,SCIP_Bool lockup)4432 SCIP_RETCODE SCIPunlockVarCons(
4433    SCIP*                 scip,               /**< SCIP data structure */
4434    SCIP_VAR*             var,                /**< problem variable */
4435    SCIP_CONS*            cons,               /**< constraint */
4436    SCIP_Bool             lockdown,           /**< should the rounding be unlocked in downwards direction? */
4437    SCIP_Bool             lockup              /**< should the rounding be unlocked in upwards direction? */
4438    )
4439 {
4440    int nlocksdown[NLOCKTYPES];
4441    int nlocksup[NLOCKTYPES];
4442    int i;
4443 
4444    SCIP_CALL( SCIPcheckStage(scip, "SCIPunlockVarCons", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4445 
4446    assert( var->scip == scip );
4447 
4448    for( i = 0; i < NLOCKTYPES; i++ )
4449    {
4450       nlocksdown[i] = 0;
4451       nlocksup[i] = 0;
4452 
4453       if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4454       {
4455          if( lockdown )
4456             ++nlocksdown[i];
4457          if( lockup )
4458             ++nlocksup[i];
4459       }
4460       if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4461       {
4462          if( lockdown )
4463             ++nlocksup[i];
4464          if( lockup )
4465             ++nlocksdown[i];
4466       }
4467    }
4468    switch( scip->set->stage )
4469    {
4470    case SCIP_STAGE_PROBLEM:
4471       assert(!SCIPvarIsTransformed(var));
4472       /*lint -fallthrough*/
4473    case SCIP_STAGE_TRANSFORMING:
4474    case SCIP_STAGE_INITPRESOLVE:
4475    case SCIP_STAGE_PRESOLVING:
4476    case SCIP_STAGE_EXITPRESOLVE:
4477    case SCIP_STAGE_INITSOLVE:
4478    case SCIP_STAGE_SOLVING:
4479    case SCIP_STAGE_EXITSOLVE:
4480    case SCIP_STAGE_FREETRANS:
4481       for( i = 0; i < NLOCKTYPES; i++ )
4482       {
4483          if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4484             continue;
4485 
4486          SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE)  i, -nlocksdown[i], -nlocksup[i]) );
4487       }
4488       return SCIP_OKAY;
4489 
4490    default:
4491       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4492       return SCIP_INVALIDCALL;
4493    }  /*lint !e788*/
4494 }
4495 
4496 /** changes variable's objective value
4497  *
4498  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4499  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4500  *
4501  *  @pre This method can be called if @p scip is in one of the following stages:
4502  *       - \ref SCIP_STAGE_PROBLEM
4503  *       - \ref SCIP_STAGE_TRANSFORMING
4504  *       - \ref SCIP_STAGE_PRESOLVING
4505  *       - \ref SCIP_STAGE_PRESOLVED
4506  */
SCIPchgVarObj(SCIP * scip,SCIP_VAR * var,SCIP_Real newobj)4507 SCIP_RETCODE SCIPchgVarObj(
4508    SCIP*                 scip,               /**< SCIP data structure */
4509    SCIP_VAR*             var,                /**< variable to change the objective value for */
4510    SCIP_Real             newobj              /**< new objective value */
4511    )
4512 {
4513    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4514 
4515    assert( var->scip == scip );
4516 
4517    /* forbid infinite objective values */
4518    if( SCIPisInfinity(scip, REALABS(newobj)) )
4519    {
4520       SCIPerrorMessage("invalid objective value: objective value is infinite\n");
4521       return SCIP_INVALIDDATA;
4522    }
4523 
4524    switch( scip->set->stage )
4525    {
4526    case SCIP_STAGE_PROBLEM:
4527       assert(!SCIPvarIsTransformed(var));
4528       SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->origprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4529       return SCIP_OKAY;
4530 
4531    case SCIP_STAGE_TRANSFORMED:
4532    case SCIP_STAGE_TRANSFORMING:
4533    case SCIP_STAGE_PRESOLVING:
4534    case SCIP_STAGE_PRESOLVED:
4535       SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set,  scip->transprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4536       return SCIP_OKAY;
4537 
4538    default:
4539       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4540       return SCIP_INVALIDCALL;
4541    }  /*lint !e788*/
4542 }
4543 
4544 /** adds value to variable's objective value
4545  *
4546  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4547  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4548  *
4549  *  @pre This method can be called if @p scip is in one of the following stages:
4550  *       - \ref SCIP_STAGE_PROBLEM
4551  *       - \ref SCIP_STAGE_TRANSFORMING
4552  *       - \ref SCIP_STAGE_PRESOLVING
4553  *       - \ref SCIP_STAGE_EXITPRESOLVE
4554  *       - \ref SCIP_STAGE_PRESOLVED
4555  */
SCIPaddVarObj(SCIP * scip,SCIP_VAR * var,SCIP_Real addobj)4556 SCIP_RETCODE SCIPaddVarObj(
4557    SCIP*                 scip,               /**< SCIP data structure */
4558    SCIP_VAR*             var,                /**< variable to change the objective value for */
4559    SCIP_Real             addobj              /**< additional objective value */
4560    )
4561 {
4562    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4563 
4564    assert( var->scip == scip );
4565 
4566    switch( scip->set->stage )
4567    {
4568    case SCIP_STAGE_PROBLEM:
4569       assert(!SCIPvarIsTransformed(var));
4570       SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4571             scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4572       return SCIP_OKAY;
4573 
4574    case SCIP_STAGE_TRANSFORMING:
4575    case SCIP_STAGE_PRESOLVING:
4576    case SCIP_STAGE_EXITPRESOLVE:
4577    case SCIP_STAGE_PRESOLVED:
4578       SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4579             scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4580       return SCIP_OKAY;
4581 
4582    default:
4583       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4584       return SCIP_INVALIDCALL;
4585    }  /*lint !e788*/
4586 }
4587 
4588 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) lower bound value;
4589  *  does not change the bounds of the variable
4590  *
4591  *  @return adjusted lower bound for the given variable; the bound of the variable is not changed
4592  *
4593  *  @pre This method can be called if @p scip is in one of the following stages:
4594  *       - \ref SCIP_STAGE_PROBLEM
4595  *       - \ref SCIP_STAGE_TRANSFORMING
4596  *       - \ref SCIP_STAGE_TRANSFORMED
4597  *       - \ref SCIP_STAGE_INITPRESOLVE
4598  *       - \ref SCIP_STAGE_PRESOLVING
4599  *       - \ref SCIP_STAGE_EXITPRESOLVE
4600  *       - \ref SCIP_STAGE_PRESOLVED
4601  *       - \ref SCIP_STAGE_INITSOLVE
4602  *       - \ref SCIP_STAGE_SOLVING
4603  *       - \ref SCIP_STAGE_SOLVED
4604  *       - \ref SCIP_STAGE_EXITSOLVE
4605  *       - \ref SCIP_STAGE_FREETRANS
4606  */
SCIPadjustedVarLb(SCIP * scip,SCIP_VAR * var,SCIP_Real lb)4607 SCIP_Real SCIPadjustedVarLb(
4608    SCIP*                 scip,               /**< SCIP data structure */
4609    SCIP_VAR*             var,                /**< variable to adjust the bound for */
4610    SCIP_Real             lb                  /**< lower bound value to adjust */
4611    )
4612 {
4613    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarLb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
4614 
4615    SCIPvarAdjustLb(var, scip->set, &lb);
4616 
4617    return lb;
4618 }
4619 
4620 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) upper bound value;
4621  *  does not change the bounds of the variable
4622  *
4623  *  @return adjusted upper bound for the given variable; the bound of the variable is not changed
4624  *
4625  *  @pre This method can be called if @p scip is in one of the following stages:
4626  *       - \ref SCIP_STAGE_PROBLEM
4627  *       - \ref SCIP_STAGE_TRANSFORMING
4628  *       - \ref SCIP_STAGE_TRANSFORMED
4629  *       - \ref SCIP_STAGE_INITPRESOLVE
4630  *       - \ref SCIP_STAGE_PRESOLVING
4631  *       - \ref SCIP_STAGE_EXITPRESOLVE
4632  *       - \ref SCIP_STAGE_PRESOLVED
4633  *       - \ref SCIP_STAGE_INITSOLVE
4634  *       - \ref SCIP_STAGE_SOLVING
4635  *       - \ref SCIP_STAGE_SOLVED
4636  *       - \ref SCIP_STAGE_EXITSOLVE
4637  *       - \ref SCIP_STAGE_FREETRANS
4638  */
SCIPadjustedVarUb(SCIP * scip,SCIP_VAR * var,SCIP_Real ub)4639 SCIP_Real SCIPadjustedVarUb(
4640    SCIP*                 scip,               /**< SCIP data structure */
4641    SCIP_VAR*             var,                /**< variable to adjust the bound for */
4642    SCIP_Real             ub                  /**< upper bound value to adjust */
4643    )
4644 {
4645    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarUb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
4646 
4647    SCIPvarAdjustUb(var, scip->set, &ub);
4648 
4649    return ub;
4650 }
4651 
4652 /** depending on SCIP's stage, changes lower bound of variable in the problem, in preprocessing, or in current node;
4653  *  if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such
4654  *  that in conflict analysis, this change is treated like a branching decision
4655  *
4656  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4657  *           SCIPgetVars()) gets resorted.
4658  *
4659  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4660  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4661  *
4662  *  @pre This method can be called if @p scip is in one of the following stages:
4663  *       - \ref SCIP_STAGE_PROBLEM
4664  *       - \ref SCIP_STAGE_TRANSFORMING
4665  *       - \ref SCIP_STAGE_PRESOLVING
4666  *       - \ref SCIP_STAGE_SOLVING
4667  *
4668  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4669  */
SCIPchgVarLb(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound)4670 SCIP_RETCODE SCIPchgVarLb(
4671    SCIP*                 scip,               /**< SCIP data structure */
4672    SCIP_VAR*             var,                /**< variable to change the bound for */
4673    SCIP_Real             newbound            /**< new value for bound */
4674    )
4675 {
4676    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4677 
4678    SCIPvarAdjustLb(var, scip->set, &newbound);
4679 
4680    /* ignore tightenings of lower bounds to +infinity during solving process */
4681    if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4682    {
4683 #ifndef NDEBUG
4684       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4685          SCIPvarGetLbLocal(var));
4686 #endif
4687       return SCIP_OKAY;
4688    }
4689 
4690    switch( scip->set->stage )
4691    {
4692    case SCIP_STAGE_PROBLEM:
4693       assert(!SCIPvarIsTransformed(var));
4694       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4695             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4696       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4697             scip->branchcand, scip->eventqueue, newbound) );
4698       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
4699       break;
4700 
4701    case SCIP_STAGE_TRANSFORMING:
4702    case SCIP_STAGE_PRESOLVED:
4703       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4704             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4705       break;
4706 
4707    case SCIP_STAGE_PRESOLVING:
4708       if( !SCIPinProbing(scip) )
4709       {
4710          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4711          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4712 
4713          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4714                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable,
4715                var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
4716 
4717          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4718          {
4719             SCIP_Bool infeasible;
4720 
4721             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4722             assert(!infeasible);
4723          }
4724          break;
4725       }
4726       /*lint -fallthrough*/
4727    case SCIP_STAGE_SOLVING:
4728       SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
4729             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4730             scip->cliquetable, var, newbound,
4731             SCIP_BOUNDTYPE_LOWER, FALSE) );
4732       break;
4733 
4734    default:
4735       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4736       return SCIP_INVALIDCALL;
4737    }  /*lint !e788*/
4738 
4739    return SCIP_OKAY;
4740 }
4741 
4742 /** depending on SCIP's stage, changes upper bound of variable in the problem, in preprocessing, or in current node;
4743  *  if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such
4744  *  that in conflict analysis, this change is treated like a branching decision
4745  *
4746  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4747  *           SCIPgetVars()) gets resorted.
4748  *
4749  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4750  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4751  *
4752  *  @pre This method can be called if @p scip is in one of the following stages:
4753  *       - \ref SCIP_STAGE_PROBLEM
4754  *       - \ref SCIP_STAGE_TRANSFORMING
4755  *       - \ref SCIP_STAGE_PRESOLVING
4756  *       - \ref SCIP_STAGE_SOLVING
4757  *
4758  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4759  */
SCIPchgVarUb(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound)4760 SCIP_RETCODE SCIPchgVarUb(
4761    SCIP*                 scip,               /**< SCIP data structure */
4762    SCIP_VAR*             var,                /**< variable to change the bound for */
4763    SCIP_Real             newbound            /**< new value for bound */
4764    )
4765 {
4766    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4767 
4768    SCIPvarAdjustUb(var, scip->set, &newbound);
4769 
4770    /* ignore tightenings of upper bounds to -infinity during solving process */
4771    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4772    {
4773 #ifndef NDEBUG
4774       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
4775          SCIPvarGetUbLocal(var));
4776 #endif
4777       return SCIP_OKAY;
4778    }
4779 
4780    switch( scip->set->stage )
4781    {
4782    case SCIP_STAGE_PROBLEM:
4783       assert(!SCIPvarIsTransformed(var));
4784       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4785             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4786       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4787             scip->branchcand, scip->eventqueue, newbound) );
4788       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
4789       break;
4790 
4791    case SCIP_STAGE_TRANSFORMING:
4792    case SCIP_STAGE_PRESOLVED:
4793       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4794             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4795       break;
4796 
4797    case SCIP_STAGE_PRESOLVING:
4798       if( !SCIPinProbing(scip) )
4799       {
4800          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4801          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4802 
4803          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4804                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4805                scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
4806 
4807          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4808          {
4809             SCIP_Bool infeasible;
4810 
4811             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4812             assert(!infeasible);
4813          }
4814          break;
4815       }
4816       /*lint -fallthrough*/
4817    case SCIP_STAGE_SOLVING:
4818       SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
4819             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4820             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
4821       break;
4822 
4823    default:
4824       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4825       return SCIP_INVALIDCALL;
4826    }  /*lint !e788*/
4827 
4828    return SCIP_OKAY;
4829 }
4830 
4831 /** changes lower bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any
4832  *  inference information in the bound change, such that in conflict analysis, this change is treated like a branching
4833  *  decision
4834  *
4835  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4836  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4837  *
4838  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
4839  */
SCIPchgVarLbNode(SCIP * scip,SCIP_NODE * node,SCIP_VAR * var,SCIP_Real newbound)4840 SCIP_RETCODE SCIPchgVarLbNode(
4841    SCIP*                 scip,               /**< SCIP data structure */
4842    SCIP_NODE*            node,               /**< node to change bound at, or NULL for current node */
4843    SCIP_VAR*             var,                /**< variable to change the bound for */
4844    SCIP_Real             newbound            /**< new value for bound */
4845    )
4846 {
4847    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4848 
4849    if( node == NULL )
4850    {
4851       SCIP_CALL( SCIPchgVarLb(scip, var, newbound) );
4852    }
4853    else
4854    {
4855       SCIPvarAdjustLb(var, scip->set, &newbound);
4856 
4857       /* ignore tightenings of lower bounds to +infinity during solving process */
4858       if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4859       {
4860 #ifndef NDEBUG
4861          SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4862             SCIPvarGetLbLocal(var));
4863 #endif
4864          return SCIP_OKAY;
4865       }
4866 
4867       SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
4868             scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4869             SCIP_BOUNDTYPE_LOWER, FALSE) );
4870    }
4871 
4872    return SCIP_OKAY;
4873 }
4874 
4875 /** changes upper bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any
4876  *  inference information in the bound change, such that in conflict analysis, this change is treated like a branching
4877  *  decision
4878  *
4879  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4880  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4881  *
4882  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
4883  */
SCIPchgVarUbNode(SCIP * scip,SCIP_NODE * node,SCIP_VAR * var,SCIP_Real newbound)4884 SCIP_RETCODE SCIPchgVarUbNode(
4885    SCIP*                 scip,               /**< SCIP data structure */
4886    SCIP_NODE*            node,               /**< node to change bound at, or NULL for current node */
4887    SCIP_VAR*             var,                /**< variable to change the bound for */
4888    SCIP_Real             newbound            /**< new value for bound */
4889    )
4890 {
4891    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4892 
4893    if( node == NULL )
4894    {
4895       SCIP_CALL( SCIPchgVarUb(scip, var, newbound) );
4896    }
4897    else
4898    {
4899       SCIPvarAdjustUb(var, scip->set, &newbound);
4900 
4901       /* ignore tightenings of upper bounds to -infinity during solving process */
4902       if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4903       {
4904 #ifndef NDEBUG
4905          SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
4906             SCIPvarGetUbLocal(var));
4907 #endif
4908          return SCIP_OKAY;
4909       }
4910 
4911       SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
4912             scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4913             SCIP_BOUNDTYPE_UPPER, FALSE) );
4914    }
4915 
4916    return SCIP_OKAY;
4917 }
4918 
4919 /** changes global lower bound of variable; if possible, adjust bound to integral value; also tightens the local bound,
4920  *  if the global bound is better than the local bound
4921  *
4922  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4923  *           SCIPgetVars()) gets resorted.
4924  *
4925  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4926  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4927  *
4928  *  @pre This method can be called if @p scip is in one of the following stages:
4929  *       - \ref SCIP_STAGE_PROBLEM
4930  *       - \ref SCIP_STAGE_TRANSFORMING
4931  *       - \ref SCIP_STAGE_PRESOLVING
4932  *       - \ref SCIP_STAGE_SOLVING
4933  *
4934  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4935  */
SCIPchgVarLbGlobal(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound)4936 SCIP_RETCODE SCIPchgVarLbGlobal(
4937    SCIP*                 scip,               /**< SCIP data structure */
4938    SCIP_VAR*             var,                /**< variable to change the bound for */
4939    SCIP_Real             newbound            /**< new value for bound */
4940    )
4941 {
4942    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4943 
4944    SCIPvarAdjustLb(var, scip->set, &newbound);
4945 
4946    /* ignore tightenings of lower bounds to +infinity during solving process */
4947    if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4948    {
4949 #ifndef NDEBUG
4950       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4951          SCIPvarGetLbLocal(var));
4952 #endif
4953       return SCIP_OKAY;
4954    }
4955 
4956    switch( scip->set->stage )
4957    {
4958    case SCIP_STAGE_PROBLEM:
4959       assert(!SCIPvarIsTransformed(var));
4960       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4961             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4962       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4963             scip->branchcand, scip->eventqueue, newbound) );
4964       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
4965       break;
4966 
4967    case SCIP_STAGE_TRANSFORMING:
4968       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4969             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4970       break;
4971 
4972    case SCIP_STAGE_PRESOLVING:
4973       if( !SCIPinProbing(scip) )
4974       {
4975          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4976          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4977 
4978          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4979                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4980                SCIP_BOUNDTYPE_LOWER, FALSE) );
4981 
4982          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4983          {
4984             SCIP_Bool infeasible;
4985 
4986             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4987             assert(!infeasible);
4988          }
4989          break;
4990       }
4991       /*lint -fallthrough*/
4992    case SCIP_STAGE_SOLVING:
4993       SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4994             scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4995             SCIP_BOUNDTYPE_LOWER, FALSE) );
4996       break;
4997 
4998    default:
4999       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5000       return SCIP_INVALIDCALL;
5001    }  /*lint !e788*/
5002 
5003    return SCIP_OKAY;
5004 }
5005 
5006 /** changes global upper bound of variable; if possible, adjust bound to integral value; also tightens the local bound,
5007  *  if the global bound is better than the local bound
5008  *
5009  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5010  *           SCIPgetVars()) gets resorted.
5011  *
5012  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5013  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5014  *
5015  *  @pre This method can be called if @p scip is in one of the following stages:
5016  *       - \ref SCIP_STAGE_PROBLEM
5017  *       - \ref SCIP_STAGE_TRANSFORMING
5018  *       - \ref SCIP_STAGE_PRESOLVING
5019  *       - \ref SCIP_STAGE_SOLVING
5020  *
5021  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5022  */
SCIPchgVarUbGlobal(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound)5023 SCIP_RETCODE SCIPchgVarUbGlobal(
5024    SCIP*                 scip,               /**< SCIP data structure */
5025    SCIP_VAR*             var,                /**< variable to change the bound for */
5026    SCIP_Real             newbound            /**< new value for bound */
5027    )
5028 {
5029    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5030 
5031    SCIPvarAdjustUb(var, scip->set, &newbound);
5032 
5033    /* ignore tightenings of upper bounds to -infinity during solving process */
5034    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5035    {
5036 #ifndef NDEBUG
5037       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5038          SCIPvarGetUbLocal(var));
5039 #endif
5040       return SCIP_OKAY;
5041    }
5042 
5043    switch( scip->set->stage )
5044    {
5045    case SCIP_STAGE_PROBLEM:
5046       assert(!SCIPvarIsTransformed(var));
5047       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5048             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5049       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5050             scip->branchcand, scip->eventqueue, newbound) );
5051       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5052       break;
5053 
5054    case SCIP_STAGE_TRANSFORMING:
5055       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5056             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5057       break;
5058 
5059    case SCIP_STAGE_PRESOLVING:
5060       if( !SCIPinProbing(scip) )
5061       {
5062          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5063          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5064 
5065          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5066                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5067                SCIP_BOUNDTYPE_UPPER, FALSE) );
5068 
5069          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5070          {
5071             SCIP_Bool infeasible;
5072 
5073             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
5074             assert(!infeasible);
5075          }
5076          break;
5077       }
5078       /*lint -fallthrough*/
5079    case SCIP_STAGE_SOLVING:
5080       SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5081             scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5082             SCIP_BOUNDTYPE_UPPER, FALSE) );
5083       break;
5084 
5085    default:
5086       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5087       return SCIP_INVALIDCALL;
5088    }  /*lint !e788*/
5089 
5090    return SCIP_OKAY;
5091 }
5092 
5093 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet
5094  *
5095  *  lazy bounds are bounds, that are enforced by constraints and the objective function; hence, these bounds do not need
5096  *  to be put into the LP explicitly.
5097  *
5098  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5099  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5100  *
5101  *  @pre This method can be called if @p scip is in one of the following stages:
5102  *       - \ref SCIP_STAGE_PROBLEM
5103  *       - \ref SCIP_STAGE_TRANSFORMING
5104  *       - \ref SCIP_STAGE_TRANSFORMED
5105  *       - \ref SCIP_STAGE_PRESOLVING
5106  *       - \ref SCIP_STAGE_SOLVING
5107  *
5108  *  @note lazy bounds are useful for branch-and-price since the corresponding variable bounds are not part of the LP
5109  */
SCIPchgVarLbLazy(SCIP * scip,SCIP_VAR * var,SCIP_Real lazylb)5110 SCIP_RETCODE SCIPchgVarLbLazy(
5111    SCIP*                 scip,               /**< SCIP data structure */
5112    SCIP_VAR*             var,                /**< problem variable */
5113    SCIP_Real             lazylb              /**< the lazy lower bound to be set */
5114    )
5115 {
5116    assert(scip != NULL);
5117    assert(var != NULL);
5118 
5119    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5120 
5121    SCIP_CALL( SCIPvarChgLbLazy(var, scip->set, lazylb) );
5122 
5123    return SCIP_OKAY;
5124 }
5125 
5126 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet
5127  *
5128  *  lazy bounds are bounds, that are enforced by constraints and the objective function; hence, these bounds do not need
5129  *  to be put into the LP explicitly.
5130  *
5131  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5132  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5133  *
5134  *  @pre This method can be called if @p scip is in one of the following stages:
5135  *       - \ref SCIP_STAGE_PROBLEM
5136  *       - \ref SCIP_STAGE_TRANSFORMING
5137  *       - \ref SCIP_STAGE_TRANSFORMED
5138  *       - \ref SCIP_STAGE_PRESOLVING
5139  *       - \ref SCIP_STAGE_SOLVING
5140  *
5141  *  @note lazy bounds are useful for branch-and-price since the corresponding variable bounds are not part of the LP
5142  */
SCIPchgVarUbLazy(SCIP * scip,SCIP_VAR * var,SCIP_Real lazyub)5143 SCIP_RETCODE SCIPchgVarUbLazy(
5144    SCIP*                 scip,               /**< SCIP data structure */
5145    SCIP_VAR*             var,                /**< problem variable */
5146    SCIP_Real             lazyub              /**< the lazy lower bound to be set */
5147    )
5148 {
5149    assert(scip != NULL);
5150    assert(var != NULL);
5151 
5152    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5153 
5154    SCIP_CALL( SCIPvarChgUbLazy(var, scip->set, lazyub) );
5155 
5156    return SCIP_OKAY;
5157 }
5158 
5159 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5160  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5161  *  doesn't store any inference information in the bound change, such that in conflict analysis, this change
5162  *  is treated like a branching decision
5163  *
5164  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5165  *           SCIPgetVars()) gets resorted.
5166  *
5167  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5168  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5169  *
5170  *  @pre This method can be called if @p scip is in one of the following stages:
5171  *       - \ref SCIP_STAGE_PROBLEM
5172  *       - \ref SCIP_STAGE_PRESOLVING
5173  *       - \ref SCIP_STAGE_SOLVING
5174  *
5175  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5176  */
SCIPtightenVarLb(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5177 SCIP_RETCODE SCIPtightenVarLb(
5178    SCIP*                 scip,               /**< SCIP data structure */
5179    SCIP_VAR*             var,                /**< variable to change the bound for */
5180    SCIP_Real             newbound,           /**< new value for bound */
5181    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5182    SCIP_Bool*            infeasible,         /**< pointer to store whether the new domain is empty */
5183    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5184    )
5185 {
5186    SCIP_Real lb;
5187    SCIP_Real ub;
5188 
5189    assert(infeasible != NULL);
5190 
5191    SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5192    /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */
5193    assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip));
5194 
5195    *infeasible = FALSE;
5196    if( tightened != NULL )
5197       *tightened = FALSE;
5198 
5199    SCIPvarAdjustLb(var, scip->set, &newbound);
5200 
5201    /* ignore tightenings of lower bounds to +infinity during solving process */
5202    if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5203    {
5204 #ifndef NDEBUG
5205       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5206          SCIPvarGetLbLocal(var));
5207 #endif
5208       return SCIP_OKAY;
5209    }
5210 
5211    /* get current bounds */
5212    lb = SCIPcomputeVarLbLocal(scip, var);
5213    ub = SCIPcomputeVarUbLocal(scip, var);
5214    assert(SCIPsetIsLE(scip->set, lb, ub));
5215 
5216    if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5217    {
5218       *infeasible = TRUE;
5219       return SCIP_OKAY;
5220    }
5221    newbound = MIN(newbound, ub);
5222 
5223    if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
5224       return SCIP_OKAY;
5225 
5226    switch( scip->set->stage )
5227    {
5228    case SCIP_STAGE_PROBLEM:
5229       assert(!SCIPvarIsTransformed(var));
5230       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5231             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5232       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5233             scip->branchcand, scip->eventqueue, newbound) );
5234       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5235       break;
5236    case SCIP_STAGE_TRANSFORMED:
5237       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5238             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5239       break;
5240    case SCIP_STAGE_PRESOLVING:
5241       if( !SCIPinProbing(scip) )
5242       {
5243          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5244          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5245 
5246          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5247                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5248                SCIP_BOUNDTYPE_LOWER, FALSE) );
5249 
5250          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5251          {
5252             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5253             assert(!(*infeasible));
5254          }
5255          break;
5256       }
5257       /*lint -fallthrough*/
5258    case SCIP_STAGE_SOLVING:
5259       SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5260             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable,
5261             var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
5262       break;
5263 
5264    default:
5265       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5266       return SCIP_INVALIDCALL;
5267    }  /*lint !e788*/
5268 
5269    /* check whether the lower bound improved */
5270    if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5271       *tightened = TRUE;
5272 
5273    return SCIP_OKAY;
5274 }
5275 
5276 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5277  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5278  *  doesn't store any inference information in the bound change, such that in conflict analysis, this change
5279  *  is treated like a branching decision
5280  *
5281  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5282  *           SCIPgetVars()) gets resorted.
5283  *
5284  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5285  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5286  *
5287  *  @pre This method can be called if @p scip is in one of the following stages:
5288  *       - \ref SCIP_STAGE_PROBLEM
5289  *       - \ref SCIP_STAGE_PRESOLVING
5290  *       - \ref SCIP_STAGE_SOLVING
5291  *
5292  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5293  */
SCIPtightenVarUb(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5294 SCIP_RETCODE SCIPtightenVarUb(
5295    SCIP*                 scip,               /**< SCIP data structure */
5296    SCIP_VAR*             var,                /**< variable to change the bound for */
5297    SCIP_Real             newbound,           /**< new value for bound */
5298    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5299    SCIP_Bool*            infeasible,         /**< pointer to store whether the new domain is empty */
5300    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5301    )
5302 {
5303    SCIP_Real lb;
5304    SCIP_Real ub;
5305 
5306    assert(infeasible != NULL);
5307    SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5308 
5309    /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */
5310    assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip));
5311 
5312    *infeasible = FALSE;
5313    if( tightened != NULL )
5314       *tightened = FALSE;
5315 
5316    SCIPvarAdjustUb(var, scip->set, &newbound);
5317 
5318    /* ignore tightenings of upper bounds to -infinity during solving process */
5319    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5320    {
5321 #ifndef NDEBUG
5322       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5323          SCIPvarGetUbLocal(var));
5324 #endif
5325       return SCIP_OKAY;
5326    }
5327 
5328    /* get current bounds */
5329    lb = SCIPcomputeVarLbLocal(scip, var);
5330    ub = SCIPcomputeVarUbLocal(scip, var);
5331    assert(SCIPsetIsLE(scip->set, lb, ub));
5332 
5333    if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
5334    {
5335       *infeasible = TRUE;
5336       return SCIP_OKAY;
5337    }
5338    newbound = MAX(newbound, lb);
5339 
5340    if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
5341       return SCIP_OKAY;
5342 
5343    switch( scip->set->stage )
5344    {
5345    case SCIP_STAGE_PROBLEM:
5346       assert(!SCIPvarIsTransformed(var));
5347       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5348             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5349       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5350             scip->branchcand, scip->eventqueue, newbound) );
5351       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5352       break;
5353    case SCIP_STAGE_TRANSFORMED:
5354       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5355             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5356       break;
5357    case SCIP_STAGE_PRESOLVING:
5358       if( !SCIPinProbing(scip) )
5359       {
5360          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5361          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5362 
5363          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5364                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5365                SCIP_BOUNDTYPE_UPPER, FALSE) );
5366 
5367          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5368          {
5369             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5370             assert(!(*infeasible));
5371          }
5372          break;
5373       }
5374       /*lint -fallthrough*/
5375    case SCIP_STAGE_SOLVING:
5376       SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5377             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5378             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
5379       break;
5380 
5381    default:
5382       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5383       return SCIP_INVALIDCALL;
5384    }  /*lint !e788*/
5385 
5386    /* check whether the upper bound improved */
5387    if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
5388       *tightened = TRUE;
5389 
5390    return SCIP_OKAY;
5391 }
5392 
5393 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening
5394  *  epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is
5395  *  stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change
5396  *
5397  *  @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method
5398  *        changes first the lowerbound by calling SCIPinferVarLbCons and second the upperbound by calling
5399  *        SCIPinferVarUbCons
5400  *
5401  *  @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via
5402  *        SCIPgetVars()) gets resorted.
5403  *
5404  *  @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable.
5405  */
SCIPinferVarFixCons(SCIP * scip,SCIP_VAR * var,SCIP_Real fixedval,SCIP_CONS * infercons,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5406 SCIP_RETCODE SCIPinferVarFixCons(
5407    SCIP*                 scip,               /**< SCIP data structure */
5408    SCIP_VAR*             var,                /**< variable to change the bound for */
5409    SCIP_Real             fixedval,           /**< new value for fixation */
5410    SCIP_CONS*            infercons,          /**< constraint that deduced the bound change */
5411    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5412    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5413    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5414    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5415    )
5416 {
5417    assert(scip != NULL);
5418    assert(var != NULL);
5419    assert(infeasible != NULL);
5420 
5421    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5422 
5423    if( tightened != NULL )
5424       *tightened = FALSE;
5425 
5426    /* in presolving case we take the shortcut to directly fix the variables */
5427    if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5428    {
5429       SCIP_Bool fixed;
5430 
5431       SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5432             scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter,
5433             scip->eventqueue, scip->cliquetable, fixedval, infeasible, &fixed) );
5434 
5435       if( tightened != NULL )
5436 	 *tightened = fixed;
5437    }
5438    /* otherwise we use the lb and ub methods */
5439    else
5440    {
5441       SCIP_Bool lbtightened;
5442 
5443       SCIP_CALL( SCIPinferVarLbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, &lbtightened) );
5444 
5445       if( ! (*infeasible) )
5446       {
5447 	 SCIP_CALL( SCIPinferVarUbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, tightened) );
5448 
5449 	 if( tightened != NULL )
5450 	    *tightened |= lbtightened;
5451       }
5452    }
5453 
5454    return SCIP_OKAY;
5455 }
5456 
5457 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5458  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5459  *  the given inference constraint is stored, such that the conflict analysis is able to find out the reason
5460  *  for the deduction of the bound change
5461  *
5462  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5463  *           SCIPgetVars()) gets resorted.
5464  *
5465  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5466  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5467  *
5468  *  @pre This method can be called if @p scip is in one of the following stages:
5469  *       - \ref SCIP_STAGE_PROBLEM
5470  *       - \ref SCIP_STAGE_PRESOLVING
5471  *       - \ref SCIP_STAGE_SOLVING
5472  *
5473  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5474  */
SCIPinferVarLbCons(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_CONS * infercons,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5475 SCIP_RETCODE SCIPinferVarLbCons(
5476    SCIP*                 scip,               /**< SCIP data structure */
5477    SCIP_VAR*             var,                /**< variable to change the bound for */
5478    SCIP_Real             newbound,           /**< new value for bound */
5479    SCIP_CONS*            infercons,          /**< constraint that deduced the bound change */
5480    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5481    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5482    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5483    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5484    )
5485 {
5486    SCIP_Real lb;
5487    SCIP_Real ub;
5488 
5489    assert(infeasible != NULL);
5490 
5491    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5492 
5493    *infeasible = FALSE;
5494    if( tightened != NULL )
5495       *tightened = FALSE;
5496 
5497    SCIPvarAdjustLb(var, scip->set, &newbound);
5498 
5499    /* ignore tightenings of lower bounds to +infinity during solving process */
5500    if( SCIPisInfinity(scip, newbound)  && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5501    {
5502 #ifndef NDEBUG
5503       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5504          SCIPvarGetLbLocal(var));
5505 #endif
5506       return SCIP_OKAY;
5507    }
5508 
5509    /* get current bounds */
5510    lb = SCIPvarGetLbLocal(var);
5511    ub = SCIPvarGetUbLocal(var);
5512    assert(SCIPsetIsLE(scip->set, lb, ub));
5513 
5514    if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5515    {
5516       *infeasible = TRUE;
5517       return SCIP_OKAY;
5518    }
5519    newbound = MIN(newbound, ub);
5520 
5521    if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
5522       return SCIP_OKAY;
5523 
5524    switch( scip->set->stage )
5525    {
5526    case SCIP_STAGE_PROBLEM:
5527       assert(!SCIPvarIsTransformed(var));
5528       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5529             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5530       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5531             scip->branchcand, scip->eventqueue, newbound) );
5532       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5533       break;
5534 
5535    case SCIP_STAGE_PRESOLVING:
5536       if( !SCIPinProbing(scip) )
5537       {
5538          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5539          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5540 
5541          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5542                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5543                SCIP_BOUNDTYPE_LOWER, FALSE) );
5544 
5545          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5546          {
5547             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5548             assert(!(*infeasible));
5549          }
5550          break;
5551       }
5552       /*lint -fallthrough*/
5553    case SCIP_STAGE_SOLVING:
5554       SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5555             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5556             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) );
5557       break;
5558 
5559    default:
5560       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5561       return SCIP_INVALIDCALL;
5562    }  /*lint !e788*/
5563 
5564    /* check whether the lower bound improved */
5565    if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5566       *tightened = TRUE;
5567 
5568    return SCIP_OKAY;
5569 }
5570 
5571 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5572  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5573  *  the given inference constraint is stored, such that the conflict analysis is able to find out the reason
5574  *  for the deduction of the bound change
5575  *
5576  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5577  *           SCIPgetVars()) gets resorted.
5578  *
5579  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5580  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5581  *
5582  *  @pre This method can be called if @p scip is in one of the following stages:
5583  *       - \ref SCIP_STAGE_PROBLEM
5584  *       - \ref SCIP_STAGE_PRESOLVING
5585  *       - \ref SCIP_STAGE_SOLVING
5586  *
5587  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5588  */
SCIPinferVarUbCons(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_CONS * infercons,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5589 SCIP_RETCODE SCIPinferVarUbCons(
5590    SCIP*                 scip,               /**< SCIP data structure */
5591    SCIP_VAR*             var,                /**< variable to change the bound for */
5592    SCIP_Real             newbound,           /**< new value for bound */
5593    SCIP_CONS*            infercons,          /**< constraint that deduced the bound change */
5594    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5595    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5596    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5597    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5598    )
5599 {
5600    SCIP_Real lb;
5601    SCIP_Real ub;
5602 
5603    assert(infeasible != NULL);
5604 
5605    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5606 
5607    *infeasible = FALSE;
5608    if( tightened != NULL )
5609       *tightened = FALSE;
5610 
5611    SCIPvarAdjustUb(var, scip->set, &newbound);
5612 
5613    /* ignore tightenings of upper bounds to -infinity during solving process */
5614    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5615    {
5616 #ifndef NDEBUG
5617       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5618          SCIPvarGetUbLocal(var));
5619 #endif
5620       return SCIP_OKAY;
5621    }
5622 
5623    /* get current bounds */
5624    lb = SCIPvarGetLbLocal(var);
5625    ub = SCIPvarGetUbLocal(var);
5626    assert(SCIPsetIsLE(scip->set, lb, ub));
5627 
5628    if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
5629    {
5630       *infeasible = TRUE;
5631       return SCIP_OKAY;
5632    }
5633    newbound = MAX(newbound, lb);
5634 
5635    if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
5636       return SCIP_OKAY;
5637 
5638    switch( scip->set->stage )
5639    {
5640    case SCIP_STAGE_PROBLEM:
5641       assert(!SCIPvarIsTransformed(var));
5642       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5643             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5644       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5645             scip->branchcand, scip->eventqueue, newbound) );
5646       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5647       break;
5648 
5649    case SCIP_STAGE_PRESOLVING:
5650       if( !SCIPinProbing(scip) )
5651       {
5652          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5653          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5654 
5655          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5656                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5657                SCIP_BOUNDTYPE_UPPER, FALSE) );
5658 
5659          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5660          {
5661             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5662             assert(!(*infeasible));
5663          }
5664          break;
5665       }
5666       /*lint -fallthrough*/
5667    case SCIP_STAGE_SOLVING:
5668       SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5669             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5670             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) );
5671       break;
5672 
5673    default:
5674       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5675       return SCIP_INVALIDCALL;
5676    }  /*lint !e788*/
5677 
5678    /* check whether the upper bound improved */
5679    if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
5680       *tightened = TRUE;
5681 
5682    return SCIP_OKAY;
5683 }
5684 
5685 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node;
5686  *  the given inference constraint is stored, such that the conflict analysis is able to find out the reason for the
5687  *  deduction of the fixing
5688  *
5689  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5690  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5691  *
5692  *  @pre This method can be called if @p scip is in one of the following stages:
5693  *       - \ref SCIP_STAGE_PROBLEM
5694  *       - \ref SCIP_STAGE_PRESOLVING
5695  *       - \ref SCIP_STAGE_SOLVING
5696  */
SCIPinferBinvarCons(SCIP * scip,SCIP_VAR * var,SCIP_Bool fixedval,SCIP_CONS * infercons,int inferinfo,SCIP_Bool * infeasible,SCIP_Bool * tightened)5697 SCIP_RETCODE SCIPinferBinvarCons(
5698    SCIP*                 scip,               /**< SCIP data structure */
5699    SCIP_VAR*             var,                /**< binary variable to fix */
5700    SCIP_Bool             fixedval,           /**< value to fix binary variable to */
5701    SCIP_CONS*            infercons,          /**< constraint that deduced the fixing */
5702    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5703    SCIP_Bool*            infeasible,         /**< pointer to store whether the fixing is infeasible */
5704    SCIP_Bool*            tightened           /**< pointer to store whether the fixing tightened the local bounds, or NULL */
5705    )
5706 {
5707    SCIP_Real lb;
5708    SCIP_Real ub;
5709 
5710    assert(SCIPvarIsBinary(var));
5711    assert(fixedval == TRUE || fixedval == FALSE);
5712    assert(infeasible != NULL);
5713 
5714    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5715 
5716    *infeasible = FALSE;
5717    if( tightened != NULL )
5718       *tightened = FALSE;
5719 
5720    /* get current bounds */
5721    lb = SCIPvarGetLbLocal(var);
5722    ub = SCIPvarGetUbLocal(var);
5723    assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0));
5724    assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0));
5725    assert(SCIPsetIsLE(scip->set, lb, ub));
5726 
5727    /* check, if variable is already fixed */
5728    if( (lb > 0.5) || (ub < 0.5) )
5729    {
5730       *infeasible = (fixedval == (lb < 0.5));
5731 
5732       return SCIP_OKAY;
5733    }
5734 
5735    /* apply the fixing */
5736    switch( scip->set->stage )
5737    {
5738    case SCIP_STAGE_PROBLEM:
5739       assert(!SCIPvarIsTransformed(var));
5740       if( fixedval == TRUE )
5741       {
5742          SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
5743       }
5744       else
5745       {
5746          SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
5747       }
5748       break;
5749 
5750    case SCIP_STAGE_PRESOLVING:
5751       if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5752       {
5753          SCIP_Bool fixed;
5754 
5755          SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5756                scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
5757                scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) );
5758          break;
5759       }
5760       /*lint -fallthrough*/
5761    case SCIP_STAGE_SOLVING:
5762       if( fixedval == TRUE )
5763       {
5764          SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5765                scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5766                scip->cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) );
5767       }
5768       else
5769       {
5770          SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5771                scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5772                scip->cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) );
5773       }
5774       break;
5775 
5776    default:
5777       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5778       return SCIP_INVALIDCALL;
5779    }  /*lint !e788*/
5780 
5781    if( tightened != NULL )
5782       *tightened = TRUE;
5783 
5784    return SCIP_OKAY;
5785 }
5786 
5787 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening
5788  *  epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is
5789  *  stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change
5790  *
5791  *  @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method
5792  *        changes first the lowerbound by calling SCIPinferVarLbProp and second the upperbound by calling
5793  *        SCIPinferVarUbProp
5794  *
5795  *  @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via
5796  *        SCIPgetVars()) gets resorted.
5797  *
5798  *  @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable.
5799  */
SCIPinferVarFixProp(SCIP * scip,SCIP_VAR * var,SCIP_Real fixedval,SCIP_PROP * inferprop,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5800 SCIP_RETCODE SCIPinferVarFixProp(
5801    SCIP*                 scip,               /**< SCIP data structure */
5802    SCIP_VAR*             var,                /**< variable to change the bound for */
5803    SCIP_Real             fixedval,           /**< new value for fixation */
5804    SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change */
5805    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5806    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5807    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5808    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5809    )
5810 {
5811    assert(scip != NULL);
5812    assert(var != NULL);
5813    assert(infeasible != NULL);
5814 
5815    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5816 
5817    if( tightened != NULL )
5818       *tightened = FALSE;
5819 
5820    /* in presolving case we take the shortcut to directly fix the variables */
5821    if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5822    {
5823       SCIP_Bool fixed;
5824 
5825       SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5826             scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
5827             scip->cliquetable, fixedval, infeasible, &fixed) );
5828 
5829       if( tightened != NULL )
5830 	 *tightened = fixed;
5831    }
5832    /* otherwise we use the lb and ub methods */
5833    else
5834    {
5835       SCIP_Bool lbtightened;
5836 
5837       SCIP_CALL( SCIPinferVarLbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, &lbtightened) );
5838 
5839       if( ! (*infeasible) )
5840       {
5841 	 SCIP_CALL( SCIPinferVarUbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, tightened) );
5842 
5843 	 if( tightened != NULL )
5844 	    *tightened |= lbtightened;
5845       }
5846    }
5847 
5848    return SCIP_OKAY;
5849 }
5850 
5851 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5852  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5853  *  the given inference propagator is stored, such that the conflict analysis is able to find out the reason
5854  *  for the deduction of the bound change
5855  *
5856  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5857  *           SCIPgetVars()) gets resorted.
5858  *
5859  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5860  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5861  *
5862  *  @pre This method can be called if @p scip is in one of the following stages:
5863  *       - \ref SCIP_STAGE_PROBLEM
5864  *       - \ref SCIP_STAGE_PRESOLVING
5865  *       - \ref SCIP_STAGE_SOLVING
5866  *
5867  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5868  */
SCIPinferVarLbProp(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_PROP * inferprop,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5869 SCIP_RETCODE SCIPinferVarLbProp(
5870    SCIP*                 scip,               /**< SCIP data structure */
5871    SCIP_VAR*             var,                /**< variable to change the bound for */
5872    SCIP_Real             newbound,           /**< new value for bound */
5873    SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change */
5874    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5875    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5876    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5877    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5878    )
5879 {
5880    SCIP_Real lb;
5881    SCIP_Real ub;
5882 
5883    assert(infeasible != NULL);
5884 
5885    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5886 
5887    *infeasible = FALSE;
5888    if( tightened != NULL )
5889       *tightened = FALSE;
5890 
5891    SCIPvarAdjustLb(var, scip->set, &newbound);
5892 
5893    /* ignore tightenings of lower bounds to +infinity during solving process */
5894    if( SCIPisInfinity(scip, newbound)  && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5895    {
5896 #ifndef NDEBUG
5897       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5898          SCIPvarGetLbLocal(var));
5899 #endif
5900       return SCIP_OKAY;
5901    }
5902 
5903    /* get current bounds */
5904    lb = SCIPvarGetLbLocal(var);
5905    ub = SCIPvarGetUbLocal(var);
5906    assert(SCIPsetIsLE(scip->set, lb, ub));
5907 
5908    if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5909    {
5910       *infeasible = TRUE;
5911       return SCIP_OKAY;
5912    }
5913    newbound = MIN(newbound, ub);
5914 
5915    if( (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub))
5916       || SCIPsetIsLE(scip->set, newbound, lb) )
5917       return SCIP_OKAY;
5918 
5919    switch( scip->set->stage )
5920    {
5921    case SCIP_STAGE_PROBLEM:
5922       assert(!SCIPvarIsTransformed(var));
5923       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5924             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5925       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5926             scip->branchcand, scip->eventqueue, newbound) );
5927       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5928       break;
5929 
5930    case SCIP_STAGE_PRESOLVING:
5931       if( !SCIPinProbing(scip) )
5932       {
5933          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5934          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5935 
5936          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5937                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5938                SCIP_BOUNDTYPE_LOWER, FALSE) );
5939 
5940          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5941          {
5942             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5943             assert(!(*infeasible));
5944          }
5945          break;
5946       }
5947       /*lint -fallthrough*/
5948    case SCIP_STAGE_SOLVING:
5949       SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5950             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5951             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) );
5952       break;
5953 
5954    default:
5955       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5956       return SCIP_INVALIDCALL;
5957    }  /*lint !e788*/
5958 
5959    /* check whether the lower bound improved */
5960    if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5961       *tightened = TRUE;
5962 
5963    return SCIP_OKAY;
5964 }
5965 
5966 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5967  *  (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5968  *  the given inference propagator is stored, such that the conflict analysis is able to find out the reason
5969  *  for the deduction of the bound change
5970  *
5971  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5972  *           SCIPgetVars()) gets resorted.
5973  *
5974  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5975  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5976  *
5977  *  @pre This method can be called if @p scip is in one of the following stages:
5978  *       - \ref SCIP_STAGE_PROBLEM
5979  *       - \ref SCIP_STAGE_PRESOLVING
5980  *       - \ref SCIP_STAGE_SOLVING
5981  *
5982  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5983  */
SCIPinferVarUbProp(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_PROP * inferprop,int inferinfo,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)5984 SCIP_RETCODE SCIPinferVarUbProp(
5985    SCIP*                 scip,               /**< SCIP data structure */
5986    SCIP_VAR*             var,                /**< variable to change the bound for */
5987    SCIP_Real             newbound,           /**< new value for bound */
5988    SCIP_PROP*            inferprop,          /**< propagator that deduced the bound change */
5989    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
5990    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
5991    SCIP_Bool*            infeasible,         /**< pointer to store whether the bound change is infeasible */
5992    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
5993    )
5994 {
5995    SCIP_Real lb;
5996    SCIP_Real ub;
5997 
5998    assert(infeasible != NULL);
5999 
6000    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6001 
6002    *infeasible = FALSE;
6003    if( tightened != NULL )
6004       *tightened = FALSE;
6005 
6006    SCIPvarAdjustUb(var, scip->set, &newbound);
6007 
6008    /* ignore tightenings of upper bounds to -infinity during solving process */
6009    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6010    {
6011 #ifndef NDEBUG
6012       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
6013          SCIPvarGetUbLocal(var));
6014 #endif
6015       return SCIP_OKAY;
6016    }
6017 
6018    /* get current bounds */
6019    lb = SCIPvarGetLbLocal(var);
6020    ub = SCIPvarGetUbLocal(var);
6021    assert(SCIPsetIsLE(scip->set, lb, ub));
6022 
6023    if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
6024    {
6025       *infeasible = TRUE;
6026       return SCIP_OKAY;
6027    }
6028    newbound = MAX(newbound, lb);
6029 
6030    if( (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub))
6031       || SCIPsetIsGE(scip->set, newbound, ub) )
6032       return SCIP_OKAY;
6033 
6034    switch( scip->set->stage )
6035    {
6036    case SCIP_STAGE_PROBLEM:
6037       assert(!SCIPvarIsTransformed(var));
6038       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6039             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6040       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6041             scip->branchcand, scip->eventqueue, newbound) );
6042       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
6043       break;
6044 
6045    case SCIP_STAGE_PRESOLVING:
6046       if( !SCIPinProbing(scip) )
6047       {
6048          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6049          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6050 
6051          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6052                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6053                SCIP_BOUNDTYPE_UPPER, FALSE) );
6054 
6055          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6056          {
6057             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6058             assert(!(*infeasible));
6059          }
6060          break;
6061       }
6062       /*lint -fallthrough*/
6063    case SCIP_STAGE_SOLVING:
6064       SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6065             scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
6066             scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) );
6067       break;
6068 
6069    default:
6070       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6071       return SCIP_INVALIDCALL;
6072    }  /*lint !e788*/
6073 
6074    /* check whether the upper bound improved */
6075    if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
6076       *tightened = TRUE;
6077 
6078    return SCIP_OKAY;
6079 }
6080 
6081 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node;
6082  *  the given inference propagator is stored, such that the conflict analysis is able to find out the reason for the
6083  *  deduction of the fixing
6084  *
6085  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6086  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6087  *
6088  *  @pre This method can be called if @p scip is in one of the following stages:
6089  *       - \ref SCIP_STAGE_PROBLEM
6090  *       - \ref SCIP_STAGE_PRESOLVING
6091  *       - \ref SCIP_STAGE_PRESOLVED
6092  *       - \ref SCIP_STAGE_SOLVING
6093  */
SCIPinferBinvarProp(SCIP * scip,SCIP_VAR * var,SCIP_Bool fixedval,SCIP_PROP * inferprop,int inferinfo,SCIP_Bool * infeasible,SCIP_Bool * tightened)6094 SCIP_RETCODE SCIPinferBinvarProp(
6095    SCIP*                 scip,               /**< SCIP data structure */
6096    SCIP_VAR*             var,                /**< binary variable to fix */
6097    SCIP_Bool             fixedval,           /**< value to fix binary variable to */
6098    SCIP_PROP*            inferprop,          /**< propagator that deduced the fixing */
6099    int                   inferinfo,          /**< user information for inference to help resolving the conflict */
6100    SCIP_Bool*            infeasible,         /**< pointer to store whether the fixing is infeasible */
6101    SCIP_Bool*            tightened           /**< pointer to store whether the fixing tightened the local bounds, or NULL */
6102    )
6103 {
6104    SCIP_Real lb;
6105    SCIP_Real ub;
6106 
6107    assert(SCIPvarIsBinary(var));
6108    assert(fixedval == TRUE || fixedval == FALSE);
6109    assert(infeasible != NULL);
6110 
6111    SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6112 
6113    *infeasible = FALSE;
6114    if( tightened != NULL )
6115       *tightened = FALSE;
6116 
6117    /* get current bounds */
6118    lb = SCIPvarGetLbLocal(var);
6119    ub = SCIPvarGetUbLocal(var);
6120    assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0));
6121    assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0));
6122    assert(SCIPsetIsLE(scip->set, lb, ub));
6123 
6124    /* check, if variable is already fixed */
6125    if( (lb > 0.5) || (ub < 0.5) )
6126    {
6127       *infeasible = (fixedval == (lb < 0.5));
6128 
6129       return SCIP_OKAY;
6130    }
6131 
6132    /* apply the fixing */
6133    switch( scip->set->stage )
6134    {
6135    case SCIP_STAGE_PROBLEM:
6136       assert(!SCIPvarIsTransformed(var));
6137       if( fixedval == TRUE )
6138       {
6139          SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
6140       }
6141       else
6142       {
6143          SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
6144       }
6145       break;
6146 
6147    case SCIP_STAGE_PRESOLVING:
6148       if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
6149       {
6150          SCIP_Bool fixed;
6151 
6152          SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6153                scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
6154                scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) );
6155          break;
6156       }
6157       /*lint -fallthrough*/
6158    case SCIP_STAGE_SOLVING:
6159       if( fixedval == TRUE )
6160       {
6161          SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6162                scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 1.0,
6163                SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) );
6164       }
6165       else
6166       {
6167          SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6168                scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 0.0,
6169                SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) );
6170       }
6171       break;
6172 
6173    default:
6174       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6175       return SCIP_INVALIDCALL;
6176    }  /*lint !e788*/
6177 
6178    if( tightened != NULL )
6179       *tightened = TRUE;
6180 
6181    return SCIP_OKAY;
6182 }
6183 
6184 /** changes global lower bound of variable in preprocessing or in the current node, if the new bound is tighter
6185  *  (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value;
6186  *  also tightens the local bound, if the global bound is better than the local bound
6187  *
6188  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
6189  *           SCIPgetVars()) gets resorted.
6190  *
6191  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6192  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6193  *
6194  *  @pre This method can be called if @p scip is in one of the following stages:
6195  *       - \ref SCIP_STAGE_PROBLEM
6196  *       - \ref SCIP_STAGE_TRANSFORMING
6197  *       - \ref SCIP_STAGE_PRESOLVING
6198  *       - \ref SCIP_STAGE_SOLVING
6199  *
6200  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
6201  */
SCIPtightenVarLbGlobal(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)6202 SCIP_RETCODE SCIPtightenVarLbGlobal(
6203    SCIP*                 scip,               /**< SCIP data structure */
6204    SCIP_VAR*             var,                /**< variable to change the bound for */
6205    SCIP_Real             newbound,           /**< new value for bound */
6206    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
6207    SCIP_Bool*            infeasible,         /**< pointer to store whether the new domain is empty */
6208    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
6209    )
6210 {
6211    SCIP_Real lb;
6212    SCIP_Real ub;
6213 
6214    assert(infeasible != NULL);
6215 
6216    SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6217 
6218    *infeasible = FALSE;
6219    if( tightened != NULL )
6220       *tightened = FALSE;
6221 
6222    SCIPvarAdjustLb(var, scip->set, &newbound);
6223 
6224    /* ignore tightenings of lower bounds to +infinity during solving process */
6225    if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6226    {
6227 #ifndef NDEBUG
6228       SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
6229          SCIPvarGetLbLocal(var));
6230 #endif
6231       return SCIP_OKAY;
6232    }
6233 
6234    /* get current bounds */
6235    lb = SCIPvarGetLbGlobal(var);
6236    ub = SCIPvarGetUbGlobal(var);
6237    assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub));
6238 
6239    if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
6240    {
6241       *infeasible = TRUE;
6242       return SCIP_OKAY;
6243    }
6244    newbound = MIN(newbound, ub);
6245 
6246    /* bound changes of less than epsilon are ignored by SCIPvarChgLb or raise an assert in SCIPnodeAddBoundinfer,
6247     * so don't apply them even if force is set
6248     */
6249    if( SCIPsetIsEQ(scip->set, lb, newbound) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
6250       return SCIP_OKAY;
6251 
6252    switch( scip->set->stage )
6253    {
6254    case SCIP_STAGE_PROBLEM:
6255       assert(!SCIPvarIsTransformed(var));
6256       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6257             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6258       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6259             scip->branchcand, scip->eventqueue, newbound) );
6260       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
6261       break;
6262 
6263    case SCIP_STAGE_TRANSFORMING:
6264       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6265             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6266       break;
6267 
6268    case SCIP_STAGE_PRESOLVING:
6269       if( !SCIPinProbing(scip) )
6270       {
6271          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6272          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6273 
6274          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6275                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6276                SCIP_BOUNDTYPE_LOWER, FALSE) );
6277 
6278          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6279          {
6280             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6281             assert(!(*infeasible));
6282          }
6283          break;
6284       }
6285       /*lint -fallthrough*/
6286    case SCIP_STAGE_SOLVING:
6287       SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6288             scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6289             SCIP_BOUNDTYPE_LOWER, FALSE) );
6290       break;
6291 
6292    default:
6293       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6294       return SCIP_INVALIDCALL;
6295    }  /*lint !e788*/
6296 
6297    /* coverity: unreachable code */
6298    if( tightened != NULL && lb < SCIPcomputeVarLbGlobal(scip, var) )
6299       *tightened = TRUE;
6300 
6301    return SCIP_OKAY;
6302 }
6303 
6304 /** changes global upper bound of variable in preprocessing or in the current node, if the new bound is tighter
6305  *  (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value;
6306  *  also tightens the local bound, if the global bound is better than the local bound
6307  *
6308  *  @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
6309  *           SCIPgetVars()) gets resorted.
6310  *
6311  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6312  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6313  *
6314  *  @pre This method can be called if @p scip is in one of the following stages:
6315  *       - \ref SCIP_STAGE_PROBLEM
6316  *       - \ref SCIP_STAGE_TRANSFORMING
6317  *       - \ref SCIP_STAGE_PRESOLVING
6318  *       - \ref SCIP_STAGE_SOLVING
6319  *
6320  *  @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
6321  */
SCIPtightenVarUbGlobal(SCIP * scip,SCIP_VAR * var,SCIP_Real newbound,SCIP_Bool force,SCIP_Bool * infeasible,SCIP_Bool * tightened)6322 SCIP_RETCODE SCIPtightenVarUbGlobal(
6323    SCIP*                 scip,               /**< SCIP data structure */
6324    SCIP_VAR*             var,                /**< variable to change the bound for */
6325    SCIP_Real             newbound,           /**< new value for bound */
6326    SCIP_Bool             force,              /**< force tightening even if below bound strengthening tolerance */
6327    SCIP_Bool*            infeasible,         /**< pointer to store whether the new domain is empty */
6328    SCIP_Bool*            tightened           /**< pointer to store whether the bound was tightened, or NULL */
6329    )
6330 {
6331    SCIP_Real lb;
6332    SCIP_Real ub;
6333 
6334    assert(infeasible != NULL);
6335 
6336    SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6337 
6338    *infeasible = FALSE;
6339    if( tightened != NULL )
6340       *tightened = FALSE;
6341 
6342    SCIPvarAdjustUb(var, scip->set, &newbound);
6343 
6344    /* ignore tightenings of upper bounds to -infinity during solving process */
6345    if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6346    {
6347 #ifndef NDEBUG
6348       SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
6349          SCIPvarGetUbLocal(var));
6350 #endif
6351       return SCIP_OKAY;
6352    }
6353 
6354    /* get current bounds */
6355    lb = SCIPvarGetLbGlobal(var);
6356    ub = SCIPvarGetUbGlobal(var);
6357    assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub));
6358 
6359    if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
6360    {
6361       *infeasible = TRUE;
6362       return SCIP_OKAY;
6363    }
6364    newbound = MAX(newbound, lb);
6365 
6366    /* bound changes of less than epsilon are ignored by SCIPvarChgUb or raise an assert in SCIPnodeAddBoundinfer,
6367     * so don't apply them even if force is set
6368     */
6369    if( SCIPsetIsEQ(scip->set, ub, newbound) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
6370       return SCIP_OKAY;
6371 
6372    switch( scip->set->stage )
6373    {
6374    case SCIP_STAGE_PROBLEM:
6375       assert(!SCIPvarIsTransformed(var));
6376       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6377             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6378       SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6379             scip->branchcand, scip->eventqueue, newbound) );
6380       SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
6381       break;
6382 
6383    case SCIP_STAGE_TRANSFORMING:
6384       SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6385             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6386       break;
6387 
6388    case SCIP_STAGE_PRESOLVING:
6389       if( !SCIPinProbing(scip) )
6390       {
6391          assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6392          assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6393 
6394          SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6395                scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6396                SCIP_BOUNDTYPE_UPPER, FALSE) );
6397 
6398          if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6399          {
6400             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6401             assert(!(*infeasible));
6402          }
6403          break;
6404       }
6405       /*lint -fallthrough*/
6406    case SCIP_STAGE_SOLVING:
6407       SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6408             scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6409             SCIP_BOUNDTYPE_UPPER, FALSE) );
6410       break;
6411 
6412    default:
6413       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6414       return SCIP_INVALIDCALL;
6415    }  /*lint !e788*/
6416 
6417    /* coverity: unreachable code */
6418    if( tightened != NULL && ub > SCIPcomputeVarUbGlobal(scip, var) )
6419       *tightened = TRUE;
6420 
6421    return SCIP_OKAY;
6422 }
6423 
6424 /* some simple variable functions implemented as defines */
6425 #undef SCIPcomputeVarLbGlobal
6426 #undef SCIPcomputeVarUbGlobal
6427 #undef SCIPcomputeVarLbLocal
6428 #undef SCIPcomputeVarUbLocal
6429 
6430 /** for a multi-aggregated variable, returns the global lower bound computed by adding the global bounds from all aggregation variables
6431  *
6432  *  This global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is not updated if bounds of aggregation variables are changing
6433  *  calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbGlobal.
6434  *
6435  *  @return the global lower bound computed by adding the global bounds from all aggregation variables
6436  */
SCIPcomputeVarLbGlobal(SCIP * scip,SCIP_VAR * var)6437 SCIP_Real SCIPcomputeVarLbGlobal(
6438    SCIP*                 scip,               /**< SCIP data structure */
6439    SCIP_VAR*             var                 /**< variable to compute the bound for */
6440    )
6441 {
6442    assert(scip != NULL);
6443    assert(var != NULL);
6444 
6445    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6446       return SCIPvarGetMultaggrLbGlobal(var, scip->set);
6447    else
6448       return SCIPvarGetLbGlobal(var);
6449 }
6450 
6451 /** for a multi-aggregated variable, returns the global upper bound computed by adding the global bounds from all aggregation variables
6452  *
6453  *  This global bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is not updated if bounds of aggregation variables are changing
6454  *  calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbGlobal
6455  *
6456  *  @return the global upper bound computed by adding the global bounds from all aggregation variables
6457  */
SCIPcomputeVarUbGlobal(SCIP * scip,SCIP_VAR * var)6458 SCIP_Real SCIPcomputeVarUbGlobal(
6459    SCIP*                 scip,               /**< SCIP data structure */
6460    SCIP_VAR*             var                 /**< variable to compute the bound for */
6461    )
6462 {
6463    assert(scip != NULL);
6464    assert(var != NULL);
6465 
6466    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6467       return SCIPvarGetMultaggrUbGlobal(var, scip->set);
6468    else
6469       return SCIPvarGetUbGlobal(var);
6470 }
6471 
6472 /** for a multi-aggregated variable, returns the local lower bound computed by adding the local bounds from all aggregation variables
6473  *
6474  *  This local bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing
6475  *  calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbLocal.
6476  *
6477  *  @return the local lower bound computed by adding the global bounds from all aggregation variables
6478  */
SCIPcomputeVarLbLocal(SCIP * scip,SCIP_VAR * var)6479 SCIP_Real SCIPcomputeVarLbLocal(
6480    SCIP*                 scip,               /**< SCIP data structure */
6481    SCIP_VAR*             var                 /**< variable to compute the bound for */
6482    )
6483 {
6484    assert(scip != NULL);
6485    assert(var != NULL);
6486 
6487    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6488       return SCIPvarGetMultaggrLbLocal(var, scip->set);
6489    else
6490       return SCIPvarGetLbLocal(var);
6491 }
6492 
6493 /** for a multi-aggregated variable, returns the local upper bound computed by adding the local bounds from all aggregation variables
6494  *
6495  *  This local bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is not updated if bounds of aggregation variables are changing
6496  *  calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbLocal.
6497  *
6498  *  @return the local upper bound computed by adding the global bounds from all aggregation variables
6499  */
SCIPcomputeVarUbLocal(SCIP * scip,SCIP_VAR * var)6500 SCIP_Real SCIPcomputeVarUbLocal(
6501    SCIP*                 scip,               /**< SCIP data structure */
6502    SCIP_VAR*             var                 /**< variable to compute the bound for */
6503    )
6504 {
6505    assert(scip != NULL);
6506    assert(var != NULL);
6507 
6508    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6509       return SCIPvarGetMultaggrUbLocal(var, scip->set);
6510    else
6511       return SCIPvarGetUbLocal(var);
6512 }
6513 
6514 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
6515  *  aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
6516  *  not updated if bounds of aggregation variables are changing
6517  *
6518  *  calling this function for a non-multi-aggregated variable is not allowed
6519  */
SCIPgetVarMultaggrLbGlobal(SCIP * scip,SCIP_VAR * var)6520 SCIP_Real SCIPgetVarMultaggrLbGlobal(
6521    SCIP*                 scip,               /**< SCIP data structure */
6522    SCIP_VAR*             var                 /**< variable to compute the bound for */
6523    )
6524 {
6525    assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6526    return SCIPvarGetMultaggrLbGlobal(var, scip->set);
6527 }
6528 
6529 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
6530  *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
6531  *  not updated if bounds of aggregation variables are changing
6532  *
6533  *  calling this function for a non-multi-aggregated variable is not allowed
6534  */
SCIPgetVarMultaggrUbGlobal(SCIP * scip,SCIP_VAR * var)6535 SCIP_Real SCIPgetVarMultaggrUbGlobal(
6536    SCIP*                 scip,               /**< SCIP data structure */
6537    SCIP_VAR*             var                 /**< variable to compute the bound for */
6538    )
6539 {
6540    assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6541    return SCIPvarGetMultaggrUbGlobal(var, scip->set);
6542 }
6543 
6544 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
6545  *  aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
6546  *  not updated if bounds of aggregation variables are changing
6547  *
6548  *  calling this function for a non-multi-aggregated variable is not allowed
6549  */
SCIPgetVarMultaggrLbLocal(SCIP * scip,SCIP_VAR * var)6550 SCIP_Real SCIPgetVarMultaggrLbLocal(
6551    SCIP*                 scip,               /**< SCIP data structure */
6552    SCIP_VAR*             var                 /**< variable to compute the bound for */
6553    )
6554 {
6555    assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6556    return SCIPvarGetMultaggrLbLocal(var, scip->set);
6557 }
6558 
6559 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
6560  *  aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
6561  *  not updated if bounds of aggregation variables are changing
6562  *
6563  *  calling this function for a non-multi-aggregated variable is not allowed
6564  */
SCIPgetVarMultaggrUbLocal(SCIP * scip,SCIP_VAR * var)6565 SCIP_Real SCIPgetVarMultaggrUbLocal(
6566    SCIP*                 scip,               /**< SCIP data structure */
6567    SCIP_VAR*             var                 /**< variable to compute the bound for */
6568    )
6569 {
6570    assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6571    return SCIPvarGetMultaggrUbLocal(var, scip->set);
6572 }
6573 
6574 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal
6575  *  solution or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is
6576  *  available
6577  *
6578  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6579  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6580  *
6581  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
6582  */
SCIPgetVarClosestVlb(SCIP * scip,SCIP_VAR * var,SCIP_SOL * sol,SCIP_Real * closestvlb,int * closestvlbidx)6583 SCIP_RETCODE SCIPgetVarClosestVlb(
6584    SCIP*                 scip,               /**< SCIP data structure */
6585    SCIP_VAR*             var,                /**< active problem variable */
6586    SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
6587    SCIP_Real*            closestvlb,         /**< pointer to store the value of the closest variable lower bound */
6588    int*                  closestvlbidx       /**< pointer to store the index of the closest variable lower bound */
6589    )
6590 {
6591    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVlb", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6592 
6593    SCIPvarGetClosestVlb(var, sol, scip->set, scip->stat, closestvlb, closestvlbidx);
6594 
6595    return SCIP_OKAY;
6596 }
6597 
6598 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
6599  *  or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
6600  *
6601  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6602  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6603  *
6604  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
6605  */
SCIPgetVarClosestVub(SCIP * scip,SCIP_VAR * var,SCIP_SOL * sol,SCIP_Real * closestvub,int * closestvubidx)6606 SCIP_RETCODE SCIPgetVarClosestVub(
6607    SCIP*                 scip,               /**< SCIP data structure */
6608    SCIP_VAR*             var,                /**< active problem variable */
6609    SCIP_SOL*             sol,                /**< primal solution, or NULL for LP solution */
6610    SCIP_Real*            closestvub,         /**< pointer to store the value of the closest variable lower bound */
6611    int*                  closestvubidx       /**< pointer to store the index of the closest variable lower bound */
6612    )
6613 {
6614    SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVub", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6615 
6616    SCIPvarGetClosestVub(var, sol, scip->set, scip->stat, closestvub, closestvubidx);
6617 
6618    return SCIP_OKAY;
6619 }
6620 
6621 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
6622  *  if z is binary, the corresponding valid implication for z is also added;
6623  *  if z is non-continuous and 1/b not too small, the corresponding valid upper/lower bound
6624  *  z <= (x-d)/b or z >= (x-d)/b (depending on the sign of of b) is added, too;
6625  *  improves the global bounds of the variable and the vlb variable if possible
6626  *
6627  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6628  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6629  *
6630  *  @pre This method can be called if @p scip is in one of the following stages:
6631  *       - \ref SCIP_STAGE_PRESOLVING
6632  *       - \ref SCIP_STAGE_PRESOLVED
6633  *       - \ref SCIP_STAGE_SOLVING
6634  */
SCIPaddVarVlb(SCIP * scip,SCIP_VAR * var,SCIP_VAR * vlbvar,SCIP_Real vlbcoef,SCIP_Real vlbconstant,SCIP_Bool * infeasible,int * nbdchgs)6635 SCIP_RETCODE SCIPaddVarVlb(
6636    SCIP*                 scip,               /**< SCIP data structure */
6637    SCIP_VAR*             var,                /**< problem variable */
6638    SCIP_VAR*             vlbvar,             /**< variable z    in x >= b*z + d */
6639    SCIP_Real             vlbcoef,            /**< coefficient b in x >= b*z + d */
6640    SCIP_Real             vlbconstant,        /**< constant d    in x >= b*z + d */
6641    SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
6642    int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
6643    )
6644 {
6645    int nlocalbdchgs;
6646 
6647    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVlb", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6648 
6649    SCIP_CALL( SCIPvarAddVlb(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree,
6650          scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vlbvar, vlbcoef, vlbconstant,
6651          TRUE, infeasible, &nlocalbdchgs) );
6652 
6653    *nbdchgs = nlocalbdchgs;
6654 
6655    /* if x is not continuous we add a variable bound for z; do not add it if cofficient would be too small or we already
6656     * detected infeasibility
6657     */
6658    if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vlbcoef) )
6659    {
6660       if( vlbcoef > 0.0 )
6661       {
6662          /* if b > 0, we have a variable upper bound: x >= b*z + d  =>  z <= (x-d)/b */
6663          SCIP_CALL( SCIPvarAddVub(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6664                scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef,
6665                -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) );
6666       }
6667       else
6668       {
6669          /* if b < 0, we have a variable lower bound: x >= b*z + d  =>  z >= (x-d)/b */
6670          SCIP_CALL( SCIPvarAddVlb(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6671                scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef,
6672                -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) );
6673       }
6674       *nbdchgs += nlocalbdchgs;
6675    }
6676 
6677    return SCIP_OKAY;
6678 }
6679 
6680 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
6681  *  if z is binary, the corresponding valid implication for z is also added;
6682  *  if z is non-continuous and 1/b not too small, the corresponding valid lower/upper bound
6683  *  z >= (x-d)/b or z <= (x-d)/b (depending on the sign of of b) is added, too;
6684  *  improves the global bounds of the variable and the vlb variable if possible
6685  *
6686  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6687  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6688  *
6689  *  @pre This method can be called if @p scip is in one of the following stages:
6690  *       - \ref SCIP_STAGE_PRESOLVING
6691  *       - \ref SCIP_STAGE_PRESOLVED
6692  *       - \ref SCIP_STAGE_SOLVING
6693  */
SCIPaddVarVub(SCIP * scip,SCIP_VAR * var,SCIP_VAR * vubvar,SCIP_Real vubcoef,SCIP_Real vubconstant,SCIP_Bool * infeasible,int * nbdchgs)6694 SCIP_RETCODE SCIPaddVarVub(
6695    SCIP*                 scip,               /**< SCIP data structure */
6696    SCIP_VAR*             var,                /**< problem variable */
6697    SCIP_VAR*             vubvar,             /**< variable z    in x <= b*z + d */
6698    SCIP_Real             vubcoef,            /**< coefficient b in x <= b*z + d */
6699    SCIP_Real             vubconstant,        /**< constant d    in x <= b*z + d */
6700    SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
6701    int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
6702    )
6703 {
6704    int nlocalbdchgs;
6705 
6706    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVub", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6707 
6708    SCIP_CALL( SCIPvarAddVub(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree,
6709          scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vubvar, vubcoef, vubconstant, TRUE,
6710          infeasible, &nlocalbdchgs) );
6711 
6712    *nbdchgs = nlocalbdchgs;
6713 
6714    /* if x is not continuous we add a variable bound for z; do not add it if cofficient would be too small or we already
6715     * detected infeasibility
6716     */
6717    if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vubcoef) )
6718    {
6719       if( vubcoef > 0.0 )
6720       {
6721          /* if b < 0, we have a variable lower bound: x >= b*z + d  =>  z >= (x-d)/b */
6722          SCIP_CALL( SCIPvarAddVlb(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6723                scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef,
6724                -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) );
6725       }
6726       else
6727       {
6728          /* if b > 0, we have a variable upper bound: x >= b*z + d  =>  z <= (x-d)/b */
6729          SCIP_CALL( SCIPvarAddVub(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6730                scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef,
6731                -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) );
6732       }
6733       *nbdchgs += nlocalbdchgs;
6734    }
6735 
6736    return SCIP_OKAY;
6737 }
6738 
6739 /** informs binary variable x about a globally valid implication:  x == 0 or x == 1  ==>  y <= b  or  y >= b;
6740  *  also adds the corresponding implication or variable bound to the implied variable;
6741  *  if the implication is conflicting, the variable is fixed to the opposite value;
6742  *  if the variable is already fixed to the given value, the implication is performed immediately;
6743  *  if the implication is redundant with respect to the variables' global bounds, it is ignored
6744  *
6745  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6746  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6747  *
6748  *  @pre This method can be called if @p scip is in one of the following stages:
6749  *       - \ref SCIP_STAGE_TRANSFORMED
6750  *       - \ref SCIP_STAGE_PRESOLVING
6751  *       - \ref SCIP_STAGE_PRESOLVED
6752  *       - \ref SCIP_STAGE_SOLVING
6753  */
SCIPaddVarImplication(SCIP * scip,SCIP_VAR * var,SCIP_Bool varfixing,SCIP_VAR * implvar,SCIP_BOUNDTYPE impltype,SCIP_Real implbound,SCIP_Bool * infeasible,int * nbdchgs)6754 SCIP_RETCODE SCIPaddVarImplication(
6755    SCIP*                 scip,               /**< SCIP data structure */
6756    SCIP_VAR*             var,                /**< problem variable */
6757    SCIP_Bool             varfixing,          /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
6758    SCIP_VAR*             implvar,            /**< variable y in implication y <= b or y >= b */
6759    SCIP_BOUNDTYPE        impltype,           /**< type       of implication y <= b (SCIP_BOUNDTYPE_UPPER)
6760                                               *                          or y >= b (SCIP_BOUNDTYPE_LOWER) */
6761    SCIP_Real             implbound,          /**< bound b    in implication y <= b or y >= b */
6762    SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
6763    int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
6764    )
6765 {
6766    SCIP_VAR* implprobvar;
6767 
6768    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarImplication", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6769 
6770    assert(infeasible != NULL);
6771    *infeasible = FALSE;
6772 
6773    if ( nbdchgs != NULL )
6774       *nbdchgs = 0;
6775 
6776    if( !SCIPvarIsBinary(var) )
6777    {
6778       SCIPerrorMessage("can't add implication for nonbinary variable\n");
6779       return SCIP_INVALIDDATA;
6780    }
6781 
6782    implprobvar = SCIPvarGetProbvar(implvar);
6783    /* transform implication containing two binary variables to a clique; the condition ensures that the active representative
6784     * of implvar is actually binary
6785     */
6786    if( SCIPvarIsBinary(implvar) && (SCIPvarIsActive(implvar) || (implprobvar != NULL && SCIPvarIsBinary(implprobvar))) )
6787    {
6788       assert(SCIPisFeasEQ(scip, implbound, 1.0) || SCIPisFeasZero(scip, implbound));
6789       assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPisFeasZero(scip, implbound));
6790 
6791       /* only add clique if implication is not redundant with respect to global bounds of the implication variable */
6792       if( (impltype == SCIP_BOUNDTYPE_LOWER && SCIPvarGetLbGlobal(implvar) < 0.5) ||
6793           (impltype == SCIP_BOUNDTYPE_UPPER && SCIPvarGetUbGlobal(implvar) > 0.5) )
6794       {
6795          SCIP_VAR* vars[2];
6796          SCIP_Bool vals[2];
6797 
6798          vars[0] = var;
6799          vars[1] = implvar;
6800          vals[0] = varfixing;
6801          vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
6802 
6803          SCIP_CALL( SCIPaddClique(scip, vars, vals, 2, FALSE, infeasible, nbdchgs) );
6804       }
6805 
6806       return SCIP_OKAY;
6807    }
6808 
6809    /* the implication graph can only handle 'real' binary (SCIP_VARTYPE_BINARY) variables, therefore we transform the
6810     * implication in variable bounds, (lowerbound of y will be abbreviated by lby, upperbound equivlaent) the follwing
6811     * four cases are:
6812     *
6813     * 1. (x >= 1 => y >= b) => y >= (b - lby) * x + lby
6814     * 2. (x >= 1 => y <= b) => y <= (b - uby) * x + uby
6815     * 3. (x <= 0 => y >= b) => y >= (lby - b) * x + b
6816     * 4. (x <= 0 => y <= b) => y <= (uby - b) * x + b
6817     */
6818    if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
6819    {
6820       SCIP_Real lby;
6821       SCIP_Real uby;
6822 
6823       lby = SCIPvarGetLbGlobal(implvar);
6824       uby = SCIPvarGetUbGlobal(implvar);
6825 
6826       if( varfixing == TRUE )
6827       {
6828          if( impltype == SCIP_BOUNDTYPE_LOWER )
6829          {
6830             /* we return if the lower bound is infinity */
6831             if( SCIPisInfinity(scip, -lby) )
6832                return SCIP_OKAY;
6833 
6834             SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6835                   scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6836                   implbound - lby, lby, TRUE, infeasible, nbdchgs) );
6837          }
6838          else
6839          {
6840             /* we return if the upper bound is infinity */
6841             if( SCIPisInfinity(scip, uby) )
6842                return SCIP_OKAY;
6843 
6844             SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6845                   scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6846                   implbound - uby, uby, TRUE, infeasible, nbdchgs) );
6847          }
6848       }
6849       else
6850       {
6851          if( impltype == SCIP_BOUNDTYPE_LOWER )
6852          {
6853             /* we return if the lower bound is infinity */
6854             if( SCIPisInfinity(scip, -lby) )
6855                return SCIP_OKAY;
6856 
6857             SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6858                   scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6859                   lby - implbound, implbound, TRUE, infeasible, nbdchgs) );
6860          }
6861          else
6862          {
6863             /* we return if the upper bound is infinity */
6864             if( SCIPisInfinity(scip, uby) )
6865                return SCIP_OKAY;
6866 
6867             SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6868                   scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6869                   uby - implbound, implbound, TRUE, infeasible, nbdchgs) );
6870          }
6871       }
6872    }
6873    else
6874    {
6875       SCIP_CALL( SCIPvarAddImplic(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6876             scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, varfixing, implvar, impltype,
6877             implbound, TRUE, infeasible, nbdchgs) );
6878    }
6879 
6880    return SCIP_OKAY;
6881 }
6882 
6883 /** adds a clique information to SCIP, stating that at most one of the given binary variables can be set to 1;
6884  *  if a variable appears twice in the same clique, the corresponding implications are performed
6885  *
6886  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6887  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6888  *
6889  *  @pre This method can be called if @p scip is in one of the following stages:
6890  *       - \ref SCIP_STAGE_TRANSFORMED
6891  *       - \ref SCIP_STAGE_PRESOLVING
6892  *       - \ref SCIP_STAGE_PRESOLVED
6893  *       - \ref SCIP_STAGE_SOLVING
6894  */
SCIPaddClique(SCIP * scip,SCIP_VAR ** vars,SCIP_Bool * values,int nvars,SCIP_Bool isequation,SCIP_Bool * infeasible,int * nbdchgs)6895 SCIP_RETCODE SCIPaddClique(
6896    SCIP*                 scip,               /**< SCIP data structure */
6897    SCIP_VAR**            vars,               /**< binary variables in the clique from which at most one can be set to 1 */
6898    SCIP_Bool*            values,             /**< values of the variables in the clique; NULL to use TRUE for all vars */
6899    int                   nvars,              /**< number of variables in the clique */
6900    SCIP_Bool             isequation,         /**< is the clique an equation or an inequality? */
6901    SCIP_Bool*            infeasible,         /**< pointer to store whether an infeasibility was detected */
6902    int*                  nbdchgs             /**< pointer to store the number of performed bound changes, or NULL */
6903    )
6904 {
6905    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddClique", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6906 
6907    *infeasible = FALSE;
6908    if( nbdchgs != NULL )
6909       *nbdchgs = 0;
6910 
6911    if( nvars > 1 )
6912    {
6913       /* add the clique to the clique table */
6914       SCIP_CALL( SCIPcliquetableAdd(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6915             scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, vars, values, nvars, isequation,
6916             infeasible, nbdchgs) );
6917    }
6918 
6919    return SCIP_OKAY;
6920 }
6921 
6922 /** relabels the given labels in-place in an increasing fashion: the first seen label is 0, the next label 1, etc...
6923  *
6924  *  @note every label equal to -1 is treated as a previously unseen, unique label and gets a new ordered label.
6925  */
6926 static
relabelOrderConsistent(SCIP * const scip,int * labels,int const nlabels,int * nclasses)6927 SCIP_RETCODE relabelOrderConsistent(
6928    SCIP*const            scip,               /**< SCIP data structure */
6929    int*                  labels,             /**< current labels that will be overwritten */
6930    int const             nlabels,            /**< number of variables in the clique */
6931    int*                  nclasses            /**< pointer to store the total number of distinct labels */
6932    )
6933 {
6934    SCIP_HASHMAP* classidx2newlabel;
6935 
6936    int classidx;
6937    int i;
6938 
6939    SCIP_CALL( SCIPhashmapCreate(&classidx2newlabel, SCIPblkmem(scip), nlabels) );
6940 
6941    classidx = 0;
6942 
6943    /* loop over labels to create local class indices that obey the variable order */
6944    for( i = 0; i < nlabels; ++i )
6945    {
6946       int currentlabel = labels[i];
6947       int localclassidx;
6948 
6949       /* labels equal to -1 are stored as singleton classes */
6950       if( currentlabel == -1 )
6951       {
6952          ++classidx;
6953          localclassidx = classidx;
6954       }
6955       else
6956       {
6957          assert(currentlabel >= 0);
6958          /* look up the class index image in the hash map; if it is not stored yet, new class index is created and stored */
6959          if( !SCIPhashmapExists(classidx2newlabel, (void*)(size_t)currentlabel) )
6960          {
6961             ++classidx;
6962             localclassidx = classidx;
6963             SCIP_CALL( SCIPhashmapInsertInt(classidx2newlabel, (void*)(size_t)currentlabel, classidx) ); /*lint !e571*/
6964          }
6965          else
6966          {
6967             localclassidx = SCIPhashmapGetImageInt(classidx2newlabel, (void*)(size_t)currentlabel); /*lint !e571*/
6968          }
6969       }
6970       assert(localclassidx - 1 >= 0);
6971       assert(localclassidx - 1 <= i);
6972 
6973       /* indices start with zero, but we have an offset of 1 because we cannot store 0 in a hashmap */
6974       labels[i] = localclassidx - 1;
6975    }
6976 
6977    assert(classidx > 0);
6978    assert(classidx <= nlabels);
6979    *nclasses = classidx;
6980 
6981    SCIPhashmapFree(&classidx2newlabel);
6982 
6983    return SCIP_OKAY;
6984 }
6985 
6986 /** sort the variables w.r.t. the given labels; thereby ensure the current order of the variables with the same label. */
6987 static
labelSortStable(SCIP * scip,SCIP_VAR ** vars,int * classlabels,SCIP_VAR ** sortedvars,int * sortedindices,int * classesstartposs,int nvars,int nclasses)6988 SCIP_RETCODE labelSortStable(
6989    SCIP*                 scip,               /**< SCIP data structure */
6990    SCIP_VAR**            vars,               /**< variable array */
6991    int*                  classlabels,        /**< array that contains a class label for every variable */
6992    SCIP_VAR**            sortedvars,         /**< array to store variables after stable sorting */
6993    int*                  sortedindices,      /**< array to store indices of sorted variables in the original vars array */
6994    int*                  classesstartposs,   /**< starting position array for each label class (must have size nclasses + 1) */
6995    int                   nvars,              /**< size of the vars arrays */
6996    int                   nclasses            /**< number of label classes */
6997    )
6998 {
6999    SCIP_VAR*** varpointers;
7000    int** indexpointers;
7001    int* classcount;
7002 
7003    int nextpos;
7004    int c;
7005    int v;
7006 
7007    assert(scip != NULL);
7008    assert(vars != NULL);
7009    assert(sortedindices != NULL);
7010    assert(classesstartposs != NULL);
7011 
7012    assert(nvars == 0 || vars != NULL);
7013 
7014    if( nvars == 0 )
7015       return SCIP_OKAY;
7016 
7017    assert(classlabels != NULL);
7018    assert(nclasses > 0);
7019 
7020    /* we first count all class cardinalities and allocate temporary memory for a bucket sort */
7021    SCIP_CALL( SCIPallocBufferArray(scip, &classcount, nclasses) );
7022    BMSclearMemoryArray(classcount, nclasses);
7023 
7024    /* first we count for each class the number of elements */
7025    for( v = nvars - 1; v >= 0; --v )
7026    {
7027       assert(0 <= classlabels[v] && classlabels[v] < nclasses);
7028       ++(classcount[classlabels[v]]);
7029    }
7030 
7031 #ifndef NDEBUG
7032    BMSclearMemoryArray(sortedvars, nvars);
7033    BMSclearMemoryArray(sortedindices, nvars);
7034 #endif
7035    SCIP_CALL( SCIPallocBufferArray(scip, &varpointers, nclasses) );
7036    SCIP_CALL( SCIPallocBufferArray(scip, &indexpointers, nclasses) );
7037 
7038    nextpos = 0;
7039    /* now we initialize all start pointers for each class, so they will be ordered */
7040    for( c = 0; c < nclasses; ++c )
7041    {
7042       /* to reach the goal that all variables of each class will be standing next to each other we will initialize the
7043        * starting pointers for each class by adding the cardinality of each class to the last class starting pointer
7044        * e.g. class1 has 4 elements and class2 has 3 elements then the starting pointer for class1 will be the pointer
7045        *      to sortedvars[0], the starting pointer to class2 will be the pointer to sortedvars[4] and to class3 it will be
7046        *      the pointer to sortedvars[7]
7047        */
7048       varpointers[c] = (SCIP_VAR**) (sortedvars + nextpos);
7049       indexpointers[c] = (int*) (sortedindices + nextpos);
7050       classesstartposs[c] = nextpos;
7051       assert(classcount[c] > 0);
7052       nextpos += classcount[c];
7053       assert(nextpos > 0);
7054    }
7055    assert(nextpos == nvars);
7056    classesstartposs[c] = nextpos;
7057 
7058    /* now we copy all variables to the right order */
7059    for( v = 0; v < nvars; ++v )
7060    {
7061       /* copy variable itself to the right position */
7062       *(varpointers[classlabels[v]]) = vars[v];  /*lint !e613*/
7063       ++(varpointers[classlabels[v]]);
7064 
7065       /* copy index */
7066       *(indexpointers[classlabels[v]]) = v;
7067       ++(indexpointers[classlabels[v]]);
7068    }
7069 
7070 /* in debug mode, we ensure the correctness of the mapping */
7071 #ifndef NDEBUG
7072    for( v = 0; v < nvars; ++v )
7073    {
7074       assert(sortedvars[v] != NULL);
7075       assert(sortedindices[v] >= 0);
7076 
7077       /* assert that the sorted indices map back to the correct variable in the original order */
7078       assert(vars[sortedindices[v]] == sortedvars[v]);
7079    }
7080 #endif
7081 
7082    /* free temporary memory */
7083    SCIPfreeBufferArray(scip, &indexpointers);
7084    SCIPfreeBufferArray(scip, &varpointers);
7085    SCIPfreeBufferArray(scip, &classcount);
7086 
7087    return SCIP_OKAY;
7088 }
7089 
7090 
7091 /* calculate clique partition for a maximal amount of comparisons on variables due to expensive algorithm
7092  * @todo: check for a good value, maybe it's better to check parts of variables
7093  */
7094 #define MAXNCLIQUEVARSCOMP 1000000
7095 
7096 /** calculates a partition of the given set of binary variables into cliques;
7097  *  afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7098  *  were assigned to the same clique;
7099  *  the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of
7100  *  the preceding variables was assigned to clique i-1;
7101  *  for each clique at most 1 variables can be set to TRUE in a feasible solution;
7102  *
7103  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7104  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7105  *
7106  *  @pre This method can be called if @p scip is in one of the following stages:
7107  *       - \ref SCIP_STAGE_INITPRESOLVE
7108  *       - \ref SCIP_STAGE_PRESOLVING
7109  *       - \ref SCIP_STAGE_EXITPRESOLVE
7110  *       - \ref SCIP_STAGE_PRESOLVED
7111  *       - \ref SCIP_STAGE_SOLVING
7112  */
7113 static
calcCliquePartitionGreedy(SCIP * const scip,SCIP_VAR ** const vars,SCIP_Bool * const values,int const nvars,int * const cliquepartition,int * const ncliques)7114 SCIP_RETCODE calcCliquePartitionGreedy(
7115    SCIP*const            scip,               /**< SCIP data structure */
7116    SCIP_VAR**const       vars,               /**< binary variables in the clique from which at most one can be set to 1 */
7117    SCIP_Bool*const       values,             /**< clique value (TRUE or FALSE) for each variable in the clique */
7118    int const             nvars,              /**< number of variables in the array */
7119    int*const             cliquepartition,    /**< array of length nvars to store the clique partition */
7120    int*const             ncliques            /**< pointer to store the number of cliques actually contained in the partition */
7121    )
7122 {
7123    SCIP_VAR** cliquevars;
7124    SCIP_Bool* cliquevalues;
7125    int i;
7126    int maxncliquevarscomp;
7127    int ncliquevars;
7128 
7129    /* allocate temporary memory for storing the variables of the current clique */
7130    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevars, nvars) );
7131    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevalues, nvars) );
7132 
7133    /* initialize the cliquepartition array with -1 */
7134    for( i = nvars - 1; i >= 0; --i )
7135       cliquepartition[i] = -1;
7136 
7137    maxncliquevarscomp = (int) MIN(nvars * (SCIP_Longint)nvars, MAXNCLIQUEVARSCOMP);
7138    /* calculate the clique partition */
7139    *ncliques = 0;
7140    for( i = 0; i < nvars; ++i )
7141    {
7142       if( cliquepartition[i] == -1 )
7143       {
7144          int j;
7145 
7146          /* variable starts a new clique */
7147          cliquepartition[i] = *ncliques;
7148          cliquevars[0] = vars[i];
7149          cliquevalues[0] = values[i];
7150          ncliquevars = 1;
7151 
7152          /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */
7153          if( SCIPvarIsActive(vars[i]) && SCIPvarGetNCliques(vars[i], values[i]) > 0 )
7154          {
7155             /* greedily fill up the clique */
7156             for( j = i+1; j < nvars; ++j )
7157             {
7158                /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */
7159                if( cliquepartition[j] == -1 && SCIPvarIsActive(vars[j]) )
7160                {
7161                   int k;
7162 
7163                   /* check if every variable in the current clique can be extended by tmpvars[j] */
7164                   for( k = ncliquevars - 1; k >= 0; --k )
7165                   {
7166                      if( !SCIPvarsHaveCommonClique(vars[j], values[j], cliquevars[k], cliquevalues[k], FALSE) )
7167                         break;
7168                   }
7169 
7170                   if( k == -1 )
7171                   {
7172                      /* put the variable into the same clique */
7173                      cliquepartition[j] = cliquepartition[i];
7174                      cliquevars[ncliquevars] = vars[j];
7175                      cliquevalues[ncliquevars] = values[j];
7176                      ++ncliquevars;
7177                   }
7178                }
7179             }
7180          }
7181 
7182          /* this clique is finished */
7183          ++(*ncliques);
7184       }
7185       assert(cliquepartition[i] >= 0 && cliquepartition[i] < i+1);
7186 
7187       /* break if we reached the maximal number of comparisons */
7188       if( i * nvars > maxncliquevarscomp )
7189          break;
7190    }
7191    /* if we had to many variables fill up the cliquepartition and put each variable in a separate clique */
7192    for( ; i < nvars; ++i )
7193    {
7194       if( cliquepartition[i] == -1 )
7195       {
7196          cliquepartition[i] = *ncliques;
7197          ++(*ncliques);
7198       }
7199    }
7200 
7201    SCIPsetFreeBufferArray(scip->set, &cliquevalues);
7202    SCIPsetFreeBufferArray(scip->set, &cliquevars);
7203 
7204    return SCIP_OKAY;
7205 }
7206 
7207 /** calculates a partition of the given set of binary variables into cliques; takes into account independent clique components
7208  *
7209  *  The algorithm performs the following steps:
7210  *  - recomputes connected components of the clique table, if necessary
7211  *  - computes a clique partition for every connected component greedily.
7212  *  - relabels the resulting clique partition such that it satisfies the description below
7213  *
7214  *  afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7215  *  were assigned to the same clique;
7216  *  the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of
7217  *  the preceding variables was assigned to clique i-1;
7218  *  for each clique at most 1 variables can be set to TRUE in a feasible solution;
7219  *
7220  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7221  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7222  *
7223  *  @pre This method can be called if @p scip is in one of the following stages:
7224  *       - \ref SCIP_STAGE_INITPRESOLVE
7225  *       - \ref SCIP_STAGE_PRESOLVING
7226  *       - \ref SCIP_STAGE_EXITPRESOLVE
7227  *       - \ref SCIP_STAGE_PRESOLVED
7228  *       - \ref SCIP_STAGE_SOLVING
7229  */
SCIPcalcCliquePartition(SCIP * const scip,SCIP_VAR ** const vars,int const nvars,int * const cliquepartition,int * const ncliques)7230 SCIP_RETCODE SCIPcalcCliquePartition(
7231    SCIP*const            scip,               /**< SCIP data structure */
7232    SCIP_VAR**const       vars,               /**< binary variables in the clique from which at most one can be set to 1 */
7233    int const             nvars,              /**< number of variables in the clique */
7234    int*const             cliquepartition,    /**< array of length nvars to store the clique partition */
7235    int*const             ncliques            /**< pointer to store the number of cliques actually contained in the partition */
7236    )
7237 {
7238    SCIP_VAR** tmpvars;
7239 
7240    SCIP_VAR** sortedtmpvars;
7241    SCIP_Bool* tmpvalues;
7242    SCIP_Bool* sortedtmpvalues;
7243    int* componentlabels;
7244    int* sortedindices;
7245    int* componentstartposs;
7246    int i;
7247    int c;
7248 
7249    int ncomponents;
7250 
7251    assert(scip != NULL);
7252    assert(nvars == 0 || vars != NULL);
7253    assert(nvars == 0 || cliquepartition != NULL);
7254    assert(ncliques != NULL);
7255 
7256    SCIP_CALL( SCIPcheckStage(scip, "SCIPcalcCliquePartition", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7257 
7258    if( nvars == 0 )
7259    {
7260       *ncliques = 0;
7261       return SCIP_OKAY;
7262    }
7263 
7264    /* early abort if no cliques are present */
7265    if( SCIPgetNCliques(scip) == 0 )
7266    {
7267       for( i = 0; i < nvars; ++i )
7268          cliquepartition[i] = i;
7269 
7270       *ncliques = nvars;
7271 
7272       return SCIP_OKAY;
7273    }
7274 
7275    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &tmpvalues, nvars) );
7276    SCIP_CALL( SCIPsetDuplicateBufferArray(scip->set, &tmpvars, vars, nvars) );
7277    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentlabels, nvars) );
7278    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedindices, nvars) );
7279 
7280    /* initialize the tmpvalues array */
7281    for( i = nvars - 1; i >= 0; --i )
7282    {
7283       tmpvalues[i] = TRUE;
7284       cliquepartition[i] = -1;
7285    }
7286 
7287    /* get corresponding active problem variables */
7288    SCIP_CALL( SCIPvarsGetProbvarBinary(&tmpvars, &tmpvalues, nvars) );
7289 
7290    ncomponents = -1;
7291 
7292    /* update clique components if necessary */
7293    if( SCIPcliquetableNeedsComponentUpdate(scip->cliquetable) )
7294    {
7295       SCIP_VAR** allvars;
7296       int nallbinvars;
7297       int nallintvars;
7298       int nallimplvars;
7299 
7300       SCIP_CALL( SCIPgetVarsData(scip, &allvars, NULL, &nallbinvars, &nallintvars, &nallimplvars, NULL) );
7301 
7302       SCIP_CALL( SCIPcliquetableComputeCliqueComponents(scip->cliquetable, scip->set, SCIPblkmem(scip), allvars, nallbinvars, nallintvars, nallimplvars) );
7303    }
7304 
7305    assert(!SCIPcliquetableNeedsComponentUpdate(scip->cliquetable));
7306 
7307    /* store the global clique component labels */
7308    for( i = 0; i < nvars; ++i )
7309    {
7310       if( SCIPvarIsActive(tmpvars[i]) )
7311          componentlabels[i] = SCIPcliquetableGetVarComponentIdx(scip->cliquetable, tmpvars[i]);
7312       else
7313          componentlabels[i] = -1;
7314    }
7315 
7316    /* relabel component labels order consistent as prerequisite for a stable sort */
7317    SCIP_CALL( relabelOrderConsistent(scip, componentlabels, nvars, &ncomponents) );
7318    assert(ncomponents >= 1);
7319    assert(ncomponents <= nvars);
7320 
7321    /* allocate storage array for the starting positions of the components */
7322    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentstartposs, ncomponents + 1) );
7323 
7324    /* stable sort the variables w.r.t. the component labels so that we can restrict the quadratic algorithm to the components */
7325    if( ncomponents > 1 )
7326    {
7327       SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvars, nvars) );
7328       SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvalues, nvars) );
7329       SCIP_CALL( labelSortStable(scip, tmpvars, componentlabels, sortedtmpvars, sortedindices, componentstartposs, nvars, ncomponents) );
7330 
7331       /* reassign the tmpvalues with respect to the sorting */
7332       for( i = 0; i < nvars; ++i )
7333       {
7334          assert(tmpvars[sortedindices[i]] == sortedtmpvars[i]);
7335          sortedtmpvalues[i] = tmpvalues[sortedindices[i]];
7336       }
7337    }
7338    else
7339    {
7340       /* if we have only one large connected component, skip the stable sorting and prepare the data differently */
7341       sortedtmpvars = tmpvars;
7342       sortedtmpvalues = tmpvalues;
7343       componentstartposs[0] = 0;
7344       componentstartposs[1] = nvars;
7345 
7346       /* sorted indices are the identity */
7347       for( i = 0; i < nvars; ++i )
7348          sortedindices[i] = i;
7349    }
7350 
7351    *ncliques = 0;
7352    /* calculate a greedy clique partition for each connected component */
7353    for( c = 0; c < ncomponents; ++c )
7354    {
7355       int* localcliquepartition;
7356       int nlocalcliques;
7357       int ncomponentvars;
7358       int l;
7359 
7360       /* extract the number of variables in this connected component */
7361       ncomponentvars = componentstartposs[c + 1] - componentstartposs[c];
7362       nlocalcliques = 0;
7363 
7364       /* allocate necessary memory to hold the intermediate component clique partition */
7365       SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &localcliquepartition, ncomponentvars) );
7366 
7367       /* call greedy clique algorithm for all component variables */
7368       SCIP_CALL( calcCliquePartitionGreedy(scip, &(sortedtmpvars[componentstartposs[c]]), &(sortedtmpvalues[componentstartposs[c]]),
7369             ncomponentvars, localcliquepartition, &nlocalcliques) );
7370 
7371       assert(nlocalcliques >= 1);
7372       assert(nlocalcliques <= ncomponentvars);
7373 
7374       /* store the obtained clique partition with an offset of ncliques for the original variables */
7375       for( l = componentstartposs[c]; l < componentstartposs[c + 1]; ++l )
7376       {
7377          int origvaridx = sortedindices[l];
7378          assert(cliquepartition[origvaridx] == -1);
7379          assert(localcliquepartition[l - componentstartposs[c]] <= l - componentstartposs[c]);
7380          cliquepartition[origvaridx] = localcliquepartition[l - componentstartposs[c]] + (*ncliques);
7381       }
7382       *ncliques += nlocalcliques;
7383 
7384       /* free the local clique partition */
7385       SCIPsetFreeBufferArray(scip->set, &localcliquepartition);
7386    }
7387 
7388    /* except in the two trivial cases, we have to ensure the order consistency of the partition indices */
7389    if( ncomponents > 1 && ncomponents < nvars )
7390    {
7391       int partitionsize;
7392       SCIP_CALL( relabelOrderConsistent(scip, cliquepartition, nvars, &partitionsize) );
7393 
7394       assert(partitionsize == *ncliques);
7395    }
7396 
7397    if( ncomponents > 1 )
7398    {
7399       SCIPsetFreeBufferArray(scip->set, &sortedtmpvalues);
7400       SCIPsetFreeBufferArray(scip->set, &sortedtmpvars);
7401    }
7402 
7403    /* use the greedy algorithm as a whole to verify the result on small number of variables */
7404 #ifdef SCIP_DISABLED_CODE
7405    {
7406       int* debugcliquepartition;
7407       int ndebugcliques;
7408 
7409       SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &debugcliquepartition, nvars) );
7410 
7411       /* call greedy clique algorithm for all component variables */
7412       SCIP_CALL( calcCliquePartitionGreedy(scip, tmpvars, tmpvalues, nvars, debugcliquepartition, &ndebugcliques) );
7413 
7414       /* loop and compare the traditional greedy clique with  */
7415       for( i = 0; i < nvars; ++i )
7416          assert(i * nvars > MAXNCLIQUEVARSCOMP || cliquepartition[i] == debugcliquepartition[i]);
7417 
7418       SCIPsetFreeBufferArray(scip->set, &debugcliquepartition);
7419    }
7420 #endif
7421 
7422    /* free temporary memory */
7423    SCIPsetFreeBufferArray(scip->set, &componentstartposs);
7424    SCIPsetFreeBufferArray(scip->set, &sortedindices);
7425    SCIPsetFreeBufferArray(scip->set, &componentlabels);
7426    SCIPsetFreeBufferArray(scip->set, &tmpvars);
7427    SCIPsetFreeBufferArray(scip->set, &tmpvalues);
7428 
7429    return SCIP_OKAY;
7430 }
7431 
7432 /** calculates a partition of the given set of binary variables into negated cliques;
7433  *  afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7434  *  were assigned to the same negated clique;
7435  *  the first variable is always assigned to clique 0 and a variable can only be assigned to clique i if at least one of
7436  *  the preceding variables was assigned to clique i-1;
7437  *  for each clique with n_c variables at least n_c-1 variables can be set to TRUE in a feasible solution;
7438  *
7439  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7440  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7441  *
7442  *  @pre This method can be called if @p scip is in one of the following stages:
7443  *       - \ref SCIP_STAGE_INITPRESOLVE
7444  *       - \ref SCIP_STAGE_PRESOLVING
7445  *       - \ref SCIP_STAGE_EXITPRESOLVE
7446  *       - \ref SCIP_STAGE_PRESOLVED
7447  *       - \ref SCIP_STAGE_SOLVING
7448  */
SCIPcalcNegatedCliquePartition(SCIP * const scip,SCIP_VAR ** const vars,int const nvars,int * const cliquepartition,int * const ncliques)7449 SCIP_RETCODE SCIPcalcNegatedCliquePartition(
7450    SCIP*const            scip,               /**< SCIP data structure */
7451    SCIP_VAR**const       vars,               /**< binary variables in the clique from which at most one can be set to 1 */
7452    int const             nvars,              /**< number of variables in the clique */
7453    int*const             cliquepartition,    /**< array of length nvars to store the clique partition */
7454    int*const             ncliques            /**< pointer to store the number of cliques actually contained in the partition */
7455    )
7456 {
7457    SCIP_VAR** negvars;
7458    int v;
7459 
7460    assert(scip != NULL);
7461    assert(cliquepartition != NULL || nvars == 0);
7462    assert(ncliques != NULL);
7463 
7464    if( nvars == 0 )
7465    {
7466       *ncliques = 0;
7467       return SCIP_OKAY;
7468    }
7469    assert(vars != NULL);
7470 
7471    /* allocate temporary memory */
7472    SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &negvars, nvars) );
7473 
7474    /* get all negated variables */
7475    for( v = nvars - 1; v >= 0; --v )
7476    {
7477       SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &(negvars[v])) );
7478    }
7479 
7480    /* calculate cliques on negated variables, which are "negated" cliques on normal variables array */
7481    SCIP_CALL( SCIPcalcCliquePartition( scip, negvars, nvars, cliquepartition, ncliques) );
7482 
7483    /* free temporary memory */
7484    SCIPsetFreeBufferArray(scip->set, &negvars);
7485 
7486    return SCIP_OKAY;
7487 }
7488 
7489 
7490 /** force SCIP to clean up all cliques; cliques do not get automatically cleaned up after presolving. Use
7491  *  this method to prevent inactive variables in cliques when retrieved via SCIPgetCliques()
7492  *
7493  *  @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed
7494  *
7495  *  @pre This method can be called if @p scip is in one of the following stages:
7496  *       - \ref SCIP_STAGE_TRANSFORMED
7497  *       - \ref SCIP_STAGE_INITPRESOLVE
7498  *       - \ref SCIP_STAGE_PRESOLVING
7499  *       - \ref SCIP_STAGE_EXITPRESOLVE
7500  *       - \ref SCIP_STAGE_PRESOLVED
7501  *       - \ref SCIP_STAGE_INITSOLVE
7502  *       - \ref SCIP_STAGE_SOLVING
7503  *       - \ref SCIP_STAGE_SOLVED
7504  *       - \ref SCIP_STAGE_EXITSOLVE
7505  */
SCIPcleanupCliques(SCIP * scip,SCIP_Bool * infeasible)7506 SCIP_RETCODE SCIPcleanupCliques(
7507    SCIP*                 scip,               /**< SCIP data structure */
7508    SCIP_Bool*            infeasible          /**< pointer to store if cleanup detected infeasibility */
7509    )
7510 {
7511    int nlocalbdchgs;
7512    SCIP_Bool globalinfeasibility;
7513 
7514    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcleanupCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7515 
7516    globalinfeasibility = FALSE;
7517    nlocalbdchgs = 0;
7518    SCIP_CALL( SCIPcliquetableCleanup(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
7519          scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, &nlocalbdchgs,
7520          &globalinfeasibility) );
7521 
7522    if( infeasible != NULL )
7523       *infeasible = globalinfeasibility;
7524 
7525    if( globalinfeasibility )
7526       scip->stat->status = SCIP_STATUS_INFEASIBLE;
7527 
7528    return SCIP_OKAY;
7529 }
7530 
7531 /** gets the number of cliques in the clique table
7532  *
7533  *  @return number of cliques in the clique table
7534  *
7535  *  @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7536  *  to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7537  *
7538  *  @pre This method can be called if @p scip is in one of the following stages:
7539  *       - \ref SCIP_STAGE_TRANSFORMED
7540  *       - \ref SCIP_STAGE_INITPRESOLVE
7541  *       - \ref SCIP_STAGE_PRESOLVING
7542  *       - \ref SCIP_STAGE_EXITPRESOLVE
7543  *       - \ref SCIP_STAGE_PRESOLVED
7544  *       - \ref SCIP_STAGE_INITSOLVE
7545  *       - \ref SCIP_STAGE_SOLVING
7546  *       - \ref SCIP_STAGE_SOLVED
7547  *       - \ref SCIP_STAGE_EXITSOLVE
7548  */
SCIPgetNCliques(SCIP * scip)7549 int SCIPgetNCliques(
7550    SCIP*                 scip                /**< SCIP data structure */
7551    )
7552 {
7553    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7554 
7555    return SCIPcliquetableGetNCliques(scip->cliquetable);
7556 }
7557 
7558 /** gets the number of cliques created so far by the cliquetable
7559  *
7560  *  @return number of cliques created so far by the cliquetable
7561  *
7562  *  @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7563  *  to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7564  *
7565  *  @pre This method can be called if @p scip is in one of the following stages:
7566  *       - \ref SCIP_STAGE_TRANSFORMED
7567  *       - \ref SCIP_STAGE_INITPRESOLVE
7568  *       - \ref SCIP_STAGE_PRESOLVING
7569  *       - \ref SCIP_STAGE_EXITPRESOLVE
7570  *       - \ref SCIP_STAGE_PRESOLVED
7571  *       - \ref SCIP_STAGE_INITSOLVE
7572  *       - \ref SCIP_STAGE_SOLVING
7573  *       - \ref SCIP_STAGE_SOLVED
7574  *       - \ref SCIP_STAGE_EXITSOLVE
7575  */
SCIPgetNCliquesCreated(SCIP * scip)7576 int SCIPgetNCliquesCreated(
7577    SCIP*                 scip                /**< SCIP data structure */
7578    )
7579 {
7580    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliquesCreated", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7581 
7582    return SCIPcliquetableGetNCliquesCreated(scip->cliquetable);
7583 }
7584 
7585 /** gets the array of cliques in the clique table
7586  *
7587  *  @return array of cliques in the clique table
7588  *
7589  *  @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7590  *  to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7591  *
7592  *  @pre This method can be called if @p scip is in one of the following stages:
7593  *       - \ref SCIP_STAGE_TRANSFORMED
7594  *       - \ref SCIP_STAGE_INITPRESOLVE
7595  *       - \ref SCIP_STAGE_PRESOLVING
7596  *       - \ref SCIP_STAGE_EXITPRESOLVE
7597  *       - \ref SCIP_STAGE_PRESOLVED
7598  *       - \ref SCIP_STAGE_INITSOLVE
7599  *       - \ref SCIP_STAGE_SOLVING
7600  *       - \ref SCIP_STAGE_SOLVED
7601  *       - \ref SCIP_STAGE_EXITSOLVE
7602  */
SCIPgetCliques(SCIP * scip)7603 SCIP_CLIQUE** SCIPgetCliques(
7604    SCIP*                 scip                /**< SCIP data structure */
7605    )
7606 {
7607    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7608 
7609    return SCIPcliquetableGetCliques(scip->cliquetable);
7610 }
7611 
7612 /** returns whether there is a clique that contains both given variable/value pairs;
7613  *  the variables must be active binary variables;
7614  *  if regardimplics is FALSE, only the cliques in the clique table are looked at;
7615  *  if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
7616  *
7617  *  @return TRUE, if there is a clique that contains both variable/clique pairs; FALSE, otherwise
7618  *
7619  *  @pre This method can be called if @p scip is in one of the following stages:
7620  *       - \ref SCIP_STAGE_TRANSFORMED
7621  *       - \ref SCIP_STAGE_INITPRESOLVE
7622  *       - \ref SCIP_STAGE_PRESOLVING
7623  *       - \ref SCIP_STAGE_EXITPRESOLVE
7624  *       - \ref SCIP_STAGE_PRESOLVED
7625  *       - \ref SCIP_STAGE_INITSOLVE
7626  *       - \ref SCIP_STAGE_SOLVING
7627  *       - \ref SCIP_STAGE_SOLVED
7628  *       - \ref SCIP_STAGE_EXITSOLVE
7629  *
7630  *  @note a variable with it's negated variable are NOT! in a clique
7631  *  @note a variable with itself are in a clique
7632  */
SCIPhaveVarsCommonClique(SCIP * scip,SCIP_VAR * var1,SCIP_Bool value1,SCIP_VAR * var2,SCIP_Bool value2,SCIP_Bool regardimplics)7633 SCIP_Bool SCIPhaveVarsCommonClique(
7634    SCIP*                 scip,               /**< SCIP data structure */
7635    SCIP_VAR*             var1,               /**< first variable */
7636    SCIP_Bool             value1,             /**< value of first variable */
7637    SCIP_VAR*             var2,               /**< second variable */
7638    SCIP_Bool             value2,             /**< value of second variable */
7639    SCIP_Bool             regardimplics       /**< should the implication graph also be searched for a clique? */
7640    )
7641 {
7642    assert(scip != NULL);
7643    assert(var1 != NULL);
7644    assert(var2 != NULL);
7645    assert(SCIPvarIsActive(var1));
7646    assert(SCIPvarIsActive(var2));
7647    assert(SCIPvarIsBinary(var1));
7648    assert(SCIPvarIsBinary(var2));
7649 
7650    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPhaveVarsCommonClique", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7651 
7652    /* if both variables together have more cliques then actual cliques exist, then they have a common clique (in debug
7653     * mode we check this for correctness), otherwise we need to call the pairwise comparison method for these variables
7654     */
7655 #ifndef NDEBUG
7656    assert((SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable)) ? SCIPvarsHaveCommonClique(var1, value1, var2, value2, FALSE) : TRUE);
7657 #endif
7658 
7659    return (SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable)
7660       || SCIPvarsHaveCommonClique(var1, value1, var2, value2, regardimplics));
7661 }
7662 
7663 /** writes the clique graph to a gml file
7664  *
7665  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7666  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7667  *
7668  *  @pre This method can be called if @p scip is in one of the following stages:
7669  *       - \ref SCIP_STAGE_TRANSFORMED
7670  *       - \ref SCIP_STAGE_INITPRESOLVE
7671  *       - \ref SCIP_STAGE_PRESOLVING
7672  *       - \ref SCIP_STAGE_EXITPRESOLVE
7673  *       - \ref SCIP_STAGE_PRESOLVED
7674  *       - \ref SCIP_STAGE_INITSOLVE
7675  *       - \ref SCIP_STAGE_SOLVING
7676  *       - \ref SCIP_STAGE_SOLVED
7677  *       - \ref SCIP_STAGE_EXITSOLVE
7678  *
7679  *  @note there can be duplicated arcs in the output file
7680  *
7681  *  If @p writenodeweights is true, only nodes corresponding to variables that have a fractional value and only edges
7682  *  between such nodes are written.
7683  */
SCIPwriteCliqueGraph(SCIP * scip,const char * fname,SCIP_Bool writenodeweights)7684 SCIP_RETCODE SCIPwriteCliqueGraph(
7685    SCIP*                 scip,               /**< SCIP data structure */
7686    const char*           fname,              /**< name of file */
7687    SCIP_Bool             writenodeweights    /**< should we write weights of nodes? */
7688    )
7689 {
7690    FILE* gmlfile;
7691    SCIP_HASHMAP* nodehashmap;
7692    SCIP_CLIQUE** cliques;
7693    SCIP_VAR** clqvars;
7694    SCIP_VAR** allvars;
7695    SCIP_Bool* clqvalues;
7696    char nodename[SCIP_MAXSTRLEN];
7697    int nallvars;
7698    int nbinvars;
7699    int nintvars;
7700    int nimplvars;
7701    int ncliques;
7702    int c;
7703    int v1;
7704    int v2;
7705    int id1;
7706    int id2;
7707 
7708    assert(scip != NULL);
7709    assert(fname != NULL);
7710 
7711    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPwriteCliqueGraph", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7712 
7713    /* get all active variables */
7714    SCIP_CALL( SCIPgetVarsData(scip, &allvars, &nallvars, &nbinvars, &nintvars, &nimplvars, NULL) );
7715 
7716    /* no possible variables for cliques exist */
7717    if( nbinvars + nimplvars == 0 )
7718       return SCIP_OKAY;
7719 
7720    ncliques = SCIPgetNCliques(scip);
7721 
7722    /* no cliques and do not wont to check for binary implications */
7723    if( ncliques == 0 )
7724       return SCIP_OKAY;
7725 
7726    /* open gml file */
7727    gmlfile = fopen(fname, "w");
7728 
7729    if( gmlfile == NULL )
7730    {
7731       SCIPerrorMessage("cannot open graph file <%s>\n", fname);
7732       SCIPABORT();
7733       return SCIP_INVALIDDATA; /*lint !e527*/
7734    }
7735 
7736    /* create the hash map */
7737    SCIP_CALL_FINALLY( SCIPhashmapCreate(&nodehashmap, SCIPblkmem(scip), nbinvars+nimplvars), fclose(gmlfile) );
7738 
7739    /* write starting of gml file */
7740    SCIPgmlWriteOpening(gmlfile, TRUE);
7741 
7742    cliques = SCIPgetCliques(scip);
7743 
7744    /* write nodes and arcs for all cliques */
7745    for( c = ncliques - 1; c >= 0; --c )
7746    {
7747       clqvalues = SCIPcliqueGetValues(cliques[c]);
7748       clqvars = SCIPcliqueGetVars(cliques[c]);
7749 
7750       for( v1 = SCIPcliqueGetNVars(cliques[c]) - 1; v1 >= 0; --v1 )
7751       {
7752 	 id1 = clqvalues[v1] ? SCIPvarGetProbindex(clqvars[v1]) : (nallvars + SCIPvarGetProbindex(clqvars[v1]));
7753 
7754 	 /* if corresponding node was not added yet, add it */
7755 	 if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id1) )
7756 	 {
7757             assert(id1 >= 0);
7758 	    SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id1, 1), fclose(gmlfile) ); /*lint !e571*/
7759 
7760 	    (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id1 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v1]));
7761 
7762             /* write new gml node for new variable */
7763             if ( writenodeweights )
7764             {
7765                if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v1])) )
7766                   SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v1]));
7767             }
7768             else
7769             {
7770                SCIPgmlWriteNode(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL);
7771             }
7772 	 }
7773 
7774 	 for( v2 = SCIPcliqueGetNVars(cliques[c]) - 1; v2 >= 0; --v2 )
7775 	 {
7776 	    if( v1 == v2 )
7777 	       continue;
7778 
7779 	    id2 = clqvalues[v2] ? SCIPvarGetProbindex(clqvars[v2]) : (nallvars + SCIPvarGetProbindex(clqvars[v2]));
7780 
7781 	    /* if corresponding node was not added yet, add it */
7782 	    if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id2) )
7783 	    {
7784                assert(id2 >= 0);
7785 	       SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id2, 1), fclose(gmlfile) ); /*lint !e571*/
7786 
7787 	       (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id2 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v2]));
7788 
7789 	       /* write new gml node for new variable */
7790                if ( writenodeweights )
7791                {
7792                   if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) )
7793                      SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v2]));
7794                }
7795                else
7796                {
7797                   SCIPgmlWriteNode(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL);
7798                }
7799             }
7800 
7801 	    /* write gml arc between resultant and operand */
7802             if ( ! writenodeweights || ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) )
7803                SCIPgmlWriteArc(gmlfile, (unsigned int)id1, (unsigned int)id2, NULL, NULL);
7804 	 }
7805       }
7806    }
7807 
7808    /* free the hash map */
7809    SCIPhashmapFree(&nodehashmap);
7810 
7811    SCIPgmlWriteClosing(gmlfile);
7812    fclose(gmlfile);
7813 
7814    return SCIP_OKAY;
7815 }
7816 
7817 /** Removes (irrelevant) variable from all its global structures, i.e. cliques, implications and variable bounds.
7818  *  This is an advanced method which should be used with care.
7819  *
7820  *  @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed
7821  *
7822  *  @pre This method can be called if @p scip is in one of the following stages:
7823  *       - \ref SCIP_STAGE_TRANSFORMED
7824  *       - \ref SCIP_STAGE_INITPRESOLVE
7825  *       - \ref SCIP_STAGE_PRESOLVING
7826  *       - \ref SCIP_STAGE_EXITPRESOLVE
7827  *       - \ref SCIP_STAGE_PRESOLVED
7828  *       - \ref SCIP_STAGE_INITSOLVE
7829  *       - \ref SCIP_STAGE_SOLVING
7830  *       - \ref SCIP_STAGE_SOLVED
7831  *       - \ref SCIP_STAGE_EXITSOLVE
7832  */
SCIPremoveVarFromGlobalStructures(SCIP * scip,SCIP_VAR * var)7833 SCIP_RETCODE SCIPremoveVarFromGlobalStructures(
7834    SCIP*                 scip,               /**< SCIP data structure */
7835    SCIP_VAR*             var                 /**< variable to remove from global structures */
7836    )
7837 {
7838    assert(scip != NULL);
7839 
7840    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPremoveVarFromGlobalStructures", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7841 
7842    /* mark the variable as deletable from global structures - This is necessary for the delayed clean up of cliques */
7843    SCIPvarMarkDeleteGlobalStructures(var);
7844 
7845    /* remove variable from all its cliques, implications, and variable bounds */
7846    SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, SCIPblkmem(scip), scip->cliquetable, scip->set, TRUE, FALSE, TRUE) );
7847 
7848    return SCIP_OKAY;
7849 }
7850 
7851 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
7852  *  values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
7853  *
7854  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7855  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7856  *
7857  *  @pre This method can be called if @p scip is in one of the following stages:
7858  *       - \ref SCIP_STAGE_PROBLEM
7859  *       - \ref SCIP_STAGE_TRANSFORMING
7860  *       - \ref SCIP_STAGE_TRANSFORMED
7861  *       - \ref SCIP_STAGE_INITPRESOLVE
7862  *       - \ref SCIP_STAGE_PRESOLVING
7863  *       - \ref SCIP_STAGE_EXITPRESOLVE
7864  *       - \ref SCIP_STAGE_PRESOLVED
7865  *       - \ref SCIP_STAGE_SOLVING
7866  */
SCIPchgVarBranchFactor(SCIP * scip,SCIP_VAR * var,SCIP_Real branchfactor)7867 SCIP_RETCODE SCIPchgVarBranchFactor(
7868    SCIP*                 scip,               /**< SCIP data structure */
7869    SCIP_VAR*             var,                /**< problem variable */
7870    SCIP_Real             branchfactor        /**< factor to weigh variable's branching score with */
7871    )
7872 {
7873    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7874 
7875    SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, branchfactor) );
7876 
7877    return SCIP_OKAY;
7878 }
7879 
7880 /** scales the branch factor of the variable with the given value
7881  *
7882  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7883  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7884  *
7885  *  @pre This method can be called if @p scip is in one of the following stages:
7886  *       - \ref SCIP_STAGE_PROBLEM
7887  *       - \ref SCIP_STAGE_TRANSFORMING
7888  *       - \ref SCIP_STAGE_TRANSFORMED
7889  *       - \ref SCIP_STAGE_INITPRESOLVE
7890  *       - \ref SCIP_STAGE_PRESOLVING
7891  *       - \ref SCIP_STAGE_EXITPRESOLVE
7892  *       - \ref SCIP_STAGE_PRESOLVED
7893  *       - \ref SCIP_STAGE_SOLVING
7894  */
SCIPscaleVarBranchFactor(SCIP * scip,SCIP_VAR * var,SCIP_Real scale)7895 SCIP_RETCODE SCIPscaleVarBranchFactor(
7896    SCIP*                 scip,               /**< SCIP data structure */
7897    SCIP_VAR*             var,                /**< problem variable */
7898    SCIP_Real             scale               /**< factor to scale variable's branching factor with */
7899    )
7900 {
7901    SCIP_CALL( SCIPcheckStage(scip, "SCIPscaleVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7902 
7903    SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, scale * SCIPvarGetBranchFactor(var)) );
7904 
7905    return SCIP_OKAY;
7906 }
7907 
7908 /** adds the given value to the branch factor of the variable
7909  *
7910  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7911  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7912  *
7913  *  @pre This method can be called if @p scip is in one of the following stages:
7914  *       - \ref SCIP_STAGE_PROBLEM
7915  *       - \ref SCIP_STAGE_TRANSFORMING
7916  *       - \ref SCIP_STAGE_TRANSFORMED
7917  *       - \ref SCIP_STAGE_INITPRESOLVE
7918  *       - \ref SCIP_STAGE_PRESOLVING
7919  *       - \ref SCIP_STAGE_EXITPRESOLVE
7920  *       - \ref SCIP_STAGE_PRESOLVED
7921  *       - \ref SCIP_STAGE_SOLVING
7922  */
SCIPaddVarBranchFactor(SCIP * scip,SCIP_VAR * var,SCIP_Real addfactor)7923 SCIP_RETCODE SCIPaddVarBranchFactor(
7924    SCIP*                 scip,               /**< SCIP data structure */
7925    SCIP_VAR*             var,                /**< problem variable */
7926    SCIP_Real             addfactor           /**< value to add to the branch factor of the variable */
7927    )
7928 {
7929    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7930 
7931    SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, addfactor + SCIPvarGetBranchFactor(var)) );
7932 
7933    return SCIP_OKAY;
7934 }
7935 
7936 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
7937  *  with lower priority in selection of branching variable
7938  *
7939  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7940  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7941  *
7942  *  @pre This method can be called if @p scip is in one of the following stages:
7943  *       - \ref SCIP_STAGE_PROBLEM
7944  *       - \ref SCIP_STAGE_TRANSFORMING
7945  *       - \ref SCIP_STAGE_TRANSFORMED
7946  *       - \ref SCIP_STAGE_INITPRESOLVE
7947  *       - \ref SCIP_STAGE_PRESOLVING
7948  *       - \ref SCIP_STAGE_EXITPRESOLVE
7949  *       - \ref SCIP_STAGE_PRESOLVED
7950  *       - \ref SCIP_STAGE_SOLVING
7951  *
7952  * @note the default branching priority is 0
7953  */
SCIPchgVarBranchPriority(SCIP * scip,SCIP_VAR * var,int branchpriority)7954 SCIP_RETCODE SCIPchgVarBranchPriority(
7955    SCIP*                 scip,               /**< SCIP data structure */
7956    SCIP_VAR*             var,                /**< problem variable */
7957    int                   branchpriority      /**< branch priority of the variable */
7958    )
7959 {
7960    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7961 
7962    assert( var->scip == scip );
7963 
7964    if( SCIPisTransformed(scip)  )
7965    {
7966       assert(scip->branchcand != NULL);
7967 
7968       /* inform the pseudo branch candidates that the branch priority changes and change the branch priority */
7969       SCIP_CALL( SCIPbranchcandUpdateVarBranchPriority(scip->branchcand, scip->set, var, branchpriority) );
7970    }
7971    else
7972    {
7973       /* change the branching priority of the variable */
7974       SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
7975    }
7976 
7977    return SCIP_OKAY;
7978 }
7979 
7980 /** changes the branch priority of the variable to the given value, if it is larger than the current priority
7981  *
7982  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7983  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7984  *
7985  *  @pre This method can be called if @p scip is in one of the following stages:
7986  *       - \ref SCIP_STAGE_PROBLEM
7987  *       - \ref SCIP_STAGE_TRANSFORMING
7988  *       - \ref SCIP_STAGE_TRANSFORMED
7989  *       - \ref SCIP_STAGE_INITPRESOLVE
7990  *       - \ref SCIP_STAGE_PRESOLVING
7991  *       - \ref SCIP_STAGE_EXITPRESOLVE
7992  *       - \ref SCIP_STAGE_PRESOLVED
7993  *       - \ref SCIP_STAGE_SOLVING
7994  */
SCIPupdateVarBranchPriority(SCIP * scip,SCIP_VAR * var,int branchpriority)7995 SCIP_RETCODE SCIPupdateVarBranchPriority(
7996    SCIP*                 scip,               /**< SCIP data structure */
7997    SCIP_VAR*             var,                /**< problem variable */
7998    int                   branchpriority      /**< new branch priority of the variable, if it is larger than current priority */
7999    )
8000 {
8001    SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8002 
8003    assert( var->scip == scip );
8004 
8005    if( branchpriority > SCIPvarGetBranchPriority(var) )
8006    {
8007       SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8008    }
8009 
8010    return SCIP_OKAY;
8011 }
8012 
8013 /** adds the given value to the branch priority of the variable
8014  *
8015  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8016  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8017  *
8018  *  @pre This method can be called if @p scip is in one of the following stages:
8019  *       - \ref SCIP_STAGE_PROBLEM
8020  *       - \ref SCIP_STAGE_TRANSFORMING
8021  *       - \ref SCIP_STAGE_TRANSFORMED
8022  *       - \ref SCIP_STAGE_INITPRESOLVE
8023  *       - \ref SCIP_STAGE_PRESOLVING
8024  *       - \ref SCIP_STAGE_EXITPRESOLVE
8025  *       - \ref SCIP_STAGE_PRESOLVED
8026  *       - \ref SCIP_STAGE_SOLVING
8027  */
SCIPaddVarBranchPriority(SCIP * scip,SCIP_VAR * var,int addpriority)8028 SCIP_RETCODE SCIPaddVarBranchPriority(
8029    SCIP*                 scip,               /**< SCIP data structure */
8030    SCIP_VAR*             var,                /**< problem variable */
8031    int                   addpriority         /**< value to add to the branch priority of the variable */
8032    )
8033 {
8034    SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8035 
8036    assert( var->scip == scip );
8037 
8038    SCIP_CALL( SCIPvarChgBranchPriority(var, addpriority + SCIPvarGetBranchPriority(var)) );
8039 
8040    return SCIP_OKAY;
8041 }
8042 
8043 /** sets the branch direction of the variable (-1: prefer downwards branch, 0: automatic selection, +1: prefer upwards
8044  *  branch)
8045  *
8046  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8047  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8048  *
8049  *  @pre This method can be called if @p scip is in one of the following stages:
8050  *       - \ref SCIP_STAGE_PROBLEM
8051  *       - \ref SCIP_STAGE_TRANSFORMING
8052  *       - \ref SCIP_STAGE_TRANSFORMED
8053  *       - \ref SCIP_STAGE_INITPRESOLVE
8054  *       - \ref SCIP_STAGE_PRESOLVING
8055  *       - \ref SCIP_STAGE_EXITPRESOLVE
8056  *       - \ref SCIP_STAGE_PRESOLVED
8057  *       - \ref SCIP_STAGE_SOLVING
8058  */
SCIPchgVarBranchDirection(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR branchdirection)8059 SCIP_RETCODE SCIPchgVarBranchDirection(
8060    SCIP*                 scip,               /**< SCIP data structure */
8061    SCIP_VAR*             var,                /**< problem variable */
8062    SCIP_BRANCHDIR        branchdirection     /**< preferred branch direction of the variable (downwards, upwards, auto) */
8063    )
8064 {
8065    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchDirection", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8066 
8067    assert( var->scip == scip );
8068 
8069    SCIP_CALL( SCIPvarChgBranchDirection(var, branchdirection) );
8070 
8071    return SCIP_OKAY;
8072 }
8073 
8074 /** tightens the variable bounds due to a new variable type */
8075 static
tightenBounds(SCIP * scip,SCIP_VAR * var,SCIP_VARTYPE vartype,SCIP_Bool * infeasible)8076 SCIP_RETCODE tightenBounds(
8077    SCIP*                 scip,               /**< SCIP data structure */
8078    SCIP_VAR*             var,                /**< variable to change the bound for */
8079    SCIP_VARTYPE          vartype,            /**< new type of variable */
8080    SCIP_Bool*            infeasible          /**< pointer to store whether an infeasibility was detected (, due to
8081                                               *   integrality condition of the new variable type) */
8082    )
8083 {
8084    assert(scip != NULL);
8085    assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING);
8086    assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPvarIsTransformed(var));
8087    assert(var->scip == scip);
8088 
8089    *infeasible = FALSE;
8090 
8091    /* adjusts bounds if the variable type changed form continuous to non-continuous (integral) */
8092    if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_CONTINUOUS )
8093    {
8094       SCIP_Bool tightened;
8095 
8096       /* we adjust variable bounds to integers first, since otherwise a later bound tightening with a fractional old
8097        * bound may give an assert because SCIP expects non-continuous variables to have non-fractional bounds
8098        *
8099        * we adjust bounds with a fractionality within [eps,feastol] only if the resulting bound change is a bound
8100        * tightening, because relaxing bounds may not be allowed
8101        */
8102       if( !SCIPisFeasIntegral(scip, SCIPvarGetLbGlobal(var)) ||
8103          (!SCIPisIntegral(scip, SCIPvarGetLbGlobal(var)) && SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) ||
8104          (!SCIPsetIsEQ(scip->set, SCIPvarGetLbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) &&
8105           SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)))
8106         )
8107       {
8108          SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)), TRUE, infeasible, &tightened) );
8109          if( *infeasible )
8110             return SCIP_OKAY;
8111 
8112          /* the only reason for not applying a forced boundchange is when the new bound is reduced because the variables upper bound is below the new bound
8113           * in a concrete case, lb == ub == 100.99999001; even though within feastol of 101, the lower bound cannot be tighented to 101 due to the upper bound
8114           */
8115          assert(tightened || SCIPisFeasLE(scip, SCIPvarGetUbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))));
8116       }
8117       if( !SCIPisFeasIntegral(scip, SCIPvarGetUbGlobal(var)) ||
8118          (!SCIPisIntegral(scip, SCIPvarGetUbGlobal(var)) && SCIPvarGetUbGlobal(var) > SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)))
8119         )
8120       {
8121          SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)), TRUE, infeasible, &tightened) );
8122          if( *infeasible )
8123             return SCIP_OKAY;
8124 
8125          assert(tightened || SCIPisFeasGE(scip, SCIPvarGetLbGlobal(var), SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var))));
8126       }
8127    }
8128 
8129    return SCIP_OKAY;
8130 }
8131 
8132 /** changes type of variable in the problem;
8133  *
8134  *  @warning This type change might change the variable array returned from SCIPgetVars() and SCIPgetVarsData();
8135  *
8136  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8137  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8138  *
8139  *  @pre This method can be called if @p scip is in one of the following stages:
8140  *       - \ref SCIP_STAGE_PROBLEM
8141  *       - \ref SCIP_STAGE_TRANSFORMING
8142  *       - \ref SCIP_STAGE_PRESOLVING
8143  *
8144  *  @note If SCIP is already beyond the SCIP_STAGE_PROBLEM and a original variable is passed, the variable type of the
8145  *        corresponding transformed variable is changed; the type of the original variable does not change
8146  *
8147  *  @note If the type changes from a continuous variable to a non-continuous variable the bounds of the variable get
8148  *        adjusted w.r.t. to integrality information
8149  */
SCIPchgVarType(SCIP * scip,SCIP_VAR * var,SCIP_VARTYPE vartype,SCIP_Bool * infeasible)8150 SCIP_RETCODE SCIPchgVarType(
8151    SCIP*                 scip,               /**< SCIP data structure */
8152    SCIP_VAR*             var,                /**< variable to change the bound for */
8153    SCIP_VARTYPE          vartype,            /**< new type of variable */
8154    SCIP_Bool*            infeasible          /**< pointer to store whether an infeasibility was detected (, due to
8155                                               *   integrality condition of the new variable type) */
8156    )
8157 {
8158    SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarType", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8159 
8160    assert(var != NULL);
8161    assert(var->scip == scip);
8162 
8163    if( SCIPvarIsNegated(var) )
8164    {
8165       SCIPdebugMsg(scip, "upgrading type of negated variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype);
8166       var = SCIPvarGetNegationVar(var);
8167    }
8168 #ifndef NDEBUG
8169    else
8170    {
8171       if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
8172       {
8173          SCIPdebugMsg(scip, "upgrading type of variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype);
8174       }
8175    }
8176 #endif
8177 
8178    /* change variable type */
8179    switch( scip->set->stage )
8180    {
8181    case SCIP_STAGE_PROBLEM:
8182       assert(!SCIPvarIsTransformed(var));
8183 
8184       /* first adjust the variable due to new integrality information */
8185       SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) );
8186 
8187       /* second change variable type */
8188       if( SCIPvarGetProbindex(var) >= 0 )
8189       {
8190          SCIP_CALL( SCIPprobChgVarType(scip->origprob, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8191             scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) );
8192       }
8193       else
8194       {
8195          SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8196             scip->eventqueue, vartype) );
8197       }
8198       break;
8199 
8200    case SCIP_STAGE_PRESOLVING:
8201       if( !SCIPvarIsTransformed(var) )
8202       {
8203          SCIP_VAR* transvar;
8204 
8205          SCIP_CALL( SCIPgetTransformedVar(scip, var, &transvar) );
8206          assert(transvar != NULL);
8207 
8208          /* recall method with transformed variable */
8209          SCIP_CALL( SCIPchgVarType(scip, transvar, vartype, infeasible) );
8210          return SCIP_OKAY;
8211       }
8212 
8213       /* first adjust the variable due to new integrality information */
8214       SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) );
8215 
8216       /* second change variable type */
8217       if( SCIPvarGetProbindex(var) >= 0 )
8218       {
8219          SCIP_CALL( SCIPprobChgVarType(scip->transprob, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8220             scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) );
8221       }
8222       else
8223       {
8224          SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8225             scip->eventqueue, vartype) );
8226       }
8227       break;
8228 
8229    default:
8230       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
8231       return SCIP_INVALIDCALL;
8232    }  /*lint !e788*/
8233 
8234    return SCIP_OKAY;
8235 }
8236 
8237 /** in problem creation and solving stage, both bounds of the variable are set to the given value;
8238  *  in presolving stage, the variable is converted into a fixed variable, and bounds are changed respectively;
8239  *  conversion into a fixed variable changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(),
8240  *  and also renders arrays returned from the SCIPvarGetImpl...() methods invalid
8241  *
8242  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8243  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8244  *
8245  *  @pre This method can be called if @p scip is in one of the following stages:
8246  *       - \ref SCIP_STAGE_PROBLEM
8247  *       - \ref SCIP_STAGE_PRESOLVING
8248  *       - \ref SCIP_STAGE_SOLVING
8249  */
SCIPfixVar(SCIP * scip,SCIP_VAR * var,SCIP_Real fixedval,SCIP_Bool * infeasible,SCIP_Bool * fixed)8250 SCIP_RETCODE SCIPfixVar(
8251    SCIP*                 scip,               /**< SCIP data structure */
8252    SCIP_VAR*             var,                /**< variable to fix */
8253    SCIP_Real             fixedval,           /**< value to fix variable to */
8254    SCIP_Bool*            infeasible,         /**< pointer to store whether the fixing is infeasible */
8255    SCIP_Bool*            fixed               /**< pointer to store whether the fixing was performed (variable was unfixed) */
8256    )
8257 {
8258    assert(var != NULL);
8259    assert(infeasible != NULL);
8260    assert(fixed != NULL);
8261 
8262    SCIP_CALL( SCIPcheckStage(scip, "SCIPfixVar", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8263 
8264    *infeasible = FALSE;
8265    *fixed = FALSE;
8266 
8267    /* in the problem creation stage, modify the bounds as requested, independently from the current bounds */
8268    if( scip->set->stage != SCIP_STAGE_PROBLEM )
8269    {
8270       if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(scip->set, fixedval))
8271          || SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var))
8272          || SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8273       {
8274          *infeasible = TRUE;
8275          return SCIP_OKAY;
8276       }
8277       else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED )
8278       {
8279          *infeasible = !SCIPsetIsFeasEQ(scip->set, fixedval, SCIPvarGetLbLocal(var));
8280          return SCIP_OKAY;
8281       }
8282    }
8283    else
8284       assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
8285 
8286    switch( scip->set->stage )
8287    {
8288    case SCIP_STAGE_PROBLEM:
8289       /* in the problem creation stage, modify the bounds as requested, independently from the current bounds;
8290        * we have to make sure, that the order of the bound changes does not intermediately produce an invalid
8291        * interval lb > ub
8292        */
8293       if( fixedval <= SCIPvarGetLbLocal(var) )
8294       {
8295          SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8296          SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8297          *fixed = TRUE;
8298       }
8299       else
8300       {
8301          SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8302          SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8303          *fixed = TRUE;
8304       }
8305       return SCIP_OKAY;
8306 
8307    case SCIP_STAGE_PRESOLVING:
8308       if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
8309       {
8310          SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8311                scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8312                scip->cliquetable, fixedval, infeasible, fixed) );
8313          return SCIP_OKAY;
8314       }
8315       /*lint -fallthrough*/
8316    case SCIP_STAGE_SOLVING:
8317       if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetLbLocal(var)) )
8318       {
8319          if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8320          {
8321             *infeasible = TRUE;
8322             return SCIP_OKAY;
8323          }
8324          else
8325          {
8326             SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8327             *fixed = TRUE;
8328          }
8329       }
8330       if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8331       {
8332          if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var)) )
8333          {
8334             *infeasible = TRUE;
8335             return SCIP_OKAY;
8336          }
8337          else
8338          {
8339             SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8340             *fixed = TRUE;
8341          }
8342       }
8343       return SCIP_OKAY;
8344 
8345    default:
8346       SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
8347       return SCIP_INVALIDCALL;
8348    }  /*lint !e788*/
8349 }
8350 
8351 /** From a given equality a*x + b*y == c, aggregates one of the variables and removes it from the set of
8352  *  active problem variables. This changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(),
8353  *  and also renders the arrays returned from the SCIPvarGetImpl...() methods for the two variables invalid.
8354  *  In the first step, the equality is transformed into an equality with active problem variables
8355  *  a'*x' + b'*y' == c'. If x' == y', this leads to the detection of redundancy if a' == -b' and c' == 0,
8356  *  of infeasibility, if a' == -b' and c' != 0, or to a variable fixing x' == c'/(a'+b') (and possible
8357  *  infeasibility) otherwise.
8358  *  In the second step, the variable to be aggregated is chosen among x' and y', prefering a less strict variable
8359  *  type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
8360  *  over integers, and integers over binaries). If none of the variables is continuous, it is tried to find an integer
8361  *  aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
8362  *  the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
8363  *  aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
8364  *
8365  *  The output flags have the following meaning:
8366  *  - infeasible: the problem is infeasible
8367  *  - redundant:  the equality can be deleted from the constraint set
8368  *  - aggregated: the aggregation was successfully performed (the variables were not aggregated before)
8369  *
8370  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8371  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8372  *
8373  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING
8374  */
SCIPaggregateVars(SCIP * scip,SCIP_VAR * varx,SCIP_VAR * vary,SCIP_Real scalarx,SCIP_Real scalary,SCIP_Real rhs,SCIP_Bool * infeasible,SCIP_Bool * redundant,SCIP_Bool * aggregated)8375 SCIP_RETCODE SCIPaggregateVars(
8376    SCIP*                 scip,               /**< SCIP data structure */
8377    SCIP_VAR*             varx,               /**< variable x in equality a*x + b*y == c */
8378    SCIP_VAR*             vary,               /**< variable y in equality a*x + b*y == c */
8379    SCIP_Real             scalarx,            /**< multiplier a in equality a*x + b*y == c */
8380    SCIP_Real             scalary,            /**< multiplier b in equality a*x + b*y == c */
8381    SCIP_Real             rhs,                /**< right hand side c in equality a*x + b*y == c */
8382    SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
8383    SCIP_Bool*            redundant,          /**< pointer to store whether the equality is (now) redundant */
8384    SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
8385    )
8386 {
8387    SCIP_Real constantx;
8388    SCIP_Real constanty;
8389 
8390    assert(infeasible != NULL);
8391    assert(redundant != NULL);
8392    assert(aggregated != NULL);
8393 
8394    SCIP_CALL( SCIPcheckStage(scip, "SCIPaggregateVars", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8395 
8396    *infeasible = FALSE;
8397    *redundant = FALSE;
8398    *aggregated = FALSE;
8399 
8400    if( SCIPtreeProbing(scip->tree) )
8401    {
8402       SCIPerrorMessage("cannot aggregate variables during probing\n");
8403       return SCIP_INVALIDCALL;
8404    }
8405    assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
8406 
8407    /* do not perform aggregation if it is globally deactivated */
8408    if( scip->set->presol_donotaggr )
8409       return SCIP_OKAY;
8410 
8411    /* get the corresponding equality in active problem variable space:
8412     * transform both expressions "a*x + 0" and "b*y + 0" into problem variable space
8413     */
8414    constantx = 0.0;
8415    constanty = 0.0;
8416    SCIP_CALL( SCIPvarGetProbvarSum(&varx, scip->set, &scalarx, &constantx) );
8417    SCIP_CALL( SCIPvarGetProbvarSum(&vary, scip->set, &scalary, &constanty) );
8418 
8419    /* we cannot aggregate multi-aggregated variables */
8420    if( SCIPvarGetStatus(varx) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vary) == SCIP_VARSTATUS_MULTAGGR )
8421       return SCIP_OKAY;
8422 
8423    /* move the constant to the right hand side to acquire the form "a'*x' + b'*y' == c'" */
8424    rhs -= (constantx + constanty);
8425 
8426    /* if a scalar is zero, treat the variable as fixed-to-zero variable */
8427    if( SCIPsetIsZero(scip->set, scalarx) )
8428       varx = NULL;
8429    if( SCIPsetIsZero(scip->set, scalary) )
8430       vary = NULL;
8431 
8432    /* capture the special cases that less than two variables are left, due to resolutions to a fixed variable or
8433     * to the same active variable
8434     */
8435    if( varx == NULL && vary == NULL )
8436    {
8437       /* both variables were resolved to fixed variables */
8438       *infeasible = !SCIPsetIsZero(scip->set, rhs);
8439       *redundant = TRUE;
8440    }
8441    else if( varx == NULL )
8442    {
8443       assert(SCIPsetIsZero(scip->set, scalarx));
8444       assert(!SCIPsetIsZero(scip->set, scalary));
8445 
8446       /* variable x was resolved to fixed variable: variable y can be fixed to c'/b' */
8447       SCIP_CALL( SCIPvarFix(vary, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8448             scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8449             scip->cliquetable, rhs/scalary, infeasible, aggregated) );
8450       *redundant = TRUE;
8451    }
8452    else if( vary == NULL )
8453    {
8454       assert(SCIPsetIsZero(scip->set, scalary));
8455       assert(!SCIPsetIsZero(scip->set, scalarx));
8456 
8457       /* variable y was resolved to fixed variable: variable x can be fixed to c'/a' */
8458       SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8459             scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8460             scip->cliquetable, rhs/scalarx, infeasible, aggregated) );
8461       *redundant = TRUE;
8462    }
8463    else if( varx == vary )
8464    {
8465       /* both variables were resolved to the same active problem variable: this variable can be fixed */
8466       scalarx += scalary;
8467       if( SCIPsetIsZero(scip->set, scalarx) )
8468       {
8469          /* left hand side of equality is zero: equality is potentially infeasible */
8470          *infeasible = !SCIPsetIsZero(scip->set, rhs);
8471       }
8472       else
8473       {
8474          /* sum of scalars is not zero: fix variable x' == y' to c'/(a'+b') */
8475          SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8476                scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8477                scip->cliquetable, rhs/scalarx, infeasible, aggregated) );
8478       }
8479       *redundant = TRUE;
8480    }
8481    else
8482    {
8483       /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8484       SCIP_CALL( SCIPvarTryAggregateVars(scip->set, scip->mem->probmem, scip->stat, scip->transprob, scip->origprob,
8485             scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter,
8486             scip->eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
8487       *redundant = *aggregated;
8488    }
8489 
8490    return SCIP_OKAY;
8491 }
8492 
8493 /** converts variable into multi-aggregated variable; this changes the variable array returned from
8494  *  SCIPgetVars() and SCIPgetVarsData();
8495  *
8496  *  @warning The integrality condition is not checked anymore on the multi-aggregated variable. You must not
8497  *           multi-aggregate an integer variable without being sure, that integrality on the aggregation variables
8498  *           implies integrality on the aggregated variable.
8499  *
8500  *  The output flags have the following meaning:
8501  *  - infeasible: the problem is infeasible
8502  *  - aggregated: the aggregation was successfully performed (the variables were not aggregated before)
8503  *
8504  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8505  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8506  *
8507  *  @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING
8508  */
SCIPmultiaggregateVar(SCIP * scip,SCIP_VAR * var,int naggvars,SCIP_VAR ** aggvars,SCIP_Real * scalars,SCIP_Real constant,SCIP_Bool * infeasible,SCIP_Bool * aggregated)8509 SCIP_RETCODE SCIPmultiaggregateVar(
8510    SCIP*                 scip,               /**< SCIP data structure */
8511    SCIP_VAR*             var,                /**< variable x to aggregate */
8512    int                   naggvars,           /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8513    SCIP_VAR**            aggvars,            /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8514    SCIP_Real*            scalars,            /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8515    SCIP_Real             constant,           /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8516    SCIP_Bool*            infeasible,         /**< pointer to store whether the aggregation is infeasible */
8517    SCIP_Bool*            aggregated          /**< pointer to store whether the aggregation was successful */
8518    )
8519 {
8520    SCIP_CALL( SCIPcheckStage(scip, "SCIPmultiaggregateVar", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8521 
8522    assert(var->scip == scip);
8523 
8524    if( SCIPtreeProbing(scip->tree) )
8525    {
8526       SCIPerrorMessage("cannot multi-aggregate variables during probing\n");
8527       return SCIP_INVALIDCALL;
8528    }
8529    assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
8530 
8531    SCIP_CALL( SCIPvarMultiaggregate(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8532          scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter,
8533          scip->eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8534 
8535    return SCIP_OKAY;
8536 }
8537 
8538 /** returns whether aggregation of variables is not allowed */
SCIPdoNotAggr(SCIP * scip)8539 SCIP_Bool SCIPdoNotAggr(
8540    SCIP*                 scip                /**< SCIP data structure */
8541    )
8542 {
8543    assert(scip != NULL);
8544 
8545    return scip->set->presol_donotaggr;
8546 }
8547 
8548 /** returns whether multi-aggregation is disabled */
SCIPdoNotMultaggr(SCIP * scip)8549 SCIP_Bool SCIPdoNotMultaggr(
8550    SCIP*                 scip                /**< SCIP data structure */
8551    )
8552 {
8553    assert(scip != NULL);
8554 
8555    return scip->set->presol_donotmultaggr;
8556 }
8557 
8558 /** returns whether variable is not allowed to be multi-aggregated */
SCIPdoNotMultaggrVar(SCIP * scip,SCIP_VAR * var)8559 SCIP_Bool SCIPdoNotMultaggrVar(
8560    SCIP*                 scip,               /**< SCIP data structure */
8561    SCIP_VAR*             var                 /**< variable x to aggregate */
8562    )
8563 {
8564    assert(scip != NULL);
8565    assert(var != NULL);
8566    assert(var->scip == scip);
8567 
8568    return scip->set->presol_donotmultaggr || SCIPvarDoNotMultaggr(var);
8569 }
8570 
8571 /** returns whether dual reductions are allowed during propagation and presolving
8572  *
8573  *  @deprecated Please use SCIPallowStrongDualReds()
8574  */
SCIPallowDualReds(SCIP * scip)8575 SCIP_Bool SCIPallowDualReds(
8576    SCIP*                 scip                /**< SCIP data structure */
8577    )
8578 {
8579    assert(scip != NULL);
8580 
8581    return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds;
8582 }
8583 
8584 /** returns whether strong dual reductions are allowed during propagation and presolving
8585  *
8586  *  @note A reduction is called strong dual, if it may discard feasible/optimal solutions, but leaves at least one
8587  *        optimal solution intact. Often such reductions are based on analyzing the objective function and variable
8588  *        locks.
8589  */
SCIPallowStrongDualReds(SCIP * scip)8590 SCIP_Bool SCIPallowStrongDualReds(
8591    SCIP*                 scip                /**< SCIP data structure */
8592    )
8593 {
8594    assert(scip != NULL);
8595 
8596    return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds;
8597 }
8598 
8599 /** returns whether propagation w.r.t. current objective is allowed
8600  *
8601  *  @deprecated Please use SCIPallowWeakDualReds()
8602  */
SCIPallowObjProp(SCIP * scip)8603 SCIP_Bool SCIPallowObjProp(
8604    SCIP*                 scip                /**< SCIP data structure */
8605    )
8606 {
8607    assert(scip != NULL);
8608 
8609    return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds;
8610 }
8611 
8612 /** returns whether weak dual reductions are allowed during propagation and presolving
8613  *
8614  *  @note A reduction is called weak dual, if it may discard feasible solutions, but leaves at all optimal solutions
8615  *        intact. Often such reductions are based on analyzing the objective function, reduced costs, and/or dual LPs.
8616  */
SCIPallowWeakDualReds(SCIP * scip)8617 SCIP_Bool SCIPallowWeakDualReds(
8618    SCIP*                 scip                /**< SCIP data structure */
8619    )
8620 {
8621    assert(scip != NULL);
8622 
8623    return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds;
8624 }
8625 
8626 /** marks the variable that it must not be multi-aggregated
8627  *
8628  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8629  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8630  *
8631  *  @pre This method can be called if @p scip is in one of the following stages:
8632  *       - \ref SCIP_STAGE_INIT
8633  *       - \ref SCIP_STAGE_PROBLEM
8634  *       - \ref SCIP_STAGE_TRANSFORMING
8635  *       - \ref SCIP_STAGE_TRANSFORMED
8636  *       - \ref SCIP_STAGE_INITPRESOLVE
8637  *       - \ref SCIP_STAGE_PRESOLVING
8638  *       - \ref SCIP_STAGE_EXITPRESOLVE
8639  *
8640  *  @note There exists no "unmark" method since it has to be ensured that if a plugin requires that a variable is not
8641  *        multi-aggregated that this is will be the case.
8642  */
SCIPmarkDoNotMultaggrVar(SCIP * scip,SCIP_VAR * var)8643 SCIP_RETCODE SCIPmarkDoNotMultaggrVar(
8644    SCIP*                 scip,               /**< SCIP data structure */
8645    SCIP_VAR*             var                 /**< variable to delete */
8646    )
8647 {
8648    assert(scip != NULL);
8649    assert(var != NULL);
8650    assert(var->scip == scip);
8651 
8652    SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkDoNotMultaggrVar", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE) );
8653 
8654    SCIP_CALL( SCIPvarMarkDoNotMultaggr(var) );
8655 
8656    return SCIP_OKAY;
8657 }
8658 
8659 /** enables the collection of statistics for a variable
8660  *
8661  *  @pre This method can be called if @p scip is in one of the following stages:
8662  *       - \ref SCIP_STAGE_PROBLEM
8663  *       - \ref SCIP_STAGE_INITPRESOLVE
8664  *       - \ref SCIP_STAGE_PRESOLVING
8665  *       - \ref SCIP_STAGE_EXITPRESOLVE
8666  *       - \ref SCIP_STAGE_SOLVING
8667  *       - \ref SCIP_STAGE_SOLVED
8668  */
SCIPenableVarHistory(SCIP * scip)8669 void SCIPenableVarHistory(
8670    SCIP*                 scip                /**< SCIP data structure */
8671    )
8672 {
8673    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPenableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8674 
8675    SCIPstatEnableVarHistory(scip->stat);
8676 }
8677 
8678 /** disables the collection of any statistic for a variable
8679  *
8680  *  @pre This method can be called if @p scip is in one of the following stages:
8681  *       - \ref SCIP_STAGE_PROBLEM
8682  *       - \ref SCIP_STAGE_INITPRESOLVE
8683  *       - \ref SCIP_STAGE_PRESOLVING
8684  *       - \ref SCIP_STAGE_EXITPRESOLVE
8685  *       - \ref SCIP_STAGE_SOLVING
8686  *       - \ref SCIP_STAGE_SOLVED
8687  */
SCIPdisableVarHistory(SCIP * scip)8688 void SCIPdisableVarHistory(
8689    SCIP*                 scip                /**< SCIP data structure */
8690    )
8691 {
8692    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPdisableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8693 
8694    SCIPstatDisableVarHistory(scip->stat);
8695 }
8696 
8697 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of "solvaldelta" in the
8698  *  variable's solution value and resulting change of "objdelta" in the in the LP's objective value;
8699  *  the update is ignored, if the objective value difference is infinite
8700  *
8701  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8702  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8703  *
8704  *  @pre This method can be called if @p scip is in one of the following stages:
8705  *       - \ref SCIP_STAGE_SOLVING
8706  *       - \ref SCIP_STAGE_SOLVED
8707  */
SCIPupdateVarPseudocost(SCIP * scip,SCIP_VAR * var,SCIP_Real solvaldelta,SCIP_Real objdelta,SCIP_Real weight)8708 SCIP_RETCODE SCIPupdateVarPseudocost(
8709    SCIP*                 scip,               /**< SCIP data structure */
8710    SCIP_VAR*             var,                /**< problem variable */
8711    SCIP_Real             solvaldelta,        /**< difference of variable's new LP value - old LP value */
8712    SCIP_Real             objdelta,           /**< difference of new LP's objective value - old LP's objective value */
8713    SCIP_Real             weight              /**< weight in (0,1] of this update in pseudo cost sum */
8714    )
8715 {
8716    SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarPseudocost", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8717 
8718    if( !SCIPsetIsInfinity(scip->set, 2*objdelta) ) /* differences  infinity - eps  should also be treated as infinity */
8719    {
8720       if( scip->set->branch_divingpscost || (!scip->lp->diving && !SCIPtreeProbing(scip->tree)) )
8721       {
8722          SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, solvaldelta, objdelta, weight) );
8723       }
8724    }
8725 
8726    return SCIP_OKAY;
8727 }
8728 
8729 /** gets the variable's pseudo cost value for the given change of the variable's LP value
8730  *
8731  *  @return the variable's pseudo cost value for the given change of the variable's LP value
8732  *
8733  *  @pre This method can be called if @p scip is in one of the following stages:
8734  *       - \ref SCIP_STAGE_INITPRESOLVE
8735  *       - \ref SCIP_STAGE_PRESOLVING
8736  *       - \ref SCIP_STAGE_EXITPRESOLVE
8737  *       - \ref SCIP_STAGE_PRESOLVED
8738  *       - \ref SCIP_STAGE_INITSOLVE
8739  *       - \ref SCIP_STAGE_SOLVING
8740  *       - \ref SCIP_STAGE_SOLVED
8741  */
SCIPgetVarPseudocostVal(SCIP * scip,SCIP_VAR * var,SCIP_Real solvaldelta)8742 SCIP_Real SCIPgetVarPseudocostVal(
8743    SCIP*                 scip,               /**< SCIP data structure */
8744    SCIP_VAR*             var,                /**< problem variable */
8745    SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
8746    )
8747 {
8748    assert( var->scip == scip );
8749 
8750    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVal", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8751 
8752    return SCIPvarGetPseudocost(var, scip->stat, solvaldelta);
8753 }
8754 
8755 /** gets the variable's pseudo cost value for the given change of the variable's LP value,
8756  *  only using the pseudo cost information of the current run
8757  *
8758  *  @return the variable's pseudo cost value for the given change of the variable's LP value,
8759  *  only using the pseudo cost information of the current run
8760  *
8761  *  @pre This method can be called if @p scip is in one of the following stages:
8762  *       - \ref SCIP_STAGE_INITPRESOLVE
8763  *       - \ref SCIP_STAGE_PRESOLVING
8764  *       - \ref SCIP_STAGE_EXITPRESOLVE
8765  *       - \ref SCIP_STAGE_PRESOLVED
8766  *       - \ref SCIP_STAGE_INITSOLVE
8767  *       - \ref SCIP_STAGE_SOLVING
8768  *       - \ref SCIP_STAGE_SOLVED
8769  */
SCIPgetVarPseudocostValCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_Real solvaldelta)8770 SCIP_Real SCIPgetVarPseudocostValCurrentRun(
8771    SCIP*                 scip,               /**< SCIP data structure */
8772    SCIP_VAR*             var,                /**< problem variable */
8773    SCIP_Real             solvaldelta         /**< difference of variable's new LP value - old LP value */
8774    )
8775 {
8776    assert( var->scip == scip );
8777 
8778    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostValCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8779 
8780    return SCIPvarGetPseudocostCurrentRun(var, scip->stat, solvaldelta);
8781 }
8782 
8783 /** gets the variable's pseudo cost value for the given direction
8784  *
8785  *  @return the variable's pseudo cost value for the given direction
8786  *
8787  *  @pre This method can be called if @p scip is in one of the following stages:
8788  *       - \ref SCIP_STAGE_INITPRESOLVE
8789  *       - \ref SCIP_STAGE_PRESOLVING
8790  *       - \ref SCIP_STAGE_EXITPRESOLVE
8791  *       - \ref SCIP_STAGE_PRESOLVED
8792  *       - \ref SCIP_STAGE_INITSOLVE
8793  *       - \ref SCIP_STAGE_SOLVING
8794  *       - \ref SCIP_STAGE_SOLVED
8795  */
SCIPgetVarPseudocost(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)8796 SCIP_Real SCIPgetVarPseudocost(
8797    SCIP*                 scip,               /**< SCIP data structure */
8798    SCIP_VAR*             var,                /**< problem variable */
8799    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
8800    )
8801 {
8802    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocost", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8803    assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8804    assert(var->scip == scip);
8805 
8806    return SCIPvarGetPseudocost(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
8807 }
8808 
8809 /** gets the variable's pseudo cost value for the given direction,
8810  *  only using the pseudo cost information of the current run
8811  *
8812  *  @return the variable's pseudo cost value for the given direction,
8813  *  only using the pseudo cost information of the current run
8814  *
8815  *  @pre This method can be called if @p scip is in one of the following stages:
8816  *       - \ref SCIP_STAGE_INITPRESOLVE
8817  *       - \ref SCIP_STAGE_PRESOLVING
8818  *       - \ref SCIP_STAGE_EXITPRESOLVE
8819  *       - \ref SCIP_STAGE_PRESOLVED
8820  *       - \ref SCIP_STAGE_INITSOLVE
8821  *       - \ref SCIP_STAGE_SOLVING
8822  *       - \ref SCIP_STAGE_SOLVED
8823  */
SCIPgetVarPseudocostCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)8824 SCIP_Real SCIPgetVarPseudocostCurrentRun(
8825    SCIP*                 scip,               /**< SCIP data structure */
8826    SCIP_VAR*             var,                /**< problem variable */
8827    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
8828    )
8829 {
8830    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8831    assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8832    assert(var->scip == scip);
8833 
8834    return SCIPvarGetPseudocostCurrentRun(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
8835 }
8836 
8837 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction
8838  *
8839  *  @return the variable's (possible fractional) number of pseudo cost updates for the given direction
8840  *
8841  *  @pre This method can be called if @p scip is in one of the following stages:
8842  *       - \ref SCIP_STAGE_INITPRESOLVE
8843  *       - \ref SCIP_STAGE_PRESOLVING
8844  *       - \ref SCIP_STAGE_EXITPRESOLVE
8845  *       - \ref SCIP_STAGE_PRESOLVED
8846  *       - \ref SCIP_STAGE_INITSOLVE
8847  *       - \ref SCIP_STAGE_SOLVING
8848  *       - \ref SCIP_STAGE_SOLVED
8849  */
SCIPgetVarPseudocostCount(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)8850 SCIP_Real SCIPgetVarPseudocostCount(
8851    SCIP*                 scip,               /**< SCIP data structure */
8852    SCIP_VAR*             var,                /**< problem variable */
8853    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
8854    )
8855 {
8856    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCount", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8857    assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8858    assert(var->scip == scip);
8859 
8860    return SCIPvarGetPseudocostCount(var, dir);
8861 }
8862 
8863 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
8864  *  only using the pseudo cost information of the current run
8865  *
8866  *  @return the variable's (possible fractional) number of pseudo cost updates for the given direction,
8867  *  only using the pseudo cost information of the current run
8868  *
8869  *  @pre This method can be called if @p scip is in one of the following stages:
8870  *       - \ref SCIP_STAGE_INITPRESOLVE
8871  *       - \ref SCIP_STAGE_PRESOLVING
8872  *       - \ref SCIP_STAGE_EXITPRESOLVE
8873  *       - \ref SCIP_STAGE_PRESOLVED
8874  *       - \ref SCIP_STAGE_INITSOLVE
8875  *       - \ref SCIP_STAGE_SOLVING
8876  *       - \ref SCIP_STAGE_SOLVED
8877  */
SCIPgetVarPseudocostCountCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)8878 SCIP_Real SCIPgetVarPseudocostCountCurrentRun(
8879    SCIP*                 scip,               /**< SCIP data structure */
8880    SCIP_VAR*             var,                /**< problem variable */
8881    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
8882    )
8883 {
8884    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCountCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8885    assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8886    assert(var->scip == scip);
8887 
8888    return SCIPvarGetPseudocostCountCurrentRun(var, dir);
8889 }
8890 
8891 /** get pseudo cost variance of the variable, either for entire solve or only for current branch and bound run
8892  *
8893  *  @return returns the (corrected) variance of pseudo code information collected so far.
8894  *
8895  *  @pre This method can be called if @p scip is in one of the following stages:
8896  *       - \ref SCIP_STAGE_INITPRESOLVE
8897  *       - \ref SCIP_STAGE_PRESOLVING
8898  *       - \ref SCIP_STAGE_EXITPRESOLVE
8899  *       - \ref SCIP_STAGE_PRESOLVED
8900  *       - \ref SCIP_STAGE_INITSOLVE
8901  *       - \ref SCIP_STAGE_SOLVING
8902  *       - \ref SCIP_STAGE_SOLVED
8903  */
SCIPgetVarPseudocostVariance(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir,SCIP_Bool onlycurrentrun)8904 SCIP_Real SCIPgetVarPseudocostVariance(
8905    SCIP*                 scip,               /**< SCIP data structure */
8906    SCIP_VAR*             var,                /**< problem variable */
8907    SCIP_BRANCHDIR        dir,                /**< branching direction (downwards, or upwards) */
8908    SCIP_Bool             onlycurrentrun      /**< only for pseudo costs of current branch and bound run */
8909    )
8910 {
8911    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVariance", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8912    assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8913    assert(var->scip == scip);
8914 
8915    return SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
8916 }
8917 
8918 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
8919  *
8920  *  The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
8921  *  the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
8922  *  of 2 * clevel - 1.
8923  *
8924  *  @return value of confidence bound for this variable
8925  */
SCIPcalculatePscostConfidenceBound(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir,SCIP_Bool onlycurrentrun,SCIP_CONFIDENCELEVEL clevel)8926 SCIP_Real SCIPcalculatePscostConfidenceBound(
8927    SCIP*                 scip,               /**< SCIP data structure */
8928    SCIP_VAR*             var,                /**< variable in question */
8929    SCIP_BRANCHDIR        dir,                /**< the branching direction for the confidence bound */
8930    SCIP_Bool             onlycurrentrun,     /**< should only the current run be taken into account */
8931    SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for the interval */
8932    )
8933 {
8934    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcalculatePscostConfidenceBound", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8935 
8936    return SCIPvarCalcPscostConfidenceBound(var, scip->set, dir, onlycurrentrun, clevel);
8937 }
8938 
8939 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
8940  *  the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
8941  *  should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
8942  *  unknown location means of the underlying pseudo-cost distributions of x and y.
8943  *
8944  *  This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
8945  *  better than x (despite the current information), meaning that y can be expected to yield branching
8946  *  decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
8947  *  sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
8948  *  than y.
8949  *
8950  *  @note The order of x and y matters for the one-sided hypothesis
8951  *
8952  *  @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
8953  *        fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
8954  *
8955  *  @return TRUE if the hypothesis can be safely rejected at the given confidence level
8956  */
SCIPsignificantVarPscostDifference(SCIP * scip,SCIP_VAR * varx,SCIP_Real fracx,SCIP_VAR * vary,SCIP_Real fracy,SCIP_BRANCHDIR dir,SCIP_CONFIDENCELEVEL clevel,SCIP_Bool onesided)8957 SCIP_Bool SCIPsignificantVarPscostDifference(
8958    SCIP*                 scip,               /**< SCIP data structure */
8959    SCIP_VAR*             varx,               /**< variable x */
8960    SCIP_Real             fracx,              /**< the fractionality of variable x */
8961    SCIP_VAR*             vary,               /**< variable y */
8962    SCIP_Real             fracy,              /**< the fractionality of variable y */
8963    SCIP_BRANCHDIR        dir,                /**< branching direction */
8964    SCIP_CONFIDENCELEVEL  clevel,             /**< confidence level for rejecting hypothesis */
8965    SCIP_Bool             onesided            /**< should a one-sided hypothesis y >= x be tested? */
8966    )
8967 {
8968    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPsignificantVarPscostDifference", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8969 
8970    return SCIPvarSignificantPscostDifference(scip->set, scip->stat, varx, fracx, vary, fracy, dir, clevel, onesided);
8971 }
8972 
8973 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
8974  *  exceed a \p threshold. This is useful to determine if past observations provide enough evidence
8975  *  to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
8976  *  of at least \p threshold.
8977  *
8978  *  @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
8979  *        the estimated probability to exceed \p threshold is less than 25 %.
8980  *
8981  *  @see  SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
8982  *        of confidence.
8983  *
8984  *  @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
8985  *          at the given confidence level \p clevel.
8986  */
SCIPpscostThresholdProbabilityTest(SCIP * scip,SCIP_VAR * var,SCIP_Real frac,SCIP_Real threshold,SCIP_BRANCHDIR dir,SCIP_CONFIDENCELEVEL clevel)8987 SCIP_Bool SCIPpscostThresholdProbabilityTest(
8988    SCIP*                 scip,               /**< SCIP data structure */
8989    SCIP_VAR*             var,                /**< variable x */
8990    SCIP_Real             frac,               /**< the fractionality of variable x */
8991    SCIP_Real             threshold,          /**< the threshold to test against */
8992    SCIP_BRANCHDIR        dir,                /**< branching direction */
8993    SCIP_CONFIDENCELEVEL  clevel              /**< confidence level for rejecting hypothesis */
8994    )
8995 {
8996    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPpscostThresholdProbabilityTest", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8997 
8998    return SCIPvarPscostThresholdProbabilityTest(scip->set, scip->stat, var, frac, threshold, dir, clevel);
8999 }
9000 
9001 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
9002  *  Error is calculated at a specific confidence level
9003  *
9004  *  @return TRUE if relative error in variable pseudo costs is smaller than \p threshold
9005  */
SCIPisVarPscostRelerrorReliable(SCIP * scip,SCIP_VAR * var,SCIP_Real threshold,SCIP_CONFIDENCELEVEL clevel)9006 SCIP_Bool SCIPisVarPscostRelerrorReliable(
9007    SCIP*                 scip,               /**< SCIP data structure */
9008    SCIP_VAR*             var,                /**< variable in question */
9009    SCIP_Real             threshold,          /**< threshold for relative errors to be considered reliable (enough) */
9010    SCIP_CONFIDENCELEVEL  clevel              /**< a given confidence level */
9011    )
9012 {
9013    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisVarPscostRelerrorReliable", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9014 
9015    return SCIPvarIsPscostRelerrorReliable(var, scip->set, scip->stat, threshold, clevel);
9016 }
9017 
9018 /** gets the variable's pseudo cost score value for the given LP solution value
9019  *
9020  *  @return the variable's pseudo cost score value for the given LP solution value
9021  *
9022  *  @pre This method can be called if @p scip is in one of the following stages:
9023  *       - \ref SCIP_STAGE_INITPRESOLVE
9024  *       - \ref SCIP_STAGE_PRESOLVING
9025  *       - \ref SCIP_STAGE_EXITPRESOLVE
9026  *       - \ref SCIP_STAGE_PRESOLVED
9027  *       - \ref SCIP_STAGE_INITSOLVE
9028  *       - \ref SCIP_STAGE_SOLVING
9029  *       - \ref SCIP_STAGE_SOLVED
9030  */
SCIPgetVarPseudocostScore(SCIP * scip,SCIP_VAR * var,SCIP_Real solval)9031 SCIP_Real SCIPgetVarPseudocostScore(
9032    SCIP*                 scip,               /**< SCIP data structure */
9033    SCIP_VAR*             var,                /**< problem variable */
9034    SCIP_Real             solval              /**< variable's LP solution value */
9035    )
9036 {
9037    SCIP_Real downsol;
9038    SCIP_Real upsol;
9039    SCIP_Real pscostdown;
9040    SCIP_Real pscostup;
9041 
9042    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9043 
9044    assert( var->scip == scip );
9045 
9046    downsol = SCIPsetFeasCeil(scip->set, solval-1.0);
9047    upsol = SCIPsetFeasFloor(scip->set, solval+1.0);
9048    pscostdown = SCIPvarGetPseudocost(var, scip->stat, downsol-solval);
9049    pscostup = SCIPvarGetPseudocost(var, scip->stat, upsol-solval);
9050 
9051    return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup);
9052 }
9053 
9054 /** gets the variable's pseudo cost score value for the given LP solution value,
9055  *  only using the pseudo cost information of the current run
9056  *
9057  *  @return the variable's pseudo cost score value for the given LP solution value,
9058  *  only using the pseudo cost information of the current run
9059  *
9060  *  @pre This method can be called if @p scip is in one of the following stages:
9061  *       - \ref SCIP_STAGE_INITPRESOLVE
9062  *       - \ref SCIP_STAGE_PRESOLVING
9063  *       - \ref SCIP_STAGE_EXITPRESOLVE
9064  *       - \ref SCIP_STAGE_PRESOLVED
9065  *       - \ref SCIP_STAGE_INITSOLVE
9066  *       - \ref SCIP_STAGE_SOLVING
9067  *       - \ref SCIP_STAGE_SOLVED
9068  */
SCIPgetVarPseudocostScoreCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_Real solval)9069 SCIP_Real SCIPgetVarPseudocostScoreCurrentRun(
9070    SCIP*                 scip,               /**< SCIP data structure */
9071    SCIP_VAR*             var,                /**< problem variable */
9072    SCIP_Real             solval              /**< variable's LP solution value */
9073    )
9074 {
9075    SCIP_Real downsol;
9076    SCIP_Real upsol;
9077    SCIP_Real pscostdown;
9078    SCIP_Real pscostup;
9079 
9080    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9081 
9082    assert( var->scip == scip );
9083 
9084    downsol = SCIPsetFeasCeil(scip->set, solval-1.0);
9085    upsol = SCIPsetFeasFloor(scip->set, solval+1.0);
9086    pscostdown = SCIPvarGetPseudocostCurrentRun(var, scip->stat, downsol-solval);
9087    pscostup = SCIPvarGetPseudocostCurrentRun(var, scip->stat, upsol-solval);
9088 
9089    return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup);
9090 }
9091 
9092 /** returns the variable's VSIDS value
9093  *
9094  *  @return the variable's VSIDS value
9095  *
9096  *  @pre This method can be called if @p scip is in one of the following stages:
9097  *       - \ref SCIP_STAGE_INITPRESOLVE
9098  *       - \ref SCIP_STAGE_PRESOLVING
9099  *       - \ref SCIP_STAGE_EXITPRESOLVE
9100  *       - \ref SCIP_STAGE_PRESOLVED
9101  *       - \ref SCIP_STAGE_INITSOLVE
9102  *       - \ref SCIP_STAGE_SOLVING
9103  *       - \ref SCIP_STAGE_SOLVED
9104  */
SCIPgetVarVSIDS(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9105 SCIP_Real SCIPgetVarVSIDS(
9106    SCIP*                 scip,               /**< SCIP data structure */
9107    SCIP_VAR*             var,                /**< problem variable */
9108    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9109    )
9110 {
9111    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDS", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9112 
9113    assert( var->scip == scip );
9114 
9115    if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
9116    {
9117       SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
9118       return SCIP_INVALID;
9119    }
9120 
9121    return SCIPvarGetVSIDS(var, scip->stat, dir);
9122 }
9123 
9124 /** returns the variable's VSIDS value only using conflicts of the current run
9125  *
9126  *  @return the variable's VSIDS value only using conflicts of the current run
9127  *
9128  *  @pre This method can be called if @p scip is in one of the following stages:
9129  *       - \ref SCIP_STAGE_INITPRESOLVE
9130  *       - \ref SCIP_STAGE_PRESOLVING
9131  *       - \ref SCIP_STAGE_EXITPRESOLVE
9132  *       - \ref SCIP_STAGE_PRESOLVED
9133  *       - \ref SCIP_STAGE_INITSOLVE
9134  *       - \ref SCIP_STAGE_SOLVING
9135  *       - \ref SCIP_STAGE_SOLVED
9136  */
SCIPgetVarVSIDSCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9137 SCIP_Real SCIPgetVarVSIDSCurrentRun(
9138    SCIP*                 scip,               /**< SCIP data structure */
9139    SCIP_VAR*             var,                /**< problem variable */
9140    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9141    )
9142 {
9143    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDSCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9144 
9145    assert( var->scip == scip );
9146 
9147    if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
9148    {
9149       SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
9150       return SCIP_INVALID;
9151    }
9152 
9153    return SCIPvarGetVSIDSCurrentRun(var, scip->stat, dir);
9154 }
9155 
9156 /** returns the variable's conflict score value
9157  *
9158  *  @return the variable's conflict score value
9159  *
9160  *  @pre This method can be called if @p scip is in one of the following stages:
9161  *       - \ref SCIP_STAGE_INITPRESOLVE
9162  *       - \ref SCIP_STAGE_PRESOLVING
9163  *       - \ref SCIP_STAGE_EXITPRESOLVE
9164  *       - \ref SCIP_STAGE_PRESOLVED
9165  *       - \ref SCIP_STAGE_INITSOLVE
9166  *       - \ref SCIP_STAGE_SOLVING
9167  *       - \ref SCIP_STAGE_SOLVED
9168  */
SCIPgetVarConflictScore(SCIP * scip,SCIP_VAR * var)9169 SCIP_Real SCIPgetVarConflictScore(
9170    SCIP*                 scip,               /**< SCIP data structure */
9171    SCIP_VAR*             var                 /**< problem variable */
9172    )
9173 {
9174    SCIP_Real downscore;
9175    SCIP_Real upscore;
9176 
9177    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9178 
9179    assert( var->scip == scip );
9180 
9181    downscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9182    upscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9183 
9184    return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9185 }
9186 
9187 /** returns the variable's conflict score value only using conflicts of the current run
9188  *
9189  *  @return the variable's conflict score value only using conflicts of the current run
9190  *
9191  *  @pre This method can be called if @p scip is in one of the following stages:
9192  *       - \ref SCIP_STAGE_INITPRESOLVE
9193  *       - \ref SCIP_STAGE_PRESOLVING
9194  *       - \ref SCIP_STAGE_EXITPRESOLVE
9195  *       - \ref SCIP_STAGE_PRESOLVED
9196  *       - \ref SCIP_STAGE_INITSOLVE
9197  *       - \ref SCIP_STAGE_SOLVING
9198  *       - \ref SCIP_STAGE_SOLVED
9199  */
SCIPgetVarConflictScoreCurrentRun(SCIP * scip,SCIP_VAR * var)9200 SCIP_Real SCIPgetVarConflictScoreCurrentRun(
9201    SCIP*                 scip,               /**< SCIP data structure */
9202    SCIP_VAR*             var                 /**< problem variable */
9203    )
9204 {
9205    SCIP_Real downscore;
9206    SCIP_Real upscore;
9207 
9208    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9209 
9210    assert( var->scip == scip );
9211 
9212    downscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9213    upscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9214 
9215    return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9216 }
9217 
9218 /** returns the variable's conflict length score
9219  *
9220  *  @return the variable's conflict length score
9221  *
9222  *  @pre This method can be called if @p scip is in one of the following stages:
9223  *       - \ref SCIP_STAGE_INITPRESOLVE
9224  *       - \ref SCIP_STAGE_PRESOLVING
9225  *       - \ref SCIP_STAGE_EXITPRESOLVE
9226  *       - \ref SCIP_STAGE_PRESOLVED
9227  *       - \ref SCIP_STAGE_INITSOLVE
9228  *       - \ref SCIP_STAGE_SOLVING
9229  *       - \ref SCIP_STAGE_SOLVED
9230  */
SCIPgetVarConflictlengthScore(SCIP * scip,SCIP_VAR * var)9231 SCIP_Real SCIPgetVarConflictlengthScore(
9232    SCIP*                 scip,               /**< SCIP data structure */
9233    SCIP_VAR*             var                 /**< problem variable */
9234    )
9235 {
9236    SCIP_Real downscore;
9237    SCIP_Real upscore;
9238 
9239    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9240 
9241    assert( var->scip == scip );
9242 
9243    downscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_DOWNWARDS);
9244    upscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_UPWARDS);
9245 
9246    return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9247 }
9248 
9249 /** returns the variable's conflict length score only using conflicts of the current run
9250  *
9251  *  @return the variable's conflict length score only using conflicts of the current run
9252  *
9253  *  @pre This method can be called if @p scip is in one of the following stages:
9254  *       - \ref SCIP_STAGE_INITPRESOLVE
9255  *       - \ref SCIP_STAGE_PRESOLVING
9256  *       - \ref SCIP_STAGE_EXITPRESOLVE
9257  *       - \ref SCIP_STAGE_PRESOLVED
9258  *       - \ref SCIP_STAGE_INITSOLVE
9259  *       - \ref SCIP_STAGE_SOLVING
9260  *       - \ref SCIP_STAGE_SOLVED
9261  */
SCIPgetVarConflictlengthScoreCurrentRun(SCIP * scip,SCIP_VAR * var)9262 SCIP_Real SCIPgetVarConflictlengthScoreCurrentRun(
9263    SCIP*                 scip,               /**< SCIP data structure */
9264    SCIP_VAR*             var                 /**< problem variable */
9265    )
9266 {
9267    SCIP_Real downscore;
9268    SCIP_Real upscore;
9269 
9270    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9271 
9272    assert( var->scip == scip );
9273 
9274    downscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_DOWNWARDS);
9275    upscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_UPWARDS);
9276 
9277    return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9278 }
9279 
9280 /** returns the variable's average conflict length
9281  *
9282  *  @return the variable's average conflict length
9283  *
9284  *  @pre This method can be called if @p scip is in one of the following stages:
9285  *       - \ref SCIP_STAGE_INITPRESOLVE
9286  *       - \ref SCIP_STAGE_PRESOLVING
9287  *       - \ref SCIP_STAGE_EXITPRESOLVE
9288  *       - \ref SCIP_STAGE_PRESOLVED
9289  *       - \ref SCIP_STAGE_INITSOLVE
9290  *       - \ref SCIP_STAGE_SOLVING
9291  *       - \ref SCIP_STAGE_SOLVED
9292  */
SCIPgetVarAvgConflictlength(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9293 SCIP_Real SCIPgetVarAvgConflictlength(
9294    SCIP*                 scip,               /**< SCIP data structure */
9295    SCIP_VAR*             var,                /**< problem variable */
9296    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9297    )
9298 {
9299    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlength", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9300 
9301    assert( var->scip == scip );
9302 
9303    return SCIPvarGetAvgConflictlength(var, dir);
9304 }
9305 
9306 /** returns the variable's average  conflict length only using conflicts of the current run
9307  *
9308  *  @return the variable's average conflict length only using conflicts of the current run
9309  *
9310  *  @pre This method can be called if @p scip is in one of the following stages:
9311  *       - \ref SCIP_STAGE_INITPRESOLVE
9312  *       - \ref SCIP_STAGE_PRESOLVING
9313  *       - \ref SCIP_STAGE_EXITPRESOLVE
9314  *       - \ref SCIP_STAGE_PRESOLVED
9315  *       - \ref SCIP_STAGE_INITSOLVE
9316  *       - \ref SCIP_STAGE_SOLVING
9317  *       - \ref SCIP_STAGE_SOLVED
9318  */
SCIPgetVarAvgConflictlengthCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9319 SCIP_Real SCIPgetVarAvgConflictlengthCurrentRun(
9320    SCIP*                 scip,               /**< SCIP data structure */
9321    SCIP_VAR*             var,                /**< problem variable */
9322    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9323    )
9324 {
9325    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlengthCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9326 
9327    assert( var->scip == scip );
9328 
9329    return SCIPvarGetAvgConflictlengthCurrentRun(var, dir);
9330 }
9331 
9332 /** returns the average number of inferences found after branching on the variable in given direction;
9333  *  if branching on the variable in the given direction was yet evaluated, the average number of inferences
9334  *  over all variables for branching in the given direction is returned
9335  *
9336  *  @return the average number of inferences found after branching on the variable in given direction
9337  *
9338  *  @pre This method can be called if @p scip is in one of the following stages:
9339  *       - \ref SCIP_STAGE_INITPRESOLVE
9340  *       - \ref SCIP_STAGE_PRESOLVING
9341  *       - \ref SCIP_STAGE_EXITPRESOLVE
9342  *       - \ref SCIP_STAGE_PRESOLVED
9343  *       - \ref SCIP_STAGE_INITSOLVE
9344  *       - \ref SCIP_STAGE_SOLVING
9345  *       - \ref SCIP_STAGE_SOLVED
9346  */
SCIPgetVarAvgInferences(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9347 SCIP_Real SCIPgetVarAvgInferences(
9348    SCIP*                 scip,               /**< SCIP data structure */
9349    SCIP_VAR*             var,                /**< problem variable */
9350    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9351    )
9352 {
9353    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferences", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9354 
9355    assert( var->scip == scip );
9356 
9357    return SCIPvarGetAvgInferences(var, scip->stat, dir);
9358 }
9359 
9360 /** returns the average number of inferences found after branching on the variable in given direction in the current run;
9361  *  if branching on the variable in the given direction was yet evaluated, the average number of inferences
9362  *  over all variables for branching in the given direction is returned
9363  *
9364  *  @return the average number of inferences found after branching on the variable in given direction in the current run
9365  *
9366  *  @pre This method can be called if @p scip is in one of the following stages:
9367  *       - \ref SCIP_STAGE_INITPRESOLVE
9368  *       - \ref SCIP_STAGE_PRESOLVING
9369  *       - \ref SCIP_STAGE_EXITPRESOLVE
9370  *       - \ref SCIP_STAGE_PRESOLVED
9371  *       - \ref SCIP_STAGE_INITSOLVE
9372  *       - \ref SCIP_STAGE_SOLVING
9373  *       - \ref SCIP_STAGE_SOLVED
9374  */
SCIPgetVarAvgInferencesCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9375 SCIP_Real SCIPgetVarAvgInferencesCurrentRun(
9376    SCIP*                 scip,               /**< SCIP data structure */
9377    SCIP_VAR*             var,                /**< problem variable */
9378    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9379    )
9380 {
9381    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferencesCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9382 
9383    assert( var->scip == scip );
9384 
9385    return SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, dir);
9386 }
9387 
9388 /** returns the variable's average inference score value
9389  *
9390  *  @return the variable's average inference score value
9391  *
9392  *  @pre This method can be called if @p scip is in one of the following stages:
9393  *       - \ref SCIP_STAGE_INITPRESOLVE
9394  *       - \ref SCIP_STAGE_PRESOLVING
9395  *       - \ref SCIP_STAGE_EXITPRESOLVE
9396  *       - \ref SCIP_STAGE_PRESOLVED
9397  *       - \ref SCIP_STAGE_INITSOLVE
9398  *       - \ref SCIP_STAGE_SOLVING
9399  *       - \ref SCIP_STAGE_SOLVED
9400  */
SCIPgetVarAvgInferenceScore(SCIP * scip,SCIP_VAR * var)9401 SCIP_Real SCIPgetVarAvgInferenceScore(
9402    SCIP*                 scip,               /**< SCIP data structure */
9403    SCIP_VAR*             var                 /**< problem variable */
9404    )
9405 {
9406    SCIP_Real inferdown;
9407    SCIP_Real inferup;
9408 
9409    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9410 
9411    assert( var->scip == scip );
9412 
9413    inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9414    inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9415 
9416    return SCIPbranchGetScore(scip->set, var, inferdown, inferup);
9417 }
9418 
9419 /** returns the variable's average inference score value only using inferences of the current run
9420  *
9421  *  @return the variable's average inference score value only using inferences of the current run
9422  *
9423  *  @pre This method can be called if @p scip is in one of the following stages:
9424  *       - \ref SCIP_STAGE_INITPRESOLVE
9425  *       - \ref SCIP_STAGE_PRESOLVING
9426  *       - \ref SCIP_STAGE_EXITPRESOLVE
9427  *       - \ref SCIP_STAGE_PRESOLVED
9428  *       - \ref SCIP_STAGE_INITSOLVE
9429  *       - \ref SCIP_STAGE_SOLVING
9430  *       - \ref SCIP_STAGE_SOLVED
9431  */
SCIPgetVarAvgInferenceScoreCurrentRun(SCIP * scip,SCIP_VAR * var)9432 SCIP_Real SCIPgetVarAvgInferenceScoreCurrentRun(
9433    SCIP*                 scip,               /**< SCIP data structure */
9434    SCIP_VAR*             var                 /**< problem variable */
9435    )
9436 {
9437    SCIP_Real inferdown;
9438    SCIP_Real inferup;
9439 
9440    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9441 
9442    assert( var->scip == scip );
9443 
9444    inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9445    inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9446 
9447    return SCIPbranchGetScore(scip->set, var, inferdown, inferup);
9448 }
9449 
9450 /** initializes the upwards and downwards pseudocosts, conflict scores, conflict lengths, inference scores, cutoff scores
9451  *  of a variable to the given values
9452  *
9453  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9454  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9455  *
9456  *  @pre This method can be called if @p scip is in one of the following stages:
9457  *       - \ref SCIP_STAGE_TRANSFORMED
9458  *       - \ref SCIP_STAGE_INITPRESOLVE
9459  *       - \ref SCIP_STAGE_PRESOLVING
9460  *       - \ref SCIP_STAGE_EXITPRESOLVE
9461  *       - \ref SCIP_STAGE_PRESOLVED
9462  *       - \ref SCIP_STAGE_INITSOLVE
9463  *       - \ref SCIP_STAGE_SOLVING
9464  */
SCIPinitVarBranchStats(SCIP * scip,SCIP_VAR * var,SCIP_Real downpscost,SCIP_Real uppscost,SCIP_Real downvsids,SCIP_Real upvsids,SCIP_Real downconflen,SCIP_Real upconflen,SCIP_Real downinfer,SCIP_Real upinfer,SCIP_Real downcutoff,SCIP_Real upcutoff)9465 SCIP_RETCODE SCIPinitVarBranchStats(
9466    SCIP*                 scip,               /**< SCIP data structure */
9467    SCIP_VAR*             var,                /**< variable which should be initialized */
9468    SCIP_Real             downpscost,         /**< value to which pseudocosts for downwards branching should be initialized */
9469    SCIP_Real             uppscost,           /**< value to which pseudocosts for upwards branching should be initialized */
9470    SCIP_Real             downvsids,          /**< value to which VSIDS score for downwards branching should be initialized */
9471    SCIP_Real             upvsids,            /**< value to which VSIDS score for upwards branching should be initialized */
9472    SCIP_Real             downconflen,        /**< value to which conflict length score for downwards branching should be initialized */
9473    SCIP_Real             upconflen,          /**< value to which conflict length score for upwards branching should be initialized */
9474    SCIP_Real             downinfer,          /**< value to which inference counter for downwards branching should be initialized */
9475    SCIP_Real             upinfer,            /**< value to which inference counter for upwards branching should be initialized */
9476    SCIP_Real             downcutoff,         /**< value to which cutoff counter for downwards branching should be initialized */
9477    SCIP_Real             upcutoff            /**< value to which cutoff counter for upwards branching should be initialized */
9478    )
9479 {
9480    SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
9481 
9482    assert(downpscost >= 0.0 && uppscost >= 0.0);
9483    assert(downvsids >= 0.0 && upvsids >= 0.0);
9484    assert(downconflen >= 0.0 && upconflen >= 0.0);
9485    assert(downinfer >= 0.0 && upinfer >= 0.0);
9486    assert(downcutoff >= 0.0 && upcutoff >= 0.0);
9487 
9488    if( !SCIPisFeasZero(scip, downpscost) || !SCIPisFeasZero(scip, downvsids)
9489       || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) )
9490    {
9491       SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, 1) );
9492       SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, -1.0, downpscost, 1.0) );
9493       SCIP_CALL( SCIPvarIncInferenceSum(var,  NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downinfer) );
9494       SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downvsids) );
9495       SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downcutoff) );
9496    }
9497 
9498    if( !SCIPisFeasZero(scip, downconflen) )
9499    {
9500       SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downconflen) );
9501    }
9502 
9503    if( !SCIPisFeasZero(scip, uppscost) || !SCIPisFeasZero(scip, upvsids)
9504       || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) )
9505    {
9506       SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, 1) );
9507       SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, 1.0, uppscost, 1.0) );
9508       SCIP_CALL( SCIPvarIncInferenceSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upinfer) );
9509       SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upvsids) );
9510       SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upcutoff) );
9511    }
9512 
9513    if( !SCIPisFeasZero(scip, upconflen) )
9514    {
9515       SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upconflen) );
9516    }
9517 
9518    return SCIP_OKAY;
9519 }
9520 
9521 /** initializes the upwards and downwards conflict scores, conflict lengths, inference scores, cutoff scores of a
9522  *  variable w.r.t. a value by the given values (SCIP_VALUEHISTORY)
9523  *
9524  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9525  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9526  *
9527  *  @pre This method can be called if @p scip is in one of the following stages:
9528  *       - \ref SCIP_STAGE_TRANSFORMED
9529  *       - \ref SCIP_STAGE_INITPRESOLVE
9530  *       - \ref SCIP_STAGE_PRESOLVING
9531  *       - \ref SCIP_STAGE_EXITPRESOLVE
9532  *       - \ref SCIP_STAGE_PRESOLVED
9533  *       - \ref SCIP_STAGE_INITSOLVE
9534  *       - \ref SCIP_STAGE_SOLVING
9535  */
SCIPinitVarValueBranchStats(SCIP * scip,SCIP_VAR * var,SCIP_Real value,SCIP_Real downvsids,SCIP_Real upvsids,SCIP_Real downconflen,SCIP_Real upconflen,SCIP_Real downinfer,SCIP_Real upinfer,SCIP_Real downcutoff,SCIP_Real upcutoff)9536 SCIP_RETCODE SCIPinitVarValueBranchStats(
9537    SCIP*                 scip,               /**< SCIP data structure */
9538    SCIP_VAR*             var,                /**< variable which should be initialized */
9539    SCIP_Real             value,              /**< domain value, or SCIP_UNKNOWN */
9540    SCIP_Real             downvsids,          /**< value to which VSIDS score for downwards branching should be initialized */
9541    SCIP_Real             upvsids,            /**< value to which VSIDS score for upwards branching should be initialized */
9542    SCIP_Real             downconflen,        /**< value to which conflict length score for downwards branching should be initialized */
9543    SCIP_Real             upconflen,          /**< value to which conflict length score for upwards branching should be initialized */
9544    SCIP_Real             downinfer,          /**< value to which inference counter for downwards branching should be initialized */
9545    SCIP_Real             upinfer,            /**< value to which inference counter for upwards branching should be initialized */
9546    SCIP_Real             downcutoff,         /**< value to which cutoff counter for downwards branching should be initialized */
9547    SCIP_Real             upcutoff            /**< value to which cutoff counter for upwards branching should be initialized */
9548    )
9549 {
9550    SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarValueBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
9551 
9552    assert(downvsids >= 0.0 && upvsids >= 0.0);
9553    assert(downconflen >= 0.0 && upconflen >= 0.0);
9554    assert(downinfer >= 0.0 && upinfer >= 0.0);
9555    assert(downcutoff >= 0.0 && upcutoff >= 0.0);
9556 
9557    if( !SCIPisFeasZero(scip, downvsids) || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) )
9558    {
9559       SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, 1) );
9560       SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downinfer) );
9561       SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downvsids) );
9562       SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downcutoff) );
9563    }
9564 
9565    if( !SCIPisFeasZero(scip, downconflen) )
9566    {
9567       SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downconflen) );
9568    }
9569 
9570    if( !SCIPisFeasZero(scip, upvsids) || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) )
9571    {
9572       SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, 1) );
9573       SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upinfer) );
9574       SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upvsids) );
9575       SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upcutoff) );
9576    }
9577 
9578    if( !SCIPisFeasZero(scip, upconflen) )
9579    {
9580       SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upconflen) );
9581    }
9582 
9583    return SCIP_OKAY;
9584 }
9585 
9586 /** returns the average number of cutoffs found after branching on the variable in given direction;
9587  *  if branching on the variable in the given direction was yet evaluated, the average number of cutoffs
9588  *  over all variables for branching in the given direction is returned
9589  *
9590  *  @return the average number of cutoffs found after branching on the variable in given direction
9591  *
9592  *  @pre This method can be called if @p scip is in one of the following stages:
9593  *       - \ref SCIP_STAGE_INITPRESOLVE
9594  *       - \ref SCIP_STAGE_PRESOLVING
9595  *       - \ref SCIP_STAGE_EXITPRESOLVE
9596  *       - \ref SCIP_STAGE_PRESOLVED
9597  *       - \ref SCIP_STAGE_INITSOLVE
9598  *       - \ref SCIP_STAGE_SOLVING
9599  *       - \ref SCIP_STAGE_SOLVED
9600  */
SCIPgetVarAvgCutoffs(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9601 SCIP_Real SCIPgetVarAvgCutoffs(
9602    SCIP*                 scip,               /**< SCIP data structure */
9603    SCIP_VAR*             var,                /**< problem variable */
9604    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9605    )
9606 {
9607    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffs", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9608 
9609    assert( var->scip == scip );
9610 
9611    return SCIPvarGetAvgCutoffs(var, scip->stat, dir);
9612 }
9613 
9614 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run;
9615  *  if branching on the variable in the given direction was yet evaluated, the average number of cutoffs
9616  *  over all variables for branching in the given direction is returned
9617  *
9618  *  @return the average number of cutoffs found after branching on the variable in given direction in the current run
9619  *
9620  *  @pre This method can be called if @p scip is in one of the following stages:
9621  *       - \ref SCIP_STAGE_INITPRESOLVE
9622  *       - \ref SCIP_STAGE_PRESOLVING
9623  *       - \ref SCIP_STAGE_EXITPRESOLVE
9624  *       - \ref SCIP_STAGE_PRESOLVED
9625  *       - \ref SCIP_STAGE_INITSOLVE
9626  *       - \ref SCIP_STAGE_SOLVING
9627  *       - \ref SCIP_STAGE_SOLVED
9628  */
SCIPgetVarAvgCutoffsCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_BRANCHDIR dir)9629 SCIP_Real SCIPgetVarAvgCutoffsCurrentRun(
9630    SCIP*                 scip,               /**< SCIP data structure */
9631    SCIP_VAR*             var,                /**< problem variable */
9632    SCIP_BRANCHDIR        dir                 /**< branching direction (downwards, or upwards) */
9633    )
9634 {
9635    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffsCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9636 
9637    assert( var->scip == scip );
9638 
9639    return SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, dir);
9640 }
9641 
9642 /** returns the variable's average cutoff score value
9643  *
9644  *  @return the variable's average cutoff score value
9645  *
9646  *  @pre This method can be called if @p scip is in one of the following stages:
9647  *       - \ref SCIP_STAGE_INITPRESOLVE
9648  *       - \ref SCIP_STAGE_PRESOLVING
9649  *       - \ref SCIP_STAGE_EXITPRESOLVE
9650  *       - \ref SCIP_STAGE_PRESOLVED
9651  *       - \ref SCIP_STAGE_INITSOLVE
9652  *       - \ref SCIP_STAGE_SOLVING
9653  *       - \ref SCIP_STAGE_SOLVED
9654  */
SCIPgetVarAvgCutoffScore(SCIP * scip,SCIP_VAR * var)9655 SCIP_Real SCIPgetVarAvgCutoffScore(
9656    SCIP*                 scip,               /**< SCIP data structure */
9657    SCIP_VAR*             var                 /**< problem variable */
9658    )
9659 {
9660    SCIP_Real cutoffdown;
9661    SCIP_Real cutoffup;
9662 
9663    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9664 
9665    assert( var->scip == scip );
9666 
9667    cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9668    cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9669 
9670    return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup);
9671 }
9672 
9673 /** returns the variable's average cutoff score value, only using cutoffs of the current run
9674  *
9675  *  @return the variable's average cutoff score value, only using cutoffs of the current run
9676  *
9677  *  @pre This method can be called if @p scip is in one of the following stages:
9678  *       - \ref SCIP_STAGE_INITPRESOLVE
9679  *       - \ref SCIP_STAGE_PRESOLVING
9680  *       - \ref SCIP_STAGE_EXITPRESOLVE
9681  *       - \ref SCIP_STAGE_PRESOLVED
9682  *       - \ref SCIP_STAGE_INITSOLVE
9683  *       - \ref SCIP_STAGE_SOLVING
9684  *       - \ref SCIP_STAGE_SOLVED
9685  */
SCIPgetVarAvgCutoffScoreCurrentRun(SCIP * scip,SCIP_VAR * var)9686 SCIP_Real SCIPgetVarAvgCutoffScoreCurrentRun(
9687    SCIP*                 scip,               /**< SCIP data structure */
9688    SCIP_VAR*             var                 /**< problem variable */
9689    )
9690 {
9691    SCIP_Real cutoffdown;
9692    SCIP_Real cutoffup;
9693 
9694    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9695 
9696    assert( var->scip == scip );
9697 
9698    cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9699    cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9700 
9701    return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup);
9702 }
9703 
9704 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given
9705  *  factor
9706  *
9707  *  @return the variable's average inference/cutoff score value
9708  *
9709  *  @pre This method can be called if @p scip is in one of the following stages:
9710  *       - \ref SCIP_STAGE_INITPRESOLVE
9711  *       - \ref SCIP_STAGE_PRESOLVING
9712  *       - \ref SCIP_STAGE_EXITPRESOLVE
9713  *       - \ref SCIP_STAGE_PRESOLVED
9714  *       - \ref SCIP_STAGE_INITSOLVE
9715  *       - \ref SCIP_STAGE_SOLVING
9716  *       - \ref SCIP_STAGE_SOLVED
9717  */
SCIPgetVarAvgInferenceCutoffScore(SCIP * scip,SCIP_VAR * var,SCIP_Real cutoffweight)9718 SCIP_Real SCIPgetVarAvgInferenceCutoffScore(
9719    SCIP*                 scip,               /**< SCIP data structure */
9720    SCIP_VAR*             var,                /**< problem variable */
9721    SCIP_Real             cutoffweight        /**< factor to weigh average number of cutoffs in branching score */
9722    )
9723 {
9724    SCIP_Real avginferdown;
9725    SCIP_Real avginferup;
9726    SCIP_Real avginfer;
9727    SCIP_Real inferdown;
9728    SCIP_Real inferup;
9729    SCIP_Real cutoffdown;
9730    SCIP_Real cutoffup;
9731 
9732    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9733 
9734    assert( var->scip == scip );
9735 
9736    avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_DOWNWARDS);
9737    avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_UPWARDS);
9738    avginfer = (avginferdown + avginferup)/2.0;
9739    inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9740    inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9741    cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9742    cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9743 
9744    return SCIPbranchGetScore(scip->set, var,
9745       inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup);
9746 }
9747 
9748 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given
9749  *  factor, only using inferences and cutoffs of the current run
9750  *
9751  *  @return the variable's average inference/cutoff score value, only using inferences and cutoffs of the current run
9752  *
9753  *  @pre This method can be called if @p scip is in one of the following stages:
9754  *       - \ref SCIP_STAGE_INITPRESOLVE
9755  *       - \ref SCIP_STAGE_PRESOLVING
9756  *       - \ref SCIP_STAGE_EXITPRESOLVE
9757  *       - \ref SCIP_STAGE_PRESOLVED
9758  *       - \ref SCIP_STAGE_INITSOLVE
9759  *       - \ref SCIP_STAGE_SOLVING
9760  *       - \ref SCIP_STAGE_SOLVED
9761  */
SCIPgetVarAvgInferenceCutoffScoreCurrentRun(SCIP * scip,SCIP_VAR * var,SCIP_Real cutoffweight)9762 SCIP_Real SCIPgetVarAvgInferenceCutoffScoreCurrentRun(
9763    SCIP*                 scip,               /**< SCIP data structure */
9764    SCIP_VAR*             var,                /**< problem variable */
9765    SCIP_Real             cutoffweight        /**< factor to weigh average number of cutoffs in branching score */
9766    )
9767 {
9768    SCIP_Real avginferdown;
9769    SCIP_Real avginferup;
9770    SCIP_Real avginfer;
9771    SCIP_Real inferdown;
9772    SCIP_Real inferup;
9773    SCIP_Real cutoffdown;
9774    SCIP_Real cutoffup;
9775 
9776    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9777 
9778    assert( var->scip == scip );
9779 
9780    avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_DOWNWARDS);
9781    avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_UPWARDS);
9782    avginfer = (avginferdown + avginferup)/2.0;
9783    inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9784    inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9785    cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9786    cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9787 
9788    return SCIPbranchGetScore(scip->set, var,
9789       inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup);
9790 }
9791 
9792 /** outputs variable information to file stream via the message system
9793  *
9794  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9795  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9796  *
9797  *  @pre This method can be called if @p scip is in one of the following stages:
9798  *       - \ref SCIP_STAGE_PROBLEM
9799  *       - \ref SCIP_STAGE_TRANSFORMING
9800  *       - \ref SCIP_STAGE_TRANSFORMED
9801  *       - \ref SCIP_STAGE_INITPRESOLVE
9802  *       - \ref SCIP_STAGE_PRESOLVING
9803  *       - \ref SCIP_STAGE_EXITPRESOLVE
9804  *       - \ref SCIP_STAGE_PRESOLVED
9805  *       - \ref SCIP_STAGE_INITSOLVE
9806  *       - \ref SCIP_STAGE_SOLVING
9807  *       - \ref SCIP_STAGE_SOLVED
9808  *       - \ref SCIP_STAGE_EXITSOLVE
9809  *       - \ref SCIP_STAGE_FREETRANS
9810  *
9811  *  @note If the message handler is set to a NULL pointer nothing will be printed
9812  */
SCIPprintVar(SCIP * scip,SCIP_VAR * var,FILE * file)9813 SCIP_RETCODE SCIPprintVar(
9814    SCIP*                 scip,               /**< SCIP data structure */
9815    SCIP_VAR*             var,                /**< problem variable */
9816    FILE*                 file                /**< output file (or NULL for standard output) */
9817    )
9818 {
9819    SCIP_CALL( SCIPcheckStage(scip, "SCIPprintVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
9820 
9821    SCIP_CALL( SCIPvarPrint(var, scip->set, scip->messagehdlr, file) );
9822 
9823    return SCIP_OKAY;
9824 }
9825