Scippy

SCIP

Solving Constraint Integer Programs

nlp.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-2025 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 nlp.c
26 * @ingroup OTHER_CFILES
27 * @brief NLP management methods
28 * @author Thorsten Gellermann
29 * @author Stefan Vigerske
30 *
31 * In NLP management, we have to distinguish between the current NLP and the NLPI problem
32 * stored in the NLP solver. All NLP methods affect the current NLP only.
33 * Before solving the current NLP with the NLP solver, the NLP solvers data
34 * has to be updated to the current NLP with a call to SCIPnlpFlush().
35 *
36 * @todo handle linear rows from LP
37 */
38
39/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
40
41
42#include "scip/nlpi.h"
43#include "scip/pub_expr.h"
44#include "scip/expr.h"
45#include "scip/expr_varidx.h"
46#include "scip/clock.h"
47#include "scip/event.h"
48#include "scip/nlp.h"
49#include "scip/primal.h"
50#include "scip/pub_event.h"
51#include "scip/pub_lp.h"
52#include "scip/pub_message.h"
53#include "scip/pub_misc.h"
54#include "scip/pub_misc_sort.h"
55#include "scip/pub_nlp.h"
56#include "scip/pub_var.h"
57#include "scip/set.h"
58#include "scip/sol.h"
59#include "scip/struct_nlp.h"
60/* to get nlp, set, ... in event handling and mapvar2varidx */
61#include "scip/struct_scip.h"
62/* to get value of parameter "nlp/solver" and nlpis array and to get access to set->lp for releasing a variable */
63#include "scip/struct_set.h"
64#include "scip/struct_stat.h"
65#include "scip/var.h"
66#include <string.h>
67
68/* defines */
69
70#define EVENTHDLR_NAME "nlpEventHdlr" /**< name of NLP event handler that catches variable events */
71#define EVENTHDLR_DESC "handles all events necessary for maintaining NLP data" /**< description of NLP event handler */
72#define ADDNAMESTONLPI 0 /**< whether to give variable and row names to NLPI */
73
74/*lint -e440*/
75/*lint -e441*/
76/*lint -e777*/
77
78#ifdef __cplusplus
79extern "C" {
80#endif
81
82/* avoid inclusion of scip.h */ /*lint -e{2701}*/
84 SCIP* scip /**< SCIP data structure */
85 );
86
87#ifdef __cplusplus
88}
89#endif
90
91/*
92 * forward declarations
93 */
94
95/** NLP event handler execution method */
96static
97SCIP_DECL_EVENTEXEC( eventExecNlp );
98
99/** announces, that a row of the NLP was modified
100 *
101 * adjusts status of current solution;
102 * calling method has to ensure that change is passed on to the NLPI!
103 */
104static
106 SCIP_NLP* nlp, /**< current NLP data */
107 SCIP_SET* set, /**< global SCIP settings */
108 SCIP_STAT* stat, /**< problem statistics data */
109 SCIP_NLROW* nlrow /**< nonlinear row which was changed */
110 );
111
112/*
113 * private NLP nonlinear row methods
114 */
115
116/** announces, that the given linear coefficient in the constraint matrix changed */
117static
119 SCIP_NLROW* nlrow, /**< nonlinear row */
120 SCIP_SET* set, /**< global SCIP settings */
121 SCIP_STAT* stat, /**< problem statistics data */
122 SCIP_VAR* var, /**< variable which coefficient changed */
123 SCIP_Real coef, /**< new coefficient of variable, 0.0 if deleted */
124 SCIP_NLP* nlp /**< current NLP data */
125 )
126{
127 assert(nlrow != NULL);
128 assert(var != NULL);
129
130 nlrow->activity = SCIP_INVALID;
131 nlrow->validactivitynlp = -1;
133 nlrow->validpsactivitydomchg = -1;
134 nlrow->minactivity = SCIP_INVALID;
135 nlrow->maxactivity = SCIP_INVALID;
136 nlrow->validactivitybdsdomchg = -1;
137
138 if( nlrow->nlpindex >= 0 )
139 {
140 assert(nlp != NULL);
141
142 /* notify NLP that row has changed */
143 SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
144
145 /* update NLPI problem, if row is in NLPI already */
146 if( nlrow->nlpiindex >= 0 )
147 {
148 int idx;
149
150 /* get index of variable in NLPI */
151 assert(SCIPhashmapExists(nlp->varhash, var));
152 idx = SCIPhashmapGetImageInt(nlp->varhash, var);
153 assert(idx >= 0 && idx < nlp->nvars);
154
155 idx = nlp->varmap_nlp2nlpi[idx];
156 assert(idx >= 0 && idx < nlp->nvars_solver);
157
158 /* change coefficient in NLPI problem */
159 SCIP_CALL( SCIPnlpiChgLinearCoefs(set, nlp->solver, nlp->problem, nlrow->nlpiindex, 1, &idx, &coef) );
160 }
161 }
162
163 return SCIP_OKAY;
164}
165
166/** create varidx expression for var expression
167 *
168 * called when expr is duplicated for addition to NLPI
169 */
170static
172{
173 SCIP_NLP* nlp;
174 int nlpidx;
175
176 assert(sourcescip != NULL);
177 assert(sourcescip == targetscip);
178 assert(sourceexpr != NULL);
179 assert(targetexpr != NULL);
180 assert(*targetexpr == NULL);
181 assert(mapexprdata != NULL);
182
183 nlp = (SCIP_NLP*)mapexprdata;
184
185 /* do not provide map if not variable */
186 if( !SCIPexprIsVar(sourcescip->set, sourceexpr) )
187 return SCIP_OKAY;
188
189 assert(SCIPvarIsActive(SCIPgetVarExprVar(sourceexpr))); /* because we simplified exprs */
190
191 assert(SCIPhashmapExists(nlp->varhash, SCIPgetVarExprVar(sourceexpr)));
192 nlpidx = SCIPhashmapGetImageInt(nlp->varhash, SCIPgetVarExprVar(sourceexpr));
193 assert(nlpidx < nlp->nvars);
194
195 assert(nlp->varmap_nlp2nlpi[nlpidx] >= 0);
196 assert(nlp->varmap_nlp2nlpi[nlpidx] < nlp->nvars_solver);
197 SCIP_CALL( SCIPcreateExprVaridx(targetscip, targetexpr, nlp->varmap_nlp2nlpi[nlpidx], ownercreate, ownercreatedata) );
198
199 return SCIP_OKAY;
200}
201
202/** announces, that an expression changed */
203static
205 SCIP_NLROW* nlrow, /**< nonlinear row */
206 BMS_BLKMEM* blkmem, /**< block memory */
207 SCIP_SET* set, /**< global SCIP settings */
208 SCIP_STAT* stat, /**< problem statistics data */
209 SCIP_NLP* nlp /**< current NLP data */
210 )
211{
212 assert(nlrow != NULL);
213
214 nlrow->activity = SCIP_INVALID;
215 nlrow->validactivitynlp = -1;
217 nlrow->validpsactivitydomchg = -1;
218 nlrow->minactivity = SCIP_INVALID;
219 nlrow->maxactivity = SCIP_INVALID;
220 nlrow->validactivitybdsdomchg = -1;
221
222 if( nlrow->nlpindex >= 0 )
223 {
224 assert(nlp != NULL);
225
226 /* notify NLP that row has changed */
227 SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
228
229 if( nlrow->nlpiindex >= 0 )
230 {
231 /* change expression tree in NLPI problem */
232 SCIP_EXPR* nlpiexpr;
233
234 SCIP_CALL( SCIPexprCopy(set, stat, blkmem, set, stat, blkmem, nlrow->expr, &nlpiexpr, mapvar2varidx, (void*)nlp, NULL, NULL) );
235 SCIP_CALL( SCIPnlpiChgExpr(set, nlp->solver, nlp->problem, nlrow->nlpiindex, nlpiexpr) );
236 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &nlpiexpr) );
237 }
238 }
239
240 return SCIP_OKAY;
241}
242
243/** notifies nonlinear row, that its sides were changed */
244static
246 SCIP_NLROW* nlrow, /**< nonlinear row */
247 SCIP_SET* set, /**< global SCIP settings */
248 SCIP_STAT* stat, /**< problem statistics data */
249 SCIP_NLP* nlp /**< current NLP data */
250 )
251{
252 assert(nlrow != NULL);
253
254 if( nlrow->nlpindex >= 0 )
255 {
256 assert(nlp != NULL);
257
258 /* notify NLP that row has changed */
259 SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
260
261 if( nlrow->nlpiindex >= 0 )
262 {
263 SCIP_Real lhs;
264 SCIP_Real rhs;
265
266 /* change sides in NLPI problem */
267 lhs = nlrow->lhs;
268 rhs = nlrow->rhs;
269 if( !SCIPsetIsInfinity(set, -lhs) )
270 lhs -= nlrow->constant;
271 if( !SCIPsetIsInfinity(set, rhs) )
272 rhs -= nlrow->constant;
273
274 SCIP_CALL( SCIPnlpiChgConsSides(set, nlp->solver, nlp->problem, 1, &nlrow->nlpiindex, &lhs, &rhs) );
275 }
276 }
277
278 return SCIP_OKAY;
279}
280
281/** notifies nonlinear row, that its constant was changed */
282static
284 SCIP_NLROW* nlrow, /**< nonlinear row */
285 SCIP_SET* set, /**< global SCIP settings */
286 SCIP_STAT* stat, /**< problem statistics data */
287 SCIP_NLP* nlp /**< current NLP data */
288 )
289{
290 assert(nlrow != NULL);
291
292 nlrow->activity = SCIP_INVALID;
293 nlrow->validactivitynlp = -1;
295 nlrow->validpsactivitydomchg = -1;
296 nlrow->minactivity = SCIP_INVALID;
297 nlrow->maxactivity = SCIP_INVALID;
298 nlrow->validactivitybdsdomchg = -1;
299
300 if( nlrow->nlpindex >= 0 )
301 {
302 assert(nlp != NULL);
303
304 /* notify NLP that row has changed */
305 SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
306
307 if( nlrow->nlpiindex >= 0 )
308 {
309 SCIP_Real lhs;
310 SCIP_Real rhs;
311
312 lhs = nlrow->lhs;
313 rhs = nlrow->rhs;
314 if( !SCIPsetIsInfinity(set, -lhs) )
315 lhs -= nlrow->constant;
316 if( !SCIPsetIsInfinity(set, rhs) )
317 rhs -= nlrow->constant;
318
319 /* change sides in NLPI problem */
320 SCIP_CALL( SCIPnlpiChgConsSides(set, nlp->solver, nlp->problem, 1, &nlrow->nlpiindex, &lhs, &rhs) );
321 }
322 }
323
324 return SCIP_OKAY;
325}
326
327/** increments or decrements count of NLROW in NLP statistics
328 *
329 * Updates count on linear/convex/nonconvex NLP rows w.r.t. given NLROW.
330 */
331static
333 SCIP_NLP* nlp, /**< NLP */
334 SCIP_SET* set, /**< global SCIP settings */
335 SCIP_NLROW* nlrow, /**< nonlinear row */
336 int incr /**< by how much to increment statistic: +1 or -1 */
337 )
338{
339 assert(nlp != NULL);
340 assert(nlrow != NULL);
341 assert(set != NULL);
342 assert(incr == 1 || incr == -1);
343
344 if( nlrow->expr == NULL )
345 {
346 nlp->nnlrowlinear += incr;
347 assert(nlp->nnlrowlinear >= 0);
348 return;
349 }
350
351 if( !SCIPsetIsInfinity(set, -nlrow->lhs) && !SCIPsetIsInfinity(set, nlrow->rhs) )
352 {
353 nlp->nnlrownonlineareq += incr;
354 assert(nlp->nnlrownonlineareq >= 0);
355 return;
356 }
357
358 if( (SCIPsetIsInfinity(set, -nlrow->lhs) && (nlrow->curvature & SCIP_EXPRCURV_CONVEX)) || /* g(x) <= rhs with g(x) convex */
359 (SCIPsetIsInfinity(set, nlrow->rhs) && (nlrow->curvature & SCIP_EXPRCURV_CONCAVE)) ) /* g(x) >= lhs with g(x) concave */
360 {
361 nlp->nnlrowconvexineq += incr;
362 assert(nlp->nnlrowconvexineq >= 0);
363 return;
364 }
365
366 nlp->nnlrownonconvexineq += incr;
367 assert(nlp->nnlrownonconvexineq >= 0);
368}
369
370/** sorts linear part of row entries such that lower variable indices precede higher ones */
371static
373 SCIP_NLROW* nlrow /**< nonlinear row to be sorted */
374 )
375{
376 assert(nlrow != NULL);
377
378 /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
379 if( nlrow->linvarssorted )
380 return;
381
382 /* sort linear coefficients */
383 SCIPsortPtrReal((void**)nlrow->linvars, nlrow->lincoefs, SCIPvarComp, nlrow->nlinvars);
384
385 nlrow->linvarssorted = TRUE;
386}
387
388/** searches linear variable in nonlinear row, returns position in linvars vector or -1 if not found */
389static
391 SCIP_NLROW* nlrow, /**< nonlinear row to be searched in */
392 SCIP_VAR* var /**< variable to be searched for */
393 )
394{
395 int pos;
396
397 assert(nlrow != NULL);
398 assert(var != NULL);
399
400 if( nlrow->nlinvars == 0 )
401 return -1;
402
403 nlrowSortLinear(nlrow);
404 if( !SCIPsortedvecFindPtr((void**)nlrow->linvars, SCIPvarComp, (void*)var, nlrow->nlinvars, &pos) )
405 return -1;
406
407 return pos;
408}
409
410/** moves a coefficient in a nonlinear row to a different place, and updates all corresponding data structures */
411static
413 SCIP_NLROW* nlrow, /**< NLP row */
414 int oldpos, /**< old position of coefficient */
415 int newpos /**< new position of coefficient */
416 )
417{
418 assert(nlrow != NULL);
419 assert(0 <= oldpos && oldpos < nlrow->nlinvars);
420 assert(0 <= newpos && newpos < nlrow->nlinvars);
421 assert(nlrow->linvars[oldpos] != NULL);
422
423 if( oldpos == newpos )
424 return;
425
426 nlrow->linvars[newpos] = nlrow->linvars[oldpos];
427 nlrow->lincoefs[newpos] = nlrow->lincoefs[oldpos];
428
429 /* update sorted flags */
430 nlrow->linvarssorted = FALSE;
431}
432
433/** adds a previously non existing linear coefficient to a nonlinear row */
434static
436 SCIP_NLROW* nlrow, /**< nonlinear row */
437 BMS_BLKMEM* blkmem, /**< block memory */
438 SCIP_SET* set, /**< global SCIP settings */
439 SCIP_STAT* stat, /**< problem statistics data */
440 SCIP_NLP* nlp, /**< current NLP data */
441 SCIP_VAR* var, /**< variable */
442 SCIP_Real coef /**< value of coefficient */
443 )
444{
445 int pos;
446
447 assert(nlrow != NULL);
448 assert(blkmem != NULL);
449 assert(var != NULL);
450 assert(coef != 0.0);
451
452 /* assert that only active variables are added once the row is in the NLP */
453 assert(nlrow->nlpindex == -1 || SCIPvarIsActive(var) );
454
455 SCIP_CALL( SCIPnlrowEnsureLinearSize(nlrow, blkmem, set, nlrow->nlinvars+1) );
456 assert(nlrow->linvars != NULL);
457 assert(nlrow->lincoefs != NULL);
458
459 pos = nlrow->nlinvars;
460 nlrow->nlinvars++;
461
462 /* insert the variable */
463 nlrow->linvars [pos] = var;
464 nlrow->lincoefs[pos] = coef;
465
466 SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, coef, nlp) );
467
468 /* update sorted flag */
469 if( pos > 0 && SCIPvarCompare(nlrow->linvars[pos-1], nlrow->linvars[pos]) > 0 )
470 nlrow->linvarssorted = FALSE;
471
472 SCIPsetDebugMsg(set, "added linear coefficient %g * <%s> at position %d to nonlinear row <%s>\n",
473 coef, SCIPvarGetName(var), pos, nlrow->name);
474
475 return SCIP_OKAY;
476}
477
478#ifdef SCIP_DISABLED_CODE
479/** adds a linear coefficient to a nonlinear row
480 * if the variable exists in the linear part of the row already, the coefficients are added
481 * otherwise the variable is added to the row */
482static
483SCIP_RETCODE nlrowAddToLinearCoef(
484 SCIP_NLROW* nlrow, /**< nonlinear row */
485 BMS_BLKMEM* blkmem, /**< block memory */
486 SCIP_SET* set, /**< global SCIP settings */
487 SCIP_STAT* stat, /**< problem statistics data */
488 SCIP_NLP* nlp, /**< current NLP data */
489 SCIP_VAR* var, /**< variable */
490 SCIP_Real coef, /**< value of coefficient */
491 SCIP_Bool removefixed /**< whether to disaggregate var before adding */
492 )
493{
494 int pos;
495
496 assert(nlrow != NULL);
497 assert(blkmem != NULL);
498 assert(var != NULL);
499
500 if( removefixed && !SCIPvarIsActive(var) )
501 {
502 SCIP_Real constant;
503
504 constant = 0.0;
505 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &coef, &constant) );
506 if( constant != 0.0 )
507 {
508 nlrow->constant += constant;
509 SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
510 }
511
512 if( SCIPsetIsZero(set, coef) )
513 return SCIP_OKAY;
514
515 if( !SCIPvarIsActive(var) )
516 {
517 int j;
518
519 /* if var is still not active, then it is multi-aggregated */
521
522 if( SCIPvarGetMultaggrConstant(var) != 0.0 )
523 {
524 nlrow->constant += coef * SCIPvarGetMultaggrConstant(var);
525 SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
526 }
527
528 for( j = 0; j < SCIPvarGetMultaggrNVars(var); ++j )
529 {
530 SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[j], SCIPvarGetMultaggrScalars(var)[j] * coef, TRUE) );
531 }
532
533 return SCIP_OKAY;
534 }
535 }
536 else if( SCIPsetIsZero(set, coef) )
537 return SCIP_OKAY;
538
539 assert(!removefixed || SCIPvarIsActive(var));
540
541 pos = nlrowSearchLinearCoef(nlrow, var);
542
543 if( pos == -1 )
544 {
545 /* add as new coefficient */
546 SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, coef) );
547 }
548 else
549 {
550 assert(pos >= 0);
551 assert(pos < nlrow->nlinvars);
552 assert(nlrow->linvars[pos] == var);
553
554 /* add to previously existing coefficient */
555 nlrow->lincoefs[pos] += coef;
556 }
557
558 return SCIP_OKAY;
559}
560#endif
561
562/** deletes coefficient at given position from row */
563static
565 SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
566 SCIP_SET* set, /**< global SCIP settings */
567 SCIP_STAT* stat, /**< problem statistics data */
568 SCIP_NLP* nlp, /**< current NLP data */
569 int pos /**< position in row vector to delete */
570 )
571{
572 SCIP_VAR* var;
573
574 assert(nlrow != NULL);
575 assert(set != NULL);
576 assert(0 <= pos && pos < nlrow->nlinvars);
577 assert(nlrow->linvars[pos] != NULL);
578
579 var = nlrow->linvars[pos];
580
581 /* move last coefficient to position of empty slot (should set sorted flag to FALSE, if not last variable was deleted) */
582 nlrowMoveLinearCoef(nlrow, nlrow->nlinvars-1, pos);
583 nlrow->nlinvars--;
584 assert(pos == nlrow->nlinvars || nlrow->linvarssorted == FALSE);
585
586 SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, 0.0, nlp) );
587
588 return SCIP_OKAY;
589}
590
591/** changes a coefficient at given position of a nonlinear row */
592static
594 SCIP_NLROW* nlrow, /**< NLP row */
595 SCIP_SET* set, /**< global SCIP settings */
596 SCIP_STAT* stat, /**< problem statistics data */
597 SCIP_NLP* nlp, /**< current NLP data */
598 int pos, /**< position in row vector to change */
599 SCIP_Real coef /**< new value of coefficient */
600 )
601{
602 assert(nlrow != NULL);
603 assert(0 <= pos && pos < nlrow->nlinvars);
604 assert(nlrow->linvars != NULL);
605 assert(nlrow->linvars[pos] != NULL);
606
607 if( SCIPsetIsZero(set, coef) )
608 {
609 /* delete existing coefficient */
610 SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
611 }
612 else if( !SCIPsetIsEQ(set, nlrow->lincoefs[pos], coef) )
613 {
614 /* change existing coefficient */
615 nlrow->lincoefs[pos] = coef;
616 SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, nlrow->linvars[pos], coef, nlp) );
617 }
618
619 return SCIP_OKAY;
620}
621
622/** calculates minimal and maximal activity of row w.r.t. the variable's bounds */
623static
625 SCIP_NLROW* nlrow, /**< nonlinear row */
626 BMS_BLKMEM* blkmem, /**< block memory */
627 SCIP_SET* set, /**< global SCIP settings */
628 SCIP_STAT* stat /**< problem statistics data */
629 )
630{
631 SCIP_Real inf;
632 SCIP_INTERVAL activity;
633 SCIP_INTERVAL bounds;
634 int i;
635
636 assert(nlrow != NULL);
637 assert(set != NULL);
638 assert(stat != NULL);
639
640 inf = SCIPsetInfinity(set);
641
642 /* calculate activity bounds */
643 SCIPintervalSet(&activity, nlrow->constant);
644 for( i = 0; i < nlrow->nlinvars && !SCIPintervalIsEntire(inf, activity); ++i )
645 {
647 SCIPintervalMulScalar(inf, &bounds, bounds, nlrow->lincoefs[i]);
648 SCIPintervalAdd(inf, &activity, activity, bounds);
649 }
650
651 if( nlrow->expr != NULL && !SCIPintervalIsEntire(inf, activity) )
652 {
653 SCIP_CALL( SCIPexprEvalActivity(set, stat, blkmem, nlrow->expr) );
654 SCIPintervalAdd(inf, &activity, activity, SCIPexprGetActivity(nlrow->expr));
655 }
656
657 nlrow->minactivity = SCIPintervalGetInf(activity);
658 nlrow->maxactivity = SCIPintervalGetSup(activity);
659
660 nlrow->validactivitybdsdomchg = stat->domchgcount;
661
662 return SCIP_OKAY;
663}
664
665/** makes sure that there is no fixed variable at position pos of the linear part of a nonlinear row
666 *
667 * a fixed variable is replaced with the corresponding constant or disaggregated term
668 */
669static
671 SCIP_NLROW* nlrow, /**< nonlinear row */
672 BMS_BLKMEM* blkmem, /**< block memory */
673 SCIP_SET* set, /**< global SCIP settings */
674 SCIP_STAT* stat, /**< problem statistics data */
675 SCIP_NLP* nlp, /**< current NLP data */
676 int pos /**< position of variable in linear variables array */
677 )
678{
679 SCIP_Real oldconstant;
680 SCIP_VAR* var;
681
682 assert(nlrow != NULL);
683 assert(blkmem != NULL);
684 assert(pos >= 0);
685 assert(pos < nlrow->nlinvars);
686
687 var = nlrow->linvars[pos];
688
689 if( SCIPvarIsActive(var) )
690 return SCIP_OKAY;
691
692 oldconstant = nlrow->constant;
693
694 /* replace fixed, aggregated, or negated variable */
695 SCIP_CALL( SCIPvarGetProbvarSum( &nlrow->linvars[pos], set, &nlrow->lincoefs[pos], &nlrow->constant) );
696
697 /* if var had been fixed, entry should be removed from row */
698 if( nlrow->lincoefs[pos] == 0.0 )
699 {
700 nlrowMoveLinearCoef(nlrow, nlrow->nlinvars-1, pos);
701 nlrow->nlinvars--;
702
703 if( pos < nlrow->nlinvars )
704 {
705 SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
706 }
707
708 return SCIP_OKAY;
709 }
710 nlrow->linvarssorted = FALSE;
711
712 /* notify nlrow that coefficient of var is now 0.0 in row */
713 SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, 0.0, nlp) );
714
715 /* notify nlrow that constant of row has changed */
716 if( oldconstant != nlrow->constant )
717 SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
718
719 if( SCIPvarIsActive(nlrow->linvars[pos]) )
720 {
721 /* if var was aggregated or negated, notify nlrow about new coefficient */
722 SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, nlrow->linvars[pos], nlrow->lincoefs[pos], nlp) );
723 }
724 else
725 {
726 SCIP_Real coef;
727 int i;
728
729 /* if not removed or active, the new variable should be multi-aggregated */
730 assert(SCIPvarGetStatus(nlrow->linvars[pos]) == SCIP_VARSTATUS_MULTAGGR);
731
732 var = nlrow->linvars[pos];
733 coef = nlrow->lincoefs[pos];
734
735 /* remove the variable from the row */
736 SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
737
738 /* add multi-aggregated term to row */
739 if( SCIPvarGetMultaggrConstant(var) != 0.0 )
740 {
741 nlrow->constant += coef * SCIPvarGetMultaggrConstant(var);
742 SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
743 }
745 for( i = 0; i < SCIPvarGetMultaggrNVars(var); ++i )
746 {
747 if( SCIPsetIsZero(set, coef * SCIPvarGetMultaggrScalars(var)[i]) )
748 continue;
749 SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[i], coef * SCIPvarGetMultaggrScalars(var)[i]) );
750 assert(SCIPvarGetMultaggrVars(var)[i] == nlrow->linvars[nlrow->nlinvars-1]);
752 {
753 /* if newly added variable is fixed, replace it now */
754 SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, nlrow->nlinvars-1) );
755 }
756 }
757
758 /* due to nlrowDelLinearCoefPos, an inactive variable may have moved to position pos
759 * if that is the case, call ourself recursively
760 */
761 if( pos < nlrow->nlinvars && !SCIPvarIsActive(nlrow->linvars[pos]) )
762 {
763 SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
764 }
765 }
766
767 return SCIP_OKAY;
768}
769
770/** removes fixed variables from the linear part of a nonlinear row */
771static
773 SCIP_NLROW* nlrow, /**< nonlinear row */
774 BMS_BLKMEM* blkmem, /**< block memory */
775 SCIP_SET* set, /**< global SCIP settings */
776 SCIP_STAT* stat, /**< problem statistics data */
777 SCIP_NLP* nlp /**< current NLP data */
778 )
779{
780 int i;
781 int oldlen;
782
783 assert(nlrow != NULL);
784 assert(nlrow->linvars != NULL || nlrow->nlinvars == 0);
785
786 oldlen = nlrow->nlinvars;
787 for( i = 0; i < MIN(oldlen, nlrow->nlinvars); ++i )
788 {
789 assert(nlrow->linvars[i] != NULL);
790 SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, i) );
791 }
792
793 return SCIP_OKAY;
794}
795
796/** removes fixed variables from expression of a nonlinear row */
797static
799 SCIP_NLROW* nlrow, /**< nonlinear row */
800 BMS_BLKMEM* blkmem, /**< block memory */
801 SCIP_SET* set, /**< global SCIP settings */
802 SCIP_STAT* stat, /**< problem statistics data */
803 SCIP_NLP* nlp /**< current NLP data */
804 )
805{
806 SCIP_EXPR* simplified;
807 SCIP_Bool changed;
808 SCIP_Bool infeasible;
809
810 if( nlrow->expr == NULL )
811 return SCIP_OKAY;
812
813 SCIP_CALL( SCIPexprSimplify(set, stat, blkmem, nlrow->expr, &simplified, &changed, &infeasible, NULL, NULL) );
814 assert(!infeasible);
815
816 if( !changed )
817 {
818 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &simplified) );
819 return SCIP_OKAY;
820 }
821
822 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &nlrow->expr) );
823 nlrow->expr = simplified;
824
825 if( SCIPexprIsValue(set, nlrow->expr) )
826 {
827 /* if expression tree is constant, remove it */
828 SCIP_CALL( SCIPnlrowChgConstant(nlrow, set, stat, nlp, nlrow->constant + SCIPgetValueExprValue(nlrow->expr)) );
829
830 /* removing the expression changes statistics on rows in stat, if row is already in NLP
831 * first remove current nlrow from stat, then add again after releasing expression
832 */
833 if( nlrow->nlpindex >= 0 )
834 nlrowAddToStat(nlp, set, nlrow, -1);
835
836 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &nlrow->expr) );
838
839 if( nlrow->nlpindex >= 0 )
840 nlrowAddToStat(nlp, set, nlrow, 1);
841 }
842
843 SCIP_CALL( nlrowExprChanged(nlrow, blkmem, set, stat, nlp) );
844
845 return SCIP_OKAY;
846}
847
848/** removes fixed variable from nonlinear row */
849static
851 SCIP_NLROW* nlrow, /**< nonlinear row */
852 BMS_BLKMEM* blkmem, /**< block memory */
853 SCIP_SET* set, /**< global SCIP settings */
854 SCIP_STAT* stat, /**< problem statistics data */
855 SCIP_NLP* nlp, /**< current NLP data */
856 SCIP_VAR* var /**< variable that had been fixed */
857 )
858{
859 int pos;
860
861 assert(nlrow != NULL);
862 assert(var != NULL);
863 assert(!SCIPvarIsActive(var));
864
865 /* search for variable in linear part and remove if existing */
866 pos = nlrowSearchLinearCoef(nlrow, var);
867 if( pos >= 0 )
868 {
869 SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
870 }
871
872 /* search for variable in nonlinear part and remove all fixed variables in expression if existing
873 * TODO only call simplify if var appears in expr, but currently we don't store the vars in a separate array
874 */
875 if( nlrow->expr != NULL )
876 {
877 SCIP_CALL( nlrowSimplifyExpr(nlrow, blkmem, set, stat, nlp) );
878 }
879
880 return SCIP_OKAY;
881}
882
883/*
884 * public NLP nonlinear row methods
885 */
886/**@addtogroup PublicNLRowMethods
887 *
888 * @{
889 */
890
891/** create a new nonlinear row
892 *
893 * the new row is already captured
894 */
896 SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
897 BMS_BLKMEM* blkmem, /**< block memory */
898 SCIP_SET* set, /**< global SCIP settings */
899 SCIP_STAT* stat, /**< problem statistics data */
900 const char* name, /**< name of nonlinear row */
901 SCIP_Real constant, /**< constant */
902 int nlinvars, /**< number of linear variables */
903 SCIP_VAR** linvars, /**< linear variables, or NULL if nlinvars == 0 */
904 SCIP_Real* lincoefs, /**< linear coefficients, or NULL if nlinvars == 0 */
905 SCIP_EXPR* expr, /**< expression, or NULL */
906 SCIP_Real lhs, /**< left hand side */
907 SCIP_Real rhs, /**< right hand side */
908 SCIP_EXPRCURV curvature /**< curvature of the nonlinear row */
909 )
910{
911#ifndef NDEBUG
912 int i;
913#endif
914
915 assert(nlrow != NULL);
916 assert(blkmem != NULL);
917 assert(set != NULL);
918 assert(name != NULL);
919 assert(!SCIPsetIsInfinity(set, ABS(constant)));
920 assert(nlinvars == 0 || linvars != NULL);
921 assert(nlinvars == 0 || lincoefs != NULL);
922 assert(SCIPsetIsRelLE(set, lhs, rhs));
923
924 SCIP_ALLOC( BMSallocBlockMemory(blkmem, nlrow) );
925
926 /* constant part */
927 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
928 (*nlrow)->constant = constant;
929
930#ifndef NDEBUG
931 for( i = 0; i < nlinvars; ++i )
932 {
933 assert(linvars[i] != NULL);
934 assert(!SCIPsetIsInfinity(set, REALABS(lincoefs[i])));
935 }
936#endif
937
938 /* linear part */
939 (*nlrow)->nlinvars = nlinvars;
940 (*nlrow)->linvarssize = nlinvars;
941 if( nlinvars > 0 )
942 {
943 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->linvars, linvars, nlinvars) );
944 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->lincoefs, lincoefs, nlinvars) );
945 (*nlrow)->linvarssorted = FALSE;
946 }
947 else
948 {
949 (*nlrow)->linvars = NULL;
950 (*nlrow)->lincoefs = NULL;
951 (*nlrow)->linvarssorted = TRUE;
952 }
953
954 /* nonlinear part */
955 if( expr != NULL )
956 {
957 /* TODO preserve common subexpressions, or at least use only one varexpr per var */
958 SCIP_CALL( SCIPexprCopy(set, stat, blkmem, set, stat, blkmem, expr, &(*nlrow)->expr, NULL, NULL, NULL, NULL) );
959 }
960 else
961 {
962 (*nlrow)->expr = NULL;
963 }
964
965 /* left and right hand sides, asserted above that lhs is relatively less equal than rhs */
966 (*nlrow)->lhs = MIN(lhs, rhs);
967 (*nlrow)->rhs = MAX(lhs, rhs);
968
969 /* miscellaneous */
970 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->name, name, strlen(name)+1) );
971 (*nlrow)->activity = SCIP_INVALID;
972 (*nlrow)->validactivitynlp = FALSE;
973 (*nlrow)->pseudoactivity = SCIP_INVALID;
974 (*nlrow)->validpsactivitydomchg = FALSE;
975 (*nlrow)->minactivity = SCIP_INVALID;
976 (*nlrow)->maxactivity = SCIP_INVALID;
977 (*nlrow)->validactivitybdsdomchg = FALSE;
978 (*nlrow)->nlpindex = -1;
979 (*nlrow)->nlpiindex = -1;
980 (*nlrow)->nuses = 0;
981 (*nlrow)->dualsol = 0.0;
982 (*nlrow)->curvature = curvature;
983
984 /* capture the nonlinear row */
985 SCIPnlrowCapture(*nlrow);
986
987 return SCIP_OKAY;
988}
989
990/** create a nonlinear row that is a copy of a given row
991 *
992 * the new row is already captured
993 */
995 SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
996 BMS_BLKMEM* blkmem, /**< block memory */
997 SCIP_SET* set, /**< global SCIP settings */
998 SCIP_STAT* stat, /**< problem statistics data */
999 SCIP_NLROW* sourcenlrow /**< nonlinear row to copy */
1000 )
1001{
1002 assert(nlrow != NULL);
1003 assert(blkmem != NULL);
1004 assert(set != NULL);
1005 assert(sourcenlrow != NULL);
1006
1007 SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, stat, sourcenlrow->name,
1008 sourcenlrow->constant,
1009 sourcenlrow->nlinvars, sourcenlrow->linvars, sourcenlrow->lincoefs,
1010 sourcenlrow->expr,
1011 sourcenlrow->lhs, sourcenlrow->rhs, sourcenlrow->curvature) );
1012
1013 (*nlrow)->linvarssorted = sourcenlrow->linvarssorted;
1014 (*nlrow)->activity = sourcenlrow->activity;
1015 (*nlrow)->validactivitynlp = sourcenlrow->validactivitynlp;
1016 (*nlrow)->pseudoactivity = sourcenlrow->pseudoactivity;
1017 (*nlrow)->validpsactivitydomchg = sourcenlrow->validpsactivitydomchg;
1018 (*nlrow)->minactivity = sourcenlrow->minactivity;
1019 (*nlrow)->maxactivity = sourcenlrow->maxactivity;
1020 (*nlrow)->validactivitybdsdomchg = sourcenlrow->validactivitybdsdomchg;
1021
1022 return SCIP_OKAY;
1023}
1024
1025/** create a new nonlinear row from a linear row
1026 *
1027 * the new row is already captured
1028 */
1030 SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
1031 BMS_BLKMEM* blkmem, /**< block memory */
1032 SCIP_SET* set, /**< global SCIP settings */
1033 SCIP_STAT* stat, /**< problem statistics data */
1034 SCIP_ROW* row /**< the linear row to copy */
1035 )
1036{
1037 int rownz;
1038
1039 assert(nlrow != NULL);
1040 assert(blkmem != NULL);
1041 assert(set != NULL);
1042 assert(row != NULL);
1043
1044 rownz = SCIProwGetNNonz(row);
1045
1046 if( rownz > 1 )
1047 {
1048 SCIP_VAR** rowvars;
1049 int i;
1050
1051 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowvars, rownz) );
1052
1053 for( i = 0; i < rownz; ++i )
1054 {
1055 rowvars[i] = SCIPcolGetVar(SCIProwGetCols(row)[i]);
1056 assert(rowvars[i] != NULL);
1057 }
1058
1059 SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, stat, SCIProwGetName(row),
1060 SCIProwGetConstant(row),
1061 rownz, rowvars, SCIProwGetVals(row), NULL,
1062 SCIProwGetLhs(row), SCIProwGetRhs(row),
1064
1065 SCIPsetFreeBufferArray(set, &rowvars);
1066 }
1067 else if( rownz == 1 )
1068 {
1069 SCIP_VAR* rowvar;
1070
1071 rowvar = SCIPcolGetVar(SCIProwGetCols(row)[0]);
1072
1073 SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, stat, SCIProwGetName(row),
1074 SCIProwGetConstant(row),
1075 1, &rowvar, SCIProwGetVals(row), NULL,
1076 SCIProwGetLhs(row), SCIProwGetRhs(row),
1078 }
1079 else
1080 {
1081 SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, stat, SCIProwGetName(row),
1082 SCIProwGetConstant(row),
1083 0, NULL, NULL, NULL,
1084 SCIProwGetLhs(row), SCIProwGetRhs(row),
1086 }
1087
1088 return SCIP_OKAY;
1089}
1090
1091/** output nonlinear row to file stream */
1093 SCIP_NLROW* nlrow, /**< NLP row */
1094 BMS_BLKMEM* blkmem, /**< block memory */
1095 SCIP_SET* set, /**< global SCIP settings */
1096 SCIP_STAT* stat, /**< problem statistics data */
1097 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1098 FILE* file /**< output file (or NULL for standard output) */
1099 )
1100{
1101 int i;
1102
1103 assert(nlrow != NULL);
1104
1105 /* print row name */
1106 if( nlrow->name != NULL && nlrow->name[0] != '\0' )
1107 {
1108 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", nlrow->name);
1109 }
1110
1111 /* print left hand side */
1112 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", nlrow->lhs);
1113
1114 /* print constant */
1115 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g ", nlrow->constant);
1116
1117 /* print linear coefficients */
1118 for( i = 0; i < nlrow->nlinvars; ++i )
1119 {
1120 assert(nlrow->linvars[i] != NULL);
1121 assert(SCIPvarGetName(nlrow->linvars[i]) != NULL);
1122 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", nlrow->lincoefs[i], SCIPvarGetName(nlrow->linvars[i]));
1123 }
1124
1125 /* print nonlinear part */
1126 if( nlrow->expr != NULL )
1127 {
1128 SCIPmessageFPrintInfo(messagehdlr, file, " + ");
1129 SCIP_CALL( SCIPexprPrint(set, stat, blkmem, messagehdlr, file, nlrow->expr) );
1130 }
1131
1132 /* print right hand side */
1133 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g", nlrow->rhs);
1134
1135 /* print convexity */
1136 SCIPmessageFPrintInfo(messagehdlr, file, " [%s]\n", SCIPexprcurvGetName(nlrow->curvature));
1137
1138 return SCIP_OKAY;
1139}
1140
1141/** increases usage counter of nonlinear row */
1143 SCIP_NLROW* nlrow /**< nonlinear row to capture */
1144 )
1145{
1146 assert(nlrow != NULL);
1147 assert(nlrow->nuses >= 0);
1148
1149 SCIPdebugMessage("capture nonlinear row <%s> with nuses=%d\n", nlrow->name, nlrow->nuses);
1150 nlrow->nuses++;
1151}
1152
1153/** decreases usage counter of nonlinear row */
1155 SCIP_NLROW** nlrow, /**< nonlinear row to free */
1156 BMS_BLKMEM* blkmem, /**< block memory */
1157 SCIP_SET* set, /**< global SCIP settings */
1158 SCIP_STAT* stat /**< problem statistics data */
1159 )
1160{
1161 assert(blkmem != NULL);
1162 assert(nlrow != NULL);
1163 assert(*nlrow != NULL);
1164 assert((*nlrow)->nuses >= 1);
1165
1166 SCIPsetDebugMsg(set, "release nonlinear row <%s> with nuses=%d\n", (*nlrow)->name, (*nlrow)->nuses);
1167 (*nlrow)->nuses--;
1168 if( (*nlrow)->nuses > 0 )
1169 {
1170 *nlrow = NULL;
1171 return SCIP_OKAY;
1172 }
1173
1174 /* free row */
1175
1176 assert((*nlrow)->nuses == 0);
1177 assert((*nlrow)->nlpindex == -1);
1178 assert((*nlrow)->nlpiindex == -1);
1179
1180 /* linear part */
1181 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->linvars, (*nlrow)->linvarssize);
1182 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->lincoefs, (*nlrow)->linvarssize);
1183
1184 /* nonlinear part */
1185 if( (*nlrow)->expr != NULL )
1186 {
1187 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &(*nlrow)->expr) );
1188 }
1189
1190 /* miscellaneous */
1191 BMSfreeBlockMemoryArray(blkmem, &(*nlrow)->name, strlen((*nlrow)->name)+1);
1192
1193 BMSfreeBlockMemory(blkmem, nlrow);
1194
1195 return SCIP_OKAY;
1196}
1197
1198/** ensures, that linear coefficient array of nonlinear row can store at least num entries */
1200 SCIP_NLROW* nlrow, /**< NLP row */
1201 BMS_BLKMEM* blkmem, /**< block memory */
1202 SCIP_SET* set, /**< global SCIP settings */
1203 int num /**< minimum number of entries to store */
1204 )
1205{
1206 assert(nlrow != NULL);
1207 assert(nlrow->nlinvars <= nlrow->linvarssize);
1208
1209 if( num > nlrow->linvarssize )
1210 {
1211 int newsize;
1212
1213 newsize = SCIPsetCalcMemGrowSize(set, num);
1214 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->linvars, nlrow->linvarssize, newsize) );
1215 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->lincoefs, nlrow->linvarssize, newsize) );
1216 nlrow->linvarssize = newsize;
1217 }
1218 assert(num <= nlrow->linvarssize);
1219
1220 return SCIP_OKAY;
1221}
1222
1223/** adds a previously non existing linear coefficient to a nonlinear row */
1225 SCIP_NLROW* nlrow, /**< NLP nonlinear row */
1226 BMS_BLKMEM* blkmem, /**< block memory */
1227 SCIP_SET* set, /**< global SCIP settings */
1228 SCIP_STAT* stat, /**< problem statistics data */
1229 SCIP_NLP* nlp, /**< current NLP data */
1230 SCIP_VAR* var, /**< variable */
1231 SCIP_Real val /**< value of coefficient */
1232 )
1233{
1234 /* if row is in NLP already, make sure that only active variables are added */
1235 if( nlrow->nlpindex >= 0 )
1236 {
1237 SCIP_Real constant;
1238
1239 /* get corresponding active or multi-aggregated variable */
1240 constant = 0.0;
1241 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &val, &constant) );
1242
1243 /* add constant */
1244 SCIP_CALL( SCIPnlrowChgConstant(nlrow, set, stat, nlp, nlrow->constant + constant) );
1245
1246 if( val == 0.0 )
1247 /* var has been fixed */
1248 return SCIP_OKAY;
1249
1250 if( !SCIPvarIsActive(var) )
1251 {
1252 /* var should be multi-aggregated, so call this function recursively */
1253 int i;
1254
1256 for( i = 0; i < SCIPvarGetMultaggrNVars(var); ++i )
1257 {
1258 SCIP_CALL( SCIPnlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[i], SCIPvarGetMultaggrScalars(var)[i] * val) );
1259 }
1260 return SCIP_OKAY;
1261 }
1262
1263 /* var is active, so can go on like normal */
1264 }
1265
1266 SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, val) );
1267
1268 return SCIP_OKAY;
1269}
1270
1271/** deletes linear coefficient from nonlinear row */
1273 SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
1274 SCIP_SET* set, /**< global SCIP settings */
1275 SCIP_STAT* stat, /**< problem statistics data */
1276 SCIP_NLP* nlp, /**< current NLP data */
1277 SCIP_VAR* var /**< coefficient to be deleted */
1278 )
1279{
1280 int pos;
1281
1282 assert(nlrow != NULL);
1283 assert(var != NULL);
1284
1285 /* if the row is in the NLP already, we can only have active variables, so var should also be active; in non-debug mode, one gets an error below */
1286 assert(nlrow->nlpindex == -1 || SCIPvarIsActive(var) );
1287
1288 /* search the position of the variable in the row's variable vector */
1289 pos = nlrowSearchLinearCoef(nlrow, var);
1290 if( pos == -1 )
1291 {
1292 SCIPerrorMessage("coefficient for variable <%s> doesn't exist in nonlinear row <%s>\n", SCIPvarGetName(var), nlrow->name);
1293 return SCIP_INVALIDDATA;
1294 }
1295 assert(0 <= pos && pos < nlrow->nlinvars);
1296 assert(nlrow->linvars[pos] == var);
1297
1298 /* delete the variable from the row's variable vector */
1299 SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
1300
1301 return SCIP_OKAY;
1302}
1303
1304/** changes or adds a linear coefficient to a nonlinear row */
1306 SCIP_NLROW* nlrow, /**< nonlinear row */
1307 BMS_BLKMEM* blkmem, /**< block memory */
1308 SCIP_SET* set, /**< global SCIP settings */
1309 SCIP_STAT* stat, /**< problem statistics data */
1310 SCIP_NLP* nlp, /**< current NLP data */
1311 SCIP_VAR* var, /**< variable */
1312 SCIP_Real coef /**< new value of coefficient */
1313 )
1314{
1315 int pos;
1316
1317 assert(nlrow != NULL);
1318 assert(nlp != NULL);
1319 assert(var != NULL);
1320
1321 /* search the position of the variable in the row's linvars vector */
1322 pos = nlrowSearchLinearCoef(nlrow, var);
1323
1324 /* check, if column already exists in the row's linear variables vector */
1325 if( pos == -1 )
1326 {
1327 if( !SCIPsetIsZero(set, coef) )
1328 {
1329 /* add previously not existing coefficient */
1330 SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, coef) );
1331 }
1332 }
1333 else
1334 {
1335 /* change the coefficient in the row */
1336 SCIP_CALL( nlrowChgLinearCoefPos(nlrow, set, stat, nlp, pos, coef) );
1337 }
1338
1339 return SCIP_OKAY;
1340}
1341
1342/** replaces or deletes an expression in a nonlinear row */
1344 SCIP_NLROW* nlrow, /**< nonlinear row */
1345 BMS_BLKMEM* blkmem, /**< block memory */
1346 SCIP_SET* set, /**< global SCIP settings */
1347 SCIP_STAT* stat, /**< problem statistics data */
1348 SCIP_NLP* nlp, /**< current NLP data */
1349 SCIP_EXPR* expr /**< new expression */
1350 )
1351{
1352 assert(nlrow != NULL);
1353 assert(blkmem != NULL);
1354
1355 /* if row in NLP, then remove it from statistics on NLP rows */
1356 if( nlrow->nlpindex >= 0 )
1357 nlrowAddToStat(nlp, set, nlrow, -1);
1358
1359 /* free previous expression tree */
1360 if( nlrow->expr != NULL )
1361 {
1362 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &nlrow->expr) );
1363 assert(nlrow->expr == NULL);
1364 }
1365
1366 /* adds new expression tree */
1367 if( expr != NULL )
1368 {
1369 /* TODO preserve common subexpressions, or at least use only one varexpr per var */
1370 SCIP_CALL( SCIPexprCopy(set, stat, blkmem, set, stat, blkmem, expr, &nlrow->expr, NULL, NULL, NULL, NULL) );
1371
1372 /* if row is already in NLP, ensure that expr has only active variables */
1373 if( nlrow->nlpindex >= 0 )
1374 {
1375 SCIP_EXPR* simplified;
1376 SCIP_Bool changed;
1377 SCIP_Bool infeasible;
1378
1379 SCIP_CALL( SCIPexprSimplify(set, stat, blkmem, nlrow->expr, &simplified, &changed, &infeasible, NULL, NULL) );
1380 assert(!infeasible);
1381
1382 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &nlrow->expr) );
1383 nlrow->expr = simplified;
1384 }
1385 }
1386
1387 /* notify row about the change */
1388 SCIP_CALL( nlrowExprChanged(nlrow, blkmem, set, stat, nlp) );
1389
1390 /* if row in NLP, then add it again to statistics on NLP rows */
1391 if( nlrow->nlpindex >= 0 )
1392 nlrowAddToStat(nlp, set, nlrow, 1);
1393
1394 return SCIP_OKAY;
1395}
1396
1397/** changes constant of nonlinear row */
1399 SCIP_NLROW* nlrow, /**< nonlinear row */
1400 SCIP_SET* set, /**< global SCIP settings */
1401 SCIP_STAT* stat, /**< problem statistics data */
1402 SCIP_NLP* nlp, /**< current NLP data */
1403 SCIP_Real constant /**< new constant */
1404 )
1405{
1406 assert(nlrow != NULL);
1407
1408 if( !SCIPsetIsEQ(set, nlrow->constant, constant) )
1409 {
1410 nlrow->constant = constant;
1411 SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1412 }
1413
1414 return SCIP_OKAY;
1415}
1416
1417/** changes left hand side of nonlinear row */
1419 SCIP_NLROW* nlrow, /**< nonlinear row */
1420 SCIP_SET* set, /**< global SCIP settings */
1421 SCIP_STAT* stat, /**< problem statistics data */
1422 SCIP_NLP* nlp, /**< current NLP data */
1423 SCIP_Real lhs /**< new left hand side */
1424 )
1425{
1426 assert(nlrow != NULL);
1427
1428 if( !SCIPsetIsEQ(set, nlrow->lhs, lhs) )
1429 {
1430 if( nlrow->nlpindex >= 0 )
1431 nlrowAddToStat(nlp, set, nlrow, -1);
1432
1433 nlrow->lhs = lhs;
1434 SCIP_CALL( nlrowSideChanged(nlrow, set, stat, nlp) );
1435
1436 if( nlrow->nlpindex >= 0 )
1437 nlrowAddToStat(nlp, set, nlrow, 1);
1438 }
1439
1440 return SCIP_OKAY;
1441}
1442
1443/** changes right hand side of nonlinear row */
1445 SCIP_NLROW* nlrow, /**< nonlinear row */
1446 SCIP_SET* set, /**< global SCIP settings */
1447 SCIP_STAT* stat, /**< problem statistics data */
1448 SCIP_NLP* nlp, /**< current NLP data */
1449 SCIP_Real rhs /**< new right hand side */
1450 )
1451{
1452 assert(nlrow != NULL);
1453
1454 if( !SCIPsetIsEQ(set, nlrow->rhs, rhs) )
1455 {
1456 if( nlrow->nlpindex >= 0 )
1457 nlrowAddToStat(nlp, set, nlrow, -1);
1458
1459 nlrow->rhs = rhs;
1460 SCIP_CALL( nlrowSideChanged(nlrow, set, stat, nlp) );
1461
1462 if( nlrow->nlpindex >= 0 )
1463 nlrowAddToStat(nlp, set, nlrow, 1);
1464 }
1465
1466 return SCIP_OKAY;
1467}
1468
1469/** sets the curvature of a nonlinear row */
1471 SCIP_NLP* nlp, /**< NLP */
1472 SCIP_SET* set, /**< global SCIP settings */
1473 SCIP_NLROW* nlrow, /**< NLP row */
1474 SCIP_EXPRCURV curvature /**< curvature of NLP row */
1475 )
1476{
1477 assert(nlrow != NULL);
1478
1479 if( nlrow->nlpindex >= 0 )
1480 nlrowAddToStat(nlp, set, nlrow, -1);
1481
1482 nlrow->curvature = curvature;
1483
1484 if( nlrow->nlpindex >= 0 )
1485 nlrowAddToStat(nlp, set, nlrow, 1);
1486}
1487
1488/** removes (or substitutes) all fixed, negated, aggregated, multi-aggregated variables from the linear and nonlinear part of a nonlinear row and simplifies its expression */
1490 SCIP_NLROW* nlrow, /**< nonlinear row */
1491 BMS_BLKMEM* blkmem, /**< block memory */
1492 SCIP_SET* set, /**< global SCIP settings */
1493 SCIP_STAT* stat, /**< problem statistics data */
1494 SCIP_NLP* nlp /**< current NLP data */
1495 )
1496{
1497 SCIP_CALL( nlrowRemoveFixedLinearCoefs(nlrow, blkmem, set, stat, nlp) );
1498 SCIP_CALL( nlrowSimplifyExpr(nlrow, blkmem, set, stat, nlp) );
1499
1500 return SCIP_OKAY;
1501}
1502
1503/** recalculates the current activity of a nonlinear row in the current NLP solution */
1505 SCIP_NLROW* nlrow, /**< nonlinear row */
1506 BMS_BLKMEM* blkmem, /**< block memory */
1507 SCIP_SET* set, /**< global SCIP settings */
1508 SCIP_STAT* stat, /**< problem statistics data */
1509 SCIP_PRIMAL* primal, /**< primal data */
1510 SCIP_TREE* tree, /**< branch and bound tree */
1511 SCIP_NLP* nlp /**< current NLP data */
1512 )
1513{
1514 int i;
1515
1516 assert(nlrow != NULL);
1517 assert(stat != NULL);
1518 assert(nlp != NULL);
1519
1521 {
1522 SCIPerrorMessage("do not have NLP solution for computing NLP activity\n");
1523 return SCIP_ERROR;
1524 }
1525
1526 nlrow->activity = nlrow->constant;
1527 for( i = 0; i < nlrow->nlinvars; ++i )
1528 {
1529 assert(nlrow->linvars[i] != NULL);
1530 assert(SCIPvarGetNLPSol(nlrow->linvars[i]) < SCIP_INVALID);
1531
1532 nlrow->activity += nlrow->lincoefs[i] * SCIPvarGetNLPSol(nlrow->linvars[i]);
1533 }
1534
1535 if( nlrow->expr != NULL )
1536 {
1537 SCIP_SOL* sol;
1538
1539 SCIP_CALL( SCIPsolCreateNLPSol(&sol, blkmem, set, stat, primal, tree, nlp, NULL) );
1540
1541 SCIP_CALL( SCIPexprEval(set, stat, blkmem, nlrow->expr, sol, 0L) );
1542 if( SCIPexprGetEvalValue(nlrow->expr) == SCIP_INVALID )
1543 nlrow->activity = SCIP_INVALID;
1544 else
1545 nlrow->activity += SCIPexprGetEvalValue(nlrow->expr);
1546
1547 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
1548 }
1549
1550 nlrow->validactivitynlp = stat->nnlps;
1551
1552 return SCIP_OKAY;
1553}
1554
1555/** gives the activity of a nonlinear row in the current NLP solution */
1557 SCIP_NLROW* nlrow, /**< nonlinear row */
1558 BMS_BLKMEM* blkmem, /**< block memory */
1559 SCIP_SET* set, /**< global SCIP settings */
1560 SCIP_STAT* stat, /**< problem statistics data */
1561 SCIP_PRIMAL* primal, /**< primal data */
1562 SCIP_TREE* tree, /**< branch and bound tree */
1563 SCIP_NLP* nlp, /**< current NLP data */
1564 SCIP_Real* activity /**< buffer to store activity value */
1565 )
1566{
1567 assert(nlrow != NULL);
1568 assert(stat != NULL);
1569 assert(activity != NULL);
1570
1571 assert(nlrow->validactivitynlp <= stat->nnlps);
1572
1573 if( nlrow->validactivitynlp != stat->nnlps )
1574 {
1575 SCIP_CALL( SCIPnlrowRecalcNLPActivity(nlrow, blkmem, set, stat, primal, tree, nlp) );
1576 }
1577 assert(nlrow->validactivitynlp == stat->nnlps);
1578 assert(nlrow->activity < SCIP_INVALID);
1579
1580 *activity = nlrow->activity;
1581
1582 return SCIP_OKAY;
1583}
1584
1585/** gives the feasibility of a nonlinear row in the current NLP solution: negative value means infeasibility */
1587 SCIP_NLROW* nlrow, /**< nonlinear row */
1588 BMS_BLKMEM* blkmem, /**< block memory */
1589 SCIP_SET* set, /**< global SCIP settings */
1590 SCIP_STAT* stat, /**< problem statistics data */
1591 SCIP_PRIMAL* primal, /**< primal data */
1592 SCIP_TREE* tree, /**< branch and bound tree */
1593 SCIP_NLP* nlp, /**< current NLP data */
1594 SCIP_Real* feasibility /**< buffer to store feasibility value */
1595 )
1596{
1597 SCIP_Real activity;
1598
1599 assert(nlrow != NULL);
1600 assert(feasibility != NULL);
1601
1602 SCIP_CALL( SCIPnlrowGetNLPActivity(nlrow, blkmem, set, stat, primal, tree, nlp, &activity) );
1603 *feasibility = MIN(nlrow->rhs - activity, activity - nlrow->lhs);
1604
1605 return SCIP_OKAY;
1606}
1607
1608/** calculates the current pseudo activity of a nonlinear row */
1610 SCIP_NLROW* nlrow, /**< nonlinear row */
1611 BMS_BLKMEM* blkmem, /**< block memory */
1612 SCIP_SET* set, /**< global SCIP settings */
1613 SCIP_STAT* stat, /**< problem statistics data */
1614 SCIP_PROB* prob, /**< SCIP problem */
1615 SCIP_PRIMAL* primal, /**< primal data */
1616 SCIP_TREE* tree, /**< branch and bound tree */
1617 SCIP_LP* lp /**< SCIP LP */
1618 )
1619{
1620 SCIP_Real val1;
1621 int i;
1622
1623 assert(nlrow != NULL);
1624 assert(stat != NULL);
1625
1626 nlrow->pseudoactivity = nlrow->constant;
1627 for( i = 0; i < nlrow->nlinvars; ++i )
1628 {
1629 assert(nlrow->linvars[i] != NULL);
1630
1631 val1 = SCIPvarGetBestBoundLocal(nlrow->linvars[i]);
1632 nlrow->pseudoactivity += nlrow->lincoefs[i] * val1;
1633 }
1634
1635 if( nlrow->expr != NULL )
1636 {
1637 SCIP_SOL* sol;
1638
1639 SCIP_CALL( SCIPsolCreatePseudoSol(&sol, blkmem, set, stat, prob, primal, tree, lp, NULL) );
1640
1641 SCIP_CALL( SCIPexprEval(set, stat, blkmem, nlrow->expr, sol, 0L) );
1642 if( SCIPexprGetEvalValue(nlrow->expr) == SCIP_INVALID )
1644 else
1645 nlrow->pseudoactivity += SCIPexprGetEvalValue(nlrow->expr);
1646
1647 SCIP_CALL( SCIPsolFree(&sol, blkmem, primal) );
1648 }
1649
1650 nlrow->validpsactivitydomchg = stat->domchgcount;
1651
1652 return SCIP_OKAY;
1653}
1654
1655/** returns the pseudo activity of a nonlinear row in the current pseudo solution */
1657 SCIP_NLROW* nlrow, /**< nonlinear row */
1658 BMS_BLKMEM* blkmem, /**< block memory */
1659 SCIP_SET* set, /**< global SCIP settings */
1660 SCIP_STAT* stat, /**< problem statistics data */
1661 SCIP_PROB* prob, /**< SCIP problem */
1662 SCIP_PRIMAL* primal, /**< primal data */
1663 SCIP_TREE* tree, /**< branch and bound tree */
1664 SCIP_LP* lp, /**< SCIP LP */
1665 SCIP_Real* pseudoactivity /**< buffer to store pseudo activity value */
1666 )
1667{
1668 assert(nlrow != NULL);
1669 assert(stat != NULL);
1670 assert(pseudoactivity != NULL);
1671 assert(nlrow->validpsactivitydomchg <= stat->domchgcount);
1672
1673 /* check, if pseudo activity has to be calculated */
1674 if( nlrow->validpsactivitydomchg != stat->domchgcount )
1675 {
1676 SCIP_CALL( SCIPnlrowRecalcPseudoActivity(nlrow, blkmem, set, stat, prob, primal, tree, lp) );
1677 }
1678 assert(nlrow->validpsactivitydomchg == stat->domchgcount);
1679 assert(nlrow->pseudoactivity < SCIP_INVALID);
1680
1681 *pseudoactivity = nlrow->pseudoactivity;
1682
1683 return SCIP_OKAY;
1684}
1685
1686/** returns the pseudo feasibility of a nonlinear row in the current pseudo solution: negative value means infeasibility */
1688 SCIP_NLROW* nlrow, /**< nonlinear row */
1689 BMS_BLKMEM* blkmem, /**< block memory */
1690 SCIP_SET* set, /**< global SCIP settings */
1691 SCIP_STAT* stat, /**< problem statistics data */
1692 SCIP_PROB* prob, /**< SCIP problem */
1693 SCIP_PRIMAL* primal, /**< primal data */
1694 SCIP_TREE* tree, /**< branch and bound tree */
1695 SCIP_LP* lp, /**< SCIP LP */
1696 SCIP_Real* pseudofeasibility /**< buffer to store pseudo feasibility value */
1697 )
1698{
1699 SCIP_Real pseudoactivity;
1700
1701 assert(nlrow != NULL);
1702 assert(stat != NULL);
1703 assert(pseudofeasibility != NULL);
1704
1705 SCIP_CALL( SCIPnlrowGetPseudoActivity(nlrow, blkmem, set, stat, prob, primal, tree, lp, &pseudoactivity) );
1706 *pseudofeasibility = MIN(nlrow->rhs - pseudoactivity, pseudoactivity - nlrow->lhs);
1707
1708 return SCIP_OKAY;
1709}
1710
1711/** returns the activity of a nonlinear row for a given solution */
1713 SCIP_NLROW* nlrow, /**< nonlinear row */
1714 BMS_BLKMEM* blkmem, /**< block memory */
1715 SCIP_SET* set, /**< global SCIP settings */
1716 SCIP_STAT* stat, /**< problem statistics data */
1717 SCIP_SOL* sol, /**< primal CIP solution */
1718 SCIP_Real* activity /**< buffer to store activity value */
1719 )
1720{
1721 SCIP_Real inf;
1722 SCIP_Real val1;
1723 int i;
1724
1725 assert(nlrow != NULL);
1726 assert(set != NULL);
1727 assert(stat != NULL);
1728 assert(activity != NULL);
1729
1730 *activity = nlrow->constant;
1731 for( i = 0; i < nlrow->nlinvars; ++i )
1732 {
1733 assert(nlrow->linvars[i] != NULL);
1734
1735 val1 = SCIPsolGetVal(sol, set, stat, nlrow->linvars[i]);
1736 if( val1 == SCIP_UNKNOWN )
1737 {
1738 *activity = SCIP_INVALID;
1739 return SCIP_OKAY;
1740 }
1741 *activity += nlrow->lincoefs[i] * val1;
1742 }
1743
1744 if( nlrow->expr != NULL )
1745 {
1746 SCIP_CALL( SCIPexprEval(set, stat, blkmem, nlrow->expr, sol, 0L) );
1747 if( SCIPexprGetEvalValue(nlrow->expr) == SCIP_INVALID )
1748 *activity = SCIP_INVALID;
1749 else
1750 *activity += SCIPexprGetEvalValue(nlrow->expr);
1751 }
1752
1753 inf = SCIPsetInfinity(set);
1754 *activity = MAX(*activity, -inf);
1755 *activity = MIN(*activity, +inf);
1756
1757 return SCIP_OKAY;
1758}
1759
1760/** returns the feasibility of a nonlinear row for the given solution */
1762 SCIP_NLROW* nlrow, /**< nonlinear row */
1763 BMS_BLKMEM* blkmem, /**< block memory */
1764 SCIP_SET* set, /**< global SCIP settings */
1765 SCIP_STAT* stat, /**< problem statistics data */
1766 SCIP_SOL* sol, /**< primal CIP solution */
1767 SCIP_Real* feasibility /**< buffer to store feasibility value */
1768 )
1769{
1770 SCIP_Real activity;
1771
1772 assert(nlrow != NULL);
1773 assert(feasibility != NULL);
1774
1775 SCIP_CALL( SCIPnlrowGetSolActivity(nlrow, blkmem, set, stat, sol, &activity) );
1776
1777 *feasibility = MIN(nlrow->rhs - activity, activity - nlrow->lhs);
1778
1779 return SCIP_OKAY;
1780}
1781
1782/** returns the minimal activity of a nonlinear row w.r.t. the variables' bounds */
1784 SCIP_NLROW* nlrow, /**< nonlinear row */
1785 BMS_BLKMEM* blkmem, /**< block memory */
1786 SCIP_SET* set, /**< global SCIP settings */
1787 SCIP_STAT* stat, /**< problem statistics data */
1788 SCIP_Real* minactivity, /**< buffer to store minimal activity, or NULL */
1789 SCIP_Real* maxactivity /**< buffer to store maximal activity, or NULL */
1790 )
1791{
1792 assert(nlrow != NULL);
1793 assert(set != NULL);
1794 assert(stat != NULL);
1795 assert(nlrow->validactivitybdsdomchg <= stat->domchgcount);
1796
1797 /* check, if activity bounds has to be calculated */
1798 if( nlrow->validactivitybdsdomchg != stat->domchgcount )
1799 {
1800 SCIP_CALL( nlrowCalcActivityBounds(nlrow, blkmem, set, stat) );
1801 }
1802 assert(nlrow->validactivitybdsdomchg == stat->domchgcount);
1803 assert(nlrow->minactivity < SCIP_INVALID);
1804 assert(nlrow->maxactivity < SCIP_INVALID);
1805
1806 if( minactivity != NULL )
1807 *minactivity = nlrow->minactivity;
1808 if( maxactivity != NULL )
1809 *maxactivity = nlrow->maxactivity;
1810
1811 return SCIP_OKAY;
1812}
1813
1814/** returns whether the nonlinear row is redundant w.r.t. the variables' bounds */
1816 SCIP_NLROW* nlrow, /**< nonlinear row */
1817 BMS_BLKMEM* blkmem, /**< block memory */
1818 SCIP_SET* set, /**< global SCIP settings */
1819 SCIP_STAT* stat, /**< problem statistics data */
1820 SCIP_Bool* isredundant /**< buffer to store whether row is redundant */
1821 )
1822{
1823 SCIP_Real minactivity;
1824 SCIP_Real maxactivity;
1825
1826 assert(nlrow != NULL);
1827 assert(set != NULL);
1828 assert(isredundant != NULL);
1829
1830 SCIP_CALL( SCIPnlrowGetActivityBounds(nlrow, blkmem, set, stat, &minactivity, &maxactivity) );
1831
1832 *isredundant = TRUE;
1833 if( (!SCIPsetIsInfinity(set, -nlrow->lhs) && SCIPsetIsFeasLT(set, minactivity, nlrow->lhs)) ||
1834 ( !SCIPsetIsInfinity(set, nlrow->rhs) && SCIPsetIsFeasGT(set, maxactivity, nlrow->rhs)) )
1835 *isredundant = FALSE;
1836
1837 return SCIP_OKAY;
1838}
1839
1840#ifdef NDEBUG
1841/* Undo the defines from pub_nlhdlr.h, which exist if NDEBUG is defined. */
1842#undef SCIPnlrowGetConstant
1843#undef SCIPnlrowGetNLinearVars
1844#undef SCIPnlrowGetLinearVars
1845#undef SCIPnlrowGetLinearCoefs
1846#undef SCIPnlrowGetExpr
1847#undef SCIPnlrowGetLhs
1848#undef SCIPnlrowGetRhs
1849#undef SCIPnlrowGetCurvature
1850#undef SCIPnlrowGetName
1851#undef SCIPnlrowGetNLPPos
1852#undef SCIPnlrowIsInNLP
1853#undef SCIPnlrowGetDualsol
1854#endif
1855
1856/** gets constant */
1858 SCIP_NLROW* nlrow /**< NLP row */
1859 )
1860{
1861 assert(nlrow != NULL);
1862
1863 return nlrow->constant;
1864}
1865
1866/** gets number of variables of linear part */
1868 SCIP_NLROW* nlrow /**< NLP row */
1869 )
1870{
1871 assert(nlrow != NULL);
1872
1873 return nlrow->nlinvars;
1874}
1875
1876/** gets array with variables of linear part */
1878 SCIP_NLROW* nlrow /**< NLP row */
1879 )
1880{
1881 assert(nlrow != NULL);
1882
1883 return nlrow->linvars;
1884}
1885
1886/** gets array with coefficients in linear part */
1888 SCIP_NLROW* nlrow /**< NLP row */
1889 )
1890{
1891 assert(nlrow != NULL);
1892
1893 return nlrow->lincoefs;
1894}
1895
1896/** gets expression */
1898 SCIP_NLROW* nlrow /**< NLP row */
1899 )
1900{
1901 assert(nlrow != NULL);
1902
1903 return nlrow->expr;
1904}
1905
1906/** returns the left hand side of a nonlinear row */
1908 SCIP_NLROW* nlrow /**< NLP row */
1909 )
1910{
1911 assert(nlrow != NULL);
1912
1913 return nlrow->lhs;
1914}
1915
1916/** returns the right hand side of a nonlinear row */
1918 SCIP_NLROW* nlrow /**< NLP row */
1919 )
1920{
1921 assert(nlrow != NULL);
1922
1923 return nlrow->rhs;
1924}
1925
1926/** returns the curvature of a nonlinear row */
1928 SCIP_NLROW* nlrow /**< NLP row */
1929 )
1930{
1931 assert(nlrow != NULL);
1932 return nlrow->curvature;
1933}
1934
1935/** returns the name of a nonlinear row */
1937 SCIP_NLROW* nlrow /**< NLP row */
1938 )
1939{
1940 assert(nlrow != NULL);
1941
1942 return nlrow->name;
1943}
1944
1945/** gets position of a nonlinear row in current NLP, or -1 if not in NLP */
1947 SCIP_NLROW* nlrow /**< NLP row */
1948 )
1949{
1950 assert(nlrow != NULL);
1951
1952 return nlrow->nlpindex;
1953}
1954
1955/** returns TRUE iff row is member of current NLP */
1957 SCIP_NLROW* nlrow /**< NLP row */
1958 )
1959{
1960 assert(nlrow != NULL);
1961
1962 return nlrow->nlpindex != -1;
1963}
1964
1965/** gets the dual NLP solution of a nlrow
1966 *
1967 * for a ranged constraint, the dual value is positive if the right hand side is active and negative if the left hand side is active
1968 */
1970 SCIP_NLROW* nlrow /**< NLP row */
1971 )
1972{
1973 assert(nlrow != NULL);
1974
1975 return nlrow->nlpiindex >= 0 ? nlrow->dualsol : 0.0;
1976}
1977
1978/** @} */
1979
1980/*
1981 * local NLP methods
1982 */
1983
1984/** announces, that a row of the NLP was modified
1985 * adjusts status of current solution
1986 * calling method has to ensure that change is passed to the NLPI!
1987 */ /*lint -e{715}*/
1988static
1990 SCIP_NLP* nlp, /**< current NLP data */
1991 SCIP_SET* set, /**< global SCIP settings */
1992 SCIP_STAT* stat, /**< problem statistics data */
1993 SCIP_NLROW* nlrow /**< nonlinear row which was changed */
1994 )
1995{ /*lint --e{715}*/
1996 assert(nlp != NULL);
1997 assert(nlrow != NULL);
1998 assert(!nlp->indiving);
1999 assert(nlrow->nlpindex >= 0);
2000
2001 /* nlrow is a row in the NLP, so changes effect feasibility */
2002 /* if we have a feasible NLP solution and it satisfies the modified row, then it is still feasible
2003 * if the NLP was globally or locally infeasible or unbounded, then this may not be the case anymore
2004 */
2005 if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2006 {
2007 /* TODO bring this back? then everything that may call nlpRowChanged will need to pass on blkmem, primal, tree as well
2008 SCIP_Real feasibility;
2009 SCIP_CALL( SCIPnlrowGetNLPFeasibility(nlrow, blkmem, set, stat, primal, tree, nlp, &feasibility) );
2010 if( !SCIPsetIsFeasNegative(set, feasibility) )
2011 nlp->solstat = SCIP_NLPSOLSTAT_FEASIBLE;
2012 else */
2014 }
2015 else
2016 {
2018 }
2019
2020 return SCIP_OKAY;
2021}
2022
2023/** adds a set of nonlinear rows to the NLP and captures them */
2024static
2026 SCIP_NLP* nlp, /**< NLP data */
2027 BMS_BLKMEM* blkmem, /**< block memory */
2028 SCIP_SET* set, /**< global SCIP settings */
2029 SCIP_STAT* stat, /**< problem statistics data */
2030 int nnlrows, /**< number of nonlinear rows to add */
2031 SCIP_NLROW** nlrows /**< nonlinear rows to add */
2032 )
2033{
2034#ifndef NDEBUG
2035 int i;
2036#endif
2037 int j;
2038 SCIP_NLROW* nlrow;
2039
2040 assert(nlp != NULL);
2041 assert(blkmem != NULL);
2042 assert(set != NULL);
2043 assert(nlrows != NULL || nnlrows == 0);
2044 assert(!nlp->indiving);
2045
2046 SCIP_CALL( SCIPnlpEnsureNlRowsSize(nlp, blkmem, set, nlp->nnlrows + nnlrows) );
2047
2048 for( j = 0; j < nnlrows; ++j )
2049 {
2050 nlrow = nlrows[j]; /*lint !e613*/
2051
2052 /* assert that row is not in NLP (or even NLPI) yet */
2053 assert(nlrow->nlpindex == -1);
2054 assert(nlrow->nlpiindex == -1);
2055
2056 /* make sure there are only active variables in row */
2057 SCIP_CALL( SCIPnlrowSimplify(nlrow, blkmem, set, stat, nlp) );
2058
2059#ifndef NDEBUG
2060 /* assert that variables of row are in NLP */
2061 for( i = 0; i < nlrow->nlinvars; ++i )
2062 assert(SCIPhashmapExists(nlp->varhash, nlrow->linvars[i]));
2063
2064 if( nlrow->expr != NULL )
2065 {
2066 SCIP_EXPRITER* it;
2067 SCIP_EXPR* expr;
2068
2069 SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2071 for( expr = nlrow->expr; !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
2072 assert(!SCIPexprIsVar(set, expr) || SCIPhashmapExists(nlp->varhash, SCIPgetVarExprVar(expr)));
2073 SCIPexpriterFree(&it);
2074 }
2075#endif
2076
2077 /* add row to NLP and capture it */
2078 nlp->nlrows[nlp->nnlrows + j] = nlrow;
2079 nlrow->nlpindex = nlp->nnlrows + j;
2080
2081 nlrowAddToStat(nlp, set, nlrow, 1);
2082
2083 SCIPnlrowCapture(nlrow);
2084
2085 /* if we have a feasible NLP solution and it satisfies the new solution, then it is still feasible
2086 * if the NLP was globally or locally infeasible, then it stays that way
2087 * if the NLP was unbounded, then this may not be the case anymore
2088 */
2089 if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2090 {
2091 /* TODO bring this back? then everything that may call nlpAddNlRows will need to pass on primal, tree as well
2092 SCIP_Real feasibility;
2093 SCIP_CALL( SCIPnlrowGetNLPFeasibility(nlrow, blkmem, set, stat, primal, tree, nlp, &feasibility) );
2094 if( !SCIPsetIsFeasNegative(set, feasibility) )
2095 nlp->solstat = SCIP_NLPSOLSTAT_FEASIBLE;
2096 else
2097 */
2099 }
2100 else if( nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
2101 {
2103 }
2104 }
2105
2106 nlp->nnlrows += nnlrows;
2107 nlp->nunflushednlrowadd += nnlrows;
2108
2109 return SCIP_OKAY;
2110}
2111
2112/** moves a nonlinear row to a different place, and updates all corresponding data structures */
2113static
2115 SCIP_NLP* nlp, /**< NLP data structure */
2116 int oldpos, /**< old position of nonlinear row */
2117 int newpos /**< new position of nonlinear row */
2118 )
2119{
2120 assert(nlp != NULL);
2121 assert(0 <= oldpos && oldpos < nlp->nnlrows);
2122 assert(0 <= newpos && newpos < nlp->nnlrows);
2123 assert(nlp->nlrows[oldpos] != NULL);
2124
2125 if( oldpos == newpos )
2126 return;
2127
2128 nlp->nlrows[newpos] = nlp->nlrows[oldpos];
2129 nlp->nlrows[newpos]->nlpindex = newpos;
2130
2131 /* update nlpi to nlp row index mapping */
2132 if( nlp->nlrows[newpos]->nlpiindex >= 0 )
2133 {
2134 assert(nlp->nlrowmap_nlpi2nlp != NULL);
2135 assert(nlp->nlrows[newpos]->nlpiindex < nlp->sizenlrows_solver);
2136 nlp->nlrowmap_nlpi2nlp[nlp->nlrows[newpos]->nlpiindex] = newpos;
2137 }
2138}
2139
2140/** deletes nonlinear row with given position from NLP */
2141static
2143 SCIP_NLP* nlp, /**< NLP data structure */
2144 BMS_BLKMEM* blkmem, /**< block memory */
2145 SCIP_SET* set, /**< global SCIP settings */
2146 SCIP_STAT* stat, /**< problem statistics data */
2147 int pos /**< position of nonlinear row that is to be removed */
2148 )
2149{
2150 SCIP_NLROW* nlrow;
2151
2152 assert(nlp != NULL);
2153 assert(blkmem != NULL);
2154 assert(set != NULL);
2155 assert(pos >= 0);
2156 assert(pos < nlp->nnlrows);
2157 assert(!nlp->indiving);
2158 assert(nlp->nlrows != NULL);
2159
2160 nlrow = nlp->nlrows[pos];
2161 assert(nlrow != NULL);
2162 assert(nlrow->nlpindex == pos);
2163
2164 /* if row is in NLPI, then mark that it has to be removed in the next flush
2165 * if row was not in NLPI yet, then we have one unflushed nlrow addition less */
2166 if( nlrow->nlpiindex >= 0 )
2167 {
2168 assert(nlrow->nlpiindex < nlp->nnlrows_solver);
2169 nlp->nlrowmap_nlpi2nlp[nlrow->nlpiindex] = -1;
2170 nlrow->nlpiindex = -1;
2171 ++nlp->nunflushednlrowdel;
2172 }
2173 else
2174 {
2175 assert(nlrow->nlpiindex == -1);
2176 --nlp->nunflushednlrowadd;
2177 }
2178
2179 /* move NLP row from the end to pos and mark nlrow to be not in NLP anymore */
2180 nlpMoveNlrow(nlp, nlp->nnlrows-1, pos);
2181 nlrow->nlpindex = -1;
2182
2183 /* do no longer count nlrow in NLP row statistics */
2184 nlrowAddToStat(nlp, set, nlrow, -1);
2185
2186 /* forget about restriction */
2187 SCIP_CALL( SCIPnlrowRelease(&nlrow, blkmem, set, stat) );
2188 --nlp->nnlrows;
2189
2190 if( nlp->solstat < SCIP_NLPSOLSTAT_LOCOPT )
2192 else if( nlp->solstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE )
2194
2195 return SCIP_OKAY; /*lint !e438*/
2196}
2197
2198/** updates bounds on a variable in the NLPI problem */
2199static
2201 SCIP_NLP* nlp, /**< NLP data */
2202 SCIP_SET* set, /**< global SCIP settings */
2203 SCIP_VAR* var, /**< variable which bounds have changed */
2204 SCIP_Bool tightened /**< whether the bound change was a bound tightening */
2205 )
2206{
2207 int pos;
2208 SCIP_Real lb;
2209 SCIP_Real ub;
2210
2211 assert(nlp != NULL);
2212 assert(var != NULL);
2213 assert(SCIPhashmapExists(nlp->varhash, var));
2214
2215 /* original variable bounds are ignored during diving
2216 * (all variable bounds are reset to their current value in exitDiving) */
2217 if( nlp->indiving )
2218 return SCIP_OKAY;
2219
2220 /* get position of variable in NLP */
2221 pos = SCIPhashmapGetImageInt(nlp->varhash, var);
2222
2223 /* if variable not in NLPI yet, nothing to do */
2224 if( nlp->varmap_nlp2nlpi[pos] == -1 )
2225 return SCIP_OKAY;
2226
2227 /* update bounds in NLPI problem */
2228 assert(nlp->solver != NULL);
2229 assert(nlp->problem != NULL);
2230
2231 pos = nlp->varmap_nlp2nlpi[pos];
2232 lb = SCIPvarGetLbLocal(var);
2233 ub = SCIPvarGetUbLocal(var);
2234 SCIP_CALL( SCIPnlpiChgVarBounds(set, nlp->solver, nlp->problem, 1, &pos, &lb, &ub) );
2235
2236 /* if we have a feasible NLP solution and it satisfies the new bounds, then it is still feasible
2237 * if the NLP was globally or locally infeasible and we tightened a bound, then it stays that way
2238 * if the NLP was unbounded and we tightened a bound, then this may not be the case anymore
2239 */
2240 if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2241 {
2242 if( !tightened ||
2243 ((SCIPsetIsInfinity(set, -lb) || SCIPsetIsFeasLE(set, lb, SCIPvarGetNLPSol(var))) &&
2246 else
2248 }
2249 else if( !tightened || nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
2250 {
2252 }
2253
2254 return SCIP_OKAY;
2255}
2256
2257/** updates coefficient of a variable in the objective */
2258static
2260 SCIP_SET* set, /**< global SCIP settings */
2261 SCIP_NLP* nlp, /**< NLP data */
2262 SCIP_VAR* var /**< variable which bounds have changed */
2263 )
2264{
2265 int pos;
2266 int objidx;
2267 SCIP_Real coef;
2268
2269 assert(nlp != NULL);
2270 assert(var != NULL);
2271 assert(SCIPhashmapExists(nlp->varhash, var));
2272
2273 /* if the objective in the NLPI is not up to date, then we do not need to do something here */
2274 if( !nlp->objflushed )
2275 return SCIP_OKAY;
2276
2277 /* original objective is ignored during diving
2278 * we just need to remember that at end of diving we have to flush the objective */
2279 if( nlp->indiving )
2280 {
2281 nlp->objflushed = FALSE;
2282 return SCIP_OKAY;
2283 }
2284
2285 /* get position of variable in NLP and objective coefficient */
2286 pos = SCIPhashmapGetImageInt(nlp->varhash, var);
2287 assert(nlp->varmap_nlp2nlpi[pos] == -1 || nlp->solver != NULL);
2288
2289 /* actually we only need to remember flushing the objective if we also have an NLPI */
2290 if( nlp->solver == NULL )
2291 return SCIP_OKAY;
2292
2293 coef = SCIPvarGetObj(var);
2294
2295 /* if variable not in NLPI yet, then we only need to remember to update the objective after variable additions were flushed */
2296 if( nlp->varmap_nlp2nlpi[pos] == -1 && coef != 0.0 )
2297 {
2298 nlp->objflushed = FALSE;
2299
2300 return SCIP_OKAY;
2301 }
2302
2303 /* if we are here, then the objective in the NLPI is up to date,
2304 * we keep it this way by changing the coefficient of var in the NLPI problem objective */
2305 assert(nlp->solver != NULL);
2306 assert(nlp->problem != NULL);
2307
2308 pos = nlp->varmap_nlp2nlpi[pos];
2309 objidx = -1;
2310 SCIP_CALL( SCIPnlpiChgLinearCoefs(set, nlp->solver, nlp->problem, objidx, 1, &pos, &coef) );
2311
2312 /* if we had a solution and it was locally (or globally) optimal, then now we can only be sure that it is still feasible */
2315
2316 return SCIP_OKAY;
2317}
2318
2319/** adds new variables to the NLP */
2320static
2322 SCIP_NLP* nlp, /**< NLP data structure */
2323 BMS_BLKMEM* blkmem, /**< block memory */
2324 SCIP_SET* set, /**< global SCIP settings */
2325 int nvars, /**< number of variables to add */
2326 SCIP_VAR** vars /**< variable to add to NLP */
2327 )
2328{
2329 int i;
2330 SCIP_VAR* var;
2331
2332 assert(nlp != NULL);
2333 assert(blkmem != NULL);
2334 assert(set != NULL);
2335 assert(vars != NULL || nvars == 0);
2336 assert(!nlp->indiving || nvars == 0);
2337
2338 if( nvars == 0 )
2339 return SCIP_OKAY;
2340
2341 SCIP_CALL( SCIPnlpEnsureVarsSize(nlp, blkmem, set, nlp->nvars + nvars) );
2342 assert(nlp->sizevars >= nlp->nvars + nvars);
2343
2344 for( i = 0; i < nvars; ++i )
2345 {
2346 var = vars[i]; /*lint !e613*/
2347
2348 assert(SCIPvarIsTransformed(var));
2349 assert(SCIPvarIsActive(var));
2350 assert(!SCIPhashmapExists(nlp->varhash, var));
2351
2352 SCIPvarCapture(var);
2353
2354 nlp->vars[nlp->nvars+i] = var;
2355 nlp->varmap_nlp2nlpi[nlp->nvars+i] = -1;
2356 SCIP_CALL( SCIPhashmapInsertInt(nlp->varhash, var, nlp->nvars+i) );
2357
2358 nlp->varlbdualvals[nlp->nvars+i] = 0.0;
2359 nlp->varubdualvals[nlp->nvars+i] = 0.0;
2360
2361 /* update objective, if necessary (new variables have coefficient 0.0 anyway) */
2362 if( SCIPvarGetObj(var) != 0.0 )
2363 {
2364 SCIP_CALL( nlpUpdateObjCoef(set, nlp, var) );
2365 }
2366
2367 /* let's keep the previous initial guess and set it for the new variable to the best bound
2368 * (since there can be no row that uses this variable yet, this seems a good guess) */
2369 if( nlp->haveinitguess )
2370 {
2371 assert(nlp->initialguess != NULL);
2372
2373 nlp->initialguess[nlp->nvars+i] = SCIPvarGetBestBoundLocal(var);
2374 }
2375
2376 /* if we have a feasible NLP solution, then it remains feasible
2377 * but we have to update the objective function
2378 */
2379 if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2380 {
2384 }
2385
2386 /* catch events on variable */
2387 SCIP_CALL( SCIPvarCatchEvent(var, blkmem, set, \
2389 nlp->eventhdlr, (SCIP_EVENTDATA*)nlp, NULL) ); /* @todo should store event filter position in nlp? */
2390 }
2391
2392 nlp->nvars += nvars;
2393 nlp->nunflushedvaradd += nvars;
2394
2395 return SCIP_OKAY;
2396}
2397
2398/** moves a variable to a different place, and updates all corresponding data structures */
2399static
2401 SCIP_NLP* nlp, /**< NLP data structure */
2402 int oldpos, /**< old position of variable */
2403 int newpos /**< new position of variable */
2404 )
2405{
2406 int nlpipos;
2407
2408 assert(nlp != NULL);
2409 assert(0 <= oldpos && oldpos < nlp->nvars);
2410 assert(0 <= newpos && newpos < nlp->nvars);
2411 assert(nlp->vars[oldpos] != NULL);
2412
2413 if( oldpos == newpos )
2414 return SCIP_OKAY;
2415
2416 SCIP_CALL( SCIPhashmapSetImageInt(nlp->varhash, nlp->vars[oldpos], newpos) );
2417 nlp->vars[newpos] = nlp->vars[oldpos];
2418 nlp->varmap_nlp2nlpi[newpos] = nlp->varmap_nlp2nlpi[oldpos];
2419 nlp->varlbdualvals[newpos] = nlp->varlbdualvals[oldpos];
2420 nlp->varubdualvals[newpos] = nlp->varubdualvals[oldpos];
2421 if( nlp->initialguess != NULL )
2422 nlp->initialguess[newpos] = nlp->initialguess[oldpos];
2423
2424 nlpipos = nlp->varmap_nlp2nlpi[newpos];
2425 if( nlpipos > 0 )
2426 nlp->varmap_nlpi2nlp[nlpipos] = newpos;
2427
2428 return SCIP_OKAY;
2429}
2430
2431/** deletes variable with given position from NLP */
2432static
2434 SCIP_NLP* nlp, /**< NLP data structure */
2435 BMS_BLKMEM* blkmem, /**< block memory */
2436 SCIP_SET* set, /**< global SCIP settings */
2437 SCIP_STAT* stat, /**< problem statistics data */
2438 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2439 SCIP_LP* lp, /**< SCIP LP, needed if a column-variable is freed */
2440 int pos /**< position of nonlinear row that is to be removed */
2441 )
2442{
2443 SCIP_VAR* var;
2444#ifndef NDEBUG
2445 int i;
2446#endif
2447 int nlpipos;
2448
2449 assert(nlp != NULL);
2450 assert(blkmem != NULL);
2451 assert(set != NULL);
2452 assert(pos >= 0);
2453 assert(pos < nlp->nvars);
2454 assert(!nlp->indiving);
2455
2456 var = nlp->vars[pos];
2457 assert(var != NULL);
2458
2459#ifndef NDEBUG
2460 /* assert that variable is not used by any nonlinear row */
2461 for( i = 0; i < nlp->nnlrows; ++i )
2462 {
2463 int j;
2464 SCIP_NLROW* nlrow;
2465
2466 nlrow = nlp->nlrows[i];
2467 assert(nlrow != NULL);
2468
2469 /* use nlrowSearchLinearCoef only if already sorted, since otherwise we may change the solving process slightly */
2470 if( nlrow->linvarssorted )
2471 assert( nlrowSearchLinearCoef(nlrow, var) == -1 );
2472 else
2473 for( j = 0; j < nlrow->nlinvars; ++j )
2474 assert( nlrow->linvars[j] != var );
2475
2476 if( nlrow->expr != NULL )
2477 {
2478 SCIP_EXPRITER* it;
2479 SCIP_EXPR* expr;
2480 SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
2482 for( expr = nlrow->expr; !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
2483 assert(!SCIPexprIsVar(set, expr) || SCIPgetVarExprVar(expr) != var);
2484 SCIPexpriterFree(&it);
2485 }
2486 }
2487#endif
2488
2489 /* if we had a feasible solution, then adjust objective function value
2490 * if NLP was unbounded before, then maybe it is not anymore */
2491 if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2493 else if( nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
2495
2496 /* if variable is in NLPI problem, mark that we have to remember to delete it there
2497 * if it was not in the NLPI yet, then we have one unflushed var addition less now */
2498 nlpipos = nlp->varmap_nlp2nlpi[pos];
2499 if( nlpipos >= 0 )
2500 {
2501 assert(nlpipos < nlp->nvars_solver);
2502
2503 nlp->varmap_nlpi2nlp[nlpipos] = -1;
2504 ++nlp->nunflushedvardel;
2505 }
2506 else
2507 --nlp->nunflushedvaradd;
2508
2509 /* drop events on variable */
2510 SCIP_CALL( SCIPvarDropEvent(var, blkmem, set, \
2512 nlp->eventhdlr, (SCIP_EVENTDATA*)nlp, -1) );
2513
2514 /* move variable from end to pos */
2515 SCIP_CALL( nlpMoveVar(nlp, nlp->nvars-1, pos) );
2516
2517 /* forget about variable */
2518 SCIP_CALL( SCIPhashmapRemove(nlp->varhash, var) );
2519 SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
2520 --nlp->nvars;
2521
2522 return SCIP_OKAY;
2523}
2524
2525/** notifies NLP that a variable was fixed, so it is removed from objective, all rows, and the NLP variables */
2526static
2528 SCIP_NLP* nlp, /**< NLP data */
2529 BMS_BLKMEM* blkmem, /**< block memory */
2530 SCIP_SET* set, /**< global SCIP settings */
2531 SCIP_STAT* stat, /**< problem statistics data */
2532 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2533 SCIP_LP* lp, /**< SCIP LP, needed to release variable */
2534 SCIP_VAR* var /**< variable that has been fixed */
2535 )
2536{
2537 int i;
2538
2539 assert(nlp != NULL);
2540 assert(var != NULL);
2541 assert(!SCIPvarIsActive(var));
2542 assert(!nlp->indiving);
2543 assert(SCIPhashmapExists(nlp->varhash, var));
2544
2545 /* remove var from all rows */
2546 for( i = 0; i < nlp->nnlrows; ++i )
2547 {
2548 SCIP_CALL( nlrowRemoveFixedVar(nlp->nlrows[i], blkmem, set, stat, nlp, var) );
2549 }
2550
2551 /* remove variable from NLP */
2552 SCIP_CALL( SCIPnlpDelVar(nlp, blkmem, set, stat, eventqueue, lp, var) );
2553
2554 return SCIP_OKAY;
2555}
2556
2557/** creates arrays with NLPI variable indices of linear variables in a nonlinear row */
2558static
2560 SCIP_NLP* nlp, /**< NLP data */
2561 SCIP_SET* set, /**< global SCIP settings */
2562 SCIP_NLROW* nlrow, /**< nonlinear row */
2563 int** linidxs /**< buffer to store pointer to NLPI indices of linear variables */
2564 )
2565{
2566 int i;
2567 SCIP_VAR* var;
2568
2569 assert(nlp != NULL);
2570 assert(set != NULL);
2571 assert(nlrow != NULL);
2572 assert(linidxs != NULL);
2573
2574 /* get indices of variables in linear part of row */
2575 if( nlrow->nlinvars > 0 )
2576 {
2577 assert(nlrow->linvars != NULL);
2578 assert(nlrow->lincoefs != NULL);
2579
2580 SCIP_CALL( SCIPsetAllocBufferArray(set, linidxs, nlrow->nlinvars) );
2581
2582 for( i = 0; i < nlrow->nlinvars; ++i )
2583 {
2584 var = nlrow->linvars[i];
2585 assert(var != NULL);
2586 assert(SCIPvarIsActive(var)); /* at this point, there should be only active variables in the row */
2587
2588 assert(SCIPhashmapExists(nlp->varhash, var));
2589 (*linidxs)[i] = nlp->varmap_nlp2nlpi[SCIPhashmapGetImageInt(nlp->varhash, var)];
2590 assert((*linidxs)[i] >= 0);
2591 }
2592 }
2593 else
2594 *linidxs = NULL;
2595
2596 return SCIP_OKAY;
2597}
2598
2599/** ensures, that NLPI variables array of NLP can store at least num entries */
2600static
2602 SCIP_NLP* nlp, /**< NLP data */
2603 BMS_BLKMEM* blkmem, /**< block memory */
2604 SCIP_SET* set, /**< global SCIP settings */
2605 int num /**< minimum number of entries to store */
2606 )
2607{
2608 assert(nlp != NULL);
2609 assert(blkmem != NULL);
2610 assert(set != NULL);
2611 assert(nlp->nvars_solver <= nlp->sizevars_solver);
2612
2613 if( num > nlp->sizevars_solver )
2614 {
2615 int newsize;
2616
2617 newsize = SCIPsetCalcMemGrowSize(set, num);
2619
2620 nlp->sizevars_solver = newsize;
2621 }
2622 assert(num <= nlp->sizevars_solver);
2623
2624 return SCIP_OKAY;
2625}
2626
2627/** ensures, that NLPI nonlinear rows array of NLP can store at least num entries */
2628static
2630 SCIP_NLP* nlp, /**< NLP data */
2631 BMS_BLKMEM* blkmem, /**< block memory */
2632 SCIP_SET* set, /**< global SCIP settings */
2633 int num /**< minimum number of entries to store */
2634 )
2635{
2636 assert(nlp != NULL);
2637 assert(blkmem != NULL);
2638 assert(set != NULL);
2639 assert(nlp->nnlrows_solver <= nlp->sizenlrows_solver);
2640
2641 if( num > nlp->sizenlrows_solver )
2642 {
2643 int newsize;
2644
2645 newsize = SCIPsetCalcMemGrowSize(set, num);
2647
2648 nlp->sizenlrows_solver = newsize;
2649 }
2650 assert(num <= nlp->sizenlrows_solver);
2651
2652 return SCIP_OKAY;
2653}
2654
2655/** deletes rows from the NLPI problem that have been marked as to remove */
2656static
2658 SCIP_NLP* nlp, /**< NLP data */
2659 BMS_BLKMEM* blkmem, /**< block memory */
2660 SCIP_SET* set /**< global SCIP settings */
2661 )
2662{
2663 int j;
2664 int c; /* counts the number of rows to delete */
2665 int* rowset; /* marks which rows to delete and stores new indices */
2666 SCIP_NLROW* nlrow;
2667
2668 assert(nlp != NULL);
2669 assert(blkmem != NULL);
2670 assert(set != NULL);
2671 assert(nlp->nunflushednlrowdel >= 0);
2672 assert(!nlp->indiving);
2673
2674 if( nlp->nunflushednlrowdel == 0 )
2675 {
2676#ifndef NDEBUG
2677 /* check that there are really no pending removals of nonlinear rows */
2678 for( j = 0; j < nlp->nnlrows_solver; ++j )
2679 assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
2680#endif
2681 return SCIP_OKAY;
2682 }
2683
2684 assert(nlp->solver != NULL);
2685 assert(nlp->problem != NULL);
2686
2687 /* create marker which rows have to be deleted */
2689 c = 0;
2690 for( j = 0; j < nlp->nnlrows_solver; ++j )
2691 {
2692 if( nlp->nlrowmap_nlpi2nlp[j] == -1 )
2693 {
2694 rowset[j] = 1;
2695 ++c;
2696 }
2697 else
2698 rowset[j] = 0;
2699 }
2700 assert(c == nlp->nunflushednlrowdel);
2701
2702 /* remove rows from NLPI problem */
2703 SCIP_CALL( SCIPnlpiDelConsSet(set, nlp->solver, nlp->problem, rowset, nlp->nnlrows_solver) );
2704
2705 /* update NLPI row indices */
2706 for( j = 0; j < nlp->nnlrows_solver; ++j )
2707 {
2708 assert(rowset[j] <= j); /* we assume that the NLP solver did not move a row behind its previous position!! */
2709 if( rowset[j] < 0 )
2710 {
2711 /* assert that row was marked as deleted */
2712 assert(nlp->nlrowmap_nlpi2nlp[j] == -1);
2713 }
2714 else if( rowset[j] < j )
2715 {
2716 /* nlrow at position j moved (forward) to position rowset[j] */
2717 assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
2718 assert(nlp->nlrowmap_nlpi2nlp[j] < nlp->nnlrows);
2719
2720 nlrow = nlp->nlrows[nlp->nlrowmap_nlpi2nlp[j]];
2721 assert(nlrow->nlpiindex == j);
2722
2723 /* there should be no row at the new position already */
2724 assert(nlp->nlrowmap_nlpi2nlp[rowset[j]] == -1);
2725
2726 nlrow->nlpiindex = rowset[j];
2727 nlp->nlrowmap_nlpi2nlp[rowset[j]] = nlrow->nlpindex;
2728 }
2729 else
2730 {
2731 /* row j stays at position j */
2732 assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
2733 assert(nlp->nlrowmap_nlpi2nlp[j] < nlp->nnlrows);
2734 assert(nlp->nlrows[nlp->nlrowmap_nlpi2nlp[j]]->nlpiindex == j);
2735 }
2736 }
2737 nlp->nnlrows_solver -= c;
2738 nlp->nunflushednlrowdel = 0;
2739
2740 /* cleanup */
2741 SCIPsetFreeBufferArray(set, &rowset);
2742
2743 return SCIP_OKAY;
2744}
2745
2746/** deletes variables from the NLPI problem that have been marked as to remove
2747 *
2748 * assumes that there are no pending row deletions (nlpFlushNlRowDeletions() should be called first)
2749 */
2750static
2752 SCIP_NLP* nlp, /**< NLP data */
2753 BMS_BLKMEM* blkmem, /**< block memory */
2754 SCIP_SET* set /**< global SCIP settings */
2755 )
2756{
2757 int i;
2758 int c; /* counter on number of variables to remove in solver */
2759 int* colset; /* marks which variables to delete and stores new indices */
2760
2761 assert(nlp != NULL);
2762 assert(blkmem != NULL);
2763 assert(set != NULL);
2764 assert(nlp->nunflushedvardel >= 0);
2765 assert(nlp->nunflushednlrowdel == 0);
2766 assert(!nlp->indiving);
2767
2768 if( nlp->nunflushedvardel == 0 )
2769 {
2770#ifndef NDEBUG
2771 /* check that there are really no pending removals of variables */
2772 for( i = 0; i < nlp->nvars_solver; ++i )
2773 assert(nlp->varmap_nlpi2nlp[i] >= 0);
2774#endif
2775 return SCIP_OKAY;
2776 }
2777
2778 assert(nlp->solver != NULL);
2779 assert(nlp->problem != NULL);
2780
2781 /* create marker which variables have to be deleted */
2783 c = 0;
2784 for( i = 0; i < nlp->nvars_solver; ++i )
2785 {
2786 if( nlp->varmap_nlpi2nlp[i] == -1 )
2787 {
2788 colset[i] = 1;
2789 ++c;
2790 }
2791 else
2792 colset[i] = 0;
2793 }
2794 assert(c == nlp->nunflushedvardel);
2795
2796 /* delete variables from NLPI problem */
2797 SCIP_CALL( SCIPnlpiDelVarSet(set, nlp->solver, nlp->problem, colset, nlp->nvars_solver) );
2798
2799 /* update NLPI variable indices */
2800 for( i = 0; i < nlp->nvars_solver; ++i )
2801 {
2802 assert(colset[i] <= i); /* we assume that the NLP solver did not move a variable behind its previous position!! */
2803 if( colset[i] < 0 )
2804 {
2805 /* assert that variable was marked as deleted */
2806 assert(nlp->varmap_nlpi2nlp[i] == -1);
2807 }
2808 else if( colset[i] < i)
2809 {
2810 /* variable at position i moved (forward) to position colset[i] */
2811 int varpos;
2812
2813 varpos = nlp->varmap_nlpi2nlp[i]; /* position of variable i in NLP */
2814 assert(varpos >= 0);
2815 assert(varpos < nlp->nvars);
2816 assert(nlp->varmap_nlp2nlpi[varpos] == i);
2817
2818 /* there should be no variable at the new position already */
2819 assert(nlp->varmap_nlpi2nlp[colset[i]] == -1);
2820
2821 nlp->varmap_nlp2nlpi[varpos] = colset[i];
2822 nlp->varmap_nlpi2nlp[colset[i]] = varpos;
2823 }
2824 else
2825 {
2826 /* variable i stays at position i */
2827 assert(nlp->varmap_nlpi2nlp[i] >= 0);
2828 assert(nlp->varmap_nlpi2nlp[i] < nlp->nvars);
2829 assert(nlp->varmap_nlp2nlpi[nlp->varmap_nlpi2nlp[i]] == i);
2830 }
2831 }
2832
2833 nlp->nvars_solver -= c;
2834 nlp->nunflushedvardel = 0;
2835
2836 /* cleanup */
2837 SCIPsetFreeBufferArray(set, &colset);
2838
2839 return SCIP_OKAY;
2840}
2841
2842/** adds nonlinear rows to NLPI problem that have been added to NLP before
2843 *
2844 * assumes that there are no pending variable additions or deletions (nlpFlushVarDeletions() and nlpFlushVarAdditions() should be called first)
2845 */
2846static
2848 SCIP_NLP* nlp, /**< NLP data */
2849 BMS_BLKMEM* blkmem, /**< block memory */
2850 SCIP_SET* set, /**< global SCIP settings */
2851 SCIP_STAT* stat /**< problem statistics */
2852 )
2853{
2854 int c, i;
2855 SCIP_NLROW* nlrow;
2856 SCIP_Real* lhss;
2857 SCIP_Real* rhss;
2858 int* nlinvars;
2859 int** linidxs;
2860 SCIP_Real** lincoefs;
2861 SCIP_EXPR** exprs;
2862 const char** names;
2863
2864 assert(nlp != NULL);
2865 assert(blkmem != NULL);
2866 assert(set != NULL);
2867 assert(nlp->nunflushednlrowadd >= 0);
2868 assert(nlp->nunflushedvaradd == 0);
2869 assert(nlp->nunflushedvardel == 0);
2870 assert(!nlp->indiving);
2871
2872 if( nlp->nunflushednlrowadd == 0 )
2873 {
2874#ifndef NDEBUG
2875 /* check that there are really no pending additions of variables */
2876 for( i = 0; i < nlp->nnlrows; ++i )
2877 assert(nlp->nlrows[i]->nlpiindex >= 0);
2878#endif
2879 return SCIP_OKAY;
2880 }
2881
2882 assert(nlp->solver != NULL);
2883 assert(nlp->problem != NULL);
2884
2886
2893#if ADDNAMESTONLPI
2895#else
2896 names = NULL;
2897#endif
2898
2899 c = 0;
2900 for( i = 0; i < nlp->nnlrows; ++i )
2901 {
2902 nlrow = nlp->nlrows[i];
2903 assert(nlrow != NULL);
2904
2905 /* skip nonlinear rows already in NLPI problem */
2906 if( nlrow->nlpiindex >= 0 )
2907 continue;
2908 assert(c < nlp->nunflushednlrowadd);
2909
2910 /* get indices in NLPI */
2911 SCIP_CALL( nlpSetupNlpiIndices(nlp, set, nlrow, &linidxs[c]) );
2912 assert(linidxs[c] != NULL || nlrow->nlinvars == 0);
2913
2914 nlp->nlrowmap_nlpi2nlp[nlp->nnlrows_solver+c] = i;
2915 nlrow->nlpiindex = nlp->nnlrows_solver+c;
2916
2917 lhss[c] = nlrow->lhs;
2918 rhss[c] = nlrow->rhs;
2919 if( nlrow->constant != 0.0 )
2920 {
2921 if( !SCIPsetIsInfinity(set, -nlrow->lhs) )
2922 lhss[c] -= nlrow->constant;
2923 if( !SCIPsetIsInfinity(set, nlrow->rhs) )
2924 rhss[c] -= nlrow->constant;
2925 }
2926 if( rhss[c] < lhss[c] )
2927 {
2928 assert(SCIPsetIsEQ(set, lhss[c], rhss[c]));
2929 rhss[c] = lhss[c];
2930 }
2931
2932 nlinvars[c] = nlrow->nlinvars;
2933 lincoefs[c] = nlrow->lincoefs;
2934
2935 if( nlrow->expr != NULL )
2936 {
2937 /* create copy of expr that uses varidx expressions corresponding to variables indices in NLPI */
2938 SCIP_CALL( SCIPexprCopy(set, stat, blkmem, set, stat, blkmem, nlrow->expr, &exprs[c], mapvar2varidx, (void*)nlp, NULL, NULL) );
2939 }
2940 else
2941 exprs[c] = NULL;
2942
2943#if ADDNAMESTONLPI
2944 names[c] = nlrow->name;
2945#endif
2946
2947 ++c;
2948
2949#ifdef NDEBUG
2950 /* have c vars to add already, there can be no more */
2951 if( c == nlp->nunflushednlrowadd )
2952 break;
2953#endif
2954 }
2955 assert(c == nlp->nunflushednlrowadd);
2956
2957 nlp->nnlrows_solver += c;
2958
2959 SCIP_CALL( SCIPnlpiAddConstraints(set, nlp->solver, nlp->problem, c, lhss, rhss,
2960 nlinvars, linidxs, lincoefs,
2961 exprs,
2962 names) );
2963
2964 for( c = nlp->nunflushednlrowadd - 1; c >= 0 ; --c )
2965 {
2966 if( linidxs[c] != NULL )
2967 SCIPsetFreeBufferArray(set, &linidxs[c]);
2968 if( exprs[c] != NULL )
2969 {
2970 SCIP_CALL( SCIPexprRelease(set, stat, blkmem, &exprs[c]) );
2971 }
2972 }
2973
2974#if ADDNAMESTONLPI
2975 SCIPsetFreeBufferArray(set, &names);
2976#endif
2977 SCIPsetFreeBufferArray(set, &exprs);
2978 SCIPsetFreeBufferArray(set, &lincoefs);
2979 SCIPsetFreeBufferArray(set, &linidxs);
2980 SCIPsetFreeBufferArray(set, &nlinvars);
2983
2984 nlp->nunflushednlrowadd = 0;
2985
2986 return SCIP_OKAY;
2987}
2988
2989
2990/** adds variables to NLPI problem that have been added to NLP before
2991 *
2992 * may set nlp->objflushed to FALSE if a variable with nonzero objective coefficient is added to the NLPI problem
2993 */
2994static
2996 SCIP_NLP* nlp, /**< NLP data */
2997 BMS_BLKMEM* blkmem, /**< block memory */
2998 SCIP_SET* set /**< global SCIP settings */
2999 )
3000{
3001 int i, c;
3002 SCIP_Real* lbs;
3003 SCIP_Real* ubs;
3004 const char** names;
3005
3006 assert(nlp != NULL);
3007 assert(blkmem != NULL);
3008 assert(set != NULL);
3009 assert(nlp->nunflushedvaradd >= 0);
3010 assert(!nlp->indiving);
3011
3012 if( nlp->nunflushedvaradd == 0 )
3013 {
3014#ifndef NDEBUG
3015 /* check that there are really no pending additions of variables */
3016 for( i = 0; i < nlp->nvars; ++i )
3017 assert(nlp->varmap_nlp2nlpi[i] >= 0);
3018#endif
3019 return SCIP_OKAY;
3020 }
3021
3022 assert(nlp->solver != NULL);
3023 assert(nlp->problem != NULL);
3024
3026
3029#if ADDNAMESTONLPI
3031#else
3032 names = NULL;
3033#endif
3034
3035 c = 0;
3036 for( i = 0; i < nlp->nvars; ++i )
3037 {
3038 /* skip variables already in NLPI problem */
3039 if( nlp->varmap_nlp2nlpi[i] >= 0 )
3040 continue;
3041 assert(c < nlp->nunflushedvaradd);
3042
3043 nlp->varmap_nlpi2nlp[nlp->nvars_solver+c] = i;
3044 nlp->varmap_nlp2nlpi[i] = nlp->nvars_solver+c;
3045 lbs[c] = SCIPvarGetLbLocal(nlp->vars[i]);
3046 ubs[c] = SCIPvarGetUbLocal(nlp->vars[i]);
3047#if ADDNAMESTONLPI
3048 names[c] = SCIPvarGetName(nlp->vars[i]);
3049#endif
3050 ++c;
3051
3052 /* if the new variable has a nonzero objective coefficient, then the objective need to be updated */
3053 if( !SCIPsetIsZero(set, SCIPvarGetObj(nlp->vars[i])) )
3054 nlp->objflushed = FALSE;
3055
3056#ifdef NDEBUG
3057 /* have c vars to add already, there can be no more */
3058 if( c == nlp->nunflushedvaradd )
3059 break;
3060#endif
3061 }
3062 assert(c == nlp->nunflushedvaradd);
3063
3064 nlp->nvars_solver += c;
3065
3066 SCIP_CALL( SCIPnlpiAddVars(set, nlp->solver, nlp->problem, c, lbs, ubs, names) );
3067
3068#if ADDNAMESTONLPI
3069 SCIPsetFreeBufferArray(set, &names);
3070#endif
3073
3074 nlp->nunflushedvaradd = 0;
3075
3076 return SCIP_OKAY;
3077}
3078
3079/** updates the objective in the NLPI problem, if necessary
3080 *
3081 * assumes that there are no unflushed variable additions or deletions (nlpFlushVarDeletions() and nlpFlushVarAdditions() should be called first)
3082 */
3083static
3085 SCIP_NLP* nlp, /**< NLP data */
3086 BMS_BLKMEM* blkmem, /**< block memory */
3087 SCIP_SET* set /**< global SCIP settings */
3088 )
3089{
3090 int* linindices;
3091 SCIP_Real* lincoefs;
3092 SCIP_Real coef;
3093 int i;
3094 int nz;
3095
3096 assert(nlp != NULL);
3097 assert(blkmem != NULL);
3098 assert(set != NULL);
3099 assert(nlp->nunflushedvaradd == 0);
3100 assert(nlp->nunflushedvardel == 0);
3101 assert(!nlp->indiving);
3102
3103 if( nlp->objflushed )
3104 return SCIP_OKAY;
3105
3106 assert(nlp->solver != NULL);
3107 assert(nlp->problem != NULL);
3108
3109 /* assemble coefficients */
3110 SCIP_CALL( SCIPsetAllocBufferArray(set, &linindices, nlp->nvars_solver) );
3112
3113 nz = 0;
3114 for( i = 0; i < nlp->nvars_solver; ++i )
3115 {
3116 assert(nlp->varmap_nlpi2nlp[i] >= 0); /* there should be no variable deletions pending */
3117
3118 coef = SCIPvarGetObj(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
3119 if( SCIPsetIsZero(set, coef) )
3120 continue;
3121
3122 linindices[nz] = i;
3123 lincoefs[nz] = coef;
3124 ++nz;
3125 }
3126
3128 nz, linindices, lincoefs,
3129 NULL,
3130 0.0) );
3131
3132 SCIPsetFreeBufferArray(set, &lincoefs);
3133 SCIPsetFreeBufferArray(set, &linindices);
3134
3135 nlp->objflushed = TRUE;
3136
3137 return SCIP_OKAY;
3138}
3139
3140/** solves the NLP (or diving NLP), assuming it has been flushed already */
3141static
3143 SCIP_NLP* nlp, /**< NLP data */
3144 BMS_BLKMEM* blkmem, /**< block memory buffers */
3145 SCIP_SET* set, /**< global SCIP settings */
3146 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3147 SCIP_STAT* stat, /**< problem statistics */
3148 SCIP_PRIMAL* primal, /**< primal data */
3149 SCIP_TREE* tree, /**< branch and bound tree */
3150 SCIP_NLPPARAM* nlpparam /**< NLP solve parameters */
3151 )
3152{
3153 int i;
3154
3155 assert(nlp != NULL);
3156 assert(blkmem != NULL);
3157 assert(set != NULL);
3158 assert(stat != NULL);
3159
3160 if( nlp->solver == NULL )
3161 {
3162 SCIPmessagePrintWarning(messagehdlr, "Attempted to solve NLP, but no solver available.\n");
3163
3166
3167 return SCIP_OKAY;
3168 }
3169
3170 assert(nlp->solver != NULL);
3171 assert(nlp->problem != NULL);
3172
3173 /* set initial guess, if available and warmstart hasn't been enabled
3174 * when using the NLP, passing a dual solution with the initguess is not available at the moment (TODO),
3175 * so a warmstart has to start from the last solution stored in the NLPI
3176 */
3177 if( nlp->haveinitguess && !nlpparam->warmstart )
3178 {
3179 /* @todo should we not set it if we had set it already? (initguessflushed...) */
3180 SCIP_Real* initialguess_solver;
3181 int nlpidx;
3182
3183 assert(nlp->initialguess != NULL);
3184
3185 SCIP_CALL( SCIPsetAllocBufferArray(set, &initialguess_solver, nlp->nvars_solver) );
3186
3187 for( i = 0; i < nlp->nvars_solver; ++i )
3188 {
3189 nlpidx = nlp->varmap_nlpi2nlp[i];
3190 assert(nlpidx >= 0);
3191 assert(nlpidx < nlp->nvars);
3192
3193 initialguess_solver[i] = nlp->initialguess[nlpidx];
3194 }
3195 SCIP_CALL( SCIPnlpiSetInitialGuess(set, nlp->solver, nlp->problem, initialguess_solver, NULL, NULL, NULL) );
3196
3197 SCIPsetFreeBufferArray(set, &initialguess_solver);
3198 }
3199
3200 /* let NLP solver do his work */
3202
3203 SCIP_CALL( SCIPnlpiSolve(set, stat, nlp->solver, nlp->problem, nlpparam) );
3204
3206 ++stat->nnlps;
3207
3208 nlp->termstat = SCIPnlpiGetTermstat(set, nlp->solver, nlp->problem);
3209 nlp->solstat = SCIPnlpiGetSolstat(set, nlp->solver, nlp->problem);
3210 switch( nlp->solstat )
3211 {
3216 {
3217 SCIP_Real* primalvals;
3218 SCIP_Real* nlrowdualvals;
3219 SCIP_Real* varlbdualvals;
3220 SCIP_Real* varubdualvals;
3221
3222 primalvals = NULL;
3223 nlrowdualvals = NULL;
3224 varlbdualvals = NULL;
3225 varubdualvals = NULL;
3226
3227 /* get NLP solution */
3228 SCIP_CALL( SCIPnlpiGetSolution(set, nlp->solver, nlp->problem, &primalvals, &nlrowdualvals, &varlbdualvals, &varubdualvals, NULL) );
3229 assert(primalvals != NULL || nlp->nvars == 0);
3230 assert((varlbdualvals != NULL) == (varubdualvals != NULL)); /* if there are duals for one bound, then there should also be duals for the other bound */
3231
3232 /* store solution primal values in variable and evaluate objective function */
3233 if( nlp->indiving && nlp->divingobj != NULL )
3234 {
3235 for( i = 0; i < nlp->nvars; ++i )
3236 {
3237 SCIP_CALL( SCIPvarSetNLPSol(nlp->vars[i], set, primalvals[nlp->varmap_nlp2nlpi[i]]) ); /*lint !e613 */
3238 }
3239
3240 /* evaluate modified diving objective */
3241 SCIP_CALL( SCIPnlrowGetNLPActivity(nlp->divingobj, blkmem, set, stat, primal, tree, nlp, &nlp->primalsolobjval) );
3242 }
3243 else
3244 {
3245 /* evaluate SCIP objective function */
3246 nlp->primalsolobjval = 0.0;
3247 for( i = 0; i < nlp->nvars; ++i )
3248 {
3249 SCIP_Real solval = primalvals[nlp->varmap_nlp2nlpi[i]]; /*lint !e613 */
3250
3251 /* do a quick assert that variable bounds are satisfied, if feasibility is claimed */
3252 assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(nlp->vars[i])) ||
3254 assert(SCIPsetIsInfinity(set, SCIPvarGetUbLocal(nlp->vars[i])) ||
3256
3257 SCIP_CALL( SCIPvarSetNLPSol(nlp->vars[i], set, solval) ); /*lint !e613 */
3258 nlp->primalsolobjval += SCIPvarGetObj(nlp->vars[i]) * solval; /*lint !e613 */
3259 }
3260 }
3261
3262 /* store solution dual values in nlrows and variables */
3263 for( i = 0; i < nlp->nnlrows; ++i )
3264 {
3265 assert(nlp->nlrows[i]->nlpiindex >= 0); /* NLP was flushed before solve, so all nlrows should be in there */
3266
3267 nlp->nlrows[i]->dualsol = nlrowdualvals != NULL ? nlrowdualvals[nlp->nlrows[i]->nlpiindex] : 0.0;
3268
3269 /* SCIPsetDebugMsg(set, "dual of nlrow <%s> = %g\n", nlp->nlrows[i]->name, nlp->nlrows[i]->dualsol); */
3270 }
3271 assert(nlp->varlbdualvals != NULL || nlp->nvars == 0);
3272 assert(nlp->varubdualvals != NULL || nlp->nvars == 0);
3273 if( varlbdualvals != NULL )
3274 {
3275 for( i = 0; i < nlp->nvars; ++i )
3276 {
3277 assert(nlp->varmap_nlp2nlpi[i] >= 0); /* NLP was flushed before solve, so all vars should be in there */
3278
3279 nlp->varlbdualvals[i] = varlbdualvals[nlp->varmap_nlp2nlpi[i]];
3280 nlp->varubdualvals[i] = varubdualvals[nlp->varmap_nlp2nlpi[i]];
3281
3282 /* SCIPsetDebugMsg(set, "duals of var <%s> = %g %g\n", SCIPvarGetName(nlp->vars[i]), nlp->varlbdualvals[i], nlp->varubdualvals[i]); */
3283 }
3284 }
3285 else if( nlp->nvars > 0 )
3286 {
3289 }
3290
3291 break;
3292 }
3293 default:
3295 break;
3296 } /*lint !e788*/
3297
3298 return SCIP_OKAY;
3299}
3300
3301/** assembles list of fractional variables in last NLP solution */
3302static
3304 SCIP_NLP* nlp, /**< NLP data */
3305 BMS_BLKMEM* blkmem, /**< block memory buffers */
3306 SCIP_SET* set, /**< global SCIP settings */
3307 SCIP_STAT* stat /**< problem statistics */
3308 )
3309{
3310 assert(nlp != NULL);
3311 assert(blkmem != NULL);
3312 assert(set != NULL);
3313 assert(stat != NULL);
3314 assert(nlp->validfracvars <= stat->nnlps);
3315 assert(SCIPnlpHasSolution(nlp));
3316
3317 SCIPsetDebugMsg(set, "calculating NLP fractional variables: validfracvars=%" SCIP_LONGINT_FORMAT ", nnlps=%" SCIP_LONGINT_FORMAT "\n", nlp->validfracvars, stat->nnlps);
3318
3320 {
3321 nlp->nfracvars = 0;
3322 nlp->npriofracvars = 0;
3323 nlp->validfracvars = stat->nnlps;
3324
3325 SCIPsetDebugMsg(set, "NLP globally infeasible, unbounded, or worse -> no solution values -> no fractional variables\n");
3326 return SCIP_OKAY;
3327 }
3328
3329 /* check, if the current NLP fractional variables array is invalid */
3330 if( nlp->validfracvars < stat->nnlps )
3331 {
3332 SCIP_VAR* var;
3333 SCIP_Real primsol;
3334 SCIP_Real frac;
3335 int branchpriority;
3336 int insertpos;
3337 int maxpriority;
3338 int i;
3339
3340 SCIPsetDebugMsg(set, " -> recalculating NLP fractional variables\n");
3341
3342 if( nlp->fracvarssize == 0 )
3343 {
3344 assert(nlp->fracvars == NULL);
3345 assert(nlp->fracvarssol == NULL);
3346 assert(nlp->fracvarsfrac == NULL);
3347 nlp->fracvarssize = 5;
3351 }
3352
3353 maxpriority = INT_MIN;
3354 nlp->nfracvars = 0;
3355 nlp->npriofracvars = 0;
3356 for( i = 0; i < nlp->nvars; ++i )
3357 {
3358 var = nlp->vars[i];
3359 assert(var != NULL);
3360
3361 primsol = SCIPvarGetNLPSol(var);
3362 assert(primsol < SCIP_INVALID);
3363
3364 /* consider only binary and integer variables */
3366 continue;
3367
3368 /* ignore fixed variables (due to numerics, it is possible, that the NLP solution of a fixed integer variable
3369 * (with large fixed value) is fractional in terms of absolute feasibility measure)
3370 */
3371 if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
3372 continue;
3373
3374 /* check, if the LP solution value is fractional */
3375 frac = SCIPsetFeasFrac(set, primsol);
3376
3377 /* The fractionality should not be smaller than -feastol, however, if the primsol is large enough
3378 * and close to an integer, fixed precision floating point arithmetic might give us values slightly
3379 * smaller than -feastol. Originally, the "frac >= -feastol"-check was within SCIPsetIsFeasFracIntegral(),
3380 * however, we relaxed it to "frac >= -2*feastol" and have the stricter check here for small-enough primsols.
3381 */
3382 assert(SCIPsetIsGE(set, frac, -SCIPsetFeastol(set)) || (primsol > 1e14 * SCIPsetFeastol(set)));
3383
3384 if( SCIPsetIsFeasFracIntegral(set, frac) )
3385 continue;
3386
3387 /* ensure enough space in fracvars arrays */
3388 if( nlp->fracvarssize <= nlp->nfracvars )
3389 {
3390 int newsize;
3391
3392 newsize = SCIPsetCalcMemGrowSize(set, nlp->nfracvars + 1);
3393 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvars, nlp->fracvarssize, newsize) );
3394 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvarssol, nlp->fracvarssize, newsize) );
3395 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvarsfrac, nlp->fracvarssize, newsize) );
3396 nlp->fracvarssize = newsize;
3397 }
3398 assert(nlp->nfracvars < nlp->fracvarssize);
3399 assert(nlp->fracvars != NULL);
3400 assert(nlp->fracvarssol != NULL);
3401 assert(nlp->fracvarsfrac != NULL);
3402
3403 /* insert candidate in candidate list */
3404 branchpriority = SCIPvarGetBranchPriority(var);
3405 insertpos = nlp->nfracvars;
3406 nlp->nfracvars++;
3407 if( branchpriority > maxpriority )
3408 {
3409 /* candidate has higher priority than the current maximum:
3410 * move it to the front and declare it to be the single best candidate
3411 */
3412 if( insertpos != 0 )
3413 {
3414 nlp->fracvars[insertpos] = nlp->fracvars[0];
3415 nlp->fracvarssol[insertpos] = nlp->fracvarssol[0];
3416 nlp->fracvarsfrac[insertpos] = nlp->fracvarsfrac[0];
3417 insertpos = 0;
3418 }
3419 nlp->npriofracvars = 1;
3420 maxpriority = branchpriority;
3421 }
3422 else if( branchpriority == maxpriority )
3423 {
3424 /* candidate has equal priority as the current maximum:
3425 * move away the first non-maximal priority candidate, move the current candidate to the correct
3426 * slot (binaries first) and increase the number of maximal priority candidates
3427 */
3428 if( insertpos != nlp->npriofracvars )
3429 {
3430 nlp->fracvars[insertpos] = nlp->fracvars[nlp->npriofracvars];
3431 nlp->fracvarssol[insertpos] = nlp->fracvarssol[nlp->npriofracvars];
3432 nlp->fracvarsfrac[insertpos] = nlp->fracvarsfrac[nlp->npriofracvars];
3433 insertpos = nlp->npriofracvars;
3434 }
3435 ++nlp->npriofracvars;
3436 }
3437 nlp->fracvars[insertpos] = var;
3438 nlp->fracvarssol[insertpos] = primsol;
3439 nlp->fracvarsfrac[insertpos] = frac;
3440
3441 SCIPsetDebugMsg(set, " -> candidate %d: var=<%s>, sol=%g, frac=%g, prio=%d (max: %d) -> pos %d\n",
3442 nlp->nfracvars, SCIPvarGetName(var), primsol, frac, branchpriority, maxpriority, insertpos);
3443 }
3444
3445 nlp->validfracvars = stat->nnlps;
3446 }
3447 assert(0 <= nlp->npriofracvars);
3448 assert(nlp->npriofracvars <= nlp->nfracvars);
3449
3450 SCIPsetDebugMsg(set, " -> %d fractional variables (%d of maximal priority)\n", nlp->nfracvars, nlp->npriofracvars);
3451
3452 return SCIP_OKAY;
3453}
3454
3455/** event handling for variable events */
3456static
3458{
3459 SCIP_EVENTTYPE etype;
3460 SCIP_VAR* var;
3461
3462 assert(scip != NULL);
3463 assert(eventhdlr != NULL);
3464 assert(event != NULL);
3465 assert(eventdata != NULL);
3466
3467 assert((SCIP_NLP*)eventdata == scip->nlp);
3468
3469 etype = SCIPeventGetType(event);
3470 var = SCIPeventGetVar(event);
3471
3472 if( SCIP_EVENTTYPE_VARADDED & etype )
3473 {
3474 SCIPdebugMessage("-> handling varadd event, variable <%s>\n", SCIPvarGetName(var) );
3475 SCIP_CALL( SCIPnlpAddVar(scip->nlp, SCIPblkmem(scip), scip->set, var) );
3476 }
3477 else if( SCIP_EVENTTYPE_VARDELETED & etype )
3478 {
3479 SCIPdebugMessage("-> handling vardel event, variable <%s>\n", SCIPvarGetName(var) );
3480 SCIP_CALL( SCIPnlpDelVar(scip->nlp, SCIPblkmem(scip), scip->set, scip->stat, scip->eventqueue, scip->lp, var) );
3481 }
3482 else if( SCIP_EVENTTYPE_VARFIXED & etype )
3483 {
3484 /* variable was fixed, aggregated, or multi-aggregated */
3485 /* TODO is this ever happening? that is, can we have changes in a variable status during solve? */
3486 SCIPdebugMessage("-> handling variable fixation event, variable <%s>\n", SCIPvarGetName(var) );
3487 SCIP_CALL( nlpRemoveFixedVar(scip->nlp, SCIPblkmem(scip), scip->set, scip->stat, scip->eventqueue, scip->lp, var) );
3488 }
3489 else if( SCIP_EVENTTYPE_BOUNDCHANGED & etype )
3490 {
3491 SCIPdebugMessage("-> handling bound changed event %" SCIP_EVENTTYPE_FORMAT ", variable <%s>\n", etype, SCIPvarGetName(var) );
3493 }
3494 else if( SCIP_EVENTTYPE_OBJCHANGED & etype )
3495 {
3496 SCIPdebugMessage("-> handling objchg event, variable <%s>\n", SCIPvarGetName(var) );
3497 SCIP_CALL( nlpUpdateObjCoef(scip->set, scip->nlp, var) );
3498 }
3499 else
3500 {
3501 SCIPerrorMessage("unexpected event %" SCIP_EVENTTYPE_FORMAT " on variable <%s>\n", etype, SCIPvarGetName(var) );
3502 return SCIP_ERROR;
3503 }
3504
3505 return SCIP_OKAY;
3506}
3507
3508
3509/*
3510 * public NLP methods
3511 */
3512
3513/** includes event handler that is used by NLP */
3515 SCIP_SET* set, /**< global SCIP settings */
3516 BMS_BLKMEM* blkmem /**< block memory */
3517 )
3518{
3519 SCIP_EVENTHDLR* eventhdlr;
3520
3521 assert(set != NULL);
3522 assert(blkmem != NULL);
3523 assert(set->stage == SCIP_STAGE_INIT);
3524
3525 /* check whether event handler is already present */
3527 {
3528 SCIPerrorMessage("event handler <" EVENTHDLR_NAME "> already included.\n");
3529 return SCIP_INVALIDDATA;
3530 }
3531
3533 NULL, NULL, NULL, NULL, NULL, NULL, NULL, eventExecNlp, NULL) );
3534 SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
3535
3536 return SCIP_OKAY;
3537} /*lint !e715*/
3538
3539/** construct a new empty NLP */
3541 SCIP_NLP** nlp, /**< NLP handler, call by reference */
3542 BMS_BLKMEM* blkmem, /**< block memory */
3543 SCIP_SET* set, /**< global SCIP settings */
3544 SCIP_STAT* stat, /**< problem statistics */
3545 const char* name, /**< problem name */
3546 int nvars_estimate /**< an estimate on the number of variables that may be added to the NLP later */
3547 )
3548{
3549 assert(nlp != NULL);
3550 assert(blkmem != NULL);
3551 assert(set != NULL);
3552 assert(stat != NULL);
3553 assert(name != NULL);
3554
3555 SCIP_ALLOC( BMSallocMemory(nlp) );
3556
3557 /* select NLP solver (if any available) and setup problem */
3558 if( set->nnlpis > 0 )
3559 {
3560 assert(set->nlp_solver != NULL);
3561 if( set->nlp_solver[0] == '\0' )
3562 { /* take solver with highest priority */
3563 assert(set->nlpis != NULL);
3564
3565 /* sort the NLPIs if necessary */
3566 if( !set->nlpissorted )
3568
3569 (*nlp)->solver = set->nlpis[0];
3570 }
3571 else
3572 { /* find user specified NLP solver */
3573 (*nlp)->solver = SCIPsetFindNlpi(set, set->nlp_solver);
3574 if( (*nlp)->solver == NULL )
3575 {
3576 SCIPerrorMessage("Selected NLP solver <%s> not available.\n", set->nlp_solver);
3577 return SCIP_PLUGINNOTFOUND;
3578 }
3579 }
3580 assert((*nlp)->solver != NULL);
3581 SCIP_CALL( SCIPnlpiCreateProblem(set, (*nlp)->solver, &(*nlp)->problem, name) );
3582 }
3583 else
3584 {
3585 /* maybe someone wanna use the NLP just to collect nonlinearities, but is not necessarily interesting on solving
3586 * so we allow this and just continue */
3587 (*nlp)->solver = NULL;
3588 (*nlp)->problem = NULL;
3589 }
3590
3591 /* status */
3592 (*nlp)->nunflushedvaradd = 0;
3593 (*nlp)->nunflushedvardel = 0;
3594 (*nlp)->nunflushednlrowadd = 0;
3595 (*nlp)->nunflushednlrowdel = 0;
3596 (*nlp)->indiving = FALSE;
3597
3598 /* variables in problem and NLPI problem */
3599 (*nlp)->nvars = 0;
3600 (*nlp)->sizevars = 0;
3601 (*nlp)->vars = NULL;
3602 SCIP_CALL( SCIPhashmapCreate(&(*nlp)->varhash, blkmem, nvars_estimate) );
3603
3604 (*nlp)->nvars_solver = 0;
3605 (*nlp)->sizevars_solver = 0;
3606 (*nlp)->varmap_nlp2nlpi = NULL;
3607 (*nlp)->varmap_nlpi2nlp = NULL;
3608
3609 /* nonlinear rows in problem and NLPI problem */
3610 (*nlp)->nnlrows = 0;
3611 (*nlp)->sizenlrows = 0;
3612 (*nlp)->nlrows = NULL;
3613 (*nlp)->nnlrowlinear = 0;
3614 (*nlp)->nnlrowconvexineq = 0;
3615 (*nlp)->nnlrownonconvexineq = 0;
3616 (*nlp)->nnlrownonlineareq = 0;
3617
3618 (*nlp)->nnlrows_solver = 0;
3619 (*nlp)->sizenlrows_solver = 0;
3620 (*nlp)->nlrowmap_nlpi2nlp = NULL;
3621
3622 /* objective function */
3623 (*nlp)->objflushed = TRUE;
3624 (*nlp)->divingobj = NULL;
3625
3626 /* initial guess */
3627 (*nlp)->haveinitguess = FALSE;
3628 (*nlp)->initialguess = NULL;
3629
3630 /* solution of NLP */
3631 (*nlp)->primalsolobjval = SCIP_INVALID;
3632 (*nlp)->solstat = SCIP_NLPSOLSTAT_UNKNOWN;
3633 (*nlp)->termstat = SCIP_NLPTERMSTAT_OTHER;
3634 (*nlp)->varlbdualvals = NULL;
3635 (*nlp)->varubdualvals = NULL;
3636
3637 /* event handling: catch variable addition and deletion events */
3638 (*nlp)->eventhdlr = SCIPsetFindEventhdlr(set, EVENTHDLR_NAME);
3639 if( (*nlp)->eventhdlr == NULL )
3640 {
3641 SCIPerrorMessage("NLP eventhandler <" EVENTHDLR_NAME "> not found.\n");
3642 return SCIP_PLUGINNOTFOUND;
3643 }
3644 SCIP_CALL( SCIPeventfilterAdd(set->scip->eventfilter, blkmem, set,
3646 (*nlp)->eventhdlr, (SCIP_EVENTDATA*)(*nlp), &(*nlp)->globalfilterpos) );
3647
3648 /* fractional variables in last NLP solution */
3649 (*nlp)->fracvars = NULL;
3650 (*nlp)->fracvarssol = NULL;
3651 (*nlp)->fracvarsfrac = NULL;
3652 (*nlp)->nfracvars = 0;
3653 (*nlp)->npriofracvars = 0;
3654 (*nlp)->fracvarssize = 0;
3655 (*nlp)->validfracvars = -1;
3656
3657 /* miscellaneous */
3658 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlp)->name, name, strlen(name)+1) );
3659
3660 return SCIP_OKAY;
3661}
3662
3663/** frees NLP data object */
3665 SCIP_NLP** nlp, /**< pointer to NLP data object */
3666 BMS_BLKMEM* blkmem, /**< block memory */
3667 SCIP_SET* set, /**< global SCIP settings */
3668 SCIP_STAT* stat, /**< problem statistics */
3669 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3670 SCIP_LP* lp /**< SCIP LP, needed for releasing variables */
3671 )
3672{
3673 assert(nlp != NULL);
3674 assert(*nlp != NULL);
3675 assert(blkmem != NULL);
3676 assert(set != NULL);
3677
3678 /* drop fractional variables */
3679 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvars, (*nlp)->fracvarssize);
3680 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvarssol, (*nlp)->fracvarssize);
3681 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvarsfrac, (*nlp)->fracvarssize);
3682
3683 /* drop global events (variable addition and deletion) */
3684 SCIP_CALL( SCIPeventfilterDel(set->scip->eventfilter, blkmem, set,
3686 (*nlp)->eventhdlr, (SCIP_EVENTDATA*)(*nlp), (*nlp)->globalfilterpos) );
3687
3688 SCIP_CALL( SCIPnlpReset(*nlp, blkmem, set, stat, eventqueue, lp) );
3689 assert((*nlp)->nnlrows == 0);
3690 assert((*nlp)->nnlrows_solver == 0);
3691 assert((*nlp)->nvars == 0);
3692 assert((*nlp)->nvars_solver == 0);
3693 assert((*nlp)->initialguess == NULL);
3694
3695 BMSfreeBlockMemoryArray(blkmem, &(*nlp)->name, strlen((*nlp)->name)+1);
3696
3697 /* free nonlinear rows arrays */
3698 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->nlrowmap_nlpi2nlp, (*nlp)->sizenlrows_solver);
3699 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->nlrows, (*nlp)->sizenlrows);
3700
3701 /* free variables arrays */
3702 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varmap_nlp2nlpi, (*nlp)->sizevars);
3703 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varmap_nlpi2nlp, (*nlp)->sizevars_solver);
3704 SCIPhashmapFree(&(*nlp)->varhash);
3705 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->vars, (*nlp)->sizevars);
3706 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varlbdualvals, (*nlp)->sizevars);
3707 BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varubdualvals, (*nlp)->sizevars);
3708
3709 /* free NLPI problem */
3710 if( (*nlp)->problem != NULL )
3711 {
3712 SCIP_CALL( SCIPnlpiFreeProblem(set, (*nlp)->solver, &(*nlp)->problem) );
3713 }
3714
3715 /* free NLP data structure */
3716 BMSfreeMemory(nlp);
3717
3718 return SCIP_OKAY;
3719}
3720
3721/** resets the NLP to the empty NLP by removing all variables and rows from NLP,
3722 * releasing all rows, and flushing the changes to the NLP solver
3723 */
3725 SCIP_NLP* nlp, /**< NLP data */
3726 BMS_BLKMEM* blkmem, /**< block memory */
3727 SCIP_SET* set, /**< global SCIP settings */
3728 SCIP_STAT* stat, /**< problem statistics data */
3729 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3730 SCIP_LP* lp /**< SCIP LP, needed for releasing variables */
3731 )
3732{
3733 int i;
3734
3735 assert(nlp != NULL);
3736 assert(blkmem != NULL);
3737 assert(set != NULL);
3738
3739 if( nlp->indiving )
3740 {
3741 SCIP_CALL( SCIPnlpEndDive(nlp, blkmem, set, stat) );
3742 }
3743
3746
3748 nlp->haveinitguess = FALSE;
3749
3750 for(i = nlp->nnlrows - 1; i >= 0; --i)
3751 {
3752 SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, stat, i) );
3753 }
3754
3755 for(i = nlp->nvars - 1; i >= 0; --i)
3756 {
3757 SCIP_CALL( nlpDelVarPos(nlp, blkmem, set, stat, eventqueue, lp, i) );
3758 }
3759
3760 SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set, stat) );
3761
3762 return SCIP_OKAY;
3763}
3764
3765/** currently a dummy function that always returns TRUE */
3767 SCIP_NLP* nlp /**< NLP data */
3768 )
3769{
3770 assert(nlp != NULL);
3771 return TRUE;
3772} /*lint !e715*/
3773
3774/** ensures, that variables array of NLP can store at least num entries */
3776 SCIP_NLP* nlp, /**< NLP data */
3777 BMS_BLKMEM* blkmem, /**< block memory */
3778 SCIP_SET* set, /**< global SCIP settings */
3779 int num /**< minimum number of entries to store */
3780 )
3781{
3782 assert(nlp != NULL);
3783 assert(blkmem != NULL);
3784 assert(set != NULL);
3785 assert(nlp->nvars <= nlp->sizevars);
3786
3787 if( num > nlp->sizevars )
3788 {
3789 int newsize;
3790
3791 newsize = SCIPsetCalcMemGrowSize(set, num);
3792 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->vars, nlp->sizevars, newsize) );
3793 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varmap_nlp2nlpi, nlp->sizevars, newsize) );
3794 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varlbdualvals, nlp->sizevars, newsize) );
3795 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varubdualvals, nlp->sizevars, newsize) );
3796 if( nlp->initialguess != NULL )
3797 {
3798 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->initialguess, nlp->sizevars, newsize) );
3799 }
3800
3801 nlp->sizevars = newsize;
3802 }
3803 assert(num <= nlp->sizevars);
3804
3805 return SCIP_OKAY;
3806}
3807
3808/** adds a variable to the NLP and captures the variable */
3810 SCIP_NLP* nlp, /**< NLP data */
3811 BMS_BLKMEM* blkmem, /**< block memory */
3812 SCIP_SET* set, /**< global SCIP settings */
3813 SCIP_VAR* var /**< variable */
3814 )
3815{
3816 assert(nlp != NULL);
3817 assert(blkmem != NULL);
3818 assert(set != NULL);
3819 assert(var != NULL);
3820 assert(SCIPvarIsTransformed(var));
3821 assert(!SCIPhashmapExists(nlp->varhash, var));
3822
3823 if( nlp->indiving )
3824 {
3825 SCIPerrorMessage("cannot add variable during NLP diving\n");
3826 return SCIP_ERROR;
3827 }
3828
3829 SCIP_CALL( nlpAddVars(nlp, blkmem, set, 1, &var) );
3830
3831 return SCIP_OKAY;
3832}
3833
3834/** adds a set of variables to the NLP and captures the variables */
3836 SCIP_NLP* nlp, /**< NLP data */
3837 BMS_BLKMEM* blkmem, /**< block memory */
3838 SCIP_SET* set, /**< global SCIP settings */
3839 int nvars, /**< number of variables to add */
3840 SCIP_VAR** vars /**< variables to add */
3841 )
3842{
3843 assert(nlp != NULL);
3844 assert(blkmem != NULL);
3845 assert(set != NULL);
3846 assert(vars != NULL || nvars == 0);
3847
3848 if( nlp->indiving && nvars > 0)
3849 {
3850 SCIPerrorMessage("cannot add variables during NLP diving\n");
3851 return SCIP_ERROR;
3852 }
3853
3854 SCIP_CALL( nlpAddVars(nlp, blkmem, set, nvars, vars) );
3855
3856 return SCIP_OKAY;
3857}
3858
3859/** deletes a variable from the NLP and releases the variable */
3861 SCIP_NLP* nlp, /**< NLP data */
3862 BMS_BLKMEM* blkmem, /**< block memory */
3863 SCIP_SET* set, /**< global SCIP settings */
3864 SCIP_STAT* stat, /**< problem statistics data */
3865 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3866 SCIP_LP* lp, /**< SCIP LP, needed to release variable */
3867 SCIP_VAR* var /**< variable */
3868 )
3869{
3870 int varpos;
3871
3872 assert(nlp != NULL);
3873 assert(blkmem != NULL);
3874 assert(set != NULL);
3875 assert(var != NULL);
3876
3877 if( !SCIPhashmapExists(nlp->varhash, var) )
3878 {
3879 SCIPerrorMessage("variable <%s> not found in NLP, cannot delete\n", SCIPvarGetName(var));
3880 return SCIP_ERROR;
3881 }
3882
3883 if( nlp->indiving )
3884 {
3885 SCIPerrorMessage("cannot delete variable during NLP diving\n");
3886 return SCIP_ERROR;
3887 }
3888
3889 varpos = SCIPhashmapGetImageInt(nlp->varhash, var);
3890
3891 SCIP_CALL( nlpDelVarPos(nlp, blkmem, set, stat, eventqueue, lp, varpos) );
3892
3893 return SCIP_OKAY;
3894}
3895
3896/** ensures, that nonlinear rows array of NLP can store at least num entries */
3898 SCIP_NLP* nlp, /**< NLP data */
3899 BMS_BLKMEM* blkmem, /**< block memory */
3900 SCIP_SET* set, /**< global SCIP settings */
3901 int num /**< minimum number of entries to store */
3902 )
3903{
3904 assert(nlp != NULL);
3905 assert(blkmem != NULL);
3906 assert(set != NULL);
3907 assert(nlp->nnlrows <= nlp->sizenlrows);
3908
3909 if( num > nlp->sizenlrows )
3910 {
3911 int newsize;
3912
3913 newsize = SCIPsetCalcMemGrowSize(set, num);
3914 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->nlrows, nlp->sizenlrows, newsize) );
3915
3916 nlp->sizenlrows = newsize;
3917 }
3918 assert(num <= nlp->sizenlrows);
3919
3920 return SCIP_OKAY;
3921}
3922
3923/** adds a nonlinear row to the NLP and captures it
3924 *
3925 * all variables of the row need to be present in the NLP
3926 */
3928 SCIP_NLP* nlp, /**< NLP data */
3929 BMS_BLKMEM* blkmem, /**< block memory */
3930 SCIP_SET* set, /**< global SCIP settings */
3931 SCIP_STAT* stat, /**< problem statistics data */
3932 SCIP_NLROW* nlrow /**< nonlinear row */
3933 )
3934{
3935 assert(nlp != NULL);
3936 assert(nlrow != NULL);
3937
3938 if( nlp->indiving )
3939 {
3940 SCIPerrorMessage("cannot add row during NLP diving\n");
3941 return SCIP_ERROR;
3942 }
3943
3944 SCIP_CALL( nlpAddNlRows(nlp, blkmem, set, stat, 1, &nlrow) );
3945
3946 return SCIP_OKAY;
3947}
3948
3949/** adds nonlinear rows to the NLP and captures them
3950 *
3951 * all variables of the row need to be present in the NLP
3952 */
3954 SCIP_NLP* nlp, /**< NLP data */
3955 BMS_BLKMEM* blkmem, /**< block memory */
3956 SCIP_SET* set, /**< global SCIP settings */
3957 SCIP_STAT* stat, /**< problem statistics data */
3958 int nnlrows, /**< number of rows to add */
3959 SCIP_NLROW** nlrows /**< rows to add */
3960 )
3961{
3962 assert(nlp != NULL);
3963 assert(nlrows != NULL || nnlrows == 0);
3964
3965 if( nnlrows == 0 )
3966 return SCIP_OKAY;
3967
3968 if( nlp->indiving )
3969 {
3970 SCIPerrorMessage("cannot add rows during NLP diving\n");
3971 return SCIP_ERROR;
3972 }
3973
3974 SCIP_CALL( nlpAddNlRows(nlp, blkmem, set, stat, nnlrows, nlrows) );
3975
3976 return SCIP_OKAY;
3977}
3978
3979/** deletes a nonlinear row from the NLP
3980 *
3981 * does nothing if nonlinear row is not in NLP
3982 */
3984 SCIP_NLP* nlp, /**< NLP data */
3985 BMS_BLKMEM* blkmem, /**< block memory */
3986 SCIP_SET* set, /**< global SCIP settings */
3987 SCIP_STAT* stat, /**< problem statistics data */
3988 SCIP_NLROW* nlrow /**< nonlinear row */
3989 )
3990{
3991 assert(nlp != NULL);
3992 assert(blkmem != NULL);
3993 assert(set != NULL);
3994 assert(nlrow != NULL);
3995
3996 /* if row not in NLP, nothing to do */
3997 if( nlrow->nlpindex == -1 )
3998 return SCIP_OKAY;
3999
4000 assert(nlrow->nlpindex >= 0);
4001 assert(nlrow->nlpindex < nlp->nnlrows);
4002
4003 if( nlp->indiving )
4004 {
4005 SCIPerrorMessage("cannot delete row during NLP diving\n");
4006 return SCIP_ERROR;
4007 }
4008
4009 SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, stat, nlrow->nlpindex) );
4010
4011 return SCIP_OKAY;
4012}
4013
4014/** applies all cached changes to the NLP solver */
4016 SCIP_NLP* nlp, /**< current NLP data */
4017 BMS_BLKMEM* blkmem, /**< block memory */
4018 SCIP_SET* set, /**< global SCIP settings */
4019 SCIP_STAT* stat /**< problem statistics */
4020 )
4021{
4022 assert(nlp != NULL);
4023 assert(blkmem != NULL);
4024 assert(set != NULL);
4025
4026 if( nlp->indiving )
4027 {
4028 SCIPerrorMessage("cannot flush NLP during NLP diving\n");
4029 return SCIP_ERROR;
4030 }
4031
4032 /* flush removals of nonlinear rows and variables */
4033 SCIP_CALL( nlpFlushNlRowDeletions(nlp, blkmem, set) );
4034 SCIP_CALL( nlpFlushVarDeletions(nlp, blkmem, set) );
4035 assert(nlp->nunflushednlrowdel == 0);
4036 assert(nlp->nunflushedvardel == 0);
4037
4038 /* flush addition of variables, objective, and addition of rows */
4039 SCIP_CALL( nlpFlushVarAdditions(nlp, blkmem, set) );
4040 SCIP_CALL( nlpFlushObjective(nlp, blkmem, set) );
4041 SCIP_CALL( nlpFlushNlRowAdditions(nlp, blkmem, set, stat) );
4042 assert(nlp->nunflushedvaradd == 0);
4043 assert(nlp->objflushed == TRUE);
4044 assert(nlp->nunflushednlrowadd == 0);
4045
4046 assert(nlp->nvars == nlp->nvars_solver);
4047 assert(nlp->nnlrows == nlp->nnlrows_solver);
4048
4049 return SCIP_OKAY;
4050}
4051
4052/** solves the NLP or diving NLP */
4054 SCIP_NLP* nlp, /**< NLP data */
4055 BMS_BLKMEM* blkmem, /**< block memory buffers */
4056 SCIP_SET* set, /**< global SCIP settings */
4057 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4058 SCIP_STAT* stat, /**< problem statistics */
4059 SCIP_PRIMAL* primal, /**< primal data */
4060 SCIP_TREE* tree, /**< branch and bound tree */
4061 SCIP_NLPPARAM* nlpparam /**< NLP solve parameters */
4062 )
4063{
4064 assert(nlp != NULL);
4065 assert(blkmem != NULL);
4066 assert(set != NULL);
4067 assert(stat != NULL);
4068
4069 if( !nlp->indiving )
4070 {
4071 SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set, stat) );
4072 }
4073
4074 SCIP_CALL( nlpSolve(nlp, blkmem, set, messagehdlr, stat, primal, tree, nlpparam) );
4075
4076 return SCIP_OKAY;
4077}
4078
4079/** gets objective value of current NLP */
4081 SCIP_NLP* nlp /**< current NLP data */
4082 )
4083{
4084 assert(nlp != NULL);
4085
4086 return nlp->primalsolobjval;
4087}
4088
4089/** gives current pseudo objective value */
4091 SCIP_NLP* nlp, /**< current NLP data */
4092 BMS_BLKMEM* blkmem, /**< block memory */
4093 SCIP_SET* set, /**< global SCIP settings */
4094 SCIP_STAT* stat, /**< problem statistics data */
4095 SCIP_PROB* prob, /**< SCIP problem */
4096 SCIP_PRIMAL* primal, /**< primal data */
4097 SCIP_TREE* tree, /**< branch and bound tree */
4098 SCIP_LP* lp, /**< SCIP LP */
4099 SCIP_Real* pseudoobjval /**< buffer to store pseudo objective value */
4100 )
4101{
4102 assert(nlp != NULL);
4103 assert(pseudoobjval != NULL);
4104
4105 if( nlp->divingobj != NULL )
4106 {
4107 assert(nlp->indiving);
4108 SCIP_CALL( SCIPnlrowGetPseudoActivity(nlp->divingobj, blkmem, set, stat, prob, primal, tree, lp, pseudoobjval) );
4109 }
4110 else
4111 {
4112 int i;
4113
4114 *pseudoobjval = 0.0;
4115 for( i = 0; i < nlp->nvars; ++i )
4116 *pseudoobjval += SCIPvarGetObj(nlp->vars[i]) * SCIPvarGetBestBoundLocal(nlp->vars[i]);
4117 }
4118
4119 return SCIP_OKAY;
4120}
4121
4122/** gets fractional variables of last NLP solution along with solution values and fractionalities
4123 */
4125 SCIP_NLP* nlp, /**< NLP data structure */
4126 BMS_BLKMEM* blkmem, /**< block memory */
4127 SCIP_SET* set, /**< global SCIP settings */
4128 SCIP_STAT* stat, /**< problem statistics */
4129 SCIP_VAR*** fracvars, /**< pointer to store the array of NLP fractional variables, or NULL */
4130 SCIP_Real** fracvarssol, /**< pointer to store the array of NLP fractional variables solution values, or NULL */
4131 SCIP_Real** fracvarsfrac, /**< pointer to store the array of NLP fractional variables fractionalities, or NULL */
4132 int* nfracvars, /**< pointer to store the number of NLP fractional variables , or NULL */
4133 int* npriofracvars /**< pointer to store the number of NLP fractional variables with maximal branching priority, or NULL */
4134 )
4135{
4136 assert(nlp != NULL);
4137
4138 SCIP_CALL( nlpCalcFracVars(nlp, blkmem, set, stat) );
4139 assert(nlp->fracvars != NULL);
4140 assert(nlp->fracvarssol != NULL);
4141 assert(nlp->fracvarsfrac != NULL);
4142
4143 if( fracvars != NULL )
4144 *fracvars = nlp->fracvars;
4145 if( fracvarssol != NULL )
4146 *fracvarssol = nlp->fracvarssol;
4147 if( fracvarsfrac != NULL )
4148 *fracvarsfrac = nlp->fracvarsfrac;
4149 if( nfracvars != NULL )
4150 *nfracvars = nlp->nfracvars;
4151 if( npriofracvars != NULL )
4152 *npriofracvars = nlp->npriofracvars;
4153
4154 return SCIP_OKAY;
4155}
4156
4157/** removes all redundant nonlinear rows */
4159 SCIP_NLP* nlp, /**< current NLP data */
4160 BMS_BLKMEM* blkmem, /**< block memory buffers */
4161 SCIP_SET* set, /**< global SCIP settings */
4162 SCIP_STAT* stat /**< problem statistics */
4163 )
4164{
4165 SCIP_NLPSOLSTAT solstatus;
4166 SCIP_Bool isredundant;
4167 int i;
4168
4169 assert(nlp != NULL);
4170 assert(blkmem != NULL);
4171 assert(set != NULL);
4172 assert(stat != NULL);
4173
4174 if( nlp->nnlrows == 0 )
4175 return SCIP_OKAY;
4176
4177 if( nlp->indiving )
4178 {
4179 SCIPerrorMessage("cannot remove redundant rows during NLP diving\n");
4180 return SCIP_ERROR;
4181 }
4182
4183 /* removing redundant rows should not change the solution status, so we reset it at the end */
4184 solstatus = nlp->solstat;
4185
4186 for( i = 0; i < nlp->nnlrows; ++i )
4187 {
4188 SCIP_CALL( SCIPnlrowIsRedundant(nlp->nlrows[i], blkmem, set, stat, &isredundant) );
4189 if( isredundant )
4190 {
4191 SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, stat, i) );
4192 }
4193 }
4194
4195 nlp->solstat = solstatus;
4196
4197 return SCIP_OKAY;
4198}
4199
4200/** set initial guess (approximate primal solution) for next solve
4201 *
4202 * array initguess must be NULL or have length at least SCIPnlpGetNVars()
4203 */
4205 SCIP_SET* set, /**< global SCIP settings */
4206 SCIP_NLP* nlp, /**< current NLP data */
4207 BMS_BLKMEM* blkmem, /**< block memory buffers */
4208 SCIP_Real* initguess /**< new initial guess, or NULL to clear previous one */
4209 )
4210{
4211 assert(nlp != NULL);
4212 assert(blkmem != NULL);
4213 assert(nlp->solver != NULL);
4214 assert(nlp->problem != NULL);
4215
4216 /* if user wants to let NLP solver choose start point, then invalidate current initial guess both in NLP and in NLPI */
4217 if( initguess == NULL )
4218 {
4219 nlp->haveinitguess = FALSE;
4221 return SCIP_OKAY;
4222 }
4223
4224 if( nlp->initialguess != NULL )
4225 {
4226 BMScopyMemoryArray(nlp->initialguess, initguess, nlp->nvars);
4227 }
4228 else
4229 {
4230 assert( nlp->sizevars >= nlp->nvars );
4232 BMScopyMemoryArray(nlp->initialguess, initguess, nlp->nvars);
4233 }
4234 nlp->haveinitguess = TRUE;
4235
4236 return SCIP_OKAY;
4237}
4238
4239/** writes NLP to a file */
4241 SCIP_NLP* nlp, /**< current NLP data */
4242 BMS_BLKMEM* blkmem, /**< block memory buffers */
4243 SCIP_SET* set, /**< global SCIP settings */
4244 SCIP_STAT* stat, /**< problem statistics */
4245 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4246 const char* fname /**< file name */
4247 )
4248{
4249 SCIP_RETCODE retcode = SCIP_OKAY;
4250 FILE* file;
4251 int i;
4252
4253 assert(nlp != NULL);
4254
4255 if( fname != NULL )
4256 {
4257 file = fopen(fname, "w");
4258 if( file == NULL )
4259 {
4260 SCIPerrorMessage("could not open file <%s> for writing\n", fname);
4261 return SCIP_FILECREATEERROR;
4262 }
4263 }
4264 else
4265 file = stdout;
4266
4267 SCIPmessageFPrintInfo(messagehdlr, file, "STATISTICS\n");
4268 SCIPmessageFPrintInfo(messagehdlr, file, " NLP name: %s\n", nlp->name);
4269 SCIPmessageFPrintInfo(messagehdlr, file, " Variables: %d\n", nlp->nvars);
4270 SCIPmessageFPrintInfo(messagehdlr, file, " Rows: %d\n", nlp->nnlrows);
4271
4272 SCIPmessageFPrintInfo(messagehdlr, file, "VARIABLES\n");
4273 for( i = 0; i < nlp->nvars; ++i )
4274 {
4275 SCIP_CALL( SCIPvarPrint(nlp->vars[i], set, messagehdlr, file) );
4276 }
4277
4278 SCIPmessageFPrintInfo(messagehdlr, file, "NONLINEAR ROWS\n");
4279 for( i = 0; i < nlp->nnlrows; ++i )
4280 {
4281 SCIPmessageFPrintInfo(messagehdlr, file, " ");
4282 SCIP_CALL_TERMINATE( retcode, SCIPnlrowPrint(nlp->nlrows[i], blkmem, set, stat, messagehdlr, file), TERMINATE );
4283 }
4284
4285 TERMINATE:
4286 if( fname != NULL )
4287 {
4288 fclose(file);
4289 }
4290
4291 return retcode;
4292}
4293
4294/** gets array with variables of the NLP */
4296 SCIP_NLP* nlp /**< current NLP data */
4297 )
4298{
4299 assert(nlp != NULL);
4300
4301 return nlp->vars;
4302}
4303
4304/** gets current number of variables in NLP */
4306 SCIP_NLP* nlp /**< current NLP data */
4307 )
4308{
4309 assert(nlp != NULL);
4310
4311 return nlp->nvars;
4312}
4313
4314/** computes for each variables the number of NLP rows in which the variable appears in a nonlinear var */
4316 SCIP_NLP* nlp, /**< current NLP data */
4317 BMS_BLKMEM* blkmem, /**< block memory buffers */
4318 SCIP_SET* set, /**< global SCIP settings */
4319 SCIP_STAT* stat, /**< problem statistics */
4320 int* nlcount /**< an array of length at least SCIPnlpGetNVars() to store nonlinearity counts of variables */
4321 )
4322{
4323 SCIP_NLROW* nlrow;
4324 SCIP_EXPRITER* it;
4325 SCIP_EXPR* expr;
4326 int varidx;
4327 int c;
4328
4329 assert(nlp != NULL);
4330 assert(nlcount != NULL || nlp->nvars == 0);
4331
4332 BMSclearMemoryArray(nlcount, nlp->nvars);
4333
4334 SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
4335
4336 for( c = 0; c < nlp->nnlrows; ++c )
4337 {
4338 nlrow = nlp->nlrows[c];
4339 assert(nlrow != NULL);
4340
4341 if( nlrow->expr == NULL )
4342 continue;
4343
4345 for( expr = nlrow->expr; !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
4346 {
4347 if( !SCIPexprIsVar(set, expr) )
4348 continue;
4349
4350 assert(SCIPhashmapExists(nlp->varhash, SCIPgetVarExprVar(expr)));
4351
4352 varidx = SCIPhashmapGetImageInt(nlp->varhash, SCIPgetVarExprVar(expr));
4353 assert(varidx < nlp->nvars);
4354 assert(nlcount != NULL);
4355 ++nlcount[varidx];
4356 }
4357 }
4358
4359 SCIPexpriterFree(&it);
4360
4361 return SCIP_OKAY;
4362}
4363
4364
4365/** indicates whether there exists a row that contains a continuous variable in a nonlinear term
4366 *
4367 * @note The method may have to touch every row and nonlinear term to compute its result.
4368 */
4370 SCIP_NLP* nlp, /**< current NLP data */
4371 BMS_BLKMEM* blkmem, /**< block memory buffers */
4372 SCIP_SET* set, /**< global SCIP settings */
4373 SCIP_STAT* stat, /**< problem statistics */
4374 SCIP_Bool* result /**< buffer to store whether continuous variable present in an expression of any row */
4375 )
4376{
4377 SCIP_NLROW* nlrow;
4378 SCIP_EXPRITER* it;
4379 SCIP_EXPR* expr;
4380 int c;
4381
4382 assert(nlp != NULL);
4383
4384 SCIP_CALL( SCIPexpriterCreate(stat, blkmem, &it) );
4386
4387 *result = FALSE;
4388 for( c = 0; c < nlp->nnlrows && !*result; ++c )
4389 {
4390 nlrow = nlp->nlrows[c];
4391 assert(nlrow != NULL);
4392
4393 if( nlrow->expr == NULL )
4394 continue;
4395
4396 for( expr = SCIPexpriterRestartDFS(it, nlrow->expr); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) )
4397 {
4399 {
4400 *result = TRUE;
4401 break;
4402 }
4403 }
4404 }
4405
4406 SCIPexpriterFree(&it);
4407
4408 return SCIP_OKAY;
4409}
4410
4411/** gives dual solution values associated with lower bounds of NLP variables */
4413 SCIP_NLP* nlp /**< current NLP data */
4414 )
4415{
4416 assert(nlp != NULL);
4417
4418 return nlp->varlbdualvals;
4419}
4420
4421/** gives dual solution values associated with upper bounds of NLP variables */
4423 SCIP_NLP* nlp /**< current NLP data */
4424 )
4425{
4426 assert(nlp != NULL);
4427
4428 return nlp->varubdualvals;
4429}
4430
4431/** gets array with nonlinear rows of the NLP */
4433 SCIP_NLP* nlp /**< current NLP data */
4434 )
4435{
4436 assert(nlp != NULL);
4437
4438 return nlp->nlrows;
4439}
4440
4441/** gets current number of nonlinear rows in NLP */
4443 SCIP_NLP* nlp /**< current NLP data */
4444 )
4445{
4446 assert(nlp != NULL);
4447
4448 return nlp->nnlrows;
4449}
4450
4451/** gets statistics on convexity of nonlinear rows in NLP */
4453 SCIP_NLP* nlp, /**< current NLP data */
4454 int* nlinear, /**< buffer to store number of linear rows in NLP, or NULL */
4455 int* nconvexineq, /**< buffer to store number of convex inequalities in NLP, or NULL */
4456 int* nnonconvexineq, /**< buffer to store number of nonconvex inequalities in NLP, or NULL */
4457 int* nnonlineareq /**< buffer to store number of nonlinear equalities or ranged rows in NLP, or NULL */
4458 )
4459{
4460 assert(nlp != NULL);
4461
4462 if( nlinear != NULL )
4463 *nlinear = nlp->nnlrowlinear;
4464
4465 if( nconvexineq != NULL )
4466 *nconvexineq = nlp->nnlrowconvexineq;
4467
4468 if( nnonconvexineq != NULL )
4469 *nnonconvexineq = nlp->nnlrownonconvexineq;
4470
4471 if( nnonlineareq )
4472 *nnonlineareq = nlp->nnlrownonlineareq;
4473}
4474
4475/** gets the NLP solver interface */
4477 SCIP_NLP* nlp /**< current NLP data */
4478 )
4479{
4480 assert(nlp != NULL);
4481
4482 return nlp->solver;
4483}
4484
4485/** gets the NLP problem in the solver interface */
4487 SCIP_NLP* nlp /**< current NLP data */
4488 )
4489{
4490 assert(nlp != NULL);
4491
4492 return nlp->problem;
4493}
4494
4495/** indicates whether NLP is currently in diving mode */
4497 SCIP_NLP* nlp /**< current NLP data */
4498 )
4499{
4500 assert(nlp != NULL);
4501
4502 return nlp->indiving;
4503}
4504
4505/** gets solution status of current NLP */
4507 SCIP_NLP* nlp /**< current NLP data */
4508 )
4509{
4510 assert(nlp != NULL);
4511
4512 return nlp->solstat;
4513}
4514
4515/** gets termination status of last NLP solve */
4517 SCIP_NLP* nlp /**< current NLP data */
4518 )
4519{
4520 assert(nlp != NULL);
4521
4522 return nlp->termstat;
4523}
4524
4525/** gives statistics (number of iterations, solving time, ...) of last NLP solve */
4527 SCIP_SET* set, /**< global SCIP settings */
4528 SCIP_NLP* nlp, /**< pointer to NLP datastructure */
4529 SCIP_NLPSTATISTICS* statistics /**< pointer to store statistics */
4530 )
4531{
4532 assert(nlp != NULL);
4533 assert(nlp->solver != NULL);
4534 assert(nlp->problem != NULL);
4535 assert(statistics != NULL);
4536
4537 SCIP_CALL( SCIPnlpiGetStatistics(set, nlp->solver, nlp->problem, statistics) );
4538
4539 return SCIP_OKAY;
4540}
4541
4542/** indicates whether a solution for the current NLP is available
4543 *
4544 * The solution may be optimal, feasible, or infeasible.
4545 * Thus, returns whether the NLP solution status is at most \ref SCIP_NLPSOLSTAT_LOCINFEASIBLE.
4546 */
4548 SCIP_NLP* nlp /**< current NLP data */
4549 )
4550{
4551 assert(nlp != NULL);
4552
4554}
4555
4556/*
4557 * NLP diving methods
4558 */
4559
4560/** signals start of diving */
4562 SCIP_NLP* nlp, /**< current NLP data */
4563 BMS_BLKMEM* blkmem, /**< block memory buffers */
4564 SCIP_SET* set, /**< global SCIP settings */
4565 SCIP_STAT* stat /**< problem statistics */
4566 )
4567{
4568 assert(nlp != NULL);
4569
4570 if( nlp->indiving )
4571 {
4572 SCIPerrorMessage("NLP is already in diving mode\n");
4573 return SCIP_ERROR;
4574 }
4575
4576 if( nlp->solver == NULL )
4577 {
4578 /* In diving mode we do not cache changes but put them directly in the NLPI problem, which does not exist if there is no solver.
4579 * So we forbid diving of no solver is available. */
4580 SCIPerrorMessage("Cannot start diving if no NLP solver is available\n");
4581 return SCIP_ERROR;
4582 }
4583
4584 SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set, stat) );
4585
4586 nlp->indiving = TRUE;
4587
4588 return SCIP_OKAY;
4589}
4590
4591/** resets the bound and objective changes made during diving and disables diving mode */
4593 SCIP_NLP* nlp, /**< current NLP data */
4594 BMS_BLKMEM* blkmem, /**< block memory */
4595 SCIP_SET* set, /**< global SCIP settings */
4596 SCIP_STAT* stat /**< problem statistics data */
4597 )
4598{
4599 int i;
4600 int* varidx;
4601 SCIP_Real* varlb;
4602 SCIP_Real* varub;
4603
4604 assert(nlp != NULL);
4605 assert(set != NULL);
4606 assert(nlp->nvars == nlp->nvars_solver);
4607
4608 if( !nlp->indiving )
4609 {
4610 SCIPerrorMessage("NLP not in diving mode, cannot end dive\n");
4611 return SCIP_ERROR;
4612 }
4613
4614 assert(nlp->solver != NULL);
4615 assert(nlp->problem != NULL);
4616
4617 /* reset variable bounds in NLPI problem to their current values */
4618 SCIP_CALL( SCIPsetAllocBufferArray(set, &varidx, nlp->nvars) );
4619 SCIP_CALL( SCIPsetAllocBufferArray(set, &varlb, nlp->nvars) );
4620 SCIP_CALL( SCIPsetAllocBufferArray(set, &varub, nlp->nvars) );
4621 for( i = 0; i < nlp->nvars; ++i )
4622 {
4623 varidx[i] = i;
4624 varlb[i] = SCIPvarGetLbLocal(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
4625 varub[i] = SCIPvarGetUbLocal(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
4626 }
4627
4628 SCIP_CALL( SCIPnlpiChgVarBounds(set, nlp->solver, nlp->problem, nlp->nvars, varidx, varlb, varub) );
4629
4630 SCIPsetFreeBufferArray(set, &varidx);
4631 SCIPsetFreeBufferArray(set, &varlb);
4632 SCIPsetFreeBufferArray(set, &varub);
4633
4634 /* clear diving objective, if one was used (i.e., if SCIPnlpChgVarObjDive had been called)
4635 * the objective in the NLPI will be reset in the next flush */
4636 if( nlp->divingobj != NULL )
4637 {
4638 SCIP_CALL( SCIPnlrowRelease(&nlp->divingobj, blkmem, set, stat) );
4639 assert(nlp->divingobj == NULL);
4640 assert(nlp->objflushed == FALSE);
4641 }
4642
4643 /* we do not have a valid solution anymore */
4647
4648 nlp->indiving = FALSE;
4649
4650 return SCIP_OKAY;
4651}
4652
4653/** changes coefficient of variable in diving NLP */
4655 SCIP_NLP* nlp, /**< current NLP data */
4656 BMS_BLKMEM* blkmem, /**< block memory */
4657 SCIP_SET* set, /**< global SCIP settings */
4658 SCIP_STAT* stat, /**< problem statistics data */
4659 SCIP_VAR* var, /**< variable which coefficient to change */
4660 SCIP_Real coef /**< new linear coefficient of variable in objective */
4661 )
4662{
4663 int pos;
4664 int objidx;
4665
4666 assert(nlp != NULL);
4667 assert(var != NULL);
4668 assert(SCIPhashmapExists(nlp->varhash, var));
4669 assert(nlp->indiving);
4670 assert(nlp->solver != NULL);
4671 assert(nlp->problem != NULL);
4672
4673 /* get position of variable in NLPI problem */
4674 pos = SCIPhashmapGetImageInt(nlp->varhash, var);
4675 pos = nlp->varmap_nlp2nlpi[pos];
4676 assert(pos >= 0);
4677
4678 /* set coefficient in NLPI problem objective */
4679 objidx = -1;
4680 SCIP_CALL( SCIPnlpiChgLinearCoefs(set, nlp->solver, nlp->problem, objidx, 1, &pos, &coef) );
4681
4682 /* create an nlrow that holds the diving objective, if not done yet */
4683 if( nlp->divingobj == NULL )
4684 {
4685 SCIP_Real* coefs;
4686 int i;
4687
4688 SCIP_CALL( SCIPsetAllocBufferArray(set, &coefs, nlp->nvars) );
4689 for( i = 0; i < nlp->nvars; ++i )
4690 coefs[i] = SCIPvarGetObj(nlp->vars[i]);
4691
4692 SCIP_CALL( SCIPnlrowCreate(&nlp->divingobj, blkmem, set, stat, "divingobj",
4693 0.0, nlp->nvars, nlp->vars, coefs, NULL,
4696
4697 SCIPsetFreeBufferArray(set, &coefs);
4698 }
4699 assert(nlp->divingobj != NULL);
4700
4701 /* modify coefficient in diving objective */
4702 SCIP_CALL( SCIPnlrowChgLinearCoef(nlp->divingobj, blkmem, set, stat, nlp, var, coef) );
4703
4704 /* remember that we have to store objective after diving ended */
4705 nlp->objflushed = FALSE;
4706
4707 return SCIP_OKAY;
4708}
4709
4710/** changes bounds of variable in diving NLP */
4712 SCIP_SET* set, /**< global SCIP settings */
4713 SCIP_NLP* nlp, /**< current NLP data */
4714 SCIP_VAR* var, /**< variable which coefficient to change */
4715 SCIP_Real lb, /**< new lower bound of variable */
4716 SCIP_Real ub /**< new upper bound of variable */
4717 )
4718{
4719 int pos;
4720
4721 assert(nlp != NULL);
4722 assert(var != NULL);
4723 assert(SCIPhashmapExists(nlp->varhash, var));
4724 assert(nlp->indiving);
4725 assert(nlp->solver != NULL);
4726 assert(nlp->problem != NULL);
4727
4728 /* get position of variable in NLPI problem */
4729 pos = SCIPhashmapGetImageInt(nlp->varhash, var);
4730 pos = nlp->varmap_nlp2nlpi[pos];
4731 assert(pos >= 0);
4732
4733 /* set new bounds in NLPI */
4734 SCIP_CALL( SCIPnlpiChgVarBounds(set, nlp->solver, nlp->problem, 1, &pos, &lb, &ub) );
4735
4736 return SCIP_OKAY;
4737}
4738
4739/** changes bounds of a set of variables in diving NLP */
4741 SCIP_NLP* nlp, /**< current NLP data */
4742 SCIP_SET* set, /**< global SCIP settings */
4743 int nvars, /**< number of variables which bounds to change */
4744 SCIP_VAR** vars, /**< variables which bounds to change */
4745 SCIP_Real* lbs, /**< new lower bounds of variables */
4746 SCIP_Real* ubs /**< new upper bounds of variables */
4747 )
4748{
4749 int i;
4750 int* poss;
4751
4752 assert(nlp != NULL);
4753 assert(vars != NULL || nvars == 0);
4754 assert(nlp->indiving);
4755 assert(lbs != NULL || nvars == 0);
4756 assert(ubs != NULL || nvars == 0);
4757 assert(nlp->solver != NULL);
4758 assert(nlp->problem != NULL);
4759
4760 if( nvars == 0 )
4761 return SCIP_OKAY;
4762
4763 SCIP_CALL( SCIPsetAllocBufferArray(set, &poss, nvars) );
4764
4765 for( i = 0; i < nvars; ++i )
4766 {
4767 assert(SCIPhashmapExists(nlp->varhash, vars[i])); /*lint !e613*/
4768
4769 /* get position of variable in NLPI problem */
4770 poss[i] = SCIPhashmapGetImageInt(nlp->varhash, vars[i]); /*lint !e613*/
4771 poss[i] = nlp->varmap_nlp2nlpi[poss[i]];
4772 assert(poss[i] >= 0);
4773 }
4774
4775 /* set new bounds in NLPI */
4776 SCIP_CALL( SCIPnlpiChgVarBounds(set, nlp->solver, nlp->problem, nvars, poss, lbs, ubs) );
4777
4779
4780 return SCIP_OKAY;
4781}
4782
4783/** returns whether the objective function has been changed during diving */
4785 SCIP_NLP* nlp /**< current NLP data */
4786 )
4787{
4788 return nlp->divingobj != NULL;
4789}
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
internal methods for clocks and timing issues
#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_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:394
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_RETCODE SCIPeventhdlrCreate(SCIP_EVENTHDLR **eventhdlr, SCIP_SET *set, const char *name, const char *desc, SCIP_DECL_EVENTCOPY((*eventcopy)), SCIP_DECL_EVENTFREE((*eventfree)), SCIP_DECL_EVENTINIT((*eventinit)), SCIP_DECL_EVENTEXIT((*eventexit)), SCIP_DECL_EVENTINITSOL((*eventinitsol)), SCIP_DECL_EVENTEXITSOL((*eventexitsol)), SCIP_DECL_EVENTDELETE((*eventdelete)), SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event.c:123
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1979
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1886
internal methods for managing events
SCIP_RETCODE SCIPexprPrint(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_EXPR *expr)
Definition: expr.c:2266
SCIP_RETCODE SCIPexprEvalActivity(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_EXPR *rootexpr)
Definition: expr.c:2950
SCIP_RETCODE SCIPexprCopy(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_SET *targetset, SCIP_STAT *targetstat, BMS_BLKMEM *targetblkmem, SCIP_EXPR *sourceexpr, SCIP_EXPR **targetexpr, SCIP_DECL_EXPR_MAPEXPR((*mapexpr)), void *mapexprdata, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr.c:1878
SCIP_RETCODE SCIPexprSimplify(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_EXPR *rootexpr, SCIP_EXPR **simplified, SCIP_Bool *changed, SCIP_Bool *infeasible, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr.c:3189
SCIP_Bool SCIPexprIsVar(SCIP_SET *set, SCIP_EXPR *expr)
Definition: expr.c:2206
SCIP_Bool SCIPexprIsValue(SCIP_SET *set, SCIP_EXPR *expr)
Definition: expr.c:2218
SCIP_RETCODE SCIPexprRelease(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_EXPR **rootexpr)
Definition: expr.c:2074
SCIP_RETCODE SCIPexprEval(SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
Definition: expr.c:2654
private functions to work with algebraic expressions
void SCIPexpriterFree(SCIP_EXPRITER **iterator)
Definition: expriter.c:446
SCIP_RETCODE SCIPexpriterCreate(SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_EXPRITER **iterator)
Definition: expriter.c:427
handler for variable index expressions
SCIP_RETCODE SCIPcreateExprVaridx(SCIP *scip, SCIP_EXPR **expr, int varidx, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_varidx.c:220
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3111
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3077
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3426
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3195
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3442
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3360
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17042
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
const char * SCIPexprcurvGetName(SCIP_EXPRCURV curv)
Definition: exprcurv.c:586
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition: expriter.c:969
SCIP_EXPR * SCIPexpriterRestartDFS(SCIP_EXPRITER *iterator, SCIP_EXPR *expr)
Definition: expriter.c:630
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition: expr_value.c:294
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition: expr.c:3934
SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
Definition: expriter.c:858
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition: expr.c:4016
SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
Definition: expriter.c:501
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_RETCODE SCIPnlrowChgRhs(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real rhs)
Definition: nlp.c:1444
SCIP_RETCODE SCIPnlrowCreate(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: nlp.c:895
SCIP_RETCODE SCIPnlrowRelease(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: nlp.c:1154
SCIP_RETCODE SCIPnlrowEnsureLinearSize(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:1199
SCIP_RETCODE SCIPnlrowGetNLPFeasibility(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_NLP *nlp, SCIP_Real *feasibility)
Definition: nlp.c:1586
SCIP_RETCODE SCIPnlrowIsRedundant(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *isredundant)
Definition: nlp.c:1815
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:1936
SCIP_RETCODE SCIPnlrowChgLinearCoef(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_VAR *var, SCIP_Real coef)
Definition: nlp.c:1305
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1917
SCIP_RETCODE SCIPnlrowGetActivityBounds(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *minactivity, SCIP_Real *maxactivity)
Definition: nlp.c:1783
SCIP_RETCODE SCIPnlrowGetSolFeasibility(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Real *feasibility)
Definition: nlp.c:1761
SCIP_RETCODE SCIPnlrowAddLinearCoef(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_VAR *var, SCIP_Real val)
Definition: nlp.c:1224
SCIP_RETCODE SCIPnlrowChgLhs(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real lhs)
Definition: nlp.c:1418
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1907
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:1927
SCIP_RETCODE SCIPnlrowChgExpr(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_EXPR *expr)
Definition: nlp.c:1343
int SCIPnlrowGetNLPPos(SCIP_NLROW *nlrow)
Definition: nlp.c:1946
SCIP_RETCODE SCIPnlrowGetNLPActivity(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_NLP *nlp, SCIP_Real *activity)
Definition: nlp.c:1556
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1867
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1877
SCIP_RETCODE SCIPnlrowSimplify(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:1489
SCIP_RETCODE SCIPnlrowRecalcNLPActivity(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_NLP *nlp)
Definition: nlp.c:1504
SCIP_RETCODE SCIPnlrowGetSolActivity(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Real *activity)
Definition: nlp.c:1712
SCIP_RETCODE SCIPnlrowPrint(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlp.c:1092
SCIP_RETCODE SCIPnlrowChgConstant(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real constant)
Definition: nlp.c:1398
SCIP_Real SCIPnlrowGetDualsol(SCIP_NLROW *nlrow)
Definition: nlp.c:1969
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition: nlp.c:1857
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition: nlp.c:1897
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1956
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:1887
SCIP_RETCODE SCIPnlrowDelLinearCoef(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_VAR *var)
Definition: nlp.c:1272
void SCIPnlrowSetCurvature(SCIP_NLP *nlp, SCIP_SET *set, SCIP_NLROW *nlrow, SCIP_EXPRCURV curvature)
Definition: nlp.c:1470
SCIP_RETCODE SCIPnlrowCreateCopy(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLROW *sourcenlrow)
Definition: nlp.c:994
SCIP_RETCODE SCIPnlrowGetPseudoFeasibility(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Real *pseudofeasibility)
Definition: nlp.c:1687
SCIP_RETCODE SCIPnlrowCreateFromRow(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *row)
Definition: nlp.c:1029
SCIP_RETCODE SCIPnlrowRecalcPseudoActivity(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp)
Definition: nlp.c:1609
SCIP_RETCODE SCIPnlrowGetPseudoActivity(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_Real *pseudoactivity)
Definition: nlp.c:1656
void SCIPnlrowCapture(SCIP_NLROW *nlrow)
Definition: nlp.c:1142
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17292
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17213
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17238
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17302
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17351
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17258
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17248
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17902
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17768
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17558
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18164
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17581
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17946
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17604
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17439
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:18184
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17878
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17866
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18154
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18270
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11962
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18485
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17890
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
static SCIP_DECL_EVENTEXEC(eventExecNlp)
Definition: nlp.c:3457
SCIP_RETCODE SCIPnlpDelVar(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_VAR *var)</