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 */
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 */
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 */
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 */
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 */
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 terms as signomial 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 */
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 */
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 */
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 */
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 */
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 signomial 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.
793 *
794 * Parsing is stopped at the end of string (indicated by the \\0-character) or when no more monomials
795 * are recognized.
796 *
797 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
798 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
799 *
800 * @pre This method can be called if @p scip is in one of the following stages:
801 * - \ref SCIP_STAGE_PROBLEM
802 * - \ref SCIP_STAGE_TRANSFORMING
803 * - \ref SCIP_STAGE_INITPRESOLVE
804 * - \ref SCIP_STAGE_PRESOLVING
805 * - \ref SCIP_STAGE_EXITPRESOLVE
806 * - \ref SCIP_STAGE_PRESOLVED
807 * - \ref SCIP_STAGE_SOLVING
808 */
809 SCIP_RETCODE SCIPparseVarsPolynomial(
810 SCIP* scip, /**< SCIP data structure */
811 const char* str, /**< string to parse */
812 SCIP_VAR**** monomialvars, /**< pointer to store arrays with variables for each monomial */
813 SCIP_Real*** monomialexps, /**< pointer to store arrays with variable exponents */
814 SCIP_Real** monomialcoefs, /**< pointer to store array with monomial coefficients */
815 int** monomialnvars, /**< pointer to store array with number of variables for each monomial */
816 int* nmonomials, /**< pointer to store number of parsed monomials */
817 char** endptr, /**< pointer to store the final string position if successful */
818 SCIP_Bool* success /**< pointer to store the whether the parsing was successful or not */
819 )
820 {
821 typedef enum
822 {
823 SCIPPARSEPOLYNOMIAL_STATE_BEGIN, /* we are at the beginning of a monomial */
824 SCIPPARSEPOLYNOMIAL_STATE_INTERMED, /* we are in between the factors of a monomial */
825 SCIPPARSEPOLYNOMIAL_STATE_COEF, /* we parse the coefficient of a monomial */
826 SCIPPARSEPOLYNOMIAL_STATE_VARS, /* we parse monomial variables */
827 SCIPPARSEPOLYNOMIAL_STATE_EXPONENT, /* we parse the exponent of a variable */
828 SCIPPARSEPOLYNOMIAL_STATE_END, /* we are at the end the polynomial */
829 SCIPPARSEPOLYNOMIAL_STATE_ERROR /* a parsing error occured */
830 } SCIPPARSEPOLYNOMIAL_STATES;
831
832 SCIPPARSEPOLYNOMIAL_STATES state;
833 int monomialssize;
834
835 /* data of currently parsed monomial */
836 int varssize;
837 int nvars;
838 SCIP_VAR** vars;
839 SCIP_Real* exponents;
840 SCIP_Real coef;
841
842 assert(scip != NULL);
843 assert(str != NULL);
844 assert(monomialvars != NULL);
845 assert(monomialexps != NULL);
846 assert(monomialnvars != NULL);
847 assert(monomialcoefs != NULL);
848 assert(nmonomials != NULL);
849 assert(endptr != NULL);
850 assert(success != NULL);
851
852 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsPolynomial", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
853
854 *success = FALSE;
855 *nmonomials = 0;
856 monomialssize = 0;
857 *monomialvars = NULL;
858 *monomialexps = NULL;
859 *monomialcoefs = NULL;
860 *monomialnvars = NULL;
861
862 /* initialize state machine */
863 state = SCIPPARSEPOLYNOMIAL_STATE_BEGIN;
864 varssize = 0;
865 nvars = 0;
866 vars = NULL;
867 exponents = NULL;
868 coef = SCIP_INVALID;
869
870 SCIPdebugMsg(scip, "parsing polynomial from '%s'\n", str);
871
872 while( *str && state != SCIPPARSEPOLYNOMIAL_STATE_END && state != SCIPPARSEPOLYNOMIAL_STATE_ERROR )
873 {
874 /* skip white space */
875 while( isspace((unsigned char)*str) )
876 str++;
877
878 assert(state != SCIPPARSEPOLYNOMIAL_STATE_END);
879
880 switch( state )
881 {
882 case SCIPPARSEPOLYNOMIAL_STATE_BEGIN:
883 {
884 if( coef != SCIP_INVALID ) /*lint !e777*/
885 {
886 SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars);
887
888 /* push previous monomial */
889 if( monomialssize <= *nmonomials )
890 {
891 monomialssize = SCIPcalcMemGrowSize(scip, *nmonomials+1);
892
893 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, *nmonomials, monomialssize) );
894 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, *nmonomials, monomialssize) );
895 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, *nmonomials, monomialssize) );
896 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, *nmonomials, monomialssize) );
897 }
898
899 if( nvars > 0 )
900 {
901 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*monomialvars)[*nmonomials], vars, nvars) ); /*lint !e866*/
902 SCIP_CALL( SCIPduplicateBlockMemoryArray(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( SCIPreallocBlockMemoryArray(scip, &vars, nvars, varssize) );
1010 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &exponents, nvars, 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( SCIPreallocBlockMemoryArray(scip, monomialvars, *nmonomials, monomialssize) );
1075 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, *nmonomials, monomialssize) );
1076 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, *nmonomials, monomialssize) );
1077 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, *nmonomials, monomialssize) );
1078 }
1079
1080 if( nvars > 0 )
1081 {
1082 /* shrink vars and exponents array to needed size and take over ownership */
1083 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vars, varssize, nvars) );
1084 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &exponents, varssize, 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 SCIPfreeBlockMemoryArrayNull(scip, &vars, varssize);
1118 SCIPfreeBlockMemoryArrayNull(scip, &exponents, varssize);
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( SCIPreallocBlockMemoryArray(scip, monomialvars, monomialssize, *nmonomials) );
1125 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, monomialssize, *nmonomials) );
1126 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, monomialssize, *nmonomials) );
1127 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, monomialssize, *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 signomial 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 */
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 SCIPfreeBlockMemoryArrayNull(scip, &(*monomialexps)[i], (*monomialnvars)[i]);
1184 SCIPfreeBlockMemoryArrayNull(scip, &(*monomialvars)[i], (*monomialnvars)[i]);
1185 }
1186
1187 SCIPfreeBlockMemoryArray(scip, monomialcoefs, nmonomials);
1188 SCIPfreeBlockMemoryArray(scip, monomialnvars, nmonomials);
1189 SCIPfreeBlockMemoryArray(scip, monomialexps, nmonomials);
1190 SCIPfreeBlockMemoryArray(scip, monomialvars, nmonomials);
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 */
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 */
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 && (*var)->data.original.transvar != NULL )
1274 {
1275 SCIPerrorMessage("cannot release last use of original variable while associated transformed variable 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
|
(1) Event cond_false: |
Condition "(_restat_ = SCIP_OKAY) != SCIP_OKAY", taking false branch. |
|
(2) Event if_end: |
End of if statement. |
1764 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarLinearSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
|
(3) Event deref_parm_in_call: |
Function "SCIPvarGetActiveRepresentatives" dereferences "vars". [details] |
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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
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 */
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 */
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 */
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 */
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) */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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_TRANSFORMED
4340 * - \ref SCIP_STAGE_INITPRESOLVE
4341 * - \ref SCIP_STAGE_PRESOLVING
4342 * - \ref SCIP_STAGE_EXITPRESOLVE
4343 * - \ref SCIP_STAGE_INITSOLVE
4344 * - \ref SCIP_STAGE_SOLVING
4345 * - \ref SCIP_STAGE_EXITSOLVE
4346 * - \ref SCIP_STAGE_FREETRANS
4347 */
4348 SCIP_RETCODE SCIPlockVarCons(
4349 SCIP* scip, /**< SCIP data structure */
4350 SCIP_VAR* var, /**< problem variable */
4351 SCIP_CONS* cons, /**< constraint */
4352 SCIP_Bool lockdown, /**< should the rounding be locked in downwards direction? */
4353 SCIP_Bool lockup /**< should the rounding be locked in upwards direction? */
4354 )
4355 {
4356 int nlocksdown[NLOCKTYPES];
4357 int nlocksup[NLOCKTYPES];
4358 int i;
4359
4360 SCIP_CALL( SCIPcheckStage(scip, "SCIPlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4361
4362 assert( var->scip == scip );
4363
4364 for( i = 0; i < NLOCKTYPES; i++ )
4365 {
4366 nlocksdown[i] = 0;
4367 nlocksup[i] = 0;
4368
4369 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4370 {
4371 if( lockdown )
4372 ++nlocksdown[i];
4373 if( lockup )
4374 ++nlocksup[i];
4375 }
4376 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4377 {
4378 if( lockdown )
4379 ++nlocksup[i];
4380 if( lockup )
4381 ++nlocksdown[i];
4382 }
4383 }
4384
4385 switch( scip->set->stage )
4386 {
4387 case SCIP_STAGE_PROBLEM:
4388 assert(!SCIPvarIsTransformed(var));
4389 /*lint -fallthrough*/
4390 case SCIP_STAGE_TRANSFORMING:
4391 case SCIP_STAGE_TRANSFORMED:
4392 case SCIP_STAGE_INITPRESOLVE:
4393 case SCIP_STAGE_PRESOLVING:
4394 case SCIP_STAGE_EXITPRESOLVE:
4395 case SCIP_STAGE_INITSOLVE:
4396 case SCIP_STAGE_SOLVING:
4397 case SCIP_STAGE_EXITSOLVE:
4398 case SCIP_STAGE_FREETRANS:
4399 for( i = 0; i < NLOCKTYPES; i++ )
4400 {
4401 if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4402 continue;
4403
4404 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4405 }
4406 return SCIP_OKAY;
4407
4408 default:
4409 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4410 return SCIP_INVALIDCALL;
4411 } /*lint !e788*/
4412 }
4413
4414 /** remove locks of type @p locktype of variable with respect to the lock status of the constraint and its negation;
4415 * this method should be called whenever the lock status of a variable in a constraint changes, for example if
4416 * the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were
4417 * added or removed
4418 *
4419 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4420 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4421 *
4422 * @pre This method can be called if @p scip is in one of the following stages:
4423 * - \ref SCIP_STAGE_PROBLEM
4424 * - \ref SCIP_STAGE_TRANSFORMING
4425 * - \ref SCIP_STAGE_TRANSFORMED
4426 * - \ref SCIP_STAGE_INITPRESOLVE
4427 * - \ref SCIP_STAGE_PRESOLVING
4428 * - \ref SCIP_STAGE_EXITPRESOLVE
4429 * - \ref SCIP_STAGE_INITSOLVE
4430 * - \ref SCIP_STAGE_SOLVING
4431 * - \ref SCIP_STAGE_EXITSOLVE
4432 * - \ref SCIP_STAGE_FREETRANS
4433 */
4434 SCIP_RETCODE SCIPunlockVarCons(
4435 SCIP* scip, /**< SCIP data structure */
4436 SCIP_VAR* var, /**< problem variable */
4437 SCIP_CONS* cons, /**< constraint */
4438 SCIP_Bool lockdown, /**< should the rounding be unlocked in downwards direction? */
4439 SCIP_Bool lockup /**< should the rounding be unlocked in upwards direction? */
4440 )
4441 {
4442 int nlocksdown[NLOCKTYPES];
4443 int nlocksup[NLOCKTYPES];
4444 int i;
4445
4446 SCIP_CALL( SCIPcheckStage(scip, "SCIPunlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4447
4448 assert( var->scip == scip );
4449
4450 for( i = 0; i < NLOCKTYPES; i++ )
4451 {
4452 nlocksdown[i] = 0;
4453 nlocksup[i] = 0;
4454
4455 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4456 {
4457 if( lockdown )
4458 ++nlocksdown[i];
4459 if( lockup )
4460 ++nlocksup[i];
4461 }
4462 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4463 {
4464 if( lockdown )
4465 ++nlocksup[i];
4466 if( lockup )
4467 ++nlocksdown[i];
4468 }
4469 }
4470 switch( scip->set->stage )
4471 {
4472 case SCIP_STAGE_PROBLEM:
4473 assert(!SCIPvarIsTransformed(var));
4474 /*lint -fallthrough*/
4475 case SCIP_STAGE_TRANSFORMING:
4476 case SCIP_STAGE_TRANSFORMED:
4477 case SCIP_STAGE_INITPRESOLVE:
4478 case SCIP_STAGE_PRESOLVING:
4479 case SCIP_STAGE_EXITPRESOLVE:
4480 case SCIP_STAGE_INITSOLVE:
4481 case SCIP_STAGE_SOLVING:
4482 case SCIP_STAGE_EXITSOLVE:
4483 case SCIP_STAGE_FREETRANS:
4484 for( i = 0; i < NLOCKTYPES; i++ )
4485 {
4486 if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4487 continue;
4488
4489 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4490 }
4491 return SCIP_OKAY;
4492
4493 default:
4494 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4495 return SCIP_INVALIDCALL;
4496 } /*lint !e788*/
4497 }
4498
4499 /** changes variable's objective value
4500 *
4501 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4502 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4503 *
4504 * @pre This method can be called if @p scip is in one of the following stages:
4505 * - \ref SCIP_STAGE_PROBLEM
4506 * - \ref SCIP_STAGE_TRANSFORMING
4507 * - \ref SCIP_STAGE_PRESOLVING
4508 * - \ref SCIP_STAGE_PRESOLVED
4509 */
4510 SCIP_RETCODE SCIPchgVarObj(
4511 SCIP* scip, /**< SCIP data structure */
4512 SCIP_VAR* var, /**< variable to change the objective value for */
4513 SCIP_Real newobj /**< new objective value */
4514 )
4515 {
4516 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4517
4518 assert( var->scip == scip );
4519
4520 /* forbid infinite objective values */
4521 if( SCIPisInfinity(scip, REALABS(newobj)) )
4522 {
4523 SCIPerrorMessage("invalid objective value: objective value is infinite\n");
4524 return SCIP_INVALIDDATA;
4525 }
4526
4527 switch( scip->set->stage )
4528 {
4529 case SCIP_STAGE_PROBLEM:
4530 assert(!SCIPvarIsTransformed(var));
4531 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->origprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4532 return SCIP_OKAY;
4533
4534 case SCIP_STAGE_TRANSFORMED:
4535 case SCIP_STAGE_TRANSFORMING:
4536 case SCIP_STAGE_PRESOLVING:
4537 case SCIP_STAGE_PRESOLVED:
4538 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->transprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4539 return SCIP_OKAY;
4540
4541 default:
4542 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4543 return SCIP_INVALIDCALL;
4544 } /*lint !e788*/
4545 }
4546
4547 /** adds value to variable's objective value
4548 *
4549 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4550 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4551 *
4552 * @pre This method can be called if @p scip is in one of the following stages:
4553 * - \ref SCIP_STAGE_PROBLEM
4554 * - \ref SCIP_STAGE_TRANSFORMING
4555 * - \ref SCIP_STAGE_PRESOLVING
4556 * - \ref SCIP_STAGE_EXITPRESOLVE
4557 * - \ref SCIP_STAGE_PRESOLVED
4558 */
4559 SCIP_RETCODE SCIPaddVarObj(
4560 SCIP* scip, /**< SCIP data structure */
4561 SCIP_VAR* var, /**< variable to change the objective value for */
4562 SCIP_Real addobj /**< additional objective value */
4563 )
4564 {
4565 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4566
4567 assert( var->scip == scip );
4568
4569 switch( scip->set->stage )
4570 {
4571 case SCIP_STAGE_PROBLEM:
4572 assert(!SCIPvarIsTransformed(var));
4573 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4574 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4575 return SCIP_OKAY;
4576
4577 case SCIP_STAGE_TRANSFORMING:
4578 case SCIP_STAGE_PRESOLVING:
4579 case SCIP_STAGE_EXITPRESOLVE:
4580 case SCIP_STAGE_PRESOLVED:
4581 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4582 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4583 return SCIP_OKAY;
4584
4585 default:
4586 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4587 return SCIP_INVALIDCALL;
4588 } /*lint !e788*/
4589 }
4590
4591 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) lower bound value;
4592 * does not change the bounds of the variable
4593 *
4594 * @return adjusted lower bound for the given variable; the bound of the variable is not changed
4595 *
4596 * @pre This method can be called if @p scip is in one of the following stages:
4597 * - \ref SCIP_STAGE_PROBLEM
4598 * - \ref SCIP_STAGE_TRANSFORMING
4599 * - \ref SCIP_STAGE_TRANSFORMED
4600 * - \ref SCIP_STAGE_INITPRESOLVE
4601 * - \ref SCIP_STAGE_PRESOLVING
4602 * - \ref SCIP_STAGE_EXITPRESOLVE
4603 * - \ref SCIP_STAGE_PRESOLVED
4604 * - \ref SCIP_STAGE_INITSOLVE
4605 * - \ref SCIP_STAGE_SOLVING
4606 * - \ref SCIP_STAGE_SOLVED
4607 * - \ref SCIP_STAGE_EXITSOLVE
4608 * - \ref SCIP_STAGE_FREETRANS
4609 */
4610 SCIP_Real SCIPadjustedVarLb(
4611 SCIP* scip, /**< SCIP data structure */
4612 SCIP_VAR* var, /**< variable to adjust the bound for */
4613 SCIP_Real lb /**< lower bound value to adjust */
4614 )
4615 {
4616 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarLb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
4617
4618 SCIPvarAdjustLb(var, scip->set, &lb);
4619
4620 return lb;
4621 }
4622
4623 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) upper bound value;
4624 * does not change the bounds of the variable
4625 *
4626 * @return adjusted upper bound for the given variable; the bound of the variable is not changed
4627 *
4628 * @pre This method can be called if @p scip is in one of the following stages:
4629 * - \ref SCIP_STAGE_PROBLEM
4630 * - \ref SCIP_STAGE_TRANSFORMING
4631 * - \ref SCIP_STAGE_TRANSFORMED
4632 * - \ref SCIP_STAGE_INITPRESOLVE
4633 * - \ref SCIP_STAGE_PRESOLVING
4634 * - \ref SCIP_STAGE_EXITPRESOLVE
4635 * - \ref SCIP_STAGE_PRESOLVED
4636 * - \ref SCIP_STAGE_INITSOLVE
4637 * - \ref SCIP_STAGE_SOLVING
4638 * - \ref SCIP_STAGE_SOLVED
4639 * - \ref SCIP_STAGE_EXITSOLVE
4640 * - \ref SCIP_STAGE_FREETRANS
4641 */
4642 SCIP_Real SCIPadjustedVarUb(
4643 SCIP* scip, /**< SCIP data structure */
4644 SCIP_VAR* var, /**< variable to adjust the bound for */
4645 SCIP_Real ub /**< upper bound value to adjust */
4646 )
4647 {
4648 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarUb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
4649
4650 SCIPvarAdjustUb(var, scip->set, &ub);
4651
4652 return ub;
4653 }
4654
4655 /** depending on SCIP's stage, changes lower bound of variable in the problem, in preprocessing, or in current node;
4656 * if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such
4657 * that in conflict analysis, this change is treated like a branching decision
4658 *
4659 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4660 * SCIPgetVars()) gets resorted.
4661 *
4662 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4663 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4664 *
4665 * @pre This method can be called if @p scip is in one of the following stages:
4666 * - \ref SCIP_STAGE_PROBLEM
4667 * - \ref SCIP_STAGE_TRANSFORMING
4668 * - \ref SCIP_STAGE_PRESOLVING
4669 * - \ref SCIP_STAGE_SOLVING
4670 *
4671 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4672 */
4673 SCIP_RETCODE SCIPchgVarLb(
4674 SCIP* scip, /**< SCIP data structure */
4675 SCIP_VAR* var, /**< variable to change the bound for */
4676 SCIP_Real newbound /**< new value for bound */
4677 )
4678 {
4679 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4680
4681 SCIPvarAdjustLb(var, scip->set, &newbound);
4682
4683 /* ignore tightenings of lower bounds to +infinity during solving process */
4684 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4685 {
4686 #ifndef NDEBUG
4687 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4688 SCIPvarGetLbLocal(var));
4689 #endif
4690 return SCIP_OKAY;
4691 }
4692
4693 switch( scip->set->stage )
4694 {
4695 case SCIP_STAGE_PROBLEM:
4696 assert(!SCIPvarIsTransformed(var));
4697 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4698 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4699 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4700 scip->branchcand, scip->eventqueue, newbound) );
4701 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
4702 break;
4703
4704 case SCIP_STAGE_TRANSFORMING:
4705 case SCIP_STAGE_PRESOLVED:
4706 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4707 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4708 break;
4709
4710 case SCIP_STAGE_PRESOLVING:
4711 if( !SCIPinProbing(scip) )
4712 {
4713 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4714 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4715
4716 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4717 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable,
4718 var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
4719
4720 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4721 {
4722 SCIP_Bool infeasible;
4723
4724 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4725 assert(!infeasible);
4726 }
4727 break;
4728 }
4729 /*lint -fallthrough*/
4730 case SCIP_STAGE_SOLVING:
4731 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
4732 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4733 scip->cliquetable, var, newbound,
4734 SCIP_BOUNDTYPE_LOWER, FALSE) );
4735 break;
4736
4737 default:
4738 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4739 return SCIP_INVALIDCALL;
4740 } /*lint !e788*/
4741
4742 return SCIP_OKAY;
4743 }
4744
4745 /** depending on SCIP's stage, changes upper bound of variable in the problem, in preprocessing, or in current node;
4746 * if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such
4747 * that in conflict analysis, this change is treated like a branching decision
4748 *
4749 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4750 * SCIPgetVars()) gets resorted.
4751 *
4752 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4753 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4754 *
4755 * @pre This method can be called if @p scip is in one of the following stages:
4756 * - \ref SCIP_STAGE_PROBLEM
4757 * - \ref SCIP_STAGE_TRANSFORMING
4758 * - \ref SCIP_STAGE_PRESOLVING
4759 * - \ref SCIP_STAGE_SOLVING
4760 *
4761 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4762 */
4763 SCIP_RETCODE SCIPchgVarUb(
4764 SCIP* scip, /**< SCIP data structure */
4765 SCIP_VAR* var, /**< variable to change the bound for */
4766 SCIP_Real newbound /**< new value for bound */
4767 )
4768 {
4769 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4770
4771 SCIPvarAdjustUb(var, scip->set, &newbound);
4772
4773 /* ignore tightenings of upper bounds to -infinity during solving process */
4774 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4775 {
4776 #ifndef NDEBUG
4777 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
4778 SCIPvarGetUbLocal(var));
4779 #endif
4780 return SCIP_OKAY;
4781 }
4782
4783 switch( scip->set->stage )
4784 {
4785 case SCIP_STAGE_PROBLEM:
4786 assert(!SCIPvarIsTransformed(var));
4787 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4788 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4789 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4790 scip->branchcand, scip->eventqueue, newbound) );
4791 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
4792 break;
4793
4794 case SCIP_STAGE_TRANSFORMING:
4795 case SCIP_STAGE_PRESOLVED:
4796 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4797 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4798 break;
4799
4800 case SCIP_STAGE_PRESOLVING:
4801 if( !SCIPinProbing(scip) )
4802 {
4803 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4804 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4805
4806 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4807 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4808 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
4809
4810 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4811 {
4812 SCIP_Bool infeasible;
4813
4814 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4815 assert(!infeasible);
4816 }
4817 break;
4818 }
4819 /*lint -fallthrough*/
4820 case SCIP_STAGE_SOLVING:
4821 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
4822 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
4823 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
4824 break;
4825
4826 default:
4827 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4828 return SCIP_INVALIDCALL;
4829 } /*lint !e788*/
4830
4831 return SCIP_OKAY;
4832 }
4833
4834 /** changes lower bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any
4835 * inference information in the bound change, such that in conflict analysis, this change is treated like a branching
4836 * decision
4837 *
4838 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4839 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4840 *
4841 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
4842 */
4843 SCIP_RETCODE SCIPchgVarLbNode(
4844 SCIP* scip, /**< SCIP data structure */
4845 SCIP_NODE* node, /**< node to change bound at, or NULL for current node */
4846 SCIP_VAR* var, /**< variable to change the bound for */
4847 SCIP_Real newbound /**< new value for bound */
4848 )
4849 {
4850 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4851
4852 if( node == NULL )
4853 {
4854 SCIP_CALL( SCIPchgVarLb(scip, var, newbound) );
4855 }
4856 else
4857 {
4858 SCIPvarAdjustLb(var, scip->set, &newbound);
4859
4860 /* ignore tightenings of lower bounds to +infinity during solving process */
4861 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4862 {
4863 #ifndef NDEBUG
4864 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4865 SCIPvarGetLbLocal(var));
4866 #endif
4867 return SCIP_OKAY;
4868 }
4869
4870 SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
4871 scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4872 SCIP_BOUNDTYPE_LOWER, FALSE) );
4873 }
4874
4875 return SCIP_OKAY;
4876 }
4877
4878 /** changes upper bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any
4879 * inference information in the bound change, such that in conflict analysis, this change is treated like a branching
4880 * decision
4881 *
4882 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4883 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4884 *
4885 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
4886 */
4887 SCIP_RETCODE SCIPchgVarUbNode(
4888 SCIP* scip, /**< SCIP data structure */
4889 SCIP_NODE* node, /**< node to change bound at, or NULL for current node */
4890 SCIP_VAR* var, /**< variable to change the bound for */
4891 SCIP_Real newbound /**< new value for bound */
4892 )
4893 {
4894 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4895
4896 if( node == NULL )
4897 {
4898 SCIP_CALL( SCIPchgVarUb(scip, var, newbound) );
4899 }
4900 else
4901 {
4902 SCIPvarAdjustUb(var, scip->set, &newbound);
4903
4904 /* ignore tightenings of upper bounds to -infinity during solving process */
4905 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4906 {
4907 #ifndef NDEBUG
4908 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
4909 SCIPvarGetUbLocal(var));
4910 #endif
4911 return SCIP_OKAY;
4912 }
4913
4914 SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
4915 scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4916 SCIP_BOUNDTYPE_UPPER, FALSE) );
4917 }
4918
4919 return SCIP_OKAY;
4920 }
4921
4922 /** changes global lower bound of variable; if possible, adjust bound to integral value; also tightens the local bound,
4923 * if the global bound is better than the local bound
4924 *
4925 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
4926 * SCIPgetVars()) gets resorted.
4927 *
4928 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4929 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4930 *
4931 * @pre This method can be called if @p scip is in one of the following stages:
4932 * - \ref SCIP_STAGE_PROBLEM
4933 * - \ref SCIP_STAGE_TRANSFORMING
4934 * - \ref SCIP_STAGE_PRESOLVING
4935 * - \ref SCIP_STAGE_SOLVING
4936 *
4937 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
4938 */
4939 SCIP_RETCODE SCIPchgVarLbGlobal(
4940 SCIP* scip, /**< SCIP data structure */
4941 SCIP_VAR* var, /**< variable to change the bound for */
4942 SCIP_Real newbound /**< new value for bound */
4943 )
4944 {
4945 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4946
4947 SCIPvarAdjustLb(var, scip->set, &newbound);
4948
4949 /* ignore tightenings of lower bounds to +infinity during solving process */
4950 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
4951 {
4952 #ifndef NDEBUG
4953 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
4954 SCIPvarGetLbLocal(var));
4955 #endif
4956 return SCIP_OKAY;
4957 }
4958
4959 switch( scip->set->stage )
4960 {
4961 case SCIP_STAGE_PROBLEM:
4962 assert(!SCIPvarIsTransformed(var));
4963 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4964 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4965 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4966 scip->branchcand, scip->eventqueue, newbound) );
4967 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
4968 break;
4969
4970 case SCIP_STAGE_TRANSFORMING:
4971 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
4972 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
4973 break;
4974
4975 case SCIP_STAGE_PRESOLVING:
4976 if( !SCIPinProbing(scip) )
4977 {
4978 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
4979 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
4980
4981 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4982 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4983 SCIP_BOUNDTYPE_LOWER, FALSE) );
4984
4985 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
4986 {
4987 SCIP_Bool infeasible;
4988
4989 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
4990 assert(!infeasible);
4991 }
4992 break;
4993 }
4994 /*lint -fallthrough*/
4995 case SCIP_STAGE_SOLVING:
4996 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
4997 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
4998 SCIP_BOUNDTYPE_LOWER, FALSE) );
4999 break;
5000
5001 default:
5002 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5003 return SCIP_INVALIDCALL;
5004 } /*lint !e788*/
5005
5006 return SCIP_OKAY;
5007 }
5008
5009 /** changes global upper bound of variable; if possible, adjust bound to integral value; also tightens the local bound,
5010 * if the global bound is better than the local bound
5011 *
5012 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5013 * SCIPgetVars()) gets resorted.
5014 *
5015 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5016 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5017 *
5018 * @pre This method can be called if @p scip is in one of the following stages:
5019 * - \ref SCIP_STAGE_PROBLEM
5020 * - \ref SCIP_STAGE_TRANSFORMING
5021 * - \ref SCIP_STAGE_PRESOLVING
5022 * - \ref SCIP_STAGE_SOLVING
5023 *
5024 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5025 */
5026 SCIP_RETCODE SCIPchgVarUbGlobal(
5027 SCIP* scip, /**< SCIP data structure */
5028 SCIP_VAR* var, /**< variable to change the bound for */
5029 SCIP_Real newbound /**< new value for bound */
5030 )
5031 {
5032 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5033
5034 SCIPvarAdjustUb(var, scip->set, &newbound);
5035
5036 /* ignore tightenings of upper bounds to -infinity during solving process */
5037 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5038 {
5039 #ifndef NDEBUG
5040 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5041 SCIPvarGetUbLocal(var));
5042 #endif
5043 return SCIP_OKAY;
5044 }
5045
5046 switch( scip->set->stage )
5047 {
5048 case SCIP_STAGE_PROBLEM:
5049 assert(!SCIPvarIsTransformed(var));
5050 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5051 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5052 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5053 scip->branchcand, scip->eventqueue, newbound) );
5054 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5055 break;
5056
5057 case SCIP_STAGE_TRANSFORMING:
5058 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5059 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5060 break;
5061
5062 case SCIP_STAGE_PRESOLVING:
5063 if( !SCIPinProbing(scip) )
5064 {
5065 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5066 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5067
5068 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5069 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5070 SCIP_BOUNDTYPE_UPPER, FALSE) );
5071
5072 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5073 {
5074 SCIP_Bool infeasible;
5075
5076 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
5077 assert(!infeasible);
5078 }
5079 break;
5080 }
5081 /*lint -fallthrough*/
5082 case SCIP_STAGE_SOLVING:
5083 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5084 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5085 SCIP_BOUNDTYPE_UPPER, FALSE) );
5086 break;
5087
5088 default:
5089 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5090 return SCIP_INVALIDCALL;
5091 } /*lint !e788*/
5092
5093 return SCIP_OKAY;
5094 }
5095
5096 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet
5097 *
5098 * lazy bounds are bounds, that are enforced by constraints and the objective function; hence, these bounds do not need
5099 * to be put into the LP explicitly.
5100 *
5101 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5102 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5103 *
5104 * @pre This method can be called if @p scip is in one of the following stages:
5105 * - \ref SCIP_STAGE_PROBLEM
5106 * - \ref SCIP_STAGE_TRANSFORMING
5107 * - \ref SCIP_STAGE_TRANSFORMED
5108 * - \ref SCIP_STAGE_PRESOLVING
5109 * - \ref SCIP_STAGE_SOLVING
5110 *
5111 * @note lazy bounds are useful for branch-and-price since the corresponding variable bounds are not part of the LP
5112 */
5113 SCIP_RETCODE SCIPchgVarLbLazy(
5114 SCIP* scip, /**< SCIP data structure */
5115 SCIP_VAR* var, /**< problem variable */
5116 SCIP_Real lazylb /**< the lazy lower bound to be set */
5117 )
5118 {
5119 assert(scip != NULL);
5120 assert(var != NULL);
5121
5122 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5123
5124 SCIP_CALL( SCIPvarChgLbLazy(var, scip->set, lazylb) );
5125
5126 return SCIP_OKAY;
5127 }
5128
5129 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet
5130 *
5131 * lazy bounds are bounds, that are enforced by constraints and the objective function; hence, these bounds do not need
5132 * to be put into the LP explicitly.
5133 *
5134 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5135 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5136 *
5137 * @pre This method can be called if @p scip is in one of the following stages:
5138 * - \ref SCIP_STAGE_PROBLEM
5139 * - \ref SCIP_STAGE_TRANSFORMING
5140 * - \ref SCIP_STAGE_TRANSFORMED
5141 * - \ref SCIP_STAGE_PRESOLVING
5142 * - \ref SCIP_STAGE_SOLVING
5143 *
5144 * @note lazy bounds are useful for branch-and-price since the corresponding variable bounds are not part of the LP
5145 */
5146 SCIP_RETCODE SCIPchgVarUbLazy(
5147 SCIP* scip, /**< SCIP data structure */
5148 SCIP_VAR* var, /**< problem variable */
5149 SCIP_Real lazyub /**< the lazy lower bound to be set */
5150 )
5151 {
5152 assert(scip != NULL);
5153 assert(var != NULL);
5154
5155 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5156
5157 SCIP_CALL( SCIPvarChgUbLazy(var, scip->set, lazyub) );
5158
5159 return SCIP_OKAY;
5160 }
5161
5162 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5163 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5164 * doesn't store any inference information in the bound change, such that in conflict analysis, this change
5165 * is treated like a branching decision
5166 *
5167 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5168 * SCIPgetVars()) gets resorted.
5169 *
5170 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5171 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5172 *
5173 * @pre This method can be called if @p scip is in one of the following stages:
5174 * - \ref SCIP_STAGE_PROBLEM
5175 * - \ref SCIP_STAGE_PRESOLVING
5176 * - \ref SCIP_STAGE_SOLVING
5177 *
5178 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5179 */
5180 SCIP_RETCODE SCIPtightenVarLb(
5181 SCIP* scip, /**< SCIP data structure */
5182 SCIP_VAR* var, /**< variable to change the bound for */
5183 SCIP_Real newbound, /**< new value for bound */
5184 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5185 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */
5186 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5187 )
5188 {
5189 SCIP_Real lb;
5190 SCIP_Real ub;
5191
5192 assert(infeasible != NULL);
5193
5194 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5195 /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */
5196 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip));
5197
5198 *infeasible = FALSE;
5199 if( tightened != NULL )
5200 *tightened = FALSE;
5201
5202 SCIPvarAdjustLb(var, scip->set, &newbound);
5203
5204 /* ignore tightenings of lower bounds to +infinity during solving process */
5205 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5206 {
5207 #ifndef NDEBUG
5208 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5209 SCIPvarGetLbLocal(var));
5210 #endif
5211 return SCIP_OKAY;
5212 }
5213
5214 /* get current bounds */
5215 lb = SCIPcomputeVarLbLocal(scip, var);
5216 ub = SCIPcomputeVarUbLocal(scip, var);
5217 assert(SCIPsetIsLE(scip->set, lb, ub));
5218
5219 if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5220 {
5221 *infeasible = TRUE;
5222 return SCIP_OKAY;
5223 }
5224 newbound = MIN(newbound, ub);
5225
5226 if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
5227 return SCIP_OKAY;
5228
5229 switch( scip->set->stage )
5230 {
5231 case SCIP_STAGE_PROBLEM:
5232 assert(!SCIPvarIsTransformed(var));
5233 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5234 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5235 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5236 scip->branchcand, scip->eventqueue, newbound) );
5237 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5238 break;
5239 case SCIP_STAGE_TRANSFORMED:
5240 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5241 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5242 break;
5243 case SCIP_STAGE_PRESOLVING:
5244 if( !SCIPinProbing(scip) )
5245 {
5246 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5247 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5248
5249 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5250 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5251 SCIP_BOUNDTYPE_LOWER, FALSE) );
5252
5253 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5254 {
5255 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5256 assert(!(*infeasible));
5257 }
5258 break;
5259 }
5260 /*lint -fallthrough*/
5261 case SCIP_STAGE_SOLVING:
5262 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5263 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable,
5264 var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
5265 break;
5266
5267 default:
5268 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5269 return SCIP_INVALIDCALL;
5270 } /*lint !e788*/
5271
5272 /* check whether the lower bound improved */
5273 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5274 *tightened = TRUE;
5275
5276 return SCIP_OKAY;
5277 }
5278
5279 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5280 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5281 * doesn't store any inference information in the bound change, such that in conflict analysis, this change
5282 * is treated like a branching decision
5283 *
5284 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5285 * SCIPgetVars()) gets resorted.
5286 *
5287 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5288 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5289 *
5290 * @pre This method can be called if @p scip is in one of the following stages:
5291 * - \ref SCIP_STAGE_PROBLEM
5292 * - \ref SCIP_STAGE_PRESOLVING
5293 * - \ref SCIP_STAGE_SOLVING
5294 *
5295 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5296 */
5297 SCIP_RETCODE SCIPtightenVarUb(
5298 SCIP* scip, /**< SCIP data structure */
5299 SCIP_VAR* var, /**< variable to change the bound for */
5300 SCIP_Real newbound, /**< new value for bound */
5301 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5302 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */
5303 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5304 )
5305 {
5306 SCIP_Real lb;
5307 SCIP_Real ub;
5308
5309 assert(infeasible != NULL);
5310 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5311
5312 /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */
5313 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip));
5314
5315 *infeasible = FALSE;
5316 if( tightened != NULL )
5317 *tightened = FALSE;
5318
5319 SCIPvarAdjustUb(var, scip->set, &newbound);
5320
5321 /* ignore tightenings of upper bounds to -infinity during solving process */
5322 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5323 {
5324 #ifndef NDEBUG
5325 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5326 SCIPvarGetUbLocal(var));
5327 #endif
5328 return SCIP_OKAY;
5329 }
5330
5331 /* get current bounds */
5332 lb = SCIPcomputeVarLbLocal(scip, var);
5333 ub = SCIPcomputeVarUbLocal(scip, var);
5334 assert(SCIPsetIsLE(scip->set, lb, ub));
5335
5336 if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
5337 {
5338 *infeasible = TRUE;
5339 return SCIP_OKAY;
5340 }
5341 newbound = MAX(newbound, lb);
5342
5343 if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
5344 return SCIP_OKAY;
5345
5346 switch( scip->set->stage )
5347 {
5348 case SCIP_STAGE_PROBLEM:
5349 assert(!SCIPvarIsTransformed(var));
5350 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5351 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5352 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5353 scip->branchcand, scip->eventqueue, newbound) );
5354 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5355 break;
5356 case SCIP_STAGE_TRANSFORMED:
5357 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5358 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5359 break;
5360 case SCIP_STAGE_PRESOLVING:
5361 if( !SCIPinProbing(scip) )
5362 {
5363 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5364 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5365
5366 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5367 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5368 SCIP_BOUNDTYPE_UPPER, FALSE) );
5369
5370 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5371 {
5372 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5373 assert(!(*infeasible));
5374 }
5375 break;
5376 }
5377 /*lint -fallthrough*/
5378 case SCIP_STAGE_SOLVING:
5379 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5380 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5381 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
5382 break;
5383
5384 default:
5385 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5386 return SCIP_INVALIDCALL;
5387 } /*lint !e788*/
5388
5389 /* check whether the upper bound improved */
5390 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
5391 *tightened = TRUE;
5392
5393 return SCIP_OKAY;
5394 }
5395
5396 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening
5397 * epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is
5398 * stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change
5399 *
5400 * @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method
5401 * changes first the lowerbound by calling SCIPinferVarLbCons and second the upperbound by calling
5402 * SCIPinferVarUbCons
5403 *
5404 * @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via
5405 * SCIPgetVars()) gets resorted.
5406 *
5407 * @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable.
5408 */
5409 SCIP_RETCODE SCIPinferVarFixCons(
5410 SCIP* scip, /**< SCIP data structure */
5411 SCIP_VAR* var, /**< variable to change the bound for */
5412 SCIP_Real fixedval, /**< new value for fixation */
5413 SCIP_CONS* infercons, /**< constraint that deduced the bound change */
5414 int inferinfo, /**< user information for inference to help resolving the conflict */
5415 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5416 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5417 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5418 )
5419 {
5420 assert(scip != NULL);
5421 assert(var != NULL);
5422 assert(infeasible != NULL);
5423
5424 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5425
5426 if( tightened != NULL )
5427 *tightened = FALSE;
5428
5429 /* in presolving case we take the shortcut to directly fix the variables */
5430 if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5431 {
5432 SCIP_Bool fixed;
5433
5434 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5435 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter,
5436 scip->eventqueue, scip->cliquetable, fixedval, infeasible, &fixed) );
5437
5438 if( tightened != NULL )
5439 *tightened = fixed;
5440 }
5441 /* otherwise we use the lb and ub methods */
5442 else
5443 {
5444 SCIP_Bool lbtightened;
5445
5446 SCIP_CALL( SCIPinferVarLbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, &lbtightened) );
5447
5448 if( ! (*infeasible) )
5449 {
5450 SCIP_CALL( SCIPinferVarUbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, tightened) );
5451
5452 if( tightened != NULL )
5453 *tightened |= lbtightened;
5454 }
5455 }
5456
5457 return SCIP_OKAY;
5458 }
5459
5460 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5461 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5462 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason
5463 * for the deduction of the bound change
5464 *
5465 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5466 * SCIPgetVars()) gets resorted.
5467 *
5468 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5469 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5470 *
5471 * @pre This method can be called if @p scip is in one of the following stages:
5472 * - \ref SCIP_STAGE_PROBLEM
5473 * - \ref SCIP_STAGE_PRESOLVING
5474 * - \ref SCIP_STAGE_SOLVING
5475 *
5476 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5477 */
5478 SCIP_RETCODE SCIPinferVarLbCons(
5479 SCIP* scip, /**< SCIP data structure */
5480 SCIP_VAR* var, /**< variable to change the bound for */
5481 SCIP_Real newbound, /**< new value for bound */
5482 SCIP_CONS* infercons, /**< constraint that deduced the bound change */
5483 int inferinfo, /**< user information for inference to help resolving the conflict */
5484 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5485 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5486 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5487 )
5488 {
5489 SCIP_Real lb;
5490 SCIP_Real ub;
5491
5492 assert(infeasible != NULL);
5493
5494 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5495
5496 *infeasible = FALSE;
5497 if( tightened != NULL )
5498 *tightened = FALSE;
5499
5500 SCIPvarAdjustLb(var, scip->set, &newbound);
5501
5502 /* ignore tightenings of lower bounds to +infinity during solving process */
5503 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5504 {
5505 #ifndef NDEBUG
5506 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5507 SCIPvarGetLbLocal(var));
5508 #endif
5509 return SCIP_OKAY;
5510 }
5511
5512 /* get current bounds */
5513 lb = SCIPvarGetLbLocal(var);
5514 ub = SCIPvarGetUbLocal(var);
5515 assert(SCIPsetIsLE(scip->set, lb, ub));
5516
5517 if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5518 {
5519 *infeasible = TRUE;
5520 return SCIP_OKAY;
5521 }
5522 newbound = MIN(newbound, ub);
5523
5524 if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
5525 return SCIP_OKAY;
5526
5527 switch( scip->set->stage )
5528 {
5529 case SCIP_STAGE_PROBLEM:
5530 assert(!SCIPvarIsTransformed(var));
5531 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5532 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5533 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5534 scip->branchcand, scip->eventqueue, newbound) );
5535 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5536 break;
5537
5538 case SCIP_STAGE_PRESOLVING:
5539 if( !SCIPinProbing(scip) )
5540 {
5541 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5542 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5543
5544 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5545 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5546 SCIP_BOUNDTYPE_LOWER, FALSE) );
5547
5548 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5549 {
5550 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5551 assert(!(*infeasible));
5552 }
5553 break;
5554 }
5555 /*lint -fallthrough*/
5556 case SCIP_STAGE_SOLVING:
5557 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5558 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5559 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) );
5560 break;
5561
5562 default:
5563 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5564 return SCIP_INVALIDCALL;
5565 } /*lint !e788*/
5566
5567 /* check whether the lower bound improved */
5568 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5569 *tightened = TRUE;
5570
5571 return SCIP_OKAY;
5572 }
5573
5574 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5575 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5576 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason
5577 * for the deduction of the bound change
5578 *
5579 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5580 * SCIPgetVars()) gets resorted.
5581 *
5582 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5583 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5584 *
5585 * @pre This method can be called if @p scip is in one of the following stages:
5586 * - \ref SCIP_STAGE_PROBLEM
5587 * - \ref SCIP_STAGE_PRESOLVING
5588 * - \ref SCIP_STAGE_SOLVING
5589 *
5590 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5591 */
5592 SCIP_RETCODE SCIPinferVarUbCons(
5593 SCIP* scip, /**< SCIP data structure */
5594 SCIP_VAR* var, /**< variable to change the bound for */
5595 SCIP_Real newbound, /**< new value for bound */
5596 SCIP_CONS* infercons, /**< constraint that deduced the bound change */
5597 int inferinfo, /**< user information for inference to help resolving the conflict */
5598 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5599 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5600 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5601 )
5602 {
5603 SCIP_Real lb;
5604 SCIP_Real ub;
5605
5606 assert(infeasible != NULL);
5607
5608 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5609
5610 *infeasible = FALSE;
5611 if( tightened != NULL )
5612 *tightened = FALSE;
5613
5614 SCIPvarAdjustUb(var, scip->set, &newbound);
5615
5616 /* ignore tightenings of upper bounds to -infinity during solving process */
5617 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5618 {
5619 #ifndef NDEBUG
5620 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
5621 SCIPvarGetUbLocal(var));
5622 #endif
5623 return SCIP_OKAY;
5624 }
5625
5626 /* get current bounds */
5627 lb = SCIPvarGetLbLocal(var);
5628 ub = SCIPvarGetUbLocal(var);
5629 assert(SCIPsetIsLE(scip->set, lb, ub));
5630
5631 if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
5632 {
5633 *infeasible = TRUE;
5634 return SCIP_OKAY;
5635 }
5636 newbound = MAX(newbound, lb);
5637
5638 if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
5639 return SCIP_OKAY;
5640
5641 switch( scip->set->stage )
5642 {
5643 case SCIP_STAGE_PROBLEM:
5644 assert(!SCIPvarIsTransformed(var));
5645 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5646 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5647 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5648 scip->branchcand, scip->eventqueue, newbound) );
5649 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
5650 break;
5651
5652 case SCIP_STAGE_PRESOLVING:
5653 if( !SCIPinProbing(scip) )
5654 {
5655 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5656 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5657
5658 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5659 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5660 SCIP_BOUNDTYPE_UPPER, FALSE) );
5661
5662 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5663 {
5664 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5665 assert(!(*infeasible));
5666 }
5667 break;
5668 }
5669 /*lint -fallthrough*/
5670 case SCIP_STAGE_SOLVING:
5671 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5672 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5673 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) );
5674 break;
5675
5676 default:
5677 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5678 return SCIP_INVALIDCALL;
5679 } /*lint !e788*/
5680
5681 /* check whether the upper bound improved */
5682 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
5683 *tightened = TRUE;
5684
5685 return SCIP_OKAY;
5686 }
5687
5688 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node;
5689 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason for the
5690 * deduction of the fixing
5691 *
5692 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5693 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5694 *
5695 * @pre This method can be called if @p scip is in one of the following stages:
5696 * - \ref SCIP_STAGE_PROBLEM
5697 * - \ref SCIP_STAGE_PRESOLVING
5698 * - \ref SCIP_STAGE_SOLVING
5699 */
5700 SCIP_RETCODE SCIPinferBinvarCons(
5701 SCIP* scip, /**< SCIP data structure */
5702 SCIP_VAR* var, /**< binary variable to fix */
5703 SCIP_Bool fixedval, /**< value to fix binary variable to */
5704 SCIP_CONS* infercons, /**< constraint that deduced the fixing */
5705 int inferinfo, /**< user information for inference to help resolving the conflict */
5706 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
5707 SCIP_Bool* tightened /**< pointer to store whether the fixing tightened the local bounds, or NULL */
5708 )
5709 {
5710 SCIP_Real lb;
5711 SCIP_Real ub;
5712
5713 assert(SCIPvarIsBinary(var));
5714 assert(fixedval == TRUE || fixedval == FALSE);
5715 assert(infeasible != NULL);
5716
5717 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5718
5719 *infeasible = FALSE;
5720 if( tightened != NULL )
5721 *tightened = FALSE;
5722
5723 /* get current bounds */
5724 lb = SCIPvarGetLbLocal(var);
5725 ub = SCIPvarGetUbLocal(var);
5726 assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0));
5727 assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0));
5728 assert(SCIPsetIsLE(scip->set, lb, ub));
5729
5730 /* check, if variable is already fixed */
5731 if( (lb > 0.5) || (ub < 0.5) )
5732 {
5733 *infeasible = (fixedval == (lb < 0.5));
5734
5735 return SCIP_OKAY;
5736 }
5737
5738 /* apply the fixing */
5739 switch( scip->set->stage )
5740 {
5741 case SCIP_STAGE_PROBLEM:
5742 assert(!SCIPvarIsTransformed(var));
5743 if( fixedval == TRUE )
5744 {
5745 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
5746 }
5747 else
5748 {
5749 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
5750 }
5751 break;
5752
5753 case SCIP_STAGE_PRESOLVING:
5754 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5755 {
5756 SCIP_Bool fixed;
5757
5758 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5759 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
5760 scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) );
5761 break;
5762 }
5763 /*lint -fallthrough*/
5764 case SCIP_STAGE_SOLVING:
5765 if( fixedval == TRUE )
5766 {
5767 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5768 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5769 scip->cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) );
5770 }
5771 else
5772 {
5773 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5774 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5775 scip->cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) );
5776 }
5777 break;
5778
5779 default:
5780 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5781 return SCIP_INVALIDCALL;
5782 } /*lint !e788*/
5783
5784 if( tightened != NULL )
5785 *tightened = TRUE;
5786
5787 return SCIP_OKAY;
5788 }
5789
5790 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening
5791 * epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is
5792 * stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change
5793 *
5794 * @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method
5795 * changes first the lowerbound by calling SCIPinferVarLbProp and second the upperbound by calling
5796 * SCIPinferVarUbProp
5797 *
5798 * @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via
5799 * SCIPgetVars()) gets resorted.
5800 *
5801 * @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable.
5802 */
5803 SCIP_RETCODE SCIPinferVarFixProp(
5804 SCIP* scip, /**< SCIP data structure */
5805 SCIP_VAR* var, /**< variable to change the bound for */
5806 SCIP_Real fixedval, /**< new value for fixation */
5807 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */
5808 int inferinfo, /**< user information for inference to help resolving the conflict */
5809 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5810 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5811 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5812 )
5813 {
5814 assert(scip != NULL);
5815 assert(var != NULL);
5816 assert(infeasible != NULL);
5817
5818 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5819
5820 if( tightened != NULL )
5821 *tightened = FALSE;
5822
5823 /* in presolving case we take the shortcut to directly fix the variables */
5824 if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 )
5825 {
5826 SCIP_Bool fixed;
5827
5828 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
5829 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
5830 scip->cliquetable, fixedval, infeasible, &fixed) );
5831
5832 if( tightened != NULL )
5833 *tightened = fixed;
5834 }
5835 /* otherwise we use the lb and ub methods */
5836 else
5837 {
5838 SCIP_Bool lbtightened;
5839
5840 SCIP_CALL( SCIPinferVarLbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, &lbtightened) );
5841
5842 if( ! (*infeasible) )
5843 {
5844 SCIP_CALL( SCIPinferVarUbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, tightened) );
5845
5846 if( tightened != NULL )
5847 *tightened |= lbtightened;
5848 }
5849 }
5850
5851 return SCIP_OKAY;
5852 }
5853
5854 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter
5855 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5856 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason
5857 * for the deduction of the bound change
5858 *
5859 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5860 * SCIPgetVars()) gets resorted.
5861 *
5862 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5863 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5864 *
5865 * @pre This method can be called if @p scip is in one of the following stages:
5866 * - \ref SCIP_STAGE_PROBLEM
5867 * - \ref SCIP_STAGE_PRESOLVING
5868 * - \ref SCIP_STAGE_SOLVING
5869 *
5870 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5871 */
5872 SCIP_RETCODE SCIPinferVarLbProp(
5873 SCIP* scip, /**< SCIP data structure */
5874 SCIP_VAR* var, /**< variable to change the bound for */
5875 SCIP_Real newbound, /**< new value for bound */
5876 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */
5877 int inferinfo, /**< user information for inference to help resolving the conflict */
5878 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5879 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5880 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5881 )
5882 {
5883 SCIP_Real lb;
5884 SCIP_Real ub;
5885
5886 assert(infeasible != NULL);
5887
5888 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5889
5890 *infeasible = FALSE;
5891 if( tightened != NULL )
5892 *tightened = FALSE;
5893
5894 SCIPvarAdjustLb(var, scip->set, &newbound);
5895
5896 /* ignore tightenings of lower bounds to +infinity during solving process */
5897 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
5898 {
5899 #ifndef NDEBUG
5900 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
5901 SCIPvarGetLbLocal(var));
5902 #endif
5903 return SCIP_OKAY;
5904 }
5905
5906 /* get current bounds */
5907 lb = SCIPvarGetLbLocal(var);
5908 ub = SCIPvarGetUbLocal(var);
5909 assert(SCIPsetIsLE(scip->set, lb, ub));
5910
5911 if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
5912 {
5913 *infeasible = TRUE;
5914 return SCIP_OKAY;
5915 }
5916 newbound = MIN(newbound, ub);
5917
5918 if( (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub))
5919 || SCIPsetIsLE(scip->set, newbound, lb) )
5920 return SCIP_OKAY;
5921
5922 switch( scip->set->stage )
5923 {
5924 case SCIP_STAGE_PROBLEM:
5925 assert(!SCIPvarIsTransformed(var));
5926 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5927 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
5928 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
5929 scip->branchcand, scip->eventqueue, newbound) );
5930 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
5931 break;
5932
5933 case SCIP_STAGE_PRESOLVING:
5934 if( !SCIPinProbing(scip) )
5935 {
5936 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
5937 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
5938
5939 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
5940 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
5941 SCIP_BOUNDTYPE_LOWER, FALSE) );
5942
5943 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
5944 {
5945 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
5946 assert(!(*infeasible));
5947 }
5948 break;
5949 }
5950 /*lint -fallthrough*/
5951 case SCIP_STAGE_SOLVING:
5952 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
5953 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
5954 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) );
5955 break;
5956
5957 default:
5958 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
5959 return SCIP_INVALIDCALL;
5960 } /*lint !e788*/
5961
5962 /* check whether the lower bound improved */
5963 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) )
5964 *tightened = TRUE;
5965
5966 return SCIP_OKAY;
5967 }
5968
5969 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter
5970 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value;
5971 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason
5972 * for the deduction of the bound change
5973 *
5974 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
5975 * SCIPgetVars()) gets resorted.
5976 *
5977 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
5978 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
5979 *
5980 * @pre This method can be called if @p scip is in one of the following stages:
5981 * - \ref SCIP_STAGE_PROBLEM
5982 * - \ref SCIP_STAGE_PRESOLVING
5983 * - \ref SCIP_STAGE_SOLVING
5984 *
5985 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
5986 */
5987 SCIP_RETCODE SCIPinferVarUbProp(
5988 SCIP* scip, /**< SCIP data structure */
5989 SCIP_VAR* var, /**< variable to change the bound for */
5990 SCIP_Real newbound, /**< new value for bound */
5991 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */
5992 int inferinfo, /**< user information for inference to help resolving the conflict */
5993 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
5994 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */
5995 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
5996 )
5997 {
5998 SCIP_Real lb;
5999 SCIP_Real ub;
6000
6001 assert(infeasible != NULL);
6002
6003 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6004
6005 *infeasible = FALSE;
6006 if( tightened != NULL )
6007 *tightened = FALSE;
6008
6009 SCIPvarAdjustUb(var, scip->set, &newbound);
6010
6011 /* ignore tightenings of upper bounds to -infinity during solving process */
6012 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6013 {
6014 #ifndef NDEBUG
6015 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
6016 SCIPvarGetUbLocal(var));
6017 #endif
6018 return SCIP_OKAY;
6019 }
6020
6021 /* get current bounds */
6022 lb = SCIPvarGetLbLocal(var);
6023 ub = SCIPvarGetUbLocal(var);
6024 assert(SCIPsetIsLE(scip->set, lb, ub));
6025
6026 if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
6027 {
6028 *infeasible = TRUE;
6029 return SCIP_OKAY;
6030 }
6031 newbound = MAX(newbound, lb);
6032
6033 if( (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub))
6034 || SCIPsetIsGE(scip->set, newbound, ub) )
6035 return SCIP_OKAY;
6036
6037 switch( scip->set->stage )
6038 {
6039 case SCIP_STAGE_PROBLEM:
6040 assert(!SCIPvarIsTransformed(var));
6041 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6042 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6043 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6044 scip->branchcand, scip->eventqueue, newbound) );
6045 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
6046 break;
6047
6048 case SCIP_STAGE_PRESOLVING:
6049 if( !SCIPinProbing(scip) )
6050 {
6051 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6052 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6053
6054 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6055 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6056 SCIP_BOUNDTYPE_UPPER, FALSE) );
6057
6058 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6059 {
6060 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6061 assert(!(*infeasible));
6062 }
6063 break;
6064 }
6065 /*lint -fallthrough*/
6066 case SCIP_STAGE_SOLVING:
6067 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6068 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
6069 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) );
6070 break;
6071
6072 default:
6073 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6074 return SCIP_INVALIDCALL;
6075 } /*lint !e788*/
6076
6077 /* check whether the upper bound improved */
6078 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) )
6079 *tightened = TRUE;
6080
6081 return SCIP_OKAY;
6082 }
6083
6084 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node;
6085 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason for the
6086 * deduction of the fixing
6087 *
6088 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6089 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6090 *
6091 * @pre This method can be called if @p scip is in one of the following stages:
6092 * - \ref SCIP_STAGE_PROBLEM
6093 * - \ref SCIP_STAGE_PRESOLVING
6094 * - \ref SCIP_STAGE_PRESOLVED
6095 * - \ref SCIP_STAGE_SOLVING
6096 */
6097 SCIP_RETCODE SCIPinferBinvarProp(
6098 SCIP* scip, /**< SCIP data structure */
6099 SCIP_VAR* var, /**< binary variable to fix */
6100 SCIP_Bool fixedval, /**< value to fix binary variable to */
6101 SCIP_PROP* inferprop, /**< propagator that deduced the fixing */
6102 int inferinfo, /**< user information for inference to help resolving the conflict */
6103 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
6104 SCIP_Bool* tightened /**< pointer to store whether the fixing tightened the local bounds, or NULL */
6105 )
6106 {
6107 SCIP_Real lb;
6108 SCIP_Real ub;
6109
6110 assert(SCIPvarIsBinary(var));
6111 assert(fixedval == TRUE || fixedval == FALSE);
6112 assert(infeasible != NULL);
6113
6114 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6115
6116 *infeasible = FALSE;
6117 if( tightened != NULL )
6118 *tightened = FALSE;
6119
6120 /* get current bounds */
6121 lb = SCIPvarGetLbLocal(var);
6122 ub = SCIPvarGetUbLocal(var);
6123 assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0));
6124 assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0));
6125 assert(SCIPsetIsLE(scip->set, lb, ub));
6126
6127 /* check, if variable is already fixed */
6128 if( (lb > 0.5) || (ub < 0.5) )
6129 {
6130 *infeasible = (fixedval == (lb < 0.5));
6131
6132 return SCIP_OKAY;
6133 }
6134
6135 /* apply the fixing */
6136 switch( scip->set->stage )
6137 {
6138 case SCIP_STAGE_PROBLEM:
6139 assert(!SCIPvarIsTransformed(var));
6140 if( fixedval == TRUE )
6141 {
6142 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
6143 }
6144 else
6145 {
6146 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
6147 }
6148 break;
6149
6150 case SCIP_STAGE_PRESOLVING:
6151 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
6152 {
6153 SCIP_Bool fixed;
6154
6155 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6156 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
6157 scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) );
6158 break;
6159 }
6160 /*lint -fallthrough*/
6161 case SCIP_STAGE_SOLVING:
6162 if( fixedval == TRUE )
6163 {
6164 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6165 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 1.0,
6166 SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) );
6167 }
6168 else
6169 {
6170 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat,
6171 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 0.0,
6172 SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) );
6173 }
6174 break;
6175
6176 default:
6177 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6178 return SCIP_INVALIDCALL;
6179 } /*lint !e788*/
6180
6181 if( tightened != NULL )
6182 *tightened = TRUE;
6183
6184 return SCIP_OKAY;
6185 }
6186
6187 /** changes global lower bound of variable in preprocessing or in the current node, if the new bound is tighter
6188 * (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value;
6189 * also tightens the local bound, if the global bound is better than the local bound
6190 *
6191 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
6192 * SCIPgetVars()) gets resorted.
6193 *
6194 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6195 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6196 *
6197 * @pre This method can be called if @p scip is in one of the following stages:
6198 * - \ref SCIP_STAGE_PROBLEM
6199 * - \ref SCIP_STAGE_TRANSFORMING
6200 * - \ref SCIP_STAGE_PRESOLVING
6201 * - \ref SCIP_STAGE_SOLVING
6202 *
6203 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
6204 */
6205 SCIP_RETCODE SCIPtightenVarLbGlobal(
6206 SCIP* scip, /**< SCIP data structure */
6207 SCIP_VAR* var, /**< variable to change the bound for */
6208 SCIP_Real newbound, /**< new value for bound */
6209 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
6210 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */
6211 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
6212 )
6213 {
6214 SCIP_Real lb;
6215 SCIP_Real ub;
6216
6217 assert(infeasible != NULL);
6218
6219 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6220
6221 *infeasible = FALSE;
6222 if( tightened != NULL )
6223 *tightened = FALSE;
6224
6225 SCIPvarAdjustLb(var, scip->set, &newbound);
6226
6227 /* ignore tightenings of lower bounds to +infinity during solving process */
6228 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6229 {
6230 #ifndef NDEBUG
6231 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var),
6232 SCIPvarGetLbLocal(var));
6233 #endif
6234 return SCIP_OKAY;
6235 }
6236
6237 /* get current bounds */
6238 lb = SCIPvarGetLbGlobal(var);
6239 ub = SCIPvarGetUbGlobal(var);
6240 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub));
6241
6242 if( SCIPsetIsFeasGT(scip->set, newbound, ub) )
6243 {
6244 *infeasible = TRUE;
6245 return SCIP_OKAY;
6246 }
6247 newbound = MIN(newbound, ub);
6248
6249 /* bound changes of less than epsilon are ignored by SCIPvarChgLb or raise an assert in SCIPnodeAddBoundinfer,
6250 * so don't apply them even if force is set
6251 */
6252 if( SCIPsetIsEQ(scip->set, lb, newbound) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) )
6253 return SCIP_OKAY;
6254
6255 switch( scip->set->stage )
6256 {
6257 case SCIP_STAGE_PROBLEM:
6258 assert(!SCIPvarIsTransformed(var));
6259 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6260 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6261 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6262 scip->branchcand, scip->eventqueue, newbound) );
6263 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
6264 break;
6265
6266 case SCIP_STAGE_TRANSFORMING:
6267 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6268 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6269 break;
6270
6271 case SCIP_STAGE_PRESOLVING:
6272 if( !SCIPinProbing(scip) )
6273 {
6274 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6275 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6276
6277 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6278 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6279 SCIP_BOUNDTYPE_LOWER, FALSE) );
6280
6281 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6282 {
6283 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6284 assert(!(*infeasible));
6285 }
6286 break;
6287 }
6288 /*lint -fallthrough*/
6289 case SCIP_STAGE_SOLVING:
6290 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6291 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6292 SCIP_BOUNDTYPE_LOWER, FALSE) );
6293 break;
6294
6295 default:
6296 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6297 return SCIP_INVALIDCALL;
6298 } /*lint !e788*/
6299
6300 /* coverity: unreachable code */
6301 if( tightened != NULL && lb < SCIPcomputeVarLbGlobal(scip, var) )
6302 *tightened = TRUE;
6303
6304 return SCIP_OKAY;
6305 }
6306
6307 /** changes global upper bound of variable in preprocessing or in the current node, if the new bound is tighter
6308 * (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value;
6309 * also tightens the local bound, if the global bound is better than the local bound
6310 *
6311 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via
6312 * SCIPgetVars()) gets resorted.
6313 *
6314 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6315 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6316 *
6317 * @pre This method can be called if @p scip is in one of the following stages:
6318 * - \ref SCIP_STAGE_PROBLEM
6319 * - \ref SCIP_STAGE_TRANSFORMING
6320 * - \ref SCIP_STAGE_PRESOLVING
6321 * - \ref SCIP_STAGE_SOLVING
6322 *
6323 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable.
6324 */
6325 SCIP_RETCODE SCIPtightenVarUbGlobal(
6326 SCIP* scip, /**< SCIP data structure */
6327 SCIP_VAR* var, /**< variable to change the bound for */
6328 SCIP_Real newbound, /**< new value for bound */
6329 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
6330 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */
6331 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */
6332 )
6333 {
6334 SCIP_Real lb;
6335 SCIP_Real ub;
6336
6337 assert(infeasible != NULL);
6338
6339 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6340
6341 *infeasible = FALSE;
6342 if( tightened != NULL )
6343 *tightened = FALSE;
6344
6345 SCIPvarAdjustUb(var, scip->set, &newbound);
6346
6347 /* ignore tightenings of upper bounds to -infinity during solving process */
6348 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
6349 {
6350 #ifndef NDEBUG
6351 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var),
6352 SCIPvarGetUbLocal(var));
6353 #endif
6354 return SCIP_OKAY;
6355 }
6356
6357 /* get current bounds */
6358 lb = SCIPvarGetLbGlobal(var);
6359 ub = SCIPvarGetUbGlobal(var);
6360 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub));
6361
6362 if( SCIPsetIsFeasLT(scip->set, newbound, lb) )
6363 {
6364 *infeasible = TRUE;
6365 return SCIP_OKAY;
6366 }
6367 newbound = MAX(newbound, lb);
6368
6369 /* bound changes of less than epsilon are ignored by SCIPvarChgUb or raise an assert in SCIPnodeAddBoundinfer,
6370 * so don't apply them even if force is set
6371 */
6372 if( SCIPsetIsEQ(scip->set, ub, newbound) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) )
6373 return SCIP_OKAY;
6374
6375 switch( scip->set->stage )
6376 {
6377 case SCIP_STAGE_PROBLEM:
6378 assert(!SCIPvarIsTransformed(var));
6379 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6380 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6381 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6382 scip->branchcand, scip->eventqueue, newbound) );
6383 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) );
6384 break;
6385
6386 case SCIP_STAGE_TRANSFORMING:
6387 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
6388 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
6389 break;
6390
6391 case SCIP_STAGE_PRESOLVING:
6392 if( !SCIPinProbing(scip) )
6393 {
6394 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
6395 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree));
6396
6397 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6398 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6399 SCIP_BOUNDTYPE_UPPER, FALSE) );
6400
6401 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) )
6402 {
6403 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) );
6404 assert(!(*infeasible));
6405 }
6406 break;
6407 }
6408 /*lint -fallthrough*/
6409 case SCIP_STAGE_SOLVING:
6410 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6411 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound,
6412 SCIP_BOUNDTYPE_UPPER, FALSE) );
6413 break;
6414
6415 default:
6416 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
6417 return SCIP_INVALIDCALL;
6418 } /*lint !e788*/
6419
6420 /* coverity: unreachable code */
6421 if( tightened != NULL && ub > SCIPcomputeVarUbGlobal(scip, var) )
6422 *tightened = TRUE;
6423
6424 return SCIP_OKAY;
6425 }
6426
6427 /* some simple variable functions implemented as defines */
6428 #undef SCIPcomputeVarLbGlobal
6429 #undef SCIPcomputeVarUbGlobal
6430 #undef SCIPcomputeVarLbLocal
6431 #undef SCIPcomputeVarUbLocal
6432
6433 /** for a multi-aggregated variable, returns the global lower bound computed by adding the global bounds from all aggregation variables
6434 *
6435 * 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
6436 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbGlobal.
6437 *
6438 * @return the global lower bound computed by adding the global bounds from all aggregation variables
6439 */
6440 SCIP_Real SCIPcomputeVarLbGlobal(
6441 SCIP* scip, /**< SCIP data structure */
6442 SCIP_VAR* var /**< variable to compute the bound for */
6443 )
6444 {
6445 assert(scip != NULL);
6446 assert(var != NULL);
6447
6448 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6449 return SCIPvarGetMultaggrLbGlobal(var, scip->set);
6450 else
6451 return SCIPvarGetLbGlobal(var);
6452 }
6453
6454 /** for a multi-aggregated variable, returns the global upper bound computed by adding the global bounds from all aggregation variables
6455 *
6456 * 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
6457 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbGlobal
6458 *
6459 * @return the global upper bound computed by adding the global bounds from all aggregation variables
6460 */
6461 SCIP_Real SCIPcomputeVarUbGlobal(
6462 SCIP* scip, /**< SCIP data structure */
6463 SCIP_VAR* var /**< variable to compute the bound for */
6464 )
6465 {
6466 assert(scip != NULL);
6467 assert(var != NULL);
6468
6469 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6470 return SCIPvarGetMultaggrUbGlobal(var, scip->set);
6471 else
6472 return SCIPvarGetUbGlobal(var);
6473 }
6474
6475 /** for a multi-aggregated variable, returns the local lower bound computed by adding the local bounds from all aggregation variables
6476 *
6477 * 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
6478 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbLocal.
6479 *
6480 * @return the local lower bound computed by adding the global bounds from all aggregation variables
6481 */
6482 SCIP_Real SCIPcomputeVarLbLocal(
6483 SCIP* scip, /**< SCIP data structure */
6484 SCIP_VAR* var /**< variable to compute the bound for */
6485 )
6486 {
6487 assert(scip != NULL);
6488 assert(var != NULL);
6489
6490 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6491 return SCIPvarGetMultaggrLbLocal(var, scip->set);
6492 else
6493 return SCIPvarGetLbLocal(var);
6494 }
6495
6496 /** for a multi-aggregated variable, returns the local upper bound computed by adding the local bounds from all aggregation variables
6497 *
6498 * 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
6499 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbLocal.
6500 *
6501 * @return the local upper bound computed by adding the global bounds from all aggregation variables
6502 */
6503 SCIP_Real SCIPcomputeVarUbLocal(
6504 SCIP* scip, /**< SCIP data structure */
6505 SCIP_VAR* var /**< variable to compute the bound for */
6506 )
6507 {
6508 assert(scip != NULL);
6509 assert(var != NULL);
6510
6511 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6512 return SCIPvarGetMultaggrUbLocal(var, scip->set);
6513 else
6514 return SCIPvarGetUbLocal(var);
6515 }
6516
6517 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
6518 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
6519 * not updated if bounds of aggregation variables are changing
6520 *
6521 * calling this function for a non-multi-aggregated variable is not allowed
6522 */
6523 SCIP_Real SCIPgetVarMultaggrLbGlobal(
6524 SCIP* scip, /**< SCIP data structure */
6525 SCIP_VAR* var /**< variable to compute the bound for */
6526 )
6527 {
6528 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6529 return SCIPvarGetMultaggrLbGlobal(var, scip->set);
6530 }
6531
6532 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
6533 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
6534 * not updated if bounds of aggregation variables are changing
6535 *
6536 * calling this function for a non-multi-aggregated variable is not allowed
6537 */
6538 SCIP_Real SCIPgetVarMultaggrUbGlobal(
6539 SCIP* scip, /**< SCIP data structure */
6540 SCIP_VAR* var /**< variable to compute the bound for */
6541 )
6542 {
6543 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6544 return SCIPvarGetMultaggrUbGlobal(var, scip->set);
6545 }
6546
6547 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
6548 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
6549 * not updated if bounds of aggregation variables are changing
6550 *
6551 * calling this function for a non-multi-aggregated variable is not allowed
6552 */
6553 SCIP_Real SCIPgetVarMultaggrLbLocal(
6554 SCIP* scip, /**< SCIP data structure */
6555 SCIP_VAR* var /**< variable to compute the bound for */
6556 )
6557 {
6558 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6559 return SCIPvarGetMultaggrLbLocal(var, scip->set);
6560 }
6561
6562 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
6563 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
6564 * not updated if bounds of aggregation variables are changing
6565 *
6566 * calling this function for a non-multi-aggregated variable is not allowed
6567 */
6568 SCIP_Real SCIPgetVarMultaggrUbLocal(
6569 SCIP* scip, /**< SCIP data structure */
6570 SCIP_VAR* var /**< variable to compute the bound for */
6571 )
6572 {
6573 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
6574 return SCIPvarGetMultaggrUbLocal(var, scip->set);
6575 }
6576
6577 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal
6578 * solution or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is
6579 * available
6580 *
6581 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6582 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6583 *
6584 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
6585 */
6586 SCIP_RETCODE SCIPgetVarClosestVlb(
6587 SCIP* scip, /**< SCIP data structure */
6588 SCIP_VAR* var, /**< active problem variable */
6589 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
6590 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
6591 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
6592 )
6593 {
6594 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVlb", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6595
6596 SCIPvarGetClosestVlb(var, sol, scip->set, scip->stat, closestvlb, closestvlbidx);
6597
6598 return SCIP_OKAY;
6599 }
6600
6601 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
6602 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
6603 *
6604 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6605 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6606 *
6607 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING
6608 */
6609 SCIP_RETCODE SCIPgetVarClosestVub(
6610 SCIP* scip, /**< SCIP data structure */
6611 SCIP_VAR* var, /**< active problem variable */
6612 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
6613 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable lower bound */
6614 int* closestvubidx /**< pointer to store the index of the closest variable lower bound */
6615 )
6616 {
6617 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVub", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6618
6619 SCIPvarGetClosestVub(var, sol, scip->set, scip->stat, closestvub, closestvubidx);
6620
6621 return SCIP_OKAY;
6622 }
6623
6624 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
6625 * if z is binary, the corresponding valid implication for z is also added;
6626 * if z is non-continuous and 1/b not too small, the corresponding valid upper/lower bound
6627 * z <= (x-d)/b or z >= (x-d)/b (depending on the sign of of b) is added, too;
6628 * improves the global bounds of the variable and the vlb variable if possible
6629 *
6630 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6631 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6632 *
6633 * @pre This method can be called if @p scip is in one of the following stages:
6634 * - \ref SCIP_STAGE_PRESOLVING
6635 * - \ref SCIP_STAGE_PRESOLVED
6636 * - \ref SCIP_STAGE_SOLVING
6637 */
6638 SCIP_RETCODE SCIPaddVarVlb(
6639 SCIP* scip, /**< SCIP data structure */
6640 SCIP_VAR* var, /**< problem variable */
6641 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
6642 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
6643 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
6644 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
6645 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
6646 )
6647 {
6648 int nlocalbdchgs;
6649
6650 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVlb", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6651
6652 SCIP_CALL( SCIPvarAddVlb(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree,
6653 scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vlbvar, vlbcoef, vlbconstant,
6654 TRUE, infeasible, &nlocalbdchgs) );
6655
6656 *nbdchgs = nlocalbdchgs;
6657
6658 /* 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
6659 * detected infeasibility
6660 */
6661 if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vlbcoef) )
6662 {
6663 if( vlbcoef > 0.0 )
6664 {
6665 /* if b > 0, we have a variable upper bound: x >= b*z + d => z <= (x-d)/b */
6666 SCIP_CALL( SCIPvarAddVub(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6667 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef,
6668 -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) );
6669 }
6670 else
6671 {
6672 /* if b < 0, we have a variable lower bound: x >= b*z + d => z >= (x-d)/b */
6673 SCIP_CALL( SCIPvarAddVlb(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6674 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef,
6675 -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) );
6676 }
6677 *nbdchgs += nlocalbdchgs;
6678 }
6679
6680 return SCIP_OKAY;
6681 }
6682
6683 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
6684 * if z is binary, the corresponding valid implication for z is also added;
6685 * if z is non-continuous and 1/b not too small, the corresponding valid lower/upper bound
6686 * z >= (x-d)/b or z <= (x-d)/b (depending on the sign of of b) is added, too;
6687 * improves the global bounds of the variable and the vlb variable if possible
6688 *
6689 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6690 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6691 *
6692 * @pre This method can be called if @p scip is in one of the following stages:
6693 * - \ref SCIP_STAGE_PRESOLVING
6694 * - \ref SCIP_STAGE_PRESOLVED
6695 * - \ref SCIP_STAGE_SOLVING
6696 */
6697 SCIP_RETCODE SCIPaddVarVub(
6698 SCIP* scip, /**< SCIP data structure */
6699 SCIP_VAR* var, /**< problem variable */
6700 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
6701 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
6702 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
6703 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
6704 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
6705 )
6706 {
6707 int nlocalbdchgs;
6708
6709 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVub", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6710
6711 SCIP_CALL( SCIPvarAddVub(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree,
6712 scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vubvar, vubcoef, vubconstant, TRUE,
6713 infeasible, &nlocalbdchgs) );
6714
6715 *nbdchgs = nlocalbdchgs;
6716
6717 /* 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
6718 * detected infeasibility
6719 */
6720 if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vubcoef) )
6721 {
6722 if( vubcoef > 0.0 )
6723 {
6724 /* if b < 0, we have a variable lower bound: x >= b*z + d => z >= (x-d)/b */
6725 SCIP_CALL( SCIPvarAddVlb(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6726 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef,
6727 -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) );
6728 }
6729 else
6730 {
6731 /* if b > 0, we have a variable upper bound: x >= b*z + d => z <= (x-d)/b */
6732 SCIP_CALL( SCIPvarAddVub(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6733 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef,
6734 -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) );
6735 }
6736 *nbdchgs += nlocalbdchgs;
6737 }
6738
6739 return SCIP_OKAY;
6740 }
6741
6742 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
6743 * also adds the corresponding implication or variable bound to the implied variable;
6744 * if the implication is conflicting, the variable is fixed to the opposite value;
6745 * if the variable is already fixed to the given value, the implication is performed immediately;
6746 * if the implication is redundant with respect to the variables' global bounds, it is ignored
6747 *
6748 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6749 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6750 *
6751 * @pre This method can be called if @p scip is in one of the following stages:
6752 * - \ref SCIP_STAGE_TRANSFORMED
6753 * - \ref SCIP_STAGE_PRESOLVING
6754 * - \ref SCIP_STAGE_PRESOLVED
6755 * - \ref SCIP_STAGE_SOLVING
6756 */
6757 SCIP_RETCODE SCIPaddVarImplication(
6758 SCIP* scip, /**< SCIP data structure */
6759 SCIP_VAR* var, /**< problem variable */
6760 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
6761 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
6762 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER)
6763 * or y >= b (SCIP_BOUNDTYPE_LOWER) */
6764 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
6765 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
6766 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
6767 )
6768 {
6769 SCIP_VAR* implprobvar;
6770
6771 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarImplication", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6772
6773 assert(infeasible != NULL);
6774 *infeasible = FALSE;
6775
6776 if ( nbdchgs != NULL )
6777 *nbdchgs = 0;
6778
6779 if( !SCIPvarIsBinary(var) )
6780 {
6781 SCIPerrorMessage("can't add implication for nonbinary variable\n");
6782 return SCIP_INVALIDDATA;
6783 }
6784
6785 implprobvar = SCIPvarGetProbvar(implvar);
6786 /* transform implication containing two binary variables to a clique; the condition ensures that the active representative
6787 * of implvar is actually binary
6788 */
6789 if( SCIPvarIsBinary(implvar) && (SCIPvarIsActive(implvar) || (implprobvar != NULL && SCIPvarIsBinary(implprobvar))) )
6790 {
6791 assert(SCIPisFeasEQ(scip, implbound, 1.0) || SCIPisFeasZero(scip, implbound));
6792 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPisFeasZero(scip, implbound));
6793
6794 /* only add clique if implication is not redundant with respect to global bounds of the implication variable */
6795 if( (impltype == SCIP_BOUNDTYPE_LOWER && SCIPvarGetLbGlobal(implvar) < 0.5) ||
6796 (impltype == SCIP_BOUNDTYPE_UPPER && SCIPvarGetUbGlobal(implvar) > 0.5) )
6797 {
6798 SCIP_VAR* vars[2];
6799 SCIP_Bool vals[2];
6800
6801 vars[0] = var;
6802 vars[1] = implvar;
6803 vals[0] = varfixing;
6804 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
6805
6806 SCIP_CALL( SCIPaddClique(scip, vars, vals, 2, FALSE, infeasible, nbdchgs) );
6807 }
6808
6809 return SCIP_OKAY;
6810 }
6811
6812 /* the implication graph can only handle 'real' binary (SCIP_VARTYPE_BINARY) variables, therefore we transform the
6813 * implication in variable bounds, (lowerbound of y will be abbreviated by lby, upperbound equivlaent) the follwing
6814 * four cases are:
6815 *
6816 * 1. (x >= 1 => y >= b) => y >= (b - lby) * x + lby
6817 * 2. (x >= 1 => y <= b) => y <= (b - uby) * x + uby
6818 * 3. (x <= 0 => y >= b) => y >= (lby - b) * x + b
6819 * 4. (x <= 0 => y <= b) => y <= (uby - b) * x + b
6820 */
6821 if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
6822 {
6823 SCIP_Real lby;
6824 SCIP_Real uby;
6825
6826 lby = SCIPvarGetLbGlobal(implvar);
6827 uby = SCIPvarGetUbGlobal(implvar);
6828
6829 if( varfixing == TRUE )
6830 {
6831 if( impltype == SCIP_BOUNDTYPE_LOWER )
6832 {
6833 /* we return if the lower bound is infinity */
6834 if( SCIPisInfinity(scip, -lby) )
6835 return SCIP_OKAY;
6836
6837 SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6838 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6839 implbound - lby, lby, TRUE, infeasible, nbdchgs) );
6840 }
6841 else
6842 {
6843 /* we return if the upper bound is infinity */
6844 if( SCIPisInfinity(scip, uby) )
6845 return SCIP_OKAY;
6846
6847 SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6848 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6849 implbound - uby, uby, TRUE, infeasible, nbdchgs) );
6850 }
6851 }
6852 else
6853 {
6854 if( impltype == SCIP_BOUNDTYPE_LOWER )
6855 {
6856 /* we return if the lower bound is infinity */
6857 if( SCIPisInfinity(scip, -lby) )
6858 return SCIP_OKAY;
6859
6860 SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6861 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6862 lby - implbound, implbound, TRUE, infeasible, nbdchgs) );
6863 }
6864 else
6865 {
6866 /* we return if the upper bound is infinity */
6867 if( SCIPisInfinity(scip, uby) )
6868 return SCIP_OKAY;
6869
6870 SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6871 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var,
6872 uby - implbound, implbound, TRUE, infeasible, nbdchgs) );
6873 }
6874 }
6875 }
6876 else
6877 {
6878 SCIP_CALL( SCIPvarAddImplic(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
6879 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, varfixing, implvar, impltype,
6880 implbound, TRUE, infeasible, nbdchgs) );
6881 }
6882
6883 return SCIP_OKAY;
6884 }
6885
6886 /** adds a clique information to SCIP, stating that at most one of the given binary variables can be set to 1;
6887 * if a variable appears twice in the same clique, the corresponding implications are performed
6888 *
6889 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
6890 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
6891 *
6892 * @pre This method can be called if @p scip is in one of the following stages:
6893 * - \ref SCIP_STAGE_TRANSFORMED
6894 * - \ref SCIP_STAGE_PRESOLVING
6895 * - \ref SCIP_STAGE_PRESOLVED
6896 * - \ref SCIP_STAGE_SOLVING
6897 */
6898 SCIP_RETCODE SCIPaddClique(
6899 SCIP* scip, /**< SCIP data structure */
6900 SCIP_VAR** vars, /**< binary variables in the clique from which at most one can be set to 1 */
6901 SCIP_Bool* values, /**< values of the variables in the clique; NULL to use TRUE for all vars */
6902 int nvars, /**< number of variables in the clique */
6903 SCIP_Bool isequation, /**< is the clique an equation or an inequality? */
6904 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
6905 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
6906 )
6907 {
6908 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddClique", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
6909
6910 *infeasible = FALSE;
6911 if( nbdchgs != NULL )
6912 *nbdchgs = 0;
6913
6914 if( nvars > 1 )
6915 {
6916 /* add the clique to the clique table */
6917 SCIP_CALL( SCIPcliquetableAdd(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
6918 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, vars, values, nvars, isequation,
6919 infeasible, nbdchgs) );
6920 }
6921
6922 return SCIP_OKAY;
6923 }
6924
6925 /** relabels the given labels in-place in an increasing fashion: the first seen label is 0, the next label 1, etc...
6926 *
6927 * @note every label equal to -1 is treated as a previously unseen, unique label and gets a new ordered label.
6928 */
6929 static
6930 SCIP_RETCODE relabelOrderConsistent(
6931 SCIP*const scip, /**< SCIP data structure */
6932 int* labels, /**< current labels that will be overwritten */
6933 int const nlabels, /**< number of variables in the clique */
6934 int* nclasses /**< pointer to store the total number of distinct labels */
6935 )
6936 {
6937 SCIP_HASHMAP* classidx2newlabel;
6938
6939 int classidx;
6940 int i;
6941
6942 SCIP_CALL( SCIPhashmapCreate(&classidx2newlabel, SCIPblkmem(scip), nlabels) );
6943
6944 classidx = 0;
6945
6946 /* loop over labels to create local class indices that obey the variable order */
6947 for( i = 0; i < nlabels; ++i )
6948 {
6949 int currentlabel = labels[i];
6950 int localclassidx;
6951
6952 /* labels equal to -1 are stored as singleton classes */
6953 if( currentlabel == -1 )
6954 {
6955 ++classidx;
6956 localclassidx = classidx;
6957 }
6958 else
6959 {
6960 assert(currentlabel >= 0);
6961 /* look up the class index image in the hash map; if it is not stored yet, new class index is created and stored */
6962 if( !SCIPhashmapExists(classidx2newlabel, (void*)(size_t)currentlabel) )
6963 {
6964 ++classidx;
6965 localclassidx = classidx;
6966 SCIP_CALL( SCIPhashmapInsertInt(classidx2newlabel, (void*)(size_t)currentlabel, classidx) ); /*lint !e571*/
6967 }
6968 else
6969 {
6970 localclassidx = SCIPhashmapGetImageInt(classidx2newlabel, (void*)(size_t)currentlabel); /*lint !e571*/
6971 }
6972 }
6973 assert(localclassidx - 1 >= 0);
6974 assert(localclassidx - 1 <= i);
6975
6976 /* indices start with zero, but we have an offset of 1 because we cannot store 0 in a hashmap */
6977 labels[i] = localclassidx - 1;
6978 }
6979
6980 assert(classidx > 0);
6981 assert(classidx <= nlabels);
6982 *nclasses = classidx;
6983
6984 SCIPhashmapFree(&classidx2newlabel);
6985
6986 return SCIP_OKAY;
6987 }
6988
6989 /** sort the variables w.r.t. the given labels; thereby ensure the current order of the variables with the same label. */
6990 static
6991 SCIP_RETCODE labelSortStable(
6992 SCIP* scip, /**< SCIP data structure */
6993 SCIP_VAR** vars, /**< variable array */
6994 int* classlabels, /**< array that contains a class label for every variable */
6995 SCIP_VAR** sortedvars, /**< array to store variables after stable sorting */
6996 int* sortedindices, /**< array to store indices of sorted variables in the original vars array */
6997 int* classesstartposs, /**< starting position array for each label class (must have size nclasses + 1) */
6998 int nvars, /**< size of the vars arrays */
6999 int nclasses /**< number of label classes */
7000 )
7001 {
7002 SCIP_VAR*** varpointers;
7003 int** indexpointers;
7004 int* classcount;
7005
7006 int nextpos;
7007 int c;
7008 int v;
7009
7010 assert(scip != NULL);
7011 assert(vars != NULL);
7012 assert(sortedindices != NULL);
7013 assert(classesstartposs != NULL);
7014
7015 assert(nvars == 0 || vars != NULL);
7016
7017 if( nvars == 0 )
7018 return SCIP_OKAY;
7019
7020 assert(classlabels != NULL);
7021 assert(nclasses > 0);
7022
7023 /* we first count all class cardinalities and allocate temporary memory for a bucket sort */
7024 SCIP_CALL( SCIPallocBufferArray(scip, &classcount, nclasses) );
7025 BMSclearMemoryArray(classcount, nclasses);
7026
7027 /* first we count for each class the number of elements */
7028 for( v = nvars - 1; v >= 0; --v )
7029 {
7030 assert(0 <= classlabels[v] && classlabels[v] < nclasses);
7031 ++(classcount[classlabels[v]]);
7032 }
7033
7034 #ifndef NDEBUG
7035 BMSclearMemoryArray(sortedvars, nvars);
7036 BMSclearMemoryArray(sortedindices, nvars);
7037 #endif
7038 SCIP_CALL( SCIPallocBufferArray(scip, &varpointers, nclasses) );
7039 SCIP_CALL( SCIPallocBufferArray(scip, &indexpointers, nclasses) );
7040
7041 nextpos = 0;
7042 /* now we initialize all start pointers for each class, so they will be ordered */
7043 for( c = 0; c < nclasses; ++c )
7044 {
7045 /* to reach the goal that all variables of each class will be standing next to each other we will initialize the
7046 * starting pointers for each class by adding the cardinality of each class to the last class starting pointer
7047 * e.g. class1 has 4 elements and class2 has 3 elements then the starting pointer for class1 will be the pointer
7048 * to sortedvars[0], the starting pointer to class2 will be the pointer to sortedvars[4] and to class3 it will be
7049 * the pointer to sortedvars[7]
7050 */
7051 varpointers[c] = (SCIP_VAR**) (sortedvars + nextpos);
7052 indexpointers[c] = (int*) (sortedindices + nextpos);
7053 classesstartposs[c] = nextpos;
7054 assert(classcount[c] > 0);
7055 nextpos += classcount[c];
7056 assert(nextpos > 0);
7057 }
7058 assert(nextpos == nvars);
7059 classesstartposs[c] = nextpos;
7060
7061 /* now we copy all variables to the right order */
7062 for( v = 0; v < nvars; ++v )
7063 {
7064 /* copy variable itself to the right position */
7065 *(varpointers[classlabels[v]]) = vars[v]; /*lint !e613*/
7066 ++(varpointers[classlabels[v]]);
7067
7068 /* copy index */
7069 *(indexpointers[classlabels[v]]) = v;
7070 ++(indexpointers[classlabels[v]]);
7071 }
7072
7073 /* in debug mode, we ensure the correctness of the mapping */
7074 #ifndef NDEBUG
7075 for( v = 0; v < nvars; ++v )
7076 {
7077 assert(sortedvars[v] != NULL);
7078 assert(sortedindices[v] >= 0);
7079
7080 /* assert that the sorted indices map back to the correct variable in the original order */
7081 assert(vars[sortedindices[v]] == sortedvars[v]);
7082 }
7083 #endif
7084
7085 /* free temporary memory */
7086 SCIPfreeBufferArray(scip, &indexpointers);
7087 SCIPfreeBufferArray(scip, &varpointers);
7088 SCIPfreeBufferArray(scip, &classcount);
7089
7090 return SCIP_OKAY;
7091 }
7092
7093
7094 /* calculate clique partition for a maximal amount of comparisons on variables due to expensive algorithm
7095 * @todo: check for a good value, maybe it's better to check parts of variables
7096 */
7097 #define MAXNCLIQUEVARSCOMP 1000000
7098
7099 /** calculates a partition of the given set of binary variables into cliques;
7100 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7101 * were assigned to the same clique;
7102 * the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of
7103 * the preceding variables was assigned to clique i-1;
7104 * for each clique at most 1 variables can be set to TRUE in a feasible solution;
7105 *
7106 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7107 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7108 *
7109 * @pre This method can be called if @p scip is in one of the following stages:
7110 * - \ref SCIP_STAGE_INITPRESOLVE
7111 * - \ref SCIP_STAGE_PRESOLVING
7112 * - \ref SCIP_STAGE_EXITPRESOLVE
7113 * - \ref SCIP_STAGE_PRESOLVED
7114 * - \ref SCIP_STAGE_SOLVING
7115 */
7116 static
7117 SCIP_RETCODE calcCliquePartitionGreedy(
7118 SCIP*const scip, /**< SCIP data structure */
7119 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */
7120 SCIP_Bool*const values, /**< clique value (TRUE or FALSE) for each variable in the clique */
7121 int const nvars, /**< number of variables in the array */
7122 int*const cliquepartition, /**< array of length nvars to store the clique partition */
7123 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */
7124 )
7125 {
7126 SCIP_VAR** cliquevars;
7127 SCIP_Bool* cliquevalues;
7128 int i;
7129 int maxncliquevarscomp;
7130 int ncliquevars;
7131
7132 /* allocate temporary memory for storing the variables of the current clique */
7133 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevars, nvars) );
7134 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevalues, nvars) );
7135
7136 /* initialize the cliquepartition array with -1 */
7137 for( i = nvars - 1; i >= 0; --i )
7138 cliquepartition[i] = -1;
7139
7140 maxncliquevarscomp = (int) MIN(nvars * (SCIP_Longint)nvars, MAXNCLIQUEVARSCOMP);
7141 /* calculate the clique partition */
7142 *ncliques = 0;
7143 for( i = 0; i < nvars; ++i )
7144 {
7145 if( cliquepartition[i] == -1 )
7146 {
7147 int j;
7148
7149 /* variable starts a new clique */
7150 cliquepartition[i] = *ncliques;
7151 cliquevars[0] = vars[i];
7152 cliquevalues[0] = values[i];
7153 ncliquevars = 1;
7154
7155 /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */
7156 if( SCIPvarIsActive(vars[i]) && SCIPvarGetNCliques(vars[i], values[i]) > 0 )
7157 {
7158 /* greedily fill up the clique */
7159 for( j = i+1; j < nvars; ++j )
7160 {
7161 /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */
7162 if( cliquepartition[j] == -1 && SCIPvarIsActive(vars[j]) )
7163 {
7164 int k;
7165
7166 /* check if every variable in the current clique can be extended by tmpvars[j] */
7167 for( k = ncliquevars - 1; k >= 0; --k )
7168 {
7169 if( !SCIPvarsHaveCommonClique(vars[j], values[j], cliquevars[k], cliquevalues[k], FALSE) )
7170 break;
7171 }
7172
7173 if( k == -1 )
7174 {
7175 /* put the variable into the same clique */
7176 cliquepartition[j] = cliquepartition[i];
7177 cliquevars[ncliquevars] = vars[j];
7178 cliquevalues[ncliquevars] = values[j];
7179 ++ncliquevars;
7180 }
7181 }
7182 }
7183 }
7184
7185 /* this clique is finished */
7186 ++(*ncliques);
7187 }
7188 assert(cliquepartition[i] >= 0 && cliquepartition[i] < i+1);
7189
7190 /* break if we reached the maximal number of comparisons */
7191 if( i * nvars > maxncliquevarscomp )
7192 break;
7193 }
7194 /* if we had to many variables fill up the cliquepartition and put each variable in a separate clique */
7195 for( ; i < nvars; ++i )
7196 {
7197 if( cliquepartition[i] == -1 )
7198 {
7199 cliquepartition[i] = *ncliques;
7200 ++(*ncliques);
7201 }
7202 }
7203
7204 SCIPsetFreeBufferArray(scip->set, &cliquevalues);
7205 SCIPsetFreeBufferArray(scip->set, &cliquevars);
7206
7207 return SCIP_OKAY;
7208 }
7209
7210 /** calculates a partition of the given set of binary variables into cliques; takes into account independent clique components
7211 *
7212 * The algorithm performs the following steps:
7213 * - recomputes connected components of the clique table, if necessary
7214 * - computes a clique partition for every connected component greedily.
7215 * - relabels the resulting clique partition such that it satisfies the description below
7216 *
7217 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7218 * were assigned to the same clique;
7219 * the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of
7220 * the preceding variables was assigned to clique i-1;
7221 * for each clique at most 1 variables can be set to TRUE in a feasible solution;
7222 *
7223 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7224 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7225 *
7226 * @pre This method can be called if @p scip is in one of the following stages:
7227 * - \ref SCIP_STAGE_INITPRESOLVE
7228 * - \ref SCIP_STAGE_PRESOLVING
7229 * - \ref SCIP_STAGE_EXITPRESOLVE
7230 * - \ref SCIP_STAGE_PRESOLVED
7231 * - \ref SCIP_STAGE_SOLVING
7232 */
7233 SCIP_RETCODE SCIPcalcCliquePartition(
7234 SCIP*const scip, /**< SCIP data structure */
7235 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */
7236 int const nvars, /**< number of variables in the clique */
7237 int*const cliquepartition, /**< array of length nvars to store the clique partition */
7238 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */
7239 )
7240 {
7241 SCIP_VAR** tmpvars;
7242
7243 SCIP_VAR** sortedtmpvars;
7244 SCIP_Bool* tmpvalues;
7245 SCIP_Bool* sortedtmpvalues;
7246 int* componentlabels;
7247 int* sortedindices;
7248 int* componentstartposs;
7249 int i;
7250 int c;
7251
7252 int ncomponents;
7253
7254 assert(scip != NULL);
7255 assert(nvars == 0 || vars != NULL);
7256 assert(nvars == 0 || cliquepartition != NULL);
7257 assert(ncliques != NULL);
7258
7259 SCIP_CALL( SCIPcheckStage(scip, "SCIPcalcCliquePartition", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7260
7261 if( nvars == 0 )
7262 {
7263 *ncliques = 0;
7264 return SCIP_OKAY;
7265 }
7266
7267 /* early abort if no cliques are present */
7268 if( SCIPgetNCliques(scip) == 0 )
7269 {
7270 for( i = 0; i < nvars; ++i )
7271 cliquepartition[i] = i;
7272
7273 *ncliques = nvars;
7274
7275 return SCIP_OKAY;
7276 }
7277
7278 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &tmpvalues, nvars) );
7279 SCIP_CALL( SCIPsetDuplicateBufferArray(scip->set, &tmpvars, vars, nvars) );
7280 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentlabels, nvars) );
7281 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedindices, nvars) );
7282
7283 /* initialize the tmpvalues array */
7284 for( i = nvars - 1; i >= 0; --i )
7285 {
7286 tmpvalues[i] = TRUE;
7287 cliquepartition[i] = -1;
7288 }
7289
7290 /* get corresponding active problem variables */
7291 SCIP_CALL( SCIPvarsGetProbvarBinary(&tmpvars, &tmpvalues, nvars) );
7292
7293 ncomponents = -1;
7294
7295 /* update clique components if necessary */
7296 if( SCIPcliquetableNeedsComponentUpdate(scip->cliquetable) )
7297 {
7298 SCIP_VAR** allvars;
7299 int nallbinvars;
7300 int nallintvars;
7301 int nallimplvars;
7302
7303 SCIP_CALL( SCIPgetVarsData(scip, &allvars, NULL, &nallbinvars, &nallintvars, &nallimplvars, NULL) );
7304
7305 SCIP_CALL( SCIPcliquetableComputeCliqueComponents(scip->cliquetable, scip->set, SCIPblkmem(scip), allvars, nallbinvars, nallintvars, nallimplvars) );
7306 }
7307
7308 assert(!SCIPcliquetableNeedsComponentUpdate(scip->cliquetable));
7309
7310 /* store the global clique component labels */
7311 for( i = 0; i < nvars; ++i )
7312 {
7313 if( SCIPvarIsActive(tmpvars[i]) )
7314 componentlabels[i] = SCIPcliquetableGetVarComponentIdx(scip->cliquetable, tmpvars[i]);
7315 else
7316 componentlabels[i] = -1;
7317 }
7318
7319 /* relabel component labels order consistent as prerequisite for a stable sort */
7320 SCIP_CALL( relabelOrderConsistent(scip, componentlabels, nvars, &ncomponents) );
7321 assert(ncomponents >= 1);
7322 assert(ncomponents <= nvars);
7323
7324 /* allocate storage array for the starting positions of the components */
7325 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentstartposs, ncomponents + 1) );
7326
7327 /* stable sort the variables w.r.t. the component labels so that we can restrict the quadratic algorithm to the components */
7328 if( ncomponents > 1 )
7329 {
7330 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvars, nvars) );
7331 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvalues, nvars) );
7332 SCIP_CALL( labelSortStable(scip, tmpvars, componentlabels, sortedtmpvars, sortedindices, componentstartposs, nvars, ncomponents) );
7333
7334 /* reassign the tmpvalues with respect to the sorting */
7335 for( i = 0; i < nvars; ++i )
7336 {
7337 assert(tmpvars[sortedindices[i]] == sortedtmpvars[i]);
7338 sortedtmpvalues[i] = tmpvalues[sortedindices[i]];
7339 }
7340 }
7341 else
7342 {
7343 /* if we have only one large connected component, skip the stable sorting and prepare the data differently */
7344 sortedtmpvars = tmpvars;
7345 sortedtmpvalues = tmpvalues;
7346 componentstartposs[0] = 0;
7347 componentstartposs[1] = nvars;
7348
7349 /* sorted indices are the identity */
7350 for( i = 0; i < nvars; ++i )
7351 sortedindices[i] = i;
7352 }
7353
7354 *ncliques = 0;
7355 /* calculate a greedy clique partition for each connected component */
7356 for( c = 0; c < ncomponents; ++c )
7357 {
7358 int* localcliquepartition;
7359 int nlocalcliques;
7360 int ncomponentvars;
7361 int l;
7362
7363 /* extract the number of variables in this connected component */
7364 ncomponentvars = componentstartposs[c + 1] - componentstartposs[c];
7365 nlocalcliques = 0;
7366
7367 /* allocate necessary memory to hold the intermediate component clique partition */
7368 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &localcliquepartition, ncomponentvars) );
7369
7370 /* call greedy clique algorithm for all component variables */
7371 SCIP_CALL( calcCliquePartitionGreedy(scip, &(sortedtmpvars[componentstartposs[c]]), &(sortedtmpvalues[componentstartposs[c]]),
7372 ncomponentvars, localcliquepartition, &nlocalcliques) );
7373
7374 assert(nlocalcliques >= 1);
7375 assert(nlocalcliques <= ncomponentvars);
7376
7377 /* store the obtained clique partition with an offset of ncliques for the original variables */
7378 for( l = componentstartposs[c]; l < componentstartposs[c + 1]; ++l )
7379 {
7380 int origvaridx = sortedindices[l];
7381 assert(cliquepartition[origvaridx] == -1);
7382 assert(localcliquepartition[l - componentstartposs[c]] <= l - componentstartposs[c]);
7383 cliquepartition[origvaridx] = localcliquepartition[l - componentstartposs[c]] + (*ncliques);
7384 }
7385 *ncliques += nlocalcliques;
7386
7387 /* free the local clique partition */
7388 SCIPsetFreeBufferArray(scip->set, &localcliquepartition);
7389 }
7390
7391 /* except in the two trivial cases, we have to ensure the order consistency of the partition indices */
7392 if( ncomponents > 1 && ncomponents < nvars )
7393 {
7394 int partitionsize;
7395 SCIP_CALL( relabelOrderConsistent(scip, cliquepartition, nvars, &partitionsize) );
7396
7397 assert(partitionsize == *ncliques);
7398 }
7399
7400 if( ncomponents > 1 )
7401 {
7402 SCIPsetFreeBufferArray(scip->set, &sortedtmpvalues);
7403 SCIPsetFreeBufferArray(scip->set, &sortedtmpvars);
7404 }
7405
7406 /* use the greedy algorithm as a whole to verify the result on small number of variables */
7407 #ifdef SCIP_DISABLED_CODE
7408 {
7409 int* debugcliquepartition;
7410 int ndebugcliques;
7411
7412 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &debugcliquepartition, nvars) );
7413
7414 /* call greedy clique algorithm for all component variables */
7415 SCIP_CALL( calcCliquePartitionGreedy(scip, tmpvars, tmpvalues, nvars, debugcliquepartition, &ndebugcliques) );
7416
7417 /* loop and compare the traditional greedy clique with */
7418 for( i = 0; i < nvars; ++i )
7419 assert(i * nvars > MAXNCLIQUEVARSCOMP || cliquepartition[i] == debugcliquepartition[i]);
7420
7421 SCIPsetFreeBufferArray(scip->set, &debugcliquepartition);
7422 }
7423 #endif
7424
7425 /* free temporary memory */
7426 SCIPsetFreeBufferArray(scip->set, &componentstartposs);
7427 SCIPsetFreeBufferArray(scip->set, &sortedindices);
7428 SCIPsetFreeBufferArray(scip->set, &componentlabels);
7429 SCIPsetFreeBufferArray(scip->set, &tmpvars);
7430 SCIPsetFreeBufferArray(scip->set, &tmpvalues);
7431
7432 return SCIP_OKAY;
7433 }
7434
7435 /** calculates a partition of the given set of binary variables into negated cliques;
7436 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they
7437 * were assigned to the same negated clique;
7438 * the first variable is always assigned to clique 0 and a variable can only be assigned to clique i if at least one of
7439 * the preceding variables was assigned to clique i-1;
7440 * for each clique with n_c variables at least n_c-1 variables can be set to TRUE in a feasible solution;
7441 *
7442 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7443 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7444 *
7445 * @pre This method can be called if @p scip is in one of the following stages:
7446 * - \ref SCIP_STAGE_INITPRESOLVE
7447 * - \ref SCIP_STAGE_PRESOLVING
7448 * - \ref SCIP_STAGE_EXITPRESOLVE
7449 * - \ref SCIP_STAGE_PRESOLVED
7450 * - \ref SCIP_STAGE_SOLVING
7451 */
7452 SCIP_RETCODE SCIPcalcNegatedCliquePartition(
7453 SCIP*const scip, /**< SCIP data structure */
7454 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */
7455 int const nvars, /**< number of variables in the clique */
7456 int*const cliquepartition, /**< array of length nvars to store the clique partition */
7457 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */
7458 )
7459 {
7460 SCIP_VAR** negvars;
7461 int v;
7462
7463 assert(scip != NULL);
7464 assert(cliquepartition != NULL || nvars == 0);
7465 assert(ncliques != NULL);
7466
7467 if( nvars == 0 )
7468 {
7469 *ncliques = 0;
7470 return SCIP_OKAY;
7471 }
7472 assert(vars != NULL);
7473
7474 /* allocate temporary memory */
7475 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &negvars, nvars) );
7476
7477 /* get all negated variables */
7478 for( v = nvars - 1; v >= 0; --v )
7479 {
7480 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &(negvars[v])) );
7481 }
7482
7483 /* calculate cliques on negated variables, which are "negated" cliques on normal variables array */
7484 SCIP_CALL( SCIPcalcCliquePartition( scip, negvars, nvars, cliquepartition, ncliques) );
7485
7486 /* free temporary memory */
7487 SCIPsetFreeBufferArray(scip->set, &negvars);
7488
7489 return SCIP_OKAY;
7490 }
7491
7492
7493 /** force SCIP to clean up all cliques; cliques do not get automatically cleaned up after presolving. Use
7494 * this method to prevent inactive variables in cliques when retrieved via SCIPgetCliques()
7495 *
7496 * @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed
7497 *
7498 * @pre This method can be called if @p scip is in one of the following stages:
7499 * - \ref SCIP_STAGE_TRANSFORMED
7500 * - \ref SCIP_STAGE_INITPRESOLVE
7501 * - \ref SCIP_STAGE_PRESOLVING
7502 * - \ref SCIP_STAGE_EXITPRESOLVE
7503 * - \ref SCIP_STAGE_PRESOLVED
7504 * - \ref SCIP_STAGE_INITSOLVE
7505 * - \ref SCIP_STAGE_SOLVING
7506 * - \ref SCIP_STAGE_SOLVED
7507 * - \ref SCIP_STAGE_EXITSOLVE
7508 */
7509 SCIP_RETCODE SCIPcleanupCliques(
7510 SCIP* scip, /**< SCIP data structure */
7511 SCIP_Bool* infeasible /**< pointer to store if cleanup detected infeasibility */
7512 )
7513 {
7514 int nlocalbdchgs;
7515 SCIP_Bool globalinfeasibility;
7516
7517 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcleanupCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7518
7519 globalinfeasibility = FALSE;
7520 nlocalbdchgs = 0;
7521 SCIP_CALL( SCIPcliquetableCleanup(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob,
7522 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, &nlocalbdchgs,
7523 &globalinfeasibility) );
7524
7525 if( infeasible != NULL )
7526 *infeasible = globalinfeasibility;
7527
7528 if( globalinfeasibility )
7529 scip->stat->status = SCIP_STATUS_INFEASIBLE;
7530
7531 return SCIP_OKAY;
7532 }
7533
7534 /** gets the number of cliques in the clique table
7535 *
7536 * @return number of cliques in the clique table
7537 *
7538 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7539 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7540 *
7541 * @pre This method can be called if @p scip is in one of the following stages:
7542 * - \ref SCIP_STAGE_TRANSFORMED
7543 * - \ref SCIP_STAGE_INITPRESOLVE
7544 * - \ref SCIP_STAGE_PRESOLVING
7545 * - \ref SCIP_STAGE_EXITPRESOLVE
7546 * - \ref SCIP_STAGE_PRESOLVED
7547 * - \ref SCIP_STAGE_INITSOLVE
7548 * - \ref SCIP_STAGE_SOLVING
7549 * - \ref SCIP_STAGE_SOLVED
7550 * - \ref SCIP_STAGE_EXITSOLVE
7551 */
7552 int SCIPgetNCliques(
7553 SCIP* scip /**< SCIP data structure */
7554 )
7555 {
7556 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7557
7558 return SCIPcliquetableGetNCliques(scip->cliquetable);
7559 }
7560
7561 /** gets the number of cliques created so far by the cliquetable
7562 *
7563 * @return number of cliques created so far by the cliquetable
7564 *
7565 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7566 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7567 *
7568 * @pre This method can be called if @p scip is in one of the following stages:
7569 * - \ref SCIP_STAGE_TRANSFORMED
7570 * - \ref SCIP_STAGE_INITPRESOLVE
7571 * - \ref SCIP_STAGE_PRESOLVING
7572 * - \ref SCIP_STAGE_EXITPRESOLVE
7573 * - \ref SCIP_STAGE_PRESOLVED
7574 * - \ref SCIP_STAGE_INITSOLVE
7575 * - \ref SCIP_STAGE_SOLVING
7576 * - \ref SCIP_STAGE_SOLVED
7577 * - \ref SCIP_STAGE_EXITSOLVE
7578 */
7579 int SCIPgetNCliquesCreated(
7580 SCIP* scip /**< SCIP data structure */
7581 )
7582 {
7583 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliquesCreated", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7584
7585 return SCIPcliquetableGetNCliquesCreated(scip->cliquetable);
7586 }
7587
7588 /** gets the array of cliques in the clique table
7589 *
7590 * @return array of cliques in the clique table
7591 *
7592 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques()
7593 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques
7594 *
7595 * @pre This method can be called if @p scip is in one of the following stages:
7596 * - \ref SCIP_STAGE_TRANSFORMED
7597 * - \ref SCIP_STAGE_INITPRESOLVE
7598 * - \ref SCIP_STAGE_PRESOLVING
7599 * - \ref SCIP_STAGE_EXITPRESOLVE
7600 * - \ref SCIP_STAGE_PRESOLVED
7601 * - \ref SCIP_STAGE_INITSOLVE
7602 * - \ref SCIP_STAGE_SOLVING
7603 * - \ref SCIP_STAGE_SOLVED
7604 * - \ref SCIP_STAGE_EXITSOLVE
7605 */
7606 SCIP_CLIQUE** SCIPgetCliques(
7607 SCIP* scip /**< SCIP data structure */
7608 )
7609 {
7610 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7611
7612 return SCIPcliquetableGetCliques(scip->cliquetable);
7613 }
7614
7615 /** returns whether there is a clique that contains both given variable/value pairs;
7616 * the variables must be active binary variables;
7617 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
7618 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
7619 *
7620 * @return TRUE, if there is a clique that contains both variable/clique pairs; FALSE, otherwise
7621 *
7622 * @pre This method can be called if @p scip is in one of the following stages:
7623 * - \ref SCIP_STAGE_TRANSFORMED
7624 * - \ref SCIP_STAGE_INITPRESOLVE
7625 * - \ref SCIP_STAGE_PRESOLVING
7626 * - \ref SCIP_STAGE_EXITPRESOLVE
7627 * - \ref SCIP_STAGE_PRESOLVED
7628 * - \ref SCIP_STAGE_INITSOLVE
7629 * - \ref SCIP_STAGE_SOLVING
7630 * - \ref SCIP_STAGE_SOLVED
7631 * - \ref SCIP_STAGE_EXITSOLVE
7632 *
7633 * @note a variable with it's negated variable are NOT! in a clique
7634 * @note a variable with itself are in a clique
7635 */
7636 SCIP_Bool SCIPhaveVarsCommonClique(
7637 SCIP* scip, /**< SCIP data structure */
7638 SCIP_VAR* var1, /**< first variable */
7639 SCIP_Bool value1, /**< value of first variable */
7640 SCIP_VAR* var2, /**< second variable */
7641 SCIP_Bool value2, /**< value of second variable */
7642 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
7643 )
7644 {
7645 assert(scip != NULL);
7646 assert(var1 != NULL);
7647 assert(var2 != NULL);
7648 assert(SCIPvarIsActive(var1));
7649 assert(SCIPvarIsActive(var2));
7650 assert(SCIPvarIsBinary(var1));
7651 assert(SCIPvarIsBinary(var2));
7652
7653 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPhaveVarsCommonClique", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7654
7655 /* if both variables together have more cliques then actual cliques exist, then they have a common clique (in debug
7656 * mode we check this for correctness), otherwise we need to call the pairwise comparison method for these variables
7657 */
7658 #ifndef NDEBUG
7659 assert((SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable)) ? SCIPvarsHaveCommonClique(var1, value1, var2, value2, FALSE) : TRUE);
7660 #endif
7661
7662 return (SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable)
7663 || SCIPvarsHaveCommonClique(var1, value1, var2, value2, regardimplics));
7664 }
7665
7666 /** writes the clique graph to a gml file
7667 *
7668 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7669 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7670 *
7671 * @pre This method can be called if @p scip is in one of the following stages:
7672 * - \ref SCIP_STAGE_TRANSFORMED
7673 * - \ref SCIP_STAGE_INITPRESOLVE
7674 * - \ref SCIP_STAGE_PRESOLVING
7675 * - \ref SCIP_STAGE_EXITPRESOLVE
7676 * - \ref SCIP_STAGE_PRESOLVED
7677 * - \ref SCIP_STAGE_INITSOLVE
7678 * - \ref SCIP_STAGE_SOLVING
7679 * - \ref SCIP_STAGE_SOLVED
7680 * - \ref SCIP_STAGE_EXITSOLVE
7681 *
7682 * @note there can be duplicated arcs in the output file
7683 *
7684 * If @p writenodeweights is true, only nodes corresponding to variables that have a fractional value and only edges
7685 * between such nodes are written.
7686 */
7687 SCIP_RETCODE SCIPwriteCliqueGraph(
7688 SCIP* scip, /**< SCIP data structure */
7689 const char* fname, /**< name of file */
7690 SCIP_Bool writenodeweights /**< should we write weights of nodes? */
7691 )
7692 {
7693 FILE* gmlfile;
7694 SCIP_HASHMAP* nodehashmap;
7695 SCIP_CLIQUE** cliques;
7696 SCIP_VAR** clqvars;
7697 SCIP_VAR** allvars;
7698 SCIP_Bool* clqvalues;
7699 char nodename[SCIP_MAXSTRLEN];
7700 int nallvars;
7701 int nbinvars;
7702 int nintvars;
7703 int nimplvars;
7704 int ncliques;
7705 int c;
7706 int v1;
7707 int v2;
7708 int id1;
7709 int id2;
7710
7711 assert(scip != NULL);
7712 assert(fname != NULL);
7713
7714 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPwriteCliqueGraph", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7715
7716 /* get all active variables */
7717 SCIP_CALL( SCIPgetVarsData(scip, &allvars, &nallvars, &nbinvars, &nintvars, &nimplvars, NULL) );
7718
7719 /* no possible variables for cliques exist */
7720 if( nbinvars + nimplvars == 0 )
7721 return SCIP_OKAY;
7722
7723 ncliques = SCIPgetNCliques(scip);
7724
7725 /* no cliques and do not wont to check for binary implications */
7726 if( ncliques == 0 )
7727 return SCIP_OKAY;
7728
7729 /* open gml file */
7730 gmlfile = fopen(fname, "w");
7731
7732 if( gmlfile == NULL )
7733 {
7734 SCIPerrorMessage("cannot open graph file <%s>\n", fname);
7735 SCIPABORT();
7736 return SCIP_INVALIDDATA; /*lint !e527*/
7737 }
7738
7739 /* create the hash map */
7740 SCIP_CALL_FINALLY( SCIPhashmapCreate(&nodehashmap, SCIPblkmem(scip), nbinvars+nimplvars), fclose(gmlfile) );
7741
7742 /* write starting of gml file */
7743 SCIPgmlWriteOpening(gmlfile, TRUE);
7744
7745 cliques = SCIPgetCliques(scip);
7746
7747 /* write nodes and arcs for all cliques */
7748 for( c = ncliques - 1; c >= 0; --c )
7749 {
7750 clqvalues = SCIPcliqueGetValues(cliques[c]);
7751 clqvars = SCIPcliqueGetVars(cliques[c]);
7752
7753 for( v1 = SCIPcliqueGetNVars(cliques[c]) - 1; v1 >= 0; --v1 )
7754 {
7755 id1 = clqvalues[v1] ? SCIPvarGetProbindex(clqvars[v1]) : (nallvars + SCIPvarGetProbindex(clqvars[v1]));
7756
7757 /* if corresponding node was not added yet, add it */
7758 if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id1) )
7759 {
7760 assert(id1 >= 0);
7761 SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id1, 1), fclose(gmlfile) ); /*lint !e571*/
7762
7763 (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id1 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v1]));
7764
7765 /* write new gml node for new variable */
7766 if ( writenodeweights )
7767 {
7768 if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v1])) )
7769 SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v1]));
7770 }
7771 else
7772 {
7773 SCIPgmlWriteNode(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL);
7774 }
7775 }
7776
7777 for( v2 = SCIPcliqueGetNVars(cliques[c]) - 1; v2 >= 0; --v2 )
7778 {
7779 if( v1 == v2 )
7780 continue;
7781
7782 id2 = clqvalues[v2] ? SCIPvarGetProbindex(clqvars[v2]) : (nallvars + SCIPvarGetProbindex(clqvars[v2]));
7783
7784 /* if corresponding node was not added yet, add it */
7785 if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id2) )
7786 {
7787 assert(id2 >= 0);
7788 SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id2, 1), fclose(gmlfile) ); /*lint !e571*/
7789
7790 (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id2 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v2]));
7791
7792 /* write new gml node for new variable */
7793 if ( writenodeweights )
7794 {
7795 if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) )
7796 SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v2]));
7797 }
7798 else
7799 {
7800 SCIPgmlWriteNode(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL);
7801 }
7802 }
7803
7804 /* write gml arc between resultant and operand */
7805 if ( ! writenodeweights || ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) )
7806 SCIPgmlWriteArc(gmlfile, (unsigned int)id1, (unsigned int)id2, NULL, NULL);
7807 }
7808 }
7809 }
7810
7811 /* free the hash map */
7812 SCIPhashmapFree(&nodehashmap);
7813
7814 SCIPgmlWriteClosing(gmlfile);
7815 fclose(gmlfile);
7816
7817 return SCIP_OKAY;
7818 }
7819
7820 /** Removes (irrelevant) variable from all its global structures, i.e. cliques, implications and variable bounds.
7821 * This is an advanced method which should be used with care.
7822 *
7823 * @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed
7824 *
7825 * @pre This method can be called if @p scip is in one of the following stages:
7826 * - \ref SCIP_STAGE_TRANSFORMED
7827 * - \ref SCIP_STAGE_INITPRESOLVE
7828 * - \ref SCIP_STAGE_PRESOLVING
7829 * - \ref SCIP_STAGE_EXITPRESOLVE
7830 * - \ref SCIP_STAGE_PRESOLVED
7831 * - \ref SCIP_STAGE_INITSOLVE
7832 * - \ref SCIP_STAGE_SOLVING
7833 * - \ref SCIP_STAGE_SOLVED
7834 * - \ref SCIP_STAGE_EXITSOLVE
7835 */
7836 SCIP_RETCODE SCIPremoveVarFromGlobalStructures(
7837 SCIP* scip, /**< SCIP data structure */
7838 SCIP_VAR* var /**< variable to remove from global structures */
7839 )
7840 {
7841 assert(scip != NULL);
7842
7843 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPremoveVarFromGlobalStructures", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
7844
7845 /* mark the variable as deletable from global structures - This is necessary for the delayed clean up of cliques */
7846 SCIPvarMarkDeleteGlobalStructures(var);
7847
7848 /* remove variable from all its cliques, implications, and variable bounds */
7849 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, SCIPblkmem(scip), scip->cliquetable, scip->set, TRUE, FALSE, TRUE) );
7850
7851 return SCIP_OKAY;
7852 }
7853
7854 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
7855 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
7856 *
7857 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7858 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7859 *
7860 * @pre This method can be called if @p scip is in one of the following stages:
7861 * - \ref SCIP_STAGE_PROBLEM
7862 * - \ref SCIP_STAGE_TRANSFORMING
7863 * - \ref SCIP_STAGE_TRANSFORMED
7864 * - \ref SCIP_STAGE_INITPRESOLVE
7865 * - \ref SCIP_STAGE_PRESOLVING
7866 * - \ref SCIP_STAGE_EXITPRESOLVE
7867 * - \ref SCIP_STAGE_PRESOLVED
7868 * - \ref SCIP_STAGE_SOLVING
7869 */
7870 SCIP_RETCODE SCIPchgVarBranchFactor(
7871 SCIP* scip, /**< SCIP data structure */
7872 SCIP_VAR* var, /**< problem variable */
7873 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
7874 )
7875 {
7876 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7877
7878 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, branchfactor) );
7879
7880 return SCIP_OKAY;
7881 }
7882
7883 /** scales the branch factor of the variable with the given value
7884 *
7885 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7886 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7887 *
7888 * @pre This method can be called if @p scip is in one of the following stages:
7889 * - \ref SCIP_STAGE_PROBLEM
7890 * - \ref SCIP_STAGE_TRANSFORMING
7891 * - \ref SCIP_STAGE_TRANSFORMED
7892 * - \ref SCIP_STAGE_INITPRESOLVE
7893 * - \ref SCIP_STAGE_PRESOLVING
7894 * - \ref SCIP_STAGE_EXITPRESOLVE
7895 * - \ref SCIP_STAGE_PRESOLVED
7896 * - \ref SCIP_STAGE_SOLVING
7897 */
7898 SCIP_RETCODE SCIPscaleVarBranchFactor(
7899 SCIP* scip, /**< SCIP data structure */
7900 SCIP_VAR* var, /**< problem variable */
7901 SCIP_Real scale /**< factor to scale variable's branching factor with */
7902 )
7903 {
7904 SCIP_CALL( SCIPcheckStage(scip, "SCIPscaleVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7905
7906 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, scale * SCIPvarGetBranchFactor(var)) );
7907
7908 return SCIP_OKAY;
7909 }
7910
7911 /** adds the given value to the branch factor of the variable
7912 *
7913 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7914 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7915 *
7916 * @pre This method can be called if @p scip is in one of the following stages:
7917 * - \ref SCIP_STAGE_PROBLEM
7918 * - \ref SCIP_STAGE_TRANSFORMING
7919 * - \ref SCIP_STAGE_TRANSFORMED
7920 * - \ref SCIP_STAGE_INITPRESOLVE
7921 * - \ref SCIP_STAGE_PRESOLVING
7922 * - \ref SCIP_STAGE_EXITPRESOLVE
7923 * - \ref SCIP_STAGE_PRESOLVED
7924 * - \ref SCIP_STAGE_SOLVING
7925 */
7926 SCIP_RETCODE SCIPaddVarBranchFactor(
7927 SCIP* scip, /**< SCIP data structure */
7928 SCIP_VAR* var, /**< problem variable */
7929 SCIP_Real addfactor /**< value to add to the branch factor of the variable */
7930 )
7931 {
7932 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7933
7934 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, addfactor + SCIPvarGetBranchFactor(var)) );
7935
7936 return SCIP_OKAY;
7937 }
7938
7939 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
7940 * with lower priority in selection of branching variable
7941 *
7942 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7943 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7944 *
7945 * @pre This method can be called if @p scip is in one of the following stages:
7946 * - \ref SCIP_STAGE_PROBLEM
7947 * - \ref SCIP_STAGE_TRANSFORMING
7948 * - \ref SCIP_STAGE_TRANSFORMED
7949 * - \ref SCIP_STAGE_INITPRESOLVE
7950 * - \ref SCIP_STAGE_PRESOLVING
7951 * - \ref SCIP_STAGE_EXITPRESOLVE
7952 * - \ref SCIP_STAGE_PRESOLVED
7953 * - \ref SCIP_STAGE_SOLVING
7954 *
7955 * @note the default branching priority is 0
7956 */
7957 SCIP_RETCODE SCIPchgVarBranchPriority(
7958 SCIP* scip, /**< SCIP data structure */
7959 SCIP_VAR* var, /**< problem variable */
7960 int branchpriority /**< branch priority of the variable */
7961 )
7962 {
7963 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7964
7965 assert( var->scip == scip );
7966
7967 if( SCIPisTransformed(scip) )
7968 {
7969 assert(scip->branchcand != NULL);
7970
7971 /* inform the pseudo branch candidates that the branch priority changes and change the branch priority */
7972 SCIP_CALL( SCIPbranchcandUpdateVarBranchPriority(scip->branchcand, scip->set, var, branchpriority) );
7973 }
7974 else
7975 {
7976 /* change the branching priority of the variable */
7977 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
7978 }
7979
7980 return SCIP_OKAY;
7981 }
7982
7983 /** changes the branch priority of the variable to the given value, if it is larger than the current priority
7984 *
7985 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
7986 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
7987 *
7988 * @pre This method can be called if @p scip is in one of the following stages:
7989 * - \ref SCIP_STAGE_PROBLEM
7990 * - \ref SCIP_STAGE_TRANSFORMING
7991 * - \ref SCIP_STAGE_TRANSFORMED
7992 * - \ref SCIP_STAGE_INITPRESOLVE
7993 * - \ref SCIP_STAGE_PRESOLVING
7994 * - \ref SCIP_STAGE_EXITPRESOLVE
7995 * - \ref SCIP_STAGE_PRESOLVED
7996 * - \ref SCIP_STAGE_SOLVING
7997 */
7998 SCIP_RETCODE SCIPupdateVarBranchPriority(
7999 SCIP* scip, /**< SCIP data structure */
8000 SCIP_VAR* var, /**< problem variable */
8001 int branchpriority /**< new branch priority of the variable, if it is larger than current priority */
8002 )
8003 {
8004 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8005
8006 assert( var->scip == scip );
8007
8008 if( branchpriority > SCIPvarGetBranchPriority(var) )
8009 {
8010 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8011 }
8012
8013 return SCIP_OKAY;
8014 }
8015
8016 /** adds the given value to the branch priority of the variable
8017 *
8018 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8019 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8020 *
8021 * @pre This method can be called if @p scip is in one of the following stages:
8022 * - \ref SCIP_STAGE_PROBLEM
8023 * - \ref SCIP_STAGE_TRANSFORMING
8024 * - \ref SCIP_STAGE_TRANSFORMED
8025 * - \ref SCIP_STAGE_INITPRESOLVE
8026 * - \ref SCIP_STAGE_PRESOLVING
8027 * - \ref SCIP_STAGE_EXITPRESOLVE
8028 * - \ref SCIP_STAGE_PRESOLVED
8029 * - \ref SCIP_STAGE_SOLVING
8030 */
8031 SCIP_RETCODE SCIPaddVarBranchPriority(
8032 SCIP* scip, /**< SCIP data structure */
8033 SCIP_VAR* var, /**< problem variable */
8034 int addpriority /**< value to add to the branch priority of the variable */
8035 )
8036 {
8037 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8038
8039 assert( var->scip == scip );
8040
8041 SCIP_CALL( SCIPvarChgBranchPriority(var, addpriority + SCIPvarGetBranchPriority(var)) );
8042
8043 return SCIP_OKAY;
8044 }
8045
8046 /** sets the branch direction of the variable (-1: prefer downwards branch, 0: automatic selection, +1: prefer upwards
8047 * branch)
8048 *
8049 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8050 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8051 *
8052 * @pre This method can be called if @p scip is in one of the following stages:
8053 * - \ref SCIP_STAGE_PROBLEM
8054 * - \ref SCIP_STAGE_TRANSFORMING
8055 * - \ref SCIP_STAGE_TRANSFORMED
8056 * - \ref SCIP_STAGE_INITPRESOLVE
8057 * - \ref SCIP_STAGE_PRESOLVING
8058 * - \ref SCIP_STAGE_EXITPRESOLVE
8059 * - \ref SCIP_STAGE_PRESOLVED
8060 * - \ref SCIP_STAGE_SOLVING
8061 */
8062 SCIP_RETCODE SCIPchgVarBranchDirection(
8063 SCIP* scip, /**< SCIP data structure */
8064 SCIP_VAR* var, /**< problem variable */
8065 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
8066 )
8067 {
8068 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchDirection", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8069
8070 assert( var->scip == scip );
8071
8072 SCIP_CALL( SCIPvarChgBranchDirection(var, branchdirection) );
8073
8074 return SCIP_OKAY;
8075 }
8076
8077 /** tightens the variable bounds due to a new variable type */
8078 static
8079 SCIP_RETCODE tightenBounds(
8080 SCIP* scip, /**< SCIP data structure */
8081 SCIP_VAR* var, /**< variable to change the bound for */
8082 SCIP_VARTYPE vartype, /**< new type of variable */
8083 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected (, due to
8084 * integrality condition of the new variable type) */
8085 )
8086 {
8087 assert(scip != NULL);
8088 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING);
8089 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPvarIsTransformed(var));
8090 assert(var->scip == scip);
8091
8092 *infeasible = FALSE;
8093
8094 /* adjusts bounds if the variable type changed form continuous to non-continuous (integral) */
8095 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_CONTINUOUS )
8096 {
8097 SCIP_Bool tightened;
8098
8099 /* we adjust variable bounds to integers first, since otherwise a later bound tightening with a fractional old
8100 * bound may give an assert because SCIP expects non-continuous variables to have non-fractional bounds
8101 *
8102 * we adjust bounds with a fractionality within [eps,feastol] only if the resulting bound change is a bound
8103 * tightening, because relaxing bounds may not be allowed
8104 */
8105 if( !SCIPisFeasIntegral(scip, SCIPvarGetLbGlobal(var)) ||
8106 (!SCIPisIntegral(scip, SCIPvarGetLbGlobal(var)) && SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) ||
8107 (!SCIPsetIsEQ(scip->set, SCIPvarGetLbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) &&
8108 SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)))
8109 )
8110 {
8111 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)), TRUE, infeasible, &tightened) );
8112 if( *infeasible )
8113 return SCIP_OKAY;
8114
8115 /* 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
8116 * 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
8117 */
8118 assert(tightened || SCIPisFeasLE(scip, SCIPvarGetUbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))));
8119 }
8120 if( !SCIPisFeasIntegral(scip, SCIPvarGetUbGlobal(var)) ||
8121 (!SCIPisIntegral(scip, SCIPvarGetUbGlobal(var)) && SCIPvarGetUbGlobal(var) > SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)))
8122 )
8123 {
8124 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)), TRUE, infeasible, &tightened) );
8125 if( *infeasible )
8126 return SCIP_OKAY;
8127
8128 assert(tightened || SCIPisFeasGE(scip, SCIPvarGetLbGlobal(var), SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var))));
8129 }
8130 }
8131
8132 return SCIP_OKAY;
8133 }
8134
8135 /** changes type of variable in the problem;
8136 *
8137 * @warning This type change might change the variable array returned from SCIPgetVars() and SCIPgetVarsData();
8138 *
8139 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8140 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8141 *
8142 * @pre This method can be called if @p scip is in one of the following stages:
8143 * - \ref SCIP_STAGE_PROBLEM
8144 * - \ref SCIP_STAGE_TRANSFORMING
8145 * - \ref SCIP_STAGE_PRESOLVING
8146 *
8147 * @note If SCIP is already beyond the SCIP_STAGE_PROBLEM and a original variable is passed, the variable type of the
8148 * corresponding transformed variable is changed; the type of the original variable does not change
8149 *
8150 * @note If the type changes from a continuous variable to a non-continuous variable the bounds of the variable get
8151 * adjusted w.r.t. to integrality information
8152 */
8153 SCIP_RETCODE SCIPchgVarType(
8154 SCIP* scip, /**< SCIP data structure */
8155 SCIP_VAR* var, /**< variable to change the bound for */
8156 SCIP_VARTYPE vartype, /**< new type of variable */
8157 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected (, due to
8158 * integrality condition of the new variable type) */
8159 )
8160 {
8161 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarType", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8162
8163 assert(var != NULL);
8164 assert(var->scip == scip);
8165
8166 if( SCIPvarIsNegated(var) )
8167 {
8168 SCIPdebugMsg(scip, "upgrading type of negated variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype);
8169 var = SCIPvarGetNegationVar(var);
8170 }
8171 #ifndef NDEBUG
8172 else
8173 {
8174 if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
8175 {
8176 SCIPdebugMsg(scip, "upgrading type of variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype);
8177 }
8178 }
8179 #endif
8180
8181 /* change variable type */
8182 switch( scip->set->stage )
8183 {
8184 case SCIP_STAGE_PROBLEM:
8185 assert(!SCIPvarIsTransformed(var));
8186
8187 /* first adjust the variable due to new integrality information */
8188 SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) );
8189
8190 /* second change variable type */
8191 if( SCIPvarGetProbindex(var) >= 0 )
8192 {
8193 SCIP_CALL( SCIPprobChgVarType(scip->origprob, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8194 scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) );
8195 }
8196 else
8197 {
8198 SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8199 scip->eventqueue, vartype) );
8200 }
8201 break;
8202
8203 case SCIP_STAGE_PRESOLVING:
8204 if( !SCIPvarIsTransformed(var) )
8205 {
8206 SCIP_VAR* transvar;
8207
8208 SCIP_CALL( SCIPgetTransformedVar(scip, var, &transvar) );
8209 assert(transvar != NULL);
8210
8211 /* recall method with transformed variable */
8212 SCIP_CALL( SCIPchgVarType(scip, transvar, vartype, infeasible) );
8213 return SCIP_OKAY;
8214 }
8215
8216 /* first adjust the variable due to new integrality information */
8217 SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) );
8218
8219 /* second change variable type */
8220 if( SCIPvarGetProbindex(var) >= 0 )
8221 {
8222 SCIP_CALL( SCIPprobChgVarType(scip->transprob, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8223 scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) );
8224 }
8225 else
8226 {
8227 SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp,
8228 scip->eventqueue, vartype) );
8229 }
8230 break;
8231
8232 default:
8233 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
8234 return SCIP_INVALIDCALL;
8235 } /*lint !e788*/
8236
8237 return SCIP_OKAY;
8238 }
8239
8240 /** in problem creation and solving stage, both bounds of the variable are set to the given value;
8241 * in presolving stage, the variable is converted into a fixed variable, and bounds are changed respectively;
8242 * conversion into a fixed variable changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(),
8243 * and also renders arrays returned from the SCIPvarGetImpl...() methods invalid
8244 *
8245 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8246 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8247 *
8248 * @pre This method can be called if @p scip is in one of the following stages:
8249 * - \ref SCIP_STAGE_PROBLEM
8250 * - \ref SCIP_STAGE_PRESOLVING
8251 * - \ref SCIP_STAGE_SOLVING
8252 */
8253 SCIP_RETCODE SCIPfixVar(
8254 SCIP* scip, /**< SCIP data structure */
8255 SCIP_VAR* var, /**< variable to fix */
8256 SCIP_Real fixedval, /**< value to fix variable to */
8257 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
8258 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
8259 )
8260 {
8261 assert(var != NULL);
8262 assert(infeasible != NULL);
8263 assert(fixed != NULL);
8264
8265 SCIP_CALL( SCIPcheckStage(scip, "SCIPfixVar", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
8266
8267 *infeasible = FALSE;
8268 *fixed = FALSE;
8269
8270 /* in the problem creation stage, modify the bounds as requested, independently from the current bounds */
8271 if( scip->set->stage != SCIP_STAGE_PROBLEM )
8272 {
8273 if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(scip->set, fixedval))
8274 || SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var))
8275 || SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8276 {
8277 *infeasible = TRUE;
8278 return SCIP_OKAY;
8279 }
8280 else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED )
8281 {
8282 *infeasible = !SCIPsetIsFeasEQ(scip->set, fixedval, SCIPvarGetLbLocal(var));
8283 return SCIP_OKAY;
8284 }
8285 }
8286 else
8287 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
8288
8289 switch( scip->set->stage )
8290 {
8291 case SCIP_STAGE_PROBLEM:
8292 /* in the problem creation stage, modify the bounds as requested, independently from the current bounds;
8293 * we have to make sure, that the order of the bound changes does not intermediately produce an invalid
8294 * interval lb > ub
8295 */
8296 if( fixedval <= SCIPvarGetLbLocal(var) )
8297 {
8298 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8299 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8300 *fixed = TRUE;
8301 }
8302 else
8303 {
8304 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8305 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8306 *fixed = TRUE;
8307 }
8308 return SCIP_OKAY;
8309
8310 case SCIP_STAGE_PRESOLVING:
8311 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
8312 {
8313 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8314 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8315 scip->cliquetable, fixedval, infeasible, fixed) );
8316 return SCIP_OKAY;
8317 }
8318 /*lint -fallthrough*/
8319 case SCIP_STAGE_SOLVING:
8320 if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetLbLocal(var)) )
8321 {
8322 if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8323 {
8324 *infeasible = TRUE;
8325 return SCIP_OKAY;
8326 }
8327 else
8328 {
8329 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) );
8330 *fixed = TRUE;
8331 }
8332 }
8333 if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetUbLocal(var)) )
8334 {
8335 if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var)) )
8336 {
8337 *infeasible = TRUE;
8338 return SCIP_OKAY;
8339 }
8340 else
8341 {
8342 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) );
8343 *fixed = TRUE;
8344 }
8345 }
8346 return SCIP_OKAY;
8347
8348 default:
8349 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
8350 return SCIP_INVALIDCALL;
8351 } /*lint !e788*/
8352 }
8353
8354 /** From a given equality a*x + b*y == c, aggregates one of the variables and removes it from the set of
8355 * active problem variables. This changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(),
8356 * and also renders the arrays returned from the SCIPvarGetImpl...() methods for the two variables invalid.
8357 * In the first step, the equality is transformed into an equality with active problem variables
8358 * a'*x' + b'*y' == c'. If x' == y', this leads to the detection of redundancy if a' == -b' and c' == 0,
8359 * of infeasibility, if a' == -b' and c' != 0, or to a variable fixing x' == c'/(a'+b') (and possible
8360 * infeasibility) otherwise.
8361 * In the second step, the variable to be aggregated is chosen among x' and y', prefering a less strict variable
8362 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
8363 * over integers, and integers over binaries). If none of the variables is continuous, it is tried to find an integer
8364 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
8365 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
8366 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
8367 *
8368 * The output flags have the following meaning:
8369 * - infeasible: the problem is infeasible
8370 * - redundant: the equality can be deleted from the constraint set
8371 * - aggregated: the aggregation was successfully performed (the variables were not aggregated before)
8372 *
8373 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8374 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8375 *
8376 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING
8377 */
8378 SCIP_RETCODE SCIPaggregateVars(
8379 SCIP* scip, /**< SCIP data structure */
8380 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
8381 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
8382 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
8383 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
8384 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
8385 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8386 SCIP_Bool* redundant, /**< pointer to store whether the equality is (now) redundant */
8387 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8388 )
8389 {
8390 SCIP_Real constantx;
8391 SCIP_Real constanty;
8392
8393 assert(infeasible != NULL);
8394 assert(redundant != NULL);
8395 assert(aggregated != NULL);
8396
8397 SCIP_CALL( SCIPcheckStage(scip, "SCIPaggregateVars", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8398
8399 *infeasible = FALSE;
8400 *redundant = FALSE;
8401 *aggregated = FALSE;
8402
8403 if( SCIPtreeProbing(scip->tree) )
8404 {
8405 SCIPerrorMessage("cannot aggregate variables during probing\n");
8406 return SCIP_INVALIDCALL;
8407 }
8408 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
8409
8410 /* do not perform aggregation if it is globally deactivated */
8411 if( scip->set->presol_donotaggr )
8412 return SCIP_OKAY;
8413
8414 /* get the corresponding equality in active problem variable space:
8415 * transform both expressions "a*x + 0" and "b*y + 0" into problem variable space
8416 */
8417 constantx = 0.0;
8418 constanty = 0.0;
8419 SCIP_CALL( SCIPvarGetProbvarSum(&varx, scip->set, &scalarx, &constantx) );
8420 SCIP_CALL( SCIPvarGetProbvarSum(&vary, scip->set, &scalary, &constanty) );
8421
8422 /* we cannot aggregate multi-aggregated variables */
8423 if( SCIPvarGetStatus(varx) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vary) == SCIP_VARSTATUS_MULTAGGR )
8424 return SCIP_OKAY;
8425
8426 /* move the constant to the right hand side to acquire the form "a'*x' + b'*y' == c'" */
8427 rhs -= (constantx + constanty);
8428
8429 /* if a scalar is zero, treat the variable as fixed-to-zero variable */
8430 if( SCIPsetIsZero(scip->set, scalarx) )
8431 varx = NULL;
8432 if( SCIPsetIsZero(scip->set, scalary) )
8433 vary = NULL;
8434
8435 /* capture the special cases that less than two variables are left, due to resolutions to a fixed variable or
8436 * to the same active variable
8437 */
8438 if( varx == NULL && vary == NULL )
8439 {
8440 /* both variables were resolved to fixed variables */
8441 *infeasible = !SCIPsetIsZero(scip->set, rhs);
8442 *redundant = TRUE;
8443 }
8444 else if( varx == NULL )
8445 {
8446 assert(SCIPsetIsZero(scip->set, scalarx));
8447 assert(!SCIPsetIsZero(scip->set, scalary));
8448
8449 /* variable x was resolved to fixed variable: variable y can be fixed to c'/b' */
8450 SCIP_CALL( SCIPvarFix(vary, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8451 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8452 scip->cliquetable, rhs/scalary, infeasible, aggregated) );
8453 *redundant = TRUE;
8454 }
8455 else if( vary == NULL )
8456 {
8457 assert(SCIPsetIsZero(scip->set, scalary));
8458 assert(!SCIPsetIsZero(scip->set, scalarx));
8459
8460 /* variable y was resolved to fixed variable: variable x can be fixed to c'/a' */
8461 SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8462 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8463 scip->cliquetable, rhs/scalarx, infeasible, aggregated) );
8464 *redundant = TRUE;
8465 }
8466 else if( varx == vary )
8467 {
8468 /* both variables were resolved to the same active problem variable: this variable can be fixed */
8469 scalarx += scalary;
8470 if( SCIPsetIsZero(scip->set, scalarx) )
8471 {
8472 /* left hand side of equality is zero: equality is potentially infeasible */
8473 *infeasible = !SCIPsetIsZero(scip->set, rhs);
8474 }
8475 else
8476 {
8477 /* sum of scalars is not zero: fix variable x' == y' to c'/(a'+b') */
8478 SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8479 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue,
8480 scip->cliquetable, rhs/scalarx, infeasible, aggregated) );
8481 }
8482 *redundant = TRUE;
8483 }
8484 else
8485 {
8486 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8487 SCIP_CALL( SCIPvarTryAggregateVars(scip->set, scip->mem->probmem, scip->stat, scip->transprob, scip->origprob,
8488 scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter,
8489 scip->eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
8490 *redundant = *aggregated;
8491 }
8492
8493 return SCIP_OKAY;
8494 }
8495
8496 /** converts variable into multi-aggregated variable; this changes the variable array returned from
8497 * SCIPgetVars() and SCIPgetVarsData();
8498 *
8499 * @warning The integrality condition is not checked anymore on the multi-aggregated variable. You must not
8500 * multi-aggregate an integer variable without being sure, that integrality on the aggregation variables
8501 * implies integrality on the aggregated variable.
8502 *
8503 * The output flags have the following meaning:
8504 * - infeasible: the problem is infeasible
8505 * - aggregated: the aggregation was successfully performed (the variables were not aggregated before)
8506 *
8507 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8508 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8509 *
8510 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING
8511 */
8512 SCIP_RETCODE SCIPmultiaggregateVar(
8513 SCIP* scip, /**< SCIP data structure */
8514 SCIP_VAR* var, /**< variable x to aggregate */
8515 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8516 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8517 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8518 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8519 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8520 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8521 )
8522 {
8523 SCIP_CALL( SCIPcheckStage(scip, "SCIPmultiaggregateVar", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8524
8525 assert(var->scip == scip);
8526
8527 if( SCIPtreeProbing(scip->tree) )
8528 {
8529 SCIPerrorMessage("cannot multi-aggregate variables during probing\n");
8530 return SCIP_INVALIDCALL;
8531 }
8532 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0);
8533
8534 SCIP_CALL( SCIPvarMultiaggregate(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob,
8535 scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter,
8536 scip->eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8537
8538 return SCIP_OKAY;
8539 }
8540
8541 /** returns whether aggregation of variables is not allowed */
8542 SCIP_Bool SCIPdoNotAggr(
8543 SCIP* scip /**< SCIP data structure */
8544 )
8545 {
8546 assert(scip != NULL);
8547
8548 return scip->set->presol_donotaggr;
8549 }
8550
8551 /** returns whether multi-aggregation is disabled */
8552 SCIP_Bool SCIPdoNotMultaggr(
8553 SCIP* scip /**< SCIP data structure */
8554 )
8555 {
8556 assert(scip != NULL);
8557
8558 return scip->set->presol_donotmultaggr;
8559 }
8560
8561 /** returns whether variable is not allowed to be aggregated */
8562 SCIP_Bool SCIPdoNotAggrVar(
8563 SCIP* scip, /**< SCIP data structure */
8564 SCIP_VAR* var /**< variable x to aggregate */
8565 )
8566 {
8567 assert(scip != NULL);
8568 assert(var != NULL);
8569 assert(var->scip == scip);
8570
8571 return scip->set->presol_donotaggr || SCIPvarDoNotAggr(var);
8572 }
8573
8574 /** returns whether variable is not allowed to be multi-aggregated */
8575 SCIP_Bool SCIPdoNotMultaggrVar(
8576 SCIP* scip, /**< SCIP data structure */
8577 SCIP_VAR* var /**< variable x to aggregate */
8578 )
8579 {
8580 assert(scip != NULL);
8581 assert(var != NULL);
8582 assert(var->scip == scip);
8583
8584 return scip->set->presol_donotmultaggr || SCIPvarDoNotMultaggr(var);
8585 }
8586
8587 /** returns whether dual reductions are allowed during propagation and presolving
8588 *
8589 * @deprecated Please use SCIPallowStrongDualReds()
8590 */
8591 SCIP_Bool SCIPallowDualReds(
8592 SCIP* scip /**< SCIP data structure */
8593 )
8594 {
8595 assert(scip != NULL);
8596
8597 return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds;
8598 }
8599
8600 /** returns whether strong dual reductions are allowed during propagation and presolving
8601 *
8602 * @note A reduction is called strong dual, if it may discard feasible/optimal solutions, but leaves at least one
8603 * optimal solution intact. Often such reductions are based on analyzing the objective function and variable
8604 * locks.
8605 */
8606 SCIP_Bool SCIPallowStrongDualReds(
8607 SCIP* scip /**< SCIP data structure */
8608 )
8609 {
8610 assert(scip != NULL);
8611
8612 return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds;
8613 }
8614
8615 /** returns whether propagation w.r.t. current objective is allowed
8616 *
8617 * @deprecated Please use SCIPallowWeakDualReds()
8618 */
8619 SCIP_Bool SCIPallowObjProp(
8620 SCIP* scip /**< SCIP data structure */
8621 )
8622 {
8623 assert(scip != NULL);
8624
8625 return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds;
8626 }
8627
8628 /** returns whether weak dual reductions are allowed during propagation and presolving
8629 *
8630 * @note A reduction is called weak dual, if it may discard feasible solutions, but leaves at all optimal solutions
8631 * intact. Often such reductions are based on analyzing the objective function, reduced costs, and/or dual LPs.
8632 */
8633 SCIP_Bool SCIPallowWeakDualReds(
8634 SCIP* scip /**< SCIP data structure */
8635 )
8636 {
8637 assert(scip != NULL);
8638
8639 return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds;
8640 }
8641
8642 /** marks the variable that it must not be aggregated
8643 *
8644 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8645 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8646 *
8647 * @pre This method can be called if @p scip is in one of the following stages:
8648 * - \ref SCIP_STAGE_INIT
8649 * - \ref SCIP_STAGE_PROBLEM
8650 * - \ref SCIP_STAGE_TRANSFORMING
8651 * - \ref SCIP_STAGE_TRANSFORMED
8652 * - \ref SCIP_STAGE_INITPRESOLVE
8653 * - \ref SCIP_STAGE_PRESOLVING
8654 * - \ref SCIP_STAGE_EXITPRESOLVE
8655 *
8656 * @note There exists no "unmark" method since it has to be ensured that if a plugin requires that a variable is not
8657 * aggregated that this is will be the case.
8658 */
8659 SCIP_RETCODE SCIPmarkDoNotAggrVar(
8660 SCIP* scip, /**< SCIP data structure */
8661 SCIP_VAR* var /**< variable to delete */
8662 )
8663 {
8664 assert(scip != NULL);
8665 assert(var != NULL);
8666 assert(var->scip == scip);
8667
8668 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkDoNotAggrVar", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE) );
8669
8670 SCIP_CALL( SCIPvarMarkDoNotAggr(var) );
8671
8672 return SCIP_OKAY;
8673 }
8674
8675 /** marks the variable that it must not be multi-aggregated
8676 *
8677 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8678 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8679 *
8680 * @pre This method can be called if @p scip is in one of the following stages:
8681 * - \ref SCIP_STAGE_INIT
8682 * - \ref SCIP_STAGE_PROBLEM
8683 * - \ref SCIP_STAGE_TRANSFORMING
8684 * - \ref SCIP_STAGE_TRANSFORMED
8685 * - \ref SCIP_STAGE_INITPRESOLVE
8686 * - \ref SCIP_STAGE_PRESOLVING
8687 * - \ref SCIP_STAGE_EXITPRESOLVE
8688 *
8689 * @note There exists no "unmark" method since it has to be ensured that if a plugin requires that a variable is not
8690 * multi-aggregated that this is will be the case.
8691 */
8692 SCIP_RETCODE SCIPmarkDoNotMultaggrVar(
8693 SCIP* scip, /**< SCIP data structure */
8694 SCIP_VAR* var /**< variable to delete */
8695 )
8696 {
8697 assert(scip != NULL);
8698 assert(var != NULL);
8699 assert(var->scip == scip);
8700
8701 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkDoNotMultaggrVar", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE) );
8702
8703 SCIP_CALL( SCIPvarMarkDoNotMultaggr(var) );
8704
8705 return SCIP_OKAY;
8706 }
8707
8708 /** enables the collection of statistics for a variable
8709 *
8710 * @pre This method can be called if @p scip is in one of the following stages:
8711 * - \ref SCIP_STAGE_PROBLEM
8712 * - \ref SCIP_STAGE_INITPRESOLVE
8713 * - \ref SCIP_STAGE_PRESOLVING
8714 * - \ref SCIP_STAGE_EXITPRESOLVE
8715 * - \ref SCIP_STAGE_SOLVING
8716 * - \ref SCIP_STAGE_SOLVED
8717 */
8718 void SCIPenableVarHistory(
8719 SCIP* scip /**< SCIP data structure */
8720 )
8721 {
8722 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPenableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8723
8724 SCIPstatEnableVarHistory(scip->stat);
8725 }
8726
8727 /** disables the collection of any statistic for a variable
8728 *
8729 * @pre This method can be called if @p scip is in one of the following stages:
8730 * - \ref SCIP_STAGE_PROBLEM
8731 * - \ref SCIP_STAGE_INITPRESOLVE
8732 * - \ref SCIP_STAGE_PRESOLVING
8733 * - \ref SCIP_STAGE_EXITPRESOLVE
8734 * - \ref SCIP_STAGE_SOLVING
8735 * - \ref SCIP_STAGE_SOLVED
8736 */
8737 void SCIPdisableVarHistory(
8738 SCIP* scip /**< SCIP data structure */
8739 )
8740 {
8741 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPdisableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8742
8743 SCIPstatDisableVarHistory(scip->stat);
8744 }
8745
8746 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of "solvaldelta" in the
8747 * variable's solution value and resulting change of "objdelta" in the in the LP's objective value;
8748 * the update is ignored, if the objective value difference is infinite
8749 *
8750 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
8751 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
8752 *
8753 * @pre This method can be called if @p scip is in one of the following stages:
8754 * - \ref SCIP_STAGE_SOLVING
8755 * - \ref SCIP_STAGE_SOLVED
8756 */
8757 SCIP_RETCODE SCIPupdateVarPseudocost(
8758 SCIP* scip, /**< SCIP data structure */
8759 SCIP_VAR* var, /**< problem variable */
8760 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
8761 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
8762 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
8763 )
8764 {
8765 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarPseudocost", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8766
8767 if( !SCIPsetIsInfinity(scip->set, 2*objdelta) ) /* differences infinity - eps should also be treated as infinity */
8768 {
8769 if( scip->set->branch_divingpscost || (!scip->lp->diving && !SCIPtreeProbing(scip->tree)) )
8770 {
8771 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, solvaldelta, objdelta, weight) );
8772 }
8773 }
8774
8775 return SCIP_OKAY;
8776 }
8777
8778 /** gets the variable's pseudo cost value for the given change of the variable's LP value
8779 *
8780 * @return the variable's pseudo cost value for the given change of the variable's LP value
8781 *
8782 * @pre This method can be called if @p scip is in one of the following stages:
8783 * - \ref SCIP_STAGE_INITPRESOLVE
8784 * - \ref SCIP_STAGE_PRESOLVING
8785 * - \ref SCIP_STAGE_EXITPRESOLVE
8786 * - \ref SCIP_STAGE_PRESOLVED
8787 * - \ref SCIP_STAGE_INITSOLVE
8788 * - \ref SCIP_STAGE_SOLVING
8789 * - \ref SCIP_STAGE_SOLVED
8790 */
8791 SCIP_Real SCIPgetVarPseudocostVal(
8792 SCIP* scip, /**< SCIP data structure */
8793 SCIP_VAR* var, /**< problem variable */
8794 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
8795 )
8796 {
8797 assert( var->scip == scip );
8798
8799 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVal", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8800
8801 return SCIPvarGetPseudocost(var, scip->stat, solvaldelta);
8802 }
8803
8804 /** gets the variable's pseudo cost value for the given change of the variable's LP value,
8805 * only using the pseudo cost information of the current run
8806 *
8807 * @return the variable's pseudo cost value for the given change of the variable's LP value,
8808 * only using the pseudo cost information of the current run
8809 *
8810 * @pre This method can be called if @p scip is in one of the following stages:
8811 * - \ref SCIP_STAGE_INITPRESOLVE
8812 * - \ref SCIP_STAGE_PRESOLVING
8813 * - \ref SCIP_STAGE_EXITPRESOLVE
8814 * - \ref SCIP_STAGE_PRESOLVED
8815 * - \ref SCIP_STAGE_INITSOLVE
8816 * - \ref SCIP_STAGE_SOLVING
8817 * - \ref SCIP_STAGE_SOLVED
8818 */
8819 SCIP_Real SCIPgetVarPseudocostValCurrentRun(
8820 SCIP* scip, /**< SCIP data structure */
8821 SCIP_VAR* var, /**< problem variable */
8822 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
8823 )
8824 {
8825 assert( var->scip == scip );
8826
8827 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostValCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8828
8829 return SCIPvarGetPseudocostCurrentRun(var, scip->stat, solvaldelta);
8830 }
8831
8832 /** gets the variable's pseudo cost value for the given direction
8833 *
8834 * @return the variable's pseudo cost value for the given direction
8835 *
8836 * @pre This method can be called if @p scip is in one of the following stages:
8837 * - \ref SCIP_STAGE_INITPRESOLVE
8838 * - \ref SCIP_STAGE_PRESOLVING
8839 * - \ref SCIP_STAGE_EXITPRESOLVE
8840 * - \ref SCIP_STAGE_PRESOLVED
8841 * - \ref SCIP_STAGE_INITSOLVE
8842 * - \ref SCIP_STAGE_SOLVING
8843 * - \ref SCIP_STAGE_SOLVED
8844 */
8845 SCIP_Real SCIPgetVarPseudocost(
8846 SCIP* scip, /**< SCIP data structure */
8847 SCIP_VAR* var, /**< problem variable */
8848 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
8849 )
8850 {
8851 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocost", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8852 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8853 assert(var->scip == scip);
8854
8855 return SCIPvarGetPseudocost(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
8856 }
8857
8858 /** gets the variable's pseudo cost value for the given direction,
8859 * only using the pseudo cost information of the current run
8860 *
8861 * @return the variable's pseudo cost value for the given direction,
8862 * only using the pseudo cost information of the current run
8863 *
8864 * @pre This method can be called if @p scip is in one of the following stages:
8865 * - \ref SCIP_STAGE_INITPRESOLVE
8866 * - \ref SCIP_STAGE_PRESOLVING
8867 * - \ref SCIP_STAGE_EXITPRESOLVE
8868 * - \ref SCIP_STAGE_PRESOLVED
8869 * - \ref SCIP_STAGE_INITSOLVE
8870 * - \ref SCIP_STAGE_SOLVING
8871 * - \ref SCIP_STAGE_SOLVED
8872 */
8873 SCIP_Real SCIPgetVarPseudocostCurrentRun(
8874 SCIP* scip, /**< SCIP data structure */
8875 SCIP_VAR* var, /**< problem variable */
8876 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
8877 )
8878 {
8879 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8880 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8881 assert(var->scip == scip);
8882
8883 return SCIPvarGetPseudocostCurrentRun(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
8884 }
8885
8886 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction
8887 *
8888 * @return the variable's (possible fractional) number of pseudo cost updates for the given direction
8889 *
8890 * @pre This method can be called if @p scip is in one of the following stages:
8891 * - \ref SCIP_STAGE_INITPRESOLVE
8892 * - \ref SCIP_STAGE_PRESOLVING
8893 * - \ref SCIP_STAGE_EXITPRESOLVE
8894 * - \ref SCIP_STAGE_PRESOLVED
8895 * - \ref SCIP_STAGE_INITSOLVE
8896 * - \ref SCIP_STAGE_SOLVING
8897 * - \ref SCIP_STAGE_SOLVED
8898 */
8899 SCIP_Real SCIPgetVarPseudocostCount(
8900 SCIP* scip, /**< SCIP data structure */
8901 SCIP_VAR* var, /**< problem variable */
8902 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
8903 )
8904 {
8905 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCount", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8906 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8907 assert(var->scip == scip);
8908
8909 return SCIPvarGetPseudocostCount(var, dir);
8910 }
8911
8912 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
8913 * only using the pseudo cost information of the current run
8914 *
8915 * @return the variable's (possible fractional) number of pseudo cost updates for the given direction,
8916 * only using the pseudo cost information of the current run
8917 *
8918 * @pre This method can be called if @p scip is in one of the following stages:
8919 * - \ref SCIP_STAGE_INITPRESOLVE
8920 * - \ref SCIP_STAGE_PRESOLVING
8921 * - \ref SCIP_STAGE_EXITPRESOLVE
8922 * - \ref SCIP_STAGE_PRESOLVED
8923 * - \ref SCIP_STAGE_INITSOLVE
8924 * - \ref SCIP_STAGE_SOLVING
8925 * - \ref SCIP_STAGE_SOLVED
8926 */
8927 SCIP_Real SCIPgetVarPseudocostCountCurrentRun(
8928 SCIP* scip, /**< SCIP data structure */
8929 SCIP_VAR* var, /**< problem variable */
8930 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
8931 )
8932 {
8933 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCountCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8934 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8935 assert(var->scip == scip);
8936
8937 return SCIPvarGetPseudocostCountCurrentRun(var, dir);
8938 }
8939
8940 /** get pseudo cost variance of the variable, either for entire solve or only for current branch and bound run
8941 *
8942 * @return returns the (corrected) variance of pseudo code information collected so far.
8943 *
8944 * @pre This method can be called if @p scip is in one of the following stages:
8945 * - \ref SCIP_STAGE_INITPRESOLVE
8946 * - \ref SCIP_STAGE_PRESOLVING
8947 * - \ref SCIP_STAGE_EXITPRESOLVE
8948 * - \ref SCIP_STAGE_PRESOLVED
8949 * - \ref SCIP_STAGE_INITSOLVE
8950 * - \ref SCIP_STAGE_SOLVING
8951 * - \ref SCIP_STAGE_SOLVED
8952 */
8953 SCIP_Real SCIPgetVarPseudocostVariance(
8954 SCIP* scip, /**< SCIP data structure */
8955 SCIP_VAR* var, /**< problem variable */
8956 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
8957 SCIP_Bool onlycurrentrun /**< only for pseudo costs of current branch and bound run */
8958 )
8959 {
8960 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVariance", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8961 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
8962 assert(var->scip == scip);
8963
8964 return SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
8965 }
8966
8967 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
8968 *
8969 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
8970 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
8971 * of 2 * clevel - 1.
8972 *
8973 * @return value of confidence bound for this variable
8974 */
8975 SCIP_Real SCIPcalculatePscostConfidenceBound(
8976 SCIP* scip, /**< SCIP data structure */
8977 SCIP_VAR* var, /**< variable in question */
8978 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
8979 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
8980 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
8981 )
8982 {
8983 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcalculatePscostConfidenceBound", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
8984
8985 return SCIPvarCalcPscostConfidenceBound(var, scip->set, dir, onlycurrentrun, clevel);
8986 }
8987
8988 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
8989 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
8990 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
8991 * unknown location means of the underlying pseudo-cost distributions of x and y.
8992 *
8993 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
8994 * better than x (despite the current information), meaning that y can be expected to yield branching
8995 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
8996 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
8997 * than y.
8998 *
8999 * @note The order of x and y matters for the one-sided hypothesis
9000 *
9001 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
9002 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
9003 *
9004 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
9005 */
9006 SCIP_Bool SCIPsignificantVarPscostDifference(
9007 SCIP* scip, /**< SCIP data structure */
9008 SCIP_VAR* varx, /**< variable x */
9009 SCIP_Real fracx, /**< the fractionality of variable x */
9010 SCIP_VAR* vary, /**< variable y */
9011 SCIP_Real fracy, /**< the fractionality of variable y */
9012 SCIP_BRANCHDIR dir, /**< branching direction */
9013 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
9014 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
9015 )
9016 {
9017 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPsignificantVarPscostDifference", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9018
9019 return SCIPvarSignificantPscostDifference(scip->set, scip->stat, varx, fracx, vary, fracy, dir, clevel, onesided);
9020 }
9021
9022 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
9023 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
9024 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
9025 * of at least \p threshold.
9026 *
9027 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
9028 * the estimated probability to exceed \p threshold is less than 25 %.
9029 *
9030 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
9031 * of confidence.
9032 *
9033 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
9034 * at the given confidence level \p clevel.
9035 */
9036 SCIP_Bool SCIPpscostThresholdProbabilityTest(
9037 SCIP* scip, /**< SCIP data structure */
9038 SCIP_VAR* var, /**< variable x */
9039 SCIP_Real frac, /**< the fractionality of variable x */
9040 SCIP_Real threshold, /**< the threshold to test against */
9041 SCIP_BRANCHDIR dir, /**< branching direction */
9042 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
9043 )
9044 {
9045 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPpscostThresholdProbabilityTest", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9046
9047 return SCIPvarPscostThresholdProbabilityTest(scip->set, scip->stat, var, frac, threshold, dir, clevel);
9048 }
9049
9050 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
9051 * Error is calculated at a specific confidence level
9052 *
9053 * @return TRUE if relative error in variable pseudo costs is smaller than \p threshold
9054 */
9055 SCIP_Bool SCIPisVarPscostRelerrorReliable(
9056 SCIP* scip, /**< SCIP data structure */
9057 SCIP_VAR* var, /**< variable in question */
9058 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
9059 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
9060 )
9061 {
9062 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisVarPscostRelerrorReliable", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9063
9064 return SCIPvarIsPscostRelerrorReliable(var, scip->set, scip->stat, threshold, clevel);
9065 }
9066
9067 /** gets the variable's pseudo cost score value for the given LP solution value
9068 *
9069 * @return the variable's pseudo cost score value for the given LP solution value
9070 *
9071 * @pre This method can be called if @p scip is in one of the following stages:
9072 * - \ref SCIP_STAGE_INITPRESOLVE
9073 * - \ref SCIP_STAGE_PRESOLVING
9074 * - \ref SCIP_STAGE_EXITPRESOLVE
9075 * - \ref SCIP_STAGE_PRESOLVED
9076 * - \ref SCIP_STAGE_INITSOLVE
9077 * - \ref SCIP_STAGE_SOLVING
9078 * - \ref SCIP_STAGE_SOLVED
9079 */
9080 SCIP_Real SCIPgetVarPseudocostScore(
9081 SCIP* scip, /**< SCIP data structure */
9082 SCIP_VAR* var, /**< problem variable */
9083 SCIP_Real solval /**< variable's LP solution value */
9084 )
9085 {
9086 SCIP_Real downsol;
9087 SCIP_Real upsol;
9088 SCIP_Real pscostdown;
9089 SCIP_Real pscostup;
9090
9091 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9092
9093 assert( var->scip == scip );
9094
9095 downsol = SCIPsetFeasCeil(scip->set, solval-1.0);
9096 upsol = SCIPsetFeasFloor(scip->set, solval+1.0);
9097 pscostdown = SCIPvarGetPseudocost(var, scip->stat, downsol-solval);
9098 pscostup = SCIPvarGetPseudocost(var, scip->stat, upsol-solval);
9099
9100 return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup);
9101 }
9102
9103 /** gets the variable's pseudo cost score value for the given LP solution value,
9104 * only using the pseudo cost information of the current run
9105 *
9106 * @return the variable's pseudo cost score value for the given LP solution value,
9107 * only using the pseudo cost information of the current run
9108 *
9109 * @pre This method can be called if @p scip is in one of the following stages:
9110 * - \ref SCIP_STAGE_INITPRESOLVE
9111 * - \ref SCIP_STAGE_PRESOLVING
9112 * - \ref SCIP_STAGE_EXITPRESOLVE
9113 * - \ref SCIP_STAGE_PRESOLVED
9114 * - \ref SCIP_STAGE_INITSOLVE
9115 * - \ref SCIP_STAGE_SOLVING
9116 * - \ref SCIP_STAGE_SOLVED
9117 */
9118 SCIP_Real SCIPgetVarPseudocostScoreCurrentRun(
9119 SCIP* scip, /**< SCIP data structure */
9120 SCIP_VAR* var, /**< problem variable */
9121 SCIP_Real solval /**< variable's LP solution value */
9122 )
9123 {
9124 SCIP_Real downsol;
9125 SCIP_Real upsol;
9126 SCIP_Real pscostdown;
9127 SCIP_Real pscostup;
9128
9129 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9130
9131 assert( var->scip == scip );
9132
9133 downsol = SCIPsetFeasCeil(scip->set, solval-1.0);
9134 upsol = SCIPsetFeasFloor(scip->set, solval+1.0);
9135 pscostdown = SCIPvarGetPseudocostCurrentRun(var, scip->stat, downsol-solval);
9136 pscostup = SCIPvarGetPseudocostCurrentRun(var, scip->stat, upsol-solval);
9137
9138 return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup);
9139 }
9140
9141 /** returns the variable's VSIDS value
9142 *
9143 * @return the variable's VSIDS value
9144 *
9145 * @pre This method can be called if @p scip is in one of the following stages:
9146 * - \ref SCIP_STAGE_INITPRESOLVE
9147 * - \ref SCIP_STAGE_PRESOLVING
9148 * - \ref SCIP_STAGE_EXITPRESOLVE
9149 * - \ref SCIP_STAGE_PRESOLVED
9150 * - \ref SCIP_STAGE_INITSOLVE
9151 * - \ref SCIP_STAGE_SOLVING
9152 * - \ref SCIP_STAGE_SOLVED
9153 */
9154 SCIP_Real SCIPgetVarVSIDS(
9155 SCIP* scip, /**< SCIP data structure */
9156 SCIP_VAR* var, /**< problem variable */
9157 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9158 )
9159 {
9160 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDS", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9161
9162 assert( var->scip == scip );
9163
9164 if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
9165 {
9166 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
9167 return SCIP_INVALID;
9168 }
9169
9170 return SCIPvarGetVSIDS(var, scip->stat, dir);
9171 }
9172
9173 /** returns the variable's VSIDS value only using conflicts of the current run
9174 *
9175 * @return the variable's VSIDS value only using conflicts of the current run
9176 *
9177 * @pre This method can be called if @p scip is in one of the following stages:
9178 * - \ref SCIP_STAGE_INITPRESOLVE
9179 * - \ref SCIP_STAGE_PRESOLVING
9180 * - \ref SCIP_STAGE_EXITPRESOLVE
9181 * - \ref SCIP_STAGE_PRESOLVED
9182 * - \ref SCIP_STAGE_INITSOLVE
9183 * - \ref SCIP_STAGE_SOLVING
9184 * - \ref SCIP_STAGE_SOLVED
9185 */
9186 SCIP_Real SCIPgetVarVSIDSCurrentRun(
9187 SCIP* scip, /**< SCIP data structure */
9188 SCIP_VAR* var, /**< problem variable */
9189 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9190 )
9191 {
9192 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDSCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9193
9194 assert( var->scip == scip );
9195
9196 if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
9197 {
9198 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
9199 return SCIP_INVALID;
9200 }
9201
9202 return SCIPvarGetVSIDSCurrentRun(var, scip->stat, dir);
9203 }
9204
9205 /** returns the variable's conflict score value
9206 *
9207 * @return the variable's conflict score value
9208 *
9209 * @pre This method can be called if @p scip is in one of the following stages:
9210 * - \ref SCIP_STAGE_INITPRESOLVE
9211 * - \ref SCIP_STAGE_PRESOLVING
9212 * - \ref SCIP_STAGE_EXITPRESOLVE
9213 * - \ref SCIP_STAGE_PRESOLVED
9214 * - \ref SCIP_STAGE_INITSOLVE
9215 * - \ref SCIP_STAGE_SOLVING
9216 * - \ref SCIP_STAGE_SOLVED
9217 */
9218 SCIP_Real SCIPgetVarConflictScore(
9219 SCIP* scip, /**< SCIP data structure */
9220 SCIP_VAR* var /**< problem variable */
9221 )
9222 {
9223 SCIP_Real downscore;
9224 SCIP_Real upscore;
9225
9226 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9227
9228 assert( var->scip == scip );
9229
9230 downscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9231 upscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9232
9233 return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9234 }
9235
9236 /** returns the variable's conflict score value only using conflicts of the current run
9237 *
9238 * @return the variable's conflict score value only using conflicts of the current run
9239 *
9240 * @pre This method can be called if @p scip is in one of the following stages:
9241 * - \ref SCIP_STAGE_INITPRESOLVE
9242 * - \ref SCIP_STAGE_PRESOLVING
9243 * - \ref SCIP_STAGE_EXITPRESOLVE
9244 * - \ref SCIP_STAGE_PRESOLVED
9245 * - \ref SCIP_STAGE_INITSOLVE
9246 * - \ref SCIP_STAGE_SOLVING
9247 * - \ref SCIP_STAGE_SOLVED
9248 */
9249 SCIP_Real SCIPgetVarConflictScoreCurrentRun(
9250 SCIP* scip, /**< SCIP data structure */
9251 SCIP_VAR* var /**< problem variable */
9252 )
9253 {
9254 SCIP_Real downscore;
9255 SCIP_Real upscore;
9256
9257 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9258
9259 assert( var->scip == scip );
9260
9261 downscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9262 upscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9263
9264 return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9265 }
9266
9267 /** returns the variable's conflict length score
9268 *
9269 * @return the variable's conflict length score
9270 *
9271 * @pre This method can be called if @p scip is in one of the following stages:
9272 * - \ref SCIP_STAGE_INITPRESOLVE
9273 * - \ref SCIP_STAGE_PRESOLVING
9274 * - \ref SCIP_STAGE_EXITPRESOLVE
9275 * - \ref SCIP_STAGE_PRESOLVED
9276 * - \ref SCIP_STAGE_INITSOLVE
9277 * - \ref SCIP_STAGE_SOLVING
9278 * - \ref SCIP_STAGE_SOLVED
9279 */
9280 SCIP_Real SCIPgetVarConflictlengthScore(
9281 SCIP* scip, /**< SCIP data structure */
9282 SCIP_VAR* var /**< problem variable */
9283 )
9284 {
9285 SCIP_Real downscore;
9286 SCIP_Real upscore;
9287
9288 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9289
9290 assert( var->scip == scip );
9291
9292 downscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_DOWNWARDS);
9293 upscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_UPWARDS);
9294
9295 return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9296 }
9297
9298 /** returns the variable's conflict length score only using conflicts of the current run
9299 *
9300 * @return the variable's conflict length score only using conflicts of the current run
9301 *
9302 * @pre This method can be called if @p scip is in one of the following stages:
9303 * - \ref SCIP_STAGE_INITPRESOLVE
9304 * - \ref SCIP_STAGE_PRESOLVING
9305 * - \ref SCIP_STAGE_EXITPRESOLVE
9306 * - \ref SCIP_STAGE_PRESOLVED
9307 * - \ref SCIP_STAGE_INITSOLVE
9308 * - \ref SCIP_STAGE_SOLVING
9309 * - \ref SCIP_STAGE_SOLVED
9310 */
9311 SCIP_Real SCIPgetVarConflictlengthScoreCurrentRun(
9312 SCIP* scip, /**< SCIP data structure */
9313 SCIP_VAR* var /**< problem variable */
9314 )
9315 {
9316 SCIP_Real downscore;
9317 SCIP_Real upscore;
9318
9319 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9320
9321 assert( var->scip == scip );
9322
9323 downscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_DOWNWARDS);
9324 upscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_UPWARDS);
9325
9326 return SCIPbranchGetScore(scip->set, var, downscore, upscore);
9327 }
9328
9329 /** returns the variable's average conflict length
9330 *
9331 * @return the variable's average conflict length
9332 *
9333 * @pre This method can be called if @p scip is in one of the following stages:
9334 * - \ref SCIP_STAGE_INITPRESOLVE
9335 * - \ref SCIP_STAGE_PRESOLVING
9336 * - \ref SCIP_STAGE_EXITPRESOLVE
9337 * - \ref SCIP_STAGE_PRESOLVED
9338 * - \ref SCIP_STAGE_INITSOLVE
9339 * - \ref SCIP_STAGE_SOLVING
9340 * - \ref SCIP_STAGE_SOLVED
9341 */
9342 SCIP_Real SCIPgetVarAvgConflictlength(
9343 SCIP* scip, /**< SCIP data structure */
9344 SCIP_VAR* var, /**< problem variable */
9345 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9346 )
9347 {
9348 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlength", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9349
9350 assert( var->scip == scip );
9351
9352 return SCIPvarGetAvgConflictlength(var, dir);
9353 }
9354
9355 /** returns the variable's average conflict length only using conflicts of the current run
9356 *
9357 * @return the variable's average conflict length only using conflicts of the current run
9358 *
9359 * @pre This method can be called if @p scip is in one of the following stages:
9360 * - \ref SCIP_STAGE_INITPRESOLVE
9361 * - \ref SCIP_STAGE_PRESOLVING
9362 * - \ref SCIP_STAGE_EXITPRESOLVE
9363 * - \ref SCIP_STAGE_PRESOLVED
9364 * - \ref SCIP_STAGE_INITSOLVE
9365 * - \ref SCIP_STAGE_SOLVING
9366 * - \ref SCIP_STAGE_SOLVED
9367 */
9368 SCIP_Real SCIPgetVarAvgConflictlengthCurrentRun(
9369 SCIP* scip, /**< SCIP data structure */
9370 SCIP_VAR* var, /**< problem variable */
9371 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9372 )
9373 {
9374 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlengthCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9375
9376 assert( var->scip == scip );
9377
9378 return SCIPvarGetAvgConflictlengthCurrentRun(var, dir);
9379 }
9380
9381 /** returns the average number of inferences found after branching on the variable in given direction;
9382 * if branching on the variable in the given direction was yet evaluated, the average number of inferences
9383 * over all variables for branching in the given direction is returned
9384 *
9385 * @return the average number of inferences found after branching on the variable in given direction
9386 *
9387 * @pre This method can be called if @p scip is in one of the following stages:
9388 * - \ref SCIP_STAGE_INITPRESOLVE
9389 * - \ref SCIP_STAGE_PRESOLVING
9390 * - \ref SCIP_STAGE_EXITPRESOLVE
9391 * - \ref SCIP_STAGE_PRESOLVED
9392 * - \ref SCIP_STAGE_INITSOLVE
9393 * - \ref SCIP_STAGE_SOLVING
9394 * - \ref SCIP_STAGE_SOLVED
9395 */
9396 SCIP_Real SCIPgetVarAvgInferences(
9397 SCIP* scip, /**< SCIP data structure */
9398 SCIP_VAR* var, /**< problem variable */
9399 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9400 )
9401 {
9402 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferences", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9403
9404 assert( var->scip == scip );
9405
9406 return SCIPvarGetAvgInferences(var, scip->stat, dir);
9407 }
9408
9409 /** returns the average number of inferences found after branching on the variable in given direction in the current run;
9410 * if branching on the variable in the given direction was yet evaluated, the average number of inferences
9411 * over all variables for branching in the given direction is returned
9412 *
9413 * @return the average number of inferences found after branching on the variable in given direction in the current run
9414 *
9415 * @pre This method can be called if @p scip is in one of the following stages:
9416 * - \ref SCIP_STAGE_INITPRESOLVE
9417 * - \ref SCIP_STAGE_PRESOLVING
9418 * - \ref SCIP_STAGE_EXITPRESOLVE
9419 * - \ref SCIP_STAGE_PRESOLVED
9420 * - \ref SCIP_STAGE_INITSOLVE
9421 * - \ref SCIP_STAGE_SOLVING
9422 * - \ref SCIP_STAGE_SOLVED
9423 */
9424 SCIP_Real SCIPgetVarAvgInferencesCurrentRun(
9425 SCIP* scip, /**< SCIP data structure */
9426 SCIP_VAR* var, /**< problem variable */
9427 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9428 )
9429 {
9430 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferencesCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9431
9432 assert( var->scip == scip );
9433
9434 return SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, dir);
9435 }
9436
9437 /** returns the variable's average inference score value
9438 *
9439 * @return the variable's average inference score value
9440 *
9441 * @pre This method can be called if @p scip is in one of the following stages:
9442 * - \ref SCIP_STAGE_INITPRESOLVE
9443 * - \ref SCIP_STAGE_PRESOLVING
9444 * - \ref SCIP_STAGE_EXITPRESOLVE
9445 * - \ref SCIP_STAGE_PRESOLVED
9446 * - \ref SCIP_STAGE_INITSOLVE
9447 * - \ref SCIP_STAGE_SOLVING
9448 * - \ref SCIP_STAGE_SOLVED
9449 */
9450 SCIP_Real SCIPgetVarAvgInferenceScore(
9451 SCIP* scip, /**< SCIP data structure */
9452 SCIP_VAR* var /**< problem variable */
9453 )
9454 {
9455 SCIP_Real inferdown;
9456 SCIP_Real inferup;
9457
9458 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9459
9460 assert( var->scip == scip );
9461
9462 inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9463 inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9464
9465 return SCIPbranchGetScore(scip->set, var, inferdown, inferup);
9466 }
9467
9468 /** returns the variable's average inference score value only using inferences of the current run
9469 *
9470 * @return the variable's average inference score value only using inferences of the current run
9471 *
9472 * @pre This method can be called if @p scip is in one of the following stages:
9473 * - \ref SCIP_STAGE_INITPRESOLVE
9474 * - \ref SCIP_STAGE_PRESOLVING
9475 * - \ref SCIP_STAGE_EXITPRESOLVE
9476 * - \ref SCIP_STAGE_PRESOLVED
9477 * - \ref SCIP_STAGE_INITSOLVE
9478 * - \ref SCIP_STAGE_SOLVING
9479 * - \ref SCIP_STAGE_SOLVED
9480 */
9481 SCIP_Real SCIPgetVarAvgInferenceScoreCurrentRun(
9482 SCIP* scip, /**< SCIP data structure */
9483 SCIP_VAR* var /**< problem variable */
9484 )
9485 {
9486 SCIP_Real inferdown;
9487 SCIP_Real inferup;
9488
9489 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9490
9491 assert( var->scip == scip );
9492
9493 inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9494 inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9495
9496 return SCIPbranchGetScore(scip->set, var, inferdown, inferup);
9497 }
9498
9499 /** initializes the upwards and downwards pseudocosts, conflict scores, conflict lengths, inference scores, cutoff scores
9500 * of a variable to the given values
9501 *
9502 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9503 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9504 *
9505 * @pre This method can be called if @p scip is in one of the following stages:
9506 * - \ref SCIP_STAGE_TRANSFORMED
9507 * - \ref SCIP_STAGE_INITPRESOLVE
9508 * - \ref SCIP_STAGE_PRESOLVING
9509 * - \ref SCIP_STAGE_EXITPRESOLVE
9510 * - \ref SCIP_STAGE_PRESOLVED
9511 * - \ref SCIP_STAGE_INITSOLVE
9512 * - \ref SCIP_STAGE_SOLVING
9513 */
9514 SCIP_RETCODE SCIPinitVarBranchStats(
9515 SCIP* scip, /**< SCIP data structure */
9516 SCIP_VAR* var, /**< variable which should be initialized */
9517 SCIP_Real downpscost, /**< value to which pseudocosts for downwards branching should be initialized */
9518 SCIP_Real uppscost, /**< value to which pseudocosts for upwards branching should be initialized */
9519 SCIP_Real downvsids, /**< value to which VSIDS score for downwards branching should be initialized */
9520 SCIP_Real upvsids, /**< value to which VSIDS score for upwards branching should be initialized */
9521 SCIP_Real downconflen, /**< value to which conflict length score for downwards branching should be initialized */
9522 SCIP_Real upconflen, /**< value to which conflict length score for upwards branching should be initialized */
9523 SCIP_Real downinfer, /**< value to which inference counter for downwards branching should be initialized */
9524 SCIP_Real upinfer, /**< value to which inference counter for upwards branching should be initialized */
9525 SCIP_Real downcutoff, /**< value to which cutoff counter for downwards branching should be initialized */
9526 SCIP_Real upcutoff /**< value to which cutoff counter for upwards branching should be initialized */
9527 )
9528 {
9529 SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
9530
9531 assert(downpscost >= 0.0 && uppscost >= 0.0);
9532 assert(downvsids >= 0.0 && upvsids >= 0.0);
9533 assert(downconflen >= 0.0 && upconflen >= 0.0);
9534 assert(downinfer >= 0.0 && upinfer >= 0.0);
9535 assert(downcutoff >= 0.0 && upcutoff >= 0.0);
9536
9537 if( !SCIPisFeasZero(scip, downpscost) || !SCIPisFeasZero(scip, downvsids)
9538 || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) )
9539 {
9540 SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, 1) );
9541 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, -1.0, downpscost, 1.0) );
9542 SCIP_CALL( SCIPvarIncInferenceSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downinfer) );
9543 SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downvsids) );
9544 SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downcutoff) );
9545 }
9546
9547 if( !SCIPisFeasZero(scip, downconflen) )
9548 {
9549 SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downconflen) );
9550 }
9551
9552 if( !SCIPisFeasZero(scip, uppscost) || !SCIPisFeasZero(scip, upvsids)
9553 || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) )
9554 {
9555 SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, 1) );
9556 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, 1.0, uppscost, 1.0) );
9557 SCIP_CALL( SCIPvarIncInferenceSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upinfer) );
9558 SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upvsids) );
9559 SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upcutoff) );
9560 }
9561
9562 if( !SCIPisFeasZero(scip, upconflen) )
9563 {
9564 SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upconflen) );
9565 }
9566
9567 return SCIP_OKAY;
9568 }
9569
9570 /** initializes the upwards and downwards conflict scores, conflict lengths, inference scores, cutoff scores of a
9571 * variable w.r.t. a value by the given values (SCIP_VALUEHISTORY)
9572 *
9573 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9574 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9575 *
9576 * @pre This method can be called if @p scip is in one of the following stages:
9577 * - \ref SCIP_STAGE_TRANSFORMED
9578 * - \ref SCIP_STAGE_INITPRESOLVE
9579 * - \ref SCIP_STAGE_PRESOLVING
9580 * - \ref SCIP_STAGE_EXITPRESOLVE
9581 * - \ref SCIP_STAGE_PRESOLVED
9582 * - \ref SCIP_STAGE_INITSOLVE
9583 * - \ref SCIP_STAGE_SOLVING
9584 */
9585 SCIP_RETCODE SCIPinitVarValueBranchStats(
9586 SCIP* scip, /**< SCIP data structure */
9587 SCIP_VAR* var, /**< variable which should be initialized */
9588 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
9589 SCIP_Real downvsids, /**< value to which VSIDS score for downwards branching should be initialized */
9590 SCIP_Real upvsids, /**< value to which VSIDS score for upwards branching should be initialized */
9591 SCIP_Real downconflen, /**< value to which conflict length score for downwards branching should be initialized */
9592 SCIP_Real upconflen, /**< value to which conflict length score for upwards branching should be initialized */
9593 SCIP_Real downinfer, /**< value to which inference counter for downwards branching should be initialized */
9594 SCIP_Real upinfer, /**< value to which inference counter for upwards branching should be initialized */
9595 SCIP_Real downcutoff, /**< value to which cutoff counter for downwards branching should be initialized */
9596 SCIP_Real upcutoff /**< value to which cutoff counter for upwards branching should be initialized */
9597 )
9598 {
9599 SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarValueBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
9600
9601 assert(downvsids >= 0.0 && upvsids >= 0.0);
9602 assert(downconflen >= 0.0 && upconflen >= 0.0);
9603 assert(downinfer >= 0.0 && upinfer >= 0.0);
9604 assert(downcutoff >= 0.0 && upcutoff >= 0.0);
9605
9606 if( !SCIPisFeasZero(scip, downvsids) || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) )
9607 {
9608 SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, 1) );
9609 SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downinfer) );
9610 SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downvsids) );
9611 SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downcutoff) );
9612 }
9613
9614 if( !SCIPisFeasZero(scip, downconflen) )
9615 {
9616 SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downconflen) );
9617 }
9618
9619 if( !SCIPisFeasZero(scip, upvsids) || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) )
9620 {
9621 SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, 1) );
9622 SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upinfer) );
9623 SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upvsids) );
9624 SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upcutoff) );
9625 }
9626
9627 if( !SCIPisFeasZero(scip, upconflen) )
9628 {
9629 SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upconflen) );
9630 }
9631
9632 return SCIP_OKAY;
9633 }
9634
9635 /** returns the average number of cutoffs found after branching on the variable in given direction;
9636 * if branching on the variable in the given direction was yet evaluated, the average number of cutoffs
9637 * over all variables for branching in the given direction is returned
9638 *
9639 * @return the average number of cutoffs found after branching on the variable in given direction
9640 *
9641 * @pre This method can be called if @p scip is in one of the following stages:
9642 * - \ref SCIP_STAGE_INITPRESOLVE
9643 * - \ref SCIP_STAGE_PRESOLVING
9644 * - \ref SCIP_STAGE_EXITPRESOLVE
9645 * - \ref SCIP_STAGE_PRESOLVED
9646 * - \ref SCIP_STAGE_INITSOLVE
9647 * - \ref SCIP_STAGE_SOLVING
9648 * - \ref SCIP_STAGE_SOLVED
9649 */
9650 SCIP_Real SCIPgetVarAvgCutoffs(
9651 SCIP* scip, /**< SCIP data structure */
9652 SCIP_VAR* var, /**< problem variable */
9653 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9654 )
9655 {
9656 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffs", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9657
9658 assert( var->scip == scip );
9659
9660 return SCIPvarGetAvgCutoffs(var, scip->stat, dir);
9661 }
9662
9663 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run;
9664 * if branching on the variable in the given direction was yet evaluated, the average number of cutoffs
9665 * over all variables for branching in the given direction is returned
9666 *
9667 * @return the average number of cutoffs found after branching on the variable in given direction in the current run
9668 *
9669 * @pre This method can be called if @p scip is in one of the following stages:
9670 * - \ref SCIP_STAGE_INITPRESOLVE
9671 * - \ref SCIP_STAGE_PRESOLVING
9672 * - \ref SCIP_STAGE_EXITPRESOLVE
9673 * - \ref SCIP_STAGE_PRESOLVED
9674 * - \ref SCIP_STAGE_INITSOLVE
9675 * - \ref SCIP_STAGE_SOLVING
9676 * - \ref SCIP_STAGE_SOLVED
9677 */
9678 SCIP_Real SCIPgetVarAvgCutoffsCurrentRun(
9679 SCIP* scip, /**< SCIP data structure */
9680 SCIP_VAR* var, /**< problem variable */
9681 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
9682 )
9683 {
9684 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffsCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9685
9686 assert( var->scip == scip );
9687
9688 return SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, dir);
9689 }
9690
9691 /** returns the variable's average cutoff score value
9692 *
9693 * @return the variable's average cutoff score value
9694 *
9695 * @pre This method can be called if @p scip is in one of the following stages:
9696 * - \ref SCIP_STAGE_INITPRESOLVE
9697 * - \ref SCIP_STAGE_PRESOLVING
9698 * - \ref SCIP_STAGE_EXITPRESOLVE
9699 * - \ref SCIP_STAGE_PRESOLVED
9700 * - \ref SCIP_STAGE_INITSOLVE
9701 * - \ref SCIP_STAGE_SOLVING
9702 * - \ref SCIP_STAGE_SOLVED
9703 */
9704 SCIP_Real SCIPgetVarAvgCutoffScore(
9705 SCIP* scip, /**< SCIP data structure */
9706 SCIP_VAR* var /**< problem variable */
9707 )
9708 {
9709 SCIP_Real cutoffdown;
9710 SCIP_Real cutoffup;
9711
9712 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9713
9714 assert( var->scip == scip );
9715
9716 cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9717 cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9718
9719 return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup);
9720 }
9721
9722 /** returns the variable's average cutoff score value, only using cutoffs of the current run
9723 *
9724 * @return the variable's average cutoff score value, only using cutoffs of the current run
9725 *
9726 * @pre This method can be called if @p scip is in one of the following stages:
9727 * - \ref SCIP_STAGE_INITPRESOLVE
9728 * - \ref SCIP_STAGE_PRESOLVING
9729 * - \ref SCIP_STAGE_EXITPRESOLVE
9730 * - \ref SCIP_STAGE_PRESOLVED
9731 * - \ref SCIP_STAGE_INITSOLVE
9732 * - \ref SCIP_STAGE_SOLVING
9733 * - \ref SCIP_STAGE_SOLVED
9734 */
9735 SCIP_Real SCIPgetVarAvgCutoffScoreCurrentRun(
9736 SCIP* scip, /**< SCIP data structure */
9737 SCIP_VAR* var /**< problem variable */
9738 )
9739 {
9740 SCIP_Real cutoffdown;
9741 SCIP_Real cutoffup;
9742
9743 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9744
9745 assert( var->scip == scip );
9746
9747 cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9748 cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9749
9750 return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup);
9751 }
9752
9753 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given
9754 * factor
9755 *
9756 * @return the variable's average inference/cutoff score value
9757 *
9758 * @pre This method can be called if @p scip is in one of the following stages:
9759 * - \ref SCIP_STAGE_INITPRESOLVE
9760 * - \ref SCIP_STAGE_PRESOLVING
9761 * - \ref SCIP_STAGE_EXITPRESOLVE
9762 * - \ref SCIP_STAGE_PRESOLVED
9763 * - \ref SCIP_STAGE_INITSOLVE
9764 * - \ref SCIP_STAGE_SOLVING
9765 * - \ref SCIP_STAGE_SOLVED
9766 */
9767 SCIP_Real SCIPgetVarAvgInferenceCutoffScore(
9768 SCIP* scip, /**< SCIP data structure */
9769 SCIP_VAR* var, /**< problem variable */
9770 SCIP_Real cutoffweight /**< factor to weigh average number of cutoffs in branching score */
9771 )
9772 {
9773 SCIP_Real avginferdown;
9774 SCIP_Real avginferup;
9775 SCIP_Real avginfer;
9776 SCIP_Real inferdown;
9777 SCIP_Real inferup;
9778 SCIP_Real cutoffdown;
9779 SCIP_Real cutoffup;
9780
9781 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9782
9783 assert( var->scip == scip );
9784
9785 avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_DOWNWARDS);
9786 avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_UPWARDS);
9787 avginfer = (avginferdown + avginferup)/2.0;
9788 inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9789 inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9790 cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9791 cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9792
9793 return SCIPbranchGetScore(scip->set, var,
9794 inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup);
9795 }
9796
9797 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given
9798 * factor, only using inferences and cutoffs of the current run
9799 *
9800 * @return the variable's average inference/cutoff score value, only using inferences and cutoffs of the current run
9801 *
9802 * @pre This method can be called if @p scip is in one of the following stages:
9803 * - \ref SCIP_STAGE_INITPRESOLVE
9804 * - \ref SCIP_STAGE_PRESOLVING
9805 * - \ref SCIP_STAGE_EXITPRESOLVE
9806 * - \ref SCIP_STAGE_PRESOLVED
9807 * - \ref SCIP_STAGE_INITSOLVE
9808 * - \ref SCIP_STAGE_SOLVING
9809 * - \ref SCIP_STAGE_SOLVED
9810 */
9811 SCIP_Real SCIPgetVarAvgInferenceCutoffScoreCurrentRun(
9812 SCIP* scip, /**< SCIP data structure */
9813 SCIP_VAR* var, /**< problem variable */
9814 SCIP_Real cutoffweight /**< factor to weigh average number of cutoffs in branching score */
9815 )
9816 {
9817 SCIP_Real avginferdown;
9818 SCIP_Real avginferup;
9819 SCIP_Real avginfer;
9820 SCIP_Real inferdown;
9821 SCIP_Real inferup;
9822 SCIP_Real cutoffdown;
9823 SCIP_Real cutoffup;
9824
9825 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
9826
9827 assert( var->scip == scip );
9828
9829 avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_DOWNWARDS);
9830 avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_UPWARDS);
9831 avginfer = (avginferdown + avginferup)/2.0;
9832 inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9833 inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9834 cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS);
9835 cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS);
9836
9837 return SCIPbranchGetScore(scip->set, var,
9838 inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup);
9839 }
9840
9841 /** outputs variable information to file stream via the message system
9842 *
9843 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
9844 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
9845 *
9846 * @pre This method can be called if @p scip is in one of the following stages:
9847 * - \ref SCIP_STAGE_PROBLEM
9848 * - \ref SCIP_STAGE_TRANSFORMING
9849 * - \ref SCIP_STAGE_TRANSFORMED
9850 * - \ref SCIP_STAGE_INITPRESOLVE
9851 * - \ref SCIP_STAGE_PRESOLVING
9852 * - \ref SCIP_STAGE_EXITPRESOLVE
9853 * - \ref SCIP_STAGE_PRESOLVED
9854 * - \ref SCIP_STAGE_INITSOLVE
9855 * - \ref SCIP_STAGE_SOLVING
9856 * - \ref SCIP_STAGE_SOLVED
9857 * - \ref SCIP_STAGE_EXITSOLVE
9858 * - \ref SCIP_STAGE_FREETRANS
9859 *
9860 * @note If the message handler is set to a NULL pointer nothing will be printed
9861 */
9862 SCIP_RETCODE SCIPprintVar(
9863 SCIP* scip, /**< SCIP data structure */
9864 SCIP_VAR* var, /**< problem variable */
9865 FILE* file /**< output file (or NULL for standard output) */
9866 )
9867 {
9868 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
9869
9870 SCIP_CALL( SCIPvarPrint(var, scip->set, scip->messagehdlr, file) );
9871
9872 return SCIP_OKAY;
9873 }
9874