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