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