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-2016 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file nlp.c
17  * @brief NLP management methods and datastructures
18  * @author Thorsten Gellermann
19  * @author Stefan Vigerske
20  *
21  * In NLP management, we have to differ between the current NLP and the NLPI problem
22  * stored in the NLP solver. All NLP methods affect the current NLP only.
23  * Before solving the current NLP with the NLP solver, the NLP solvers data
24  * has to be updated to the current NLP with a call to nlpFlush().
25  *
26  * @todo handle linear rows from LP
27  */
28 
29 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30 
31 
32 #include <assert.h>
33 #include <string.h>
34 
35 #include "scip/def.h"
36 #include "scip/set.h"
37 #include "scip/stat.h"
38 #include "scip/intervalarith.h"
39 #include "scip/clock.h"
40 #include "scip/nlp.h"
41 #include "scip/var.h"
42 #include "scip/prob.h"
43 #include "scip/sol.h"
44 #include "scip/event.h"
45 #include "scip/pub_lp.h"
46 #include "scip/pub_message.h"
47 #include "scip/pub_misc.h"
48 #include "nlpi/nlpi.h"
49 #include "nlpi/pub_expr.h"
50 #include "nlpi/struct_expr.h"
51 #include "scip/struct_nlp.h"
52 /* to get value of parameter "nlp/solver" and nlpis array and to get access to set->lp for releasing a variable */
53 #include "scip/struct_set.h"
54 /* to get nlp, set, ... in event handling */
55 #include "scip/struct_scip.h"
56 
57 /* defines */
58 
59 #define EVENTHDLR_NAME "nlpEventHdlr" /**< name of NLP event handler that catches variable events */
60 #define EVENTHDLR_DESC "handles all events necessary for maintaining NLP data" /**< description of NLP event handler */
61 #define ADDNAMESTONLPI 0 /**< whether to give variable and row names to NLPI */
62 
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66 
67 /* avoid inclusion of scip.h */
69  SCIP* scip /**< SCIP data structure */
70  );
71 
72 #ifdef __cplusplus
73 }
74 #endif
75 
76 /*
77  * forward declarations
78  */
79 
80 /** NLP event handler execution method */
81 static
82 SCIP_DECL_EVENTEXEC( eventExecNlp );
83 
84 /** announces, that a row of the NLP was modified
85  * adjusts status of current solution
86  * calling method has to ensure that change is passed to the NLPI!
87  */
88 static
90  SCIP_NLP* nlp, /**< current NLP data */
91  SCIP_SET* set, /**< global SCIP settings */
92  SCIP_STAT* stat, /**< problem statistics data */
93  SCIP_NLROW* nlrow /**< nonlinear row which was changed */
94  );
95 
96 /*
97  * public expression tree methods
98  */
99 
100 /** returns variables of expression tree */
102  SCIP_EXPRTREE* tree /**< expression tree */
103  )
104 {
105  assert(tree != NULL);
106 
107  return (SCIP_VAR**)tree->vars;
108 }
109 
110 /** stores array of variables in expression tree */
112  SCIP_EXPRTREE* tree, /**< expression tree */
113  int nvars, /**< number of variables */
114  SCIP_VAR** vars /**< variables */
115  )
116 {
117  assert(tree != NULL);
118  assert(vars != NULL || nvars == 0);
119 
120  if( nvars == 0 )
121  {
122  BMSfreeBlockMemoryArrayNull(tree->blkmem, &tree->vars, tree->nvars);
123  tree->nvars = 0;
124  }
125  else if( tree->vars != NULL )
126  {
127  SCIP_ALLOC( BMSreallocBlockMemoryArray(tree->blkmem, &tree->vars, tree->nvars, nvars) );
128  BMScopyMemoryArray(tree->vars, (void**)vars, nvars);
129  }
130  else
131  {
132  SCIP_ALLOC( BMSduplicateBlockMemoryArray(tree->blkmem, &tree->vars, (void**)vars, nvars) );
133  }
134 
135  tree->nvars = nvars;
136 
137  assert(tree->vars != NULL || tree->nvars == 0);
138 
139  return SCIP_OKAY;
140 }
141 
142 /** adds variables to the expression tree variables array */
144  SCIP_EXPRTREE* tree, /**< expression tree */
145  int nvars, /**< number of variables */
146  SCIP_VAR** vars /**< variables */
147  )
148 {
149  assert(tree != NULL);
150  assert(vars != NULL || nvars == 0);
151  assert(tree->vars != NULL || tree->nvars == 0);
152 
153  if( nvars == 0 )
154  return SCIP_OKAY;
155 
156  if( tree->nvars == 0 )
157  {
158  SCIP_ALLOC( BMSduplicateBlockMemoryArray(tree->blkmem, &tree->vars, (void**)vars, nvars) );
159  tree->nvars = nvars;
160  return SCIP_OKAY;
161  }
162 
163  /* append vars to tree->vars array */
164  SCIP_ALLOC( BMSreallocBlockMemoryArray(tree->blkmem, &tree->vars, tree->nvars, tree->nvars + nvars) );
165  BMScopyMemoryArray(&tree->vars[tree->nvars], (void**)vars, nvars); /*lint !e866*/
166  tree->nvars += nvars;
167 
168  return SCIP_OKAY;
169 }
170 
171 /** prints an expression tree using variable names from variables array */
173  SCIP_EXPRTREE* tree, /**< expression tree */
174  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
175  FILE* file /**< file for printing, or NULL for stdout */
176  )
177 {
178  const char** varnames;
179  int i;
180 
181  assert(tree != NULL);
182 
183  if( tree->nvars == 0 )
184  {
185  SCIPexprtreePrint(tree, messagehdlr, file, NULL, NULL);
186  return SCIP_OKAY;
187  }
188 
189  assert(tree->vars != NULL);
190 
191  SCIP_ALLOC( BMSallocMemoryArray(&varnames, tree->nvars) );
192  for( i = 0; i < tree->nvars; ++i )
193  varnames[i] = SCIPvarGetName((SCIP_VAR*)tree->vars[i]);
194 
195  SCIPexprtreePrint(tree, messagehdlr, file, varnames, NULL);
196 
197  BMSfreeMemoryArray(&varnames);
198 
199  return SCIP_OKAY;
200 }
201 
202 /** searches the variables array of an expression tree for a variable and returns its position, or -1 if not found
203  * Note that this is an O(n) operation!
204  */
206  SCIP_EXPRTREE* tree, /**< expression tree */
207  SCIP_VAR* var /**< variable to search for */
208  )
209 {
210  int i;
211 
212  assert(tree != NULL);
213  assert(var != NULL);
214 
215  for( i = 0; i < tree->nvars; ++i )
216  if( (SCIP_VAR*)tree->vars[i] == var )
217  return i;
218 
219  return -1;
220 }
221 
222 /** removes fixed variables from an expression tree, so that at exit all variables are active */
224  SCIP_EXPRTREE* tree, /**< expression tree */
225  SCIP_SET* set, /**< global SCIP settings */
226  SCIP_Bool* changed, /**< buffer to store whether the tree was changed, i.e., whether there was a fixed variable */
227  int* varpos, /**< array of length at least tree->nvars to store new indices of previously existing variables in expression tree, or -1 if variable was removed; set to NULL if not of interest */
228  int* newvarsstart /**< buffer to store index in tree->vars array where new variables begin, or NULL if not of interest */
229  )
230 {
231  SCIP_HASHMAP* varhash;
232  int i;
233  int j;
234  int nvarsold;
235  SCIP_VAR* var;
236  SCIP_Real scalar;
237  SCIP_Real constant;
238  SCIP_EXPR** replaceexprs;
239  SCIP_Bool havefixedvar;
240  int idx;
241  int* newpos;
242  int offset;
243 
244  assert(tree != NULL);
245  assert(tree->vars != NULL || tree->nvars == 0);
246  assert(changed != NULL);
247 
248  *changed = FALSE;
249  if( newvarsstart != NULL )
250  *newvarsstart = tree->nvars;
251 
252  if( tree->nvars == 0 )
253  return SCIP_OKAY;
254 
255  /* create hash map from variable to indices in tree->vars and check if there is a non-fixed variable */
256  havefixedvar = FALSE;
257  SCIP_CALL( SCIPhashmapCreate(&varhash, tree->blkmem, SCIPcalcHashtableSize(5 * tree->nvars)) );
258  for( i = 0; i < tree->nvars; ++i )
259  {
260  SCIP_CALL( SCIPhashmapInsert(varhash, tree->vars[i], (void*)(size_t)i) );
261  if( !SCIPvarIsActive((SCIP_VAR*)tree->vars[i]) )
262  havefixedvar = TRUE;
263  }
264 
265  if( !havefixedvar )
266  {
267  /* nothing to do */
268  if( varpos != NULL )
269  for( i = 0; i < tree->nvars; ++i )
270  varpos[i] = i;
271  SCIPhashmapFree(&varhash);
272  return SCIP_OKAY;
273  }
274 
275  /* we will do something */
276  *changed = TRUE;
277 
278  nvarsold = tree->nvars;
279 
280  /* array to store expressions that replace a variable expression in the tree */
281  SCIP_ALLOC( BMSallocBlockMemoryArray(tree->blkmem, &replaceexprs, nvarsold) );
282  BMSclearMemoryArray(replaceexprs, nvarsold);
283 
284  /* construct for each nonactive variable an expression that replaces this variable in the tree */
285  for( i = 0; i < nvarsold; ++i )
286  {
287  var = (SCIP_VAR*)tree->vars[i];
288 
289  if( SCIPvarIsActive(var) )
290  continue;
291 
292  scalar = 1.0;
293  constant = 0.0;
294  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
295 
296  if( scalar == 0.0 )
297  {
298  /* variable is fixed, thus replace by constant expression in tree */
299  SCIP_CALL( SCIPexprCreate(tree->blkmem, &replaceexprs[i], SCIP_EXPR_CONST, constant) );
300  continue;
301  }
302 
303  if( SCIPvarIsActive(var) )
304  {
305  /* variable was aggregated or negated, thus replace by scalar * var + constant */
306  if( !SCIPhashmapExists(varhash, var) )
307  {
308  /* var not in tree yet, so add it */
309  SCIP_CALL( SCIPexprtreeAddVars(tree, 1, &var) );
310  idx = tree->nvars - 1;
311  SCIP_CALL( SCIPhashmapInsert(varhash, (void*)var, (void*)(size_t)idx) );
312  }
313  else
314  {
315  idx = (int)(size_t) SCIPhashmapGetImage(varhash, (void*)var);
316  }
317  assert(idx >= 0 && idx < tree->nvars);
318  assert((SCIP_VAR*)tree->vars[idx] == var);
319 
320  SCIP_CALL( SCIPexprCreate(tree->blkmem, &replaceexprs[i], SCIP_EXPR_VARIDX, idx) );
321  if( scalar != 1.0 || constant != 0.0 )
322  {
323  /* multiply by scalar and add constant -> linear expression */
324  SCIP_CALL( SCIPexprCreateLinear(tree->blkmem, &replaceexprs[i], 1, &replaceexprs[i], &scalar, constant) );
325  }
326  continue;
327  }
328 
329  {
330  SCIP_EXPR** children;
331  SCIP_Real* coefs;
332  int nchildren;
333  SCIP_VAR* mvar;
334  SCIP_Real mscalar;
335 
336  /* var is now multi-aggregated, thus replace by scalar * (multaggrconst + sum_j multaggrscalar_j*multaggrvar_j) + constant */
337  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
338 
339  /* allocate array for children and coefficients */
340  SCIP_ALLOC( BMSallocBlockMemoryArray(tree->blkmem, &children, SCIPvarGetMultaggrNVars(var)) ); /*lint !e666 */
341  SCIP_ALLOC( BMSallocBlockMemoryArray(tree->blkmem, &coefs, SCIPvarGetMultaggrNVars(var)) ); /*lint !e666 */
342  nchildren = 0;
343 
344  /* linear part
345  * turn each variable in SCIPvarGetMultaggrVars(var) into an active or multi-aggregated one and add corresponding term to summands */
346  for( j = 0; j < SCIPvarGetMultaggrNVars(var); ++j )
347  {
348  mvar = SCIPvarGetMultaggrVars(var)[j];
349  mscalar = scalar * SCIPvarGetMultaggrScalars(var)[j];
350  SCIP_CALL( SCIPvarGetProbvarSum(&mvar, set, &mscalar, &constant) );
351 
352  /* if variable mvar is fixed, constant has been added to constant and we can continue */
353  if( mscalar == 0.0 )
354  continue;
355 
356  assert(SCIPvarIsActive(mvar) || SCIPvarGetStatus(mvar) == SCIP_VARSTATUS_MULTAGGR);
357 
358  /* add mvar to tree, if not in tree yet */
359  if( !SCIPhashmapExists(varhash, mvar) )
360  {
361  /* var not in tree yet, so add it */
362  SCIP_CALL( SCIPexprtreeAddVars(tree, 1, &mvar) );
363  idx = tree->nvars - 1;
364  SCIP_CALL( SCIPhashmapInsert(varhash, (void*)mvar, (void*)(size_t)idx) );
365  }
366  else
367  {
368  idx = (int)(size_t) SCIPhashmapGetImage(varhash, (void*)mvar);
369  }
370  assert(idx >= 0 && idx < tree->nvars);
371  assert((SCIP_VAR*)tree->vars[idx] == mvar);
372 
373  SCIP_CALL( SCIPexprCreate(tree->blkmem, &children[nchildren], SCIP_EXPR_VARIDX, idx) );
374  coefs[nchildren] = mscalar;
375  ++nchildren;
376  }
377 
378  /* constant part */
379  constant += scalar * SCIPvarGetMultaggrConstant(var);
380 
381  if( nchildren == 0 )
382  {
383  /* somehow all aggregation variables were fixed */
384  SCIP_CALL( SCIPexprCreate(tree->blkmem, &replaceexprs[i], SCIP_EXPR_CONST, constant) );
385  }
386  else if( nchildren == 1 && constant == 0.0 )
387  {
388  /* somehow everything collapsed to one summand -> use that one for replaceexprs[i]*/
389  replaceexprs[i] = children[0];
390  }
391  else
392  {
393  /* set replaceexprs[i] to linear expression in children */
394  SCIP_CALL( SCIPexprCreateLinear(tree->blkmem, &replaceexprs[i], nchildren, children, coefs, constant) );
395  }
396 
397  BMSfreeBlockMemoryArray(tree->blkmem, &children, SCIPvarGetMultaggrNVars(var));
398  BMSfreeBlockMemoryArray(tree->blkmem, &coefs, SCIPvarGetMultaggrNVars(var));
399  }
400  }
401 
402  /* replace variables in tree by assembled expressions */
403  SCIP_CALL( SCIPexprtreeSubstituteVars(tree, replaceexprs) );
404  /* free replaceexprs */
405  for( i = 0; i < nvarsold; ++i )
406  if( replaceexprs[i] != NULL )
407  SCIPexprFreeDeep(tree->blkmem, &replaceexprs[i]);
408  BMSfreeBlockMemoryArray(tree->blkmem, &replaceexprs, nvarsold);
409 
410  /* the varhash is not needed anymore */
411  SCIPhashmapFree(&varhash);
412 
413  /* remove inactive variables from vars array and recompute variable indices */
414  SCIP_ALLOC( BMSallocBlockMemoryArray(tree->blkmem, &newpos, tree->nvars) );
415  offset = 0;
416  for( i = 0; i < tree->nvars; ++i )
417  {
418  if( SCIPvarIsActive((SCIP_VAR*)tree->vars[i]) || i >= nvarsold )
419  {
420  /* a new variable need to be either active or multi-aggregated */
421  assert(i < nvarsold || SCIPvarIsActive((SCIP_VAR*)tree->vars[i]) || SCIPvarGetStatus((SCIP_VAR*)tree->vars[i]) == SCIP_VARSTATUS_MULTAGGR);
422  newpos[i] = i - offset;
423  }
424  else
425  {
426  /* non-active variable are removed */
427  newpos[i] = -1;
428  ++offset;
429  }
430  if( varpos != NULL && i < nvarsold )
431  varpos[i] = newpos[i];
432  }
433  if( newvarsstart != NULL )
434  *newvarsstart -= offset;
435 
436  /* update indices in tree */
437  SCIPexprReindexVars(tree->root, newpos);
438 
439  /* move variable in expression tree vars array
440  * check if there is a fixed variable left */
441  havefixedvar = FALSE;
442  for( i = 0; i < tree->nvars; ++i )
443  {
444  if( newpos[i] == -1 )
445  {
446  /* variable was removed */
447  assert(!SCIPvarIsActive((SCIP_VAR*)tree->vars[i]));
448  continue;
449  }
450  /* variable is moved */
451  tree->vars[newpos[i]] = tree->vars[i];
452  if( !SCIPvarIsActive((SCIP_VAR*)tree->vars[i]) )
453  havefixedvar = TRUE;
454  }
455 
456  /* free newpos array; resize vars array */
457  BMSfreeBlockMemoryArray(tree->blkmem, &newpos, tree->nvars);
458  if( offset < tree->nvars )
459  {
460  SCIP_ALLOC( BMSreallocBlockMemoryArray(tree->blkmem, &tree->vars, tree->nvars, tree->nvars - offset) );
461  tree->nvars -= offset;
462  }
463  else
464  {
465  /* all variables were removed */
466  BMSfreeBlockMemoryArray(tree->blkmem, &tree->vars, tree->nvars);
467  tree->nvars = 0;
468  }
469 
470  if( havefixedvar )
471  {
472  /* if there are still fixed variables left, then this are newly added multi-aggregated variables
473  * it is then save to call this function recursively, since the original active variables should not be moved,
474  * i.e., varpos and *newvarsstart will remain valid
475  */
476  SCIP_Bool gotchange;
477 
478  SCIP_CALL( SCIPexprtreeRemoveFixedVars(tree, set, &gotchange, NULL, NULL) );
479  assert(gotchange);
480  }
481 
482  return SCIP_OKAY;
483 }
484 
485 /*
486  * private NLP nonlinear row methods
487  */
488 
489 /** announces, that the given linear coefficient in the constraint matrix changed */
490 static
492  SCIP_NLROW* nlrow, /**< nonlinear row */
493  SCIP_SET* set, /**< global SCIP settings */
494  SCIP_STAT* stat, /**< problem statistics data */
495  SCIP_VAR* var, /**< variable which coefficient changed */
496  SCIP_Real coef, /**< new coefficient of variable, 0.0 if deleted */
497  SCIP_NLP* nlp /**< current NLP data */
498  )
499 {
500  assert(nlrow != NULL);
501  assert(var != NULL);
502 
503  nlrow->activity = SCIP_INVALID;
504  nlrow->validactivitynlp = -1;
505  nlrow->pseudoactivity = SCIP_INVALID;
506  nlrow->validpsactivitydomchg = -1;
507  nlrow->minactivity = SCIP_INVALID;
508  nlrow->maxactivity = SCIP_INVALID;
509  nlrow->validactivitybdsdomchg = -1;
510 
511  if( nlrow->nlpindex >= 0 )
512  {
513  assert(nlp != NULL);
514 
515  /* notify NLP that row has changed */
516  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
517 
518  /* update NLPI problem, if row is in NLPI already */
519  if( nlrow->nlpiindex >= 0 )
520  {
521  int idx;
522 
523  /* get index of variable in NLPI */
524  assert(SCIPhashmapExists(nlp->varhash, var));
525  idx = (int)(size_t)SCIPhashmapGetImage(nlp->varhash, var);
526  assert(idx >= 0 && idx < nlp->nvars);
527 
528  idx = nlp->varmap_nlp2nlpi[idx];
529  assert(idx >= 0 && idx < nlp->nvars_solver);
530 
531  /* change coefficient in NLPI problem */
532  SCIP_CALL( SCIPnlpiChgLinearCoefs(nlp->solver, nlp->problem, nlrow->nlpiindex, 1, &idx, &coef) );
533  }
534  }
535 
536  return SCIP_OKAY;
537 }
538 
539 /** announces, that an element in the quadratic part of a nonlinear row changed */
540 static
542  SCIP_NLROW* nlrow, /**< nonlinear row */
543  SCIP_SET* set, /**< global SCIP settings */
544  SCIP_STAT* stat, /**< problem statistics data */
545  SCIP_QUADELEM quadelem, /**< new element (variable indices and new values), quadelem.coef == 0 if it was deleted */
546  SCIP_NLP* nlp /**< current NLP data */
547  )
548 {
549  assert(nlrow != NULL);
550  assert(quadelem.idx1 >= 0);
551  assert(quadelem.idx1 < nlrow->nquadvars);
552  assert(quadelem.idx2 >= 0);
553  assert(quadelem.idx2 < nlrow->nquadvars);
554 
555  nlrow->activity = SCIP_INVALID;
556  nlrow->validactivitynlp = -1;
557  nlrow->pseudoactivity = SCIP_INVALID;
558  nlrow->validpsactivitydomchg = -1;
559  nlrow->minactivity = SCIP_INVALID;
560  nlrow->maxactivity = SCIP_INVALID;
561  nlrow->validactivitybdsdomchg = -1;
562 
563  if( nlrow->nlpindex >= 0 )
564  {
565  assert(nlp != NULL);
566 
567  /* notify NLP that row has changed */
568  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
569 
570  /* update NLPI problem, if row is in NLPI already */
571  if( nlrow->nlpiindex >= 0 )
572  {
573  SCIP_QUADELEM elem;
574 
575  /* get NLPI index of first variable */
576  assert(nlrow->quadvars[quadelem.idx1] != NULL);
577  assert(SCIPhashmapExists(nlp->varhash, nlrow->quadvars[quadelem.idx1]));
578  elem.idx1 = (int)(size_t)SCIPhashmapGetImage(nlp->varhash, nlrow->quadvars[quadelem.idx1]);
579  assert(elem.idx1 >= 0 && elem.idx1 < nlp->nvars);
580 
581  elem.idx1 = nlp->varmap_nlp2nlpi[elem.idx1];
582  assert(elem.idx1 >= 0 && elem.idx1 < nlp->nvars_solver);
583 
584  /* get NLPI index of second variable */
585  assert(nlrow->quadvars[quadelem.idx2] != NULL);
586  assert(SCIPhashmapExists(nlp->varhash, nlrow->quadvars[quadelem.idx2]));
587  elem.idx2 = (int)(size_t)SCIPhashmapGetImage(nlp->varhash, nlrow->quadvars[quadelem.idx2]);
588  assert(elem.idx2 >= 0 && elem.idx2 < nlp->nvars);
589 
590  elem.idx2 = nlp->varmap_nlp2nlpi[elem.idx2];
591  assert(elem.idx2 >= 0 && elem.idx2 < nlp->nvars_solver);
592 
593  /* make sure idx1 <= idx2 */
594  if( elem.idx1 > elem.idx2 )
595  {
596  int tmp;
597  tmp = elem.idx2;
598  elem.idx2 = elem.idx1;
599  elem.idx1 = tmp;
600  }
601 
602  elem.coef = quadelem.coef;
603 
604  /* change coefficient in NLPI problem */
605  SCIP_CALL( SCIPnlpiChgQuadCoefs(nlp->solver, nlp->problem, nlrow->nlpiindex, 1, &elem) );
606  }
607  }
608 
609  return SCIP_OKAY;
610 }
611 
612 /** announces, that an expression tree changed */
613 static
615  SCIP_NLROW* nlrow, /**< nonlinear row */
616  SCIP_SET* set, /**< global SCIP settings */
617  SCIP_STAT* stat, /**< problem statistics data */
618  SCIP_NLP* nlp /**< current NLP data */
619  )
620 {
621  assert(nlrow != NULL);
622 
623  nlrow->activity = SCIP_INVALID;
624  nlrow->validactivitynlp = -1;
625  nlrow->pseudoactivity = SCIP_INVALID;
626  nlrow->validpsactivitydomchg = -1;
627  nlrow->minactivity = SCIP_INVALID;
628  nlrow->maxactivity = SCIP_INVALID;
629  nlrow->validactivitybdsdomchg = -1;
630 
631  if( nlrow->nlpindex >= 0 )
632  {
633  assert(nlp != NULL);
634 
635  /* notify NLP that row has changed */
636  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
637 
638  if( nlrow->nlpiindex >= 0 )
639  {
640  /* change expression tree in NLPI problem */
641  int* nlinidxs;
642 
643  /* get indices of variables in expression tree part of row */
644  if( nlrow->exprtree != NULL )
645  {
646  int i;
647  int n;
648  SCIP_VAR* var;
649 
650  n = SCIPexprtreeGetNVars(nlrow->exprtree);
651  assert(n == 0 || SCIPexprtreeGetVars(nlrow->exprtree) != NULL);
652 
653  SCIP_CALL( SCIPsetAllocBufferArray(set, &nlinidxs, n) );
654 
655  for( i = 0; i < n; ++i )
656  {
657  var = SCIPexprtreeGetVars(nlrow->exprtree)[i];
658  assert(var != NULL);
659  assert(SCIPvarIsActive(var)); /* at this point, there should be only active variables in the row */
660 
661  assert(SCIPhashmapExists(nlp->varhash, var));
662  nlinidxs[i] = nlp->varmap_nlp2nlpi[(size_t) (void*) SCIPhashmapGetImage(nlp->varhash, var)];
663  }
664 
665  SCIP_CALL( SCIPnlpiChgExprtree(nlp->solver, nlp->problem, nlrow->nlpiindex, nlinidxs, nlrow->exprtree) );
666 
667  SCIPsetFreeBufferArray(set, &nlinidxs);
668  }
669  else
670  {
671  SCIP_CALL( SCIPnlpiChgExprtree(nlp->solver, nlp->problem, nlrow->nlpiindex, NULL, NULL) );
672  }
673  }
674  }
675 
676  return SCIP_OKAY;
677 }
678 
679 /** announces, that a parameter in an expression tree has changed */
680 static
682  SCIP_NLROW* nlrow, /**< nonlinear row */
683  SCIP_SET* set, /**< global SCIP settings */
684  SCIP_STAT* stat, /**< problem statistics data */
685  int paramidx, /**< index of parameter which has changed, or -1 if all changed */
686  SCIP_NLP* nlp /**< current NLP data */
687  )
688 {
689  assert(nlrow != NULL);
690  assert(nlrow->exprtree != NULL);
691  assert(paramidx >= -1);
692  assert(paramidx < SCIPexprtreeGetNParams(nlrow->exprtree));
693 
694  nlrow->activity = SCIP_INVALID;
695  nlrow->validactivitynlp = -1;
696  nlrow->pseudoactivity = SCIP_INVALID;
697  nlrow->validpsactivitydomchg = -1;
698  nlrow->minactivity = SCIP_INVALID;
699  nlrow->maxactivity = SCIP_INVALID;
700  nlrow->validactivitybdsdomchg = -1;
701 
702  if( nlrow->nlpindex >= 0 )
703  {
704  assert(nlp != NULL);
705 
706  /* notify NLP that row has changed */
707  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
708 
709  if( nlrow->nlpiindex >= 0 )
710  {
711  if( paramidx >= 0 )
712  {
713  /* change coefficient in NLPI problem */
714  SCIP_CALL( SCIPnlpiChgNonlinCoef(nlp->solver, nlp->problem, nlrow->nlpiindex, paramidx, SCIPexprtreeGetParamVals(nlrow->exprtree)[paramidx]) );
715  }
716  else
717  {
718  SCIP_Real* paramvals;
719  int i;
720  int n;
721 
722  /* change all coefficients in NLPI problem */
723  n = SCIPexprtreeGetNParams(nlrow->exprtree);
724  paramvals = SCIPexprtreeGetParamVals(nlrow->exprtree);
725  for( i = 0; i < n; ++i )
726  {
727  SCIP_CALL( SCIPnlpiChgNonlinCoef(nlp->solver, nlp->problem, nlrow->nlpiindex, i, paramvals[i]) );
728  }
729  }
730  }
731  }
732 
733  return SCIP_OKAY;
734 }
735 
736 /** notifies nonlinear row, that its sides were changed */
737 static
739  SCIP_NLROW* nlrow, /**< nonlinear row */
740  SCIP_SET* set, /**< global SCIP settings */
741  SCIP_STAT* stat, /**< problem statistics data */
742  SCIP_NLP* nlp /**< current NLP data */
743  )
744 {
745  assert(nlrow != NULL);
746 
747  if( nlrow->nlpindex >= 0 )
748  {
749  assert(nlp != NULL);
750 
751  /* notify NLP that row has changed */
752  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
753 
754  if( nlrow->nlpiindex >= 0 )
755  {
756  SCIP_Real lhs;
757  SCIP_Real rhs;
758 
759  /* change sides in NLPI problem */
760  lhs = nlrow->lhs;
761  rhs = nlrow->rhs;
762  if( !SCIPsetIsInfinity(set, -lhs) )
763  lhs -= nlrow->constant;
764  if( !SCIPsetIsInfinity(set, rhs) )
765  rhs -= nlrow->constant;
766 
767  SCIP_CALL( SCIPnlpiChgConsSides(nlp->solver, nlp->problem, 1, &nlrow->nlpiindex, &lhs, &rhs) );
768  }
769  }
770 
771  return SCIP_OKAY;
772 }
773 
774 /** notifies nonlinear row, that its constant was changed */
775 static
777  SCIP_NLROW* nlrow, /**< nonlinear row */
778  SCIP_SET* set, /**< global SCIP settings */
779  SCIP_STAT* stat, /**< problem statistics data */
780  SCIP_NLP* nlp /**< current NLP data */
781  )
782 {
783  assert(nlrow != NULL);
784 
785  nlrow->activity = SCIP_INVALID;
786  nlrow->validactivitynlp = -1;
787  nlrow->pseudoactivity = SCIP_INVALID;
788  nlrow->validpsactivitydomchg = -1;
789  nlrow->minactivity = SCIP_INVALID;
790  nlrow->maxactivity = SCIP_INVALID;
791  nlrow->validactivitybdsdomchg = -1;
792 
793  if( nlrow->nlpindex >= 0 )
794  {
795  assert(nlp != NULL);
796 
797  /* notify NLP that row has changed */
798  SCIP_CALL( nlpRowChanged(nlp, set, stat, nlrow) );
799 
800  if( nlrow->nlpiindex >= 0 )
801  {
802  SCIP_Real lhs;
803  SCIP_Real rhs;
804 
805  lhs = nlrow->lhs;
806  rhs = nlrow->rhs;
807  if( !SCIPsetIsInfinity(set, -lhs) )
808  lhs -= nlrow->constant;
809  if( !SCIPsetIsInfinity(set, rhs) )
810  rhs -= nlrow->constant;
811 
812  /* change sides in NLPI problem */
813  SCIP_CALL( SCIPnlpiChgConsSides(nlp->solver, nlp->problem, 1, &nlrow->nlpiindex, &lhs, &rhs) );
814  }
815  }
816 
817  return SCIP_OKAY;
818 }
819 
820 /** sorts linear part of row entries such that lower variable indices precede higher ones */
821 static
823  SCIP_NLROW* nlrow /**< nonlinear row to be sorted */
824  )
825 {
826  assert(nlrow != NULL);
827 
828  /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
829  if( nlrow->linvarssorted )
830  return;
831 
832  /* sort linear coefficients */
833  SCIPsortPtrReal((void**)nlrow->linvars, nlrow->lincoefs, SCIPvarComp, nlrow->nlinvars);
834 
835  nlrow->linvarssorted = TRUE;
836 }
837 
838 /** searches linear variable in nonlinear row, returns position in linvars vector or -1 if not found */
839 static
841  SCIP_NLROW* nlrow, /**< nonlinear row to be searched in */
842  SCIP_VAR* var /**< variable to be searched for */
843  )
844 {
845  int pos;
846 
847  assert(nlrow != NULL);
848  assert(var != NULL);
849 
850  if( nlrow->nlinvars == 0 )
851  return -1;
852 
853  nlrowSortLinear(nlrow);
854  if( !SCIPsortedvecFindPtr((void**)nlrow->linvars, SCIPvarComp, (void*)var, nlrow->nlinvars, &pos) )
855  return -1;
856 
857  return pos;
858 }
859 
860 /** moves a coefficient in a nonlinear row to a different place, and updates all corresponding data structures */
861 static
863  SCIP_NLROW* nlrow, /**< NLP row */
864  int oldpos, /**< old position of coefficient */
865  int newpos /**< new position of coefficient */
866  )
867 {
868  assert(nlrow != NULL);
869  assert(0 <= oldpos && oldpos < nlrow->nlinvars);
870  assert(0 <= newpos && newpos < nlrow->nlinvars);
871  assert(nlrow->linvars[oldpos] != NULL);
872 
873  if( oldpos == newpos )
874  return;
875 
876  nlrow->linvars[newpos] = nlrow->linvars[oldpos];
877  nlrow->lincoefs[newpos] = nlrow->lincoefs[oldpos];
878 
879  /* update sorted flags */
880  nlrow->linvarssorted = FALSE;
881 }
882 
883 /** adds a previously non existing linear coefficient to a nonlinear row */
884 static
886  SCIP_NLROW* nlrow, /**< nonlinear row */
887  BMS_BLKMEM* blkmem, /**< block memory */
888  SCIP_SET* set, /**< global SCIP settings */
889  SCIP_STAT* stat, /**< problem statistics data */
890  SCIP_NLP* nlp, /**< current NLP data */
891  SCIP_VAR* var, /**< variable */
892  SCIP_Real coef /**< value of coefficient */
893  )
894 {
895  int pos;
896 
897  assert(nlrow != NULL);
898  assert(blkmem != NULL);
899  assert(var != NULL);
900  assert(!SCIPsetIsZero(set, coef));
901 
902  /* assert that only active variables are added once the row is in the NLP */
903  assert(nlrow->nlpindex == -1 || SCIPvarIsActive(var) );
904 
905  SCIP_CALL( SCIPnlrowEnsureLinearSize(nlrow, blkmem, set, nlrow->nlinvars+1) );
906  assert(nlrow->linvars != NULL);
907  assert(nlrow->lincoefs != NULL);
908 
909  pos = nlrow->nlinvars;
910  nlrow->nlinvars++;
911 
912  /* insert the variable */
913  nlrow->linvars [pos] = var;
914  nlrow->lincoefs[pos] = coef;
915 
916  SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, coef, nlp) );
917 
918  /* update sorted flag */
919  if( pos > 0 && SCIPvarCompare(nlrow->linvars[pos-1], nlrow->linvars[pos]) > 0 )
920  nlrow->linvarssorted = FALSE;
921 
922  SCIPdebugMessage("added linear coefficient %g * <%s> at position %d to nonlinear row <%s>\n",
923  coef, SCIPvarGetName(var), pos, nlrow->name);
924 
925  return SCIP_OKAY;
926 }
927 
928 /** adds a linear coefficient to a nonlinear row
929  * if the variable exists in the linear part of the row already, the coefficients are added
930  * otherwise the variable is added to the row */
931 static
933  SCIP_NLROW* nlrow, /**< nonlinear row */
934  BMS_BLKMEM* blkmem, /**< block memory */
935  SCIP_SET* set, /**< global SCIP settings */
936  SCIP_STAT* stat, /**< problem statistics data */
937  SCIP_NLP* nlp, /**< current NLP data */
938  SCIP_VAR* var, /**< variable */
939  SCIP_Real coef, /**< value of coefficient */
940  SCIP_Bool removefixed /**< whether to disaggregate var before adding */
941  )
942 {
943  int pos;
944 
945  assert(nlrow != NULL);
946  assert(blkmem != NULL);
947  assert(var != NULL);
948 
949  if( removefixed && !SCIPvarIsActive(var) )
950  {
951  SCIP_Real constant;
952 
953  constant = 0.0;
954  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &coef, &constant) );
955  if( constant != 0.0 )
956  {
957  nlrow->constant += constant;
958  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
959  }
960 
961  if( !SCIPvarIsActive(var) )
962  {
963  int j;
964 
965  /* if var is still not active, then it is multi-aggregated */
967 
968  if( SCIPvarGetMultaggrConstant(var) != 0.0 )
969  {
970  nlrow->constant += coef * SCIPvarGetMultaggrConstant(var);
971  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
972  }
973 
974  for( j = 0; j < SCIPvarGetMultaggrNVars(var); ++j )
975  {
976  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[j], SCIPvarGetMultaggrScalars(var)[j] * coef, TRUE) );
977  }
978 
979  return SCIP_OKAY;
980  }
981  }
982  assert(!removefixed || SCIPvarIsActive(var));
983 
984  if( SCIPsetIsZero(set, coef) )
985  return SCIP_OKAY;
986 
987  pos = nlrowSearchLinearCoef(nlrow, var);
988 
989  if( pos == -1 )
990  {
991  /* add as new coefficient */
992  SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, coef) );
993  }
994  else
995  {
996  assert(pos >= 0);
997  assert(pos < nlrow->nlinvars);
998  assert(nlrow->linvars[pos] == var);
999 
1000  /* add to previously existing coefficient */
1001  nlrow->lincoefs[pos] += coef;
1002  }
1003 
1004  return SCIP_OKAY;
1005 }
1006 
1007 /** deletes coefficient at given position from row */
1008 static
1010  SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
1011  SCIP_SET* set, /**< global SCIP settings */
1012  SCIP_STAT* stat, /**< problem statistics data */
1013  SCIP_NLP* nlp, /**< current NLP data */
1014  int pos /**< position in row vector to delete */
1015  )
1016 {
1017  SCIP_VAR* var;
1018 
1019  assert(nlrow != NULL);
1020  assert(set != NULL);
1021  assert(0 <= pos && pos < nlrow->nlinvars);
1022  assert(nlrow->linvars[pos] != NULL);
1023 
1024  var = nlrow->linvars[pos];
1025 
1026  /* move last coefficient to position of empty slot (should set sorted flag to FALSE, if not last variable was deleted) */
1027  nlrowMoveLinearCoef(nlrow, nlrow->nlinvars-1, pos);
1028  nlrow->nlinvars--;
1029  assert(pos == nlrow->nlinvars || nlrow->linvarssorted == FALSE);
1030 
1031  SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, 0.0, nlp) );
1032 
1033  return SCIP_OKAY;
1034 }
1035 
1036 /** changes a coefficient at given position of a nonlinear row */
1037 static
1039  SCIP_NLROW* nlrow, /**< NLP row */
1040  SCIP_SET* set, /**< global SCIP settings */
1041  SCIP_STAT* stat, /**< problem statistics data */
1042  SCIP_NLP* nlp, /**< current NLP data */
1043  int pos, /**< position in row vector to change */
1044  SCIP_Real coef /**< new value of coefficient */
1045  )
1046 {
1047  assert(nlrow != NULL);
1048  assert(0 <= pos && pos < nlrow->nlinvars);
1049  assert(nlrow->linvars[pos] != NULL);
1050 
1051  if( SCIPsetIsZero(set, coef) )
1052  {
1053  /* delete existing coefficient */
1054  SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
1055  }
1056  else if( !SCIPsetIsEQ(set, nlrow->lincoefs[pos], coef) )
1057  {
1058  /* change existing coefficient */
1059  nlrow->lincoefs[pos] = coef;
1060  SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, nlrow->linvars[pos], coef, nlp) );
1061  }
1062 
1063  return SCIP_OKAY;
1064 }
1065 
1066 /** sets up the variable hash for quadratic variables, if the number of variables exceeds some given threshold */
1067 static
1069  SCIP_NLROW* nlrow, /**< nonlinear row */
1070  BMS_BLKMEM* blkmem /**< block memory */
1071  )
1072 {
1073  int i;
1074  assert(blkmem != NULL);
1075  assert(nlrow != NULL);
1076  assert(nlrow->quadvarshash == NULL);
1077 
1078  if( nlrow->nquadvars < 3 )
1079  return SCIP_OKAY;
1080 
1081  SCIP_CALL( SCIPhashmapCreate(&nlrow->quadvarshash, blkmem, SCIPcalcHashtableSize(5 * nlrow->nquadvars)) );
1082  assert(nlrow->quadvarshash != NULL);
1083 
1084  for( i = 0; i < nlrow->nquadvars; ++i )
1085  {
1086  SCIP_CALL( SCIPhashmapInsert(nlrow->quadvarshash, (void*)nlrow->quadvars[i], (void*)(size_t)i) );
1087  }
1088 
1089  return SCIP_OKAY;
1090 }
1091 
1092 /** sorts quadratic part of row entries */
1093 static
1095  SCIP_NLROW* nlrow /**< nonlinear row to be sorted */
1096  )
1097 {
1098  assert(nlrow != NULL);
1099  assert(nlrow->quadelems != NULL);
1100 
1101  /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
1102  if( nlrow->quadelemssorted )
1103  return;
1104 
1105  /* sort quadratic elements */
1106  SCIPquadelemSort(nlrow->quadelems, nlrow->nquadelems);
1107 
1108  nlrow->quadelemssorted = TRUE;
1109 }
1110 
1111 /** searches quadratic elements in nonlinear row, returns position of given index pair in quadelems array or -1 if not found */
1112 static
1114  SCIP_NLROW* nlrow, /**< nonlinear row to be searched in */
1115  int idx1, /**< index of first variable to be searched for */
1116  int idx2 /**< index of second variable to be searched for */
1117  )
1118 {
1119  int pos;
1120 
1121  assert(nlrow != NULL);
1122  assert(idx1 >= 0);
1123  assert(idx1 < nlrow->nquadvars);
1124  assert(idx2 >= 0);
1125  assert(idx2 < nlrow->nquadvars);
1126 
1127  nlrowSortQuadElem(nlrow);
1128  if( !SCIPquadelemSortedFind(nlrow->quadelems, idx1, idx2, nlrow->nquadelems, &pos) )
1129  pos = -1;
1130 
1131  return pos;
1132 }
1133 
1134 /** moves a quadratic element in a nonlinear row to a different place, and updates all corresponding data structures */
1135 static
1137  SCIP_NLROW* nlrow, /**< NLP row */
1138  int oldpos, /**< old position of coefficient */
1139  int newpos /**< new position of coefficient */
1140  )
1141 {
1142  assert(nlrow != NULL);
1143  assert(0 <= oldpos && oldpos < nlrow->nquadelems);
1144  assert(0 <= newpos && newpos < nlrow->nquadelems);
1145 
1146  if( oldpos == newpos )
1147  return;
1148 
1149  nlrow->quadelems[newpos] = nlrow->quadelems[oldpos];
1150 
1151  /* update sorted flags */
1152  nlrow->quadelemssorted = FALSE;
1153 }
1154 
1155 /** adds a previously non existing quadratic element to a nonlinear row */
1156 static
1158  SCIP_NLROW* nlrow, /**< nonlinear row */
1159  BMS_BLKMEM* blkmem, /**< block memory */
1160  SCIP_SET* set, /**< global SCIP settings */
1161  SCIP_STAT* stat, /**< problem statistics data */
1162  SCIP_NLP* nlp, /**< current NLP data */
1163  SCIP_QUADELEM elem /**< quadratic element to add */
1164  )
1165 {
1166  int pos;
1167 
1168  assert(nlrow != NULL);
1169  assert(blkmem != NULL);
1170  assert(elem.idx1 >= 0);
1171  assert(elem.idx1 < nlrow->nquadvars);
1172  assert(elem.idx2 >= 0);
1173  assert(elem.idx2 < nlrow->nquadvars);
1174 
1175  if( SCIPsetIsZero(set, elem.coef) )
1176  return SCIP_OKAY;
1177 
1178  SCIP_CALL( SCIPnlrowEnsureQuadElementsSize(nlrow, blkmem, set, nlrow->nquadelems+1) );
1179  assert(nlrow->quadelems != NULL);
1180 
1181  pos = nlrow->nquadelems;
1182  nlrow->nquadelems++;
1183 
1184  /* insert the element */
1185  nlrow->quadelems[pos] = elem;
1186 
1187  /* notify row and NLP */
1188  SCIP_CALL( nlrowQuadElemChanged(nlrow, set, stat, elem, nlp) );
1189 
1190  /* update sorted flag */
1191  if( pos > 0 )
1192  nlrow->quadelemssorted = FALSE;
1193 
1194  SCIPdebugMessage("added quadratic element %g * <%s> * <%s> at position %d to nonlinear row <%s>\n",
1195  elem.coef, SCIPvarGetName(nlrow->quadvars[elem.idx1]), SCIPvarGetName(nlrow->quadvars[elem.idx2]), pos, nlrow->name);
1196 
1197  return SCIP_OKAY;
1198 }
1199 
1200 /** deletes coefficient at given position from row */
1201 static
1203  SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
1204  SCIP_SET* set, /**< global SCIP settings */
1205  SCIP_STAT* stat, /**< problem statistics data */
1206  SCIP_NLP* nlp, /**< current NLP data */
1207  int pos /**< position in row vector to delete */
1208  )
1209 {
1210  SCIP_QUADELEM elem;
1211 
1212  assert(nlrow != NULL);
1213  assert(set != NULL);
1214  assert(0 <= pos && pos < nlrow->nquadelems);
1215 
1216  SCIPdebugMessage("delete quad element (%d,%d) at pos %d\n", nlrow->quadelems[pos].idx1, nlrow->quadelems[pos].idx2, pos);
1217 
1218  elem = nlrow->quadelems[pos];
1219 
1220  /* move last coefficient to position of empty slot (should set sorted flag to FALSE, if not last element was deleted) */
1221  nlrowMoveQuadElement(nlrow, nlrow->nquadelems-1, pos);
1222  nlrow->nquadelems--;
1223  assert(pos == nlrow->nquadelems || nlrow->quadelemssorted == FALSE);
1224 
1225  /* notify row and NLP */
1226  elem.coef = 0.0;
1227  SCIP_CALL( nlrowQuadElemChanged(nlrow, set, stat, elem, nlp) );
1228 
1229  return SCIP_OKAY;
1230 }
1231 
1232 /** changes a coefficient at given position of quadratic element in nonlinear row */
1233 static
1235  SCIP_NLROW* nlrow, /**< NLP row */
1236  SCIP_SET* set, /**< global SCIP settings */
1237  SCIP_STAT* stat, /**< problem statistics data */
1238  SCIP_NLP* nlp, /**< current NLP data */
1239  int pos, /**< position in quadratic elements array to change */
1240  SCIP_Real coef /**< new value of coefficient */
1241  )
1242 {
1243  assert(nlrow != NULL);
1244  assert(0 <= pos && pos < nlrow->nquadelems);
1245 
1246  SCIPdebugMessage("change quad element (%d,%d) at pos %d to %g\n", nlrow->quadelems[pos].idx1, nlrow->quadelems[pos].idx2, pos, coef);
1247 
1248  if( SCIPsetIsZero(set, coef) )
1249  {
1250  /* delete existing coefficient */
1251  SCIP_CALL( nlrowDelQuadElemPos(nlrow, set, stat, nlp, pos) );
1252  }
1253  else if( !SCIPsetIsEQ(set, nlrow->quadelems[pos].coef, coef) )
1254  {
1255  /* change existing coefficient */
1256  nlrow->quadelems[pos].coef = coef;
1257  SCIP_CALL( nlrowQuadElemChanged(nlrow, set, stat, nlrow->quadelems[pos], nlp) );
1258  }
1259 
1260  return SCIP_OKAY;
1261 }
1262 
1263 /** calculates minimal and maximal activity of row w.r.t. the variable's bounds */
1264 static
1266  SCIP_NLROW* nlrow, /**< nonlinear row */
1267  SCIP_SET* set, /**< global SCIP settings */
1268  SCIP_STAT* stat /**< problem statistics data */
1269  )
1270 {
1271  SCIP_Real inf;
1272  SCIP_INTERVAL activity;
1273  SCIP_INTERVAL bounds;
1274  int i;
1275 
1276  assert(nlrow != NULL);
1277  assert(set != NULL);
1278  assert(stat != NULL);
1279 
1280  inf = SCIPsetInfinity(set);
1281 
1282  /* calculate activity bounds */
1283  SCIPintervalSet(&activity, nlrow->constant);
1284  for( i = 0; i < nlrow->nlinvars && !SCIPintervalIsEntire(inf, activity); ++i )
1285  {
1286  SCIPintervalSetBounds(&bounds, SCIPvarGetLbLocal(nlrow->linvars[i]), SCIPvarGetUbLocal(nlrow->linvars[i]));
1287  SCIPintervalMulScalar(inf, &bounds, bounds, nlrow->lincoefs[i]);
1288  SCIPintervalAdd(inf, &activity, activity, bounds);
1289  }
1290 
1291  /* @todo make sure quadelems is sorted */
1292  for( i = 0; i < nlrow->nquadelems && !SCIPintervalIsEntire(inf, activity); )
1293  {
1294  SCIP_Real a;
1295  SCIP_INTERVAL b, tmp;
1296  int idx1;
1297 
1298  idx1 = nlrow->quadelems[i].idx1;
1299  SCIPintervalSetBounds(&bounds, SCIPvarGetLbLocal(nlrow->quadvars[idx1]), SCIPvarGetUbLocal(nlrow->quadvars[idx1]));
1300 
1301  /* for x_i*(a*x_i + sum_j b_jx_j) we assemble a and sum_j b_jx_j */
1302  a = 0.0;
1303  SCIPintervalSet(&b, 0.0);
1304  do
1305  {
1306  if( nlrow->quadelems[i].idx1 == nlrow->quadelems[i].idx2 )
1307  {
1308  a = nlrow->quadelems[i].coef;
1309  }
1310  else
1311  {
1313  SCIPintervalMulScalar(inf, &tmp, tmp, nlrow->quadelems[i].coef);
1314  SCIPintervalAdd(inf, &b, b, tmp);
1315  }
1316  ++i;
1317  }
1318  while( i < nlrow->nquadvars && idx1 == nlrow->quadelems[i].idx1 );
1319 
1320  /* compute bounds for a*x_i^2 + b*x_i and add to activity bounds */
1321  SCIPintervalQuad(inf, &bounds, a, b, bounds);
1322  SCIPintervalAdd(inf, &activity, activity, bounds);
1323  }
1324 
1325  if( nlrow->exprtree != NULL && !SCIPintervalIsEntire(inf, activity))
1326  {
1327  SCIP_INTERVAL* varvals;
1328  int n;
1329 
1330  n = SCIPexprtreeGetNVars(nlrow->exprtree);
1331 
1332  SCIP_CALL( SCIPsetAllocBufferArray(set, &varvals, n) );
1333 
1334  for( i = 0; i < n; ++i )
1335  {
1337  }
1338 
1339  SCIP_CALL( SCIPexprtreeEvalInt(nlrow->exprtree, inf, varvals, &bounds) );
1340  SCIPintervalAdd(inf, &activity, activity, bounds);
1341 
1342  SCIPsetFreeBufferArray(set, &varvals);
1343  }
1344 
1345  nlrow->minactivity = SCIPintervalGetInf(activity);
1346  nlrow->maxactivity = SCIPintervalGetSup(activity);
1347 
1348  nlrow->validactivitybdsdomchg = stat->domchgcount;
1349 
1350  return SCIP_OKAY;
1351 }
1352 
1353 /** makes sure that there is no fixed variable at position pos of the linear part of a nonlinear row
1354  * a fixed variable is replaced with the corresponding constant or disaggregated term
1355  */
1356 static
1358  SCIP_NLROW* nlrow, /**< nonlinear row */
1359  BMS_BLKMEM* blkmem, /**< block memory */
1360  SCIP_SET* set, /**< global SCIP settings */
1361  SCIP_STAT* stat, /**< problem statistics data */
1362  SCIP_NLP* nlp, /**< current NLP data */
1363  int pos /**< position of variable in linear variables array */
1364  )
1365 {
1366  SCIP_Real oldconstant;
1367  SCIP_VAR* var;
1368 
1369  assert(nlrow != NULL);
1370  assert(blkmem != NULL);
1371  assert(pos >= 0);
1372  assert(pos < nlrow->nlinvars);
1373 
1374  var = nlrow->linvars[pos];
1375 
1376  if( SCIPvarIsActive(var) )
1377  return SCIP_OKAY;
1378 
1379  oldconstant = nlrow->constant;
1380 
1381  /* replace fixed, aggregated, or negated variable */
1382  SCIP_CALL( SCIPvarGetProbvarSum( &nlrow->linvars[pos], set, &nlrow->lincoefs[pos], &nlrow->constant) );
1383 
1384  /* if var had been fixed, entry should be removed from row */
1385  if( nlrow->lincoefs[pos] == 0.0 )
1386  {
1387  nlrowMoveLinearCoef(nlrow, nlrow->nlinvars-1, pos);
1388  nlrow->nlinvars--;
1389 
1390  if( pos < nlrow->nlinvars )
1391  {
1392  SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
1393  }
1394 
1395  return SCIP_OKAY;
1396  }
1397  nlrow->linvarssorted = FALSE;
1398 
1399  /* notify nlrow that coefficient of var is now 0.0 in row */
1400  SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, var, 0.0, nlp) );
1401 
1402  /* notify nlrow that constant of row has changed */
1403  if( oldconstant != nlrow->constant ) /*lint !e777*/
1404  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1405 
1406  if( SCIPvarIsActive(nlrow->linvars[pos]) )
1407  {
1408  /* if var was aggregated or negated, notify nlrow about new coefficient */
1409  SCIP_CALL( nlrowLinearCoefChanged(nlrow, set, stat, nlrow->linvars[pos], nlrow->lincoefs[pos], nlp) );
1410  }
1411  else
1412  {
1413  SCIP_Real coef;
1414  int i;
1415 
1416  /* if not removed or active, the new variable should be multi-aggregated */
1417  assert(SCIPvarGetStatus(nlrow->linvars[pos]) == SCIP_VARSTATUS_MULTAGGR);
1418 
1419  var = nlrow->linvars[pos];
1420  coef = nlrow->lincoefs[pos];
1421 
1422  /* remove the variable from the row */
1423  SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
1424 
1425  /* add multi-aggregated term to row */
1426  if( SCIPvarGetMultaggrConstant(var) != 0.0 )
1427  {
1428  nlrow->constant += coef * SCIPvarGetMultaggrConstant(var);
1429  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1430  }
1431  SCIP_CALL( SCIPnlrowEnsureLinearSize(nlrow, blkmem, set, nlrow->nlinvars + SCIPvarGetMultaggrNVars(var)) );
1432  for( i = 0; i < SCIPvarGetMultaggrNVars(var); ++i )
1433  {
1434  SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[i], coef * SCIPvarGetMultaggrScalars(var)[i]) );
1435  assert(SCIPvarGetMultaggrVars(var)[i] == nlrow->linvars[nlrow->nlinvars-1]);
1436  if( !SCIPvarIsActive(SCIPvarGetMultaggrVars(var)[i]) )
1437  {
1438  /* if newly added variable is fixed, replace it now */
1439  SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, nlrow->nlinvars-1) );
1440  }
1441  }
1442 
1443  /* due to nlrowDelLinearCoefPos, an inactive variable may have moved to position pos
1444  * if that is the case, call ourself recursively
1445  */
1446  if( pos < nlrow->nlinvars && !SCIPvarIsActive(nlrow->linvars[pos]) )
1447  {
1448  SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
1449  }
1450  }
1451 
1452  return SCIP_OKAY;
1453 }
1454 
1455 /** removes fixed variables from the linear part of a nonlinear row */
1456 static
1458  SCIP_NLROW* nlrow, /**< nonlinear row */
1459  BMS_BLKMEM* blkmem, /**< block memory */
1460  SCIP_SET* set, /**< global SCIP settings */
1461  SCIP_STAT* stat, /**< problem statistics data */
1462  SCIP_NLP* nlp /**< current NLP data */
1463  )
1464 {
1465  int i;
1466  int oldlen;
1467 
1468  assert(nlrow != NULL);
1469  assert(nlrow->linvars != NULL || nlrow->nlinvars == 0);
1470 
1471  oldlen = nlrow->nlinvars;
1472  for( i = 0; i < MIN(oldlen, nlrow->nlinvars); ++i )
1473  {
1474  assert(nlrow->linvars[i] != NULL);
1475  SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, i) );
1476  }
1477 
1478  return SCIP_OKAY;
1479 }
1480 
1481 /** removes fixed quadratic variables of a nonlinear row by replacing them with the corresponding constant or disaggregated terms */
1482 static
1484  SCIP_NLROW* nlrow, /**< nonlinear row */
1485  BMS_BLKMEM* blkmem, /**< block memory */
1486  SCIP_SET* set, /**< global SCIP settings */
1487  SCIP_STAT* stat, /**< problem statistics data */
1488  SCIP_NLP* nlp /**< current NLP data */
1489  )
1490 {
1491  int i;
1492  int nvarsold;
1493  SCIP_Bool* used;
1494  SCIP_QUADELEM elem;
1495  SCIP_QUADELEM newelem;
1496  int idx2;
1497  SCIP_Bool havechange;
1498 
1499  SCIP_VAR* var1;
1500  SCIP_Real coef1;
1501  SCIP_Real constant1;
1502  SCIP_VAR* var2;
1503  SCIP_Real coef2;
1504  SCIP_Real constant2;
1505 
1506  assert(nlrow != NULL);
1507  assert(blkmem != NULL);
1508 
1509  if( nlrow->nquadvars == 0 )
1510  return SCIP_OKAY;
1511 
1512  SCIPdebugMessage("removing fixed quadratic variables from nlrow\n");
1513 
1514  nvarsold = nlrow->nquadvars;
1515  havechange = FALSE;
1516 
1517  /* allocate array to count number of uses for each variable */
1518  SCIP_CALL( SCIPsetAllocBufferArray(set, &used, nlrow->nquadvars) );
1519  BMSclearMemoryArray(used, nlrow->nquadvars);
1520 
1521  i = 0;
1522  while( i < nlrow->nquadelems )
1523  {
1524  elem = nlrow->quadelems[i];
1525 
1526  assert(elem.idx1 < nlrow->nquadvars);
1527  assert(elem.idx2 < nlrow->nquadvars);
1528  if( SCIPvarIsActive(nlrow->quadvars[elem.idx1]) && SCIPvarIsActive(nlrow->quadvars[elem.idx2]) )
1529  {
1530  /* both variables of quadratic element are active
1531  * thus, we just remember that we saw them and can continue with the next element
1532  */
1533  if( elem.idx1 < nvarsold )
1534  used[elem.idx1] = TRUE;
1535  if( elem.idx2 < nvarsold )
1536  used[elem.idx2] = TRUE;
1537  ++i;
1538  continue;
1539  }
1540 
1541  SCIPdebugMessage("removing fixed quadratic variables from %dth element %g <%s> <%s>\n",
1542  i, elem.coef, SCIPvarGetName(nlrow->quadvars[elem.idx1]), SCIPvarGetName(nlrow->quadvars[elem.idx2]));
1543 
1544  /* if one of the variable is not active, we remove the element and insert new disaggregated ones */
1545  SCIP_CALL( nlrowDelQuadElemPos(nlrow, set, stat, nlp, i) );
1546  havechange = TRUE;
1547 
1548  var1 = nlrow->quadvars[elem.idx1];
1549  var2 = nlrow->quadvars[elem.idx2];
1550  coef1 = 1.0;
1551  coef2 = 1.0;
1552  constant1 = 0.0;
1553  constant2 = 0.0;
1554 
1555  SCIP_CALL( SCIPvarGetProbvarSum(&var1, set, &coef1, &constant1) );
1556  SCIP_CALL( SCIPvarGetProbvarSum(&var2, set, &coef2, &constant2) );
1557 
1558  if( coef1 == 0.0 && coef2 == 0.0 )
1559  {
1560  /* both variables were fixed, so we may add a constant term and continue */
1561  if( constant1 != 0.0 && constant2 != 0.0 )
1562  {
1563  nlrow->constant += elem.coef * constant1 * constant2;
1564  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1565  }
1566  continue;
1567  }
1568 
1569  if( coef1 == 0.0 )
1570  {
1571  /* only the first variable was fixed, so we may add a linear term
1572  * elem.coef * x * y -> elem.coef * constant1 * (coef2 * var2 + constant2) */
1573  if( constant1 != 0.0 )
1574  {
1575  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, var2, elem.coef * constant1 * coef2, TRUE) );
1576  if( constant2 != 0.0 )
1577  {
1578  nlrow->constant += elem.coef * constant1 * constant2;
1579  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1580  }
1581  }
1582  /* continue with next element that is at position i now */
1583  continue;
1584  }
1585 
1586  if( coef2 == 0.0 )
1587  {
1588  /* only the second variable was fixed, so we may add a linear term
1589  * elem.coef * x * y -> elem.coef * (coef1 * var1 + constant1) * constant2 */
1590  if( constant2 != 0.0 )
1591  {
1592  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, var1, elem.coef * coef1 * constant2, TRUE) );
1593  if( constant1 != 0.0 )
1594  {
1595  nlrow->constant += elem.coef * constant1 * constant2;
1596  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1597  }
1598  }
1599  /* continue with next element that is at position i now */
1600  continue;
1601  }
1602 
1603  if( var1 == var2 && !SCIPvarIsActive(var1) )
1604  {
1605  SCIP_Real tmp;
1606  int* multaggrvaridxs;
1607  int j, k;
1608 
1609  assert(SCIPvarGetStatus(var1) == SCIP_VARSTATUS_MULTAGGR);
1610  assert(coef1 == coef2); /*lint !e777*/
1611  assert(constant1 == constant2); /*lint !e777*/
1612  /* square term which variable is multi-aggregated
1613  * elem.coef * x^2 -> elem.coef * (coef1 * (multaggrconstant + sum_i multaggrscalar_i*multaggrvar_i) + constant1)^2
1614  * = elem.coef * ( (coef1 * multaggrconstant + constant1)^2 +
1615  * 2 * (coef1 * multaggrconstant + constant1) * coef1 * (sum_j multaggrscalar_j*multaggrvar_j) +
1616  * coef1^2 * (sum_{j,k} multaggrscalar_j*multaggrscalar_k*multaggrvar_j*multaggrvar_k)
1617  * )
1618  */
1619 
1620  /* add constant part */
1621  tmp = coef1 * SCIPvarGetMultaggrConstant(var1) + constant1;
1622  if( tmp != 0.0 )
1623  {
1624  nlrow->constant += elem.coef * tmp * tmp;
1625  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1626  }
1627 
1628  /* add linear part */
1629  if( constant1 != 0.0 || SCIPvarGetMultaggrConstant(var1) != 0.0 )
1630  {
1631  for( j = 0; j < SCIPvarGetMultaggrNVars(var1); ++j )
1632  {
1633  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var1)[j],
1634  2.0 * elem.coef * (coef1 * SCIPvarGetMultaggrConstant(var1) + constant1) * coef1 * SCIPvarGetMultaggrScalars(var1)[j], TRUE) );
1635  }
1636  }
1637 
1638  /* setup array with indices of multi-aggregated variables in quadvars */
1639  SCIP_CALL( SCIPsetAllocBufferArray(set, &multaggrvaridxs, SCIPvarGetMultaggrNVars(var1)) );
1640  for( j = 0; j < SCIPvarGetMultaggrNVars(var1); ++j )
1641  {
1642  multaggrvaridxs[j] = SCIPnlrowSearchQuadVar(nlrow, SCIPvarGetMultaggrVars(var1)[j]);
1643  if( multaggrvaridxs[j] == -1 )
1644  {
1645  /* variable multaggrvar_j not existing in quadvars array yet, so add it */
1646  SCIP_CALL( SCIPnlrowAddQuadVar(nlrow, blkmem, set, SCIPvarGetMultaggrVars(var1)[j]) );
1647  multaggrvaridxs[j] = nlrow->nquadvars-1;
1648  }
1649  assert(nlrow->quadvars[multaggrvaridxs[j]] == SCIPvarGetMultaggrVars(var1)[j]);
1650  }
1651 
1652  /* add quadratic elements elem.coef * coef1^2 * (sum_{j,k} multaggrscalar_j*multaggrscalar_k*multaggrvar_j*multaggrvar_k) */
1653  for( j = 0; j < SCIPvarGetMultaggrNVars(var1); ++j )
1654  {
1655  /* bilinear terms */
1656  for( k = 0; k < j; ++k )
1657  {
1658  newelem.idx1 = MIN(multaggrvaridxs[j], multaggrvaridxs[k]);
1659  newelem.idx2 = MAX(multaggrvaridxs[j], multaggrvaridxs[k]);
1660  newelem.coef = 2 * elem.coef * coef1 * coef1 * SCIPvarGetMultaggrScalars(var1)[j] * SCIPvarGetMultaggrScalars(var1)[k];
1661  SCIP_CALL( SCIPnlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, newelem) );
1662  }
1663 
1664  /* square term */
1665  newelem.idx1 = multaggrvaridxs[j];
1666  newelem.idx2 = multaggrvaridxs[j];
1667  newelem.coef = elem.coef * coef1 * coef1 * SCIPvarGetMultaggrScalars(var1)[j] * SCIPvarGetMultaggrScalars(var1)[j];
1668  SCIP_CALL( SCIPnlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, newelem) );
1669  }
1670 
1671  SCIPsetFreeBufferArray(set, &multaggrvaridxs);
1672 
1673  /* continue with next element that is at position i now */
1674  continue;
1675  }
1676 
1677  assert(var1 != NULL);
1678  assert(var2 != NULL);
1679  if( SCIPvarIsActive(var1) && !SCIPvarIsActive(var2) )
1680  {
1681  /* if the second variable is multi-aggregated, but the first one is not, swap both terms */
1682  SCIP_VAR* tmpvar;
1683  SCIP_Real tmpcoef;
1684  SCIP_Real tmpconstant;
1685 
1686  tmpvar = var1;
1687  tmpcoef = coef1;
1688  tmpconstant = constant1;
1689  var2 = var1;
1690  coef2 = coef1;
1691  constant2 = constant1;
1692  var1 = tmpvar;
1693  coef1 = tmpcoef;
1694  constant1 = tmpconstant;
1695  }
1696 
1697  if( !SCIPvarIsActive(var1) )
1698  {
1699  SCIP_Real tmp;
1700  int j;
1701 
1702  assert(SCIPvarGetStatus(var1) == SCIP_VARSTATUS_MULTAGGR);
1703 
1704  /* the first variable is multi-aggregated, add a constant and sequences of linear and quadratic terms:
1705  * elem.coef * x * y -> elem.coef * (coef1 * (multaggrconstant + sum_i multaggrscalar_i*multaggrvar_i) + constant1) * (coef2 * var2 + constant2)
1706  * = elem.coef * ( (coef1 * multaggrconstant + constant1) * constant2 +
1707  * (coef1 * multaggrconstant + constant1) * coef2 * var2 +
1708  * (coef1 * (sum_j multaggrscalar_j*multaggrvar_j)) * constant2 +
1709  * (coef1 * (sum_j multaggrscalar_j*multaggrvar_j)) * coef2 * var2
1710  * )
1711  */
1712 
1713  /* add constant part */
1714  tmp = elem.coef * (coef1 * SCIPvarGetMultaggrConstant(var1) + constant1) * constant2;
1715  if( tmp != 0.0 )
1716  {
1717  nlrow->constant += tmp;
1718  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1719  }
1720 
1721  /* add linear part */
1722  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, var2, elem.coef * (coef1 * SCIPvarGetMultaggrConstant(var1) + constant1) * coef2, TRUE) );
1723  if( constant2 != 0.0 )
1724  {
1725  for( j = 0; j < SCIPvarGetMultaggrNVars(var1); ++j )
1726  {
1727  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var1)[j], elem.coef * coef1 * SCIPvarGetMultaggrScalars(var1)[j] * constant2, TRUE) );
1728  }
1729  }
1730 
1731  /* get index of var2 in quadvars array */
1732  idx2 = SCIPnlrowSearchQuadVar(nlrow, var2);
1733  if( idx2 == -1 )
1734  {
1735  /* variable var2 not existing in quadvars array yet, so add it */
1736  SCIP_CALL( SCIPnlrowAddQuadVar(nlrow, blkmem, set, var2) );
1737  idx2 = nlrow->nquadvars-1;
1738  assert(nlrow->quadvars[idx2] == var2);
1739  }
1740 
1741  /* add quadratic elements elem.coef * coef1 * (sum_j multaggrscalar_j*multaggrvar_j) * coef2 * var2 */
1742  for( j = 0; j < SCIPvarGetMultaggrNVars(var1); ++j )
1743  {
1744  newelem.idx1 = SCIPnlrowSearchQuadVar(nlrow, SCIPvarGetMultaggrVars(var1)[j]);
1745  if( newelem.idx1 == -1 )
1746  {
1747  /* variable not existing in quadvars array yet, so add it */
1748  SCIP_CALL( SCIPnlrowAddQuadVar(nlrow, blkmem, set, SCIPvarGetMultaggrVars(var1)[j]) );
1749  newelem.idx1 = nlrow->nquadvars-1;
1750  assert(nlrow->quadvars[newelem.idx1] == SCIPvarGetMultaggrVars(var1)[j]);
1751  }
1752 
1753  newelem.idx2 = idx2;
1754 
1755  /* swap indices if newelem.idx1 <= newelem.idx2 */
1756  if( newelem.idx1 > idx2 )
1757  {
1758  newelem.idx2 = newelem.idx1;
1759  newelem.idx1 = idx2;
1760  }
1761 
1762  newelem.coef = elem.coef * coef1 * coef2 * SCIPvarGetMultaggrScalars(var1)[j];
1763 
1764  SCIP_CALL( SCIPnlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, newelem) );
1765 
1766  /* continue with next element that is at position i now */
1767  continue;
1768  }
1769  }
1770 
1771  assert(SCIPvarIsActive(var1));
1772  assert(SCIPvarIsActive(var2));
1773  /* add elem.coef * (coef1 * var1 + constant1) * (coef2 * var2 + constant2) */
1774  /* add constant part */
1775  if( constant1 != 0.0 && constant2 != 0.0 )
1776  {
1777  nlrow->constant += elem.coef * constant1 * constant2;
1778  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
1779  }
1780  /* add linear coefficients */
1781  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, var1, elem.coef * coef1 * constant2, TRUE) );
1782  SCIP_CALL( nlrowAddToLinearCoef(nlrow, blkmem, set, stat, nlp, var2, elem.coef * coef2 * constant1, TRUE) );
1783  /* get index of var1 in quadvars array */
1784  newelem.idx1 = SCIPnlrowSearchQuadVar(nlrow, var1);
1785  if( newelem.idx1 == -1 )
1786  {
1787  /* variable var2 not existing in quadvars array yet, so add it */
1788  SCIP_CALL( SCIPnlrowAddQuadVar(nlrow, blkmem, set, var1) );
1789  newelem.idx1 = nlrow->nquadvars-1;
1790  assert(nlrow->quadvars[newelem.idx1] == var1);
1791  }
1792  /* get index of var2 in quadvars array */
1793  newelem.idx2 = SCIPnlrowSearchQuadVar(nlrow, var2);
1794  if( newelem.idx2 == -1 )
1795  {
1796  /* variable var2 not existing in quadvars array yet, so add it */
1797  SCIP_CALL( SCIPnlrowAddQuadVar(nlrow, blkmem, set, var2) );
1798  newelem.idx2 = nlrow->nquadvars-1;
1799  assert(nlrow->quadvars[newelem.idx2] == var2);
1800  }
1801  /* make sure idx1 <= idx2 */
1802  if( newelem.idx1 > newelem.idx2 )
1803  {
1804  idx2 = newelem.idx2;
1805  newelem.idx2 = newelem.idx1;
1806  newelem.idx1 = idx2;
1807  }
1808  newelem.coef = elem.coef * coef1 * coef2;
1809  /* add new quadratic element */
1810  SCIP_CALL( SCIPnlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, newelem) );
1811 
1812  /* continue with next element that is at position i now */
1813  }
1814 
1815  /* clean up unused variables */
1816  if( nlrow->nquadelems == 0 )
1817  {
1818  /* the complete quadratic part was fixed or linearized, so we just free up all memory */
1819  BMSfreeBlockMemoryArray(blkmem, &nlrow->quadvars, nlrow->quadvarssize);
1820  if( nlrow->quadvarshash != NULL )
1821  SCIPhashmapFree(&nlrow->quadvarshash);
1822  BMSfreeBlockMemoryArray(blkmem, &nlrow->quadelems, nlrow->quadelemssize);
1823  nlrow->nquadvars = 0;
1824  nlrow->quadvarssize = 0;
1825  nlrow->nquadelems = 0;
1826  nlrow->quadelemssize = 0;
1827  nlrow->quadelemssorted = TRUE;
1828  }
1829  else if( havechange )
1830  {
1831  /* something had changed, so we likely have quadratic variables to remove */
1832  int* newpos;
1833  int offset;
1834 
1835  /* compute new positions of variables in quadvars array */
1836  SCIP_CALL( SCIPsetAllocBufferArray(set, &newpos, nlrow->nquadvars) );
1837 
1838  offset = 0;
1839  for( i = 0; i < nvarsold; ++i )
1840  {
1841  /* previously existing variables should either be active or not used anymore */
1842  assert(!used[i] || SCIPvarIsActive(nlrow->quadvars[i]));
1843 
1844  if( !used[i] )
1845  {
1846  /* variable has been removed */
1847  newpos[i] = -1;
1848  ++offset;
1849  }
1850  else
1851  {
1852  /* variable will move to position i-offset */
1853  newpos[i] = i-offset;
1854  }
1855  }
1856  for( ; i < nlrow->nquadvars; ++i )
1857  {
1858  if( !SCIPvarIsActive(nlrow->quadvars[i]) )
1859  {
1860  /* it can have happened that a new quadratic variable was added that is not active (when multiplying two multi-aggregations)
1861  * in this case, the variable was only temporarily used and should not be used anymore (this is asserted in the next for-loop below),
1862  * thus we can remove it
1863  */
1864  newpos[i] = -1;
1865  ++offset;
1866  }
1867  else
1868  {
1869  /* variable will move to position i-offset */
1870  newpos[i] = i-offset;
1871  }
1872  }
1873 
1874  /* adjust variable indices in quadratic elements */
1875  for( i = 0; i < nlrow->nquadelems; ++i )
1876  {
1877  assert(newpos[nlrow->quadelems[i].idx1] >= 0);
1878  assert(newpos[nlrow->quadelems[i].idx2] >= 0);
1879  nlrow->quadelems[i].idx1 = newpos[nlrow->quadelems[i].idx1];
1880  nlrow->quadelems[i].idx2 = newpos[nlrow->quadelems[i].idx2];
1881  assert(nlrow->quadelems[i].idx1 <= nlrow->quadelems[i].idx2); /* the way we shrink the quadvars array, variables should stay in the same relative position to each other */
1882  }
1883 
1884  /* move variables in quadvars array and update quadvarshash */
1885  for( i = 0; i < nlrow->nquadvars; ++i )
1886  {
1887  if( newpos[i] == -1 )
1888  {
1889  if( nlrow->quadvarshash != NULL )
1890  {
1891  SCIP_CALL( SCIPhashmapRemove(nlrow->quadvarshash, (void*)nlrow->quadvars[i]) );
1892  }
1893  }
1894  else
1895  {
1896  nlrow->quadvars[newpos[i]] = nlrow->quadvars[i];
1897  if( nlrow->quadvarshash != NULL )
1898  {
1899  SCIP_CALL( SCIPhashmapSetImage(nlrow->quadvarshash, (void*)nlrow->quadvars[i], (void*)(size_t)newpos[i]) );
1900  }
1901  }
1902  }
1903  nlrow->nquadvars -= offset;
1904 
1905  SCIPsetFreeBufferArray(set, &newpos);
1906  }
1907 
1908  SCIPsetFreeBufferArray(set, &used);
1909 
1910  SCIPdebugMessage("finished removing fixed quadratic variables\n");
1911 
1912  return SCIP_OKAY;
1913 }
1914 
1915 /** removes fixed variables from expression tree of a nonlinear row */
1916 static
1918  SCIP_NLROW* nlrow, /**< nonlinear row */
1919  SCIP_SET* set, /**< global SCIP settings */
1920  SCIP_STAT* stat, /**< problem statistics data */
1921  SCIP_NLP* nlp /**< current NLP data */
1922  )
1923 {
1924  SCIP_Bool changed;
1925 
1926  if( nlrow->exprtree == NULL )
1927  return SCIP_OKAY;
1928 
1929  SCIP_CALL( SCIPexprtreeRemoveFixedVars(nlrow->exprtree, set, &changed, NULL, NULL) );
1930  if( changed )
1931  {
1932  SCIP_CALL( nlrowExprtreeChanged(nlrow, set, stat, nlp) );
1933  }
1934 
1935  if( SCIPexprtreeGetNVars(nlrow->exprtree) == 0 && SCIPexprtreeGetNParams(nlrow->exprtree) == 0 )
1936  {
1937  /* if expression tree is constant and not parameterized now, remove it */
1938  SCIP_Real exprval;
1939  SCIP_CALL( SCIPexprtreeEval(nlrow->exprtree, NULL, &exprval) );
1940  SCIP_CALL( SCIPnlrowChgConstant(nlrow, set, stat, nlp, nlrow->constant + exprval) );
1941 
1942  SCIP_CALL( SCIPexprtreeFree(&nlrow->exprtree) );
1943  }
1944 
1945  return SCIP_OKAY;
1946 }
1947 
1948 /** removes fixed variable from nonlinear row */
1949 static
1951  SCIP_NLROW* nlrow, /**< nonlinear row */
1952  BMS_BLKMEM* blkmem, /**< block memory */
1953  SCIP_SET* set, /**< global SCIP settings */
1954  SCIP_STAT* stat, /**< problem statistics data */
1955  SCIP_NLP* nlp, /**< current NLP data */
1956  SCIP_VAR* var /**< variable that had been fixed */
1957  )
1958 {
1959  int pos;
1960 
1961  assert(nlrow != NULL);
1962  assert(var != NULL);
1963  assert(!SCIPvarIsActive(var));
1964 
1965  /* search for variable in linear part and remove if existing */
1966  pos = nlrowSearchLinearCoef(nlrow, var);
1967  if( pos >= 0 )
1968  {
1969  SCIP_CALL( nlrowRemoveFixedLinearCoefPos(nlrow, blkmem, set, stat, nlp, pos) );
1970  }
1971 
1972  /* search for variable in quadratic part and remove all fixed quadratic variables if existing */
1973  pos = SCIPnlrowSearchQuadVar(nlrow, var);
1974  if( pos >= 0 )
1975  {
1976  SCIP_CALL( nlrowRemoveFixedQuadVars(nlrow, blkmem, set, stat, nlp) );
1977  }
1978 
1979  /* search for variable in non-quadratic part and remove all fixed variables in expression tree if existing */
1980  if( nlrow->exprtree != NULL && SCIPexprtreeFindVar(nlrow->exprtree, var) >= 0 )
1981  {
1982  SCIP_CALL( nlrowRemoveFixedExprtreeVars(nlrow, set, stat, nlp) );
1983  }
1984 
1985  return SCIP_OKAY;
1986 }
1987 
1988 /*
1989  * public NLP nonlinear row methods
1990  */
1991 
1992 /** create a new nonlinear row
1993  * the new row is already captured
1994  */
1996  SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
1997  BMS_BLKMEM* blkmem, /**< block memory */
1998  SCIP_SET* set, /**< global SCIP settings */
1999  const char* name, /**< name of nonlinear row */
2000  SCIP_Real constant, /**< constant */
2001  int nlinvars, /**< number of linear variables */
2002  SCIP_VAR** linvars, /**< linear variables, or NULL if nlinvars == 0 */
2003  SCIP_Real* lincoefs, /**< linear coefficients, or NULL if nlinvars == 0 */
2004  int nquadvars, /**< number of variables in quadratic terms */
2005  SCIP_VAR** quadvars, /**< variables in quadratic terms, or NULL if nquadvars == 0 */
2006  int nquadelems, /**< number of entries in quadratic term matrix */
2007  SCIP_QUADELEM* quadelems, /**< elements of quadratic term matrix, or NULL if nquadelems == 0 */
2008  SCIP_EXPRTREE* exprtree, /**< expression tree, or NULL */
2009  SCIP_Real lhs, /**< left hand side */
2010  SCIP_Real rhs /**< right hand side */
2011  )
2012 {
2013 #ifndef NDEBUG
2014  int i;
2015 #endif
2016 
2017  assert(nlrow != NULL);
2018  assert(blkmem != NULL);
2019  assert(set != NULL);
2020  assert(name != NULL);
2021  assert(!SCIPsetIsInfinity(set, ABS(constant)));
2022  assert(nlinvars == 0 || linvars != NULL);
2023  assert(nlinvars == 0 || lincoefs != NULL);
2024  assert(nquadvars == 0 || quadvars != NULL);
2025  assert(nquadelems == 0 || quadelems != NULL);
2026  assert(nquadelems == 0 || nquadvars > 0);
2027  assert(SCIPsetIsRelLE(set, lhs, rhs));
2028 
2029  SCIP_ALLOC( BMSallocBlockMemory(blkmem, nlrow) );
2030 
2031  /* constant part */
2032  assert(!SCIPsetIsInfinity(set, REALABS(constant)));
2033  (*nlrow)->constant = constant;
2034 
2035 #ifndef NDEBUG
2036  for( i = 0; i < nlinvars; ++i )
2037  {
2038  assert(linvars[i] != NULL);
2039  assert(!SCIPsetIsInfinity(set, REALABS(lincoefs[i])));
2040  }
2041 #endif
2042 
2043  /* linear part */
2044  (*nlrow)->nlinvars = nlinvars;
2045  (*nlrow)->linvarssize = nlinvars;
2046  if( nlinvars > 0 )
2047  {
2048  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->linvars, linvars, nlinvars) );
2049  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->lincoefs, lincoefs, nlinvars) );
2050  (*nlrow)->linvarssorted = FALSE;
2051  }
2052  else
2053  {
2054  (*nlrow)->linvars = NULL;
2055  (*nlrow)->lincoefs = NULL;
2056  (*nlrow)->linvarssorted = TRUE;
2057  }
2058 
2059  /* quadratic variables */
2060 #ifndef NDEBUG
2061  for( i = 0; i < nquadvars; ++i )
2062  assert(quadvars[i] != NULL);
2063 #endif
2064 
2065  (*nlrow)->nquadvars = nquadvars;
2066  (*nlrow)->quadvarssize = nquadvars;
2067  (*nlrow)->quadvarshash = NULL;
2068  if( nquadvars > 0 )
2069  {
2070  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->quadvars, quadvars, nquadvars) );
2071  SCIP_CALL( nlrowSetupQuadVarsHash(*nlrow, blkmem) );
2072  }
2073  else
2074  {
2075  (*nlrow)->quadvars = NULL;
2076  }
2077 
2078  /* quadratic elements */
2079 #ifndef NDEBUG
2080  for( i = 0; i < nquadelems; ++i )
2081  {
2082  assert(quadelems[i].idx1 >= 0);
2083  assert(quadelems[i].idx1 < nquadvars);
2084  assert(quadelems[i].idx2 >= 0);
2085  assert(quadelems[i].idx2 < nquadvars);
2086  assert(quadelems[i].idx1 <= quadelems[i].idx2);
2087  assert(!SCIPsetIsInfinity(set, REALABS(quadelems[i].coef)));
2088  }
2089 #endif
2090 
2091  (*nlrow)->nquadelems = nquadelems;
2092  (*nlrow)->quadelemssize = nquadelems;
2093  if( nquadelems > 0 )
2094  {
2095  assert(nquadvars > 0);
2096  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->quadelems, quadelems, nquadelems) );
2097  (*nlrow)->quadelemssorted = FALSE;
2098  }
2099  else
2100  {
2101  (*nlrow)->quadelems = NULL;
2102  (*nlrow)->quadelemssorted = TRUE;
2103  }
2104 
2105  /* non-quadratic part */
2106  if( exprtree != NULL )
2107  {
2108  SCIP_CALL( SCIPexprtreeCopy( blkmem, &(*nlrow)->exprtree, exprtree) );
2109  }
2110  else
2111  {
2112  (*nlrow)->exprtree = NULL;
2113  }
2114 
2115  /* left and right hand sides, asserted above that lhs is relatively less equal than rhs */
2116  (*nlrow)->lhs = MIN(lhs, rhs);
2117  (*nlrow)->rhs = MAX(rhs, rhs);
2118 
2119  /* miscellaneous */
2120  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlrow)->name, name, strlen(name)+1) );
2121  (*nlrow)->activity = SCIP_INVALID;
2122  (*nlrow)->validactivitynlp = FALSE;
2123  (*nlrow)->pseudoactivity = SCIP_INVALID;
2124  (*nlrow)->validpsactivitydomchg = FALSE;
2125  (*nlrow)->minactivity = SCIP_INVALID;
2126  (*nlrow)->maxactivity = SCIP_INVALID;
2127  (*nlrow)->validactivitybdsdomchg = FALSE;
2128  (*nlrow)->nlpindex = -1;
2129  (*nlrow)->nlpiindex = -1;
2130  (*nlrow)->nuses = 0;
2131  (*nlrow)->dualsol = 0.0;
2132 
2133  /* capture the nonlinear row */
2134  SCIPnlrowCapture(*nlrow);
2135 
2136  return SCIP_OKAY;
2137 }
2138 
2139 /** create a nonlinear row that is a copy of a given row
2140  * the new row is already captured
2141  */
2143  SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
2144  BMS_BLKMEM* blkmem, /**< block memory */
2145  SCIP_SET* set, /**< global SCIP settings */
2146  SCIP_NLROW* sourcenlrow /**< nonlinear row to copy */
2147  )
2148 {
2149  assert(nlrow != NULL);
2150  assert(blkmem != NULL);
2151  assert(set != NULL);
2152  assert(sourcenlrow != NULL);
2153 
2154  SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, sourcenlrow->name,
2155  sourcenlrow->constant,
2156  sourcenlrow->nlinvars, sourcenlrow->linvars, sourcenlrow->lincoefs,
2157  sourcenlrow->nquadvars, sourcenlrow->quadvars, sourcenlrow->nquadelems, sourcenlrow->quadelems,
2158  sourcenlrow->exprtree,
2159  sourcenlrow->lhs, sourcenlrow->rhs) );
2160 
2161  (*nlrow)->linvarssorted = sourcenlrow->linvarssorted;
2162  (*nlrow)->quadelemssorted = sourcenlrow->quadelemssorted;
2163  (*nlrow)->activity = sourcenlrow->activity;
2164  (*nlrow)->validactivitynlp = sourcenlrow->validactivitynlp;
2165  (*nlrow)->pseudoactivity = sourcenlrow->pseudoactivity;
2166  (*nlrow)->validpsactivitydomchg = sourcenlrow->validpsactivitydomchg;
2167  (*nlrow)->minactivity = sourcenlrow->minactivity;
2168  (*nlrow)->maxactivity = sourcenlrow->maxactivity;
2169  (*nlrow)->validactivitybdsdomchg = sourcenlrow->validactivitybdsdomchg;
2170 
2171  return SCIP_OKAY;
2172 }
2173 
2174 /** create a new nonlinear row from a linear row
2175  * the new row is already captured
2176  */
2178  SCIP_NLROW** nlrow, /**< buffer to store pointer to nonlinear row */
2179  BMS_BLKMEM* blkmem, /**< block memory */
2180  SCIP_SET* set, /**< global SCIP settings */
2181  SCIP_ROW* row /**< the linear row to copy */
2182  )
2183 {
2184  int rownz;
2185 
2186  assert(nlrow != NULL);
2187  assert(blkmem != NULL);
2188  assert(set != NULL);
2189  assert(row != NULL);
2190 
2191  rownz = SCIProwGetNNonz(row);
2192 
2193  if( rownz > 1 )
2194  {
2195  SCIP_VAR** rowvars;
2196  int i;
2197 
2198  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowvars, rownz) );
2199 
2200  for( i = 0; i < rownz; ++i )
2201  {
2202  rowvars[i] = SCIPcolGetVar(SCIProwGetCols(row)[i]);
2203  assert(rowvars[i] != NULL);
2204  }
2205 
2206  SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, SCIProwGetName(row),
2207  SCIProwGetConstant(row),
2208  rownz, rowvars, SCIProwGetVals(row),
2209  0, NULL, 0, NULL,
2210  NULL,
2211  SCIProwGetLhs(row), SCIProwGetRhs(row)) );
2212 
2213  SCIPsetFreeBufferArray(set, &rowvars);
2214  }
2215  else if( rownz == 1 )
2216  {
2217  SCIP_VAR* rowvar;
2218 
2219  rowvar = SCIPcolGetVar(SCIProwGetCols(row)[0]);
2220 
2221  SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, SCIProwGetName(row),
2222  SCIProwGetConstant(row),
2223  1, &rowvar, SCIProwGetVals(row),
2224  0, NULL, 0, NULL,
2225  NULL,
2226  SCIProwGetLhs(row), SCIProwGetRhs(row)) );
2227  }
2228  else
2229  {
2230  SCIP_CALL( SCIPnlrowCreate(nlrow, blkmem, set, SCIProwGetName(row),
2231  SCIProwGetConstant(row),
2232  0, NULL, NULL,
2233  0, NULL, 0, NULL,
2234  NULL,
2235  SCIProwGetLhs(row), SCIProwGetRhs(row)) );
2236  }
2237 
2238  return SCIP_OKAY;
2239 }
2240 
2241 /** frees a nonlinear row */
2243  SCIP_NLROW** nlrow, /**< pointer to NLP row */
2244  BMS_BLKMEM* blkmem /**< block memory */
2245  )
2246 {
2247  assert(blkmem != NULL);
2248  assert(nlrow != NULL);
2249  assert(*nlrow != NULL);
2250  assert((*nlrow)->nuses == 0);
2251  assert((*nlrow)->nlpindex == -1);
2252  assert((*nlrow)->nlpiindex == -1);
2253 
2254  /* linear part */
2255  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->linvars, (*nlrow)->linvarssize);
2256  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->lincoefs, (*nlrow)->linvarssize);
2257 
2258  /* quadratic part */
2259  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->quadvars, (*nlrow)->quadvarssize);
2260  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlrow)->quadelems, (*nlrow)->quadelemssize);
2261  if( (*nlrow)->quadvarshash != NULL )
2262  SCIPhashmapFree(&(*nlrow)->quadvarshash);
2263 
2264  /* non-quadratic part */
2265  if( (*nlrow)->exprtree != NULL )
2266  {
2267  SCIP_CALL( SCIPexprtreeFree(&(*nlrow)->exprtree) );
2268  }
2269 
2270  /* miscellaneous */
2271  BMSfreeBlockMemoryArray(blkmem, &(*nlrow)->name, strlen((*nlrow)->name)+1);
2272 
2273  BMSfreeBlockMemory(blkmem, nlrow);
2274 
2275  return SCIP_OKAY;
2276 }
2277 
2278 /** output nonlinear row to file stream */
2280  SCIP_NLROW* nlrow, /**< NLP row */
2281  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2282  FILE* file /**< output file (or NULL for standard output) */
2283  )
2284 {
2285  int i;
2286 
2287  assert(nlrow != NULL);
2288 
2289  /* print row name */
2290  if( nlrow->name != NULL && nlrow->name[0] != '\0' )
2291  {
2292  SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", nlrow->name);
2293  }
2294 
2295  /* print left hand side */
2296  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", nlrow->lhs);
2297 
2298  /* print constant */
2299  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g ", nlrow->constant);
2300 
2301  /* print linear coefficients */
2302  for( i = 0; i < nlrow->nlinvars; ++i )
2303  {
2304  assert(nlrow->linvars[i] != NULL);
2305  assert(SCIPvarGetName(nlrow->linvars[i]) != NULL);
2306  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", nlrow->lincoefs[i], SCIPvarGetName(nlrow->linvars[i]));
2307  }
2308 
2309  /* print quadratic elements */
2310  for( i = 0; i < nlrow->nquadelems; ++i )
2311  {
2312  assert(SCIPvarGetName(nlrow->quadvars[nlrow->quadelems[i].idx1]) != NULL);
2313  assert(SCIPvarGetName(nlrow->quadvars[nlrow->quadelems[i].idx2]) != NULL);
2314  if( nlrow->quadelems[i].idx1 == nlrow->quadelems[i].idx2 )
2315  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15gsqr(<%s>) ", nlrow->quadelems[i].coef, SCIPvarGetName(nlrow->quadvars[nlrow->quadelems[i].idx1]));
2316  else
2317  SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s><%s> ", nlrow->quadelems[i].coef, SCIPvarGetName(nlrow->quadvars[nlrow->quadelems[i].idx1]), SCIPvarGetName(nlrow->quadvars[nlrow->quadelems[i].idx2]));
2318  }
2319 
2320  /* print non-quadratic part */
2321  if( nlrow->exprtree != NULL )
2322  {
2323  SCIPmessageFPrintInfo(messagehdlr, file, " + ");
2324  SCIP_CALL( SCIPexprtreePrintWithNames(nlrow->exprtree, messagehdlr, file) );
2325  }
2326 
2327  /* print right hand side */
2328  SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", nlrow->rhs);
2329 
2330  return SCIP_OKAY;
2331 }
2332 
2333 /** increases usage counter of NLP nonlinear row */
2335  SCIP_NLROW* nlrow /**< nonlinear row to capture */
2336  )
2337 {
2338  assert(nlrow != NULL);
2339  assert(nlrow->nuses >= 0);
2340 
2341  SCIPdebugMessage("capture nonlinear row <%s> with nuses=%d\n", nlrow->name, nlrow->nuses);
2342  nlrow->nuses++;
2343 }
2344 
2345 /** decreases usage counter of NLP nonlinear row */
2347  SCIP_NLROW** nlrow, /**< nonlinear row to free */
2348  BMS_BLKMEM* blkmem, /**< block memory */
2349  SCIP_SET* set /**< global SCIP settings */
2350  )
2351 {
2352  assert(blkmem != NULL);
2353  assert(nlrow != NULL);
2354  assert(*nlrow != NULL);
2355  assert((*nlrow)->nuses >= 1);
2356 
2357  SCIPdebugMessage("release nonlinear row <%s> with nuses=%d\n", (*nlrow)->name, (*nlrow)->nuses);
2358  (*nlrow)->nuses--;
2359  if( (*nlrow)->nuses == 0 )
2360  {
2361  SCIP_CALL( SCIPnlrowFree(nlrow, blkmem) );
2362  }
2363 
2364  *nlrow = NULL;
2365 
2366  return SCIP_OKAY;
2367 } /*lint !e715*/
2368 
2369 /** ensures, that linear coefficient array of nonlinear row can store at least num entries */
2371  SCIP_NLROW* nlrow, /**< NLP row */
2372  BMS_BLKMEM* blkmem, /**< block memory */
2373  SCIP_SET* set, /**< global SCIP settings */
2374  int num /**< minimum number of entries to store */
2375  )
2376 {
2377  assert(nlrow != NULL);
2378  assert(nlrow->nlinvars <= nlrow->linvarssize);
2379 
2380  if( num > nlrow->linvarssize )
2381  {
2382  int newsize;
2383 
2384  newsize = SCIPsetCalcMemGrowSize(set, num);
2385  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->linvars, nlrow->linvarssize, newsize) );
2386  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->lincoefs, nlrow->linvarssize, newsize) );
2387  nlrow->linvarssize = newsize;
2388  }
2389  assert(num <= nlrow->linvarssize);
2390 
2391  return SCIP_OKAY;
2392 }
2393 
2394 /** adds a previously non existing linear coefficient to an NLP nonlinear row */
2396  SCIP_NLROW* nlrow, /**< NLP nonlinear row */
2397  BMS_BLKMEM* blkmem, /**< block memory */
2398  SCIP_SET* set, /**< global SCIP settings */
2399  SCIP_STAT* stat, /**< problem statistics data */
2400  SCIP_NLP* nlp, /**< current NLP data */
2401  SCIP_VAR* var, /**< variable */
2402  SCIP_Real val /**< value of coefficient */
2403  )
2404 {
2405  /* if row is in NLP already, make sure that only active variables are added */
2406  if( nlrow->nlpindex >= 0 )
2407  {
2408  SCIP_Real constant;
2409 
2410  /* get corresponding active or multi-aggregated variable */
2411  constant = 0.0;
2412  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &val, &constant) );
2413 
2414  /* add constant */
2415  SCIP_CALL( SCIPnlrowChgConstant(nlrow, set, stat, nlp, nlrow->constant + constant) );
2416 
2417  if( val == 0.0 )
2418  /* var has been fixed */
2419  return SCIP_OKAY;
2420 
2421  if( !SCIPvarIsActive(var) )
2422  {
2423  /* var should be multi-aggregated, so call this function recursively */
2424  int i;
2425 
2426  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
2427  for( i = 0; i < SCIPvarGetMultaggrNVars(var); ++i )
2428  {
2429  SCIP_CALL( SCIPnlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, SCIPvarGetMultaggrVars(var)[i], SCIPvarGetMultaggrScalars(var)[i] * val) );
2430  }
2431  return SCIP_OKAY;
2432  }
2433 
2434  /* var is active, so can go on like normal */
2435  }
2436 
2437  SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, val) );
2438 
2439  return SCIP_OKAY;
2440 }
2441 
2442 /** deletes linear coefficient from nonlinear row */
2444  SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
2445  SCIP_SET* set, /**< global SCIP settings */
2446  SCIP_STAT* stat, /**< problem statistics data */
2447  SCIP_NLP* nlp, /**< current NLP data */
2448  SCIP_VAR* var /**< coefficient to be deleted */
2449  )
2450 {
2451  int pos;
2452 
2453  assert(nlrow != NULL);
2454  assert(var != NULL);
2455 
2456  /* 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 */
2457  assert(nlrow->nlpindex == -1 || SCIPvarIsActive(var) );
2458 
2459  /* search the position of the variable in the row's variable vector */
2460  pos = nlrowSearchLinearCoef(nlrow, var);
2461  if( pos == -1 )
2462  {
2463  SCIPerrorMessage("coefficient for variable <%s> doesn't exist in nonlinear row <%s>\n", SCIPvarGetName(var), nlrow->name);
2464  return SCIP_INVALIDDATA;
2465  }
2466  assert(0 <= pos && pos < nlrow->nlinvars);
2467  assert(nlrow->linvars[pos] == var);
2468 
2469  /* delete the variable from the row's variable vector */
2470  SCIP_CALL( nlrowDelLinearCoefPos(nlrow, set, stat, nlp, pos) );
2471 
2472  return SCIP_OKAY;
2473 }
2474 
2475 /** changes or adds a linear coefficient to a nonlinear row */
2477  SCIP_NLROW* nlrow, /**< nonlinear row */
2478  BMS_BLKMEM* blkmem, /**< block memory */
2479  SCIP_SET* set, /**< global SCIP settings */
2480  SCIP_STAT* stat, /**< problem statistics data */
2481  SCIP_NLP* nlp, /**< current NLP data */
2482  SCIP_VAR* var, /**< variable */
2483  SCIP_Real coef /**< new value of coefficient */
2484  )
2485 {
2486  int pos;
2487 
2488  assert(nlrow != NULL);
2489  assert(nlp != NULL);
2490  assert(var != NULL);
2491 
2492  /* search the position of the variable in the row's linvars vector */
2493  pos = nlrowSearchLinearCoef(nlrow, var);
2494 
2495  /* check, if column already exists in the row's linear variables vector */
2496  if( pos == -1 )
2497  {
2498  if( !SCIPsetIsZero(set, coef) )
2499  {
2500  /* add previously not existing coefficient */
2501  SCIP_CALL( nlrowAddLinearCoef(nlrow, blkmem, set, stat, nlp, var, coef) );
2502  }
2503  }
2504  else
2505  {
2506  /* change the coefficient in the row */
2507  SCIP_CALL( nlrowChgLinearCoefPos(nlrow, set, stat, nlp, pos, coef) );
2508  }
2509 
2510  return SCIP_OKAY;
2511 }
2512 
2513 /** ensures, that quadratic variables array of nonlinear row can store at least num entries */
2515  SCIP_NLROW* nlrow, /**< NLP row */
2516  BMS_BLKMEM* blkmem, /**< block memory */
2517  SCIP_SET* set, /**< global SCIP settings */
2518  int num /**< minimum number of entries to store */
2519  )
2520 {
2521  assert(nlrow != NULL);
2522  assert(nlrow->nquadvars <= nlrow->quadvarssize);
2523 
2524  if( num > nlrow->quadvarssize )
2525  {
2526  int newsize;
2527 
2528  newsize = SCIPsetCalcMemGrowSize(set, num);
2529  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->quadvars, nlrow->quadvarssize, newsize) );
2530  nlrow->quadvarssize = newsize;
2531  }
2532  assert(num <= nlrow->quadvarssize);
2533 
2534  return SCIP_OKAY;
2535 }
2536 
2537 /** adds variable to quadvars array of row */
2539  SCIP_NLROW* nlrow, /**< nonlinear row */
2540  BMS_BLKMEM* blkmem, /**< block memory */
2541  SCIP_SET* set, /**< global SCIP settings */
2542  SCIP_VAR* var /**< variable to search for */
2543  )
2544 {
2545  assert(blkmem != NULL);
2546  assert(nlrow != NULL);
2547  assert(var != NULL);
2548 
2549  /* assert that only active variables are added once the row is in the NLP */
2550  assert(nlrow->nlpindex == -1 || SCIPvarIsActive(var) );
2551 
2552  /* assert that variable has not been added already */
2553  assert(SCIPnlrowSearchQuadVar(nlrow, var) == -1);
2554 
2555  SCIP_CALL( SCIPnlrowEnsureQuadVarsSize(nlrow, blkmem, set, nlrow->nquadvars+1) );
2556  nlrow->quadvars[nlrow->nquadvars] = var;
2557  nlrow->nquadvars++;
2558 
2559  if( nlrow->quadvarshash == NULL )
2560  {
2561  SCIP_CALL( nlrowSetupQuadVarsHash(nlrow, blkmem) );
2562  }
2563  else
2564  {
2565  SCIP_CALL( SCIPhashmapInsert(nlrow->quadvarshash, (void*)var, (void*)(size_t)(nlrow->nquadvars-1)) );
2566  }
2567  assert(SCIPnlrowSearchQuadVar(nlrow, var) == nlrow->nquadvars-1);
2568 
2569  return SCIP_OKAY;
2570 }
2571 
2572 /** ensures, that quadratic elements array of nonlinear row can store at least num entries */
2574  SCIP_NLROW* nlrow, /**< NLP row */
2575  BMS_BLKMEM* blkmem, /**< block memory */
2576  SCIP_SET* set, /**< global SCIP settings */
2577  int num /**< minimum number of entries to store */
2578  )
2579 {
2580  assert(nlrow != NULL);
2581  assert(nlrow->nquadelems <= nlrow->quadelemssize);
2582 
2583  if( num > nlrow->quadelemssize )
2584  {
2585  int newsize;
2586 
2587  newsize = SCIPsetCalcMemGrowSize(set, num);
2588  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlrow->quadelems, nlrow->quadelemssize, newsize) );
2589  nlrow->quadelemssize = newsize;
2590  }
2591  assert(num <= nlrow->quadelemssize);
2592 
2593  return SCIP_OKAY;
2594 }
2595 
2596 /** adds a previously non existing quadratic element to an NLP nonlinear row */
2598  SCIP_NLROW* nlrow, /**< NLP nonlinear row */
2599  BMS_BLKMEM* blkmem, /**< block memory */
2600  SCIP_SET* set, /**< global SCIP settings */
2601  SCIP_STAT* stat, /**< problem statistics data */
2602  SCIP_NLP* nlp, /**< current NLP data */
2603  SCIP_QUADELEM elem /**< quadratic element to add */
2604  )
2605 {
2606  SCIP_CALL( nlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, elem) );
2607 
2608  return SCIP_OKAY;
2609 }
2610 
2611 /** deletes quadratic element from nonlinear row */
2613  SCIP_NLROW* nlrow, /**< nonlinear row to be changed */
2614  SCIP_SET* set, /**< global SCIP settings */
2615  SCIP_STAT* stat, /**< problem statistics data */
2616  SCIP_NLP* nlp, /**< current NLP data */
2617  int idx1, /**< index of first variable in element */
2618  int idx2 /**< index of second variable in element */
2619  )
2620 {
2621  int pos;
2622 
2623  assert(nlrow != NULL);
2624  assert(idx1 >= 0);
2625  assert(idx1 < nlrow->nquadvars);
2626  assert(idx2 >= 0);
2627  assert(idx2 < nlrow->nquadvars);
2628  assert(idx1 <= idx2);
2629 
2630  /* search the position of the variable in the row's variable vector */
2631  pos = nlrowSearchQuadElem(nlrow, idx1, idx2);
2632  if( pos == -1 )
2633  {
2634  SCIPerrorMessage("coefficient for index pair (idx1, idx2) doesn't exist in nonlinear row <%s>\n", idx1, idx2, nlrow->name);
2635  return SCIP_INVALIDDATA;
2636  }
2637  assert(0 <= pos && pos < nlrow->nquadelems);
2638 
2639  /* delete the element from the row's quadratic elements array */
2640  SCIP_CALL( nlrowDelQuadElemPos(nlrow, set, stat, nlp, pos) );
2641 
2642  return SCIP_OKAY;
2643 }
2644 
2645 /** changes or adds a quadratic element to a nonlinear row */
2647  SCIP_NLROW* nlrow, /**< nonlinear row */
2648  BMS_BLKMEM* blkmem, /**< block memory */
2649  SCIP_SET* set, /**< global SCIP settings */
2650  SCIP_STAT* stat, /**< problem statistics data */
2651  SCIP_NLP* nlp, /**< current NLP data */
2652  SCIP_QUADELEM elem /**< new quadratic element */
2653  )
2654 {
2655  int pos;
2656 
2657  assert(nlrow != NULL);
2658  assert(nlp != NULL);
2659 
2660  /* search the position of the variable in the row's linvars vector */
2661  pos = nlrowSearchQuadElem(nlrow, elem.idx1, elem.idx2);
2662 
2663  if( pos == -1 )
2664  {
2665  /* add previously not existing element */
2666  SCIP_CALL( nlrowAddQuadElement(nlrow, blkmem, set, stat, nlp, elem) );
2667  }
2668  else
2669  {
2670  /* change the coefficient in the row */
2671  SCIP_CALL( nlrowChgQuadElemPos(nlrow, set, stat, nlp, pos, elem.coef) );
2672  }
2673 
2674  return SCIP_OKAY;
2675 }
2676 
2677 /** replaces an expression tree in nonlinear row */
2679  SCIP_NLROW* nlrow, /**< nonlinear row */
2680  BMS_BLKMEM* blkmem, /**< block memory */
2681  SCIP_SET* set, /**< global SCIP settings */
2682  SCIP_STAT* stat, /**< problem statistics data */
2683  SCIP_NLP* nlp, /**< current NLP data */
2684  SCIP_EXPRTREE* exprtree /**< new expression tree */
2685  )
2686 {
2687  assert(nlrow != NULL);
2688  assert(blkmem != NULL);
2689 
2690  /* free previous expression tree */
2691  if( nlrow->exprtree != NULL )
2692  {
2693  SCIP_CALL( SCIPexprtreeFree(&nlrow->exprtree) );
2694  assert(nlrow->exprtree == NULL);
2695  }
2696 
2697  /* adds new expression tree */
2698  if( exprtree != NULL )
2699  {
2700  SCIP_CALL( SCIPexprtreeCopy(blkmem, &nlrow->exprtree, exprtree) );
2701 
2702  /* if row is already in NLP, ensure that exprtree has only active variables */
2703  if( nlrow->nlpindex >= 0 )
2704  {
2705  SCIP_Bool dummy;
2706  SCIP_CALL( SCIPexprtreeRemoveFixedVars(nlrow->exprtree, set, &dummy, NULL, NULL) );
2707  }
2708  }
2709 
2710  /* notify row about the change */
2711  SCIP_CALL( nlrowExprtreeChanged(nlrow, set, stat, nlp) );
2712 
2713  return SCIP_OKAY;
2714 }
2715 
2716 /** changes a parameter in an expression of a nonlinear row */
2718  SCIP_NLROW* nlrow, /**< nonlinear row */
2719  BMS_BLKMEM* blkmem, /**< block memory */
2720  SCIP_SET* set, /**< global SCIP settings */
2721  SCIP_STAT* stat, /**< problem statistics data */
2722  SCIP_NLP* nlp, /**< current NLP data */
2723  int paramidx, /**< index of parameter in expression tree's parameter array */
2724  SCIP_Real paramval /**< new value of parameter */
2725  )
2726 {
2727  assert(nlrow != NULL);
2728  assert(blkmem != NULL);
2729  assert(nlrow->exprtree != NULL);
2730 
2731  SCIPexprtreeSetParamVal(nlrow->exprtree, paramidx, paramval);
2732 
2733  /* notify row about the change */
2734  SCIP_CALL( nlrowExprtreeParamChanged(nlrow, set, stat, paramidx, nlp) );
2735 
2736  return SCIP_OKAY;
2737 }
2738 
2739 /** changes all parameters in an expression of a nonlinear row */
2741  SCIP_NLROW* nlrow, /**< nonlinear row */
2742  BMS_BLKMEM* blkmem, /**< block memory */
2743  SCIP_SET* set, /**< global SCIP settings */
2744  SCIP_STAT* stat, /**< problem statistics data */
2745  SCIP_NLP* nlp, /**< current NLP data */
2746  SCIP_Real* paramvals /**< new values of parameters */
2747  )
2748 {
2749  assert(nlrow != NULL);
2750  assert(blkmem != NULL);
2751  assert(nlrow->exprtree != NULL);
2752 
2754 
2755  /* notify row about the change */
2756  SCIP_CALL( nlrowExprtreeParamChanged(nlrow, set, stat, -1, nlp) );
2757 
2758  return SCIP_OKAY;
2759 }
2760 
2761 /** changes constant of nonlinear row */
2763  SCIP_NLROW* nlrow, /**< nonlinear row */
2764  SCIP_SET* set, /**< global SCIP settings */
2765  SCIP_STAT* stat, /**< problem statistics data */
2766  SCIP_NLP* nlp, /**< current NLP data */
2767  SCIP_Real constant /**< new constant */
2768  )
2769 {
2770  assert(nlrow != NULL);
2771 
2772  if( !SCIPsetIsEQ(set, nlrow->constant, constant) )
2773  {
2774  nlrow->constant = constant;
2775  SCIP_CALL( nlrowConstantChanged(nlrow, set, stat, nlp) );
2776  }
2777 
2778  return SCIP_OKAY;
2779 }
2780 
2781 /** changes left hand side of nonlinear row */
2783  SCIP_NLROW* nlrow, /**< nonlinear row */
2784  SCIP_SET* set, /**< global SCIP settings */
2785  SCIP_STAT* stat, /**< problem statistics data */
2786  SCIP_NLP* nlp, /**< current NLP data */
2787  SCIP_Real lhs /**< new left hand side */
2788  )
2789 {
2790  assert(nlrow != NULL);
2791 
2792  if( !SCIPsetIsEQ(set, nlrow->lhs, lhs) )
2793  {
2794  nlrow->lhs = lhs;
2795  SCIP_CALL( nlrowSideChanged(nlrow, set, stat, nlp) );
2796  }
2797 
2798  return SCIP_OKAY;
2799 }
2800 
2801 /** changes right hand side of nonlinear row */
2803  SCIP_NLROW* nlrow, /**< nonlinear row */
2804  SCIP_SET* set, /**< global SCIP settings */
2805  SCIP_STAT* stat, /**< problem statistics data */
2806  SCIP_NLP* nlp, /**< current NLP data */
2807  SCIP_Real rhs /**< new right hand side */
2808  )
2809 {
2810  assert(nlrow != NULL);
2811 
2812  if( !SCIPsetIsEQ(set, nlrow->rhs, rhs) )
2813  {
2814  nlrow->rhs = rhs;
2815  SCIP_CALL( nlrowSideChanged(nlrow, set, stat, nlp) );
2816  }
2817 
2818  return SCIP_OKAY;
2819 }
2820 
2821 /** removes (or substitutes) all fixed, negated, aggregated, multi-aggregated variables from the linear, quadratic, and non-quadratic terms of a nonlinear row */
2823  SCIP_NLROW* nlrow, /**< nonlinear row */
2824  BMS_BLKMEM* blkmem, /**< block memory */
2825  SCIP_SET* set, /**< global SCIP settings */
2826  SCIP_STAT* stat, /**< problem statistics data */
2827  SCIP_NLP* nlp /**< current NLP data */
2828  )
2829 {
2830  SCIP_CALL( nlrowRemoveFixedLinearCoefs(nlrow, blkmem, set, stat, nlp) );
2831  SCIP_CALL( nlrowRemoveFixedQuadVars(nlrow, blkmem, set, stat, nlp) );
2832  SCIP_CALL( nlrowRemoveFixedExprtreeVars(nlrow, set, stat, nlp) );
2833 
2834  return SCIP_OKAY;
2835 }
2836 
2837 /** recalculates the current activity of a nonlinear row */
2839  SCIP_NLROW* nlrow, /**< nonlinear row */
2840  SCIP_SET* set, /**< global SCIP settings */
2841  SCIP_STAT* stat, /**< problem statistics */
2842  SCIP_NLP* nlp /**< current NLP data */
2843  )
2844 {
2845  SCIP_Real val1, val2;
2846  int i;
2847  int previdx1;
2848 
2849  assert(nlrow != NULL);
2850  assert(stat != NULL);
2851  assert(nlp != NULL);
2852 
2854  {
2855  SCIPerrorMessage("do not have NLP solution for computing NLP activity\n");
2856  return SCIP_ERROR;
2857  }
2858 
2859  nlrow->activity = nlrow->constant;
2860  for( i = 0; i < nlrow->nlinvars; ++i )
2861  {
2862  assert(nlrow->linvars[i] != NULL);
2863  assert(SCIPvarGetNLPSol(nlrow->linvars[i]) < SCIP_INVALID);
2864 
2865  nlrow->activity += nlrow->lincoefs[i] * SCIPvarGetNLPSol(nlrow->linvars[i]);
2866  }
2867 
2868  val1 = 0.0; /* for lint */
2869  previdx1 = -1;
2870  for( i = 0; i < nlrow->nquadelems; ++i )
2871  {
2872  /* if first index of quadelems is the same as in last round, val1 is still up to date */
2873  if( previdx1 != nlrow->quadelems[i].idx1 )
2874  {
2875  previdx1 = nlrow->quadelems[i].idx1;
2876  val1 = SCIPvarGetNLPSol(nlrow->quadvars[previdx1]);
2877  assert(val1 < SCIP_INVALID);
2878 
2879  if( val1 == 0.0 )
2880  continue;
2881  }
2882 
2883  val2 = SCIPvarGetNLPSol(nlrow->quadvars[nlrow->quadelems[i].idx2]);
2884  assert(val2 < SCIP_INVALID);
2885 
2886  nlrow->activity += nlrow->quadelems[i].coef * val1 * val2;
2887  }
2888 
2889  if( nlrow->exprtree != NULL )
2890  {
2891  SCIP_Real* varvals;
2892  int n;
2893 
2894  n = SCIPexprtreeGetNVars(nlrow->exprtree);
2895 
2896  SCIP_CALL( SCIPsetAllocBufferArray(set, &varvals, n) );
2897 
2898  for( i = 0; i < n; ++i )
2899  {
2900  varvals[i] = SCIPvarGetNLPSol(SCIPexprtreeGetVars(nlrow->exprtree)[i]);
2901  }
2902 
2903  SCIP_CALL( SCIPexprtreeEval(nlrow->exprtree, varvals, &val1) );
2904  nlrow->activity += val1;
2905 
2906  SCIPsetFreeBufferArray(set, &varvals);
2907  }
2908 
2909  nlrow->validactivitynlp = stat->nnlps;
2910 
2911  return SCIP_OKAY;
2912 }
2913 
2914 /** returns the activity of a nonlinear row in the current NLP solution */
2916  SCIP_NLROW* nlrow, /**< nonlinear row */
2917  SCIP_SET* set, /**< global SCIP settings */
2918  SCIP_STAT* stat, /**< problem statistics */
2919  SCIP_NLP* nlp, /**< current NLP data */
2920  SCIP_Real* activity /**< buffer to store activity value */
2921  )
2922 {
2923  assert(nlrow != NULL);
2924  assert(stat != NULL);
2925  assert(activity != NULL);
2926 
2927  assert(nlrow->validactivitynlp <= stat->nnlps);
2928 
2929  if( nlrow->validactivitynlp != stat->nnlps )
2930  {
2931  SCIP_CALL( SCIPnlrowRecalcNLPActivity(nlrow, set, stat, nlp) );
2932  }
2933  assert(nlrow->validactivitynlp == stat->nnlps);
2934  assert(nlrow->activity < SCIP_INVALID);
2935 
2936  *activity = nlrow->activity;
2937 
2938  return SCIP_OKAY;
2939 }
2940 
2941 /** gives the feasibility of a nonlinear row in the current NLP solution: negative value means infeasibility */
2943  SCIP_NLROW* nlrow, /**< nonlinear row */
2944  SCIP_SET* set, /**< global SCIP settings */
2945  SCIP_STAT* stat, /**< problem statistics */
2946  SCIP_NLP* nlp, /**< current NLP data */
2947  SCIP_Real* feasibility /**< buffer to store feasibility value */
2948  )
2949 {
2950  SCIP_Real activity;
2951 
2952  assert(nlrow != NULL);
2953  assert(feasibility != NULL);
2954 
2955  SCIP_CALL( SCIPnlrowGetNLPActivity(nlrow, set, stat, nlp, &activity) );
2956  *feasibility = MIN(nlrow->rhs - activity, activity - nlrow->lhs);
2957 
2958  return SCIP_OKAY;
2959 }
2960 
2961 /** calculates the current pseudo activity of a nonlinear row */
2963  SCIP_NLROW* nlrow, /**< nonlinear row */
2964  SCIP_SET* set, /**< global SCIP settings */
2965  SCIP_STAT* stat /**< problem statistics */
2966  )
2967 {
2968  SCIP_Real val1, val2;
2969  int i;
2970 
2971  assert(nlrow != NULL);
2972  assert(stat != NULL);
2973 
2974  nlrow->pseudoactivity = nlrow->constant;
2975  for( i = 0; i < nlrow->nlinvars; ++i )
2976  {
2977  assert(nlrow->linvars[i] != NULL);
2978 
2979  val1 = SCIPvarGetBestBoundLocal(nlrow->linvars[i]);
2980  nlrow->pseudoactivity += nlrow->lincoefs[i] * val1;
2981  }
2982 
2983  for( i = 0; i < nlrow->nquadelems; ++i )
2984  {
2985  val1 = SCIPvarGetBestBoundLocal(nlrow->quadvars[nlrow->quadelems[i].idx1]);
2986  if( val1 == 0.0 )
2987  continue;
2988 
2989  val2 = SCIPvarGetBestBoundLocal(nlrow->quadvars[nlrow->quadelems[i].idx2]);
2990  nlrow->pseudoactivity += nlrow->quadelems[i].coef * val1 * val2;
2991  }
2992 
2993  if( nlrow->exprtree != NULL )
2994  {
2995  SCIP_Real* varvals;
2996  int n;
2997 
2998  n = SCIPexprtreeGetNVars(nlrow->exprtree);
2999 
3000  SCIP_CALL( SCIPsetAllocBufferArray(set, &varvals, n) );
3001 
3002  for( i = 0; i < n; ++i )
3003  varvals[i] = SCIPvarGetBestBoundLocal(SCIPexprtreeGetVars(nlrow->exprtree)[i]);
3004 
3005  SCIP_CALL( SCIPexprtreeEval(nlrow->exprtree, varvals, &val1) );
3006  nlrow->pseudoactivity += val1;
3007 
3008  SCIPsetFreeBufferArray(set, &varvals);
3009  }
3010 
3011  nlrow->validpsactivitydomchg = stat->domchgcount;
3012 
3013  return SCIP_OKAY;
3014 }
3015 
3016 /** returns the pseudo activity of a nonlinear row in the current pseudo solution */
3018  SCIP_NLROW* nlrow, /**< nonlinear row */
3019  SCIP_SET* set, /**< global SCIP settings */
3020  SCIP_STAT* stat, /**< problem statistics */
3021  SCIP_Real* pseudoactivity /**< buffer to store pseudo activity value */
3022  )
3023 {
3024  assert(nlrow != NULL);
3025  assert(stat != NULL);
3026  assert(pseudoactivity != NULL);
3027  assert(nlrow->validpsactivitydomchg <= stat->domchgcount);
3028 
3029  /* check, if pseudo activity has to be calculated */
3030  if( nlrow->validpsactivitydomchg != stat->domchgcount )
3031  {
3032  SCIP_CALL( SCIPnlrowRecalcPseudoActivity(nlrow, set, stat) );
3033  }
3034  assert(nlrow->validpsactivitydomchg == stat->domchgcount);
3035  assert(nlrow->pseudoactivity < SCIP_INVALID);
3036 
3037  *pseudoactivity = nlrow->pseudoactivity;
3038 
3039  return SCIP_OKAY;
3040 }
3041 
3042 /** returns the pseudo feasibility of a nonlinear row in the current pseudo solution: negative value means infeasibility */
3044  SCIP_NLROW* nlrow, /**< nonlinear row */
3045  SCIP_SET* set, /**< global SCIP settings */
3046  SCIP_STAT* stat, /**< problem statistics */
3047  SCIP_Real* pseudofeasibility /**< buffer to store pseudo feasibility value */
3048  )
3049 {
3050  SCIP_Real pseudoactivity;
3051 
3052  assert(nlrow != NULL);
3053  assert(stat != NULL);
3054  assert(pseudofeasibility != NULL);
3055 
3056  SCIP_CALL( SCIPnlrowGetPseudoActivity(nlrow, set, stat, &pseudoactivity) );
3057  *pseudofeasibility = MIN(nlrow->rhs - pseudoactivity, pseudoactivity - nlrow->lhs);
3058 
3059  return SCIP_OKAY;
3060 }
3061 
3062 /** returns the activity of a nonlinear row for a given solution */
3064  SCIP_NLROW* nlrow, /**< nonlinear row */
3065  SCIP_SET* set, /**< global SCIP settings */
3066  SCIP_STAT* stat, /**< problem statistics data */
3067  SCIP_SOL* sol, /**< primal CIP solution */
3068  SCIP_Real* activity /**< buffer to store activity value */
3069  )
3070 {
3071  SCIP_Real inf;
3072  SCIP_Real val1, val2;
3073  int i;
3074 
3075  assert(nlrow != NULL);
3076  assert(set != NULL);
3077  assert(stat != NULL);
3078  assert(activity != NULL);
3079 
3080  *activity = nlrow->constant;
3081  for( i = 0; i < nlrow->nlinvars; ++i )
3082  {
3083  assert(nlrow->linvars[i] != NULL);
3084 
3085  val1 = SCIPsolGetVal(sol, set, stat, nlrow->linvars[i]);
3086  if( val1 == SCIP_UNKNOWN ) /*lint !e777*/
3087  {
3088  *activity = SCIP_INVALID;
3089  return SCIP_OKAY;
3090  }
3091  *activity += nlrow->lincoefs[i] * val1;
3092  }
3093 
3094  for( i = 0; i < nlrow->nquadelems; ++i )
3095  {
3096  val1 = SCIPsolGetVal(sol, set, stat, nlrow->quadvars[nlrow->quadelems[i].idx1]);
3097  if( val1 == SCIP_UNKNOWN ) /*lint !e777*/
3098  {
3099  *activity = SCIP_INVALID;
3100  return SCIP_OKAY;
3101  }
3102  if( val1 == 0.0 )
3103  continue;
3104 
3105  val2 = SCIPsolGetVal(sol, set, stat, nlrow->quadvars[nlrow->quadelems[i].idx2]);
3106  if( val2 == SCIP_UNKNOWN ) /*lint !e777*/
3107  {
3108  *activity = SCIP_INVALID;
3109  return SCIP_OKAY;
3110  }
3111  *activity += nlrow->quadelems[i].coef * val1 * val2;
3112  }
3113 
3114  if( nlrow->exprtree != NULL )
3115  {
3116  SCIP_Real* varvals;
3117  int n;
3118 
3119  n = SCIPexprtreeGetNVars(nlrow->exprtree);
3120 
3121  SCIP_CALL( SCIPsetAllocBufferArray(set, &varvals, n) );
3122 
3123  for( i = 0; i < n; ++i )
3124  {
3125  varvals[i] = SCIPsolGetVal(sol, set, stat, SCIPexprtreeGetVars(nlrow->exprtree)[i]);
3126  if( varvals[i] == SCIP_UNKNOWN ) /*lint !e777*/
3127  {
3128  *activity = SCIP_INVALID;
3129  SCIPsetFreeBufferArray(set, &varvals);
3130  return SCIP_OKAY;
3131  }
3132  }
3133 
3134  SCIP_CALL( SCIPexprtreeEval(nlrow->exprtree, varvals, &val1) );
3135  *activity += val1;
3136 
3137  SCIPsetFreeBufferArray(set, &varvals);
3138  }
3139 
3140  inf = SCIPsetInfinity(set);
3141  *activity = MAX(*activity, -inf);
3142  *activity = MIN(*activity, +inf);
3143 
3144  return SCIP_OKAY;
3145 }
3146 
3147 /** returns the feasibility of a nonlinear row for the given solution */
3149  SCIP_NLROW* nlrow, /**< nonlinear row */
3150  SCIP_SET* set, /**< global SCIP settings */
3151  SCIP_STAT* stat, /**< problem statistics data */
3152  SCIP_SOL* sol, /**< primal CIP solution */
3153  SCIP_Real* feasibility /**< buffer to store feasibility value */
3154  )
3155 {
3156  SCIP_Real activity;
3157 
3158  assert(nlrow != NULL);
3159  assert(feasibility != NULL);
3160 
3161  SCIP_CALL( SCIPnlrowGetSolActivity(nlrow, set, stat, sol, &activity) );
3162 
3163  *feasibility = MIN(nlrow->rhs - activity, activity - nlrow->lhs);
3164 
3165  return SCIP_OKAY;
3166 }
3167 
3168 /** returns the minimal activity of a nonlinear row w.r.t. the variables' bounds */
3170  SCIP_NLROW* nlrow, /**< nonlinear row */
3171  SCIP_SET* set, /**< global SCIP settings */
3172  SCIP_STAT* stat, /**< problem statistics data */
3173  SCIP_Real* minactivity, /**< buffer to store minimal activity, or NULL */
3174  SCIP_Real* maxactivity /**< buffer to store maximal activity, or NULL */
3175  )
3176 {
3177  assert(nlrow != NULL);
3178  assert(set != NULL);
3179  assert(stat != NULL);
3180  assert(nlrow->validactivitybdsdomchg <= stat->domchgcount);
3181 
3182  /* check, if activity bounds has to be calculated */
3183  if( nlrow->validactivitybdsdomchg != stat->domchgcount )
3184  {
3185  SCIP_CALL( nlrowCalcActivityBounds(nlrow, set, stat) );
3186  }
3187  assert(nlrow->validactivitybdsdomchg == stat->domchgcount);
3188  assert(nlrow->minactivity < SCIP_INVALID);
3189  assert(nlrow->maxactivity < SCIP_INVALID);
3190 
3191  if( minactivity != NULL )
3192  *minactivity = nlrow->minactivity;
3193  if( maxactivity != NULL )
3194  *maxactivity = nlrow->maxactivity;
3195 
3196  return SCIP_OKAY;
3197 }
3198 
3199 /** returns whether the nonlinear row is redundant w.r.t. the variables' bounds */
3201  SCIP_NLROW* nlrow, /**< nonlinear row */
3202  SCIP_SET* set, /**< global SCIP settings */
3203  SCIP_STAT* stat, /**< problem statistics data */
3204  SCIP_Bool* isredundant /**< buffer to store whether row is redundant */
3205  )
3206 {
3207  SCIP_Real minactivity;
3208  SCIP_Real maxactivity;
3209 
3210  assert(nlrow != NULL);
3211  assert(set != NULL);
3212  assert(isredundant != NULL);
3213 
3214  SCIP_CALL( SCIPnlrowGetActivityBounds(nlrow, set, stat, &minactivity, &maxactivity) );
3215 
3216  *isredundant = TRUE;
3217  if( (!SCIPsetIsInfinity(set, -nlrow->lhs) && SCIPsetIsFeasLT(set, minactivity, nlrow->lhs)) ||
3218  ( !SCIPsetIsInfinity(set, nlrow->rhs) && SCIPsetIsFeasGT(set, maxactivity, nlrow->rhs)) )
3219  *isredundant = FALSE;
3220 
3221  return SCIP_OKAY;
3222 }
3223 
3224 /** gets constant */
3226  SCIP_NLROW* nlrow /**< NLP row */
3227  )
3228 {
3229  assert(nlrow != NULL);
3230 
3231  return nlrow->constant;
3232 }
3233 
3234 /** gets number of variables of linear part */
3236  SCIP_NLROW* nlrow /**< NLP row */
3237  )
3238 {
3239  assert(nlrow != NULL);
3240 
3241  return nlrow->nlinvars;
3242 }
3243 
3244 /** gets array with variables of linear part */
3246  SCIP_NLROW* nlrow /**< NLP row */
3247  )
3248 {
3249  assert(nlrow != NULL);
3250 
3251  return nlrow->linvars;
3252 }
3253 
3254 /** gets array with coefficients in linear part */
3256  SCIP_NLROW* nlrow /**< NLP row */
3257  )
3258 {
3259  assert(nlrow != NULL);
3260 
3261  return nlrow->lincoefs;
3262 }
3263 
3264 /** gets number of quadratic variables in quadratic part */
3266  SCIP_NLROW* nlrow /**< NLP row */
3267  )
3268 {
3269  assert(nlrow != NULL);
3270 
3271  return nlrow->nquadvars;
3272 }
3273 
3274 /** gets quadratic variables in quadratic part */
3276  SCIP_NLROW* nlrow /**< NLP row */
3277  )
3278 {
3279  assert(nlrow != NULL);
3280 
3281  return nlrow->quadvars;
3282 }
3283 
3284 /** gives position of variable in quadvars array of row, or -1 if not found */
3286  SCIP_NLROW* nlrow, /**< nonlinear row */
3287  SCIP_VAR* var /**< variable to search for */
3288  )
3289 {
3290  int pos;
3291 
3292  assert(nlrow != NULL);
3293  assert(var != NULL);
3294 
3295  if( nlrow->quadvarshash != NULL )
3296  {
3297  pos = SCIPhashmapExists(nlrow->quadvarshash, var) ? (int)(size_t)SCIPhashmapGetImage(nlrow->quadvarshash, var) : -1;
3298  }
3299  else
3300  {
3301  for( pos = nlrow->nquadvars-1; pos >= 0; --pos )
3302  if( nlrow->quadvars[pos] == var )
3303  break;
3304  }
3305 
3306  assert(pos == -1 || (pos < nlrow->nquadvars && nlrow->quadvars[pos] == var));
3307 
3308  return pos;
3309 }
3310 
3311 /** gets number of quadratic elements in quadratic part */
3313  SCIP_NLROW* nlrow /**< NLP row */
3314  )
3315 {
3316  assert(nlrow != NULL);
3317 
3318  return nlrow->nquadelems;
3319 }
3320 
3321 /** gets quadratic elements in quadratic part */
3323  SCIP_NLROW* nlrow /**< NLP row */
3324  )
3325 {
3326  assert(nlrow != NULL);
3327 
3328  return nlrow->quadelems;
3329 }
3330 
3331 /** gets array with coefficients in linear part */
3333  SCIP_NLROW* nlrow, /**< NLP row */
3334  int* nquadvars, /**< buffer to store number of variables in quadratic term, or NULL if not of interest */
3335  SCIP_VAR*** quadvars, /**< buffer to store pointer to array of variables in quadratic term, or NULL if not of interest */
3336  int* nquadelems, /**< buffer to store number of entries in quadratic term, or NULL if not of interest */
3337  SCIP_QUADELEM** quadelems /**< buffer to store pointer to array of entries in quadratic term, or NULL if not of interest */
3338  )
3339 {
3340  assert(nlrow != NULL);
3341 
3342  if( nquadvars != NULL )
3343  *nquadvars = nlrow->nquadvars;
3344  if( quadvars != NULL )
3345  *quadvars = nlrow->quadvars;
3346  if( nquadelems != NULL )
3347  *nquadelems = nlrow->nquadelems;
3348  if( quadelems != NULL )
3349  *quadelems = nlrow->quadelems;
3350 }
3351 
3352 /** gets expression tree */
3354  SCIP_NLROW* nlrow /**< NLP row */
3355  )
3356 {
3357  assert(nlrow != NULL);
3358 
3359  return nlrow->exprtree;
3360 }
3361 
3362 /** returns the left hand side of a nonlinear row */
3364  SCIP_NLROW* nlrow /**< NLP row */
3365  )
3366 {
3367  assert(nlrow != NULL);
3368 
3369  return nlrow->lhs;
3370 }
3371 
3372 /** returns the right hand side of a nonlinear row */
3374  SCIP_NLROW* nlrow /**< NLP row */
3375  )
3376 {
3377  assert(nlrow != NULL);
3378 
3379  return nlrow->rhs;
3380 }
3381 
3382 /** returns the name of a nonlinear row */
3383 const char* SCIPnlrowGetName(
3384  SCIP_NLROW* nlrow /**< NLP row */
3385  )
3386 {
3387  assert(nlrow != NULL);
3388 
3389  return nlrow->name;
3390 }
3391 
3392 /** gets position of a nonlinear row in current NLP, or -1 if not in NLP */
3394  SCIP_NLROW* nlrow /**< NLP row */
3395  )
3396 {
3397  assert(nlrow != NULL);
3398 
3399  return nlrow->nlpindex;
3400 }
3401 
3402 /** returns TRUE iff row is member of current NLP */
3404  SCIP_NLROW* nlrow /**< NLP row */
3405  )
3406 {
3407  assert(nlrow != NULL);
3408 
3409  return nlrow->nlpindex != -1;
3410 }
3411 
3412 /** gets the dual NLP solution of a nlrow
3413  * 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
3414  */
3416  SCIP_NLROW* nlrow /**< NLP row */
3417  )
3418 {
3419  assert(nlrow != NULL);
3420 
3421  return nlrow->nlpiindex >= 0 ? nlrow->dualsol : 0.0;
3422 }
3423 
3424 /*
3425  * private NLP methods
3426  */
3427 
3428 /** announces, that a row of the NLP was modified
3429  * adjusts status of current solution
3430  * calling method has to ensure that change is passed to the NLPI!
3431  */
3432 static
3434  SCIP_NLP* nlp, /**< current NLP data */
3435  SCIP_SET* set, /**< global SCIP settings */
3436  SCIP_STAT* stat, /**< problem statistics data */
3437  SCIP_NLROW* nlrow /**< nonlinear row which was changed */
3438  )
3439 {
3440  assert(nlp != NULL);
3441  assert(nlrow != NULL);
3442  assert(!nlp->indiving);
3443  assert(nlrow->nlpindex >= 0);
3444 
3445  /* nlrow is a row in the NLP, so changes effect feasibility */
3446  /* if we have a feasible NLP solution and it satisfies the modified row, then it is still feasible
3447  * if the NLP was globally or locally infeasible or unbounded, then this may not be the case anymore
3448  */
3449  if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
3450  {
3451  SCIP_Real feasibility;
3452  SCIP_CALL( SCIPnlrowGetNLPFeasibility(nlrow, set, stat, nlp, &feasibility) );
3453  if( !SCIPsetIsFeasNegative(set, feasibility) )
3455  else
3457  }
3458  else
3459  {
3461  }
3462 
3463  return SCIP_OKAY;
3464 }
3465 
3466 /** adds a set of nonlinear rows to the NLP and captures them */
3467 static
3469  SCIP_NLP* nlp, /**< NLP data */
3470  BMS_BLKMEM* blkmem, /**< block memory */
3471  SCIP_SET* set, /**< global SCIP settings */
3472  SCIP_STAT* stat, /**< problem statistics data */
3473  int nnlrows, /**< number of nonlinear rows to add */
3474  SCIP_NLROW** nlrows /**< nonlinear rows to add */
3475  )
3476 {
3477 #ifndef NDEBUG
3478  int i;
3479 #endif
3480  int j;
3481  SCIP_NLROW* nlrow;
3482 
3483  assert(nlp != NULL);
3484  assert(blkmem != NULL);
3485  assert(set != NULL);
3486  assert(nlrows != NULL || nnlrows == 0);
3487  assert(!nlp->indiving);
3488 
3489  SCIP_CALL( SCIPnlpEnsureNlRowsSize(nlp, blkmem, set, nlp->nnlrows + nnlrows) );
3490 
3491  for( j = 0; j < nnlrows; ++j )
3492  {
3493  nlrow = nlrows[j]; /*lint !e613*/
3494 
3495  /* assert that row is not in NLP (or even NLPI) yet */
3496  assert(nlrow->nlpindex == -1);
3497  assert(nlrow->nlpiindex == -1);
3498 
3499  /* make sure there are only active variables in row */
3500  SCIP_CALL( SCIPnlrowRemoveFixedVars(nlrow, blkmem, set, stat, nlp) );
3501 
3502 #ifndef NDEBUG
3503  /* assert that variables of row are in NLP */
3504  for( i = 0; i < nlrow->nlinvars; ++i )
3505  assert(SCIPhashmapExists(nlp->varhash, nlrow->linvars[i]));
3506 
3507  for( i = 0; i < nlrow->nquadvars; ++i )
3508  assert(SCIPhashmapExists(nlp->varhash, nlrow->quadvars[i]));
3509 
3510  if( nlrow->exprtree )
3511  {
3512  int n;
3513 
3514  n = SCIPexprtreeGetNVars(nlrow->exprtree);
3515  assert(SCIPexprtreeGetVars(nlrow->exprtree) != NULL || n == 0);
3516 
3517  for( i = 0; i < n; ++i )
3518  assert(SCIPhashmapExists(nlp->varhash, SCIPexprtreeGetVars(nlrow->exprtree)[i]));
3519  }
3520 #endif
3521 
3522  /* add row to NLP and capture it */
3523  nlp->nlrows[nlp->nnlrows + j] = nlrow;
3524  nlrow->nlpindex = nlp->nnlrows + j;
3525 
3526  SCIPnlrowCapture(nlrow);
3527 
3528  /* if we have a feasible NLP solution and it satisfies the new solution, then it is still feasible
3529  * if the NLP was globally or locally infeasible, then it stays that way
3530  * if the NLP was unbounded, then this may not be the case anymore
3531  */
3532  if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
3533  {
3534  SCIP_Real feasibility;
3535  SCIP_CALL( SCIPnlrowGetNLPFeasibility(nlrow, set, stat, nlp, &feasibility) );
3536  if( !SCIPsetIsFeasNegative(set, feasibility) )
3538  else
3540  }
3541  else if( nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
3542  {
3544  }
3545  }
3546 
3547  nlp->nnlrows += nnlrows;
3548  nlp->nunflushednlrowadd += nnlrows;
3549 
3550  return SCIP_OKAY;
3551 }
3552 
3553 /** moves a nonlinear row to a different place, and updates all corresponding data structures */
3554 static
3556  SCIP_NLP* nlp, /**< NLP data structure */
3557  int oldpos, /**< old position of nonlinear row */
3558  int newpos /**< new position of nonlinear row */
3559  )
3560 {
3561  assert(nlp != NULL);
3562  assert(0 <= oldpos && oldpos < nlp->nnlrows);
3563  assert(0 <= newpos && newpos < nlp->nnlrows);
3564  assert(nlp->nlrows[oldpos] != NULL);
3565 
3566  if( oldpos == newpos )
3567  return;
3568 
3569  nlp->nlrows[newpos] = nlp->nlrows[oldpos];
3570  nlp->nlrows[newpos]->nlpindex = newpos;
3571 }
3572 
3573 /** deletes nonlinear row with given position from NLP */
3574 static
3576  SCIP_NLP* nlp, /**< NLP data structure */
3577  BMS_BLKMEM* blkmem, /**< block memory */
3578  SCIP_SET* set, /**< global SCIP settings */
3579  int pos /**< position of nonlinear row that is to be removed */
3580  )
3581 {
3582  SCIP_NLROW* nlrow;
3583 
3584  assert(nlp != NULL);
3585  assert(blkmem != NULL);
3586  assert(set != NULL);
3587  assert(pos >= 0);
3588  assert(pos < nlp->nnlrows);
3589  assert(!nlp->indiving);
3590 
3591  nlrow = nlp->nlrows[pos];
3592  assert(nlrow != NULL);
3593  assert(nlrow->nlpindex == pos);
3594 
3595  /* if row is in NLPI, then mark that it has to be removed in the next flush
3596  * if row was not in NLPI yet, then we have one unflushed nlrow addition less */
3597  if( nlrow->nlpiindex >= 0 )
3598  {
3599  assert(nlrow->nlpiindex < nlp->nnlrows_solver);
3600  nlp->nlrowmap_nlpi2nlp[nlrow->nlpiindex] = -1;
3601  nlrow->nlpiindex = -1;
3602  ++nlp->nunflushednlrowdel;
3603  }
3604  else
3605  {
3606  assert(nlrow->nlpiindex == -1);
3607  --nlp->nunflushednlrowadd;
3608  }
3609 
3610  /* move NLP row from the end to pos and mark nlrow to be not in NLP anymore */
3611  nlpMoveNlrow(nlp, nlp->nnlrows-1, pos);
3612  nlrow->nlpindex = -1;
3613 
3614  /* forget about restriction */
3615  SCIP_CALL( SCIPnlrowRelease(&nlrow, blkmem, set) );
3616  --nlp->nnlrows;
3617 
3618  if( nlp->solstat < SCIP_NLPSOLSTAT_LOCOPT )
3620  else if( nlp->solstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE )
3622 
3623  return SCIP_OKAY;
3624 }
3625 
3626 /** updates bounds on a variable in the NLPI problem */
3627 static
3629  SCIP_NLP* nlp, /**< NLP data */
3630  SCIP_SET* set, /**< global SCIP settings */
3631  SCIP_VAR* var, /**< variable which bounds have changed */
3632  SCIP_Bool tightened /**< whether the bound change was a bound tightening */
3633  )
3634 {
3635  int pos;
3636  SCIP_Real lb;
3637  SCIP_Real ub;
3638 
3639  assert(nlp != NULL);
3640  assert(var != NULL);
3641  assert(SCIPhashmapExists(nlp->varhash, var));
3642 
3643  /* original variable bounds are ignored during diving
3644  * (all variable bounds are reset to their current value in exitDiving) */
3645  if( nlp->indiving )
3646  return SCIP_OKAY;
3647 
3648  /* get position of variable in NLP */
3649  pos = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, var);
3650 
3651  /* if variable not in NLPI yet, nothing to do */
3652  if( nlp->varmap_nlp2nlpi[pos] == -1 )
3653  return SCIP_OKAY;
3654 
3655  /* update bounds in NLPI problem */
3656  assert(nlp->solver != NULL);
3657  assert(nlp->problem != NULL);
3658 
3659  pos = nlp->varmap_nlp2nlpi[pos];
3660  lb = SCIPvarGetLbLocal(var);
3661  ub = SCIPvarGetUbLocal(var);
3662  SCIP_CALL( SCIPnlpiChgVarBounds(nlp->solver, nlp->problem, 1, &pos, &lb, &ub) );
3663 
3664  /* if we have a feasible NLP solution and it satisfies the new bounds, then it is still feasible
3665  * if the NLP was globally or locally infeasible and we tightened a bound, then it stays that way
3666  * if the NLP was unbounded and we tightened a bound, then this may not be the case anymore
3667  */
3668  if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
3669  {
3670  if( !tightened ||
3671  ((SCIPsetIsInfinity(set, -lb) || SCIPsetIsFeasLE(set, lb, SCIPvarGetNLPSol(var))) &&
3672  (SCIPsetIsInfinity(set, ub) || SCIPsetIsFeasGE(set, ub, SCIPvarGetNLPSol(var)))) )
3674  else
3676  }
3677  else if( !tightened || nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
3678  {
3680  }
3681 
3682  return SCIP_OKAY;
3683 }
3684 
3685 /** updates coefficient of a variable in the objective */
3686 static
3688  SCIP_NLP* nlp, /**< NLP data */
3689  SCIP_VAR* var /**< variable which bounds have changed */
3690  )
3691 {
3692  int pos;
3693  int objidx;
3694  SCIP_Real coef;
3695 
3696  assert(nlp != NULL);
3697  assert(var != NULL);
3698  assert(SCIPhashmapExists(nlp->varhash, var));
3699 
3700  /* if the objective in the NLPI is not up to date, then we do not need to do something here */
3701  if( !nlp->objflushed )
3702  return SCIP_OKAY;
3703 
3704  /* original objective is ignored during diving
3705  * we just need to remember that at end of diving we have to flush the objective */
3706  if( nlp->indiving )
3707  {
3708  nlp->objflushed = FALSE;
3709  return SCIP_OKAY;
3710  }
3711 
3712  /* get position of variable in NLP and objective coefficient */
3713  pos = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, var);
3714  assert(nlp->varmap_nlp2nlpi[pos] == -1 || nlp->solver != NULL);
3715 
3716  /* actually we only need to remember flushing the objective if we also have an NLPI */
3717  if( nlp->solver == NULL )
3718  return SCIP_OKAY;
3719 
3720  coef = SCIPvarGetObj(var);
3721 
3722  /* if variable not in NLPI yet, then we only need to remember to update the objective after variable additions were flushed */
3723  if( nlp->varmap_nlp2nlpi[pos] == -1 && coef != 0.0 )
3724  {
3725  nlp->objflushed = FALSE;
3726 
3727  return SCIP_OKAY;
3728  }
3729 
3730  /* if we are here, then the objective in the NLPI is up to date,
3731  * we keep it this way by changing the coefficient of var in the NLPI problem objective */
3732  assert(nlp->solver != NULL);
3733  assert(nlp->problem != NULL);
3734 
3735  pos = nlp->varmap_nlp2nlpi[pos];
3736  objidx = -1;
3737  SCIP_CALL( SCIPnlpiChgLinearCoefs(nlp->solver, nlp->problem, objidx, 1, &pos, &coef) );
3738 
3739  /* if we had a solution and it was locally (or globally) optimal, then now we can only be sure that it is still feasible */
3740  if( nlp->solstat < SCIP_NLPSOLSTAT_FEASIBLE )
3742 
3743  return SCIP_OKAY;
3744 }
3745 
3746 /** adds new variables to the NLP */
3747 static
3749  SCIP_NLP* nlp, /**< NLP data structure */
3750  BMS_BLKMEM* blkmem, /**< block memory */
3751  SCIP_SET* set, /**< global SCIP settings */
3752  int nvars, /**< number of variables to add */
3753  SCIP_VAR** vars /**< variable to add to NLP */
3754  )
3755 {
3756  int i;
3757  SCIP_VAR* var;
3758 
3759  assert(nlp != NULL);
3760  assert(blkmem != NULL);
3761  assert(set != NULL);
3762  assert(vars != NULL || nvars == 0);
3763  assert(!nlp->indiving || nvars == 0);
3764 
3765  if( nvars == 0 )
3766  return SCIP_OKAY;
3767 
3768  SCIP_CALL( SCIPnlpEnsureVarsSize(nlp, blkmem, set, nlp->nvars + nvars) );
3769  assert(nlp->sizevars >= nlp->nvars + nvars);
3770 
3771  for( i = 0; i < nvars; ++i )
3772  {
3773  var = vars[i]; /*lint !e613*/
3774 
3775  assert(SCIPvarIsTransformed(var));
3776  assert(SCIPvarIsActive(var));
3777  assert(!SCIPhashmapExists(nlp->varhash, var));
3778 
3779  SCIPvarCapture(var);
3780 
3781  nlp->vars[nlp->nvars+i] = var;
3782  nlp->varmap_nlp2nlpi[nlp->nvars+i] = -1;
3783  SCIP_CALL( SCIPhashmapInsert(nlp->varhash, var, (void*) (size_t) (nlp->nvars+i)) );
3784 
3785  nlp->varlbdualvals[nlp->nvars+i] = 0.0;
3786  nlp->varubdualvals[nlp->nvars+i] = 0.0;
3787 
3788  /* update objective, if necessary (new variables have coefficient 0.0 anyway) */
3789  if( SCIPvarGetObj(var) != 0.0 )
3790  {
3791  SCIP_CALL( nlpUpdateObjCoef(nlp, var) );
3792  }
3793 
3794  /* let's keep the previous initial guess and set it for the new variable to the best bound
3795  * (since there can be no row that uses this variable yet, this seems a good guess) */
3796  if( nlp->haveinitguess )
3797  {
3798  assert(nlp->initialguess != NULL);
3799 
3800  nlp->initialguess[nlp->nvars+i] = SCIPvarGetBestBoundLocal(var);
3801  }
3802 
3803  /* if we have a feasible NLP solution, then it remains feasible
3804  * but we have to update the objective function
3805  */
3806  if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
3807  {
3811  }
3812 
3813  /* catch events on variable */
3814  SCIP_CALL( SCIPvarCatchEvent(var, blkmem, set,
3816  nlp->eventhdlr, (SCIP_EVENTDATA*)nlp, NULL) ); /* @todo should store event filter position in nlp? */
3817  }
3818 
3819  nlp->nvars += nvars;
3820  nlp->nunflushedvaradd += nvars;
3821 
3822  return SCIP_OKAY;
3823 }
3824 
3825 /** moves a variable to a different place, and updates all corresponding data structures */
3826 static
3828  SCIP_NLP* nlp, /**< NLP data structure */
3829  int oldpos, /**< old position of variable */
3830  int newpos /**< new position of variable */
3831  )
3832 {
3833  int nlpipos;
3834 
3835  assert(nlp != NULL);
3836  assert(0 <= oldpos && oldpos < nlp->nvars);
3837  assert(0 <= newpos && newpos < nlp->nvars);
3838  assert(nlp->vars[oldpos] != NULL);
3839 
3840  if( oldpos == newpos )
3841  return SCIP_OKAY;
3842 
3843  SCIP_CALL( SCIPhashmapSetImage(nlp->varhash, nlp->vars[oldpos], (void*) (size_t) newpos) );
3844  nlp->vars[newpos] = nlp->vars[oldpos];
3845  nlp->varmap_nlp2nlpi[newpos] = nlp->varmap_nlp2nlpi[oldpos];
3846  nlp->varlbdualvals[newpos] = nlp->varlbdualvals[oldpos];
3847  nlp->varubdualvals[newpos] = nlp->varubdualvals[oldpos];
3848  if( nlp->initialguess != NULL )
3849  nlp->initialguess[newpos] = nlp->initialguess[oldpos];
3850 
3851  nlpipos = nlp->varmap_nlp2nlpi[newpos];
3852  if( nlpipos > 0 )
3853  nlp->varmap_nlpi2nlp[nlpipos] = newpos;
3854 
3855  return SCIP_OKAY;
3856 }
3857 
3858 /** deletes variable with given position from NLP */
3859 static
3861  SCIP_NLP* nlp, /**< NLP data structure */
3862  BMS_BLKMEM* blkmem, /**< block memory */
3863  SCIP_SET* set, /**< global SCIP settings */
3864  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3865  SCIP_LP* lp, /**< SCIP LP, needed if a column-variable is freed */
3866  int pos /**< position of nonlinear row that is to be removed */
3867  )
3868 {
3869  SCIP_VAR* var;
3870 #ifndef NDEBUG
3871  int i;
3872 #endif
3873  int nlpipos;
3874 
3875  assert(nlp != NULL);
3876  assert(blkmem != NULL);
3877  assert(set != NULL);
3878  assert(pos >= 0);
3879  assert(pos < nlp->nvars);
3880  assert(!nlp->indiving);
3881 
3882  var = nlp->vars[pos];
3883  assert(var != NULL);
3884 
3885 #ifndef NDEBUG
3886  /* assert that variable is not used by any nonlinear row */
3887  for( i = 0; i < nlp->nnlrows; ++i )
3888  {
3889  int j;
3890  SCIP_NLROW* nlrow;
3891 
3892  nlrow = nlp->nlrows[i];
3893  assert(nlrow != NULL);
3894 
3895  /* use nlrowSearchLinearCoef only if already sorted, since otherwise we may change the solving process slightly */
3896  if( nlrow->linvarssorted )
3897  assert( nlrowSearchLinearCoef(nlrow, var) == -1 );
3898  else
3899  for( j = 0; j < nlrow->nlinvars; ++j )
3900  assert( nlrow->linvars[j] != var );
3901 
3902  assert( SCIPnlrowSearchQuadVar(nlrow, var) == -1);
3903 
3904  assert(nlrow->exprtree == NULL || SCIPexprtreeFindVar(nlrow->exprtree, var) == -1);
3905  }
3906 #endif
3907 
3908  /* if we had a feasible solution, then adjust objective function value
3909  * if NLP was unbounded before, then maybe it is not anymore */
3910  if( nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
3911  nlp->primalsolobjval -= SCIPvarGetObj(var) * SCIPvarGetNLPSol(var);
3912  else if( nlp->solstat == SCIP_NLPSOLSTAT_UNBOUNDED )
3914 
3915  /* if variable is in NLPI problem, mark that we have to remember to delete it there
3916  * if it was not in the NLPI yet, then we have one unflushed var addition less now */
3917  nlpipos = nlp->varmap_nlp2nlpi[pos];
3918  if( nlpipos >= 0 )
3919  {
3920  assert(nlpipos < nlp->nvars_solver);
3921 
3922  nlp->varmap_nlpi2nlp[nlpipos] = -1;
3923  ++nlp->nunflushedvardel;
3924  }
3925  else
3926  --nlp->nunflushedvaradd;
3927 
3928  /* drop events on variable */
3929  SCIP_CALL( SCIPvarDropEvent(var, blkmem, set,
3931  nlp->eventhdlr, (SCIP_EVENTDATA*)nlp, -1) );
3932 
3933  /* move variable from end to pos */
3934  SCIP_CALL( nlpMoveVar(nlp, nlp->nvars-1, pos) );
3935 
3936  /* forget about variable */
3937  SCIP_CALL( SCIPhashmapRemove(nlp->varhash, var) );
3938  SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
3939  --nlp->nvars;
3940 
3941  return SCIP_OKAY;
3942 }
3943 
3944 /** notifies NLP that a variable was fixed, so it is removed from objective, all rows, and the NLP variables */
3945 static
3947  SCIP_NLP* nlp, /**< NLP data */
3948  BMS_BLKMEM* blkmem, /**< block memory */
3949  SCIP_SET* set, /**< global SCIP settings */
3950  SCIP_STAT* stat, /**< problem statistics data */
3951  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3952  SCIP_LP* lp, /**< SCIP LP, needed to release variable */
3953  SCIP_VAR* var /**< variable that has been fixed */
3954  )
3955 {
3956  int i;
3957 
3958  assert(nlp != NULL);
3959  assert(var != NULL);
3960  assert(!SCIPvarIsActive(var));
3961  assert(!nlp->indiving);
3962  assert(SCIPhashmapExists(nlp->varhash, var));
3963 
3964  /* remove var from all rows */
3965  for( i = 0; i < nlp->nnlrows; ++i )
3966  {
3967  SCIP_CALL( nlrowRemoveFixedVar(nlp->nlrows[i], blkmem, set, stat, nlp, var) );
3968  }
3969 
3970  /* remove variable from NLP */
3971  SCIP_CALL( SCIPnlpDelVar(nlp, blkmem, set, eventqueue, lp, var) );
3972 
3973  return SCIP_OKAY;
3974 }
3975 
3976 /** creates arrays with NLPI variable indices of variables in a nonlinear row */
3977 static
3979  SCIP_NLP* nlp, /**< NLP data */
3980  SCIP_SET* set, /**< global SCIP settings */
3981  SCIP_NLROW* nlrow, /**< nonlinear row */
3982  int** linidxs, /**< buffer to store pointer to NLPI indices of linear variables */
3983  SCIP_QUADELEM** quadelems, /**< buffer to store pointer to quadratic elements w.r.t. NLPI indices */
3984  int** nlinidxs /**< buffer to store pointer to NLPI indices of nonlinear variables */
3985  )
3986 {
3987  int i;
3988  SCIP_VAR* var;
3989 
3990  assert(nlp != NULL);
3991  assert(set != NULL);
3992  assert(nlrow != NULL);
3993  assert(linidxs != NULL);
3994  assert(quadelems != NULL);
3995  assert(nlinidxs != NULL);
3996 
3997  /* get indices of variables in linear part of row */
3998  if( nlrow->nlinvars > 0 )
3999  {
4000  assert(nlrow->linvars != NULL);
4001  assert(nlrow->lincoefs != NULL);
4002 
4003  SCIP_CALL( SCIPsetAllocBufferArray(set, linidxs, nlrow->nlinvars) );
4004 
4005  for( i = 0; i < nlrow->nlinvars; ++i )
4006  {
4007  var = nlrow->linvars[i];
4008  assert(var != NULL);
4009  assert(SCIPvarIsActive(var)); /* at this point, there should be only active variables in the row */
4010 
4011  assert(SCIPhashmapExists(nlp->varhash, var));
4012  (*linidxs)[i] = nlp->varmap_nlp2nlpi[(size_t) (void*) SCIPhashmapGetImage(nlp->varhash, var)];
4013  assert((*linidxs)[i] >= 0);
4014  }
4015  }
4016  else
4017  *linidxs = NULL;
4018 
4019  /* get indices of variables in quadratic part of row */
4020  if( nlrow->nquadvars > 0 )
4021  {
4022  int* quadvarsidx;
4023 
4024  assert(nlrow->quadvars != NULL);
4025  assert(nlrow->nquadelems > 0);
4026  assert(nlrow->quadelems != NULL);
4027 
4028  /* compute mapping of variable indices quadratic term -> NLPI */
4029  SCIP_CALL( SCIPsetAllocBufferArray(set, &quadvarsidx, nlrow->nquadvars) );
4030  for( i = 0; i < nlrow->nquadvars; ++i )
4031  {
4032  var = nlrow->quadvars[i];
4033  assert(var != NULL);
4034  assert(SCIPvarIsActive(var)); /* at this point, there should be only active variables in the row */
4035 
4036  assert(SCIPhashmapExists(nlp->varhash, var));
4037  quadvarsidx[i] = nlp->varmap_nlp2nlpi[(size_t) (void*) SCIPhashmapGetImage(nlp->varhash, var)];
4038  }
4039 
4040  /* compute quad elements using NLPI indices */
4041  SCIP_CALL( SCIPsetAllocBufferArray(set, quadelems, nlrow->nquadelems) );
4042  for( i = 0; i < nlrow->nquadelems; ++i )
4043  {
4044  assert(nlrow->quadelems[i].idx1 >= 0);
4045  assert(nlrow->quadelems[i].idx1 < nlrow->nquadvars);
4046  assert(nlrow->quadelems[i].idx2 >= 0);
4047  assert(nlrow->quadelems[i].idx2 < nlrow->nquadvars);
4048 
4049  (*quadelems)[i].idx1 = quadvarsidx[nlrow->quadelems[i].idx1];
4050  (*quadelems)[i].idx2 = quadvarsidx[nlrow->quadelems[i].idx2];
4051  if( (*quadelems)[i].idx1 > (*quadelems)[i].idx2 )
4052  {
4053  int tmp = (*quadelems)[i].idx1;
4054  (*quadelems)[i].idx1 = (*quadelems)[i].idx2;
4055  (*quadelems)[i].idx2 = tmp;
4056  }
4057  (*quadelems)[i].coef = nlrow->quadelems[i].coef;
4058  }
4059 
4060  SCIPsetFreeBufferArray(set, &quadvarsidx);
4061  }
4062  else
4063  *quadelems = NULL;
4064 
4065  /* get indices of variables in expression tree part of row */
4066  if( nlrow->exprtree != NULL )
4067  {
4068  int n;
4069 
4070  n = SCIPexprtreeGetNVars(nlrow->exprtree);
4071  assert(n == 0 || SCIPexprtreeGetVars(nlrow->exprtree) != NULL);
4072 
4073  SCIP_CALL( SCIPsetAllocBufferArray(set, nlinidxs, n) );
4074 
4075  for( i = 0; i < n; ++i )
4076  {
4077  var = SCIPexprtreeGetVars(nlrow->exprtree)[i];
4078  assert(var != NULL);
4079  assert(SCIPvarIsActive(var)); /* at this point, there should be only active variables in the row */
4080 
4081  assert(SCIPhashmapExists(nlp->varhash, var));
4082  (*nlinidxs)[i] = nlp->varmap_nlp2nlpi[(size_t) (void*) SCIPhashmapGetImage(nlp->varhash, var)];
4083  }
4084  }
4085  else
4086  *nlinidxs = NULL;
4087 
4088  return SCIP_OKAY;
4089 }
4090 
4091 /** ensures, that NLPI variables array of NLP can store at least num entries */
4092 static
4094  SCIP_NLP* nlp, /**< NLP data */
4095  BMS_BLKMEM* blkmem, /**< block memory */
4096  SCIP_SET* set, /**< global SCIP settings */
4097  int num /**< minimum number of entries to store */
4098  )
4099 {
4100  assert(nlp != NULL);
4101  assert(blkmem != NULL);
4102  assert(set != NULL);
4103  assert(nlp->nvars_solver <= nlp->sizevars_solver);
4104 
4105  if( num > nlp->sizevars_solver )
4106  {
4107  int newsize;
4108 
4109  newsize = SCIPsetCalcMemGrowSize(set, num);
4110  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varmap_nlpi2nlp, nlp->sizevars_solver, newsize) );
4111 
4112  nlp->sizevars_solver = newsize;
4113  }
4114  assert(num <= nlp->sizevars_solver);
4115 
4116  return SCIP_OKAY;
4117 }
4118 
4119 /** ensures, that NLPI nonlinear rows array of NLP can store at least num entries */
4120 static
4122  SCIP_NLP* nlp, /**< NLP data */
4123  BMS_BLKMEM* blkmem, /**< block memory */
4124  SCIP_SET* set, /**< global SCIP settings */
4125  int num /**< minimum number of entries to store */
4126  )
4127 {
4128  assert(nlp != NULL);
4129  assert(blkmem != NULL);
4130  assert(set != NULL);
4131  assert(nlp->nnlrows_solver <= nlp->sizenlrows_solver);
4132 
4133  if( num > nlp->sizenlrows_solver )
4134  {
4135  int newsize;
4136 
4137  newsize = SCIPsetCalcMemGrowSize(set, num);
4139 
4140  nlp->sizenlrows_solver = newsize;
4141  }
4142  assert(num <= nlp->sizenlrows_solver);
4143 
4144  return SCIP_OKAY;
4145 }
4146 
4147 /** deletes rows from the NLPI problem that have been marked as to remove */
4148 static
4150  SCIP_NLP* nlp, /**< NLP data */
4151  BMS_BLKMEM* blkmem, /**< block memory */
4152  SCIP_SET* set /**< global SCIP settings */
4153  )
4154 {
4155  int j;
4156  int c; /* counts the number of rows to delete */
4157  int* rowset; /* marks which rows to delete and stores new indices */
4158  SCIP_NLROW* nlrow;
4159 
4160  assert(nlp != NULL);
4161  assert(blkmem != NULL);
4162  assert(set != NULL);
4163  assert(nlp->nunflushednlrowdel >= 0);
4164  assert(!nlp->indiving);
4165 
4166  if( nlp->nunflushednlrowdel == 0 )
4167  {
4168 #ifndef NDEBUG
4169  /* check that there are really no pending removals of nonlinear rows */
4170  for( j = 0; j < nlp->nnlrows_solver; ++j )
4171  assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
4172 #endif
4173  return SCIP_OKAY;
4174  }
4175 
4176  assert(nlp->solver != NULL);
4177  assert(nlp->problem != NULL);
4178 
4179  /* create marker which rows have to be deleted */
4180  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowset, nlp->nnlrows_solver) );
4181  c = 0;
4182  for( j = 0; j < nlp->nnlrows_solver; ++j )
4183  {
4184  if( nlp->nlrowmap_nlpi2nlp[j] == -1 )
4185  {
4186  rowset[j] = 1;
4187  ++c;
4188  }
4189  else
4190  rowset[j] = 0;
4191  }
4192  assert(c == nlp->nunflushednlrowdel);
4193 
4194  /* remove rows from NLPI problem */
4195  SCIP_CALL( SCIPnlpiDelConsSet(nlp->solver, nlp->problem, rowset) );
4196 
4197  /* update NLPI row indices */
4198  for( j = 0; j < nlp->nnlrows_solver; ++j )
4199  {
4200  assert(rowset[j] <= j); /* we assume that the NLP solver did not move a row behind its previous position!! */
4201  if( rowset[j] < 0 )
4202  {
4203  /* assert that row was marked as deleted */
4204  assert(nlp->nlrowmap_nlpi2nlp[j] == -1);
4205  }
4206  else if( rowset[j] < j )
4207  {
4208  /* nlrow at position j moved (forward) to position rowset[j] */
4209  assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
4210  assert(nlp->nlrowmap_nlpi2nlp[j] < nlp->nnlrows);
4211 
4212  nlrow = nlp->nlrows[nlp->nlrowmap_nlpi2nlp[j]];
4213  assert(nlrow->nlpiindex == j);
4214 
4215  /* there should be no row at the new position already */
4216  assert(nlp->nlrowmap_nlpi2nlp[rowset[j]] == -1);
4217 
4218  nlrow->nlpiindex = rowset[j];
4219  nlp->nlrowmap_nlpi2nlp[rowset[j]] = nlrow->nlpindex;
4220  }
4221  else
4222  {
4223  /* row j stays at position j */
4224  assert(nlp->nlrowmap_nlpi2nlp[j] >= 0);
4225  assert(nlp->nlrowmap_nlpi2nlp[j] < nlp->nnlrows);
4226  assert(nlp->nlrows[nlp->nlrowmap_nlpi2nlp[j]]->nlpiindex == j);
4227  }
4228  }
4229  nlp->nnlrows_solver -= c;
4230  nlp->nunflushednlrowdel = 0;
4231 
4232  /* cleanup */
4233  SCIPsetFreeBufferArray(set, &rowset);
4234 
4235  return SCIP_OKAY;
4236 }
4237 
4238 /** deletes variables from the NLPI problem that have been marked as to remove
4239  * assumes that there are no pending row deletions (nlpFlushNlRowDeletions should be called first)
4240  */
4241 static
4243  SCIP_NLP* nlp, /**< NLP data */
4244  BMS_BLKMEM* blkmem, /**< block memory */
4245  SCIP_SET* set /**< global SCIP settings */
4246  )
4247 {
4248  int i;
4249  int c; /* counter on number of variables to remove in solver */
4250  int* colset; /* marks which variables to delete and stores new indices */
4251 
4252  assert(nlp != NULL);
4253  assert(blkmem != NULL);
4254  assert(set != NULL);
4255  assert(nlp->nunflushedvardel >= 0);
4256  assert(nlp->nunflushednlrowdel == 0);
4257  assert(!nlp->indiving);
4258 
4259  if( nlp->nunflushedvardel == 0 )
4260  {
4261 #ifndef NDEBUG
4262  /* check that there are really no pending removals of variables */
4263  for( i = 0; i < nlp->nvars_solver; ++i )
4264  assert(nlp->varmap_nlpi2nlp[i] >= 0);
4265 #endif
4266  return SCIP_OKAY;
4267  }
4268 
4269  assert(nlp->solver != NULL);
4270  assert(nlp->problem != NULL);
4271 
4272  /* create marker which variables have to be deleted */
4273  SCIP_CALL( SCIPsetAllocBufferArray(set, &colset, nlp->nvars_solver) );
4274  c = 0;
4275  for( i = 0; i < nlp->nvars_solver; ++i )
4276  {
4277  if( nlp->varmap_nlpi2nlp[i] == -1 )
4278  {
4279  colset[i] = 1;
4280  ++c;
4281  }
4282  else
4283  colset[i] = 0;
4284  }
4285  assert(c == nlp->nunflushedvardel);
4286 
4287  /* delete variables from NLPI problem */
4288  SCIP_CALL( SCIPnlpiDelVarSet(nlp->solver, nlp->problem, colset) );
4289 
4290  /* update NLPI variable indices */
4291  for( i = 0; i < nlp->nvars_solver; ++i )
4292  {
4293  assert(colset[i] <= i); /* we assume that the NLP solver did not move a variable behind its previous position!! */
4294  if( colset[i] < 0 )
4295  {
4296  /* assert that variable was marked as deleted */
4297  assert(nlp->varmap_nlpi2nlp[i] == -1);
4298  }
4299  else if( colset[i] < i)
4300  {
4301  /* variable at position i moved (forward) to position colset[i] */
4302  int varpos;
4303 
4304  varpos = nlp->varmap_nlpi2nlp[i]; /* position of variable i in NLP */
4305  assert(varpos >= 0);
4306  assert(varpos < nlp->nvars);
4307  assert(nlp->varmap_nlp2nlpi[varpos] == i);
4308 
4309  /* there should be no variable at the new position already */
4310  assert(nlp->varmap_nlpi2nlp[colset[i]] == -1);
4311 
4312  nlp->varmap_nlp2nlpi[varpos] = colset[i];
4313  nlp->varmap_nlpi2nlp[colset[i]] = varpos;
4314  }
4315  else
4316  {
4317  /* variable i stays at position i */
4318  assert(nlp->varmap_nlpi2nlp[i] >= 0);
4319  assert(nlp->varmap_nlpi2nlp[i] < nlp->nvars);
4320  assert(nlp->varmap_nlp2nlpi[nlp->varmap_nlpi2nlp[i]] == i);
4321  }
4322  }
4323 
4324  nlp->nvars_solver -= c;
4325  nlp->nunflushedvardel = 0;
4326 
4327  /* cleanup */
4328  SCIPsetFreeBufferArray(set, &colset);
4329 
4330  return SCIP_OKAY;
4331 }
4332 
4333 /** adds nonlinear rows to NLPI problem that have been added to NLP before
4334  * assumes that there are no pending variable additions or deletions (nlpFlushVarDeletions and nlpFlushVarAdditions should be called first) */
4335 static
4337  SCIP_NLP* nlp, /**< NLP data */
4338  BMS_BLKMEM* blkmem, /**< block memory */
4339  SCIP_SET* set /**< global SCIP settings */
4340  )
4341 {
4342  int c, i;
4343  SCIP_NLROW* nlrow;
4344  SCIP_Real* lhss;
4345  SCIP_Real* rhss;
4346  int* nlinvars;
4347  int** linidxs;
4348  SCIP_Real** lincoefs;
4349  int* nquadelems;
4350  SCIP_QUADELEM** quadelems;
4351  int** nlidxs;
4352  SCIP_EXPRTREE** exprtrees;
4353  const char** names;
4354 
4355  assert(nlp != NULL);
4356  assert(blkmem != NULL);
4357  assert(set != NULL);
4358  assert(nlp->nunflushednlrowadd >= 0);
4359  assert(nlp->nunflushedvaradd == 0);
4360  assert(nlp->nunflushedvardel == 0);
4361  assert(!nlp->indiving);
4362 
4363  if( nlp->nunflushednlrowadd == 0 )
4364  {
4365 #ifndef NDEBUG
4366  /* check that there are really no pending additions of variables */
4367  for( i = 0; i < nlp->nnlrows; ++i )
4368  assert(nlp->nlrows[i]->nlpiindex >= 0);
4369 #endif
4370  return SCIP_OKAY;
4371  }
4372 
4373  assert(nlp->solver != NULL);
4374  assert(nlp->problem != NULL);
4375 
4376  SCIP_CALL( nlpEnsureNlRowsSolverSize(nlp, blkmem, set, nlp->nnlrows_solver + nlp->nunflushednlrowadd) );
4377 
4380  SCIP_CALL( SCIPsetAllocBufferArray(set, &nlinvars, nlp->nunflushednlrowadd) );
4381  SCIP_CALL( SCIPsetAllocBufferArray(set, &linidxs, nlp->nunflushednlrowadd) );
4382  SCIP_CALL( SCIPsetAllocBufferArray(set, &lincoefs, nlp->nunflushednlrowadd) );
4383  SCIP_CALL( SCIPsetAllocBufferArray(set, &nquadelems, nlp->nunflushednlrowadd) );
4384  SCIP_CALL( SCIPsetAllocBufferArray(set, &quadelems, nlp->nunflushednlrowadd) );
4385  SCIP_CALL( SCIPsetAllocBufferArray(set, &nlidxs, nlp->nunflushednlrowadd) );
4386  SCIP_CALL( SCIPsetAllocBufferArray(set, &exprtrees, nlp->nunflushednlrowadd) );
4387 #if ADDNAMESTONLPI
4389 #else
4390  names = NULL;
4391 #endif
4392 
4393  c = 0;
4394  for( i = 0; i < nlp->nnlrows; ++i )
4395  {
4396  nlrow = nlp->nlrows[i];
4397  assert(nlrow != NULL);
4398 
4399  /* skip nonlinear rows already in NLPI problem */
4400  if( nlrow->nlpiindex >= 0 )
4401  continue;
4402  assert(c < nlp->nunflushednlrowadd);
4403 
4404  /* get indices in NLPI */
4405  SCIP_CALL( nlpSetupNlpiIndices(nlp, set, nlrow, &linidxs[c], &quadelems[c], &nlidxs[c]) );
4406  assert(linidxs[c] != NULL || nlrow->nlinvars == 0);
4407  assert(quadelems[c] != NULL || nlrow->nquadvars == 0);
4408  assert(nlidxs[c] != NULL || nlrow->exprtree == NULL);
4409 
4410  nlp->nlrowmap_nlpi2nlp[nlp->nnlrows_solver+c] = i;
4411  nlrow->nlpiindex = nlp->nnlrows_solver+c;
4412 
4413  lhss[c] = nlrow->lhs;
4414  rhss[c] = nlrow->rhs;
4415  if( nlrow->constant != 0.0 )
4416  {
4417  if( !SCIPsetIsInfinity(set, -nlrow->lhs) )
4418  lhss[c] -= nlrow->constant;
4419  if( !SCIPsetIsInfinity(set, nlrow->rhs) )
4420  rhss[c] -= nlrow->constant;
4421  }
4422  if( rhss[c] < lhss[c] )
4423  {
4424  assert(SCIPsetIsEQ(set, lhss[c], rhss[c]));
4425  rhss[c] = lhss[c];
4426  }
4427 
4428  nlinvars[c] = nlrow->nlinvars;
4429  lincoefs[c] = nlrow->lincoefs;
4430 
4431  nquadelems[c] = nlrow->nquadelems;
4432 
4433  exprtrees[c] = nlrow->exprtree;
4434 
4435 #if ADDNAMESTONLPI
4436  names[c] = nlrow->name;
4437 #endif
4438 
4439  ++c;
4440 
4441 #ifdef NDEBUG
4442  /* have c vars to add already, there can be no more */
4443  if( c == nlp->nunflushednlrowadd )
4444  break;
4445 #endif
4446  }
4447  assert(c == nlp->nunflushednlrowadd);
4448 
4449  nlp->nnlrows_solver += c;
4450 
4451  SCIP_CALL( SCIPnlpiAddConstraints(nlp->solver, nlp->problem, c, lhss, rhss,
4452  nlinvars, linidxs, lincoefs,
4453  nquadelems, quadelems,
4454  nlidxs, exprtrees,
4455  names) );
4456 
4457  for( c = 0; c < nlp->nunflushednlrowadd; ++c )
4458  {
4459  if( linidxs[c] != NULL )
4460  SCIPsetFreeBufferArray(set, &linidxs[c]);
4461  if( quadelems[c] != NULL )
4462  SCIPsetFreeBufferArray(set, &quadelems[c]);
4463  if( nlidxs[c] != NULL )
4464  SCIPsetFreeBufferArray(set, &nlidxs[c]);
4465  }
4466 
4467 #if ADDNAMESTONLPI
4468  SCIPsetFreeBufferArray(set, &names);
4469 #endif
4470  SCIPsetFreeBufferArray(set, &lhss);
4471  SCIPsetFreeBufferArray(set, &rhss);
4472  SCIPsetFreeBufferArray(set, &nlinvars);
4473  SCIPsetFreeBufferArray(set, &linidxs);
4474  SCIPsetFreeBufferArray(set, &lincoefs);
4475  SCIPsetFreeBufferArray(set, &nquadelems);
4476  SCIPsetFreeBufferArray(set, &quadelems);
4477  SCIPsetFreeBufferArray(set, &nlidxs);
4478  SCIPsetFreeBufferArray(set, &exprtrees);
4479 
4480  nlp->nunflushednlrowadd = 0;
4481 
4482  return SCIP_OKAY;
4483 }
4484 
4485 
4486 /** adds variables to NLPI problem that have been added to NLP before
4487  * may set nlp->objflushed to FALSE if a variable with nonzero obj.coefficient is added to the NLPI problem */
4488 static
4490  SCIP_NLP* nlp, /**< NLP data */
4491  BMS_BLKMEM* blkmem, /**< block memory */
4492  SCIP_SET* set /**< global SCIP settings */
4493  )
4494 {
4495  int i, c;
4496  SCIP_Real* lbs;
4497  SCIP_Real* ubs;
4498  const char** names;
4499 
4500  assert(nlp != NULL);
4501  assert(blkmem != NULL);
4502  assert(set != NULL);
4503  assert(nlp->nunflushedvaradd >= 0);
4504  assert(!nlp->indiving);
4505 
4506  if( nlp->nunflushedvaradd == 0 )
4507  {
4508 #ifndef NDEBUG
4509  /* check that there are really no pending additions of variables */
4510  for( i = 0; i < nlp->nvars; ++i )
4511  assert(nlp->varmap_nlp2nlpi[i] >= 0);
4512 #endif
4513  return SCIP_OKAY;
4514  }
4515 
4516  assert(nlp->solver != NULL);
4517  assert(nlp->problem != NULL);
4518 
4519  SCIP_CALL( nlpEnsureVarsSolverSize(nlp, blkmem, set, nlp->nvars_solver + nlp->nunflushedvaradd) );
4520 
4523 #if ADDNAMESTONLPI
4524  SCIP_CALL( SCIPsetAllocBufferArray(set, &names, nlp->nunflushedvaradd) );
4525 #else
4526  names = NULL;
4527 #endif
4528 
4529  c = 0;
4530  for( i = 0; i < nlp->nvars; ++i )
4531  {
4532  /* skip variables already in NLPI problem */
4533  if( nlp->varmap_nlp2nlpi[i] >= 0 )
4534  continue;
4535  assert(c < nlp->nunflushedvaradd);
4536 
4537  nlp->varmap_nlpi2nlp[nlp->nvars_solver+c] = i;
4538  nlp->varmap_nlp2nlpi[i] = nlp->nvars_solver+c;
4539  lbs[c] = SCIPvarGetLbLocal(nlp->vars[i]);
4540  ubs[c] = SCIPvarGetUbLocal(nlp->vars[i]);
4541 #if ADDNAMESTONLPI
4542  names[c] = SCIPvarGetName(nlp->vars[i]);
4543 #endif
4544  ++c;
4545 
4546  /* if the new variable has a nonzero objective coefficient, then the objective need to be updated */
4547  if( !SCIPsetIsZero(set, SCIPvarGetObj(nlp->vars[i])) )
4548  nlp->objflushed = FALSE;
4549 
4550 #ifdef NDEBUG
4551  /* have c vars to add already, there can be no more */
4552  if( c == nlp->nunflushedvaradd )
4553  break;
4554 #endif
4555  }
4556  assert(c == nlp->nunflushedvaradd);
4557 
4558  nlp->nvars_solver += c;
4559 
4560  SCIP_CALL( SCIPnlpiAddVars(nlp->solver, nlp->problem, c, lbs, ubs, names) );
4561 
4562 #if ADDNAMESTONLPI
4563  SCIPsetFreeBufferArray(set, &names);
4564 #endif
4565  SCIPsetFreeBufferArray(set, &lbs);
4566  SCIPsetFreeBufferArray(set, &ubs);
4567 
4568  nlp->nunflushedvaradd = 0;
4569 
4570  return SCIP_OKAY;
4571 }
4572 
4573 /** updates the objective in the NLPI problem, if necessary
4574  * assumes that there are no unflushed variable additions or deletions (nlpFlushVarDeletions and nlpFlushVarAdditions should be called first)
4575  */
4576 static
4578  SCIP_NLP* nlp, /**< NLP data */
4579  BMS_BLKMEM* blkmem, /**< block memory */
4580  SCIP_SET* set /**< global SCIP settings */
4581  )
4582 {
4583  int* linindices;
4584  SCIP_Real* lincoefs;
4585  SCIP_Real coef;
4586  int i;
4587  int nz;
4588 
4589  assert(nlp != NULL);
4590  assert(blkmem != NULL);
4591  assert(set != NULL);
4592  assert(nlp->nunflushedvaradd == 0);
4593  assert(nlp->nunflushedvardel == 0);
4594  assert(!nlp->indiving);
4595 
4596  if( nlp->objflushed )
4597  return SCIP_OKAY;
4598 
4599  assert(nlp->solver != NULL);
4600  assert(nlp->problem != NULL);
4601 
4602  /* assemble coefficients */
4603  SCIP_CALL( SCIPsetAllocBufferArray(set, &linindices, nlp->nvars_solver) );
4604  SCIP_CALL( SCIPsetAllocBufferArray(set, &lincoefs, nlp->nvars_solver) );
4605 
4606  nz = 0;
4607  for( i = 0; i < nlp->nvars_solver; ++i )
4608  {
4609  assert(nlp->varmap_nlpi2nlp[i] >= 0); /* there should be no variable deletions pending */
4610 
4611  coef = SCIPvarGetObj(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
4612  if( SCIPsetIsZero(set, coef) )
4613  continue;
4614 
4615  linindices[nz] = i;
4616  lincoefs[nz] = coef;
4617  ++nz;
4618  }
4619 
4621  nz, linindices, lincoefs,
4622  0, NULL,
4623  NULL, NULL,
4624  0.0) );
4625 
4626  SCIPsetFreeBufferArray(set, &linindices);
4627  SCIPsetFreeBufferArray(set, &lincoefs);
4628 
4629  nlp->objflushed = TRUE;
4630 
4631  return SCIP_OKAY;
4632 }
4633 
4634 /** solves the NLP, assuming it has been flushed already
4635  *
4636  * is used also to solve diving NLP
4637  */
4638 static
4640  SCIP_NLP* nlp, /**< NLP data */
4641  BMS_BLKMEM* blkmem, /**< block memory buffers */
4642  SCIP_SET* set, /**< global SCIP settings */
4643  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4644  SCIP_STAT* stat /**< problem statistics */
4645  )
4646 {
4647  int i;
4648 
4649  assert(nlp != NULL);
4650  assert(blkmem != NULL);
4651  assert(set != NULL);
4652  assert(stat != NULL);
4653 
4654  if( nlp->solver == NULL )
4655  {
4656  SCIPmessagePrintWarning(messagehdlr, "Attempted to solve NLP, but no solver available.\n");
4657 
4660 
4661  return SCIP_OKAY;
4662  }
4663 
4664  assert(nlp->solver != NULL);
4665  assert(nlp->problem != NULL);
4666 
4667  /* set initial guess, if available */
4668  if( nlp->haveinitguess )
4669  {
4670  /* @todo should we not set it if we had set it already? (initguessflushed...) */
4671  SCIP_Real* initialguess_solver;
4672  int nlpidx;
4673 
4674  assert(nlp->initialguess != NULL);
4675 
4676  SCIP_CALL( SCIPsetAllocBufferArray(set, &initialguess_solver, nlp->nvars_solver) );
4677 
4678  for( i = 0; i < nlp->nvars_solver; ++i )
4679  {
4680  nlpidx = nlp->varmap_nlpi2nlp[i];
4681  assert(nlpidx >= 0);
4682  assert(nlpidx < nlp->nvars);
4683 
4684  initialguess_solver[i] = nlp->initialguess[nlpidx];
4685  }
4686  SCIP_CALL( SCIPnlpiSetInitialGuess(nlp->solver, nlp->problem, initialguess_solver, NULL, NULL, NULL) );
4687 
4688  SCIPsetFreeBufferArray(set, &initialguess_solver);
4689  }
4690 
4691  /* let NLP solver do his work */
4692  SCIPclockStart(stat->nlpsoltime, set);
4693 
4694  SCIP_CALL( SCIPnlpiSolve(nlp->solver, nlp->problem) );
4695 
4696  SCIPclockStop(stat->nlpsoltime, set);
4697  ++stat->nnlps;
4698 
4699  nlp->termstat = SCIPnlpiGetTermstat(nlp->solver, nlp->problem);
4700  nlp->solstat = SCIPnlpiGetSolstat(nlp->solver, nlp->problem);
4701  switch( nlp->solstat )
4702  {
4707  {
4708  SCIP_Real* primalvals;
4709  SCIP_Real* nlrowdualvals;
4710  SCIP_Real* varlbdualvals;
4711  SCIP_Real* varubdualvals;
4712 
4713  primalvals = NULL;
4714  nlrowdualvals = NULL;
4715  varlbdualvals = NULL;
4716  varubdualvals = NULL;
4717 
4718  /* get NLP solution */
4719  SCIP_CALL( SCIPnlpiGetSolution(nlp->solver, nlp->problem, &primalvals, &nlrowdualvals, &varlbdualvals, &varubdualvals) );
4720  assert(primalvals != NULL || nlp->nvars == 0);
4721  assert((varlbdualvals != NULL) == (varubdualvals != NULL)); /* if there are duals for one bound, then there should also be duals for the other bound */
4722 
4723  /* store solution primal values in variable and evaluate objective function */
4724  if( nlp->indiving && nlp->divingobj != NULL )
4725  {
4726  for( i = 0; i < nlp->nvars; ++i )
4727  {
4728  SCIP_CALL( SCIPvarSetNLPSol(nlp->vars[i], set, primalvals[nlp->varmap_nlp2nlpi[i]]) ); /*lint !e613 */
4729  }
4730 
4731  /* evaluate modified diving objective */
4732  SCIP_CALL( SCIPnlrowGetNLPActivity(nlp->divingobj, set, stat, nlp, &nlp->primalsolobjval) );
4733  }
4734  else
4735  {
4736  /* evaluate SCIP objective function */
4737  nlp->primalsolobjval = 0.0;
4738  for( i = 0; i < nlp->nvars; ++i )
4739  {
4740  SCIP_CALL( SCIPvarSetNLPSol(nlp->vars[i], set, primalvals[nlp->varmap_nlp2nlpi[i]]) ); /*lint !e613 */
4741  nlp->primalsolobjval += SCIPvarGetObj(nlp->vars[i]) * primalvals[nlp->varmap_nlp2nlpi[i]]; /*lint !e613 */
4742  }
4743  }
4744 
4745  /* store solution dual values in nlrows and variables */
4746  for( i = 0; i < nlp->nnlrows; ++i )
4747  {
4748  assert(nlp->nlrows[i]->nlpiindex >= 0); /* NLP was flushed before solve, so all nlrows should be in there */
4749 
4750  nlp->nlrows[i]->dualsol = nlrowdualvals != NULL ? nlrowdualvals[nlp->nlrows[i]->nlpiindex] : 0.0;
4751 
4752  /* SCIPdebugMessage("dual of nlrow <%s> = %g\n", nlp->nlrows[i]->name, nlp->nlrows[i]->dualsol); */
4753  }
4754  assert(nlp->varlbdualvals != NULL || nlp->nvars == 0);
4755  assert(nlp->varubdualvals != NULL || nlp->nvars == 0);
4756  if( varlbdualvals != NULL )
4757  {
4758  for( i = 0; i < nlp->nvars; ++i )
4759  {
4760  assert(nlp->varmap_nlp2nlpi[i] >= 0); /* NLP was flushed before solve, so all vars should be in there */
4761 
4762  nlp->varlbdualvals[i] = varlbdualvals[nlp->varmap_nlp2nlpi[i]];
4763  nlp->varubdualvals[i] = varubdualvals[nlp->varmap_nlp2nlpi[i]];
4764 
4765  /* SCIPdebugMessage("duals of var <%s> = %g %g\n", SCIPvarGetName(nlp->vars[i]), nlp->varlbdualvals[i], nlp->varubdualvals[i]); */
4766  }
4767  }
4768  else if( nlp->nvars > 0 )
4769  {
4772  }
4773 
4774  break;
4775  }
4776  default:
4778  break;
4779  } /*lint !e788*/
4780 
4781  return SCIP_OKAY;
4782 }
4783 
4784 /** assembles list of fractional variables in last NLP solution */
4785 static
4787  SCIP_NLP* nlp, /**< NLP data */
4788  BMS_BLKMEM* blkmem, /**< block memory buffers */
4789  SCIP_SET* set, /**< global SCIP settings */
4790  SCIP_STAT* stat /**< problem statistics */
4791  )
4792 {
4793  assert(nlp != NULL);
4794  assert(blkmem != NULL);
4795  assert(set != NULL);
4796  assert(stat != NULL);
4797  assert(nlp->validfracvars <= stat->nnlps);
4798  assert(SCIPnlpHasSolution(nlp));
4799 
4800  SCIPdebugMessage("calculating NLP fractional variables: validfracvars=%" SCIP_LONGINT_FORMAT ", nnlps=%" SCIP_LONGINT_FORMAT "\n", nlp->validfracvars, stat->nnlps);
4801 
4803  {
4804  nlp->nfracvars = 0;
4805  nlp->npriofracvars = 0;
4806  nlp->validfracvars = stat->nnlps;
4807 
4808  SCIPdebugMessage("NLP globally infeasible, unbounded, or worse -> no solution values -> no fractional variables\n");
4809  return SCIP_OKAY;
4810  }
4811 
4812  /* check, if the current NLP fractional variables array is invalid */
4813  if( nlp->validfracvars < stat->nnlps )
4814  {
4815  SCIP_VAR* var;
4816  SCIP_Real primsol;
4817  SCIP_Real frac;
4818  int branchpriority;
4819  int insertpos;
4820  int maxpriority;
4821  int i;
4822 
4823  SCIPdebugMessage(" -> recalculating NLP fractional variables\n");
4824 
4825  if( nlp->fracvarssize == 0 )
4826  {
4827  assert(nlp->fracvars == NULL);
4828  assert(nlp->fracvarssol == NULL);
4829  assert(nlp->fracvarsfrac == NULL);
4830  nlp->fracvarssize = 5;
4831  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &nlp->fracvars, nlp->fracvarssize) );
4834  }
4835 
4836  maxpriority = INT_MIN;
4837  nlp->nfracvars = 0;
4838  nlp->npriofracvars = 0;
4839  for( i = 0; i < nlp->nvars; ++i )
4840  {
4841  var = nlp->vars[i];
4842  assert(var != NULL);
4843 
4844  primsol = SCIPvarGetNLPSol(var);
4845  assert(primsol < SCIP_INVALID);
4846 
4847  /* consider only binary and integer variables */
4849  continue;
4850 
4851  /* ignore fixed variables (due to numerics, it is possible, that the NLP solution of a fixed integer variable
4852  * (with large fixed value) is fractional in terms of absolute feasibility measure)
4853  */
4854  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
4855  continue;
4856 
4857  /* check, if the LP solution value is fractional */
4858  frac = SCIPsetFeasFrac(set, primsol);
4859  if( SCIPsetIsFeasFracIntegral(set, frac) )
4860  continue;
4861 
4862  /* ensure enough space in fracvars arrays */
4863  if( nlp->fracvarssize <= nlp->nfracvars )
4864  {
4865  int newsize;
4866 
4867  newsize = SCIPsetCalcMemGrowSize(set, nlp->nfracvars + 1);
4868  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvars, nlp->fracvarssize, newsize) );
4869  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvarssol, nlp->fracvarssize, newsize) );
4870  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->fracvarsfrac, nlp->fracvarssize, newsize) );
4871  nlp->fracvarssize = newsize;
4872  }
4873  assert(nlp->nfracvars < nlp->fracvarssize);
4874  assert(nlp->fracvars != NULL);
4875  assert(nlp->fracvarssol != NULL);
4876  assert(nlp->fracvarsfrac != NULL);
4877 
4878  /* insert candidate in candidate list */
4879  branchpriority = SCIPvarGetBranchPriority(var);
4880  insertpos = nlp->nfracvars;
4881  nlp->nfracvars++;
4882  if( branchpriority > maxpriority )
4883  {
4884  /* candidate has higher priority than the current maximum:
4885  * move it to the front and declare it to be the single best candidate
4886  */
4887  if( insertpos != 0 )
4888  {
4889  nlp->fracvars[insertpos] = nlp->fracvars[0];
4890  nlp->fracvarssol[insertpos] = nlp->fracvarssol[0];
4891  nlp->fracvarsfrac[insertpos] = nlp->fracvarsfrac[0];
4892  insertpos = 0;
4893  }
4894  nlp->npriofracvars = 1;
4895  maxpriority = branchpriority;
4896  }
4897  else if( branchpriority == maxpriority )
4898  {
4899  /* candidate has equal priority as the current maximum:
4900  * move away the first non-maximal priority candidate, move the current candidate to the correct
4901  * slot (binaries first) and increase the number of maximal priority candidates
4902  */
4903  if( insertpos != nlp->npriofracvars )
4904  {
4905  nlp->fracvars[insertpos] = nlp->fracvars[nlp->npriofracvars];
4906  nlp->fracvarssol[insertpos] = nlp->fracvarssol[nlp->npriofracvars];
4907  nlp->fracvarsfrac[insertpos] = nlp->fracvarsfrac[nlp->npriofracvars];
4908  insertpos = nlp->npriofracvars;
4909  }
4910  ++nlp->npriofracvars;
4911  }
4912  nlp->fracvars[insertpos] = var;
4913  nlp->fracvarssol[insertpos] = primsol;
4914  nlp->fracvarsfrac[insertpos] = frac;
4915 
4916  SCIPdebugMessage(" -> candidate %d: var=<%s>, sol=%g, frac=%g, prio=%d (max: %d) -> pos %d\n",
4917  nlp->nfracvars, SCIPvarGetName(var), primsol, frac, branchpriority, maxpriority, insertpos);
4918  }
4919 
4920  nlp->validfracvars = stat->nnlps;
4921  }
4922  assert(0 <= nlp->npriofracvars);
4923  assert(nlp->npriofracvars <= nlp->nfracvars);
4924 
4925  SCIPdebugMessage(" -> %d fractional variables (%d of maximal priority)\n", nlp->nfracvars, nlp->npriofracvars);
4926 
4927  return SCIP_OKAY;
4928 }
4929 
4930 /** event handling for variable events */
4931 static
4932 SCIP_DECL_EVENTEXEC(eventExecNlp)
4933 {
4934  SCIP_EVENTTYPE etype;
4935  SCIP_VAR* var;
4936 
4937  assert(scip != NULL);
4938  assert(eventhdlr != NULL);
4939  assert(event != NULL);
4940  assert(eventdata != NULL);
4941 
4942  assert((SCIP_NLP*)eventdata == scip->nlp);
4943 
4944  etype = SCIPeventGetType(event);
4945  var = SCIPeventGetVar(event);
4946 
4947  if( SCIP_EVENTTYPE_VARADDED & etype )
4948  {
4949  SCIPdebugMessage( "-> handling varadd event, variable <%s>\n", SCIPvarGetName(var) );
4950  SCIP_CALL( SCIPnlpAddVar(scip->nlp, SCIPblkmem(scip), scip->set, var) );
4951  }
4952  else if( SCIP_EVENTTYPE_VARDELETED & etype )
4953  {
4954  SCIPdebugMessage( "-> handling vardel event, variable <%s>\n", SCIPvarGetName(var) );
4955  SCIP_CALL( SCIPnlpDelVar(scip->nlp, SCIPblkmem(scip), scip->set, scip->eventqueue, scip->lp, var) );
4956  }
4957  else if( SCIP_EVENTTYPE_VARFIXED & etype )
4958  {
4959  /* variable was fixed, aggregated, or multi-aggregated */
4960  SCIPdebugMessage( "-> handling variable fixation event, variable <%s>\n", SCIPvarGetName(var) );
4961  SCIP_CALL( nlpRemoveFixedVar(scip->nlp, SCIPblkmem(scip), scip->set, scip->stat, scip->eventqueue, scip->lp, var) );
4962  }
4963  else if( SCIP_EVENTTYPE_BOUNDCHANGED & etype )
4964  {
4965  SCIPdebugMessage( "-> handling bound changed event %x, variable <%s>\n", etype, SCIPvarGetName(var) );
4967  }
4968  else if( SCIP_EVENTTYPE_OBJCHANGED & etype )
4969  {
4970  SCIPdebugMessage( "-> handling objchg event, variable <%s>\n", SCIPvarGetName(var) );
4971  SCIP_CALL( nlpUpdateObjCoef(scip->nlp, var) );
4972  }
4973  else
4974  {
4975  SCIPerrorMessage("unexpected event %d on variable <%s>\n", etype, SCIPvarGetName(var) );
4976  return SCIP_ERROR;
4977  }
4978 
4979  return SCIP_OKAY;
4980 }
4981 
4982 
4983 /*
4984  * public NLP methods
4985  */
4986 
4987 /** includes NLP specific plugins (e.g., event handler) and parameters */
4989  SCIP_SET* set, /**< global SCIP settings */
4990  BMS_BLKMEM* blkmem /**< block memory */
4991  )
4992 {
4993  SCIP_EVENTHDLR* eventhdlr;
4994 
4995  assert(set != NULL);
4996  assert(set->stage == SCIP_STAGE_INIT);
4997 
4998  /* check whether event handler is already present */
5000  {
5001  SCIPerrorMessage("event handler <" EVENTHDLR_NAME "> already included.\n");
5002  return SCIP_INVALIDDATA;
5003  }
5004 
5006  NULL, NULL, NULL, NULL, NULL, NULL, NULL, eventExecNlp, NULL) );
5007  SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
5008 
5009  return SCIP_OKAY;
5010 } /*lint !e715*/
5011 
5012 /** construct a new empty NLP */
5014  SCIP_NLP** nlp, /**< NLP handler, call by reference */
5015  BMS_BLKMEM* blkmem, /**< block memory */
5016  SCIP_SET* set, /**< global SCIP settings */
5017  SCIP_STAT* stat, /**< problem statistics */
5018  const char* name, /**< problem name */
5019  int nvars_estimate /**< an estimate on the number of variables that may be added to the NLP later */
5020  )
5021 {
5022  assert(nlp != NULL);
5023  assert(blkmem != NULL);
5024  assert(set != NULL);
5025  assert(stat != NULL);
5026  assert(name != NULL);
5027 
5028  SCIP_ALLOC( BMSallocMemory(nlp) );
5029 
5030  /* select NLP solver (if any available) and setup problem */
5031  if( set->nnlpis > 0 )
5032  {
5033  assert(set->nlp_solver != NULL);
5034  if( set->nlp_solver[0] == '\0' )
5035  { /* take solver with highest priority */
5036  assert(set->nlpis != NULL);
5037 
5038  /* sort the NLPIs if necessary */
5039  if( !set->nlpissorted )
5040  SCIPsetSortNlpis(set);
5041 
5042  (*nlp)->solver = set->nlpis[0];
5043  }
5044  else
5045  { /* find user specified NLP solver */
5046  (*nlp)->solver = SCIPsetFindNlpi(set, set->nlp_solver);
5047  if( (*nlp)->solver == NULL )
5048  {
5049  SCIPerrorMessage("Selected NLP solver <%s> not available.\n", set->nlp_solver);
5050  return SCIP_PLUGINNOTFOUND;
5051  }
5052  }
5053  assert((*nlp)->solver != NULL);
5054  SCIP_CALL( SCIPnlpiCreateProblem((*nlp)->solver, &(*nlp)->problem, "scip_nlp") );
5055  }
5056  else
5057  {
5058  /* maybe someone wanna use the NLP just to collect nonlinearities, but is not necessarily interesting on solving
5059  * so we allow this and just continue */
5060  (*nlp)->solver = NULL;
5061  (*nlp)->problem = NULL;
5062  }
5063 
5064  /* status */
5065  (*nlp)->nunflushedvaradd = 0;
5066  (*nlp)->nunflushedvardel = 0;
5067  (*nlp)->nunflushednlrowadd = 0;
5068  (*nlp)->nunflushednlrowdel = 0;
5069  (*nlp)->isrelax = TRUE;
5070  (*nlp)->indiving = FALSE;
5071 
5072  /* variables in problem and NLPI problem */
5073  (*nlp)->nvars = 0;
5074  (*nlp)->sizevars = 0;
5075  (*nlp)->vars = NULL;
5076  SCIP_CALL( SCIPhashmapCreate(&(*nlp)->varhash, blkmem, SCIPcalcHashtableSize(5 * nvars_estimate)) );
5077 
5078  (*nlp)->nvars_solver = 0;
5079  (*nlp)->sizevars_solver = 0;
5080  (*nlp)->varmap_nlp2nlpi = NULL;
5081  (*nlp)->varmap_nlpi2nlp = NULL;
5082 
5083  /* nonlinear rows in problem and NLPI problem */
5084  (*nlp)->nnlrows = 0;
5085  (*nlp)->sizenlrows = 0;
5086  (*nlp)->nlrows = NULL;
5087 
5088  (*nlp)->nnlrows_solver = 0;
5089  (*nlp)->sizenlrows_solver = 0;
5090  (*nlp)->nlrowmap_nlpi2nlp = NULL;
5091 
5092  /* objective function */
5093  (*nlp)->objflushed = TRUE;
5094  (*nlp)->divingobj = NULL;
5095 
5096  /* initial guess */
5097  (*nlp)->haveinitguess = FALSE;
5098  (*nlp)->initialguess = NULL;
5099 
5100  /* solution of NLP */
5101  (*nlp)->primalsolobjval = SCIP_INVALID;
5102  (*nlp)->solstat = SCIP_NLPSOLSTAT_UNKNOWN;
5103  (*nlp)->termstat = SCIP_NLPTERMSTAT_OTHER;
5104  (*nlp)->varlbdualvals = NULL;
5105  (*nlp)->varubdualvals = NULL;
5106 
5107  /* event handling: catch variable addition and deletion events */
5108  (*nlp)->eventhdlr = SCIPsetFindEventhdlr(set, EVENTHDLR_NAME);
5109  if( (*nlp)->eventhdlr == NULL )
5110  {
5111  SCIPerrorMessage("NLP eventhandler <" EVENTHDLR_NAME "> not found.\n");
5112  return SCIP_PLUGINNOTFOUND;
5113  }
5114  SCIP_CALL( SCIPeventfilterAdd(set->scip->eventfilter, blkmem, set,
5116  (*nlp)->eventhdlr, (SCIP_EVENTDATA*)(*nlp), &(*nlp)->globalfilterpos) );
5117 
5118  /* fractional variables in last NLP solution */
5119  (*nlp)->fracvars = NULL;
5120  (*nlp)->fracvarssol = NULL;
5121  (*nlp)->fracvarsfrac = NULL;
5122  (*nlp)->nfracvars = 0;
5123  (*nlp)->npriofracvars = 0;
5124  (*nlp)->fracvarssize = 0;
5125  (*nlp)->validfracvars = -1;
5126 
5127  /* miscellaneous */
5128  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*nlp)->name, name, strlen(name)+1) );
5129 
5130  return SCIP_OKAY;
5131 }
5132 
5133 /** frees NLP data object */
5135  SCIP_NLP** nlp, /**< pointer to NLP data object */
5136  BMS_BLKMEM* blkmem, /**< block memory */
5137  SCIP_SET* set, /**< global SCIP settings */
5138  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5139  SCIP_LP* lp /**< SCIP LP, needed for releasing variables */
5140  )
5141 {
5142  assert(nlp != NULL);
5143  assert(*nlp != NULL);
5144  assert(blkmem != NULL);
5145  assert(set != NULL);
5146 
5147  /* drop fractional variables */
5148  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvars, (*nlp)->fracvarssize);
5149  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvarssol, (*nlp)->fracvarssize);
5150  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->fracvarsfrac, (*nlp)->fracvarssize);
5151 
5152  /* drop global events (variable addition and deletion) */
5153  SCIP_CALL( SCIPeventfilterDel(set->scip->eventfilter, blkmem, set,
5155  (*nlp)->eventhdlr, (SCIP_EVENTDATA*)(*nlp), (*nlp)->globalfilterpos) );
5156 
5157  SCIP_CALL( SCIPnlpReset(*nlp, blkmem, set, eventqueue, lp) );
5158  assert((*nlp)->nnlrows == 0);
5159  assert((*nlp)->nnlrows_solver == 0);
5160  assert((*nlp)->nvars == 0);
5161  assert((*nlp)->nvars_solver == 0);
5162  assert((*nlp)->initialguess == NULL);
5163 
5164  BMSfreeBlockMemoryArray(blkmem, &(*nlp)->name, strlen((*nlp)->name)+1);
5165 
5166  /* free nonlinear rows arrays */
5167  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->nlrowmap_nlpi2nlp, (*nlp)->sizenlrows_solver);
5168  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->nlrows, (*nlp)->sizenlrows);
5169 
5170  /* free variables arrays */
5171  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varmap_nlp2nlpi, (*nlp)->sizevars);
5172  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varmap_nlpi2nlp, (*nlp)->sizevars_solver);
5173  SCIPhashmapFree(&(*nlp)->varhash);
5174  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->vars, (*nlp)->sizevars);
5175  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varlbdualvals, (*nlp)->sizevars);
5176  BMSfreeBlockMemoryArrayNull(blkmem, &(*nlp)->varubdualvals, (*nlp)->sizevars);
5177 
5178  /* free NLPI problem */
5179  if( (*nlp)->problem != NULL )
5180  {
5181  SCIP_CALL( SCIPnlpiFreeProblem((*nlp)->solver, &(*nlp)->problem) );
5182  }
5183 
5184  /* free NLP data structure */
5185  BMSfreeMemory(nlp);
5186 
5187  return SCIP_OKAY;
5188 }
5189 
5190 /** resets the NLP to the empty NLP by removing all variables and rows from NLP,
5191  * releasing all rows, and flushing the changes to the NLP solver
5192  */
5194  SCIP_NLP* nlp, /**< NLP data */
5195  BMS_BLKMEM* blkmem, /**< block memory */
5196  SCIP_SET* set, /**< global SCIP settings */
5197  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5198  SCIP_LP* lp /**< SCIP LP, needed for releasing variables */
5199  )
5200 {
5201  int i;
5202 
5203  assert(nlp != NULL);
5204  assert(blkmem != NULL);
5205  assert(set != NULL);
5206 
5207  if( nlp->indiving )
5208  {
5209  SCIP_CALL( SCIPnlpEndDive(nlp, blkmem, set) );
5210  }
5211 
5214 
5215  BMSfreeBlockMemoryArrayNull(blkmem, &nlp->initialguess, nlp->nvars);
5216  nlp->haveinitguess = FALSE;
5217 
5218  for(i = nlp->nnlrows - 1; i >= 0; --i)
5219  {
5220  SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, i) );
5221  }
5222 
5223  for(i = nlp->nvars - 1; i >= 0; --i)
5224  {
5225  SCIP_CALL( nlpDelVarPos(nlp, blkmem, set, eventqueue, lp, i) );
5226  }
5227 
5228  SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set) );
5229 
5230  return SCIP_OKAY;
5231 }
5232 
5233 /** currently a dummy function that always returns TRUE */
5235  SCIP_NLP* nlp /**< NLP data */
5236  )
5237 {
5238  return TRUE;
5239 } /*lint !e715*/
5240 
5241 /** ensures, that variables array of NLP can store at least num entries */
5243  SCIP_NLP* nlp, /**< NLP data */
5244  BMS_BLKMEM* blkmem, /**< block memory */
5245  SCIP_SET* set, /**< global SCIP settings */
5246  int num /**< minimum number of entries to store */
5247  )
5248 {
5249  assert(nlp != NULL);
5250  assert(blkmem != NULL);
5251  assert(set != NULL);
5252  assert(nlp->nvars <= nlp->sizevars);
5253 
5254  if( num > nlp->sizevars )
5255  {
5256  int newsize;
5257 
5258  newsize = SCIPsetCalcMemGrowSize(set, num);
5259  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->vars, nlp->sizevars, newsize) );
5260  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varmap_nlp2nlpi, nlp->sizevars, newsize) );
5261  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varlbdualvals, nlp->sizevars, newsize) );
5262  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->varubdualvals, nlp->sizevars, newsize) );
5263  if( nlp->initialguess != NULL )
5264  {
5265  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->initialguess, nlp->sizevars, newsize) );
5266  }
5267 
5268  nlp->sizevars = newsize;
5269  }
5270  assert(num <= nlp->sizevars);
5271 
5272  return SCIP_OKAY;
5273 }
5274 
5275 /** adds a variable to the NLP and captures the variable */
5277  SCIP_NLP* nlp, /**< NLP data */
5278  BMS_BLKMEM* blkmem, /**< block memory */
5279  SCIP_SET* set, /**< global SCIP settings */
5280  SCIP_VAR* var /**< variable */
5281  )
5282 {
5283  assert(nlp != NULL);
5284  assert(blkmem != NULL);
5285  assert(set != NULL);
5286  assert(var != NULL);
5287  assert(SCIPvarIsTransformed(var));
5288  assert(!SCIPhashmapExists(nlp->varhash, var));
5289 
5290  if( nlp->indiving )
5291  {
5292  SCIPerrorMessage("cannot add variable during NLP diving\n");
5293  return SCIP_ERROR;
5294  }
5295 
5296  SCIP_CALL( nlpAddVars(nlp, blkmem, set, 1, &var) );
5297 
5298  return SCIP_OKAY;
5299 }
5300 
5301 /** adds a set of variables to the NLP and captures the variables */
5303  SCIP_NLP* nlp, /**< NLP data */
5304  BMS_BLKMEM* blkmem, /**< block memory */
5305  SCIP_SET* set, /**< global SCIP settings */
5306  int nvars, /**< number of variables to add */
5307  SCIP_VAR** vars /**< variables to add */
5308  )
5309 {
5310  assert(nlp != NULL);
5311  assert(blkmem != NULL);
5312  assert(set != NULL);
5313  assert(vars != NULL || nvars == 0);
5314 
5315  if( nlp->indiving && nvars > 0)
5316  {
5317  SCIPerrorMessage("cannot add variables during NLP diving\n");
5318  return SCIP_ERROR;
5319  }
5320 
5321  SCIP_CALL( nlpAddVars(nlp, blkmem, set, nvars, vars) );
5322 
5323  return SCIP_OKAY;
5324 }
5325 
5326 /** deletes a variable from the NLP and releases the variable */
5328  SCIP_NLP* nlp, /**< NLP data */
5329  BMS_BLKMEM* blkmem, /**< block memory */
5330  SCIP_SET* set, /**< global SCIP settings */
5331  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5332  SCIP_LP* lp, /**< SCIP LP, needed to release variable */
5333  SCIP_VAR* var /**< variable */
5334  )
5335 {
5336  int varpos;
5337 
5338  assert(nlp != NULL);
5339  assert(blkmem != NULL);
5340  assert(set != NULL);
5341  assert(var != NULL);
5342 
5343  if( !SCIPhashmapExists(nlp->varhash, var) )
5344  {
5345  SCIPerrorMessage("variable <%s> not found in NLP, cannot delete\n", SCIPvarGetName(var));
5346  return SCIP_ERROR;
5347  }
5348 
5349  if( nlp->indiving )
5350  {
5351  SCIPerrorMessage("cannot delete variable during NLP diving\n");
5352  return SCIP_ERROR;
5353  }
5354 
5355  varpos = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, var);
5356 
5357  SCIP_CALL( nlpDelVarPos(nlp, blkmem, set, eventqueue, lp, varpos) );
5358 
5359  return SCIP_OKAY;
5360 }
5361 
5362 /** ensures, that nonlinear rows array of NLP can store at least num entries */
5364  SCIP_NLP* nlp, /**< NLP data */
5365  BMS_BLKMEM* blkmem, /**< block memory */
5366  SCIP_SET* set, /**< global SCIP settings */
5367  int num /**< minimum number of entries to store */
5368  )
5369 {
5370  assert(nlp != NULL);
5371  assert(blkmem != NULL);
5372  assert(set != NULL);
5373  assert(nlp->nnlrows <= nlp->sizenlrows);
5374 
5375  if( num > nlp->sizenlrows )
5376  {
5377  int newsize;
5378 
5379  newsize = SCIPsetCalcMemGrowSize(set, num);
5380  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &nlp->nlrows, nlp->sizenlrows, newsize) );
5381 
5382  nlp->sizenlrows = newsize;
5383  }
5384  assert(num <= nlp->sizenlrows);
5385 
5386  return SCIP_OKAY;
5387 }
5388 
5389 /** adds a nonlinear row to the NLP and captures it
5390  * all variables of the row need to be present in the NLP */
5392  SCIP_NLP* nlp, /**< NLP data */
5393  BMS_BLKMEM* blkmem, /**< block memory */
5394  SCIP_SET* set, /**< global SCIP settings */
5395  SCIP_STAT* stat, /**< problem statistics data */
5396  SCIP_NLROW* nlrow /**< nonlinear row */
5397  )
5398 {
5399  assert(nlp != NULL);
5400  assert(nlrow != NULL);
5401 
5402  if( nlp->indiving )
5403  {
5404  SCIPerrorMessage("cannot add row during NLP diving\n");
5405  return SCIP_ERROR;
5406  }
5407 
5408  SCIP_CALL( nlpAddNlRows(nlp, blkmem, set, stat, 1, &nlrow) );
5409 
5410  return SCIP_OKAY;
5411 }
5412 
5413 /** adds nonlinear rows to the NLP and captures them
5414  * all variables of the row need to be present in the NLP */
5416  SCIP_NLP* nlp, /**< NLP data */
5417  BMS_BLKMEM* blkmem, /**< block memory */
5418  SCIP_SET* set, /**< global SCIP settings */
5419  SCIP_STAT* stat, /**< problem statistics data */
5420  int nnlrows, /**< number of rows to add */
5421  SCIP_NLROW** nlrows /**< rows to add */
5422  )
5423 {
5424  assert(nlp != NULL);
5425  assert(nlrows != NULL || nnlrows == 0);
5426 
5427  if( nnlrows == 0 )
5428  return SCIP_OKAY;
5429 
5430  if( nlp->indiving )
5431  {
5432  SCIPerrorMessage("cannot add rows during NLP diving\n");
5433  return SCIP_ERROR;
5434  }
5435 
5436  SCIP_CALL( nlpAddNlRows(nlp, blkmem, set, stat, nnlrows, nlrows) );
5437 
5438  return SCIP_OKAY;
5439 }
5440 
5441 /** deletes a nonlinear row from the NLP
5442  * does nothing if nonlinear row is not in NLP */
5444  SCIP_NLP* nlp, /**< NLP data */
5445  BMS_BLKMEM* blkmem, /**< block memory */
5446  SCIP_SET* set, /**< global SCIP settings */
5447  SCIP_NLROW* nlrow /**< nonlinear row */
5448  )
5449 {
5450  assert(nlp != NULL);
5451  assert(blkmem != NULL);
5452  assert(set != NULL);
5453  assert(nlrow != NULL);
5454 
5455  /* if row not in NLP, nothing to do */
5456  if( nlrow->nlpindex == -1 )
5457  return SCIP_OKAY;
5458 
5459  assert(nlrow->nlpindex >= 0);
5460  assert(nlrow->nlpindex < nlp->nnlrows);
5461 
5462  if( nlp->indiving )
5463  {
5464  SCIPerrorMessage("cannot delete row during NLP diving\n");
5465  return SCIP_ERROR;
5466  }
5467 
5468  SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, nlrow->nlpindex) );
5469 
5470  return SCIP_OKAY;
5471 }
5472 
5473 /** applies all cached changes to the NLP solver */
5475  SCIP_NLP* nlp, /**< current NLP data */
5476  BMS_BLKMEM* blkmem, /**< block memory */
5477  SCIP_SET* set /**< global SCIP settings */
5478  )
5479 {
5480  assert(nlp != NULL);
5481  assert(blkmem != NULL);
5482  assert(set != NULL);
5483 
5484  if( nlp->indiving )
5485  {
5486  SCIPerrorMessage("cannot flush NLP during NLP diving\n");
5487  return SCIP_ERROR;
5488  }
5489 
5490  /* flush removals of nonlinear rows and variables */
5491  SCIP_CALL( nlpFlushNlRowDeletions(nlp, blkmem, set) );
5492  SCIP_CALL( nlpFlushVarDeletions(nlp, blkmem, set) );
5493  assert(nlp->nunflushednlrowdel == 0);
5494  assert(nlp->nunflushedvardel == 0);
5495 
5496  /* flush addition of variables, objective, and addition of rows */
5497  SCIP_CALL( nlpFlushVarAdditions(nlp, blkmem, set) );
5498  SCIP_CALL( nlpFlushObjective(nlp, blkmem, set) );
5499  SCIP_CALL( nlpFlushNlRowAdditions(nlp, blkmem, set) );
5500  assert(nlp->nunflushedvaradd == 0);
5501  assert(nlp->objflushed == TRUE);
5502  assert(nlp->nunflushednlrowadd == 0);
5503 
5504  assert(nlp->nvars == nlp->nvars_solver);
5505  assert(nlp->nnlrows == nlp->nnlrows_solver);
5506 
5507  return SCIP_OKAY;
5508 }
5509 
5510 /** solves the NLP */
5512  SCIP_NLP* nlp, /**< NLP data */
5513  BMS_BLKMEM* blkmem, /**< block memory buffers */
5514  SCIP_SET* set, /**< global SCIP settings */
5515  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5516  SCIP_STAT* stat /**< problem statistics */
5517  )
5518 {
5519  assert(nlp != NULL);
5520  assert(blkmem != NULL);
5521  assert(set != NULL);
5522  assert(stat != NULL);
5523 
5524  if( nlp->indiving )
5525  {
5526  SCIPerrorMessage("cannot solve NLP during NLP diving (use SCIPsolveDiveNLP)\n");
5527  return SCIP_ERROR;
5528  }
5529 
5530  SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set) );
5531 
5532  SCIP_CALL( nlpSolve(nlp, blkmem, set, messagehdlr, stat) );
5533 
5534  return SCIP_OKAY;
5535 }
5536 
5537 /** gets objective value of current NLP */
5539  SCIP_NLP* nlp /**< current NLP data */
5540  )
5541 {
5542  assert(nlp != NULL);
5543 
5544  return nlp->primalsolobjval;
5545 }
5546 
5547 /** gives current pseudo objective value */
5549  SCIP_NLP* nlp, /**< current NLP data */
5550  SCIP_SET* set, /**< global SCIP settings */
5551  SCIP_STAT* stat, /**< problem statistics */
5552  SCIP_Real* pseudoobjval /**< buffer to store pseudo objective value */
5553  )
5554 {
5555  assert(nlp != NULL);
5556  assert(pseudoobjval != NULL);
5557 
5558  if( nlp->divingobj != NULL )
5559  {
5560  assert(nlp->indiving);
5561  SCIP_CALL( SCIPnlrowGetPseudoActivity(nlp->divingobj, set, stat, pseudoobjval) );
5562  }
5563  else
5564  {
5565  int i;
5566 
5567  *pseudoobjval = 0.0;
5568  for( i = 0; i < nlp->nvars; ++i )
5569  *pseudoobjval += SCIPvarGetObj(nlp->vars[i]) * SCIPvarGetBestBoundLocal(nlp->vars[i]);
5570  }
5571 
5572  return SCIP_OKAY;
5573 }
5574 
5575 /** gets fractional variables of last NLP solution along with solution values and fractionalities
5576  */
5578  SCIP_NLP* nlp, /**< NLP data structure */
5579  BMS_BLKMEM* blkmem, /**< block memory */
5580  SCIP_SET* set, /**< global SCIP settings */
5581  SCIP_STAT* stat, /**< problem statistics */
5582  SCIP_VAR*** fracvars, /**< pointer to store the array of NLP fractional variables, or NULL */
5583  SCIP_Real** fracvarssol, /**< pointer to store the array of NLP fractional variables solution values, or NULL */
5584  SCIP_Real** fracvarsfrac, /**< pointer to store the array of NLP fractional variables fractionalities, or NULL */
5585  int* nfracvars, /**< pointer to store the number of NLP fractional variables , or NULL */
5586  int* npriofracvars /**< pointer to store the number of NLP fractional variables with maximal branching priority, or NULL */
5587  )
5588 {
5589  assert(nlp != NULL);
5590 
5591  SCIP_CALL( nlpCalcFracVars(nlp, blkmem, set, stat) );
5592  assert(nlp->fracvars != NULL);
5593  assert(nlp->fracvarssol != NULL);
5594  assert(nlp->fracvarsfrac != NULL);
5595 
5596  if( fracvars != NULL )
5597  *fracvars = nlp->fracvars;
5598  if( fracvarssol != NULL )
5599  *fracvarssol = nlp->fracvarssol;
5600  if( fracvarsfrac != NULL )
5601  *fracvarsfrac = nlp->fracvarsfrac;
5602  if( nfracvars != NULL )
5603  *nfracvars = nlp->nfracvars;
5604  if( npriofracvars != NULL )
5605  *npriofracvars = nlp->npriofracvars;
5606 
5607  return SCIP_OKAY;
5608 }
5609 
5610 /** removes all redundant nonlinear rows */
5612  SCIP_NLP* nlp, /**< current NLP data */
5613  BMS_BLKMEM* blkmem, /**< block memory buffers */
5614  SCIP_SET* set, /**< global SCIP settings */
5615  SCIP_STAT* stat /**< problem statistics */
5616  )
5617 {
5618  SCIP_NLPSOLSTAT solstatus;
5619  SCIP_Bool isredundant;
5620  int i;
5621 
5622  assert(nlp != NULL);
5623  assert(blkmem != NULL);
5624  assert(set != NULL);
5625  assert(stat != NULL);
5626 
5627  if( nlp->nnlrows == 0 )
5628  return SCIP_OKAY;
5629 
5630  if( nlp->indiving )
5631  {
5632  SCIPerrorMessage("cannot remove redundant rows during NLP diving\n");
5633  return SCIP_ERROR;
5634  }
5635 
5636  /* removing redundant rows should not change the solution status, so we reset it at the end */
5637  solstatus = nlp->solstat;
5638 
5639  for( i = 0; i < nlp->nnlrows; ++i )
5640  {
5641  SCIP_CALL( SCIPnlrowIsRedundant(nlp->nlrows[i], set, stat, &isredundant) );
5642  if( isredundant )
5643  {
5644  SCIP_CALL( nlpDelNlRowPos(nlp, blkmem, set, i) );
5645  }
5646  }
5647 
5648  nlp->solstat = solstatus;
5649 
5650  return SCIP_OKAY;
5651 }
5652 
5653 /** set initial guess (approximate primal solution) for next solve
5654  *
5655  * array initguess must be NULL or have length at least SCIPnlpGetNVars()
5656  */
5658  SCIP_NLP* nlp, /**< current NLP data */
5659  BMS_BLKMEM* blkmem, /**< block memory buffers */
5660  SCIP_Real* initguess /**< new initial guess, or NULL to clear previous one */
5661  )
5662 {
5663  assert(nlp != NULL);
5664  assert(blkmem != NULL);
5665  assert(nlp->solver != NULL);
5666  assert(nlp->problem != NULL);
5667 
5668  /* if user wants to let NLP solver choose start point, then invalidate current initial guess both in NLP and in NLPI */
5669  if( initguess == NULL )
5670  {
5671  nlp->haveinitguess = FALSE;
5673  return SCIP_OKAY;
5674  }
5675 
5676  if( nlp->initialguess != NULL )
5677  {
5678  BMScopyMemoryArray(nlp->initialguess, initguess, nlp->nvars);
5679  }
5680  else
5681  {
5682  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &nlp->initialguess, initguess, nlp->nvars) );
5683  }
5684  nlp->haveinitguess = TRUE;
5685 
5686  return SCIP_OKAY;
5687 }
5688 
5689 /** writes NLP to a file */
5691  SCIP_NLP* nlp, /**< current NLP data */
5692  SCIP_SET* set, /**< global SCIP settings */
5693  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5694  const char* fname /**< file name */
5695  )
5696 {
5697  FILE* file;
5698  int i;
5699 
5700  assert(nlp != NULL);
5701 
5702  if( fname != NULL )
5703  {
5704  file = fopen(fname, "w");
5705  if( file == NULL )
5706  {
5707  SCIPerrorMessage("could not open file <%s> for writing\n", fname);
5708  return SCIP_FILECREATEERROR;
5709  }
5710  }
5711  else
5712  file = stdout;
5713 
5714  SCIPmessageFPrintInfo(messagehdlr, file, "STATISTICS\n");
5715  SCIPmessageFPrintInfo(messagehdlr, file, " NLP name: %s\n", nlp->name);
5716  SCIPmessageFPrintInfo(messagehdlr, file, " Variables: %d\n", nlp->nvars);
5717  SCIPmessageFPrintInfo(messagehdlr, file, " Rows: %d\n", nlp->nnlrows);
5718 
5719  SCIPmessageFPrintInfo(messagehdlr, file, "VARIABLES\n");
5720  for( i = 0; i < nlp->nvars; ++i )
5721  {
5722  SCIP_CALL( SCIPvarPrint(nlp->vars[i], set, messagehdlr, file) );
5723  }
5724 
5725  SCIPmessageFPrintInfo(messagehdlr, file, "NONLINEAR ROWS\n");
5726  for( i = 0; i < nlp->nnlrows; ++i )
5727  {
5728  SCIPmessageFPrintInfo(messagehdlr, file, " ");
5729  SCIP_CALL( SCIPnlrowPrint(nlp->nlrows[i], messagehdlr, file) );
5730  }
5731 
5732  if( fname != NULL )
5733  {
5734  fclose(file);
5735  }
5736 
5737  return SCIP_OKAY;
5738 }
5739 
5740 /** gets array with variables of the NLP */
5742  SCIP_NLP* nlp /**< current NLP data */
5743  )
5744 {
5745  assert(nlp != NULL);
5746 
5747  return nlp->vars;
5748 }
5749 
5750 /** gets current number of variables in NLP */
5752  SCIP_NLP* nlp /**< current NLP data */
5753  )
5754 {
5755  assert(nlp != NULL);
5756 
5757  return nlp->nvars;
5758 }
5759 
5760 /** computes for each variables the number of NLP rows in which the variable appears in a nonlinear var */
5762  SCIP_NLP* nlp, /**< current NLP data */
5763  int* nlcount /**< an array of length at least SCIPnlpGetNVars() to store nonlinearity counts of variables */
5764  )
5765 {
5766  SCIP_NLROW* nlrow;
5767  int varidx;
5768  int i;
5769  int c;
5770 
5771  assert(nlp != NULL);
5772  assert(nlcount != NULL || nlp->nvars == 0);
5773 
5774  BMSclearMemoryArray(nlcount, nlp->nvars);
5775 
5776  for( c = 0; c < nlp->nnlrows; ++c )
5777  {
5778  nlrow = nlp->nlrows[c];
5779  assert(nlrow != NULL);
5780 
5781  for( i = 0; i < nlrow->nquadvars; ++i )
5782  {
5783  assert(SCIPhashmapExists(nlp->varhash, (void*)nlrow->quadvars[i]));
5784  varidx = (int)(size_t) SCIPhashmapGetImage(nlp->varhash, (void*)nlrow->quadvars[i]);
5785  assert(varidx < nlp->nvars);
5786  ++nlcount[varidx]; /*lint !e613 */
5787  }
5788 
5789  if( nlrow->exprtree != NULL )
5790  {
5791  SCIP_VAR** exprtreevars;
5792  int nexprtreevars;
5793 
5794  exprtreevars = SCIPexprtreeGetVars(nlrow->exprtree);
5795  nexprtreevars = SCIPexprtreeGetNVars(nlrow->exprtree);
5796  assert(exprtreevars != NULL || nexprtreevars == 0);
5797  for( i = 0; i < nexprtreevars; ++i )
5798  {
5799  assert(SCIPhashmapExists(nlp->varhash, (void*)exprtreevars[i])); /*lint !e613 */
5800 
5801  /* skip variables that also appear in quadratic part, so they are not counted twice */
5802  if( nlrow->quadvarshash != NULL && SCIPhashmapExists(nlrow->quadvarshash, (void*)exprtreevars[i]) ) /*lint !e613 */
5803  continue;
5804 
5805  varidx = (int)(size_t) SCIPhashmapGetImage(nlp->varhash, (void*)exprtreevars[i]); /*lint !e613 */
5806  assert(varidx < nlp->nvars);
5807  ++nlcount[varidx]; /*lint !e613 */
5808  }
5809  }
5810  }
5811 
5812  return SCIP_OKAY;
5813 }
5814 
5815 
5816 /** indicates whether there exists a row that contains a continuous variable in a nonlinear term
5817  *
5818  * @note The method may have to touch every row and nonlinear term to compute its result.
5819  */
5821  SCIP_NLP* nlp /**< current NLP data */
5822  )
5823 {
5824  SCIP_NLROW* nlrow;
5825  int c;
5826  int i;
5827 
5828  assert(nlp != NULL);
5829 
5830  for( c = 0; c < nlp->nnlrows; ++c )
5831  {
5832  nlrow = nlp->nlrows[c];
5833  assert(nlrow != NULL);
5834 
5835  for( i = 0; i < nlrow->nquadvars; ++i )
5836  if( SCIPvarGetType(nlrow->quadvars[i]) == SCIP_VARTYPE_CONTINUOUS )
5837  return TRUE;
5838 
5839  if( nlrow->exprtree != NULL )
5840  {
5841  SCIP_VAR** exprtreevars;
5842  int nexprtreevars;
5843 
5844  exprtreevars = SCIPexprtreeGetVars(nlrow->exprtree);
5845  nexprtreevars = SCIPexprtreeGetNVars(nlrow->exprtree);
5846  assert(exprtreevars != NULL || nexprtreevars == 0);
5847 
5848  for( i = 0; i < nexprtreevars; ++i )
5849  if( SCIPvarGetType(exprtreevars[i]) == SCIP_VARTYPE_CONTINUOUS ) /*lint !e613*/
5850  return TRUE;
5851  }
5852  }
5853 
5854  return FALSE;
5855 }
5856 
5857 /** gives dual solution values associated with lower bounds of NLP variables */
5859  SCIP_NLP* nlp /**< current NLP data */
5860  )
5861 {
5862  assert(nlp != NULL);
5863 
5864  return nlp->varlbdualvals;
5865 }
5866 
5867 /** gives dual solution values associated with upper bounds of NLP variables */
5869  SCIP_NLP* nlp /**< current NLP data */
5870  )
5871 {
5872  assert(nlp != NULL);
5873 
5874  return nlp->varubdualvals;
5875 }
5876 
5877 /** gets array with nonlinear rows of the NLP */
5879  SCIP_NLP* nlp /**< current NLP data */
5880  )
5881 {
5882  assert(nlp != NULL);
5883 
5884  return nlp->nlrows;
5885 }
5886 
5887 /** gets current number of nonlinear rows in NLP */
5889  SCIP_NLP* nlp /**< current NLP data */
5890  )
5891 {
5892  assert(nlp != NULL);
5893 
5894  return nlp->nnlrows;
5895 }
5896 
5897 /** gets the NLP solver interface */
5899  SCIP_NLP* nlp /**< current NLP data */
5900  )
5901 {
5902  assert(nlp != NULL);
5903 
5904  return nlp->solver;
5905 }
5906 
5907 /** gets the NLP problem in the solver interface */
5909  SCIP_NLP* nlp /**< current NLP data */
5910  )
5911 {
5912  assert(nlp != NULL);
5913 
5914  return nlp->problem;
5915 }
5916 
5917 /** indicates whether NLP is currently in diving mode */
5919  SCIP_NLP* nlp /**< current NLP data */
5920  )
5921 {
5922  assert(nlp != NULL);
5923 
5924  return nlp->indiving;
5925 }
5926 
5927 /** gets solution status of current NLP */
5929  SCIP_NLP* nlp /**< current NLP data */
5930  )
5931 {
5932  assert(nlp != NULL);
5933 
5934  return nlp->solstat;
5935 }
5936 
5937 /** gets termination status of last NLP solve */
5939  SCIP_NLP* nlp /**< current NLP data */
5940  )
5941 {
5942  assert(nlp != NULL);
5943 
5944  return nlp->termstat;
5945 }
5946 
5947 /** gives statistics (number of iterations, solving time, ...) of last NLP solve */
5949  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
5950  SCIP_NLPSTATISTICS* statistics /**< pointer to store statistics */
5951  )
5952 {
5953  assert(nlp != NULL);
5954  assert(nlp->solver != NULL);
5955  assert(nlp->problem != NULL);
5956  assert(statistics != NULL);
5957 
5958  SCIP_CALL( SCIPnlpiGetStatistics(nlp->solver, nlp->problem, statistics) );
5959 
5960  return SCIP_OKAY;
5961 }
5962 
5963 /** indicates whether a feasible solution for the current NLP is available
5964  * thus, returns whether the solution status <= feasible */
5966  SCIP_NLP* nlp /**< current NLP data */
5967  )
5968 {
5969  assert(nlp != NULL);
5970 
5971  return nlp->solstat <= SCIP_NLPSOLSTAT_FEASIBLE;
5972 }
5973 
5974 /** gets integer parameter of NLP */
5976  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
5977  SCIP_NLPPARAM type, /**< parameter number */
5978  int* ival /**< pointer to store the parameter value */
5979  )
5980 {
5981  assert(nlp != NULL);
5982  assert(nlp->solver != NULL);
5983  assert(nlp->problem != NULL);
5984  assert(ival != NULL);
5985 
5986  SCIP_CALL( SCIPnlpiGetIntPar(nlp->solver, nlp->problem, type, ival) );
5987 
5988  return SCIP_OKAY;
5989 }
5990 
5991 /** sets integer parameter of NLP */
5993  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
5994  SCIP_NLPPARAM type, /**< parameter number */
5995  int ival /**< parameter value */
5996  )
5997 {
5998  assert(nlp != NULL);
5999  assert(nlp->solver != NULL);
6000  assert(nlp->problem != NULL);
6001 
6002  SCIP_CALL( SCIPnlpiSetIntPar(nlp->solver, nlp->problem, type, ival) );
6003 
6004  return SCIP_OKAY;
6005 }
6006 
6007 /** gets floating point parameter of NLP */
6009  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
6010  SCIP_NLPPARAM type, /**< parameter number */
6011  SCIP_Real* dval /**< pointer to store the parameter value */
6012  )
6013 {
6014  assert(nlp != NULL);
6015  assert(nlp->solver != NULL);
6016  assert(nlp->problem != NULL);
6017  assert(dval != NULL);
6018 
6019  SCIP_CALL( SCIPnlpiGetRealPar(nlp->solver, nlp->problem, type, dval) );
6020 
6021  return SCIP_OKAY;
6022 }
6023 
6024 /** sets floating point parameter of NLP */
6026  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
6027  SCIP_NLPPARAM type, /**< parameter number */
6028  SCIP_Real dval /**< parameter value */
6029  )
6030 {
6031  assert(nlp != NULL);
6032  assert(nlp->solver != NULL);
6033  assert(nlp->problem != NULL);
6034 
6035  SCIP_CALL( SCIPnlpiSetRealPar(nlp->solver, nlp->problem, type, dval) );
6036 
6037  return SCIP_OKAY;
6038 }
6039 
6040 /** gets string parameter of NLP */
6042  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
6043  SCIP_NLPPARAM type, /**< parameter number */
6044  const char** sval /**< pointer to store the parameter value */
6045  )
6046 {
6047  assert(nlp != NULL);
6048  assert(nlp->solver != NULL);
6049  assert(nlp->problem != NULL);
6050  assert(sval != NULL);
6051 
6052  SCIP_CALL( SCIPnlpiGetStringPar(nlp->solver, nlp->problem, type, sval) );
6053 
6054  return SCIP_OKAY;
6055 }
6056 
6057 /** sets string parameter of NLP */
6059  SCIP_NLP* nlp, /**< pointer to NLP datastructure */
6060  SCIP_NLPPARAM type, /**< parameter number */
6061  const char* sval /**< parameter value */
6062  )
6063 {
6064  assert(nlp != NULL);
6065  assert(nlp->solver != NULL);
6066  assert(nlp->problem != NULL);
6067 
6068  SCIP_CALL( SCIPnlpiSetStringPar(nlp->solver, nlp->problem, type, sval) );
6069 
6070  return SCIP_OKAY;
6071 }
6072 
6073 /*
6074  * NLP diving methods
6075  */
6076 
6077 /** signals start of diving */
6079  SCIP_NLP* nlp, /**< current NLP data */
6080  BMS_BLKMEM* blkmem, /**< block memory buffers */
6081  SCIP_SET* set /**< global SCIP settings */
6082  )
6083 {
6084  assert(nlp != NULL);
6085 
6086  if( nlp->indiving )
6087  {
6088  SCIPerrorMessage("NLP is already in diving mode\n");
6089  return SCIP_ERROR;
6090  }
6091 
6092  if( nlp->solver == NULL )
6093  {
6094  /* 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.
6095  * So we forbid diving of no solver is available. */
6096  SCIPerrorMessage("Cannot start diving if no NLP solver is available\n");
6097  return SCIP_ERROR;
6098  }
6099 
6100  SCIP_CALL( SCIPnlpFlush(nlp, blkmem, set) );
6101 
6102  nlp->indiving = TRUE;
6103 
6104  return SCIP_OKAY;
6105 }
6106 
6107 /** resets the bound and objective changes made during diving and disables diving mode */
6109  SCIP_NLP* nlp, /**< current NLP data */
6110  BMS_BLKMEM* blkmem, /**< block memory */
6111  SCIP_SET* set /**< global SCIP settings */
6112  )
6113 {
6114  int i;
6115  int* varidx;
6116  SCIP_Real* varlb;
6117  SCIP_Real* varub;
6118 
6119  assert(nlp != NULL);
6120  assert(set != NULL);
6121  assert(nlp->nvars == nlp->nvars_solver);
6122 
6123  if( !nlp->indiving )
6124  {
6125  SCIPerrorMessage("NLP not in diving mode, cannot end dive\n");
6126  return SCIP_ERROR;
6127  }
6128 
6129  assert(nlp->solver != NULL);
6130  assert(nlp->problem != NULL);
6131 
6132  /* reset variable bounds in NLPI problem to their current values */
6133  SCIP_CALL( SCIPsetAllocBufferArray(set, &varidx, nlp->nvars) );
6134  SCIP_CALL( SCIPsetAllocBufferArray(set, &varlb, nlp->nvars) );
6135  SCIP_CALL( SCIPsetAllocBufferArray(set, &varub, nlp->nvars) );
6136  for( i = 0; i < nlp->nvars; ++i )
6137  {
6138  varidx[i] = i;
6139  varlb[i] = SCIPvarGetLbLocal(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
6140  varub[i] = SCIPvarGetUbLocal(nlp->vars[nlp->varmap_nlpi2nlp[i]]);
6141  }
6142 
6143  SCIP_CALL( SCIPnlpiChgVarBounds(nlp->solver, nlp->problem, nlp->nvars, varidx, varlb, varub) );
6144 
6145  SCIPsetFreeBufferArray(set, &varidx);
6146  SCIPsetFreeBufferArray(set, &varlb);
6147  SCIPsetFreeBufferArray(set, &varub);
6148 
6149  /* clear diving objective, if one was used (i.e., if SCIPnlpChgVarObjDive had been called)
6150  * the objective in the NLPI will be reset in the next flush */
6151  if( nlp->divingobj != NULL )
6152  {
6153  SCIP_CALL( SCIPnlrowRelease(&nlp->divingobj, blkmem, set) );
6154  assert(nlp->divingobj == NULL);
6155  assert(nlp->objflushed == FALSE);
6156  }
6157 
6158  /* we do not have a valid solution anymore */
6162 
6163  nlp->indiving = FALSE;
6164 
6165  return SCIP_OKAY;
6166 }
6167 
6168 /** changes coefficient of variable in diving NLP */
6170  SCIP_NLP* nlp, /**< current NLP data */
6171  BMS_BLKMEM* blkmem, /**< block memory */
6172  SCIP_SET* set, /**< global SCIP settings */
6173  SCIP_STAT* stat, /**< problem statistics data */
6174  SCIP_VAR* var, /**< variable which coefficient to change */
6175  SCIP_Real coef /**< new linear coefficient of variable in objective */
6176  )
6177 {
6178  int pos;
6179  int objidx;
6180 
6181  assert(nlp != NULL);
6182  assert(var != NULL);
6183  assert(SCIPhashmapExists(nlp->varhash, var));
6184  assert(nlp->indiving);
6185  assert(nlp->solver != NULL);
6186  assert(nlp->problem != NULL);
6187 
6188  /* get position of variable in NLPI problem */
6189  pos = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, var);
6190  pos = nlp->varmap_nlp2nlpi[pos];
6191  assert(pos >= 0);
6192 
6193  /* set coefficient in NLPI problem objective */
6194  objidx = -1;
6195  SCIP_CALL( SCIPnlpiChgLinearCoefs(nlp->solver, nlp->problem, objidx, 1, &pos, &coef) );
6196 
6197  /* create an nlrow that holds the diving objective, if not done yet */
6198  if( nlp->divingobj == NULL )
6199  {
6200  SCIP_Real* coefs;
6201  int i;
6202 
6203  SCIP_CALL( SCIPsetAllocBufferArray(set, &coefs, nlp->nvars) );
6204  for( i = 0; i < nlp->nvars; ++i )
6205  coefs[i] = SCIPvarGetObj(nlp->vars[i]);
6206 
6207  SCIP_CALL( SCIPnlrowCreate(&nlp->divingobj, blkmem, set, "divingobj",
6208  0.0,
6209  nlp->nvars, nlp->vars, coefs,
6210  0, NULL, 0, NULL,
6211  NULL,
6212  -SCIPsetInfinity(set), SCIPsetInfinity(set)) );
6213 
6214  SCIPsetFreeBufferArray(set, &coefs);
6215  }
6216  assert(nlp->divingobj != NULL);
6217 
6218  /* modify coefficient in diving objective */
6219  SCIP_CALL( SCIPnlrowChgLinearCoef(nlp->divingobj, blkmem, set, stat, nlp, var, coef) );
6220 
6221  /* remember that we have to store objective after diving ended */
6222  nlp->objflushed = FALSE;
6223 
6224  return SCIP_OKAY;
6225 }
6226 
6227 /** changes bounds of variable in diving NLP */
6229  SCIP_NLP* nlp, /**< current NLP data */
6230  SCIP_VAR* var, /**< variable which coefficient to change */
6231  SCIP_Real lb, /**< new lower bound of variable */
6232  SCIP_Real ub /**< new upper bound of variable */
6233  )
6234 {
6235  int pos;
6236 
6237  assert(nlp != NULL);
6238  assert(var != NULL);
6239  assert(SCIPhashmapExists(nlp->varhash, var));
6240  assert(nlp->indiving);
6241  assert(nlp->solver != NULL);
6242  assert(nlp->problem != NULL);
6243 
6244  /* get position of variable in NLPI problem */
6245  pos = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, var);
6246  pos = nlp->varmap_nlp2nlpi[pos];
6247  assert(pos >= 0);
6248 
6249  /* set new bounds in NLPI */
6250  SCIP_CALL( SCIPnlpiChgVarBounds(nlp->solver, nlp->problem, 1, &pos, &lb, &ub) );
6251 
6252  return SCIP_OKAY;
6253 }
6254 
6255 /** changes bounds of a set of variables in diving NLP */
6257  SCIP_NLP* nlp, /**< current NLP data */
6258  SCIP_SET* set, /**< global SCIP settings */
6259  int nvars, /**< number of variables which bounds to change */
6260  SCIP_VAR** vars, /**< variables which bounds to change */
6261  SCIP_Real* lbs, /**< new lower bounds of variables */
6262  SCIP_Real* ubs /**< new upper bounds of variables */
6263  )
6264 {
6265  int i;
6266  int* poss;
6267 
6268  assert(nlp != NULL);
6269  assert(vars != NULL || nvars == 0);
6270  assert(nlp->indiving);
6271  assert(lbs != NULL || nvars == 0);
6272  assert(ubs != NULL || nvars == 0);
6273  assert(nlp->solver != NULL);
6274  assert(nlp->problem != NULL);
6275 
6276  if( nvars == 0 )
6277  return SCIP_OKAY;
6278 
6279  SCIP_CALL( SCIPsetAllocBufferArray(set, &poss, nvars) );
6280 
6281  for( i = 0; i < nvars; ++i )
6282  {
6283  assert(SCIPhashmapExists(nlp->varhash, vars[i])); /*lint !e613*/
6284 
6285  /* get position of variable in NLPI problem */
6286  poss[i] = (int) (size_t) SCIPhashmapGetImage(nlp->varhash, vars[i]); /*lint !e613*/
6287  poss[i] = nlp->varmap_nlp2nlpi[poss[i]];
6288  assert(poss[i] >= 0);
6289  }
6290 
6291  /* set new bounds in NLPI */
6292  SCIP_CALL( SCIPnlpiChgVarBounds(nlp->solver, nlp->problem, nvars, poss, lbs, ubs) );
6293 
6294  SCIPsetFreeBufferArray(set, &poss);
6295 
6296  return SCIP_OKAY;
6297 }
6298 
6299 /** returns whether the objective function has been changed during diving */
6301  SCIP_NLP* nlp /**< current NLP data */
6302  )
6303 {
6304  return nlp->divingobj != NULL;
6305 }
6306 
6307 /** solves diving NLP */
6309  SCIP_NLP* nlp, /**< current NLP data */
6310  BMS_BLKMEM* blkmem, /**< block memory buffers */
6311  SCIP_SET* set, /**< global SCIP settings */
6312  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6313  SCIP_STAT* stat /**< problem statistics */
6314  )
6315 {
6316  SCIP_CALL( nlpSolve(nlp, blkmem, set, messagehdlr, stat) );
6317 
6318  return SCIP_OKAY;
6319 }
6320 
SCIP_RETCODE SCIPnlpSetRealPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: nlp.c:6025
static SCIP_RETCODE nlrowRemoveFixedLinearCoefs(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:1457
SCIP_RETCODE SCIPnlpiDelConsSet(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int *dstats)
Definition: nlpi.c:377
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:491
int nfracvars
Definition: struct_nlp.h:164
static int nlrowSearchQuadElem(SCIP_NLROW *nlrow, int idx1, int idx2)
Definition: nlp.c:1113
SCIP_RETCODE SCIPnlpEnsureNlRowsSize(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:5363
SCIP_Real * fracvarssol
Definition: struct_nlp.h:162
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:102
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16861
static SCIP_RETCODE nlpEnsureVarsSolverSize(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:4093
SCIP_Longint validpsactivitydomchg
Definition: struct_nlp.h:97
int * varmap_nlpi2nlp
Definition: struct_nlp.h:130
void SCIPexprFreeDeep(BMS_BLKMEM *blkmem, SCIP_EXPR **expr)
Definition: expr.c:6061
void SCIPquadelemSort(SCIP_QUADELEM *quadelems, int nquadelems)
Definition: expr.c:9030
static SCIP_RETCODE nlrowExprtreeChanged(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:614
SCIP_RETCODE SCIPnlrowGetPseudoFeasibility(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *pseudofeasibility)
Definition: nlp.c:3043
SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
Definition: set.c:3936
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5180
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:406
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:422
internal methods for managing events
enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
Definition: type_nlpi.h:85
SCIP_EXPRTREE * exprtree
Definition: struct_nlp.h:89
SCIP_RETCODE SCIPnlrowPrint(SCIP_NLROW *nlrow, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlp.c:2279
SCIP_RETCODE SCIPnlrowChgRhs(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real rhs)
Definition: nlp.c:2802
SCIP_RETCODE SCIPnlpiGetStringPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, const char **sval)
Definition: nlpi.c:684
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
internal methods for storing primal CIP solutions
#define SCIP_EVENTTYPE_OBJCHANGED
Definition: type_event.h:52
SCIP_Real * SCIPnlpGetVarsLbDualsol(SCIP_NLP *nlp)
Definition: nlp.c:5858
SCIP_RETCODE SCIPexprtreeEvalInt(SCIP_EXPRTREE *tree, SCIP_Real infinity, SCIP_INTERVAL *varvals, SCIP_INTERVAL *val)
Definition: expr.c:8579
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13260
SCIP_RETCODE SCIPeventhdlrCreate(SCIP_EVENTHDLR **eventhdlr, 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:64
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:48
void SCIPexprtreePrint(SCIP_EXPRTREE *tree, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char **varnames, const char **paramnames)
Definition: expr.c:8596
static int nlrowSearchLinearCoef(SCIP_NLROW *nlrow, SCIP_VAR *var)
Definition: nlp.c:840
SCIP_NLPI * SCIPsetFindNlpi(SCIP_SET *set, const char *name)
Definition: set.c:4261
static SCIP_RETCODE nlpUpdateVarBounds(SCIP_NLP *nlp, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool tightened)
Definition: nlp.c:3628
int SCIPnlrowGetNQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3312
int linvarssize
Definition: struct_nlp.h:73
SCIP_NLROW * divingobj
Definition: struct_nlp.h:143
static SCIP_RETCODE nlrowAddQuadElement(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_QUADELEM elem)
Definition: nlp.c:1157
SCIP_RETCODE SCIPnlrowAddQuadElement(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_QUADELEM elem)
Definition: nlp.c:2597
void SCIPnlrowCapture(SCIP_NLROW *nlrow)
Definition: nlp.c:2334
static SCIP_RETCODE nlpSetupNlpiIndices(SCIP_NLP *nlp, SCIP_SET *set, SCIP_NLROW *nlrow, int **linidxs, SCIP_QUADELEM **quadelems, int **nlinidxs)
Definition: nlp.c:3978
SCIP_Bool SCIPnlpIsDiving(SCIP_NLP *nlp)
Definition: nlp.c:5918
SCIP_VAR ** linvars
Definition: struct_nlp.h:74
static SCIP_RETCODE nlrowQuadElemChanged(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_QUADELEM quadelem, SCIP_NLP *nlp)
Definition: nlp.c:541
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1788
SCIP_RETCODE SCIPnlrowRelease(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:2346
internal methods for clocks and timing issues
static SCIP_RETCODE nlrowChgQuadElemPos(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int pos, SCIP_Real coef)
Definition: nlp.c:1234
#define NULL
Definition: lpi_spx.cpp:130
SCIP_EVENTHDLR * SCIPsetFindEventhdlr(SCIP_SET *set, const char *name)
Definition: set.c:3959
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition: nlp.c:3225
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
static SCIP_RETCODE nlpFlushNlRowAdditions(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:4336
#define EVENTHDLR_NAME
Definition: nlp.c:59
SCIP_VAR ** fracvars
Definition: struct_nlp.h:161
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:1808
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:940
int nnlrows
Definition: struct_nlp.h:133
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
internal methods for NLPI solver interfaces
SCIP_RETCODE SCIPnlrowEnsureQuadVarsSize(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:2514
SCIP_Real * SCIPexprtreeGetParamVals(SCIP_EXPRTREE *tree)
Definition: expr.c:8472
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5042
SCIP_RETCODE SCIPnlrowCreate(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadvars, SCIP_VAR **quadvars, int nquadelems, SCIP_QUADELEM *quadelems, SCIP_EXPRTREE *exprtree, SCIP_Real lhs, SCIP_Real rhs)
Definition: nlp.c:1995
SCIP_HASHMAP * quadvarshash
Definition: struct_nlp.h:82
SCIP_NLPSOLSTAT solstat
Definition: struct_nlp.h:151
SCIP_RETCODE SCIPnlpGetStatistics(SCIP_NLP *nlp, SCIP_NLPSTATISTICS *statistics)
Definition: nlp.c:5948
SCIP_Real * initialguess
Definition: struct_nlp.h:147
data definitions for expressions and expression trees
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:17537
SCIP_NLPIPROBLEM * problem
Definition: struct_nlp.h:111
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
static SCIP_RETCODE nlpFlushVarDeletions(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:4242
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPnlpSolveDive(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat)
Definition: nlp.c:6308
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
SCIP_RETCODE SCIPnlpGetVarsNonlinearity(SCIP_NLP *nlp, int *nlcount)
Definition: nlp.c:5761
SCIP_RETCODE SCIPnlpiFreeProblem(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **problem)
Definition: nlpi.c:224
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
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:1950
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:111
int SCIPexprtreeFindVar(SCIP_EXPRTREE *tree, SCIP_VAR *var)
Definition: nlp.c:205
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5292
SCIP_Real pseudoactivity
Definition: struct_nlp.h:96
static SCIP_RETCODE nlpCalcFracVars(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: nlp.c:4786
#define TRUE
Definition: def.h:55
int nvars_solver
Definition: struct_nlp.h:127
SCIP_RETCODE SCIPnlrowEnsureQuadElementsSize(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:2573
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPnlpCreate(SCIP_NLP **nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, int nvars_estimate)
Definition: nlp.c:5013
int nnlrows_solver
Definition: struct_nlp.h:137
SCIP_VAR ** quadvars
Definition: struct_nlp.h:81
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_Real dualsol
Definition: struct_nlp.h:103
SCIP_Longint nnlps
Definition: struct_stat.h:162
SCIP_RETCODE SCIPnlpChgVarsBoundsDive(SCIP_NLP *nlp, SCIP_SET *set, int nvars, SCIP_VAR **vars, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: nlp.c:6256
SCIP_RETCODE SCIPexprtreeCopy(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **targettree, SCIP_EXPRTREE *sourcetree)
Definition: expr.c:8652
SCIP_RETCODE SCIPnlpiSetStringPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, const char *sval)
Definition: nlpi.c:701
datastructures for NLP management
#define EVENTHDLR_DESC
Definition: nlp.c:60
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4766
SCIP_RETCODE SCIPnlpGetPseudoObjval(SCIP_NLP *nlp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *pseudoobjval)
Definition: nlp.c:5548
void SCIPexprReindexVars(SCIP_EXPR *expr, int *newindices)
Definition: expr.c:8029
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
unsigned int * used
Definition: memory.c:2419
SCIP_NLPTERMSTAT SCIPnlpGetTermstat(SCIP_NLP *nlp)
Definition: nlp.c:5938
int quadelemssize
Definition: struct_nlp.h:84
SCIP_RETCODE SCIPnlrowChgExprtreeParams(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real *paramvals)
Definition: nlp.c:2740
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPnlpReset(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: nlp.c:5193
static SCIP_RETCODE nlrowConstantChanged(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:776
SCIP_RETCODE SCIPnlpiGetSolution(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_Real **primalvalues, SCIP_Real **consdualvalues, SCIP_Real **varlbdualvalues, SCIP_Real **varubdualvalues)
Definition: nlpi.c:535
int nunflushedvaradd
Definition: struct_nlp.h:114
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
enum SCIP_NlpParam SCIP_NLPPARAM
Definition: type_nlpi.h:56
SCIP_QUADELEM * quadelems
Definition: struct_nlp.h:85
SCIP_RETCODE SCIPnlrowEnsureLinearSize(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:2370
SCIP_RETCODE SCIPnlpiGetRealPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, SCIP_Real *dval)
Definition: nlpi.c:650
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
SCIP_NLPI * solver
Definition: struct_nlp.h:110
char * name
Definition: struct_nlp.h:92
SCIP_RETCODE SCIPnlpGetIntPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, int *ival)
Definition: nlp.c:5975
SCIP_Bool SCIPquadelemSortedFind(SCIP_QUADELEM *quadelems, int idx1, int idx2, int nquadelems, int *pos)
Definition: expr.c:9055
void SCIPexprtreeSetParamVal(SCIP_EXPRTREE *tree, int paramidx, SCIP_Real paramval)
Definition: expr.c:8482
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
SCIP_CLOCK * nlpsoltime
Definition: struct_stat.h:130
SCIP_RETCODE SCIPnlrowChgQuadElem(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_QUADELEM elem)
Definition: nlp.c:2646
SCIP_Real minactivity
Definition: struct_nlp.h:98
SCIP_EXPR * root
Definition: struct_expr.h:58
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11206
SCIP_Bool SCIPsetIsFeasFracIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5732
int fracvarssize
Definition: struct_nlp.h:166
static void nlrowSortQuadElem(SCIP_NLROW *nlrow)
Definition: nlp.c:1094
SCIP_RETCODE SCIPnlrowChgLhs(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real lhs)
Definition: nlp.c:2782
SCIP_Longint validfracvars
Definition: struct_nlp.h:167
SCIP_RETCODE SCIPnlrowGetNLPFeasibility(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real *feasibility)
Definition: nlp.c:2942
SCIP_RETCODE SCIPnlpDelNlRow(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_NLROW *nlrow)
Definition: nlp.c:5443
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1245
public methods for expressions, expression trees, expression graphs, and related stuff ...
int sizenlrows
Definition: struct_nlp.h:134
SCIP_RETCODE SCIPnlpiChgConsSides(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nconss, const int *indices, const SCIP_Real *lhss, const SCIP_Real *rhss)
Definition: nlpi.c:343
SCIP_Longint validactivitybdsdomchg
Definition: struct_nlp.h:100
int quadvarssize
Definition: struct_nlp.h:80
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
static SCIP_RETCODE nlrowChgLinearCoefPos(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int pos, SCIP_Real coef)
Definition: nlp.c:1038
SCIP_RETCODE SCIPnlrowAddQuadVar(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var)
Definition: nlp.c:2538
SCIP_Real * varubdualvals
Definition: struct_nlp.h:154
static SCIP_RETCODE nlpSolve(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat)
Definition: nlp.c:4639
SCIP_Real rhs
Definition: struct_nlp.h:66
SCIP_RETCODE SCIPnlpStartDive(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:6078
SCIP_Real lhs
Definition: struct_nlp.h:65
static SCIP_RETCODE nlpFlushVarAdditions(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:4489
SCIP_Bool quadelemssorted
Definition: struct_nlp.h:86
SCIP_Bool SCIPnlpHasContinuousNonlinearity(SCIP_NLP *nlp)
Definition: nlp.c:5820
SCIP_Real coef
Definition: type_expr.h:102
static SCIP_RETCODE nlrowRemoveFixedExprtreeVars(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:1917
SCIP_Bool SCIPnlpIsDivingObjChanged(SCIP_NLP *nlp)
Definition: nlp.c:6300
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16585
SCIP_Bool objflushed
Definition: struct_nlp.h:142
static SCIP_RETCODE nlrowRemoveFixedQuadVars(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:1483
static SCIP_RETCODE nlpMoveVar(SCIP_NLP *nlp, int oldpos, int newpos)
Definition: nlp.c:3827
SCIP_RETCODE SCIPnlpAddVars(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int nvars, SCIP_VAR **vars)
Definition: nlp.c:5302
void SCIPnlrowGetQuadData(SCIP_NLROW *nlrow, int *nquadvars, SCIP_VAR ***quadvars, int *nquadelems, SCIP_QUADELEM **quadelems)
Definition: nlp.c:3332
SCIP_Real maxactivity
Definition: struct_nlp.h:99
SCIP_Real * fracvarsfrac
Definition: struct_nlp.h:163
static SCIP_RETCODE nlrowDelQuadElemPos(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int pos)
Definition: nlp.c:1202
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:416
SCIP_NLPTERMSTAT SCIPnlpiGetTermstat(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:521
SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
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:1715
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_RETCODE SCIPnlpiDelVarSet(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int *dstats)
Definition: nlpi.c:361
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
interval arithmetics for provable bounds
SCIP_HASHMAP * varhash
Definition: struct_nlp.h:125
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:2476
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
int nlpiindex
Definition: struct_nlp.h:102
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
SCIP_RETCODE SCIPnlpGetRealPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, SCIP_Real *dval)
Definition: nlp.c:6008
SCIP_EVENTHDLR * eventhdlr
Definition: struct_nlp.h:157
SCIP_RETCODE SCIPnlpiAddVars(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nvars, const SCIP_Real *lbs, const SCIP_Real *ubs, const char **varnames)
Definition: nlpi.c:250
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2752
SCIP_RETCODE SCIPnlpiChgLinearCoefs(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, const int idx, int nvals, const int *varidxs, const SCIP_Real *vals)
Definition: nlpi.c:393
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_Real * varlbdualvals
Definition: struct_nlp.h:153
SCIP_RETCODE SCIPnlrowGetPseudoActivity(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *pseudoactivity)
Definition: nlp.c:3017
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
SCIP_RETCODE SCIPnlrowDelLinearCoef(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_VAR *var)
Definition: nlp.c:2443
SCIP_RETCODE SCIPnlpiSetIntPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, int ival)
Definition: nlpi.c:633
int SCIPnlpGetNNlRows(SCIP_NLP *nlp)
Definition: nlp.c:5888
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:4577
SCIP_Real SCIPnlpGetObjval(SCIP_NLP *nlp)
Definition: nlp.c:5538
SCIP_RETCODE SCIPnlpiCreateProblem(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **problem, const char *name)
Definition: nlpi.c:211
static void nlpMoveNlrow(SCIP_NLP *nlp, int oldpos, int newpos)
Definition: nlp.c:3555
SCIP_NLROW ** SCIPnlpGetNlRows(SCIP_NLP *nlp)
Definition: nlp.c:5878
SCIP_RETCODE SCIPnlrowGetSolFeasibility(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Real *feasibility)
Definition: nlp.c:3148
#define BMSallocMemory(ptr)
Definition: memory.h:74
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
SCIP_RETCODE SCIPnlrowDelQuadElement(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int idx1, int idx2)
Definition: nlp.c:2612
internal methods for NLP management
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
SCIP_RETCODE SCIPnlpSetIntPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, int ival)
Definition: nlp.c:5992
static SCIP_RETCODE nlpRowChanged(SCIP_NLP *nlp, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLROW *nlrow)
Definition: nlp.c:3433
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:411
SCIP_Bool SCIPsetIsRelLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6101
SCIP_RETCODE SCIPnlpiChgQuadCoefs(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int idx, int nquadelems, const SCIP_QUADELEM *quadelems)
Definition: nlpi.c:411
SCIP_RETCODE SCIPnlpEnsureVarsSize(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:5242
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8452
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16837
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:3403
static SCIP_RETCODE nlpEnsureNlRowsSolverSize(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: nlp.c:4121
internal methods for global SCIP settings
SCIP_VAR ** vars
Definition: struct_nlp.h:124
SCIP main data structure.
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5666
#define BMSfreeMemory(ptr)
Definition: memory.h:100
static SCIP_RETCODE nlpDelNlRowPos(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int pos)
Definition: nlp.c:3575
static SCIP_RETCODE nlrowRemoveFixedLinearCoefPos(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int pos)
Definition: nlp.c:1357
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17229
SCIP_RETCODE SCIPnlpSetInitialGuess(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_Real *initguess)
Definition: nlp.c:5657
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
SCIP_RETCODE SCIPnlrowCreateFromRow(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_ROW *row)
Definition: nlp.c:2177
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5202
SCIP_RETCODE SCIPnlpChgVarObjDive(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_Real coef)
Definition: nlp.c:6169
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2873
SCIP_RETCODE SCIPnlrowChgConstant(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real constant)
Definition: nlp.c:2762
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:97
SCIP_RETCODE SCIPnlpChgVarBoundsDive(SCIP_NLP *nlp, SCIP_VAR *var, SCIP_Real lb, SCIP_Real ub)
Definition: nlp.c:6228
SCIP_NLPTERMSTAT termstat
Definition: struct_nlp.h:152
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5622
SCIP_RETCODE SCIPnlrowChgExprtreeParam(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int paramidx, SCIP_Real paramval)
Definition: nlp.c:2717
static SCIP_RETCODE nlpAddVars(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, int nvars, SCIP_VAR **vars)
Definition: nlp.c:3748
SCIP_RETCODE SCIPexprtreeRemoveFixedVars(SCIP_EXPRTREE *tree, SCIP_SET *set, SCIP_Bool *changed, int *varpos, int *newvarsstart)
Definition: nlp.c:223
static SCIP_RETCODE nlrowSideChanged(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:738
internal methods for problem variables
SCIP_RETCODE SCIPnlpWrite(SCIP_NLP *nlp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *fname)
Definition: nlp.c:5690
static SCIP_DECL_EVENTEXEC(eventExecNlp)
Definition: nlp.c:4932
#define SCIP_UNKNOWN
Definition: def.h:148
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3373
public data structures and miscellaneous methods
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
SCIP_RETCODE SCIPnlpEndDive(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:6108
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3235
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17444
SCIP_RETCODE SCIPnlpiSetRealPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: nlpi.c:668
#define SCIP_Bool
Definition: def.h:53
void ** vars
Definition: struct_expr.h:60
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3245
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2740
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:885
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:408
static void nlrowSortLinear(SCIP_NLROW *nlrow)
Definition: nlp.c:822
SCIP_RETCODE SCIPnlpiSetObjective(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nlins, const int *lininds, const SCIP_Real *linvals, int nquadelems, const SCIP_QUADELEM *quadelems, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree, const SCIP_Real constant)
Definition: nlpi.c:300
int nquadvars
Definition: struct_nlp.h:79
SCIP_RETCODE SCIPnlpiSetInitialGuess(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_Real *primalvalues, SCIP_Real *consdualvalues, SCIP_Real *varlbdualvalues, SCIP_Real *varubdualvalues)
Definition: nlpi.c:477
SCIP_Bool SCIPnlpHasCurrentNodeNLP(SCIP_NLP *nlp)
Definition: nlp.c:5234
SCIP_NLPSOLSTAT SCIPnlpGetSolstat(SCIP_NLP *nlp)
Definition: nlp.c:5928
char * name
Definition: struct_nlp.h:170
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17143
BMS_BLKMEM * blkmem
Definition: struct_expr.h:57
SCIP_RETCODE SCIPnlpAddNlRow(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLROW *nlrow)
Definition: nlp.c:5391
static SCIP_RETCODE nlpDelVarPos(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos)
Definition: nlp.c:3860
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:3255
SCIP_RETCODE SCIPnlpFlush(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:5474
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
#define MAX(x, y)
Definition: tclique_def.h:75
void SCIPsetSortNlpis(SCIP_SET *set)
Definition: set.c:4281
SCIP_RETCODE SCIPnlpiGetIntPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, int *ival)
Definition: nlpi.c:616
int SCIPnlrowGetNQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3265
public methods for LP management
SCIP_RETCODE SCIPnlpiChgVarBounds(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nvars, const int *indices, const SCIP_Real *lbs, const SCIP_Real *ubs)
Definition: nlpi.c:325
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5853
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:419
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8692
SCIP_RETCODE SCIPnlrowGetNLPActivity(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_Real *activity)
Definition: nlp.c:2915
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16825
SCIP_RETCODE SCIPnlrowChgExprtree(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_EXPRTREE *exprtree)
Definition: nlp.c:2678
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPnlrowRemoveFixedVars(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:2822
SCIP_RETCODE SCIPnlpiSolve(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:495
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3363
int SCIPnlpGetNVars(SCIP_NLP *nlp)
Definition: nlp.c:5751
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16849
SCIP_NLROW ** nlrows
Definition: struct_nlp.h:135
SCIP_RETCODE SCIPnlrowGetActivityBounds(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *minactivity, SCIP_Real *maxactivity)
Definition: nlp.c:3169
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:5577
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5600
int nunflushedvardel
Definition: struct_nlp.h:115
SCIP_Bool haveinitguess
Definition: struct_nlp.h:146
SCIP_RETCODE SCIPnlrowGetSolActivity(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Real *activity)
Definition: nlp.c:3063
SCIP_Real SCIPsetFeasFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5780
int nunflushednlrowadd
Definition: struct_nlp.h:116
SCIP_RETCODE SCIPnlpSolve(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat)
Definition: nlp.c:5511
static SCIP_RETCODE nlpFlushNlRowDeletions(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: nlp.c:4149
SCIP_RETCODE SCIPnlpDelVar(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_VAR *var)
Definition: nlp.c:5327
int SCIPnlrowGetNLPPos(SCIP_NLROW *nlrow)
Definition: nlp.c:3393
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
int nvars
Definition: struct_nlp.h:122
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2177
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:2395
static SCIP_RETCODE nlrowDelLinearCoefPos(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, int pos)
Definition: nlp.c:1009
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3275
SCIP_NLPIPROBLEM * SCIPnlpGetNLPIProblem(SCIP_NLP *nlp)
Definition: nlp.c:5908
static SCIP_RETCODE nlrowSetupQuadVarsHash(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem)
Definition: nlp.c:1068
int sizevars
Definition: struct_nlp.h:123
#define REALABS(x)
Definition: def.h:151
SCIP_Longint domchgcount
Definition: struct_stat.h:85
SCIP_Bool indiving
Definition: struct_nlp.h:119
SCIP_RETCODE SCIPnlrowFree(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem)
Definition: nlp.c:2242
int * varmap_nlp2nlpi
Definition: struct_nlp.h:129
SCIP_RETCODE SCIPnlpFree(SCIP_NLP **nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: nlp.c:5134
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3353
SCIP_Real SCIPnlrowGetDualsol(SCIP_NLROW *nlrow)
Definition: nlp.c:3415
SCIP_RETCODE SCIPnlpiChgExprtree(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int idxcons, const int *exprvaridxs, SCIP_EXPRTREE *exprtree)
Definition: nlpi.c:428
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
static void nlrowMoveQuadElement(SCIP_NLROW *nlrow, int oldpos, int newpos)
Definition: nlp.c:1136
SCIP_RETCODE SCIPnlrowRecalcNLPActivity(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp)
Definition: nlp.c:2838
public methods for message output
static SCIP_RETCODE nlpUpdateObjCoef(SCIP_NLP *nlp, SCIP_VAR *var)
Definition: nlp.c:3687
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:602
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2137
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:3383
#define SCIP_Real
Definition: def.h:127
internal methods for problem statistics
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:3946
int nunflushednlrowdel
Definition: struct_nlp.h:117
static SCIP_RETCODE nlrowExprtreeParamChanged(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, int paramidx, SCIP_NLP *nlp)
Definition: nlp.c:681
#define MIN(x, y)
Definition: memory.c:67
void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
static SCIP_RETCODE nlrowCalcActivityBounds(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat)
Definition: nlp.c:1265
SCIP_Real activity
Definition: struct_nlp.h:94
SCIP_RETCODE SCIPnlpiAddConstraints(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, const int *nquadelems, SCIP_QUADELEM *const *quadelems, int *const *exprvaridxs, SCIP_EXPRTREE *const *exprtrees, const char **names)
Definition: nlpi.c:268
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1795
#define SCIP_INVALID
Definition: def.h:147
SCIP_RETCODE SCIPnlpAddNlRows(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int nnlrows, SCIP_NLROW **nlrows)
Definition: nlp.c:5415
SCIP_NLPI * SCIPnlpGetNLPI(SCIP_NLP *nlp)
Definition: nlp.c:5898
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPexprtreeSubstituteVars(SCIP_EXPRTREE *tree, SCIP_EXPR **substexprs)
Definition: expr.c:8866
SCIP_RETCODE SCIPnlpSetStringPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, const char *sval)
Definition: nlp.c:6058
SCIP_RETCODE SCIPexprtreePrintWithNames(SCIP_EXPRTREE *tree, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlp.c:172
int nlinvars
Definition: struct_nlp.h:72
SCIP_VAR ** SCIPnlpGetVars(SCIP_NLP *nlp)
Definition: nlp.c:5741
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
int nquadelems
Definition: struct_nlp.h:83
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5644
int SCIPexprtreeGetNParams(SCIP_EXPRTREE *tree)
Definition: expr.c:8462
int sizevars_solver
Definition: struct_nlp.h:128
SCIP_RETCODE SCIPnlpGetStringPar(SCIP_NLP *nlp, SCIP_NLPPARAM type, const char **sval)
Definition: nlp.c:6041
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
int nlpindex
Definition: struct_nlp.h:101
static SCIP_RETCODE nlrowAddToLinearCoef(SCIP_NLROW *nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_NLP *nlp, SCIP_VAR *var, SCIP_Real coef, SCIP_Bool removefixed)
Definition: nlp.c:932
static SCIP_RETCODE nlpAddNlRows(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int nnlrows, SCIP_NLROW **nlrows)
Definition: nlp.c:3468
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:78
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:17564
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
SCIP_Real * SCIPnlpGetVarsUbDualsol(SCIP_NLP *nlp)
Definition: nlp.c:5868
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPnlpiChgNonlinCoef(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int considx, int paramidx, SCIP_Real value)
Definition: nlpi.c:445
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_RETCODE SCIPnlpInclude(SCIP_SET *set, BMS_BLKMEM *blkmem)
Definition: nlp.c:4988
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11906
SCIP_RETCODE SCIPnlpRemoveRedundantNlRows(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: nlp.c:5611
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_RETCODE SCIPexprCreateLinear(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:6380
int * nlrowmap_nlpi2nlp
Definition: struct_nlp.h:139
SCIP_RETCODE SCIPnlpiGetStatistics(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:553
#define SCIP_ALLOC(x)
Definition: def.h:277
SCIP_Real constant
Definition: struct_nlp.h:69
int SCIPnlrowSearchQuadVar(SCIP_NLROW *nlrow, SCIP_VAR *var)
Definition: nlp.c:3285
SCIP_RETCODE SCIPnlrowRecalcPseudoActivity(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat)
Definition: nlp.c:2962
SCIP_Real primalsolobjval
Definition: struct_nlp.h:150
SCIP_RETCODE SCIPexprtreeSetParams(SCIP_EXPRTREE *tree, int nparams, SCIP_Real *paramvals)
Definition: expr.c:8716
static void nlrowMoveLinearCoef(SCIP_NLROW *nlrow, int oldpos, int newpos)
Definition: nlp.c:862
double * lincoefs
Definition: struct_nlp.h:75
SCIP_RETCODE SCIPnlrowIsRedundant(SCIP_NLROW *nlrow, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *isredundant)
Definition: nlp.c:3200
SCIP_RETCODE SCIPnlpAddVar(SCIP_NLP *nlp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var)
Definition: nlp.c:5276
#define SCIP_EVENTTYPE_VARADDED
Definition: type_event.h:46
SCIP_Bool SCIPnlpHasSolution(SCIP_NLP *nlp)
Definition: nlp.c:5965
datastructures for global SCIP settings
SCIP_Bool linvarssorted
Definition: struct_nlp.h:76
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:412
SCIP_RETCODE SCIPexprtreeAddVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:143
int npriofracvars
Definition: struct_nlp.h:165
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
SCIP_RETCODE SCIPnlrowCreateCopy(SCIP_NLROW **nlrow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_NLROW *sourcenlrow)
Definition: nlp.c:2142
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:47
SCIP_Longint validactivitynlp
Definition: struct_nlp.h:95
SCIP_NLPSOLSTAT SCIPnlpiGetSolstat(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:509
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5710
SCIP_RETCODE SCIPexprtreeEval(SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Real *val)
Definition: expr.c:8563
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3322
int sizenlrows_solver
Definition: struct_nlp.h:138
void SCIPintervalQuad(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_Real sqrcoeff, SCIP_INTERVAL lincoeff, SCIP_INTERVAL xrng)