Scippy

SCIP

Solving Constraint Integer Programs

scip_var.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 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>
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"
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 */
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
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 {
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
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 */
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 */
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]",
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 */
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 */
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 */
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 */
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
492
493 switch( scip->set->stage )
494 {
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
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 */
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 */
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 */
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 */
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 /* coverity[dead_error_line] */
1053 case SCIPPARSEPOLYNOMIAL_STATE_END:
1054 /* coverity[dead_error_line] */
1055 case SCIPPARSEPOLYNOMIAL_STATE_ERROR:
1056 default:
1057 SCIPerrorMessage("unexpected state\n");
1058 return SCIP_READERROR;
1059 }
1060 }
1061
1062 /* set end pointer */
1063 *endptr = (char*)str;
1064
1065 /* check state at end of string */
1066 switch( state )
1067 {
1068 case SCIPPARSEPOLYNOMIAL_STATE_BEGIN:
1069 case SCIPPARSEPOLYNOMIAL_STATE_END:
1070 case SCIPPARSEPOLYNOMIAL_STATE_INTERMED:
1071 {
1072 if( coef != SCIP_INVALID ) /*lint !e777*/
1073 {
1074 /* push last monomial */
1075 SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars);
1076 if( monomialssize <= *nmonomials )
1077 {
1078 monomialssize = *nmonomials+1;
1079 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, *nmonomials, monomialssize) );
1080 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, *nmonomials, monomialssize) );
1081 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, *nmonomials, monomialssize) );
1082 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, *nmonomials, monomialssize) );
1083 }
1084
1085 if( nvars > 0 )
1086 {
1087 /* shrink vars and exponents array to needed size and take over ownership */
1088 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vars, varssize, nvars) );
1089 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &exponents, varssize, nvars) );
1090 (*monomialvars)[*nmonomials] = vars;
1091 (*monomialexps)[*nmonomials] = exponents;
1092 vars = NULL;
1093 exponents = NULL;
1094 }
1095 else
1096 {
1097 (*monomialvars)[*nmonomials] = NULL;
1098 (*monomialexps)[*nmonomials] = NULL;
1099 }
1100 (*monomialcoefs)[*nmonomials] = coef;
1101 (*monomialnvars)[*nmonomials] = nvars;
1102 ++*nmonomials;
1103 }
1104
1105 *success = TRUE;
1106 break;
1107 }
1108
1109 case SCIPPARSEPOLYNOMIAL_STATE_COEF:
1110 case SCIPPARSEPOLYNOMIAL_STATE_VARS:
1111 case SCIPPARSEPOLYNOMIAL_STATE_EXPONENT:
1112 {
1113 SCIPerrorMessage("unexpected parsing state at end of polynomial string\n");
1114 }
1115 /*lint -fallthrough*/
1116 case SCIPPARSEPOLYNOMIAL_STATE_ERROR:
1117 assert(!*success);
1118 break;
1119 }
1120
1121 /* free memory to store current monomial, if still existing */
1122 SCIPfreeBlockMemoryArrayNull(scip, &vars, varssize);
1123 SCIPfreeBlockMemoryArrayNull(scip, &exponents, varssize);
1124
1125 if( *success && *nmonomials > 0 )
1126 {
1127 /* shrink arrays to required size, so we do not need to keep monomialssize around */
1128 assert(*nmonomials <= monomialssize);
1129 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, monomialssize, *nmonomials) );
1130 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, monomialssize, *nmonomials) );
1131 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, monomialssize, *nmonomials) );
1132 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, monomialssize, *nmonomials) );
1133
1134 /* SCIPwriteVarsPolynomial(scip, NULL, *monomialvars, *monomialexps, *monomialcoefs, *monomialnvars, *nmonomials, FALSE); */
1135 }
1136 else
1137 {
1138 /* in case of error, cleanup all data here */
1139 SCIPfreeParseVarsPolynomialData(scip, monomialvars, monomialexps, monomialcoefs, monomialnvars, *nmonomials);
1140 *nmonomials = 0;
1141 }
1142
1143 return SCIP_OKAY;
1144}
1145
1146/** frees memory allocated when parsing a signomial from a string
1147 *
1148 * @pre This method can be called if @p scip is in one of the following stages:
1149 * - \ref SCIP_STAGE_PROBLEM
1150 * - \ref SCIP_STAGE_TRANSFORMING
1151 * - \ref SCIP_STAGE_INITPRESOLVE
1152 * - \ref SCIP_STAGE_PRESOLVING
1153 * - \ref SCIP_STAGE_EXITPRESOLVE
1154 * - \ref SCIP_STAGE_PRESOLVED
1155 * - \ref SCIP_STAGE_SOLVING
1156 */
1158 SCIP* scip, /**< SCIP data structure */
1159 SCIP_VAR**** monomialvars, /**< pointer to store arrays with variables for each monomial */
1160 SCIP_Real*** monomialexps, /**< pointer to store arrays with variable exponents */
1161 SCIP_Real** monomialcoefs, /**< pointer to store array with monomial coefficients */
1162 int** monomialnvars, /**< pointer to store array with number of variables for each monomial */
1163 int nmonomials /**< pointer to store number of parsed monomials */
1164 )
1165{
1166 int i;
1167
1168 assert(scip != NULL);
1169 assert(monomialvars != NULL);
1170 assert(monomialexps != NULL);
1171 assert(monomialcoefs != NULL);
1172 assert(monomialnvars != NULL);
1173
1174 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfreeParseVarsPolynomialData", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
1175
1176 if( nmonomials == 0 )
1177 return;
1178
1179 assert(*monomialvars != NULL);
1180 assert(*monomialexps != NULL);
1181 assert(*monomialcoefs != NULL);
1182 assert(*monomialnvars != NULL);
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 */
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 */
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
1272 case SCIP_STAGE_SOLVING:
1273 case SCIP_STAGE_SOLVED:
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 */
1300 SCIP* scip, /**< SCIP data structure */
1301 SCIP_VAR* var, /**< variable */
1302 const char* name /**< new name of constraint */
1303 )
1304{
1306 assert( var->scip == scip );
1307
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
1767 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarLinearSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
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 */
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 */
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 */
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 {
1876 if( var->data.original.transvar == NULL )
1877 return SCIP_INVALID;
1879
1881 return SCIPgetColRedcost(scip, SCIPvarGetCol(var));
1882
1884 return SCIP_INVALID;
1885
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 */
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 {
1922 if( var->data.original.transvar == NULL )
1923 return SCIP_INVALID;
1924 return SCIPgetVarImplRedcost(scip, var->data.original.transvar, varfixing);
1925
1927 return SCIPvarGetImplRedcost(var, scip->set, varfixing, scip->stat, scip->transprob, scip->lp);
1928
1930 return SCIP_INVALID;
1931
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 */
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 {
1966 if( var->data.original.transvar == NULL )
1967 return SCIP_INVALID;
1969
1972
1974 return SCIP_INVALID;
1975
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 */
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 {
2009 assert(var->data.original.transvar != NULL);
2010 return SCIPgetVarLbAtIndex(scip, var->data.original.transvar, bdchgidx, after);
2011
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
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
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);
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 */
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 {
2145 assert(var->data.original.transvar != NULL);
2146 return SCIPgetVarUbAtIndex(scip, var->data.original.transvar, bdchgidx, after);
2147
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
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
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);
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 */
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 */
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 */
2308 SCIP* scip, /**< SCIP data structure */
2309 SCIP_VAR* var /**< variable to get solution value for */
2310 )
2311{
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 */
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
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 */
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 */
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
2424
2425 SCIP_CALL( SCIPvarSetRelaxSol(var, scip->set, scip->relaxation, val, TRUE) );
2426
2427 if( val != 0.0 )
2428 SCIPrelaxationSetSolZero(scip->relaxation, 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 */
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
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 */
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
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 */
2538 SCIP* scip /**< SCIP data structure */
2539 )
2540{
2541 assert(scip != NULL);
2542
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 */
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 */
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
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 */
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
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 */
2633 SCIP* scip /**< SCIP data structure */
2634 )
2635{
2636 assert(scip != NULL);
2637
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 */
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');
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 */
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 */
2723 }
2724 else
2725 {
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 */
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);
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 */
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
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 */
2838static
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
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 */
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
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) */
3025static
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 */
3112 {
3113 /* create a new probing node for the strong branching child and apply the new bound for the variable */
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 {
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 }
3219 ++scip->stat->nsbtimesiterlimhit;
3220 /*lint -fallthrough*/
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 }
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 */
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 */
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
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,
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 */
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
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 */
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 );
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 */
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 );
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) */
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 */
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
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 */
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
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 */
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;
4096 SCIP_Longint oldnbestsolsfound = scip->primal->nbestsolsfound;
4097
4098 /* start clock for strong branching solutions */
4099 SCIPclockStart(scip->stat->sbsoltime, scip->set);
4100
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 */
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
4170 return -1;
4171
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 */
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
4204 return SCIP_LONGINT_MAX;
4205
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 */
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
4236 return 0;
4237
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 */
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*/
4283 case SCIP_STAGE_SOLVING:
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 */
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 */
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*/
4399 case SCIP_STAGE_SOLVING:
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 */
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*/
4484 case SCIP_STAGE_SOLVING:
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 */
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{
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
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 */
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{
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
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 */
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 */
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 */
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{
4683
4684 SCIPvarAdjustLb(var, scip->set, &newbound);
4685
4686 /* ignore tightenings of lower bounds to +infinity during solving process */
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
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
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
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