Scippy

SCIP

Solving Constraint Integer Programs

misc_rowprep.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 misc_rowprep.c
26 * @ingroup OTHER_CFILES
27 * @brief linear inequalities in preparation
28 * @author Stefan Vigerske
29 * @author Benjamin Mueller
30 * @author Felipe Serrano
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
36#include "scip/pub_misc_sort.h"
37#include "scip/pub_var.h"
38#include "scip/pub_message.h"
39#include "scip/scip_lp.h"
40#include "scip/scip_mem.h"
41#include "scip/scip_message.h"
42#include "scip/scip_numerics.h"
43#include "scip/scip_sepa.h"
44#include "scip/scip_sol.h"
45#include "scip/scip_tree.h"
46#include "scip/struct_misc.h"
47#include "scip/struct_scip.h"
48#include "scip/set.h"
49
50#define ROWPREP_SCALEUP_VIOLNONZERO (10.0*SCIPepsilon(scip)) /**< minimal violation for considering up-scaling of rowprep (we want to avoid upscaling very small violations) */
51#define ROWPREP_SCALEUP_MINVIOLFACTOR 2.0 /**< scale up will target a violation of ~MINVIOLFACTOR*minviol, where minviol is given by caller */
52#define ROWPREP_SCALEUP_MAXMINCOEF (1.0 / SCIPfeastol(scip)) /**< scale up only if min. coef is below this number (before scaling) */
53#define ROWPREP_SCALEUP_MAXMAXCOEF SCIPgetHugeValue(scip) /**< scale up only if max. coef will not exceed this number by scaling */
54#define ROWPREP_SCALEUP_MAXSIDE SCIPgetHugeValue(scip) /**< scale up only if side will not exceed this number by scaling */
55#define ROWPREP_SCALEDOWN_MINMAXCOEF (1.0 / SCIPfeastol(scip)) /**< scale down if max. coef is at least this number (before scaling) */
56#define ROWPREP_SCALEDOWN_MINCOEF SCIPfeastol(scip) /**< scale down only if min. coef does not drop below this number by scaling */
57
58#ifndef M_SQRT2
59#define M_SQRT2 sqrt(2.0)
60#endif
61
62/** adds a variable to the `rowprep->modifiedvars` array, if recording of modification has been enabled and the variable is not fixed */
63static
65 SCIP* scip, /**< SCIP data structure */
66 SCIP_ROWPREP* rowprep, /**< rowprep */
67 SCIP_VAR* var /**< variable to add */
68 )
69{
70 int oldsize;
71
72 if( !rowprep->recordmodifications )
73 return SCIP_OKAY;
74
75 /* do not record for fixed variables, as they are not suitable for branching */
77 {
78 SCIPdebugMsg(scip, "skip recording modification for fixed variable <%s>[%g,%g]\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
79 return SCIP_OKAY;
80 }
81
82 /* increase modifiedvars array size */
83 if( rowprep->nmodifiedvars >= rowprep->modifiedvarssize )
84 {
85 oldsize = rowprep->modifiedvarssize;
87
89 }
90
91 rowprep->modifiedvars[rowprep->nmodifiedvars] = var;
92 ++rowprep->nmodifiedvars;
93
94 return SCIP_OKAY;
95}
96
97/** sort terms by absolute value of coefficients, from largest to smallest */
98static
100 SCIP* scip, /**< SCIP data structure */
101 SCIP_ROWPREP* rowprep /**< rowprep to be sorted */
102 )
103{
104 int i;
105
106 assert(scip != NULL);
107 assert(rowprep != NULL);
108
109 /* special treatment for cuts with few variables */
110 switch( rowprep->nvars )
111 {
112 case 0:
113 case 1:
114 break;
115
116 case 2:
117 {
118 if( REALABS(rowprep->coefs[0]) < REALABS(rowprep->coefs[1]) )
119 {
120 SCIP_Real tmp1;
121 SCIP_VAR* tmp2;
122
123 tmp1 = rowprep->coefs[0];
124 rowprep->coefs[0] = rowprep->coefs[1];
125 rowprep->coefs[1] = tmp1;
126
127 tmp2 = rowprep->vars[0];
128 rowprep->vars[0] = rowprep->vars[1];
129 rowprep->vars[1] = tmp2;
130 }
131 break;
132 }
133
134 default :
135 {
136 SCIP_Real* abscoefs;
137
138 SCIP_CALL( SCIPallocBufferArray(scip, &abscoefs, rowprep->nvars) );
139 for( i = 0; i < rowprep->nvars; ++i )
140 abscoefs[i] = REALABS(rowprep->coefs[i]);
141 SCIPsortDownRealRealPtr(abscoefs, rowprep->coefs, (void**)rowprep->vars, rowprep->nvars);
142 SCIPfreeBufferArray(scip, &abscoefs);
143 }
144 }
145
146 /* forget about coefs that are exactly zero (unlikely to have some) */
147 while( rowprep->nvars > 0 && rowprep->coefs[rowprep->nvars-1] == 0.0 )
148 --rowprep->nvars;
149
150 return SCIP_OKAY;
151}
152
153/** try to improve coef range by aggregating row with variable bounds
154 *
155 * Assumes terms have been sorted by rowprepCleanupSortTerms().
156 */
157static
159 SCIP* scip, /**< SCIP data structure */
160 SCIP_ROWPREP* rowprep, /**< rowprep to be improve */
161 SCIP_SOL* sol, /**< solution that we try to cut off, or NULL for LP solution */
162 SCIP_Real maxcoefrange /**< maximal allowed coefficients range */
163 )
164{
165 SCIP_VAR* var;
166 SCIP_Real lb;
167 SCIP_Real ub;
168 SCIP_Real ref;
169 SCIP_Real coef;
170 SCIP_Real mincoef;
171 SCIP_Real maxcoef;
172 SCIP_Real loss[2];
173 int maxcoefidx;
174 int pos;
175
176 maxcoefidx = 0;
177 if( rowprep->nvars > 0 )
178 {
179 maxcoef = REALABS(rowprep->coefs[0]);
180 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
181 }
182 else
183 mincoef = maxcoef = 1.0;
184
185 /* eliminate minimal or maximal coefs as long as coef range is too large
186 * this is likely going to eliminate coefs that are within eps of 0.0
187 * if not, then we do so after scaling (or should we enforce this here?)
188 */
189 while( maxcoef / mincoef > maxcoefrange )
190 {
191 SCIPdebugMsg(scip, "cut coefficients have very large range: mincoef = %g maxcoef = %g\n", mincoef, maxcoef);
192
193 /* max/min can only be > 1 if there is more than one var
194 * we need this below for updating the max/min coef after eliminating a term
195 */
196 assert(rowprep->nvars > 1);
197
198 /* try to reduce coef range by aggregating with variable bounds
199 * that is, eliminate a term like a*x from a*x + ... <= side by adding -a*x <= -a*lb(x)
200 * with ref(x) the reference point we try to eliminate, this would weaken the cut by a*(lb(x)-ref(x))
201 *
202 * we consider eliminating either the term with maximal or the one with minimal coefficient,
203 * taking the one that leads to the least weakening of the cut
204 *
205 * TODO (suggested by @bzfserra, see !496):
206 * - Also one could think of not completely removing the coefficient but do an aggregation that makes the coefficient look better. For instance:
207 * say you have $`a x + 0.1 y \leq r`$ and $`y`$ has only an upper bound, $`y \leq b`$,
208 * then you can't really remove $`y`$. However, you could aggregate it with $`0.9 \cdot (y \leq b)`$ to get
209 * $`a x + y \leq r + 0.9 b`$, which has better numerics (and hopefully still cuts the point... actually, if for the point you want to separate, $`y^* = b`$, then the violation is the same)
210 */
211
212 for( pos = 0; pos < 2; ++pos )
213 {
214 var = rowprep->vars[pos ? rowprep->nvars-1 : maxcoefidx];
215 coef = rowprep->coefs[pos ? rowprep->nvars-1 : maxcoefidx];
216 lb = SCIPvarGetLbLocal(var);
217 ub = SCIPvarGetUbLocal(var);
218 ref = SCIPgetSolVal(scip, sol, var);
219 assert(coef != 0.0);
220
221 /* make sure reference point is something reasonable within the bounds, preferable the value from the solution */
222 if( SCIPisInfinity(scip, REALABS(ref)) )
223 ref = 0.0;
224 ref = MAX(lb, MIN(ub, ref));
225
226 /* check whether we can eliminate coef*var from rowprep and how much we would loose w.r.t. ref(x) */
227 if( ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) )
228 {
229 /* we would need to aggregate with -coef*var <= -coef*lb(x) */
230 if( SCIPisInfinity(scip, -lb) )
231 loss[pos] = SCIP_INVALID;
232 else
233 loss[pos] = REALABS(coef) * (ref - lb);
234 }
235 else
236 {
237 assert((coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT));
238 /* we would need to aggregate with -coef*var >= -coef*ub(x) */
239 if( SCIPisInfinity(scip, ub) )
240 loss[pos] = SCIP_INVALID;
241 else
242 loss[pos] = REALABS(coef) * (ub - ref);
243 }
244 assert(loss[pos] >= 0.0); /* assuming SCIP_INVALID >= 0 */
245
246 SCIPdebugMsg(scip, "aggregating %g*<%s> %c= ... with <%s>[%g] %c= %g looses %g\n",
247 coef, SCIPvarGetName(var), rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? '<' : '>',
248 SCIPvarGetName(var), ref,
249 ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) ? '>' : '<',
250 ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) ? lb : ub, loss[pos]);
251 }
252
253 /*lint --e{777} */
254 if( loss[0] == SCIP_INVALID && loss[1] == SCIP_INVALID )
255 break; /* cannot eliminate coefficient */
256
257 /* select position with smaller loss */
258 pos = (loss[1] == SCIP_INVALID || loss[1] > loss[0]) ? 0 : 1;
259
260 /* now do the actual elimination */
261 var = rowprep->vars[pos ? rowprep->nvars-1 : maxcoefidx];
262 coef = rowprep->coefs[pos ? rowprep->nvars-1 : maxcoefidx];
263
264 /* eliminate coef*var from rowprep: increase side */
265 if( ((coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT)) )
266 {
267 /* we aggregate with -coef*var <= -coef*lb(x) */
268 assert(!SCIPisInfinity(scip, -SCIPvarGetLbLocal(var)));
269 SCIProwprepAddConstant(rowprep, coef * SCIPvarGetLbLocal(var));
270 rowprep->local |= SCIPisGT(scip, SCIPvarGetLbLocal(var), SCIPvarGetLbGlobal(var));
271 }
272 else
273 {
274 assert((coef < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT) || (coef > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT));
275 /* we aggregate with -coef*var >= -coef*ub(x) */
276 assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
277 SCIProwprepAddConstant(rowprep, coef * SCIPvarGetUbLocal(var));
278 rowprep->local |= SCIPisLT(scip, SCIPvarGetUbLocal(var), SCIPvarGetUbGlobal(var));
279 }
280
281 /* eliminate coef*var from rowprep: remove coef */
282 if( pos == 0 )
283 {
284 /* set first term to zero */
285 rowprep->coefs[maxcoefidx] = 0.0;
286
287 /* update index */
288 ++maxcoefidx;
289
290 /* update maxcoef */
291 maxcoef = REALABS(rowprep->coefs[maxcoefidx]);
292 }
293 else
294 {
295 /* forget last term */
296 --rowprep->nvars;
297
298 /* update mincoef */
299 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
300 }
301
302 /* (potentially) remember the variable that has been removed here */
303 SCIP_CALL( rowprepRecordModifiedVar(scip, rowprep, var) );
304 }
305
306 /* if maximal coefs were removed, then there are now 0's in the beginning of the coefs array
307 * -> move all remaining coefs and vars up front
308 */
309 if( maxcoefidx > 0 )
310 {
311 int i;
312 for( i = maxcoefidx; i < rowprep->nvars; ++i )
313 {
314 rowprep->vars[i-maxcoefidx] = rowprep->vars[i];
315 rowprep->coefs[i-maxcoefidx] = rowprep->coefs[i];
316 }
317 rowprep->nvars -= maxcoefidx;
318 }
319
320 return SCIP_OKAY;
321}
322
323
324/** scales up rowprep if it seems useful */
325static
327 SCIP* scip, /**< SCIP data structure */
328 SCIP_ROWPREP* rowprep, /**< rowprep to be improve */
329 SCIP_Real* viol, /**< violation of cut in sol (input and output) */
330 SCIP_Real minviol /**< minimal violation we try to achieve */
331 )
332{
333 SCIP_Real scalefactor;
334 SCIP_Real mincoef;
335 SCIP_Real maxcoef;
336
337 assert(scip != NULL);
338 assert(rowprep != NULL);
339 assert(viol != NULL);
340
341 /* if violation is very small than better don't scale up */
342 if( *viol < ROWPREP_SCALEUP_VIOLNONZERO )
343 return;
344
345 /* if violation is already above minviol, then nothing to do */
346 if( *viol >= minviol )
347 return;
348 assert(!SCIPisInfinity(scip, *viol));
349
350 /* if violation is sufficiently positive (>10*eps), but has not reached minviol,
351 * then consider scaling up to reach approx MINVIOLFACTOR*minviol
352 */
353 scalefactor = ROWPREP_SCALEUP_MINVIOLFACTOR * minviol / *viol;
354
355 /* scale by approx. scalefactor, if minimal coef is not so large yet and maximal coef and rhs don't get huge by doing so (or have been so before) */
356 mincoef = rowprep->nvars > 0 ? REALABS(rowprep->coefs[rowprep->nvars-1]) : 1.0;
357 maxcoef = rowprep->nvars > 0 ? REALABS(rowprep->coefs[0]) : 1.0;
358 if( mincoef < ROWPREP_SCALEUP_MAXMINCOEF && scalefactor * maxcoef < ROWPREP_SCALEUP_MAXMAXCOEF && scalefactor * REALABS(rowprep->side) < ROWPREP_SCALEUP_MAXSIDE )
359 {
360 int scaleexp;
361
362 /* SCIPinfoMessage(scip, NULL, "scale up by ~%g, viol=%g: ", scalefactor, myviol);
363 SCIPprintRowprep(scip, rowprep, NULL); */
364
365 /* SCIPscaleRowprep returns the actually applied scale factor */
366 scaleexp = SCIPscaleRowprep(rowprep, scalefactor);
367 *viol = ldexp(*viol, scaleexp);
368
369 /* SCIPinfoMessage(scip, NULL, "scaled up by %g, viol=%g: ", ldexp(1.0, scaleexp), myviol);
370 SCIPprintRowprep(scip, rowprep, NULL); */
371 }
372}
373
374/** scales down rowprep if it improves coefs and keeps rowprep violated */
375static
377 SCIP* scip, /**< SCIP data structure */
378 SCIP_ROWPREP* rowprep, /**< rowprep to be improve */
379 SCIP_Real* viol, /**< violation of cut in sol (input and output) */
380 SCIP_Real minviol /**< minimal violation we try to keep */
381 )
382{
383 SCIP_Real scalefactor;
384
385 /* if maxcoef < ROWPREP_SCALEDOWN_MINMAXCOEF (or no terms), then don't consider scaling down */
386 if( rowprep->nvars == 0 || REALABS(rowprep->coefs[0]) < ROWPREP_SCALEDOWN_MINMAXCOEF )
387 return;
388
389 /* consider scaling down so that maxcoef ~ 10 */
390 scalefactor = 10.0 / REALABS(rowprep->coefs[0]);
391
392 /* if minimal violation would be lost by scaling down, then increase scalefactor such that minviol is still reached */
393 if( *viol > minviol && !SCIPisInfinity(scip, *viol) && scalefactor * *viol < minviol )
394 {
395 assert(minviol > 0.0); /* since viol >= 0, the if-condition should ensure that minviol > 0 */
396 assert(*viol > 0.0); /* since minviol > 0, the if-condition ensures viol > 0 */
397 scalefactor = ROWPREP_SCALEUP_MINVIOLFACTOR * minviol / *viol;
398 }
399
400 /* scale by approx. scalefactor if scaling down and minimal coef does not get too small
401 * myviol < minviol (-> scalefactor > 1) or mincoef < feastol before scaling is possible, in which case we also don't scale down
402 */
403 if( scalefactor < 1.0 && scalefactor * REALABS(rowprep->coefs[rowprep->nvars-1]) > ROWPREP_SCALEDOWN_MINCOEF )
404 {
405 int scaleexp;
406
407 /* SCIPinfoMessage(scip, NULL, "scale down by ~%g, viol=%g: ", scalefactor, myviol);
408 SCIPprintRowprep(scip, rowprep, NULL); */
409
410 scaleexp = SCIPscaleRowprep(rowprep, scalefactor);
411 if( !SCIPisInfinity(scip, *viol) )
412 *viol = ldexp(*viol, scaleexp);
413
414 /* SCIPinfoMessage(scip, NULL, "scaled down by %g, viol=%g: ", ldexp(1.0, scaleexp), myviol);
415 SCIPprintRowprep(scip, rowprep, NULL); */
416 }
417}
418
419/** rounds almost integral coefs to integrals, thereby trying to relax the cut */
420static
422 SCIP* scip, /**< SCIP data structure */
423 SCIP_ROWPREP* rowprep, /**< rowprep to be improve */
424 SCIP_Real* viol /**< NULL or violation of cut in sol (input), set to SCIP_INVALID if some coef changed */
425 )
426{
427 SCIP_Real coef;
428 SCIP_Real roundcoef;
429 int i;
430
431 assert(scip != NULL);
432 assert(rowprep != NULL);
433
434 /* Coefficients smaller than epsilon are rounded to 0.0 when added to row and
435 * coefficients very close to integral values are rounded to integers when added to LP.
436 * Both cases can be problematic if variable value is very large (bad numerics).
437 * Thus, we anticipate by rounding coef here, but also modify constant so that cut is still valid (if possible),
438 * i.e., bound coef[i]*x by round(coef[i])*x + (coef[i]-round(coef[i])) * bound(x).
439 * Or in other words, we aggregate with the variable bound.
440 *
441 * If the required bound of x is not finite, then only round coef (introduces an error).
442 * @TODO If only the opposite bound is available, then one could move the coefficient
443 * away from the closest integer so that the SCIP_ROW won't try to round it.
444 *
445 * Exception: If the coefficient is almost zero and there is only one variable, then
446 * we scale up the row instead (if that doesn't make the side too huge).
447 * Eventually, the row would have been changed to a boundchange anyway and a similar
448 * operation happens, but we need to ensure that coefficient isn't just rounded to 0 first.
449 */
450
451 if( rowprep->nvars == 1 && rowprep->coefs[0] != 0.0 && SCIPisZero(scip, rowprep->coefs[0]) && REALABS(rowprep->side / rowprep->coefs[0]) < ROWPREP_SCALEUP_MAXSIDE )
452 {
453 SCIPdebugMsg(scip, "var with almost zero coef in boundchange-row %.15g*<%s> <=/>= %.15g; scaling up\n",
454 rowprep->coefs[0], SCIPvarGetName(rowprep->vars[0]), rowprep->side);
455 (void) SCIPscaleRowprep(rowprep, REALABS(1.0/rowprep->coefs[0]));
456 return SCIP_OKAY;
457 }
458
459 for( i = 0; i < rowprep->nvars; ++i )
460 {
461 coef = rowprep->coefs[i];
462 roundcoef = SCIPround(scip, coef);
463 if( coef != roundcoef && SCIPisEQ(scip, coef, roundcoef) ) /*lint !e777*/
464 {
465 SCIP_Real xbnd;
466 SCIP_VAR* var;
467
468 var = rowprep->vars[i];
469 if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
470 if( rowprep->local )
471 xbnd = coef > roundcoef ? SCIPvarGetLbLocal(var) : SCIPvarGetUbLocal(var);
472 else
473 xbnd = coef > roundcoef ? SCIPvarGetLbGlobal(var) : SCIPvarGetUbGlobal(var);
474 else
475 if( rowprep->local )
476 xbnd = coef > roundcoef ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
477 else
478 xbnd = coef > roundcoef ? SCIPvarGetUbGlobal(var) : SCIPvarGetLbGlobal(var);
479
480 if( !SCIPisInfinity(scip, REALABS(xbnd)) )
481 {
482 /* if there is a bound, then relax row side so rounding coef will not introduce an error */
483 SCIPdebugMsg(scip, "var <%s> [%g,%g] has almost integral coef %.15g, round coefficient to %g and add constant %g\n",
484 SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), coef, roundcoef, (coef-roundcoef) * xbnd);
485 SCIProwprepAddConstant(rowprep, (coef-roundcoef) * xbnd);
486 }
487 else
488 {
489 /* if there is no bound, then we make the coef integral, too, even though this will introduce an error
490 * however, SCIP_ROW would do this anyway, but doing this here might eliminate some epsilon coefs (so they don't determine mincoef below)
491 * and helps to get a more accurate row violation value
492 */
493 SCIPdebugMsg(scip, "var <%s> [%g,%g] has almost integral coef %.15g, round coefficient to %g without relaxing side (!)\n",
494 SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), coef, roundcoef);
495 }
496 rowprep->coefs[i] = roundcoef;
497 if( viol != NULL )
498 *viol = SCIP_INVALID;
499
500 /* (potentially) remember the variable which coef has been modified here */
501 SCIP_CALL( rowprepRecordModifiedVar(scip, rowprep, var) );
502 }
503 }
504
505 /* forget about coefs that became exactly zero by the above step */
506 while( rowprep->nvars > 0 && rowprep->coefs[rowprep->nvars-1] == 0.0 )
507 --rowprep->nvars;
508
509 return SCIP_OKAY;
510}
511
512/** relaxes almost zero side */
513static
515 SCIP* scip, /**< SCIP data structure */
516 SCIP_ROWPREP* rowprep, /**< rowprep to be improve */
517 SCIP_Real* viol /**< NULL or violation of cut in sol (input), set to SCIP_INVALID if some coef changed */
518 )
519{
520 /* SCIP_ROW handling will replace a side close to 0 by 0.0, even if that makes the row more restrictive
521 * we thus relax the side here so that it will either be 0 now or will not be rounded to 0 later
522 */
523 if( rowprep->side == 0.0 || !SCIPisZero(scip, rowprep->side) )
524 return;
525
526 if( rowprep->side > 0.0 && rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
527 rowprep->side = 1.1*SCIPepsilon(scip);
528 else if( rowprep->side < 0.0 && rowprep->sidetype == SCIP_SIDETYPE_LEFT )
529 rowprep->side = -1.1*SCIPepsilon(scip);
530 else
531 rowprep->side = 0.0;
532
533 if( rowprep->recordmodifications )
534 rowprep->modifiedside = TRUE;
535
536 if( viol != NULL )
537 *viol = SCIP_INVALID;
538}
539
540#ifdef NDEBUG
541/* Undo the defines from pub_misc_rowprep.h, which exist if NDEBUG is defined. */
542#undef SCIProwprepGetNVars
543#undef SCIProwprepGetVars
544#undef SCIProwprepGetCoefs
545#undef SCIProwprepGetSide
546#undef SCIProwprepGetSidetype
547#undef SCIProwprepIsLocal
548#undef SCIProwprepGetName
549#undef SCIProwprepGetNModifiedVars
550#undef SCIProwprepGetModifiedVars
551#undef SCIProwprepSetCoef
552#undef SCIProwprepAddSide
553#undef SCIProwprepAddConstant
554#undef SCIProwprepSetSidetype
555#undef SCIProwprepSetLocal
556#undef SCIProwprepRecordModifications
557#endif
558
559/** creates a SCIP_ROWPREP datastructure
560 *
561 * Initial row represents 0 &le; 0.
562 */
564 SCIP* scip, /**< SCIP data structure */
565 SCIP_ROWPREP** rowprep, /**< buffer to store pointer to rowprep */
566 SCIP_SIDETYPE sidetype, /**< whether cut will be or lower-equal or larger-equal type */
567 SCIP_Bool local /**< whether cut will be valid only locally */
568 )
569{
570 assert(scip != NULL);
571 assert(rowprep != NULL);
572
574 BMSclearMemory(*rowprep);
575
576 (*rowprep)->sidetype = sidetype;
577 (*rowprep)->local = local;
578
579 return SCIP_OKAY;
580}
581
582/** frees a SCIP_ROWPREP datastructure */
584 SCIP* scip, /**< SCIP data structure */
585 SCIP_ROWPREP** rowprep /**< pointer that stores pointer to rowprep */
586 )
587{
588 assert(scip != NULL);
589 assert(rowprep != NULL);
590 assert(*rowprep != NULL);
591
592 SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->vars, (*rowprep)->varssize);
593 SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->coefs, (*rowprep)->varssize);
594 SCIPfreeBlockMemoryArrayNull(scip, &(*rowprep)->modifiedvars, (*rowprep)->modifiedvarssize);
595 SCIPfreeBlockMemory(scip, rowprep);
596}
597
598/** creates a copy of a SCIP_ROWPREP datastructure */
600 SCIP* scip, /**< SCIP data structure */
601 SCIP_ROWPREP** target, /**< buffer to store pointer of rowprep copy */
602 SCIP_ROWPREP* source /**< rowprep to copy */
603 )
604{
605 assert(scip != NULL);
606 assert(target != NULL);
607 assert(source != NULL);
608
609 SCIP_CALL( SCIPduplicateBlockMemory(scip, target, source) );
610 if( source->coefs != NULL )
611 {
612 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->coefs, source->coefs, source->varssize) );
613 }
614 if( source->vars != NULL )
615 {
616 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*target)->vars, source->vars, source->varssize) );
617 }
618
619 (*target)->recordmodifications = FALSE;
620 (*target)->modifiedvars = NULL;
621 (*target)->modifiedvarssize = 0;
622 (*target)->nmodifiedvars = 0;
623 (*target)->modifiedside = FALSE;
624
625 return SCIP_OKAY;
626}
627
628/** gives number of terms in rowprep */
630 SCIP_ROWPREP* rowprep /**< rowprep */
631 )
632{
633 assert(rowprep != NULL);
634
635 return rowprep->nvars;
636}
637
638/** gives variables of rowprep (feel free to modify) */
640 SCIP_ROWPREP* rowprep /**< rowprep */
641 )
642{
643 assert(rowprep != NULL);
644
645 return rowprep->vars;
646}
647
648/** gives coefficients of rowprep (feel free to modify) */
650 SCIP_ROWPREP* rowprep /**< rowprep */
651 )
652{
653 assert(rowprep != NULL);
654
655 return rowprep->coefs;
656}
657
658/** gives side of rowprep */
660 SCIP_ROWPREP* rowprep /**< rowprep */
661 )
662{
663 assert(rowprep != NULL);
664
665 return rowprep->side;
666}
667
668/** gives kind of inequality of rowprep */
670 SCIP_ROWPREP* rowprep /**< rowprep */
671 )
672{
673 assert(rowprep != NULL);
674
675 return rowprep->sidetype;
676}
677
678/** returns whether rowprep is locally valid only */
680 SCIP_ROWPREP* rowprep /**< rowprep */
681 )
682{
683 assert(rowprep != NULL);
684
685 return rowprep->local;
686}
687
688/** returns name of rowprep (feel free to modify) */
690 SCIP_ROWPREP* rowprep /**< rowprep */
691 )
692{
693 assert(rowprep != NULL);
694
695 return rowprep->name;
696}
697
698/** returns number of variables which coefficients were modified in cleanup */
700 SCIP_ROWPREP* rowprep /**< rowprep */
701 )
702{
703 assert(rowprep != NULL);
704
705 return rowprep->nmodifiedvars;
706}
707
708/** returns variables which coefficients were modified in cleanup */
710 SCIP_ROWPREP* rowprep /**< rowprep */
711 )
712{
713 assert(rowprep != NULL);
714
715 return rowprep->modifiedvars;
716}
717
718/** resets rowprep to have 0 terms and side 0.0 */
720 SCIP_ROWPREP* rowprep /**< rowprep */
721 )
722{
723 assert(rowprep != NULL);
724
725 rowprep->nvars = 0;
726 rowprep->side = 0.0;
727
728 rowprep->recordmodifications = FALSE;
729 rowprep->nmodifiedvars = 0;
730 rowprep->modifiedside = FALSE;
731}
732
733/** sets coefficient idx of rowprep */
735 SCIP_ROWPREP* rowprep, /**< rowprep */
736 int idx, /**< index of coef to set */
737 SCIP_Real newcoef /**< new coefficient */
738 )
739{
740 assert(rowprep != NULL);
741
742 rowprep->coefs[idx] = newcoef;
743}
744
745/** adds constant value to side of rowprep */
747 SCIP_ROWPREP* rowprep, /**< rowprep */
748 SCIP_Real side /**< constant value to be added to side */
749 )
750{
751 assert(rowprep != NULL);
752
753 rowprep->side += side;
754}
755
756/** adds constant term to rowprep
757 *
758 * Substracts constant from side.
759 */
761 SCIP_ROWPREP* rowprep, /**< rowprep */
762 SCIP_Real constant /**< constant value to be added */
763 )
764{
765 SCIProwprepAddSide(rowprep, -constant);
766}
767
768/** sets side type of rowprep */
770 SCIP_ROWPREP* rowprep, /**< rowprep */
771 SCIP_SIDETYPE sidetype /**< new side type */
772 )
773{
774 assert(rowprep != NULL);
775
776 rowprep->sidetype = sidetype;
777}
778
779/** sets whether rowprep is local */
781 SCIP_ROWPREP* rowprep, /**< rowprep */
782 SCIP_Bool islocal /**< whether rowprep is local */
783 )
784{
785 assert(rowprep != NULL);
786
787 rowprep->local = islocal;
788}
789
790/** enables recording for where modifications were done in cleanup */
792 SCIP_ROWPREP* rowprep /**< rowprep */
793 )
794{
795 assert(rowprep != NULL);
796
797 rowprep->recordmodifications = TRUE;
798}
799
800/** prints a rowprep */
802 SCIP* scip, /**< SCIP data structure */
803 SCIP_ROWPREP* rowprep, /**< rowprep to be printed */
804 FILE* file /**< file to print to, or NULL for stdout */
805 )
806{
807 int i;
808
809 assert(scip != NULL);
810 assert(rowprep != NULL);
811
812 if( *rowprep->name != '\0' )
813 {
814 SCIPinfoMessage(scip, file, "[%s](%c) ", rowprep->name, rowprep->local ? 'l' : 'g');
815 }
816
817 for( i = 0; i < rowprep->nvars; ++i )
818 {
819 SCIPinfoMessage(scip, file, "%+.15g*<%s> ", rowprep->coefs[i], SCIPvarGetName(rowprep->vars[i]));
820 }
821
822 SCIPinfoMessage(scip, file, rowprep->sidetype == SCIP_SIDETYPE_LEFT ? ">= %.15g\n" : "<= %.15g\n", rowprep->side);
823}
824
825/** prints a rowprep and values in solution */
827 SCIP* scip, /**< SCIP data structure */
828 SCIP_ROWPREP* rowprep, /**< rowprep to be printed */
829 SCIP_SOL* sol, /**< solution for activity */
830 FILE* file /**< file to print to, or NULL for stdout */
831 )
832{
833 SCIP_VAR* var;
834 SCIP_Real coef;
835 SCIP_Real term;
836 SCIP_Real maxterm;
837 SCIP_Real activity;
838 SCIP_Real violation;
839 int maxtermidx;
840 int i;
841
842 assert(scip != NULL);
843 assert(rowprep != NULL);
844
845 if( *rowprep->name != '\0' )
846 {
847 SCIPinfoMessage(scip, file, "[%s](%c) ", rowprep->name, rowprep->local ? 'l' : 'g');
848 }
849
850 activity = 0.0;
851 maxterm = REALABS(rowprep->side);
852 maxtermidx = -1;
853 for( i = 0; i < rowprep->nvars; ++i )
854 {
855 coef = rowprep->coefs[i];
856 var = rowprep->vars[i];
857 SCIPinfoMessage(scip, file, "%+.15g*<%s>(%.15g) ", coef, SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var));
858
859 term = coef * SCIPgetSolVal(scip, sol, var);
860 if( REALABS(term) > maxterm )
861 {
862 maxterm = term;
863 maxtermidx = i;
864 }
865
866 activity += term;
867 }
868
869 SCIPinfoMessage(scip, file, rowprep->sidetype == SCIP_SIDETYPE_LEFT ? ">= %.15g" : "<= %.15g", rowprep->side);
870
871 if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
872 /* cut is activity <= side -> violation is activity - side (if positive) */
873 violation = activity - rowprep->side;
874 else
875 /* cut is activity >= side -> violation is side - activity (if positive) */
876 violation = rowprep->side - activity;
877
878 SCIPinfoMessage(scip, file, "; activity %.15g", activity);
879 SCIPinfoMessage(scip, file, "; violation %e", violation);
880 SCIPinfoMessage(scip, file, "; maxterm %e at pos %d\n", maxterm, maxtermidx);
881}
882
883/** ensures that rowprep has space for at least given number of additional terms
884 *
885 * Useful when knowing in advance how many terms will be added.
886 */
888 SCIP* scip, /**< SCIP data structure */
889 SCIP_ROWPREP* rowprep, /**< rowprep */
890 int size /**< number of additional terms for which to alloc space in rowprep */
891 )
892{
893 int oldsize;
894
895 assert(scip != NULL);
896 assert(rowprep != NULL);
897 assert(size >= 0);
898
899 if( rowprep->varssize >= rowprep->nvars + size )
900 return SCIP_OKAY; /* already enough space left */
901
902 /* realloc vars and coefs array */
903 oldsize = rowprep->varssize;
904 rowprep->varssize = SCIPcalcMemGrowSize(scip, rowprep->nvars + size);
905
906 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &rowprep->vars, oldsize, rowprep->varssize) );
907 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &rowprep->coefs, oldsize, rowprep->varssize) );
908
909 return SCIP_OKAY;
910}
911
912/** adds a term coef*var to a rowprep */
914 SCIP* scip, /**< SCIP data structure */
915 SCIP_ROWPREP* rowprep, /**< rowprep */
916 SCIP_VAR* var, /**< variable to add */
917 SCIP_Real coef /**< coefficient to add */
918 )
919{
920 assert(scip != NULL);
921 assert(rowprep != NULL);
922 assert(var != NULL);
923
924 if( coef == 0.0 )
925 return SCIP_OKAY;
926
927 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, 1) );
928 assert(rowprep->varssize > rowprep->nvars);
929
930 rowprep->vars[rowprep->nvars] = var;
931 rowprep->coefs[rowprep->nvars] = coef;
932 ++rowprep->nvars;
933
934 return SCIP_OKAY;
935}
936
937/** adds several terms coef*var to a rowprep */
939 SCIP* scip, /**< SCIP data structure */
940 SCIP_ROWPREP* rowprep, /**< rowprep */
941 int nvars, /**< number of terms to add */
942 SCIP_VAR** vars, /**< variables to add */
943 SCIP_Real* coefs /**< coefficients to add */
944 )
945{
946 assert(scip != NULL);
947 assert(rowprep != NULL);
948 assert(vars != NULL || nvars == 0);
949 assert(coefs != NULL || nvars == 0);
950
951 if( nvars == 0 )
952 return SCIP_OKAY;
953
954 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nvars) );
955 assert(rowprep->varssize >= rowprep->nvars + nvars);
956
957 /*lint --e{866} */
958 BMScopyMemoryArray(rowprep->vars + rowprep->nvars, vars, nvars);
959 BMScopyMemoryArray(rowprep->coefs + rowprep->nvars, coefs, nvars);
960 rowprep->nvars += nvars;
961
962 return SCIP_OKAY;
963}
964
965/** computes violation of rowprep in a given solution
966 *
967 * Can return whether the violation value is reliable from a floating-point accuracy point of view.
968 * The value will not be deemed reliable when its calculation involved the subtraction of large numbers.
969 * To be precise, the violation of an inequality \f$ \sum_i a_ix_i \leq b \f$ in a solution \f$x^*\f$ is deemed
970 * reliable if \f$ |\sum_i a_ix^*_i - b| \geq 2^{-50} \max (|b|, \max_i |a_ix^*_i|) \f$.
971 */
973 SCIP* scip, /**< SCIP data structure */
974 SCIP_ROWPREP* rowprep, /**< rowprep */
975 SCIP_SOL* sol, /**< solution or NULL for LP solution */
976 SCIP_Bool* reliable /**< buffer to store whether computed violation is reliable (numerically), or NULL if not of interest */
977 )
978{
979 SCIP_Real activity;
980 SCIP_Real maxterm;
981 SCIP_Real term;
982 SCIP_Real violation;
983 SCIP_Real val;
984 int i;
985
986 activity = 0.0;
987 maxterm = REALABS(rowprep->side);
988 for( i = 0; i < rowprep->nvars; ++i )
989 {
990 /* Loose variable have the best bound as LP solution value.
991 * HOWEVER, they become column variables when they are added to a row (via SCIPaddVarsToRow below).
992 * When this happens, their LP solution value changes to 0.0!
993 * So when calculating the row activity for an LP solution, we treat loose variable as if they were already column variables.
994 */
995 if( sol != NULL || SCIPvarGetStatus(rowprep->vars[i]) != SCIP_VARSTATUS_LOOSE )
996 {
997 val = SCIPgetSolVal(scip, sol, rowprep->vars[i]);
998
999 /* If a variable is at infinity, then this should lead to an immediate decision.
1000 * Having different contradicting infinities is something I would now know how to handle and am ignoring now.
1001 */
1002 if( SCIPisInfinity(scip, val * (rowprep->coefs[i] >= 0.0 ? 1.0 : -1.0)) )
1003 {
1004 /* activity = SCIPinfinity(scip); */
1005 if( reliable != NULL )
1006 *reliable = TRUE;
1007 if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
1008 return SCIPinfinity(scip); /* infinity <= side -> always violated */
1009 else
1010 return 0.0; /* infinity >= side -> never violated */
1011 }
1012 if( SCIPisInfinity(scip, val * (rowprep->coefs[i] >= 0.0 ? -1.0 : 1.0)) )
1013 {
1014 /* activity = -SCIPinfinity(scip); */
1015 if( reliable != NULL )
1016 *reliable = TRUE;
1017 if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
1018 return 0.0; /* -infinity <= side -> never violated */
1019 else
1020 return SCIPinfinity(scip); /* -infinity >= side -> always violated */
1021 }
1022
1023 term = rowprep->coefs[i] * val;
1024 activity += term;
1025
1026 if( reliable != NULL && REALABS(term) > maxterm )
1027 maxterm = REALABS(term);
1028 }
1029 }
1030
1031 if( rowprep->sidetype == SCIP_SIDETYPE_RIGHT )
1032 /* cut is activity <= side -> violation is activity - side (if positive) */
1033 violation = activity - rowprep->side;
1034 else
1035 /* cut is activity >= side -> violation is side - activity (if positive) */
1036 violation = rowprep->side - activity;
1037
1038 /* In double precision, the mantissa (or significand) of a floating point number has 52 bit.
1039 * Therefore, if the exponent in the violation is 52 (or more) less than the one of maxterm,
1040 * then it is essentially random.
1041 * We require here that the exponents differ by at most 50.
1042 * To be more robust w.r.t. scaling of the row, we look at the exponent of the quotient maxterm/violation
1043 * instead of the difference of the exponents of maxterm and violation.
1044 */
1045 if( reliable != NULL )
1046 {
1047 if( violation != 0.0 )
1048 {
1049 int exponent;
1050 (void) frexp(maxterm / violation, &exponent); /* difference in exponents for maxterm and violation */
1051 *reliable = exponent <= 50;
1052 }
1053 else
1054 *reliable = TRUE; /* not clear how to evaluate reliability here, so think positive */
1055 }
1056
1057 return MAX(violation, 0.0);
1058}
1059
1060/** computes violation of rowprep in a given solution and reports whether that value seem numerically reliable
1061 *
1062 * @see SCIPgetRowprepViolation()
1063 */
1065 SCIP* scip, /**< SCIP data structure */
1066 SCIP_ROWPREP* rowprep, /**< rowprep */
1067 SCIP_SOL* sol /**< solution or NULL for LP solution */
1068 )
1069{
1070 SCIP_Bool reliable;
1071
1072 assert(scip != NULL);
1073 assert(rowprep != NULL);
1074
1075 (void) SCIPgetRowprepViolation(scip, rowprep, sol, &reliable);
1076
1077 return reliable;
1078}
1079
1080/** Merge terms that use same variable and eliminate zero coefficients.
1081 *
1082 * Removes a variable if its bounds have a relative difference of below epsilon.
1083 * Local bounds are checked for local rows, otherwise global bounds are used.
1084 * If the bounds are not absolute equal, the bound that relaxes the row is used.
1085 *
1086 * Terms are sorted by variable (see SCIPvarComp()) after return.
1087 */
1089 SCIP* scip, /**< SCIP data structure */
1090 SCIP_ROWPREP* rowprep /**< rowprep to be cleaned up */
1091 )
1092{
1093 int i;
1094 int j;
1095
1096 assert(scip != NULL);
1097 assert(rowprep != NULL);
1098
1099 if( rowprep->nvars <= 1 )
1100 return;
1101
1102 /* sort terms by variable index */
1103 SCIPsortPtrReal((void**)rowprep->vars, rowprep->coefs, SCIPvarComp, rowprep->nvars);
1104
1105 /* merge terms with same variable, drop 0 coefficients */
1106 i = 0;
1107 j = 1;
1108 while( j < rowprep->nvars )
1109 {
1110 if( rowprep->vars[i] == rowprep->vars[j] )
1111 {
1112 /* merge term j into term i */
1113 rowprep->coefs[i] += rowprep->coefs[j];
1114 ++j;
1115 continue;
1116 }
1117
1118 /* move term i into side if fixed */
1119 if( rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbLocal(rowprep->vars[i]), SCIPvarGetUbLocal(rowprep->vars[i])) )
1120 {
1121 if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1122 rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbLocal(rowprep->vars[i]);
1123 else
1124 rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbLocal(rowprep->vars[i]);
1125 rowprep->coefs[i] = 0.0; /* so will be cleaned out below */
1126 }
1127 else if( !rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbGlobal(rowprep->vars[i]), SCIPvarGetUbGlobal(rowprep->vars[i])) )
1128 {
1129 if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1130 rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbGlobal(rowprep->vars[i]);
1131 else
1132 rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbGlobal(rowprep->vars[i]);
1133 rowprep->coefs[i] = 0.0; /* so will be cleaned out below */
1134 }
1135
1136 if( rowprep->coefs[i] == 0.0 )
1137 {
1138 /* move term j to position i */
1139 rowprep->coefs[i] = rowprep->coefs[j];
1140 rowprep->vars[i] = rowprep->vars[j];
1141 ++j;
1142 continue;
1143 }
1144
1145 /* move term j to position i+1 and move on */
1146 if( j != i+1 )
1147 {
1148 rowprep->vars[i+1] = rowprep->vars[j];
1149 rowprep->coefs[i+1] = rowprep->coefs[j];
1150 }
1151 ++i;
1152 ++j;
1153 }
1154
1155 /* move term i into side if fixed */
1156 if( rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbLocal(rowprep->vars[i]), SCIPvarGetUbLocal(rowprep->vars[i])) )
1157 {
1158 if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1159 rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbLocal(rowprep->vars[i]);
1160 else
1161 rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbLocal(rowprep->vars[i]);
1162 rowprep->coefs[i] = 0.0; /* so will be cleaned out below */
1163 }
1164 else if( !rowprep->local && SCIPisRelEQ(scip, SCIPvarGetLbGlobal(rowprep->vars[i]), SCIPvarGetUbGlobal(rowprep->vars[i])) )
1165 {
1166 if( (rowprep->coefs[i] > 0.0) == (rowprep->sidetype == SCIP_SIDETYPE_RIGHT) )
1167 rowprep->side -= rowprep->coefs[i] * SCIPvarGetLbGlobal(rowprep->vars[i]);
1168 else
1169 rowprep->side -= rowprep->coefs[i] * SCIPvarGetUbGlobal(rowprep->vars[i]);
1170 rowprep->coefs[i] = 0.0; /* so will be cleaned out below */
1171 }
1172
1173 /* remaining term can have coef zero -> forget about it */
1174 if( rowprep->coefs[i] == 0.0 )
1175 --i;
1176
1177 /* i points to last term */
1178 rowprep->nvars = i+1;
1179}
1180
1181/** Cleans up and attempts to improve rowprep
1182 *
1183 * Drops small or large coefficients if coefrange is too large, if this can be done by relaxing the row.
1184 * Scales coefficients up to reach minimal violation, if possible.
1185 * Scaling is omitted if violation is very small (\ref ROWPREP_SCALEUP_VIOLNONZERO) or
1186 * maximal coefficient would become huge (\ref ROWPREP_SCALEUP_MAXMAXCOEF).
1187 * Scales coefficients and side down if they are large and if the minimal violation is still reached.
1188 * Rounds coefficients close to integral values to integrals, if this can be done by relaxing the row.
1189 * Rounds side within epsilon of 0 to 0.0 or +/-1.1*epsilon, whichever relaxes the row least.
1190 *
1191 * After return, the terms in the rowprep will be sorted by absolute value of coefficient, in decreasing order.
1192 * Thus, the coefrange can be obtained via `REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1])` (if nvars>0).
1193 *
1194 * `success` is set to TRUE if and only if the rowprep satisfies the following:
1195 * - the coefrange is below `maxcoefrange`
1196 * - the violation is at least `minviol`
1197 * - the violation is reliable or `minviol` = 0
1198 * - the absolute value of coefficients are below SCIPinfinity()
1199 * - the absolute value of the side is below SCIPinfinity()
1200 */
1202 SCIP* scip, /**< SCIP data structure */
1203 SCIP_ROWPREP* rowprep, /**< rowprep to be cleaned */
1204 SCIP_SOL* sol, /**< solution that we try to cut off, or NULL for LP solution */
1205 SCIP_Real minviol, /**< minimal absolute violation the row should achieve (w.r.t. sol) */
1206 SCIP_Real* viol, /**< buffer to store absolute violation of cleaned up cut in sol, or NULL if not of interest */
1207 SCIP_Bool* success /**< buffer to store whether cut cleanup was successful, or NULL if not of interest */
1208 )
1209{
1210 SCIP_Real myviol;
1211 SCIP_Bool violreliable = TRUE;
1212 SCIP_Real maxcoefrange;
1213#ifdef SCIP_DEBUG
1214 SCIP_Real mincoef = 1.0;
1215 SCIP_Real maxcoef = 1.0;
1216#endif
1217
1218 maxcoefrange = SCIPsetGetSepaMaxCoefRatioRowprep(scip->set);
1219
1220 if( rowprep->recordmodifications )
1221 {
1222 /* forget about possible previous modifications */
1223 rowprep->nmodifiedvars = 0;
1224 rowprep->modifiedside = FALSE;
1225 }
1226
1227 /* sort term by absolute value of coef. */
1229
1230#ifdef SCIP_DEBUG
1231 if( rowprep->nvars > 0 )
1232 {
1233 maxcoef = REALABS(rowprep->coefs[0]);
1234 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1235 }
1236
1237 SCIPinfoMessage(scip, NULL, "starting cleanup, coefrange %g: ", maxcoef/mincoef);
1238 SCIPprintRowprep(scip, rowprep, NULL);
1239#endif
1240
1241 /* improve coefficient range by aggregating out variables */
1242 SCIP_CALL( rowprepCleanupImproveCoefrange(scip, rowprep, sol, maxcoefrange) );
1243
1244 /* get current violation in sol (reliability info only needed if success is not NULL) */
1245 myviol = SCIPgetRowprepViolation(scip, rowprep, sol, success != NULL ? &violreliable : NULL); /*lint !e826*/
1246 assert(myviol >= 0.0);
1247
1248#ifdef SCIP_DEBUG
1249 if( rowprep->nvars > 0 )
1250 {
1251 maxcoef = REALABS(rowprep->coefs[0]);
1252 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1253 }
1254
1255 SCIPinfoMessage(scip, NULL, "improved coefrange to %g, viol %g: ", maxcoef / mincoef, myviol);
1256 SCIPprintRowprep(scip, rowprep, NULL);
1257#endif
1258
1259 /* if there is interest in achieving some minimal violation, then possibly scale up to increase violation
1260 * this updates myviol; since this is only scaling the cut, it doesn't change anything about the reliability of the violation value */
1261 if( minviol > 0.0 )
1262 {
1263 /* first, try to achieve scip's minefficacy (typically 1e-4) */
1264 if( SCIPgetSepaMinEfficacy(scip) > minviol )
1266 /* in case scip minefficacy could not be reached or was smaller than minviol, try with the given minviol */
1267 rowprepCleanupScaleup(scip, rowprep, &myviol, minviol);
1268 }
1269
1270 /* scale down to improve numerics, updates myviol (reliability doesn't change) */
1271 rowprepCleanupScaledown(scip, rowprep, &myviol, MAX(SCIPgetSepaMinEfficacy(scip), minviol)); /*lint !e666*/
1272
1273#ifdef SCIP_DEBUG
1274 SCIPinfoMessage(scip, NULL, "applied scaling, viol %g: ", myviol);
1275 SCIPprintRowprep(scip, rowprep, NULL);
1276#endif
1277
1278 /* turn almost-integral coefs to integral values, may set myviol to SCIP_INVALID */
1279 SCIP_CALL( rowprepCleanupIntegralCoefs(scip, rowprep, &myviol) );
1280
1281 /* relax almost-zero side, may set myviol to SCIP_INVALID */
1282 rowprepCleanupSide(scip, rowprep, &myviol);
1283
1284#ifdef SCIP_DEBUG
1285 SCIPinfoMessage(scip, NULL, "adjusted almost-integral coefs and sides, viol %g: ", myviol);
1286 SCIPprintRowprep(scip, rowprep, NULL);
1287#endif
1288
1289#if !1
1290 /* compute final coefrange, if requested by caller */
1291 if( coefrange != NULL )
1292 {
1293 if( rowprep->nvars > 0 )
1294 *coefrange = REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]);
1295 else
1296 *coefrange = 1.0;
1297 }
1298#endif
1299
1300 /* check whether rowprep could be turned into a reasonable row */
1301 if( success != NULL )
1302 {
1303 *success = TRUE;
1304
1305 /* check whether the coef.range is below maxcoefrange */
1306 if( rowprep->nvars > 0 && REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]) > maxcoefrange )
1307 {
1308 SCIPdebugMsg(scip, "rowprep coefrange %g is above the limit %g\n", REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]), maxcoefrange);
1309 *success = FALSE;
1310 }
1311
1312 /* check whether coefficients are below SCIPinfinity (terms are order by coef value) */
1313 if( *success && rowprep->nvars > 0 && SCIPisInfinity(scip, REALABS(rowprep->coefs[0])) )
1314 {
1315 SCIPdebugMsg(scip, "rowprep coefficient %g is beyond value for infinity\n", rowprep->coefs[0]);
1316 *success = FALSE;
1317 }
1318
1319 /* check whether the absolute value of the side is below SCIPinfinity */
1320 if( *success && SCIPisInfinity(scip, REALABS(rowprep->side)) )
1321 {
1322 SCIPdebugMsg(scip, "rowprep side %g is beyond value for infinity\n", rowprep->side);
1323 *success = FALSE;
1324 }
1325
1326 /* check if violation is at least minviol and reliable, if minviol > 0 */
1327 if( *success && minviol > 0.0 )
1328 {
1329 /* may need to recompute violation if coefs or side was modified above */
1330 if( myviol == SCIP_INVALID ) /*lint !e777 */
1331 myviol = SCIPgetRowprepViolation(scip, rowprep, sol, &violreliable);
1332
1333 if( !violreliable )
1334 {
1335 SCIPdebugMsg(scip, "rowprep violation %g is not reliable\n", myviol);
1336 *success = FALSE;
1337 }
1338 else if( myviol < minviol )
1339 {
1340 SCIPdebugMsg(scip, "rowprep violation %g is below minimal violation %g\n", myviol, minviol);
1341 *success = FALSE;
1342 }
1343 }
1344 }
1345
1346 /* If we updated myviol correctly, then it should coincide with freshly computed violation.
1347 * I leave this assert off for now, since getting the tolerance in the EQ correctly is not trivial. We recompute viol below anyway.
1348 */
1349 /* assert(myviol == SCIP_INVALID || SCIPisEQ(scip, myviol, SCIPgetRowprepViolation(scip, rowprep, sol, NULL))); */
1350
1351 /* compute final violation, if requested by caller */
1352 if( viol != NULL ) /*lint --e{777} */
1353 *viol = myviol == SCIP_INVALID ? SCIPgetRowprepViolation(scip, rowprep, sol, NULL) : myviol;
1354
1355 return SCIP_OKAY;
1356}
1357
1358/** Cleans up and attempts to improve rowprep without regard for violation
1359 *
1360 * Drops small or large coefficients if their ratio is beyond separating/maxcoefratiofacrowprep / numerics/feastol,
1361 * if this can be done by relaxing the row.
1362 * Scales coefficients and side to have maximal coefficient in `[1/maxcoefbound,maxcoefbound]`.
1363 * Rounds coefficients close to integral values to integrals, if this can be done by relaxing the row.
1364 * Rounds side within epsilon of 0 to 0.0 or +/-1.1*epsilon, whichever relaxes the row least.
1365 *
1366 * After return, the terms in the rowprep will be sorted by absolute value of coefficient, in decreasing order.
1367 * Thus, the coefratio can be obtained via `REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1])` (if nvars>0).
1368 *
1369 * `success` is set to TRUE if and only if the rowprep satisfies the following:
1370 * - the coefratio is below separating/maxcoefratiofacrowprep / numerics/feastol
1371 * - the absolute value of coefficients are below SCIPinfinity()
1372 * - the absolute value of the side is below SCIPinfinity()
1373 *
1374 * In difference to SCIPcleanupRowprep(), this function does not scale up the row to increase the absolute violation.
1375 */
1377 SCIP* scip, /**< SCIP data structure */
1378 SCIP_ROWPREP* rowprep, /**< rowprep to be cleaned */
1379 SCIP_SOL* sol, /**< solution that we try to cut off, or NULL for LP solution */
1380 SCIP_Real maxcoefbound, /**< bound on absolute value of largest coefficient */
1381 SCIP_Bool* success /**< buffer to store whether cut cleanup was successful, or NULL if not of interest */
1382 )
1383{
1384 SCIP_Real maxcoefrange;
1385#ifdef SCIP_DEBUG
1386 SCIP_Real mincoef = 1.0;
1387 SCIP_Real maxcoef = 1.0;
1388#endif
1389
1390 assert(maxcoefbound >= 1.0);
1391
1392 maxcoefrange = SCIPsetGetSepaMaxCoefRatioRowprep(scip->set);
1393
1394 if( rowprep->recordmodifications )
1395 {
1396 /* forget about possible previous modifications */
1397 rowprep->nmodifiedvars = 0;
1398 rowprep->modifiedside = FALSE;
1399 }
1400
1401 /* sort term by absolute value of coef. */
1403
1404#ifdef SCIP_DEBUG
1405 if( rowprep->nvars > 0 )
1406 {
1407 maxcoef = REALABS(rowprep->coefs[0]);
1408 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1409 }
1410
1411 SCIPinfoMessage(scip, NULL, "starting cleanup, coefrange %g: ", maxcoef/mincoef);
1412 SCIPprintRowprep(scip, rowprep, NULL);
1413#endif
1414
1415 /* improve coefficient range by aggregating out variables */
1416 SCIP_CALL( rowprepCleanupImproveCoefrange(scip, rowprep, sol, maxcoefrange) );
1417
1418#ifdef SCIP_DEBUG
1419 if( rowprep->nvars > 0 )
1420 {
1421 maxcoef = REALABS(rowprep->coefs[0]);
1422 mincoef = REALABS(rowprep->coefs[rowprep->nvars-1]);
1423 }
1424
1425 SCIPinfoMessage(scip, NULL, "improved coefrange to %g: ", maxcoef / mincoef);
1426 SCIPprintRowprep(scip, rowprep, NULL);
1427#endif
1428
1429 /* scale up or down to improve numerics
1430 * if maximal coef is below 1.0/maxcoefbound, scale up to reach ~ 1.0/maxcoefbound
1431 * if maximal coef is above maxcoefbound, scale down to ~ maxcoefbound
1432 */
1433 if( rowprep->nvars > 0 && !SCIPisInfinity(scip, maxcoefbound) )
1434 {
1435 SCIP_Real expon = 0.0;
1436 if( REALABS(rowprep->coefs[0]) < 1.0/maxcoefbound )
1437 expon = SCIPscaleRowprep(rowprep, (1.0/maxcoefbound) / REALABS(rowprep->coefs[0]));
1438 else if( REALABS(rowprep->coefs[0]) > maxcoefbound )
1439 expon = SCIPscaleRowprep(rowprep, maxcoefbound / REALABS(rowprep->coefs[0]));
1440
1441#ifdef SCIP_DEBUG
1442 SCIPinfoMessage(scip, NULL, "applied scaling by %g: ", pow(2.0, expon));
1443 SCIPprintRowprep(scip, rowprep, NULL);
1444#else
1445 (void) expon;
1446#endif
1447 }
1448
1449 /* turn almost-integral coefs to integral values */
1451
1452 /* relax almost-zero side */
1453 rowprepCleanupSide(scip, rowprep, NULL);
1454
1455#ifdef SCIP_DEBUG
1456 SCIPinfoMessage(scip, NULL, "adjusted almost-integral coefs and sides: ");
1457 SCIPprintRowprep(scip, rowprep, NULL);
1458#endif
1459
1460 /* check whether rowprep could be turned into a reasonable row */
1461 if( success != NULL )
1462 {
1463 *success = TRUE;
1464
1465 /* check whether the coef.range is below maxcoefrange */
1466 if( rowprep->nvars > 0 && REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]) > maxcoefrange )
1467 {
1468 SCIPdebugMsg(scip, "rowprep coefrange %g is above the limit %g\n", REALABS(rowprep->coefs[0]) / REALABS(rowprep->coefs[rowprep->nvars-1]), maxcoefrange);
1469 *success = FALSE;
1470 }
1471
1472 /* check whether coefficients are below SCIPinfinity (terms are order by coef value) */
1473 if( *success && rowprep->nvars > 0 && SCIPisInfinity(scip, REALABS(rowprep->coefs[0])) )
1474 {
1475 SCIPdebugMsg(scip, "rowprep coefficient %g is beyond value for infinity\n", rowprep->coefs[0]);
1476 *success = FALSE;
1477 }
1478
1479 /* check whether the absolute value of the side is below SCIPinfinity */
1480 if( *success && SCIPisInfinity(scip, REALABS(rowprep->side)) )
1481 {
1482 SCIPdebugMsg(scip, "rowprep side %g is beyond value for infinity\n", rowprep->side);
1483 *success = FALSE;
1484 }
1485 }
1486
1487 return SCIP_OKAY;
1488}
1489
1490/** Scales up a rowprep to increase coefficients/sides that are within epsilon to an integer value, if possible.
1491 *
1492 * Computes the minimal fractionality of all fractional coefficients and the side of the rowprep.
1493 * If this fractionality is below epsilon, the rowprep is scaled up such that the fractionality exceeds epsilon,
1494 * if this will not put any coefficient or side above SCIPhugeValue().
1495 *
1496 * This function does not relax the rowprep.
1497 *
1498 * `success` is set to TRUE if the resulting rowprep can be turned into a SCIP_ROW, that is,
1499 * all coefs and the side is below SCIPinfinity() and fractionalities are above epsilon.
1500 * If `success` is set to FALSE, then the rowprep will not have been modified.
1501 *
1502 * @return The applied scaling factor, if `success` is set to TRUE.
1503 */
1505 SCIP* scip, /**< SCIP data structure */
1506 SCIP_ROWPREP* rowprep, /**< rowprep to be cleaned */
1507 SCIP_Real minscaleup, /**< minimal factor by which to scale up row, or <= 1.0 if to be ignored */
1508 SCIP_Bool* success /**< buffer to store whether rowprep could be turned into SCIP_ROW without loss, or NULL if not of interest */
1509 )
1510{
1511 SCIP_Real minfrac = 0.5;
1512 SCIP_Real minfrac0 = 0.5;
1513 SCIP_Real frac;
1514 SCIP_Real maxval;
1515 SCIP_Real factor = 1.0;
1516 SCIP_Bool makeintegral = TRUE;
1517 int i;
1518
1519 /* find the smallest fractionality in rowprep sides and coefficients and the largest absolute coefficient/side */
1520 frac = REALABS(floor(rowprep->side + 0.5) - rowprep->side);
1521 if( frac != 0.0 )
1522 {
1523 if( REALABS(rowprep->side) > 0.5 )
1524 {
1525 if( frac < minfrac )
1526 minfrac = frac;
1527 }
1528 else if( frac < minfrac0 )
1529 minfrac0 = frac;
1530 }
1531 maxval = REALABS(rowprep->side);
1532
1533 for( i = 0; i < rowprep->nvars; ++i )
1534 {
1535 frac = REALABS(floor(rowprep->coefs[i] + 0.5) - rowprep->coefs[i]);
1536 if( frac != 0.0 )
1537 {
1538 if( REALABS(rowprep->coefs[i]) > 0.5 )
1539 {
1540 if( frac < minfrac )
1541 minfrac = frac;
1542 }
1543 else if( frac < minfrac0 )
1544 minfrac0 = frac;
1545 }
1546 if( REALABS(rowprep->coefs[i]) > maxval )
1547 maxval = REALABS(rowprep->coefs[i]);
1548 }
1549
1550 SCIPdebugMsg(scip, "minimal fractional of rowprep coefs and side is %g, max coef/side is %g\n", MIN(minfrac, minfrac0), maxval);
1551
1552 /* in order for SCIP_ROW to not modify the coefs and side, they need to be more than epsilon way from an integer value
1553 *
1554 * If the integer value is 0, then scaling up the rowprep by epsilon/minfrac will increase its minimal fractionality
1555 * above epsilon.
1556 * If the integer value is not zero, then scaling up the rowprep by a well-chosen fractional number alpha will increase
1557 * the minimal fractionality by about alpha*integer-value mod 1. To reduce the chance that alpha*integer-value is integral,
1558 * we use a "very fractional" value for alpha.
1559 *
1560 * If the scaling increases the maximal coef/value beyond SCIPinfinity, then the rowprep would be useless.
1561 * We even check that we don't increase beyond SCIPhugeValue here
1562 */
1563 if( minfrac0 <= SCIPepsilon(scip) )
1564 {
1565 factor = 1.1 * SCIPepsilon(scip) / minfrac0;
1566
1567 if( factor < minscaleup )
1568 factor = minscaleup;
1569 }
1570 else if( minfrac <= SCIPepsilon(scip) )
1571 {
1572 factor = MAX(M_SQRT2, minscaleup);
1573 makeintegral = FALSE;
1574 }
1575 else if( minscaleup > 1.0 )
1576 {
1577 factor = minscaleup;
1578 }
1579 else
1580 {
1581 /* do not scale up, only check whether maxval is already below infinity */
1582 if( success != NULL )
1583 *success = !SCIPisInfinity(scip, maxval);
1584
1585 return 1.0;
1586 }
1587
1588 if( !SCIPisHugeValue(scip, factor * maxval) )
1589 {
1590 if( makeintegral)
1591 {
1592 factor = SCIPscaleRowprep(rowprep, factor);
1593
1594#ifdef SCIP_DEBUG
1595 factor = pow(2.0, factor); /* SCIPscaleRowprep() actually returned log2 of factor */
1596#endif
1597 }
1598 else
1599 {
1600 /* multiply each coefficient by factor */
1601 for( i = 0; i < rowprep->nvars; ++i )
1602 rowprep->coefs[i] *= factor;
1603
1604 /* multiply side by factor */
1605 rowprep->side *= factor;
1606 }
1607#ifdef SCIP_DEBUG
1608 maxval *= factor;
1609 SCIPinfoMessage(scip, NULL, "scaled up rowprep by %g (minfrac=%g, minscaleup=%g), maxval is now %g\n", factor, minfrac, minscaleup, maxval);
1610 SCIPprintRowprep(scip, rowprep, NULL);
1611#endif
1612
1613 if( success != NULL )
1614 *success = TRUE;
1615 }
1616 else if( success != NULL )
1617 *success = FALSE;
1618
1619 return factor;
1620}
1621
1622/** scales a rowprep by given factor (after some rounding)
1623 *
1624 * @return Exponent of actually applied scaling factor, if written as \f$2^x\f$.
1625 */
1627 SCIP_ROWPREP* rowprep, /**< rowprep to be scaled */
1628 SCIP_Real factor /**< suggested scale factor */
1629 )
1630{
1631 double v;
1632 int expon;
1633 int i;
1634
1635 assert(rowprep != NULL);
1636 assert(factor > 0.0);
1637
1638 /* write factor as v*2^expon with v in [0.5,1) */
1639 v = frexp(factor, &expon);
1640 /* adjust to v'*2^expon with v' in (0.5,1] by v'=v if v > 0.5, v'=1 if v=0.5 */
1641 if( v == 0.5 )
1642 --expon;
1643
1644 /* multiply each coefficient by 2^expon */
1645 for( i = 0; i < rowprep->nvars; ++i )
1646 rowprep->coefs[i] = ldexp(rowprep->coefs[i], expon);
1647
1648 /* multiply side by 2^expon */
1649 rowprep->side = ldexp(rowprep->side, expon);
1650
1651 return expon;
1652}
1653
1654/** generates a SCIP_ROW from a rowprep, setting its origin to given constraint handler */
1656 SCIP* scip, /**< SCIP data structure */
1657 SCIP_ROW** row, /**< buffer to store pointer to new row */
1658 SCIP_ROWPREP* rowprep, /**< rowprep to be turned into a row */
1659 SCIP_CONSHDLR* conshdlr /**< constraint handler */
1660 )
1661{
1662 assert(scip != NULL);
1663 assert(row != NULL);
1664 assert(rowprep != NULL);
1665 assert(conshdlr != NULL);
1666
1667 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, row, conshdlr, rowprep->name,
1668 rowprep->sidetype == SCIP_SIDETYPE_LEFT ? rowprep->side : -SCIPinfinity(scip),
1669 rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side : SCIPinfinity(scip),
1670 rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1671
1672 SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1673
1674 return SCIP_OKAY;
1675}
1676
1677/** generates a SCIP_ROW from a rowprep, setting its origin to given constraint */
1679 SCIP* scip, /**< SCIP data structure */
1680 SCIP_ROW** row, /**< buffer to store pointer to new row */
1681 SCIP_ROWPREP* rowprep, /**< rowprep to be turned into a row */
1682 SCIP_CONS* cons /**< constraint */
1683 )
1684{
1685 assert(scip != NULL);
1686 assert(row != NULL);
1687 assert(rowprep != NULL);
1688 assert(cons != NULL);
1689
1690 SCIP_CALL( SCIPcreateEmptyRowCons(scip, row, cons, rowprep->name,
1691 rowprep->sidetype == SCIP_SIDETYPE_LEFT ? rowprep->side : -SCIPinfinity(scip),
1692 rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side : SCIPinfinity(scip),
1693 rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1694
1695 SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1696
1697 return SCIP_OKAY;
1698}
1699
1700/** generates a SCIP_ROW from a rowprep, setting its origin to given separator */
1702 SCIP* scip, /**< SCIP data structure */
1703 SCIP_ROW** row, /**< buffer to store pointer to new row */
1704 SCIP_ROWPREP* rowprep, /**< rowprep to be turned into a row */
1705 SCIP_SEPA* sepa /**< separator */
1706 )
1707{
1708 assert(scip != NULL);
1709 assert(row != NULL);
1710 assert(rowprep != NULL);
1711
1712 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, rowprep->name,
1713 rowprep->sidetype == SCIP_SIDETYPE_LEFT ? rowprep->side : -SCIPinfinity(scip),
1714 rowprep->sidetype == SCIP_SIDETYPE_RIGHT ? rowprep->side : SCIPinfinity(scip),
1715 rowprep->local && (SCIPgetDepth(scip) > 0), FALSE, TRUE) );
1716
1717 SCIP_CALL( SCIPaddVarsToRow(scip, *row, rowprep->nvars, rowprep->vars, rowprep->coefs) );
1718
1719 return SCIP_OKAY;
1720}
#define NULL
Definition: def.h:266
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
#define SCIPduplicateBlockMemory(scip, ptr, source)
Definition: scip_mem.h:103
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_RETCODE SCIPcreateEmptyRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1391
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1453
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Real SCIPgetSepaMinEfficacy(SCIP *scip)
Definition: scip_sepa.c:339
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17537
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18143
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18087
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18133
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18077
SCIP_VAR ** SCIProwprepGetVars(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:639
void SCIProwprepReset(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:719
SCIP_RETCODE SCIPcleanupRowprep2(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real maxcoefbound, SCIP_Bool *success)
SCIP_Real SCIProwprepGetSide(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:659
SCIP_RETCODE SCIPensureRowprepSize(SCIP *scip, SCIP_ROWPREP *rowprep, int size)
Definition: misc_rowprep.c:887
void SCIPmergeRowprepTerms(SCIP *scip, SCIP_ROWPREP *rowprep)
int SCIProwprepGetNModifiedVars(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:699
SCIP_Real SCIPgetRowprepViolation(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Bool *reliable)
Definition: misc_rowprep.c:972
void SCIProwprepSetCoef(SCIP_ROWPREP *rowprep, int idx, SCIP_Real newcoef)
Definition: misc_rowprep.c:734
SCIP_Real SCIPscaleupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real minscaleup, SCIP_Bool *success)
SCIP_Real * SCIProwprepGetCoefs(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:649
SCIP_VAR ** SCIProwprepGetModifiedVars(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:709
char * SCIProwprepGetName(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:689
void SCIProwprepSetSidetype(SCIP_ROWPREP *rowprep, SCIP_SIDETYPE sidetype)
Definition: misc_rowprep.c:769
SCIP_Bool SCIPisRowprepViolationReliable(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol)
SCIP_Bool SCIProwprepIsLocal(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:679
void SCIPprintRowprepSol(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, FILE *file)
Definition: misc_rowprep.c:826
void SCIProwprepAddConstant(SCIP_ROWPREP *rowprep, SCIP_Real constant)
Definition: misc_rowprep.c:760
SCIP_SIDETYPE SCIProwprepGetSidetype(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:669
SCIP_RETCODE SCIPgetRowprepRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_SEPA *sepa)
SCIP_RETCODE SCIPaddRowprepTerm(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_VAR *var, SCIP_Real coef)
Definition: misc_rowprep.c:913
SCIP_RETCODE SCIPgetRowprepRowCons(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetRowprepRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_CONSHDLR *conshdlr)
SCIP_RETCODE SCIPcreateRowprep(SCIP *scip, SCIP_ROWPREP **rowprep, SCIP_SIDETYPE sidetype, SCIP_Bool local)
Definition: misc_rowprep.c:563
int SCIPscaleRowprep(SCIP_ROWPREP *rowprep, SCIP_Real factor)
int SCIProwprepGetNVars(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:629
void SCIProwprepRecordModifications(SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:791
SCIP_RETCODE SCIPaddRowprepTerms(SCIP *scip, SCIP_ROWPREP *rowprep, int nvars, SCIP_VAR **vars, SCIP_Real *coefs)
Definition: misc_rowprep.c:938
void SCIProwprepSetLocal(SCIP_ROWPREP *rowprep, SCIP_Bool islocal)
Definition: misc_rowprep.c:780
void SCIProwprepAddSide(SCIP_ROWPREP *rowprep, SCIP_Real side)
Definition: misc_rowprep.c:746
SCIP_RETCODE SCIPcopyRowprep(SCIP *scip, SCIP_ROWPREP **target, SCIP_ROWPREP *source)
Definition: misc_rowprep.c:599
SCIP_RETCODE SCIPcleanupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real minviol, SCIP_Real *viol, SCIP_Bool *success)
void SCIPfreeRowprep(SCIP *scip, SCIP_ROWPREP **rowprep)
Definition: misc_rowprep.c:583
void SCIPprintRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, FILE *file)
Definition: misc_rowprep.c:801
void SCIPsortDownRealRealPtr(SCIP_Real *realarray1, SCIP_Real *realarray2, void **ptrarray, int len)
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define ROWPREP_SCALEUP_MAXSIDE
Definition: misc_rowprep.c:54
#define ROWPREP_SCALEUP_MAXMAXCOEF
Definition: misc_rowprep.c:53
#define ROWPREP_SCALEDOWN_MINMAXCOEF
Definition: misc_rowprep.c:55
static SCIP_RETCODE rowprepCleanupIntegralCoefs(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real *viol)
Definition: misc_rowprep.c:421
#define M_SQRT2
Definition: misc_rowprep.c:59
#define ROWPREP_SCALEUP_MAXMINCOEF
Definition: misc_rowprep.c:52
static SCIP_RETCODE rowprepCleanupImproveCoefrange(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real maxcoefrange)
Definition: misc_rowprep.c:158
static void rowprepCleanupSide(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real *viol)
Definition: misc_rowprep.c:514
#define ROWPREP_SCALEUP_VIOLNONZERO
Definition: misc_rowprep.c:50
static SCIP_RETCODE rowprepCleanupSortTerms(SCIP *scip, SCIP_ROWPREP *rowprep)
Definition: misc_rowprep.c:99
#define ROWPREP_SCALEDOWN_MINCOEF
Definition: misc_rowprep.c:56
static SCIP_RETCODE rowprepRecordModifiedVar(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_VAR *var)
Definition: misc_rowprep.c:64
static void rowprepCleanupScaleup(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real *viol, SCIP_Real minviol)
Definition: misc_rowprep.c:326
static void rowprepCleanupScaledown(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real *viol, SCIP_Real minviol)
Definition: misc_rowprep.c:376
#define ROWPREP_SCALEUP_MINVIOLFACTOR
Definition: misc_rowprep.c:51
public methods for message output
preparation of a linear inequality to become a SCIP_ROW
methods for sorting joint arrays of various types
public methods for problem variables
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for separator plugins
public methods for solutions
public methods for the branch-and-bound tree
SCIP_Real SCIPsetGetSepaMaxCoefRatioRowprep(SCIP_SET *set)
Definition: set.c:5931
internal methods for global SCIP settings
SCIP_Real side
Definition: struct_misc.h:292
SCIP_Bool modifiedside
Definition: struct_misc.h:301
SCIP_VAR ** modifiedvars
Definition: struct_misc.h:298
SCIP_VAR ** vars
Definition: struct_misc.h:288
char name[SCIP_MAXSTRLEN]
Definition: struct_misc.h:295
SCIP_Real * coefs
Definition: struct_misc.h:289
SCIP_Bool local
Definition: struct_misc.h:294
SCIP_Bool recordmodifications
Definition: struct_misc.h:297
int modifiedvarssize
Definition: struct_misc.h:300
SCIP_SIDETYPE sidetype
Definition: struct_misc.h:293
miscellaneous datastructures
SCIP main data structure.
@ SCIP_SIDETYPE_RIGHT
Definition: type_lp.h:65
@ SCIP_SIDETYPE_LEFT
Definition: type_lp.h:64
enum SCIP_SideType SCIP_SIDETYPE
Definition: type_lp.h:67
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:50