SCIP Doxygen Documentation
Loading...
Searching...
No Matches
nlhdlr_default.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-2026 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 nlhdlr_default.c
26 * @ingroup DEFPLUGINS_NLHDLR
27 * @brief default nonlinear handler that calls expression handler methods
28 * @author Stefan Vigerske
29 */
30
31#include "scip/nlhdlr_default.h"
32#include "scip/pub_nlhdlr.h"
33#include "scip/cons_nonlinear.h"
34
35/* fundamental nonlinear handler properties */
36#define NLHDLR_NAME "default"
37#define NLHDLR_DESC "default handler for expressions"
38#define NLHDLR_DETECTPRIORITY 0
39#define NLHDLR_ENFOPRIORITY 0
40
41/** translate from one value of infinity to another
42 *
43 * if val is ≥ infty1, then give infty2, else give val
44 */
45#define infty2infty(infty1, infty2, val) ((val) >= (infty1) ? (infty2) : (val))
46
47#define UNDERESTIMATEUSESACTIVITY 0x1u /**< whether underestimation uses activity */
48#define OVERESTIMATEUSESACTIVITY 0x2u /**< whether overestimation uses activity */
49
50/*lint -e666*/
51/*lint -e850*/
52
53/** evaluates an expression w.r.t. the values in the auxiliary variables */
54static
56 SCIP* scip, /**< SCIP data structure */
57 SCIP_EXPR* expr, /**< expression to be evaluated */
58 SCIP_Real* val, /**< buffer to store value of expression */
59 SCIP_SOL* sol /**< solution to be evaluated */
60 )
61{
62 SCIP_Real* childvals;
63 SCIP_VAR* childvar;
64 int c;
65
66 assert(scip != NULL);
67 assert(expr != NULL);
68 assert(val != NULL);
70
72
73 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
74 {
76 /* there should be an auxiliary variable, because we created them in detect for every child if we said that we will separate;
77 * at the moment, EVALAUX should only be called for nlhdlrs that said they will separate
78 * if that changes, then we should handle this here, e.g., via *val = SCIPexprGetEvalValue(expr); break;
79 */
80 assert(childvar != NULL);
81
82 childvals[c] = SCIPgetSolVal(scip, sol, childvar);
83 }
84
85 SCIP_CALL( SCIPcallExprEval(scip, expr, childvals, val) );
86
87 SCIPfreeBufferArray(scip, &childvals);
88
89 return SCIP_OKAY;
90}
91
92/** check whether expression should be handled by the default nlhdlr
93 *
94 * if no nlhdlr so far provides enforcement or boundtightening for expr, then the default nlhdlr takes over
95 */
96static
97SCIP_DECL_NLHDLRDETECT(nlhdlrDetectDefault)
98{ /*lint --e{715}*/
99 SCIP_EXPRHDLR* exprhdlr;
100 SCIP_Bool estimatebelowusesactivity = FALSE;
101 SCIP_Bool estimateaboveusesactivity = FALSE;
102 int c;
103
104 assert(scip != NULL);
105 assert(nlhdlr != NULL);
106 assert(expr != NULL);
107 assert(enforcing != NULL);
108 assert(participating != NULL);
109 assert(nlhdlrexprdata != NULL);
110
111 exprhdlr = SCIPexprGetHdlr(expr);
112 assert(exprhdlr != NULL);
113
114 if( (*enforcing & SCIP_NLHDLR_METHOD_ACTIVITY) == 0 )
115 {
116 /* expr handlers having reverseprop but no inteval is something that we don't support at the moment for simplicity */
118
119 /* participate in inteval and/or reverseprop if that is not yet provided in enforcing and we have inteval */
120 if( SCIPexprhdlrHasIntEval(exprhdlr) )
121 *participating = SCIP_NLHDLR_METHOD_ACTIVITY;
122 }
123
124 /* participate in sepa if exprhdlr for expr has an estimate callback and sepa below or above is still missing */
126 {
127 /* communicate back that the nlhdlr will provide the separation on the currently missing sides */
128 if( (*enforcing & SCIP_NLHDLR_METHOD_SEPABELOW) == 0 )
129 *participating |= SCIP_NLHDLR_METHOD_SEPABELOW;
130
131 if( (*enforcing & SCIP_NLHDLR_METHOD_SEPAABOVE) == 0 )
132 *participating |= SCIP_NLHDLR_METHOD_SEPAABOVE;
133 }
134
135 if( !*participating )
136 return SCIP_OKAY;
137
138 /* since this is the default handler, we enforce where we participate */
139 *enforcing |= *participating;
140
141 /* increment activity usage counter and create auxiliary variables if necessary
142 * if separating, first guess whether we will use activities in estimate (distinguish under- and overestimation)
143 * we assume that the exprhdlr will use activity on all children iff we are estimating on a nonconvex side
144 * TODO it would be better to request this information directly from the exprhdlr than inferring it from curvature,
145 * but with the currently available exprhdlr that wouldn't make a difference
146 */
147 if( *participating & SCIP_NLHDLR_METHOD_SEPABOTH )
148 {
149 SCIP_EXPRCURV* childcurv;
150
151 /* allocate memory to store the required curvature of the children (though we don't use it) */
153
154 if( *participating & SCIP_NLHDLR_METHOD_SEPABELOW )
155 {
156 /* check whether the expression is convex */
157 SCIP_Bool isconvex;
158 SCIP_CALL( SCIPcallExprCurvature(scip, expr, SCIP_EXPRCURV_CONVEX, &isconvex, childcurv) );
159 estimatebelowusesactivity = !isconvex;
160 }
161
162 if( *participating & SCIP_NLHDLR_METHOD_SEPAABOVE )
163 {
164 /* check whether the expression is concave */
165 SCIP_Bool isconcave;
166 SCIP_CALL( SCIPcallExprCurvature(scip, expr, SCIP_EXPRCURV_CONCAVE, &isconcave, childcurv) );
167 estimateaboveusesactivity = !isconcave;
168 }
169
170 /* free memory */
171 SCIPfreeBufferArray(scip, &childcurv);
172 }
173
174 /* indicate enforcement methods required in children:
175 * - if separating, make sure that (auxiliary) variable will exist
176 * - if activity computation, then register activity usage
177 * - if estimating on a non-convex side, then indicate activity usage for separation for that side
178 */
179 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
180 {
181 /* todo skip auxvarusage for value-expressions? would then need update in evalExprInAux, too */
183 *participating & SCIP_NLHDLR_METHOD_SEPABOTH,
184 *participating & SCIP_NLHDLR_METHOD_ACTIVITY, estimatebelowusesactivity, estimateaboveusesactivity) );
185 }
186
187 /* remember estimatebelowusesactivity and estimateaboveusesactivity in nlhdlrexprdata */
188 *nlhdlrexprdata = (SCIP_NLHDLREXPRDATA*)(size_t)((estimatebelowusesactivity ? UNDERESTIMATEUSESACTIVITY : 0x0u)
189 | (estimateaboveusesactivity ? OVERESTIMATEUSESACTIVITY : 0x0u));
190
191 return SCIP_OKAY;
192}
193
194/** evaluate expression w.r.t. values of auxiliary variables in children */
195static
196SCIP_DECL_NLHDLREVALAUX(nlhdlrEvalAuxDefault)
197{ /*lint --e{715}*/
198 assert(expr != NULL);
199 assert(auxvalue != NULL);
200
201 SCIP_CALL( evalExprInAux(scip, expr, auxvalue, sol) );
202
203 return SCIP_OKAY;
204}
205
206/** initialize LP relaxation by initial estimators */
207static
208SCIP_DECL_NLHDLRINITSEPA(nlhdlrInitSepaDefault)
209{ /*lint --e{715}*/
210 SCIP_INTERVAL* childrenbounds;
213 SCIP_VAR* auxvar;
214 SCIP_ROWPREP* rowprep;
215 int nreturned;
216 int i, j;
217
218 assert(scip != NULL);
219 assert(expr != NULL);
220 assert(infeasible != NULL);
221
222 *infeasible = FALSE;
223
225 return SCIP_OKAY;
226
227 SCIPdebug( SCIPinfoMessage(scip, NULL, "initsepa exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
228 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
230
231 /* use global bounds of auxvar as global valid bounds for children
232 * if at root node (thus local=global) and estimate actually uses bounds, then intersect with (local) activity of expression
233 */
234 SCIP_CALL( SCIPallocBufferArray(scip, &childrenbounds, SCIPexprGetNChildren(expr)) );
235 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
236 {
238 assert(auxvar != NULL);
239
240 SCIPintervalSetBounds(&childrenbounds[i],
243
244 if( SCIPgetDepth(scip) == 0 &&
245 ((underestimate && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY)) ||
246 (overestimate && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY ))) )
247 {
249 SCIPintervalIntersect(&childrenbounds[i], childrenbounds[i], SCIPexprGetActivity(SCIPexprGetChildren(expr)[i]));
250 }
251
252 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childrenbounds[i]) )
253 {
254 SCIPdebugMsg(scip, "activity for expression %d (unexpectedly) empty in initsepa\n", i);
255 *infeasible = TRUE;
256 SCIPfreeBufferArray(scip, &childrenbounds);
257 return SCIP_OKAY;
258 }
259 }
260
261 /* allocate each coefficients array */
262 for( i = 0; i < SCIP_EXPR_MAXINITESTIMATES; ++i )
263 {
265 }
266
267 /* create rowprep */
270
271 /* call the separation initialization callback of the expression handler and turn estimates into SCIP rows */
272 for( i = 0; i < 2 && !*infeasible; ++i )
273 {
274 nreturned = 0;
275 if( i == 0 && underestimate )
276 {
277 SCIP_CALL( SCIPcallExprInitestimates(scip, expr, childrenbounds, FALSE, coefs, constant, &nreturned) );
279 }
280 if( i == 1 && overestimate )
281 {
282 SCIP_CALL( SCIPcallExprInitestimates(scip, expr, childrenbounds, TRUE, coefs, constant, &nreturned) );
284 }
285
286 for( j = 0; j < nreturned && !*infeasible; ++j )
287 {
288 SCIP_Bool success;
289 int v;
290
291 SCIProwprepReset(rowprep);
292
293 for( v = 0; v < SCIPexprGetNChildren(expr); ++v )
294 {
296 }
298 SCIProwprepAddConstant(rowprep, constant[j]); /*lint !e644*/
299
300 /* special treatment for sums to get equality rows */
301 if( j == 0 && SCIPisExprSum(scip, expr) )
302 {
303 SCIP_Real scalefactor;
304 SCIP_ROW* row;
305
306 /* improve numerics by scaling only (does not relax inequality) */
307 scalefactor = SCIPscaleupRowprep(scip, rowprep, 1.0, &success);
308 if( success && scalefactor == 1.0 && underestimate && overestimate )
309 {
310 /* if the rowprep didn't have to be changed, then turn it into a row, change this to an equality, and add it to the LP */
311 /* TODO do this also if not actually needing both under- and overestimator (should still be valid, but also stronger?) */
312 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "initestimate_sum%d", j);
313
314 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
315
316 /* since we did not relax the estimator, we can turn the row into an equality */
318 {
320 }
321 else
322 {
324 }
325 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
326
327 SCIPdebug( SCIPinfoMessage(scip, NULL, " added %scut ", *infeasible ? "infeasible " : "") );
329
330 SCIP_CALL( SCIPreleaseRow(scip, &row) );
331
332 i = 2; /* to break outside loop on i, too */
333 break;
334 }
335 }
336
337 /* straighten out numerics */
339
340 /* if cleanup removed all but one variable, then the cut is essentially a bound; we can skip this and rely on boundtightening */
341 if( success && SCIProwprepGetNVars(rowprep) > 1 )
342 {
343 /* add the cut */
344 SCIP_ROW* row;
345
346 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "init%sestimate%d_%s",
347 i == 0 ? "under" : "over", j, SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)));
348
349 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
350 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
351
352 SCIPdebug( SCIPinfoMessage(scip, NULL, " added %scut ", *infeasible ? "infeasible " : "") );
354
355 SCIP_CALL( SCIPreleaseRow(scip, &row) );
356 }
357 }
358 }
359
360 SCIPfreeRowprep(scip, &rowprep);
361
362 for( i = SCIP_EXPR_MAXINITESTIMATES-1; i >= 0; --i )
363 {
364 SCIPfreeBufferArray(scip, &coefs[i]);
365 }
366
367 SCIPfreeBufferArray(scip, &childrenbounds);
368
369 return SCIP_OKAY;
370}
371
372/** compute linear estimator */
373static
374SCIP_DECL_NLHDLRESTIMATE(nlhdlrEstimateDefault)
375{ /*lint --e{715}*/
376 SCIP_Real constant;
377 SCIP_Bool local;
378 SCIP_Bool* branchcand = NULL;
379 int nchildren;
380 int c;
381 SCIP_INTERVAL* localbounds;
382 SCIP_INTERVAL* globalbounds;
383 SCIP_Real* refpoint;
384 SCIP_ROWPREP* rowprep;
385 SCIP_VAR* auxvar;
386
387 assert(scip != NULL);
388 assert(expr != NULL);
389 assert(rowpreps != NULL);
390 assert(success != NULL);
391
392 *addedbranchscores = FALSE;
393
394 nchildren = SCIPexprGetNChildren(expr);
395
396 SCIP_CALL( SCIPallocBufferArray(scip, &localbounds, nchildren) );
397 SCIP_CALL( SCIPallocBufferArray(scip, &globalbounds, nchildren) );
398 SCIP_CALL( SCIPallocBufferArray(scip, &refpoint, nchildren) );
399 /* we need to pass a branchcand array to exprhdlr's estimate also if not asked to add branching scores */
400 SCIP_CALL( SCIPallocBufferArray(scip, &branchcand, nchildren) );
401
402 SCIPdebug( SCIPinfoMessage(scip, NULL, "estimate exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
403 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
405
406 for( c = 0; c < nchildren; ++c )
407 {
409 assert(auxvar != NULL);
410
411 SCIPintervalSetBounds(&localbounds[c],
414
415 if( ((size_t)nlhdlrexprdata & (overestimate ? OVERESTIMATEUSESACTIVITY : UNDERESTIMATEUSESACTIVITY)) )
416 {
417 /* if expr estimate uses bounds, then intersect the auxvar bounds with the current activity, in case the latter is a bit tighter */
420
421 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, localbounds[c]) )
422 {
423 *success = FALSE;
424 goto TERMINATE;
425 }
426 }
427 else
428 {
429 /* if we think that expr estimate wouldn't use bounds, then just set something valid */
430 }
431
432 SCIPintervalSetBounds(&globalbounds[c],
435
436 refpoint[c] = SCIPgetSolVal(scip, sol, auxvar);
437
438 branchcand[c] = TRUE;
439 }
440
442
443 /* make sure enough space is available in rowprep arrays */
444 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nchildren) );
445
446 /* call the estimation callback of the expression handler */
447 SCIP_CALL( SCIPcallExprEstimate(scip, expr, localbounds, globalbounds, refpoint, overestimate, targetvalue,
448 SCIProwprepGetCoefs(rowprep), &constant, &local, success, branchcand) );
449
450 if( *success )
451 {
452 int i;
453
454 SCIProwprepSetLocal(rowprep, local);
455
456 /* add variables to rowprep (coefs were already added by SCIPexprhdlrEstimateExpr) */
457 for( i = 0; i < nchildren; ++i )
458 {
460 SCIProwprepGetCoefs(rowprep)[i]) );
461 }
462
463 SCIProwprepAddConstant(rowprep, constant);
464
465 SCIPdebug( SCIPinfoMessage(scip, NULL, " found rowprep ") );
467
468 SCIP_CALL( SCIPsetPtrarrayVal(scip, rowpreps, 0, rowprep) );
469
470 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "%sestimate_%s%p_%s%" SCIP_LONGINT_FORMAT,
471 overestimate ? "over" : "under",
473 (void*)expr,
474 sol != NULL ? "sol" : "lp",
476 }
477 else
478 {
479 SCIPfreeRowprep(scip, &rowprep);
480 }
481
482 if( addbranchscores )
483 {
484 SCIP_Real violation;
485
486#ifndef BRSCORE_ABSVIOL
487 SCIP_CALL( SCIPgetExprRelAuxViolationNonlinear(scip, expr, auxvalue, sol, &violation, NULL, NULL) );
488#else
489 SCIP_CALL( SCIPgetExprAbsAuxViolationNonlinear(scip, expr, auxvalue, sol, &violation, NULL, NULL) );
490#endif
491 assert(violation > 0.0); /* there should be a violation if we were called to enforce */
492
493 if( nchildren == 1 )
494 {
495 if( branchcand[0] )
496 {
497 SCIP_CALL( SCIPaddExprsViolScoreNonlinear(scip, SCIPexprGetChildren(expr), 1, violation, sol, addedbranchscores) );
498 }
499 }
500 else
501 {
502 SCIP_EXPR** exprs;
503 int nexprs = 0;
504
505 /* get list of those children that have the branchcand-flag set */
506 SCIP_CALL( SCIPallocBufferArray(scip, &exprs, nchildren) );
507
508 for( c = 0; c < nchildren; ++c )
509 if( branchcand[c] )
510 exprs[nexprs++] = SCIPexprGetChildren(expr)[c];
511
512 SCIP_CALL( SCIPaddExprsViolScoreNonlinear(scip, exprs, nexprs, violation, sol, addedbranchscores) );
513
514 SCIPfreeBufferArray(scip, &exprs);
515 }
516
517 if( *addedbranchscores )
518 {
519 /* count this branchscore as belonging to the exprhdlr, too
520 * thus, it will be counted for the default nlhdlr, but also for this exprhdlr
521 */
523 }
524 }
525
526TERMINATE:
527 SCIPfreeBufferArray(scip, &branchcand);
528 SCIPfreeBufferArray(scip, &refpoint);
529 SCIPfreeBufferArray(scip, &globalbounds);
530 SCIPfreeBufferArray(scip, &localbounds);
531
532 return SCIP_OKAY;
533}
534
535/** solution linearization callback */
536static
537SCIP_DECL_NLHDLRSOLLINEARIZE(nlhdlrSollinearizeDefault)
538{ /*lint --e{715}*/
539 SCIP_Real constant;
540 SCIP_Bool local;
541 SCIP_Bool* branchcand = NULL;
542 int nchildren;
543 int c;
544 int rnd;
545 SCIP_INTERVAL* bounds;
546 SCIP_Real* refpoint;
547 SCIP_VAR* auxvar;
548
549 assert(scip != NULL);
550 assert(expr != NULL);
551
552 SCIPdebug( SCIPinfoMessage(scip, NULL, "sollinearize exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
553 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
555
556 nchildren = SCIPexprGetNChildren(expr);
557
558 if( !overestimate && !underestimate )
559 return SCIP_OKAY;
560
561 /* skip on sum, as the estimator doesn't depend on the reference point (expr is linear in auxvars) */
562 if( SCIPisExprSum(scip, expr) )
563 return SCIP_OKAY;
564
565 /* if expr estimate would use bounds, then the function is very likely not convex (w.r.t. global bounds), so skip */
566 if( (overestimate && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY)) &&
567 (underestimate && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY)) )
568 return SCIP_OKAY;
569
570 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nchildren) );
571 SCIP_CALL( SCIPallocBufferArray(scip, &refpoint, nchildren) );
572 /* we need to pass a branchcand array to exprhdlr's estimate also if not asked to add branching scores */
573 SCIP_CALL( SCIPallocBufferArray(scip, &branchcand, nchildren) );
574
575 for( c = 0; c < nchildren; ++c )
576 {
578 assert(auxvar != NULL);
579
580 SCIPintervalSetBounds(&bounds[c],
583
584 refpoint[c] = SCIPgetSolVal(scip, sol, auxvar);
585 }
586
587 for( rnd = (overestimate ? 0 : 1); rnd < (underestimate ? 2 : 1); ++rnd ) /* rnd == 0: overestimate, rnd == 1: underestimate */
588 {
589 SCIP_ROWPREP* rowprep;
590 SCIP_Bool success = FALSE;
591
592 if( rnd == 0 && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY) )
593 continue;
594 if( rnd == 1 && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY) )
595 continue;
596
598
599 /* make sure enough space is available in rowprep arrays */
600 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nchildren + 1) );
601
602 for( c = 0; c < nchildren; ++c )
603 branchcand[c] = TRUE;
604
605 /* call the estimation callback of the expression handler
606 * since we pass the global bounds as local bounds, too, we can ignore whether resulting estimator is marked as local
607 */
608 SCIP_CALL( SCIPcallExprEstimate(scip, expr, bounds, bounds, refpoint, rnd == 0,
609 rnd == 0 ? SCIPinfinity(scip) : -SCIPinfinity(scip),
610 SCIProwprepGetCoefs(rowprep), &constant, &local, &success, branchcand) );
611
612 if( success )
613 {
614 int i;
615
616 /* add variables to rowprep (coefs were already added by SCIPexprhdlrEstimateExpr) */
617 for( i = 0; i < nchildren; ++i )
618 {
620 SCIProwprepGetCoefs(rowprep)[i]) );
621 }
622
623 SCIProwprepAddConstant(rowprep, constant);
624
625 SCIPdebug( SCIPinfoMessage(scip, NULL, " found rowprep ") );
627
628 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "%sestimate_%s%p_sol%dnotify",
629 rnd == 0 ? "over" : "under", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), (void*)expr, SCIPsolGetIndex(sol));
630
631 /* complete estimator to cut and clean it up */
633 SCIP_CALL( SCIPcleanupRowprep2(scip, rowprep, sol, SCIPgetHugeValue(scip), &success) );
634 }
635
636 /* if cleanup succeeded and rowprep is still global, add to cutpool */
637 if( success && !SCIProwprepIsLocal(rowprep) )
638 {
639 SCIP_ROW* row;
640
641 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
643 SCIP_CALL( SCIPreleaseRow(scip, &row) );
644 }
645
646 SCIPfreeRowprep(scip, &rowprep);
647 }
648
649 SCIPfreeBufferArray(scip, &branchcand);
650 SCIPfreeBufferArray(scip, &refpoint);
651 SCIPfreeBufferArray(scip, &bounds);
652
653 return SCIP_OKAY;
654}
655
656/** interval-evaluate expression w.r.t. activity of children */
657static
658SCIP_DECL_NLHDLRINTEVAL(nlhdlrIntevalDefault)
659{ /*lint --e{715}*/
660 assert(scip != NULL);
661 assert(expr != NULL);
662
663 /* call the interval evaluation callback of the expression handler */
664 SCIP_CALL( SCIPcallExprInteval(scip, expr, interval, intevalvar, intevalvardata) );
665
666 return SCIP_OKAY;
667}
668
669/** tighten bounds on children from bounds on expression and bounds on children */
670static
671SCIP_DECL_NLHDLRREVERSEPROP(nlhdlrReversepropDefault)
672{ /*lint --e{715}*/
673 SCIP_INTERVAL* childrenbounds;
674 int c;
675
676 assert(scip != NULL);
677 assert(expr != NULL);
678 assert(infeasible != NULL);
679 assert(nreductions != NULL);
680
681 *nreductions = 0;
682
683 SCIP_CALL( SCIPallocBufferArray(scip, &childrenbounds, SCIPexprGetNChildren(expr)) );
684 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
685 childrenbounds[c] = SCIPgetExprBoundsNonlinear(scip, SCIPexprGetChildren(expr)[c]);
686
687 /* call the reverse propagation callback of the expression handler */
688 SCIP_CALL( SCIPcallExprReverseprop(scip, expr, bounds, childrenbounds, infeasible) );
689
690 if( !*infeasible )
691 {
692 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
693 {
695 infeasible, nreductions) );
696 }
698 }
699
700 SCIPfreeBufferArray(scip, &childrenbounds);
701
702 return SCIP_OKAY;
703}
704
705/** nonlinear handler copy callback */
706static
707SCIP_DECL_NLHDLRCOPYHDLR(nlhdlrCopyhdlrDefault)
708{ /*lint --e{715}*/
709 assert(targetscip != NULL);
710 assert(sourcenlhdlr != NULL);
711
713
714 SCIP_CALL( SCIPincludeNlhdlrDefault(targetscip) );
715
716 return SCIP_OKAY;
717}
718
719/** callback to free expression specific data */
720static
721SCIP_DECL_NLHDLRFREEEXPRDATA(nlhdlrFreeExprDataDefault)
722{ /*lint --e{715}*/
723 assert(nlhdlrexprdata != NULL);
724
725 *nlhdlrexprdata = NULL;
726
727 return SCIP_OKAY;
728}
729
730/** includes default nonlinear handler in nonlinear constraint handler */
732 SCIP* scip /**< SCIP data structure */
733 )
734{
735 SCIP_NLHDLR* nlhdlr;
736
737 assert(scip != NULL);
738
740 NLHDLR_ENFOPRIORITY, nlhdlrDetectDefault, nlhdlrEvalAuxDefault, NULL) );
741 assert(nlhdlr != NULL);
742
743 SCIPnlhdlrSetCopyHdlr(nlhdlr, nlhdlrCopyhdlrDefault);
744 SCIPnlhdlrSetFreeExprData(nlhdlr, nlhdlrFreeExprDataDefault);
745 SCIPnlhdlrSetSepa(nlhdlr, nlhdlrInitSepaDefault, NULL, nlhdlrEstimateDefault, NULL);
746 SCIPnlhdlrSetSollinearize(nlhdlr, nlhdlrSollinearizeDefault);
747 SCIPnlhdlrSetProp(nlhdlr, nlhdlrIntevalDefault, nlhdlrReversepropDefault);
748
749 return SCIP_OKAY;
750}
constraint handler for nonlinear constraints specified by algebraic expressions
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_INTERVAL_INFINITY
Definition def.h:189
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPgetExprRelAuxViolationNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Real auxvalue, SCIP_SOL *sol, SCIP_Real *viol, SCIP_Bool *violunder, SCIP_Bool *violover)
SCIP_VAR * SCIPgetExprAuxVarNonlinear(SCIP_EXPR *expr)
SCIP_RETCODE SCIPtightenExprIntervalNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_INTERVAL newbounds, SCIP_Bool *cutoff, int *ntightenings)
SCIP_RETCODE SCIPaddExprsViolScoreNonlinear(SCIP *scip, SCIP_EXPR **exprs, int nexprs, SCIP_Real violscore, SCIP_SOL *sol, SCIP_Bool *success)
SCIP_RETCODE SCIPregisterExprUsageNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool useauxvar, SCIP_Bool useactivityforprop, SCIP_Bool useactivityforsepabelow, SCIP_Bool useactivityforsepaabove)
SCIP_INTERVAL SCIPgetExprBoundsNonlinear(SCIP *scip, SCIP_EXPR *expr)
SCIP_RETCODE SCIPgetExprAbsAuxViolationNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Real auxvalue, SCIP_SOL *sol, SCIP_Real *viol, SCIP_Bool *violunder, SCIP_Bool *violover)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
SCIP_RETCODE SCIPincludeNlhdlrDefault(SCIP *scip)
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:336
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPsetPtrarrayVal(SCIP *scip, SCIP_PTRARRAY *ptrarray, int idx, void *val)
const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:545
void SCIPexprhdlrIncrementNDomainReductions(SCIP_EXPRHDLR *exprhdlr, int nreductions)
Definition expr.c:771
void SCIPexprhdlrIncrementNBranchings(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:817
SCIP_Bool SCIPexprhdlrHasReverseProp(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:675
SCIP_Bool SCIPexprhdlrHasInitEstimates(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:635
SCIP_Bool SCIPexprhdlrHasEstimate(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:625
SCIP_Bool SCIPexprhdlrHasIntEval(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:615
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3872
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1479
SCIP_RETCODE SCIPcallExprEval(SCIP *scip, SCIP_EXPR *expr, SCIP_Real *childrenvalues, SCIP_Real *val)
Definition scip_expr.c:2210
SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
Definition scip_expr.c:1512
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition expr.c:4028
SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1742
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition expr.c:3895
void SCIPintervalIntersectEps(SCIP_INTERVAL *resultant, SCIP_Real eps, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
struct SCIP_Interval SCIP_INTERVAL
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
void SCIPnlhdlrSetFreeExprData(SCIP_NLHDLR *nlhdlr,)
Definition nlhdlr.c:99
const char * SCIPnlhdlrGetName(SCIP_NLHDLR *nlhdlr)
Definition nlhdlr.c:167
void SCIPnlhdlrSetSollinearize(SCIP_NLHDLR *nlhdlr,)
Definition nlhdlr.c:155
void SCIPnlhdlrSetSepa(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRINITSEPA((*initsepa)), SCIP_DECL_NLHDLRENFO((*enfo)), SCIP_DECL_NLHDLRESTIMATE((*estimate)),)
Definition nlhdlr.c:137
void SCIPnlhdlrSetCopyHdlr(SCIP_NLHDLR *nlhdlr,)
Definition nlhdlr.c:77
SCIP_RETCODE SCIPincludeNlhdlrNonlinear(SCIP *scip, SCIP_NLHDLR **nlhdlr, const char *name, const char *desc, int detectpriority, int enfopriority, SCIP_DECL_NLHDLRDETECT((*detect)), SCIP_DECL_NLHDLREVALAUX((*evalaux)), SCIP_NLHDLRDATA *nlhdlrdata)
void SCIPnlhdlrSetProp(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRINTEVAL((*inteval)),)
Definition nlhdlr.c:124
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17696
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1553
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition sol.c:4305
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Longint SCIPgetNLPs(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Real SCIPepsilon(SCIP *scip)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
void SCIProwprepReset(SCIP_ROWPREP *rowprep)
SCIP_RETCODE SCIPcleanupRowprep2(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real maxcoefbound, SCIP_Bool *success)
SCIP_RETCODE SCIPensureRowprepSize(SCIP *scip, SCIP_ROWPREP *rowprep, int size)
SCIP_Real SCIPscaleupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real minscaleup, SCIP_Bool *success)
SCIP_Real * SCIProwprepGetCoefs(SCIP_ROWPREP *rowprep)
char * SCIProwprepGetName(SCIP_ROWPREP *rowprep)
void SCIProwprepSetSidetype(SCIP_ROWPREP *rowprep, SCIP_SIDETYPE sidetype)
SCIP_Bool SCIProwprepIsLocal(SCIP_ROWPREP *rowprep)
void SCIPprintRowprepSol(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, FILE *file)
void SCIProwprepAddConstant(SCIP_ROWPREP *rowprep, SCIP_Real constant)
SCIP_SIDETYPE SCIProwprepGetSidetype(SCIP_ROWPREP *rowprep)
SCIP_RETCODE SCIPaddRowprepTerm(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_VAR *var, SCIP_Real coef)
SCIP_RETCODE SCIPgetRowprepRowCons(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateRowprep(SCIP *scip, SCIP_ROWPREP **rowprep, SCIP_SIDETYPE sidetype, SCIP_Bool local)
int SCIProwprepGetNVars(SCIP_ROWPREP *rowprep)
void SCIProwprepSetLocal(SCIP_ROWPREP *rowprep, SCIP_Bool islocal)
void SCIPfreeRowprep(SCIP *scip, SCIP_ROWPREP **rowprep)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
int c
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
#define NLHDLR_DETECTPRIORITY
#define NLHDLR_ENFOPRIORITY
#define NLHDLR_DESC
#define NLHDLR_NAME
#define OVERESTIMATEUSESACTIVITY
#define UNDERESTIMATEUSESACTIVITY
#define infty2infty(infty1, infty2, val)
static SCIP_RETCODE evalExprInAux(SCIP *scip, SCIP_EXPR *expr, SCIP_Real *val, SCIP_SOL *sol)
default nonlinear handler that calls expression handler methods
#define SCIPdebug(x)
Definition pub_message.h:93
public functions of nonlinear handlers of nonlinear constraints
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
SCIP_EXPRCURV
Definition type_expr.h:61
@ SCIP_EXPRCURV_CONVEX
Definition type_expr.h:63
@ SCIP_EXPRCURV_CONCAVE
Definition type_expr.h:64
#define SCIP_EXPR_MAXINITESTIMATES
Definition type_expr.h:198
struct SCIP_Exprhdlr SCIP_EXPRHDLR
Definition type_expr.h:194
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_SIDETYPE_RIGHT
Definition type_lp.h:66
@ SCIP_SIDETYPE_LEFT
Definition type_lp.h:65
struct SCIP_RowPrep SCIP_ROWPREP
Definition type_misc.h:173
#define SCIP_NLHDLR_METHOD_SEPAABOVE
Definition type_nlhdlr.h:52
#define SCIP_DECL_NLHDLREVALAUX(x)
#define SCIP_DECL_NLHDLRESTIMATE(x)
#define SCIP_NLHDLR_METHOD_SEPABOTH
Definition type_nlhdlr.h:53
#define SCIP_DECL_NLHDLRCOPYHDLR(x)
Definition type_nlhdlr.h:70
#define SCIP_NLHDLR_METHOD_ACTIVITY
Definition type_nlhdlr.h:54
#define SCIP_DECL_NLHDLRSOLLINEARIZE(x)
#define SCIP_DECL_NLHDLRFREEEXPRDATA(x)
Definition type_nlhdlr.h:94
#define SCIP_DECL_NLHDLRDETECT(x)
struct SCIP_Nlhdlr SCIP_NLHDLR
#define SCIP_DECL_NLHDLRINITSEPA(x)
struct SCIP_NlhdlrExprData SCIP_NLHDLREXPRDATA
#define SCIP_DECL_NLHDLRREVERSEPROP(x)
#define SCIP_DECL_NLHDLRINTEVAL(x)
#define SCIP_NLHDLR_METHOD_SEPABELOW
Definition type_nlhdlr.h:51
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166