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