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 lpobjval;
2942 SCIP_Real localdown;
2943 SCIP_Real localup;
2944 SCIP_Bool localdownvalid;
2945 SCIP_Bool localupvalid;
2946
2947 assert(var != NULL);
2948 assert(lperror != NULL);
2949 assert(!SCIPinProbing(scip)); /* 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 lpobjval = SCIPgetLPObjval(scip);
2955 if( downvalid != NULL )
2956 *downvalid = FALSE;
2957 if( upvalid != NULL )
2958 *upvalid = FALSE;
2959 if( downinf != NULL )
2960 *downinf = FALSE;
2961 if( upinf != NULL )
2962 *upinf = FALSE;
2963 if( downconflict != NULL )
2964 *downconflict = FALSE;
2965 if( upconflict != NULL )
2966 *upconflict = FALSE;
2967
2969 {
2970 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
2971 return SCIP_INVALIDDATA;
2972 }
2973
2974 col = SCIPvarGetCol(var);
2975 assert(col != NULL);
2976
2977 if( !SCIPcolIsInLP(col) )
2978 {
2979 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
2980 return SCIP_INVALIDDATA;
2981 }
2982
2983 /* check if the solving process should be aborted */
2984 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
2985 {
2986 /* mark this as if the LP failed */
2987 *lperror = TRUE;
2988 return SCIP_OKAY;
2989 }
2990
2991 /* call strong branching for column with fractional value */
2992 SCIP_CALL( SCIPcolGetStrongbranch(col, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent,
2993 &localdown, &localup, &localdownvalid, &localupvalid, lperror) );
2994
2995 /* update lower bound by the higher pseudo objective value */
2996 if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
2997 {
2998 SCIP_Real oldbound;
2999 SCIP_Real newbound;
3000 SCIP_Real pseudoobjval;
3001 SCIP_BOUNDTYPE boundtype = SCIPvarGetBestBoundType(var);
3002
3003 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3004 {
3005 oldbound = SCIPvarGetUbLocal(var);
3006 newbound = SCIPfeasFloor(scip, SCIPvarGetLPSol(var));
3007 }
3008 else
3009 {
3010 oldbound = SCIPvarGetLbLocal(var);
3011 newbound = SCIPfeasCeil(scip, SCIPvarGetLPSol(var));
3012 }
3013
3014 if( scip->set->misc_exactsolve )
3015 pseudoobjval = SCIPlpGetModifiedProvedPseudoObjval(scip->lp, scip->set, var, oldbound, newbound, boundtype);
3016 else
3017 pseudoobjval = SCIPlpGetModifiedPseudoObjval(scip->lp, scip->set, scip->transprob, var, oldbound, newbound, boundtype);
3018
3019 if( pseudoobjval > lpobjval )
3020 {
3021 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3022 {
3023 if( !localdownvalid || localdown < pseudoobjval )
3024 {
3025 localdown = pseudoobjval;
3026 localdownvalid = TRUE;
3027 }
3028 }
3029 else
3030 {
3031 if( !localupvalid || localup < pseudoobjval )
3032 {
3033 localup = pseudoobjval;
3034 localupvalid = TRUE;
3035 }
3036 }
3037 }
3038 }
3039
3040 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3041 * declare the sub nodes infeasible
3042 */
3043 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3044 {
3045 if( !idempotent ) /*lint !e774*/
3046 {
3047 SCIP_CALL( analyzeStrongbranch(scip, var, NULL, NULL, downconflict, upconflict) );
3048 }
3049
3050 if( downinf != NULL )
3051 *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound);
3052 if( upinf != NULL )
3053 *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound);
3054 }
3055
3056 if( down != NULL )
3057 *down = localdown;
3058 if( up != NULL )
3059 *up = localup;
3060 if( downvalid != NULL )
3061 *downvalid = localdownvalid;
3062 if( upvalid != NULL )
3063 *upvalid = localupvalid;
3064
3065 return SCIP_OKAY;
3066}
3067
3068/** create, solve, and evaluate a single strong branching child (for strong branching with propagation) */
3069static
3071 SCIP* scip, /**< SCIP data structure */
3072 SCIP_VAR* var, /**< variable to get strong branching values for */
3073 SCIP_Bool down, /**< do we regard the down child? */
3074 SCIP_Bool firstchild, /**< is this the first of the two strong branching children? */
3075 SCIP_Bool propagate, /**< should domain propagation be performed? */
3076 SCIP_Real newbound, /**< new bound to apply at the strong branching child */
3077 int itlim, /**< iteration limit for strong branchings */
3078 int maxproprounds, /**< maximum number of propagation rounds (-1: no limit, -2: parameter
3079 * settings) */
3080 SCIP_Real* value, /**< stores dual bound for strong branching child */
3081 SCIP_Bool* valid, /**< stores whether the returned value is a valid dual bound, or NULL;
3082 * otherwise, it can only be used as an estimate value */
3083 SCIP_Longint* ndomreductions, /**< pointer to store the number of domain reductions found, or NULL */
3084 SCIP_Bool* conflict, /**< pointer to store whether a conflict constraint was created for an
3085 * infeasible strong branching child, or NULL */
3086 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred or the
3087 * solving process should be stopped (e.g., due to a time limit) */
3088 SCIP_VAR** vars, /**< active problem variables */
3089 int nvars, /**< number of active problem variables */
3090 SCIP_Real* newlbs, /**< array to store valid lower bounds for all active variables, or NULL */
3091 SCIP_Real* newubs, /**< array to store valid upper bounds for all active variables, or NULL */
3092 SCIP_Bool* foundsol, /**< pointer to store whether a primal solution was found during strong branching */
3093 SCIP_Bool* cutoff /**< pointer to store whether the strong branching child is infeasible */
3094 )
3095{
3096 SCIP_Longint ndomreds;
3097
3098 assert(value != NULL);
3099 assert(foundsol != NULL);
3100 assert(cutoff != NULL);
3101 assert(lperror != NULL);
3102 assert(valid != NULL ? !(*valid) : TRUE);
3103
3104 *foundsol = FALSE;
3105 *cutoff = FALSE;
3106 *lperror = FALSE;
3107
3108 /* check whether the strong branching child is already infeasible due to the bound change */
3109 if( down )
3110 {
3111 /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the
3112 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3113 * are valid for and were already applied at the probing root
3114 */
3115 if( newbound < SCIPvarGetLbLocal(var) - 0.5 )
3116 {
3117 *value = SCIPinfinity(scip);
3118
3119 if( valid != NULL )
3120 *valid = TRUE;
3121
3122 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3123 if( conflict != NULL )
3124 *conflict = TRUE;
3125
3126 *cutoff = TRUE;
3127
3128 return SCIP_OKAY;
3129 }
3130 }
3131 else
3132 {
3133 /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the
3134 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3135 * are valid for and were already applied at the probing root
3136 */
3137 if( newbound > SCIPvarGetUbLocal(var) + 0.5 )
3138 {
3139 *value = SCIPinfinity(scip);
3140
3141 if( valid != NULL )
3142 *valid = TRUE;
3143
3144 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3145 if( conflict != NULL )
3146 *conflict = TRUE;
3147
3148 *cutoff = TRUE;
3149
3150 return SCIP_OKAY;
3151 }
3152 }
3153
3154 /* we need to ensure that we can create at least one new probing node without exceeding the maximal tree depth */
3156 {
3157 /* create a new probing node for the strong branching child and apply the new bound for the variable */
3159
3160 if( down )
3161 {
3162 assert(SCIPisGE(scip, newbound, SCIPvarGetLbLocal(var)));
3163 if( SCIPisLT(scip, newbound, SCIPvarGetUbLocal(var)) )
3164 {
3165 SCIP_CALL( SCIPchgVarUbProbing(scip, var, newbound) );
3166 }
3167 }
3168 else
3169 {
3170 assert(SCIPisLE(scip, newbound, SCIPvarGetUbLocal(var)));
3171 if( SCIPisGT(scip, newbound, SCIPvarGetLbLocal(var)) )
3172 {
3173 SCIP_CALL( SCIPchgVarLbProbing(scip, var, newbound) );
3174 }
3175 }
3176 }
3177 else
3178 {
3179 if( valid != NULL )
3180 *valid = FALSE;
3181
3182 *cutoff = FALSE;
3183
3184 if( conflict != NULL )
3185 *conflict = FALSE;
3186
3187 return SCIP_OKAY;
3188 }
3189
3190 /* propagate domains at the probing node */
3191 if( propagate )
3192 {
3193 /* start time measuring */
3194 SCIPclockStart(scip->stat->strongpropclock, scip->set);
3195
3196 ndomreds = 0;
3197 SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, cutoff, &ndomreds) );
3198
3199 /* store number of domain reductions in strong branching */
3200 if( down )
3201 SCIPstatAdd(scip->stat, scip->set, nsbdowndomchgs, ndomreds);
3202 else
3203 SCIPstatAdd(scip->stat, scip->set, nsbupdomchgs, ndomreds);
3204
3205 if( ndomreductions != NULL )
3206 *ndomreductions = ndomreds;
3207
3208 /* stop time measuring */
3209 SCIPclockStop(scip->stat->strongpropclock, scip->set);
3210
3211 if( *cutoff )
3212 {
3213 *value = SCIPinfinity(scip);
3214
3215 if( valid != NULL )
3216 *valid = TRUE;
3217
3218 SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible during propagation\n",
3219 down ? "down" : "up", SCIPvarGetName(var));
3220 }
3221 }
3222
3223 /* if propagation did not already detect infeasibility, solve the probing LP */
3224 if( !(*cutoff) )
3225 {
3226 SCIP_CALL( SCIPsolveProbingLP(scip, itlim, lperror, cutoff) );
3227 assert(SCIPisLPRelax(scip));
3228
3229 if( *cutoff )
3230 {
3231 assert(!(*lperror));
3232
3233 *value = SCIPinfinity(scip);
3234
3235 if( valid != NULL )
3236 *valid = TRUE;
3237
3238 SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible in LP solving: status=%d\n",
3239 down ? "down" : "up", SCIPvarGetName(var), SCIPgetLPSolstat(scip));
3240 }
3241 else if( !(*lperror) )
3242 {
3243 /* save the lp solution status */
3244 scip->stat->lastsblpsolstats[down ? 0 : 1] = SCIPgetLPSolstat(scip);
3245
3246 switch( SCIPgetLPSolstat(scip) )
3247 {
3249 {
3250 *value = SCIPgetLPObjval(scip);
3251 assert(SCIPisLT(scip, *value, SCIPgetCutoffbound(scip)));
3252
3253 SCIPdebugMsg(scip, "probing LP solved to optimality, objective value: %16.9g\n", *value);
3254
3255 if( valid != NULL )
3256 *valid = TRUE;
3257
3258 /* check the strong branching LP solution for feasibility */
3259 SCIP_CALL( SCIPtryStrongbranchLPSol(scip, foundsol, cutoff) );
3260 break;
3261 }
3263 ++scip->stat->nsbtimesiterlimhit;
3264 /*lint -fallthrough*/
3266 {
3267 /* use LP value as estimate */
3268 SCIP_LPI* lpi;
3269 SCIP_Real objval;
3270 SCIP_Real looseobjval;
3271
3272 SCIPdebugMsg(scip, "probing LP hit %s limit\n", SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_ITERLIMIT ? "iteration" : "time");
3273
3274 /* we access the LPI directly, because when a time limit was hit, we cannot access objective value and dual
3275 * feasibility using the SCIPlp... methods; we should try to avoid direct calls to the LPI, but this is rather
3276 * uncritical here, because we are immediately after the SCIPsolveProbingLP() call, because we access the LPI
3277 * read-only, and we check SCIPlpiWasSolved() first
3278 */
3279 SCIP_CALL( SCIPgetLPI(scip, &lpi) );
3280
3281 if( SCIPlpiWasSolved(lpi) )
3282 {
3283 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
3284 looseobjval = SCIPlpGetLooseObjval(scip->lp, scip->set, scip->transprob);
3285
3286 /* the infinity value in the LPI should not be smaller than SCIP's infinity value */
3287 assert(!SCIPlpiIsInfinity(lpi, objval) || SCIPisInfinity(scip, objval));
3288
3289 /* we use SCIP's infinity value here because a value larger than this is counted as infeasible by SCIP */
3290 if( SCIPisInfinity(scip, objval) )
3291 *value = SCIPinfinity(scip);
3292 else if( SCIPisInfinity(scip, -looseobjval) )
3293 *value = -SCIPinfinity(scip);
3294 else
3295 *value = objval + looseobjval;
3296
3297 if( SCIPlpiIsDualFeasible(lpi) )
3298 {
3299 if( valid != NULL )
3300 *valid = TRUE;
3301
3302 if( SCIPisGE(scip, *value, SCIPgetCutoffbound(scip)) )
3303 *cutoff = TRUE;
3304 }
3305 }
3306 break;
3307 }
3310 *lperror = TRUE;
3311 break;
3312 case SCIP_LPSOLSTAT_NOTSOLVED: /* should only be the case for *cutoff = TRUE or *lperror = TRUE */
3313 case SCIP_LPSOLSTAT_OBJLIMIT: /* in this case, *cutoff should be TRUE and we should not get here */
3314 case SCIP_LPSOLSTAT_INFEASIBLE: /* in this case, *cutoff should be TRUE and we should not get here */
3315 default:
3316 SCIPerrorMessage("invalid LP solution status <%d>\n", SCIPgetLPSolstat(scip));
3317 return SCIP_INVALIDDATA;
3318 } /*lint !e788*/
3319 }
3320
3321 /* If columns are missing in the LP, the cutoff flag may be wrong. Therefore, we need to set it and the valid pointer
3322 * to false here.
3323 */
3324 if( (*cutoff) && !SCIPallColsInLP(scip) )
3325 {
3326 *cutoff = FALSE;
3327 }
3328
3329#ifndef NDEBUG
3330 if( *lperror )
3331 {
3332 SCIPdebugMsg(scip, "error during strong branching probing LP solving: status=%d\n", SCIPgetLPSolstat(scip));
3333 }
3334#endif
3335 }
3336
3337 /* if the subproblem was feasible, we store the local bounds of the variables after propagation and (possibly)
3338 * conflict analysis
3339 * @todo do this after propagation? should be able to get valid bounds more often, but they might be weaker
3340 */
3341 if( !(*cutoff) && newlbs != NULL)
3342 {
3343 int v;
3344
3345 assert(newubs != NULL);
3346
3347 /* initialize the newlbs and newubs to the current local bounds */
3348 if( firstchild )
3349 {
3350 for( v = 0; v < nvars; ++v )
3351 {
3352 newlbs[v] = SCIPvarGetLbLocal(vars[v]);
3353 newubs[v] = SCIPvarGetUbLocal(vars[v]);
3354 }
3355 }
3356 /* update newlbs and newubs: take the weaker of the already stored bounds and the current local bounds */
3357 else
3358 {
3359 for( v = 0; v < nvars; ++v )
3360 {
3361 SCIP_Real lb = SCIPvarGetLbLocal(vars[v]);
3362 SCIP_Real ub = SCIPvarGetUbLocal(vars[v]);
3363
3364 newlbs[v] = MIN(newlbs[v], lb);
3365 newubs[v] = MAX(newubs[v], ub);
3366 }
3367 }
3368 }
3369
3370 /* revert all changes at the probing node */
3372
3373 return SCIP_OKAY;
3374}
3375
3376/** gets strong branching information with previous domain propagation on column variable
3377 *
3378 * Before calling this method, the strong branching mode must have been activated by calling SCIPstartStrongbranch();
3379 * after strong branching was done for all candidate variables, the strong branching mode must be ended by
3380 * SCIPendStrongbranch(). Since this method applies domain propagation before strongbranching, propagation has to be be
3381 * enabled in the SCIPstartStrongbranch() call.
3382 *
3383 * Before solving the strong branching LP, domain propagation can be performed. The number of propagation rounds
3384 * can be specified by the parameter @p maxproprounds.
3385 *
3386 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3387 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3388 *
3389 * @pre This method can be called if @p scip is in one of the following stages:
3390 * - \ref SCIP_STAGE_PRESOLVED
3391 * - \ref SCIP_STAGE_SOLVING
3392 *
3393 * @warning When using this method, LP banching candidates and solution values must be copied beforehand, because
3394 * they are updated w.r.t. the strong branching LP solution.
3395 */
3397 SCIP* scip, /**< SCIP data structure */
3398 SCIP_VAR* var, /**< variable to get strong branching values for */
3399 SCIP_Real solval, /**< value of the variable in the current LP solution */
3400 SCIP_Real lpobjval, /**< LP objective value of the current LP solution */
3401 int itlim, /**< iteration limit for strong branchings */
3402 int maxproprounds, /**< maximum number of propagation rounds (-1: no limit, -2: parameter
3403 * settings) */
3404 SCIP_Real* down, /**< stores dual bound after branching column down */
3405 SCIP_Real* up, /**< stores dual bound after branching column up */
3406 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
3407 * otherwise, it can only be used as an estimate value */
3408 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
3409 * otherwise, it can only be used as an estimate value */
3410 SCIP_Longint* ndomredsdown, /**< pointer to store the number of domain reductions down, or NULL */
3411 SCIP_Longint* ndomredsup, /**< pointer to store the number of domain reductions up, or NULL */
3412 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */
3413 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */
3414 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an
3415 * infeasible downwards branch, or NULL */
3416 SCIP_Bool* upconflict, /**< pointer to store whether a conflict constraint was created for an
3417 * infeasible upwards branch, or NULL */
3418 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred or the
3419 * solving process should be stopped (e.g., due to a time limit) */
3420 SCIP_Real* newlbs, /**< array to store valid lower bounds for all active variables, or NULL */
3421 SCIP_Real* newubs /**< array to store valid upper bounds for all active variables, or NULL */
3422 )
3423{
3424 SCIP_COL* col;
3425 SCIP_VAR** vars;
3426 SCIP_Longint oldniters;
3427 SCIP_Real newub;
3428 SCIP_Real newlb;
3429 SCIP_Bool propagate;
3430 SCIP_Bool cutoff;
3431 SCIP_Bool downchild;
3432 SCIP_Bool firstchild;
3433 SCIP_Bool foundsol;
3434 SCIP_Bool downvalidlocal;
3435 SCIP_Bool upvalidlocal;
3436 SCIP_Bool allcolsinlp;
3437 SCIP_Bool enabledconflict;
3438 int oldnconflicts;
3439 int nvars;
3440
3441 assert(var != NULL);
3442 assert(SCIPvarIsIntegral(var));
3443 assert(down != NULL);
3444 assert(up != NULL);
3445 assert(lperror != NULL);
3446 assert((newlbs != NULL) == (newubs != NULL));
3447 assert(SCIPinProbing(scip));
3448 assert(var->scip == scip);
3449
3450 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchWithPropagation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3451
3452 /* check whether propagation should be performed */
3453 propagate = (maxproprounds != 0 && maxproprounds != -3);
3454
3455 /* Check, if all existing columns are in LP.
3456 * If this is not the case, we may still return that the up and down dual bounds are valid, because the branching
3457 * rule should not apply them otherwise.
3458 * However, we must not set the downinf or upinf pointers to TRUE based on the dual bound, because we cannot
3459 * guarantee that this node can be cut off.
3460 */
3461 allcolsinlp = SCIPallColsInLP(scip);
3462
3463 /* if maxproprounds is -2, change it to 0, which for the following calls means using the parameter settings */
3464 if( maxproprounds == -2 )
3465 maxproprounds = 0;
3466
3467 *down = lpobjval;
3468 *up = lpobjval;
3469 if( downvalid != NULL )
3470 *downvalid = FALSE;
3471 if( upvalid != NULL )
3472 *upvalid = FALSE;
3473 if( downinf != NULL )
3474 *downinf = FALSE;
3475 if( upinf != NULL )
3476 *upinf = FALSE;
3477 if( downconflict != NULL )
3478 *downconflict = FALSE;
3479 if( upconflict != NULL )
3480 *upconflict = FALSE;
3481 if( ndomredsdown != NULL )
3482 *ndomredsdown = 0;
3483 if( ndomredsup != NULL )
3484 *ndomredsup = 0;
3485
3486 *lperror = FALSE;
3487
3488 vars = SCIPgetVars(scip);
3489 nvars = SCIPgetNVars(scip);
3490
3491 scip->stat->lastsblpsolstats[0] = scip->stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED;
3492
3493 /* check if the solving process should be aborted */
3494 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3495 {
3496 /* mark this as if the LP failed */
3497 *lperror = TRUE;
3498 return SCIP_OKAY;
3499 }
3500
3502 {
3503 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3504 return SCIP_INVALIDDATA;
3505 }
3506
3507 col = SCIPvarGetCol(var);
3508 assert(col != NULL);
3509
3510 if( !SCIPcolIsInLP(col) )
3511 {
3512 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3513 return SCIP_INVALIDDATA;
3514 }
3515
3516 newlb = SCIPfeasFloor(scip, solval + 1.0);
3517 newub = SCIPfeasCeil(scip, solval - 1.0);
3518
3519 SCIPdebugMsg(scip, "strong branching on var <%s>: solval=%g, lb=%g, ub=%g\n", SCIPvarGetName(var), solval,
3521
3522 /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the
3523 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3524 * are valid for and were already applied at the probing root
3525 */
3526 if( newlb > SCIPvarGetUbLocal(var) + 0.5 )
3527 {
3528 *up = SCIPinfinity(scip);
3529
3530 if( upinf != NULL )
3531 *upinf = TRUE;
3532
3533 if( upvalid != NULL )
3534 *upvalid = TRUE;
3535
3536 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3537 if( upconflict != NULL )
3538 *upconflict = TRUE;
3539
3540 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3541 *down, *up, FALSE, TRUE, 0LL, INT_MAX);
3542
3543 /* we do not regard the down branch; its valid pointer stays set to FALSE */
3544 return SCIP_OKAY;
3545 }
3546
3547 /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the
3548 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which
3549 * are valid for and were already applied at the probing root
3550 */
3551 if( newub < SCIPvarGetLbLocal(var) - 0.5 )
3552 {
3553 *down = SCIPinfinity(scip);
3554
3555 if( downinf != NULL )
3556 *downinf = TRUE;
3557
3558 if( downvalid != NULL )
3559 *downvalid = TRUE;
3560
3561 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */
3562 if( downconflict != NULL )
3563 *downconflict = TRUE;
3564
3565 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3566 *down, *up, TRUE, FALSE, 0LL, INT_MAX);
3567
3568 /* we do not regard the up branch; its valid pointer stays set to FALSE */
3569 return SCIP_OKAY;
3570 }
3571
3572 /* We now do strong branching by creating the two potential child nodes as probing nodes and solving them one after
3573 * the other. We will stop when the first child is detected infeasible, saving the effort we would need for the
3574 * second child. Since empirically, the up child tends to be infeasible more often, we do strongbranching first on
3575 * the up branch.
3576 */
3577 oldniters = scip->stat->nsbdivinglpiterations;
3578 firstchild = TRUE;
3579 cutoff = FALSE;
3580
3581 /* switch conflict analysis according to usesb parameter */
3582 enabledconflict = scip->set->conf_enable;
3583 scip->set->conf_enable = (scip->set->conf_enable && scip->set->conf_usesb);
3584
3585 /* @todo: decide the branch to look at first based on the cutoffs in previous calls? */
3586 downchild = SCIPisStrongbranchDownFirst(scip, var);
3587
3588 downvalidlocal = FALSE;
3589 upvalidlocal = FALSE;
3590
3591 do
3592 {
3593 oldnconflicts = SCIPconflictGetNConflicts(scip->conflict);
3594
3595 if( downchild )
3596 {
3597 SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild || cutoff, propagate, newub, itlim, maxproprounds,
3598 down, &downvalidlocal, ndomredsdown, downconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) );
3599
3600 /* check for infeasibility */
3601 if( cutoff )
3602 {
3603 if( downinf != NULL )
3604 *downinf = TRUE;
3605
3606 if( downconflict != NULL
3607 && ( SCIPvarGetLbLocal(var) > newub + 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts ) )
3608 *downconflict = TRUE;
3609 }
3610
3611 /* check whether new solutions rendered the other child infeasible */
3612 if( foundsol && allcolsinlp && SCIPisGE(scip, upvalidlocal ? *up : lpobjval, SCIPgetCutoffbound(scip)) )
3613 {
3614 if( upinf != NULL )
3615 *upinf = TRUE;
3616
3617 upvalidlocal = TRUE;
3618 cutoff = TRUE;
3619 }
3620 }
3621 else
3622 {
3623 SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild || cutoff, propagate, newlb, itlim, maxproprounds,
3624 up, &upvalidlocal, ndomredsup, upconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) );
3625
3626 /* check for infeasibility */
3627 if( cutoff )
3628 {
3629 if( upinf != NULL )
3630 *upinf = TRUE;
3631
3632 if( upconflict != NULL
3633 && ( SCIPvarGetUbLocal(var) < newlb - 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts ) )
3634 *upconflict = TRUE;
3635 }
3636
3637 /* check whether new solutions rendered the other child infeasible */
3638 if( foundsol && allcolsinlp && SCIPisGE(scip, downvalidlocal ? *down : lpobjval, SCIPgetCutoffbound(scip)) )
3639 {
3640 if( downinf != NULL )
3641 *downinf = TRUE;
3642
3643 downvalidlocal = TRUE;
3644 cutoff = TRUE;
3645 }
3646 }
3647
3648 downchild = !downchild;
3649 firstchild = !firstchild;
3650 }
3651 /* if a child is cut off and forceall is FALSE, we do not regard the other child */
3652 while( !firstchild && ( !cutoff || scip->set->branch_forceall ) );
3653
3654 /* update lower bound by the higher pseudo objective value */
3655 if( ( downinf == NULL || !(*downinf) ) && ( upinf == NULL || !(*upinf) ) && !SCIPisZero(scip, SCIPvarGetObj(var)) )
3656 {
3657 SCIP_Real oldbound;
3658 SCIP_Real newbound;
3659 SCIP_Real pseudoobjval;
3660 SCIP_BOUNDTYPE boundtype = SCIPvarGetBestBoundType(var);
3661
3662 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3663 {
3664 oldbound = SCIPvarGetUbLocal(var);
3665 newbound = newub;
3666 }
3667 else
3668 {
3669 oldbound = SCIPvarGetLbLocal(var);
3670 newbound = newlb;
3671 }
3672
3673 if( scip->set->misc_exactsolve )
3674 pseudoobjval = SCIPlpGetModifiedProvedPseudoObjval(scip->lp, scip->set, var, oldbound, newbound, boundtype);
3675 else
3676 pseudoobjval = SCIPlpGetModifiedPseudoObjval(scip->lp, scip->set, scip->transprob, var, oldbound, newbound, boundtype);
3677
3678 if( pseudoobjval > lpobjval )
3679 {
3680 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3681 {
3682 if( !downvalidlocal || *down < pseudoobjval )
3683 {
3684 *down = pseudoobjval;
3685 downvalidlocal = TRUE;
3686
3687 if( downinf != NULL && allcolsinlp && SCIPisGE(scip, *down, SCIPgetCutoffbound(scip)) )
3688 *downinf = TRUE;
3689 }
3690 }
3691 else
3692 {
3693 if( !upvalidlocal || *up < pseudoobjval )
3694 {
3695 *up = pseudoobjval;
3696 upvalidlocal = TRUE;
3697
3698 if( upinf != NULL && allcolsinlp && SCIPisGE(scip, *up, SCIPgetCutoffbound(scip)) )
3699 *upinf = TRUE;
3700 }
3701 }
3702 }
3703 }
3704
3705 /* set strong branching information in column */
3706 if( *lperror )
3707 {
3708 SCIPcolInvalidateStrongbranchData(col, scip->set, scip->stat, scip->lp);
3709 }
3710 else
3711 {
3712 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval,
3713 *down, *up, downvalidlocal, upvalidlocal, scip->stat->nsbdivinglpiterations - oldniters, itlim);
3714 }
3715
3716 if( downvalid != NULL )
3717 *downvalid = downvalidlocal;
3718 if( upvalid != NULL )
3719 *upvalid = upvalidlocal;
3720
3721 scip->set->conf_enable = enabledconflict;
3722
3723 return SCIP_OKAY; /*lint !e438*/
3724}
3725
3726/** gets strong branching information on column variable x with integral LP solution value (val); that is, the down branch
3727 * is (val -1.0) and the up brach ins (val +1.0)
3728 *
3729 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3730 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3731 *
3732 * @pre This method can be called if @p scip is in one of the following stages:
3733 * - \ref SCIP_STAGE_PRESOLVED
3734 * - \ref SCIP_STAGE_SOLVING
3735 *
3736 * @note If the integral LP solution value is the lower or upper bound of the variable, the corresponding branch will be
3737 * marked as infeasible. That is, the valid pointer and the infeasible pointer are set to TRUE.
3738 */
3740 SCIP* scip, /**< SCIP data structure */
3741 SCIP_VAR* var, /**< variable to get strong branching values for */
3742 int itlim, /**< iteration limit for strong branchings */
3743 SCIP_Bool idempotent, /**< should scip's state remain the same after the call (statistics, column states...), or should it be updated ? */
3744 SCIP_Real* down, /**< stores dual bound after branching column down */
3745 SCIP_Real* up, /**< stores dual bound after branching column up */
3746 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
3747 * otherwise, it can only be used as an estimate value */
3748 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
3749 * otherwise, it can only be used as an estimate value */
3750 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */
3751 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */
3752 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an
3753 * infeasible downwards branch, or NULL */
3754 SCIP_Bool* upconflict, /**< pointer to store whether a conflict constraint was created for an
3755 * infeasible upwards branch, or NULL */
3756 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the
3757 * solving process should be stopped (e.g., due to a time limit) */
3758 )
3759{
3760 SCIP_COL* col;
3761 SCIP_Real lpobjval;
3762 SCIP_Real localdown;
3763 SCIP_Real localup;
3764 SCIP_Bool localdownvalid;
3765 SCIP_Bool localupvalid;
3766
3767 assert(var != NULL);
3768 assert(lperror != NULL);
3769 assert(var->scip == scip);
3770
3771 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3772
3773 lpobjval = SCIPgetLPObjval(scip);
3774 if( downvalid != NULL )
3775 *downvalid = FALSE;
3776 if( upvalid != NULL )
3777 *upvalid = FALSE;
3778 if( downinf != NULL )
3779 *downinf = FALSE;
3780 if( upinf != NULL )
3781 *upinf = FALSE;
3782 if( downconflict != NULL )
3783 *downconflict = FALSE;
3784 if( upconflict != NULL )
3785 *upconflict = FALSE;
3786
3788 {
3789 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3790 return SCIP_INVALIDDATA;
3791 }
3792
3793 col = SCIPvarGetCol(var);
3794 assert(col != NULL);
3795
3796 if( !SCIPcolIsInLP(col) )
3797 {
3798 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3799 return SCIP_INVALIDDATA;
3800 }
3801
3802 /* check if the solving process should be aborted */
3803 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3804 {
3805 /* mark this as if the LP failed */
3806 *lperror = TRUE;
3807 return SCIP_OKAY;
3808 }
3809
3810 /* call strong branching for column */
3811 SCIP_CALL( SCIPcolGetStrongbranch(col, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent,
3812 &localdown, &localup, &localdownvalid, &localupvalid, lperror) );
3813
3814 /* update lower bound by the higher pseudo objective value */
3815 if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
3816 {
3817 SCIP_Real oldbound;
3818 SCIP_Real newbound;
3819 SCIP_Real pseudoobjval;
3820 SCIP_BOUNDTYPE boundtype = SCIPvarGetBestBoundType(var);
3821
3822 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3823 {
3824 oldbound = SCIPvarGetUbLocal(var);
3825 newbound = SCIPfeasCeil(scip, SCIPvarGetLPSol(var)) - 1.0;
3826 }
3827 else
3828 {
3829 oldbound = SCIPvarGetLbLocal(var);
3830 newbound = SCIPfeasFloor(scip, SCIPvarGetLPSol(var)) + 1.0;
3831 }
3832
3833 if( scip->set->misc_exactsolve )
3834 pseudoobjval = SCIPlpGetModifiedProvedPseudoObjval(scip->lp, scip->set, var, oldbound, newbound, boundtype);
3835 else
3836 pseudoobjval = SCIPlpGetModifiedPseudoObjval(scip->lp, scip->set, scip->transprob, var, oldbound, newbound, boundtype);
3837
3838 if( pseudoobjval > lpobjval )
3839 {
3840 if( boundtype == SCIP_BOUNDTYPE_UPPER )
3841 {
3842 if( !localdownvalid || localdown < pseudoobjval )
3843 {
3844 localdown = pseudoobjval;
3845 localdownvalid = TRUE;
3846 }
3847 }
3848 else
3849 {
3850 if( !localupvalid || localup < pseudoobjval )
3851 {
3852 localup = pseudoobjval;
3853 localupvalid = TRUE;
3854 }
3855 }
3856 }
3857 }
3858
3859 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3860 * declare the sub nodes infeasible
3861 */
3862 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3863 {
3864 if( !idempotent ) /*lint !e774*/
3865 {
3866 SCIP_CALL( analyzeStrongbranch(scip, var, NULL, NULL, downconflict, upconflict) );
3867 }
3868
3869 if( downinf != NULL )
3870 *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound);
3871 if( upinf != NULL )
3872 *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound);
3873 }
3874
3875 if( down != NULL )
3876 *down = localdown;
3877 if( up != NULL )
3878 *up = localup;
3879 if( downvalid != NULL )
3880 *downvalid = localdownvalid;
3881 if( upvalid != NULL )
3882 *upvalid = localupvalid;
3883
3884 return SCIP_OKAY;
3885}
3886
3887/** gets strong branching information on column variables with fractional values
3888 *
3889 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3890 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3891 *
3892 * @pre This method can be called if @p scip is in one of the following stages:
3893 * - \ref SCIP_STAGE_PRESOLVED
3894 * - \ref SCIP_STAGE_SOLVING
3895 */
3897 SCIP* scip, /**< SCIP data structure */
3898 SCIP_VAR** vars, /**< variables to get strong branching values for */
3899 int nvars, /**< number of variables */
3900 int itlim, /**< iteration limit for strong branchings */
3901 SCIP_Real* down, /**< stores dual bounds after branching variables down */
3902 SCIP_Real* up, /**< stores dual bounds after branching variables up */
3903 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
3904 * otherwise, they can only be used as an estimate value */
3905 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
3906 * otherwise, they can only be used as an estimate value */
3907 SCIP_Bool* downinf, /**< array to store whether the downward branches are infeasible, or NULL */
3908 SCIP_Bool* upinf, /**< array to store whether the upward branches are infeasible, or NULL */
3909 SCIP_Bool* downconflict, /**< array to store whether conflict constraints were created for
3910 * infeasible downward branches, or NULL */
3911 SCIP_Bool* upconflict, /**< array to store whether conflict constraints were created for
3912 * infeasible upward branches, or NULL */
3913 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the
3914 * solving process should be stopped (e.g., due to a time limit) */
3915 )
3916{
3917 SCIP_COL** cols;
3918 int j;
3919
3920 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesFrac", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
3921
3922 assert( lperror != NULL );
3923 assert( vars != NULL );
3924
3925 /* set up data */
3926 cols = NULL;
3927 SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) );
3928 assert(cols != NULL);
3929 for( j = 0; j < nvars; ++j )
3930 {
3931 SCIP_VAR* var;
3932 SCIP_COL* col;
3933
3934 if( downvalid != NULL )
3935 downvalid[j] = FALSE;
3936 if( upvalid != NULL )
3937 upvalid[j] = FALSE;
3938 if( downinf != NULL )
3939 downinf[j] = FALSE;
3940 if( upinf != NULL )
3941 upinf[j] = FALSE;
3942 if( downconflict != NULL )
3943 downconflict[j] = FALSE;
3944 if( upconflict != NULL )
3945 upconflict[j] = FALSE;
3946
3947 var = vars[j];
3948 assert( var != NULL );
3950 {
3951 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
3952 SCIPfreeBufferArray(scip, &cols);
3953 return SCIP_INVALIDDATA;
3954 }
3955
3956 col = SCIPvarGetCol(var);
3957 assert(col != NULL);
3958 cols[j] = col;
3959
3960 if( !SCIPcolIsInLP(col) )
3961 {
3962 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
3963 SCIPfreeBufferArray(scip, &cols);
3964 return SCIP_INVALIDDATA;
3965 }
3966 }
3967
3968 /* check if the solving process should be aborted */
3969 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
3970 {
3971 /* mark this as if the LP failed */
3972 *lperror = TRUE;
3973 }
3974 else
3975 {
3976 /* call strong branching for columns with fractional value */
3977 SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim,
3978 down, up, downvalid, upvalid, lperror) );
3979
3980 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
3981 * declare the sub nodes infeasible
3982 */
3983 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
3984 {
3985 for( j = 0; j < nvars; ++j )
3986 {
3987 SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL,
3988 (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL,
3989 (upconflict != NULL) ? (&(upconflict[j])) : NULL) );
3990 }
3991 }
3992 }
3993 SCIPfreeBufferArray(scip, &cols);
3994
3995 return SCIP_OKAY;
3996}
3997
3998/** gets strong branching information on column variables with integral values
3999 *
4000 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4001 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4002 *
4003 * @pre This method can be called if @p scip is in one of the following stages:
4004 * - \ref SCIP_STAGE_PRESOLVED
4005 * - \ref SCIP_STAGE_SOLVING
4006 */
4008 SCIP* scip, /**< SCIP data structure */
4009 SCIP_VAR** vars, /**< variables to get strong branching values for */
4010 int nvars, /**< number of variables */
4011 int itlim, /**< iteration limit for strong branchings */
4012 SCIP_Real* down, /**< stores dual bounds after branching variables down */
4013 SCIP_Real* up, /**< stores dual bounds after branching variables up */
4014 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4015 * otherwise, they can only be used as an estimate value */
4016 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4017 * otherwise, they can only be used as an estimate value */
4018 SCIP_Bool* downinf, /**< array to store whether the downward branches are infeasible, or NULL */
4019 SCIP_Bool* upinf, /**< array to store whether the upward branches are infeasible, or NULL */
4020 SCIP_Bool* downconflict, /**< array to store whether conflict constraints were created for
4021 * infeasible downward branches, or NULL */
4022 SCIP_Bool* upconflict, /**< array to store whether conflict constraints were created for
4023 * infeasible upward branches, or NULL */
4024 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the
4025 * solving process should be stopped (e.g., due to a time limit) */
4026 )
4027{
4028 SCIP_COL** cols;
4029 int j;
4030
4031 assert(lperror != NULL);
4032
4033 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4034
4035 assert( vars != NULL );
4036
4037 /* set up data */
4038 cols = NULL;
4039 SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) );
4040 assert(cols != NULL);
4041 for( j = 0; j < nvars; ++j )
4042 {
4043 SCIP_VAR* var;
4044 SCIP_COL* col;
4045
4046 if( downvalid != NULL )
4047 downvalid[j] = FALSE;
4048 if( upvalid != NULL )
4049 upvalid[j] = FALSE;
4050 if( downinf != NULL )
4051 downinf[j] = FALSE;
4052 if( upinf != NULL )
4053 upinf[j] = FALSE;
4054 if( downconflict != NULL )
4055 downconflict[j] = FALSE;
4056 if( upconflict != NULL )
4057 upconflict[j] = FALSE;
4058
4059 var = vars[j];
4060 assert( var != NULL );
4062 {
4063 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var));
4064 SCIPfreeBufferArray(scip, &cols);
4065 return SCIP_INVALIDDATA;
4066 }
4067
4068 col = SCIPvarGetCol(var);
4069 assert(col != NULL);
4070 cols[j] = col;
4071
4072 if( !SCIPcolIsInLP(col) )
4073 {
4074 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var));
4075 SCIPfreeBufferArray(scip, &cols);
4076 return SCIP_INVALIDDATA;
4077 }
4078 }
4079
4080 /* check if the solving process should be aborted */
4081 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) )
4082 {
4083 /* mark this as if the LP failed */
4084 *lperror = TRUE;
4085 }
4086 else
4087 {
4088 /* call strong branching for columns */
4089 SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim,
4090 down, up, downvalid, upvalid, lperror) );
4091
4092 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to
4093 * declare the sub nodes infeasible
4094 */
4095 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve )
4096 {
4097 for( j = 0; j < nvars; ++j )
4098 {
4099 SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL,
4100 (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL,
4101 (upconflict != NULL) ? (&(upconflict[j])) : NULL) );
4102 }
4103 }
4104 }
4105 SCIPfreeBufferArray(scip, &cols);
4106
4107 return SCIP_OKAY;
4108}
4109
4110/** get LP solution status of last strong branching call (currently only works for strong branching with propagation) */
4112 SCIP* scip, /**< SCIP data structure */
4113 SCIP_BRANCHDIR branchdir /**< branching direction for which LP solution status is requested */
4114 )
4115{
4116 assert(NULL != scip);
4117 assert(branchdir == SCIP_BRANCHDIR_DOWNWARDS || branchdir == SCIP_BRANCHDIR_UPWARDS);
4118
4119 return scip->stat->lastsblpsolstats[branchdir == SCIP_BRANCHDIR_DOWNWARDS ? 0 : 1];
4120}
4121
4122/** gets strong branching information on COLUMN variable of the last SCIPgetVarStrongbranch() call;
4123 * returns values of SCIP_INVALID, if strong branching was not yet called on the given variable;
4124 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4125 *
4126 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4127 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4128 *
4129 * @pre This method can be called if @p scip is in one of the following stages:
4130 * - \ref SCIP_STAGE_SOLVING
4131 * - \ref SCIP_STAGE_SOLVED
4132 */
4134 SCIP* scip, /**< SCIP data structure */
4135 SCIP_VAR* var, /**< variable to get last strong branching values for */
4136 SCIP_Real* down, /**< stores dual bound after branching column down */
4137 SCIP_Real* up, /**< stores dual bound after branching column up */
4138 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4139 * otherwise, it can only be used as an estimate value */
4140 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4141 * otherwise, it can only be used as an estimate value */
4142 SCIP_Real* solval, /**< stores LP solution value of variable at the last strong branching call, or NULL */
4143 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4144 )
4145{
4146 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLast", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) );
4147
4149 {
4150 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable\n");
4151 return SCIP_INVALIDDATA;
4152 }
4153
4154 SCIPcolGetStrongbranchLast(SCIPvarGetCol(var), down, up, downvalid, upvalid, solval, lpobjval);
4155
4156 return SCIP_OKAY;
4157}
4158
4159/** sets strong branching information for a column variable
4160 *
4161 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4162 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4163 *
4164 * @pre This method can be called if @p scip is in one of the following stages:
4165 * - \ref SCIP_STAGE_SOLVING
4166 */
4168 SCIP* scip, /**< SCIP data structure */
4169 SCIP_VAR* var, /**< variable to set last strong branching values for */
4170 SCIP_Real lpobjval, /**< objective value of the current LP */
4171 SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4172 SCIP_Real down, /**< dual bound after branching column down */
4173 SCIP_Real up, /**< dual bound after branching column up */
4174 SCIP_Bool downvalid, /**< is the returned down value a valid dual bound? */
4175 SCIP_Bool upvalid, /**< is the returned up value a valid dual bound? */
4176 SCIP_Longint iter, /**< total number of strong branching iterations */
4177 int itlim /**< iteration limit applied to the strong branching call */
4178 )
4179{
4180 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetVarStrongbranchData", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4181
4183 {
4184 SCIPerrorMessage("cannot set strong branching information on non-COLUMN variable\n");
4185 return SCIP_INVALIDDATA;
4186 }
4187
4188 SCIPcolSetStrongbranchData(SCIPvarGetCol(var), scip->set, scip->stat, scip->lp, lpobjval, primsol,
4189 down, up, downvalid, upvalid, iter, itlim);
4190
4191 return SCIP_OKAY;
4192}
4193
4194/** rounds the current solution and tries it afterwards; if feasible, adds it to storage
4195 *
4196 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4197 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4198 *
4199 * @pre This method can be called if @p scip is in one of the following stages:
4200 * - \ref SCIP_STAGE_SOLVING
4201 */
4203 SCIP* scip, /**< SCIP data structure */
4204 SCIP_Bool* foundsol, /**< stores whether solution was feasible and good enough to keep */
4205 SCIP_Bool* cutoff /**< stores whether solution was cutoff due to exceeding the cutoffbound */
4206 )
4207{
4208 assert(scip != NULL);
4209 assert(foundsol != NULL);
4210 assert(cutoff != NULL);
4211
4212 SCIP_CALL( SCIPcheckStage(scip, "SCIPtryStrongbranchLPSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
4213
4214 if( scip->set->branch_checksbsol )
4215 {
4216 SCIP_SOL* sol;
4217 SCIP_Bool rounded = TRUE;
4219 SCIP_Longint oldnbestsolsfound = scip->primal->nbestsolsfound;
4220
4221 /* start clock for strong branching solutions */
4222 SCIPclockStart(scip->stat->sbsoltime, scip->set);
4223
4226
4227 /* try to round the strong branching solution */
4228 if( scip->set->branch_roundsbsol )
4229 {
4230 SCIP_CALL( SCIProundSol(scip, sol, &rounded) );
4231 }
4232
4233 /* check the solution for feasibility if rounding worked well (or was not tried) */
4234 if( rounded )
4235 {
4236 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, TRUE, FALSE, foundsol) );
4237 }
4238 else
4239 {
4240 SCIP_CALL( SCIPfreeSol(scip, &sol) );
4241 }
4242
4243 if( *foundsol )
4244 {
4245 SCIPdebugMsg(scip, "found new solution in strong branching\n");
4246
4247 scip->stat->nsbsolsfound++;
4248
4249 if( scip->primal->nbestsolsfound != oldnbestsolsfound )
4250 {
4251 scip->stat->nsbbestsolsfound++;
4252 }
4253
4254 if( SCIPisGE(scip, value, SCIPgetCutoffbound(scip)) )
4255 *cutoff = TRUE;
4256 }
4257
4258 /* stop clock for strong branching solutions */
4259 SCIPclockStop(scip->stat->sbsoltime, scip->set);
4260 }
4261 return SCIP_OKAY;
4262}
4263
4264
4265/** gets node number of the last node in current branch and bound run, where strong branching was used on the
4266 * given variable, or -1 if strong branching was never applied to the variable in current run
4267 *
4268 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4269 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4270 *
4271 * @pre This method can be called if @p scip is in one of the following stages:
4272 * - \ref SCIP_STAGE_TRANSFORMING
4273 * - \ref SCIP_STAGE_TRANSFORMED
4274 * - \ref SCIP_STAGE_INITPRESOLVE
4275 * - \ref SCIP_STAGE_PRESOLVING
4276 * - \ref SCIP_STAGE_EXITPRESOLVE
4277 * - \ref SCIP_STAGE_PRESOLVED
4278 * - \ref SCIP_STAGE_INITSOLVE
4279 * - \ref SCIP_STAGE_SOLVING
4280 * - \ref SCIP_STAGE_SOLVED
4281 * - \ref SCIP_STAGE_EXITSOLVE
4282 */
4284 SCIP* scip, /**< SCIP data structure */
4285 SCIP_VAR* var /**< variable to get last strong branching node for */
4286 )
4287{
4288 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchNode", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4289
4290 assert( var->scip == scip );
4291
4293 return -1;
4294
4296}
4297
4298/** if strong branching was already applied on the variable at the current node, returns the number of LPs solved after
4299 * the LP where the strong branching on this variable was applied;
4300 * if strong branching was not yet applied on the variable at the current node, returns INT_MAX
4301 *
4302 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4303 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4304 *
4305 * @pre This method can be called if @p scip is in one of the following stages:
4306 * - \ref SCIP_STAGE_TRANSFORMING
4307 * - \ref SCIP_STAGE_TRANSFORMED
4308 * - \ref SCIP_STAGE_INITPRESOLVE
4309 * - \ref SCIP_STAGE_PRESOLVING
4310 * - \ref SCIP_STAGE_EXITPRESOLVE
4311 * - \ref SCIP_STAGE_PRESOLVED
4312 * - \ref SCIP_STAGE_INITSOLVE
4313 * - \ref SCIP_STAGE_SOLVING
4314 * - \ref SCIP_STAGE_SOLVED
4315 * - \ref SCIP_STAGE_EXITSOLVE
4316 */
4318 SCIP* scip, /**< SCIP data structure */
4319 SCIP_VAR* var /**< variable to get strong branching LP age for */
4320 )
4321{
4322 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLPAge", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4323
4324 assert( var->scip == scip );
4325
4327 return SCIP_LONGINT_MAX;
4328
4330}
4331
4332/** gets number of times, strong branching was applied in current run on the given variable
4333 *
4334 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4335 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4336 *
4337 * @pre This method can be called if @p scip is in one of the following stages:
4338 * - \ref SCIP_STAGE_TRANSFORMING
4339 * - \ref SCIP_STAGE_TRANSFORMED
4340 * - \ref SCIP_STAGE_INITPRESOLVE
4341 * - \ref SCIP_STAGE_PRESOLVING
4342 * - \ref SCIP_STAGE_EXITPRESOLVE
4343 * - \ref SCIP_STAGE_PRESOLVED
4344 * - \ref SCIP_STAGE_INITSOLVE
4345 * - \ref SCIP_STAGE_SOLVING
4346 * - \ref SCIP_STAGE_SOLVED
4347 * - \ref SCIP_STAGE_EXITSOLVE
4348 */
4350 SCIP* scip, /**< SCIP data structure */
4351 SCIP_VAR* var /**< variable to get last strong branching node for */
4352 )
4353{
4354 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarNStrongbranchs", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) );
4355
4356 assert( var->scip == scip );
4357
4359 return 0;
4360
4362}
4363
4364/** adds given values to lock numbers of type @p locktype of variable for rounding
4365 *
4366 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4367 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4368 *
4369 * @pre This method can be called if @p scip is in one of the following stages:
4370 * - \ref SCIP_STAGE_PROBLEM
4371 * - \ref SCIP_STAGE_TRANSFORMING
4372 * - \ref SCIP_STAGE_TRANSFORMED
4373 * - \ref SCIP_STAGE_INITPRESOLVE
4374 * - \ref SCIP_STAGE_PRESOLVING
4375 * - \ref SCIP_STAGE_EXITPRESOLVE
4376 * - \ref SCIP_STAGE_PRESOLVED
4377 * - \ref SCIP_STAGE_INITSOLVE
4378 * - \ref SCIP_STAGE_SOLVING
4379 * - \ref SCIP_STAGE_EXITSOLVE
4380 * - \ref SCIP_STAGE_FREETRANS
4381 */
4383 SCIP* scip, /**< SCIP data structure */
4384 SCIP_VAR* var, /**< problem variable */
4385 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
4386 int nlocksdown, /**< modification in number of rounding down locks */
4387 int nlocksup /**< modification in number of rounding up locks */
4388 )
4389{
4390 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocksType", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4391
4392 assert( var->scip == scip );
4393
4394 switch( scip->set->stage )
4395 {
4396 case SCIP_STAGE_PROBLEM:
4397 assert(!SCIPvarIsTransformed(var));
4398 /*lint -fallthrough*/
4406 case SCIP_STAGE_SOLVING:
4409 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, locktype, nlocksdown, nlocksup) );
4410 return SCIP_OKAY;
4411
4412 default:
4413 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4414 return SCIP_INVALIDCALL;
4415 } /*lint !e788*/
4416}
4417
4418/** adds given values to lock numbers of variable for rounding
4419 *
4420 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4421 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4422 *
4423 * @pre This method can be called if @p scip is in one of the following stages:
4424 * - \ref SCIP_STAGE_PROBLEM
4425 * - \ref SCIP_STAGE_TRANSFORMING
4426 * - \ref SCIP_STAGE_TRANSFORMED
4427 * - \ref SCIP_STAGE_INITPRESOLVE
4428 * - \ref SCIP_STAGE_PRESOLVING
4429 * - \ref SCIP_STAGE_EXITPRESOLVE
4430 * - \ref SCIP_STAGE_PRESOLVED
4431 * - \ref SCIP_STAGE_INITSOLVE
4432 * - \ref SCIP_STAGE_SOLVING
4433 * - \ref SCIP_STAGE_EXITSOLVE
4434 * - \ref SCIP_STAGE_FREETRANS
4435 *
4436 * @note This method will always add variable locks of type model
4437 *
4438 * @note It is recommented to use SCIPaddVarLocksType()
4439 */
4441 SCIP* scip, /**< SCIP data structure */
4442 SCIP_VAR* var, /**< problem variable */
4443 int nlocksdown, /**< modification in number of rounding down locks */
4444 int nlocksup /**< modification in number of rounding up locks */
4445 )
4446{
4447 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocks", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4448
4449 SCIP_CALL( SCIPaddVarLocksType(scip, var, SCIP_LOCKTYPE_MODEL, nlocksdown, nlocksup) );
4450
4451 return SCIP_OKAY;
4452}
4453
4454/** add locks of variable with respect to the lock status of the constraint and its negation;
4455 * this method should be called whenever the lock status of a variable in a constraint changes, for example if
4456 * the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were
4457 * added or removed
4458 *
4459 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4460 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4461 *
4462 * @pre This method can be called if @p scip is in one of the following stages:
4463 * - \ref SCIP_STAGE_PROBLEM
4464 * - \ref SCIP_STAGE_TRANSFORMING
4465 * - \ref SCIP_STAGE_TRANSFORMED
4466 * - \ref SCIP_STAGE_INITPRESOLVE
4467 * - \ref SCIP_STAGE_PRESOLVING
4468 * - \ref SCIP_STAGE_EXITPRESOLVE
4469 * - \ref SCIP_STAGE_INITSOLVE
4470 * - \ref SCIP_STAGE_SOLVING
4471 * - \ref SCIP_STAGE_EXITSOLVE
4472 * - \ref SCIP_STAGE_FREETRANS
4473 */
4475 SCIP* scip, /**< SCIP data structure */
4476 SCIP_VAR* var, /**< problem variable */
4477 SCIP_CONS* cons, /**< constraint */
4478 SCIP_Bool lockdown, /**< should the rounding be locked in downwards direction? */
4479 SCIP_Bool lockup /**< should the rounding be locked in upwards direction? */
4480 )
4481{
4482 int nlocksdown[NLOCKTYPES];
4483 int nlocksup[NLOCKTYPES];
4484 int i;
4485
4486 SCIP_CALL( SCIPcheckStage(scip, "SCIPlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4487
4488 assert( var->scip == scip );
4489
4490 for( i = 0; i < NLOCKTYPES; i++ )
4491 {
4492 nlocksdown[i] = 0;
4493 nlocksup[i] = 0;
4494
4495 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4496 {
4497 if( lockdown )
4498 ++nlocksdown[i];
4499 if( lockup )
4500 ++nlocksup[i];
4501 }
4502 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4503 {
4504 if( lockdown )
4505 ++nlocksup[i];
4506 if( lockup )
4507 ++nlocksdown[i];
4508 }
4509 }
4510
4511 switch( scip->set->stage )
4512 {
4513 case SCIP_STAGE_PROBLEM:
4514 assert(!SCIPvarIsTransformed(var));
4515 /*lint -fallthrough*/
4522 case SCIP_STAGE_SOLVING:
4525 for( i = 0; i < NLOCKTYPES; i++ )
4526 {
4527 if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4528 continue;
4529
4530 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4531 }
4532 return SCIP_OKAY;
4533
4534 default:
4535 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4536 return SCIP_INVALIDCALL;
4537 } /*lint !e788*/
4538}
4539
4540/** remove locks of type @p locktype of variable with respect to the lock status of the constraint and its negation;
4541 * this method should be called whenever the lock status of a variable in a constraint changes, for example if
4542 * the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were
4543 * added or removed
4544 *
4545 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4546 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4547 *
4548 * @pre This method can be called if @p scip is in one of the following stages:
4549 * - \ref SCIP_STAGE_PROBLEM
4550 * - \ref SCIP_STAGE_TRANSFORMING
4551 * - \ref SCIP_STAGE_TRANSFORMED
4552 * - \ref SCIP_STAGE_INITPRESOLVE
4553 * - \ref SCIP_STAGE_PRESOLVING
4554 * - \ref SCIP_STAGE_EXITPRESOLVE
4555 * - \ref SCIP_STAGE_INITSOLVE
4556 * - \ref SCIP_STAGE_SOLVING
4557 * - \ref SCIP_STAGE_EXITSOLVE
4558 * - \ref SCIP_STAGE_FREETRANS
4559 */
4561 SCIP* scip, /**< SCIP data structure */
4562 SCIP_VAR* var, /**< problem variable */
4563 SCIP_CONS* cons, /**< constraint */
4564 SCIP_Bool lockdown, /**< should the rounding be unlocked in downwards direction? */
4565 SCIP_Bool lockup /**< should the rounding be unlocked in upwards direction? */
4566 )
4567{
4568 int nlocksdown[NLOCKTYPES];
4569 int nlocksup[NLOCKTYPES];
4570 int i;
4571
4572 SCIP_CALL( SCIPcheckStage(scip, "SCIPunlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
4573
4574 assert( var->scip == scip );
4575
4576 for( i = 0; i < NLOCKTYPES; i++ )
4577 {
4578 nlocksdown[i] = 0;
4579 nlocksup[i] = 0;
4580
4581 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) )
4582 {
4583 if( lockdown )
4584 ++nlocksdown[i];
4585 if( lockup )
4586 ++nlocksup[i];
4587 }
4588 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) )
4589 {
4590 if( lockdown )
4591 ++nlocksup[i];
4592 if( lockup )
4593 ++nlocksdown[i];
4594 }
4595 }
4596 switch( scip->set->stage )
4597 {
4598 case SCIP_STAGE_PROBLEM:
4599 assert(!SCIPvarIsTransformed(var));
4600 /*lint -fallthrough*/
4607 case SCIP_STAGE_SOLVING:
4610 for( i = 0; i < NLOCKTYPES; i++ )
4611 {
4612 if( nlocksdown[i] == 0 && nlocksup[i] == 0 )
4613 continue;
4614
4615 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4616 }
4617 return SCIP_OKAY;
4618
4619 default:
4620 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4621 return SCIP_INVALIDCALL;
4622 } /*lint !e788*/
4623}
4624
4625/** changes variable's objective value
4626 *
4627 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4628 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4629 *
4630 * @pre This method can be called if @p scip is in one of the following stages:
4631 * - \ref SCIP_STAGE_PROBLEM
4632 * - \ref SCIP_STAGE_TRANSFORMING
4633 * - \ref SCIP_STAGE_PRESOLVING
4634 * - \ref SCIP_STAGE_PRESOLVED
4635 */
4637 SCIP* scip, /**< SCIP data structure */
4638 SCIP_VAR* var, /**< variable to change the objective value for */
4639 SCIP_Real newobj /**< new objective value */
4640 )
4641{
4643
4644 assert( var->scip == scip );
4645
4646 /* forbid infinite objective values */
4647 if( SCIPisInfinity(scip, REALABS(newobj)) )
4648 {
4649 SCIPerrorMessage("invalid objective value: objective value is infinite\n");
4650 return SCIP_INVALIDDATA;
4651 }
4652
4653 switch( scip->set->stage )
4654 {
4655 case SCIP_STAGE_PROBLEM:
4656 assert(!SCIPvarIsTransformed(var));
4657 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->origprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4658 return SCIP_OKAY;
4659
4664 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->transprob, scip->primal, scip->lp, scip->eventqueue, newobj) );
4665 return SCIP_OKAY;
4666
4667 default:
4668 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4669 return SCIP_INVALIDCALL;
4670 } /*lint !e788*/
4671}
4672
4673/** adds value to variable's objective value
4674 *
4675 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4676 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
4677 *
4678 * @pre This method can be called if @p scip is in one of the following stages:
4679 * - \ref SCIP_STAGE_PROBLEM
4680 * - \ref SCIP_STAGE_TRANSFORMING
4681 * - \ref SCIP_STAGE_PRESOLVING
4682 * - \ref SCIP_STAGE_EXITPRESOLVE
4683 * - \ref SCIP_STAGE_PRESOLVED
4684 */
4686 SCIP* scip, /**< SCIP data structure */
4687 SCIP_VAR* var, /**< variable to change the objective value for */
4688 SCIP_Real addobj /**< additional objective value */
4689 )
4690{
4692
4693 assert( var->scip == scip );
4694
4695 switch( scip->set->stage )
4696 {
4697 case SCIP_STAGE_PROBLEM:
4698 assert(!SCIPvarIsTransformed(var));
4699 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4700 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4701 return SCIP_OKAY;
4702
4707 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal,
4708 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) );
4709 return SCIP_OKAY;
4710
4711 default:
4712 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage);
4713 return SCIP_INVALIDCALL;
4714 } /*lint !e788*/
4715}
4716
4717/** returns the adjusted (i.e. rounded, if the given variable is of integral type) lower bound value;
4718 * does not change the bounds of the variable
4719 *
4720 * @return adjusted lower bound for the given variable; the bound of the variable is not changed
4721 *
4722 * @pre This method can be called if @p scip is in one of the following stages:
4723 * - \ref SCIP_STAGE_PROBLEM
4724 * - \ref SCIP_STAGE_TRANSFORMING
4725 * - \ref SCIP_STAGE_TRANSFORMED
4726 * - \ref SCIP_STAGE_INITPRESOLVE
4727 * - \ref SCIP_STAGE_PRESOLVING
4728 * - \ref SCIP_STAGE_EXITPRESOLVE
4729 * - \ref SCIP_STAGE_PRESOLVED
4730 * - \ref SCIP_STAGE_INITSOLVE
4731 * - \ref SCIP_STAGE_SOLVING
4732 * - \ref SCIP_STAGE_SOLVED
4733 * - \ref SCIP_STAGE_EXITSOLVE
4734 * - \ref SCIP_STAGE_FREETRANS
4735 */
4737 SCIP* scip, /**< SCIP data structure */
4738 SCIP_VAR* var, /**< variable to adjust the bound for */
4739 SCIP_Real lb /**< lower bound value to adjust */
4740 )
4741{
4742 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarLb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
4743
4744 SCIPvarAdjustLb(var, scip->set, &lb);
4745
4746 return lb;
4747}
4748
4749/** returns the adjusted (i.e. rounded, if the given variable is of integral type) upper bound value;
4750 * does not change the bounds of the variable
4751 *
4752 * @return adjusted upper bound for the given variable; the bound of the variable is not changed
4753 *
4754 * @pre This method can be called if @p scip is in one of the following stages:
4755 * - \ref SCIP_STAGE_PROBLEM
4756 * - \ref SCIP_STAGE_TRANSFORMING
4757 * - \ref SCIP_STAGE_TRANSFORMED
4758 * - \ref SCIP_STAGE_INITPRESOLVE