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