Scippy

SCIP

Solving Constraint Integer Programs

nlpioracle.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file nlpioracle.c
17  * @brief implementation of NLPI oracle interface
18  * @author Stefan Vigerske
19  *
20  * @todo jacobi evaluation should be sparse
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include "scip/pub_message.h"
26 #include "scip/pub_misc.h"
27 #include "nlpi/nlpioracle.h"
28 #include "nlpi/pub_expr.h"
29 #include "nlpi/exprinterpret.h"
30 
31 #include <string.h> /* for strlen */
32 
33 /**@name NLPI Oracle data structures */
34 /**@{ */
35 
37 {
38  SCIP_Real lhs; /**< left hand side (for constraint) or constant (for objective) */
39  SCIP_Real rhs; /**< right hand side (for constraint) or constant (for objective) */
40 
41  int linsize; /**< length of linidxs and lincoefs arrays */
42  int nlinidxs; /**< number of linear variable indices and coefficients */
43  int* linidxs; /**< variable indices in linear part, or NULL if none */
44  SCIP_Real* lincoefs; /**< variable coefficients in linear part, of NULL if none */
45 
46  int quadsize; /**< length of quadelems array */
47  int nquadelems; /**< number of quadratic elements */
48  SCIP_QUADELEM* quadelems; /**< quadratic elements, or NULL if none */
49 
50  int* exprvaridxs; /**< indices of variables in expression tree, or NULL if no exprtree */
51  SCIP_EXPRTREE* exprtree; /**< expression tree for nonlinear part, or NULL if none */
52 
53  char* name; /**< name of constraint */
54 };
56 
58 {
59  BMS_BLKMEM* blkmem; /**< block memory */
60  SCIP_Real infinity; /**< value for infinity */
61  char* name; /**< name of problem */
62 
63  int varssize; /**< length of variables related arrays */
64  int nvars; /**< number of variables */
65  SCIP_Real* varlbs; /**< array with variable lower bounds */
66  SCIP_Real* varubs; /**< array with variable upper bounds */
67  char** varnames; /**< array with variable names */
68  int* vardegrees; /**< array with maximal degree of variable over objective and all constraints */
69  SCIP_Bool vardegreesuptodate; /**< whether the variable degrees are up to date */
70 
71  int consssize; /**< length of constraints related arrays */
72  int nconss; /**< number of constraints */
73  SCIP_NLPIORACLECONS** conss; /**< constraints, or NULL if none */
74 
75  SCIP_NLPIORACLECONS* objective; /**< objective */
76 
77  int* jacoffsets; /**< rowwise jacobi sparsity pattern: constraint offsets in jaccols */
78  int* jaccols; /**< rowwise jacobi sparsity pattern: indices of variables appearing in constraints */
79 
80  int* heslagoffsets; /**< rowwise sparsity pattern of hessian matrix of Lagrangian: row offsets in heslagcol */
81  int* heslagcols; /**< rowwise sparsity pattern of hessian matrix of Lagrangian: column indices; sorted for each row */
82 
83 
84  SCIP_EXPRINT* exprinterpreter; /**< interpreter for expression trees: evaluation and derivatives */
85 };
86 
87 /**@} */
88 
89 /**@name Local functions */
90 /**@{ */
91 
92 /** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
93 static
95  int num /**< minimum number of entries to store */
96  )
97 {
98  int size;
99 
100  /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
101  size = 4;
102  while( size < num )
103  size = (int)(1.2 * size + 4);
104 
105  return size;
106 }
107 
108 /** ensures that variables related arrays in oracle have at least a given length */
109 static
111  SCIP_NLPIORACLE* oracle, /**< NLPIORACLE data structure */
112  int minsize /**< minimal required size */
113  )
114 {
115  assert(oracle != NULL);
116 
117  if( minsize > oracle->varssize )
118  {
119  int newsize;
120 
121  newsize = calcGrowSize(minsize);
122  assert(newsize >= minsize);
123 
124  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varlbs, oracle->varssize, newsize) );
125  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varubs, oracle->varssize, newsize) );
126  if( oracle->varnames != NULL )
127  {
128  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varnames, oracle->varssize, newsize) );
129  }
130  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->vardegrees, oracle->varssize, newsize) );
131 
132  oracle->varssize = newsize;
133  }
134  assert(oracle->varssize >= minsize);
135 
136  return SCIP_OKAY;
137 }
138 
139 /** ensures that constraints array in oracle has at least a given length */
140 static
142  SCIP_NLPIORACLE* oracle, /**< NLPIORACLE data structure */
143  int minsize /**< minimal required size */
144  )
145 {
146  assert(oracle != NULL);
147 
148  if( minsize > oracle->consssize )
149  {
150  int newsize;
151 
152  newsize = calcGrowSize(minsize);
153  assert(newsize >= minsize);
154 
155  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->conss, oracle->consssize, newsize) );
156  oracle->consssize = newsize;
157  }
158  assert(oracle->consssize >= minsize);
159 
160  return SCIP_OKAY;
161 }
162 
163 /** ensures that arrays for linear part in a oracle constraints have at least a given length */
164 static
166  BMS_BLKMEM* blkmem, /**< block memory */
167  SCIP_NLPIORACLECONS* cons, /**< oracle constraint */
168  int minsize /**< minimal required size */
169  )
170 {
171  assert(blkmem != NULL);
172  assert(cons != NULL);
173 
174  if( minsize > cons->linsize )
175  {
176  int newsize;
177 
178  newsize = calcGrowSize(minsize);
179  assert(newsize >= minsize);
180 
181  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &cons->linidxs, cons->linsize, newsize) );
182  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &cons->lincoefs, cons->linsize, newsize) );
183  cons->linsize = newsize;
184  }
185  assert(cons->linsize >= minsize);
186 
187  return SCIP_OKAY;
188 }
189 
190 /** ensures that arrays for quadratic part in a oracle constraints have at least a given length */
191 static
193  BMS_BLKMEM* blkmem, /**< block memory */
194  SCIP_NLPIORACLECONS* cons, /**< oracle constraint */
195  int minsize /**< minimal required size */
196  )
197 {
198  assert(blkmem != NULL);
199  assert(cons != NULL);
200 
201  if( minsize > cons->quadsize )
202  {
203  int newsize;
204 
205  newsize = calcGrowSize(minsize);
206  assert(newsize >= minsize);
207 
208  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &cons->quadelems, cons->quadsize, newsize) );
209  cons->quadsize = newsize;
210  }
211  assert(cons->quadsize >= minsize);
212 
213  return SCIP_OKAY;
214 }
215 
216 /** ensures that a given array of integers has at least a given length */
217 static
219  BMS_BLKMEM* blkmem, /**< block memory */
220  int** intarray, /**< array of integers */
221  int* len, /**< length of array (modified if reallocated) */
222  int minsize /**< minimal required array length */
223  )
224 {
225  assert(blkmem != NULL);
226  assert(intarray != NULL);
227  assert(len != NULL);
228 
229  if( minsize > *len )
230  {
231  int newsize;
232 
233  newsize = calcGrowSize(minsize);
234  assert(newsize >= minsize);
235 
236  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, intarray, *len, newsize) );
237  *len = newsize;
238  }
239  assert(*len >= minsize);
240 
241  return SCIP_OKAY;
242 }
243 
244 /** Invalidates the sparsity pattern of the Jacobian.
245  * Should be called when constraints are added or deleted.
246  */
247 static
249  SCIP_NLPIORACLE* oracle /**< pointer to store NLPIORACLE data structure */
250  )
251 {
252  assert(oracle != NULL);
253 
254  SCIPdebugMessage("%p invalidate jacobian sparsity\n", (void*)oracle);
255 
256  if( oracle->jacoffsets == NULL )
257  { /* nothing to do */
258  assert(oracle->jaccols == NULL);
259  return;
260  }
261 
262  assert(oracle->jaccols != NULL);
263  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->jaccols, oracle->jacoffsets[oracle->nconss]);
264  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->jacoffsets, oracle->nconss + 1);
265 }
266 
267 /** Invalidates the sparsity pattern of the Hessian of the Lagragian.
268  * Should be called when the objective is set or constraints are added or deleted.
269  */
270 static
272  SCIP_NLPIORACLE* oracle /**< pointer to store NLPIORACLE data structure */
273  )
274 {
275  assert(oracle != NULL);
276 
277  SCIPdebugMessage("%p invalidate hessian lag sparsity\n", (void*)oracle);
278 
279  if( oracle->heslagoffsets == NULL )
280  { /* nothing to do */
281  assert(oracle->heslagcols == NULL);
282  return;
283  }
284 
285  assert(oracle->heslagcols != NULL);
286  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->heslagcols, oracle->heslagoffsets[oracle->nvars]);
287  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->heslagoffsets, oracle->nvars + 1);
288 }
289 
290 /** sorts a linear term, merges duplicate entries and removes entries with coefficient 0.0 */
291 static
293  int* nidxs, /**< number of variables */
294  int* idxs, /**< indices of variables */
295  SCIP_Real* coefs /**< coefficients of variables */
296  )
297 {
298  int offset;
299  int j;
300 
301  assert(nidxs != NULL);
302  assert(idxs != NULL || *nidxs == 0);
303  assert(coefs != NULL || *nidxs == 0);
304 
305  if( *nidxs == 0 )
306  return;
307 
308  SCIPsortIntReal(idxs, coefs, *nidxs);
309 
310  offset = 0;
311  j = 0;
312  while( j+offset < *nidxs )
313  {
314  assert(idxs[j] >= 0); /*lint !e613*/
315 
316  /* move j+offset to j, if different */
317  if( offset > 0 )
318  {
319  idxs[j] = idxs[j+offset]; /*lint !e613*/
320  coefs[j] = coefs[j+offset]; /*lint !e613*/
321  }
322 
323  /* add up coefs for j+offset+1... as long as they have the same index */
324  while( j+offset+1 < *nidxs && idxs[j] == idxs[j+offset+1] ) /*lint !e613*/
325  {
326  coefs[j] += coefs[j+offset+1]; /*lint !e613*/
327  ++offset;
328  }
329 
330  /* if j'th element is 0, increase offset, otherwise increase j */
331  if( coefs[j] == 0.0 ) /*lint !e613*/
332  ++offset;
333  else
334  ++j;
335  }
336  *nidxs -= offset;
337 }
338 
339 /** creates a NLPI constraint from given constraint data */
340 static
342  BMS_BLKMEM* blkmem, /**< block memory */
343  SCIP_NLPIORACLECONS** cons, /**< buffer where to store pointer to constraint */
344  int nlinidxs, /**< length of linear part */
345  const int* linidxs, /**< indices of linear part, or NULL if nlinidxs == 0 */
346  const SCIP_Real* lincoefs, /**< coefficients of linear part, or NULL if nlinidxs == 0 */
347  int nquadelems, /**< lenght of quadratic part */
348  const SCIP_QUADELEM* quadelems, /**< quadratic elements, or NULL if nquadelems == 0 */
349  const int* exprvaridxs, /**< indicies of variables in expression tree, or NULL if exprtree == NULL */
350  const SCIP_EXPRTREE* exprtree, /**< expression tree, or NULL */
351  SCIP_Real lhs, /**< left-hand-side of constraint */
352  SCIP_Real rhs, /**< right-hand-side of constraint */
353  const char* name /**< name of constraint, or NULL */
354  )
355 {
356  assert(blkmem != NULL);
357  assert(cons != NULL);
358  assert(nlinidxs >= 0);
359  assert(linidxs != NULL || nlinidxs == 0);
360  assert(lincoefs != NULL || nlinidxs == 0);
361  assert(nquadelems >= 0);
362  assert(quadelems != NULL || nquadelems == 0);
363  assert(exprvaridxs != NULL || exprtree == NULL);
364  assert(EPSLE(lhs, rhs, SCIP_DEFAULT_EPSILON));
365 
366  SCIP_ALLOC( BMSallocBlockMemory(blkmem, cons) );
367  assert(*cons != NULL);
368  BMSclearMemory(*cons);
369 
370  if( nlinidxs > 0 )
371  {
372  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->linidxs, linidxs, nlinidxs) );
373  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->lincoefs, lincoefs, nlinidxs) );
374  (*cons)->linsize = nlinidxs;
375  (*cons)->nlinidxs = nlinidxs;
376 
377  /* sort, merge duplicates, remove zero's */
378  sortLinearCoefficients(&(*cons)->nlinidxs, (*cons)->linidxs, (*cons)->lincoefs);
379  assert((*cons)->linidxs[0] >= 0);
380  }
381 
382  if( nquadelems > 0 )
383  {
384  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->quadelems, quadelems, nquadelems) );
385  (*cons)->nquadelems = nquadelems;
386  (*cons)->quadsize = nquadelems;
387 
388  /* sort and squeeze quadratic part */
389  SCIPquadelemSort((*cons)->quadelems, nquadelems);
390  SCIPquadelemSqueeze((*cons)->quadelems, nquadelems, &(*cons)->nquadelems);
391  assert((*cons)->nquadelems == 0 || (*cons)->quadelems[0].idx1 >= 0);
392  assert((*cons)->nquadelems == 0 || (*cons)->quadelems[0].idx2 >= 0);
393  }
394 
395  if( exprtree != NULL )
396  {
397  SCIP_CALL( SCIPexprtreeCopy(blkmem, &(*cons)->exprtree, (SCIP_EXPRTREE*)exprtree) );
398 
399  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->exprvaridxs, exprvaridxs, SCIPexprtreeGetNVars((SCIP_EXPRTREE*)exprtree)) );
400  }
401 
402  if( lhs > rhs )
403  {
404  assert(EPSEQ(lhs, rhs, SCIP_DEFAULT_EPSILON));
405  lhs = rhs;
406  }
407  (*cons)->lhs = lhs;
408  (*cons)->rhs = rhs;
409 
410  if( name != NULL )
411  {
412  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->name, name, strlen(name)+1) );
413  }
414 
415  return SCIP_OKAY;
416 }
417 
418 /** frees a constraint */
419 static
421  BMS_BLKMEM* blkmem, /**< block memory */
422  SCIP_NLPIORACLECONS** cons /**< pointer to constraint that should be freed */
423  )
424 {
425  assert(blkmem != NULL);
426  assert(cons != NULL);
427  assert(*cons != NULL);
428 
429  SCIPdebugMessage("free constraint %p\n", (void*)*cons);
430 
431  BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->linidxs, (*cons)->linsize);
432  BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->lincoefs, (*cons)->linsize);
433 
434  BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->quadelems, (*cons)->quadsize);
435 
436  if( (*cons)->exprtree != NULL )
437  {
438  BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->exprvaridxs, SCIPexprtreeGetNVars((*cons)->exprtree));
439  SCIP_CALL_ABORT( SCIPexprtreeFree(&(*cons)->exprtree) );
440  }
441 
442  if( (*cons)->name != NULL )
443  {
444  BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->name, strlen((*cons)->name)+1);
445  }
446 
447  BMSfreeBlockMemory(blkmem, cons);
448  assert(*cons == NULL);
449 }
450 
451 /** frees all constraints */
452 static
454  SCIP_NLPIORACLE* oracle /**< pointer to store NLPIORACLE data structure */
455  )
456 {
457  int i;
458 
459  assert(oracle != NULL);
460 
461  SCIPdebugMessage("%p free constraints\n", (void*)oracle);
462 
463  for( i = 0; i < oracle->nconss; ++i )
464  {
465  freeConstraint(oracle->blkmem, &oracle->conss[i]);
466  assert(oracle->conss[i] == NULL);
467  }
468  oracle->nconss = 0;
469 
470  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &oracle->conss, oracle->consssize);
471  oracle->consssize = 0;
472 }
473 
474 /** moves one variable
475  * The place where it moves to need to be empty (all NULL) but allocated.
476  * Note that this function does not update the variable indices in the constraints!
477  */
478 static
480  SCIP_NLPIORACLE* oracle, /**< pointer to store NLPIORACLE data structure */
481  int fromidx, /**< index of variable to move */
482  int toidx /**< index of place where to move variable to */
483  )
484 {
485  assert(oracle != NULL);
486 
487  SCIPdebugMessage("%p move variable\n", (void*)oracle);
488 
489  assert(0 <= fromidx);
490  assert(0 <= toidx);
491  assert(fromidx < oracle->nvars);
492  assert(toidx < oracle->nvars);
493 
494  assert(oracle->varlbs[toidx] <= -oracle->infinity);
495  assert(oracle->varubs[toidx] >= oracle->infinity);
496  assert(oracle->varnames == NULL || oracle->varnames[toidx] == NULL);
497  assert(!oracle->vardegreesuptodate || oracle->vardegrees[toidx] == -1);
498 
499  oracle->varlbs[toidx] = oracle->varlbs[fromidx];
500  oracle->varubs[toidx] = oracle->varubs[fromidx];
501 
502  oracle->varlbs[fromidx] = -oracle->infinity;
503  oracle->varubs[fromidx] = oracle->infinity;
504 
505  oracle->vardegrees[toidx] = oracle->vardegrees[fromidx];
506  oracle->vardegrees[fromidx] = -1;
507 
508  if( oracle->varnames != NULL )
509  {
510  oracle->varnames[toidx] = oracle->varnames[fromidx];
511  oracle->varnames[fromidx] = NULL;
512  }
513 
514  return SCIP_OKAY;
515 }
516 
517 /** frees all variables */
518 static
520  SCIP_NLPIORACLE* oracle /**< pointer to store NLPIORACLE data structure */
521  )
522 {
523  int i;
524 
525  assert(oracle != NULL);
526 
527  SCIPdebugMessage("%p free variables\n", (void*)oracle);
528 
529  if( oracle->varnames != NULL )
530  {
531  for( i = 0; i < oracle->nvars; ++i )
532  {
533  if( oracle->varnames[i] != NULL )
534  {
535  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[i], strlen(oracle->varnames[i])+1); /*lint !e866*/
536  }
537  }
538  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &oracle->varnames, oracle->varssize);
539  }
540  oracle->nvars = 0;
541  oracle->vardegreesuptodate = TRUE;
542 
543  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &oracle->varlbs, oracle->varssize);
544  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &oracle->varubs, oracle->varssize);
545  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &oracle->vardegrees, oracle->varssize);
546 
547  oracle->varssize = 0;
548 }
549 
550 /** increases variable degrees in oracle w.r.t. variables occuring in a single constraint */
551 static
553  SCIP_NLPIORACLE* oracle, /**< oracle data structure */
554  SCIP_NLPIORACLECONS* cons /**< oracle constraint */
555  )
556 {
557  int j;
558 
559  assert(oracle != NULL);
560  assert(oracle->vardegrees != NULL);
561  assert(cons != NULL);
562 
563  for( j = 0; j < cons->nlinidxs; ++j )
564  if( oracle->vardegrees[cons->linidxs[j]] < 1 )
565  oracle->vardegrees[cons->linidxs[j]] = 1;
566 
567  for( j = 0; j < cons->nquadelems; ++j )
568  {
569  if( oracle->vardegrees[cons->quadelems[j].idx1] < 2 )
570  oracle->vardegrees[cons->quadelems[j].idx1] = 2;
571 
572  if( oracle->vardegrees[cons->quadelems[j].idx2] < 2 )
573  oracle->vardegrees[cons->quadelems[j].idx2] = 2;
574  }
575 
576  /* we could use exprtreeGetDegree to get actual degree of a variable in tree,
577  * but so far no solver could make use of this information */
578  if( cons->exprtree != NULL )
579  for( j = SCIPexprtreeGetNVars(cons->exprtree)-1; j >= 0; --j )
580  oracle->vardegrees[cons->exprvaridxs[j]] = INT_MAX;
581 }
582 
583 /** Updates the degrees of all variables. */
584 static
586  SCIP_NLPIORACLE* oracle /**< pointer to store NLPIORACLE data structure */
587  )
588 {
589  int c;
590 
591  assert(oracle != NULL);
592  assert(oracle->nvars == 0 || oracle->vardegrees != NULL);
593  assert(oracle->objective != NULL);
594 
595  SCIPdebugMessage("%p update variable degrees\n", (void*)oracle);
596 
597  if( oracle->vardegreesuptodate || oracle->nvars == 0 )
598  return;
599 
600  /* assume all variables do not appear in NLP */
601  BMSclearMemoryArray(oracle->vardegrees, oracle->nvars);
602 
603  updateVariableDegreesCons(oracle, oracle->objective);
604  for( c = 0; c < oracle->nconss; ++c )
605  updateVariableDegreesCons(oracle, oracle->conss[c]);
606 
607  oracle->vardegreesuptodate = TRUE;
608 }
609 
610 /** applies a mapping of indices to one array of indices */
611 static
613  int* indexmap, /**< mapping from old variable indices to new indices */
614  int nindices, /**< number of indices in indices1 and indices2 */
615  int* indices /**< array of indices to adjust */
616  )
617 {
618  assert(indexmap != NULL);
619  assert(nindices == 0 || indices != NULL);
620 
621  for( ; nindices ; --nindices, ++indices )
622  {
623  assert(indexmap[*indices] >= 0);
624  *indices = indexmap[*indices];
625  }
626 }
627 
628 /** removes entries with index -1 (marked as deleted) from array of linear elements
629  * assumes that array is sorted by index, i.e., all -1 are at the beginning
630  */
631 static
633  BMS_BLKMEM* blkmem, /**< block memory */
634  int** linidxs, /**< variable indices */
635  SCIP_Real** coefs, /**< variable coefficients */
636  int* nidxs /**< number of indices */
637  )
638 {
639  int i;
640  int offset;
641 
642  SCIPdebugMessage("clear deleted linear elements\n");
643 
644  assert(blkmem != NULL);
645  assert(linidxs != NULL);
646  assert(*linidxs != NULL);
647  assert(coefs != NULL);
648  assert(*coefs != NULL);
649  assert(nidxs != NULL);
650  assert(*nidxs > 0);
651 
652  /* search for beginning of non-delete entries @todo binary search? */
653  for( offset = 0; offset < *nidxs; ++offset )
654  if( (*linidxs)[offset] >= 0 )
655  break;
656 
657  /* nothing was deleted */
658  if( offset == 0 )
659  return;
660 
661  /* some or all elements were deleted -> move remaining ones front */
662  for( i = 0; i < *nidxs - offset; ++i )
663  {
664  (*linidxs)[i] = (*linidxs)[i+offset];
665  (*coefs)[i] = (*coefs) [i+offset];
666  }
667  *nidxs -= offset;
668 }
669 
670 /** removes entries with index pair (-1,-1) (marked as deleted) from array of quadratic elements
671  * assumes that array is sorted, i.e., all deleted elements are at the beginning
672  */
673 static
675  BMS_BLKMEM* blkmem, /**< block memory */
676  SCIP_QUADELEM** quadelems, /**< quadratic elements */
677  int* nquadelems /**< number of quadratic elements */
678  )
679 {
680  int i;
681  int offset;
682 
683  SCIPdebugMessage("clear deleted quad elements\n");
684 
685  assert(blkmem != NULL);
686  assert(quadelems != NULL);
687  assert(*quadelems != NULL);
688  assert(nquadelems != NULL);
689  assert(*nquadelems > 0);
690 
691  /* search for beginning of non-delete entries @todo binary search? */
692  for( offset = 0; offset < *nquadelems; ++offset )
693  {
694  /* either both variables are marked as deleted or none of them */
695  assert(((*quadelems)[offset].idx1 >= 0) == ((*quadelems)[offset].idx2 >= 0));
696  if( (*quadelems)[offset].idx1 >= 0 )
697  break;
698  }
699 
700  /* nothing was deleted */
701  if( offset == 0 )
702  return;
703 
704  /* some or all elements were deleted -> move remaining ones front */
705  for( i = 0; i < *nquadelems - offset; ++i )
706  (*quadelems)[i] = (*quadelems)[i+offset];
707  *nquadelems -= offset;
708 }
709 
710 /** applies a mapping of indices to an array of quadratic elements */
711 static
713  int* indexmap, /**< mapping from old variable indices to new indices */
714  int nelems, /**< number of quadratic elements */
715  SCIP_QUADELEM* elems /**< array of quadratic elements to adjust */
716  )
717 {
718  assert(indexmap != NULL);
719  assert(nelems == 0 || elems != NULL);
720 
721  for( ; nelems ; --nelems, ++elems )
722  {
723  assert(indexmap[elems->idx1] >= 0);
724  assert(indexmap[elems->idx2] >= 0);
725  elems->idx1 = indexmap[elems->idx1];
726  elems->idx2 = indexmap[elems->idx2];
727  /* swap indices if not idx1 <= idx2 */
728  if( elems->idx1 > elems->idx2 )
729  {
730  int tmp = elems->idx2;
731  elems->idx2 = elems->idx1;
732  elems->idx1 = tmp;
733  }
734  }
735 }
736 
737 /** computes the value of a function */
738 static
740  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
741  SCIP_NLPIORACLECONS* cons, /**< oracle constraint */
742  const SCIP_Real* x, /**< the point where to evaluate */
743  SCIP_Real* val /**< pointer to store function value */
744  )
745 { /*lint --e{715}*/
746  assert(oracle != NULL);
747  assert(cons != NULL);
748  assert(x != NULL || oracle->nvars == 0);
749  assert(val != NULL);
750 
751  SCIPdebugMessage("%p eval function value\n", (void*)oracle);
752 
753  *val = 0.0;
754 
755  if( cons->nlinidxs > 0 )
756  {
757  int* linidxs;
759  int nlin;
760 
761  nlin = cons->nlinidxs;
762  linidxs = cons->linidxs;
763  lincoefs = cons->lincoefs;
764  assert(linidxs != NULL);
765  assert(lincoefs != NULL);
766  assert(x != NULL);
767 
768  for( ; nlin > 0; --nlin, ++linidxs, ++lincoefs )
769  *val += *lincoefs * x[*linidxs];
770  }
771 
772  if( cons->nquadelems > 0 )
773  {
775  int nquadelems;
776 
777  quadelems = cons->quadelems;
778  nquadelems = cons->nquadelems;
779  assert(quadelems != NULL);
780  assert(x != NULL);
781 
782  for( ; nquadelems > 0; --nquadelems, ++quadelems )
783  *val += quadelems->coef * x[quadelems->idx1] * x[quadelems->idx2];
784  }
785 
786  if( cons->exprtree != NULL )
787  {
788  SCIP_Real* xx;
789  int i;
790  SCIP_Real nlval;
791  int nvars;
792 
793  nvars = SCIPexprtreeGetNVars(cons->exprtree);
794 
795  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &xx, nvars) );
796  for( i = 0; i < nvars; ++i )
797  {
798  assert(cons->exprvaridxs[i] >= 0);
799  assert(cons->exprvaridxs[i] < oracle->nvars);
800  xx[i] = x[cons->exprvaridxs[i]]; /*lint !e613 !e644*/
801  }
802 
803  SCIP_CALL( SCIPexprintEval(oracle->exprinterpreter, cons->exprtree, xx, &nlval) );
804  if( nlval != nlval || ABS(nlval) >= oracle->infinity ) /*lint !e777*/
805  *val = nlval;
806  else
807  *val += nlval;
808 
809  BMSfreeBlockMemoryArray(oracle->blkmem, &xx, nvars);
810  }
811 
812  return SCIP_OKAY;
813 }
814 
815 /** computes the value and gradient of a function
816  *
817  * @return SCIP_INVALIDDATA, if the function or its gradient could not be evaluated (domain error, etc.)
818  */
819 static
821  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
822  SCIP_NLPIORACLECONS* cons, /**< oracle constraint */
823  const SCIP_Real* x, /**< the point where to evaluate */
824  SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
825  SCIP_Real* RESTRICT val, /**< pointer to store function value */
826  SCIP_Real* RESTRICT grad /**< pointer to store function gradient */
827  )
828 { /*lint --e{715}*/
829  assert(oracle != NULL);
830  assert(x != NULL || oracle->nvars == 0);
831  assert(val != NULL);
832  assert(grad != NULL);
833 
834  SCIPdebugMessage("%p eval function gradient\n", (void*)oracle);
835 
836  *val = 0.0;
837  BMSclearMemoryArray(grad, oracle->nvars);
838 
839  if( cons->nlinidxs > 0 )
840  {
841  int* linidxs;
843  int nlin;
844 
845  nlin = cons->nlinidxs;
846  linidxs = cons->linidxs;
847  lincoefs = cons->lincoefs;
848  assert(linidxs != NULL);
849  assert(lincoefs != NULL);
850  assert(x != NULL);
851 
852  for( ; nlin > 0; --nlin, ++linidxs, ++lincoefs )
853  {
854  *val += *lincoefs * x[*linidxs];
855  assert(grad[*linidxs] == 0.0); /* we do not like duplicate indices */
856  grad[*linidxs] = *lincoefs;
857  }
858  }
859 
860  if( cons->nquadelems > 0 )
861  {
862  SCIP_Real tmp;
864  int nquadelems;
865 
866  quadelems = cons->quadelems;
867  nquadelems = cons->nquadelems;
868  assert(quadelems != NULL);
869  assert(x != NULL);
870 
871  for( ; nquadelems > 0; --nquadelems, ++quadelems )
872  {
873  tmp = quadelems->coef * x[quadelems->idx1];
874  *val += tmp * x[quadelems->idx2];
875  grad[quadelems->idx2] += tmp;
876  grad[quadelems->idx1] += quadelems->coef * x[quadelems->idx2];
877  }
878  }
879 
880  if( cons->exprtree != NULL )
881  {
882  SCIP_Real* xx;
883  SCIP_Real* g;
884  int i;
885  SCIP_Real nlval;
886  int nvars;
887 
888  xx = NULL;
889  nvars = SCIPexprtreeGetNVars(cons->exprtree);
890 
891  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &g, nvars) );
892 
893  if( isnewx )
894  {
895  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &xx, nvars) );
896  for( i = 0; i < nvars; ++i )
897  {
898  assert(cons->exprvaridxs[i] >= 0);
899  assert(cons->exprvaridxs[i] < oracle->nvars);
900  xx[i] = x[cons->exprvaridxs[i]]; /*lint !e613*/
901  }
902  }
903 
904  SCIPdebugMessage("eval gradient of ");
905  SCIPdebug( if( isnewx ) {printf("\nx ="); for( i = 0; i < nvars; ++i) printf(" %g", xx[i]); /*lint !e613*/ printf("\n");} )
906 
907  SCIP_CALL( SCIPexprintGrad(oracle->exprinterpreter, cons->exprtree, xx, isnewx, &nlval, g) ); /*lint !e644*/
908 
909  SCIPdebug( printf("g ="); for( i = 0; i < nvars; ++i) printf(" %g", g[i]); printf("\n"); )
910 
911  if( nlval != nlval || ABS(nlval) >= oracle->infinity ) /*lint !e777*/
912  {
913  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
914  BMSfreeBlockMemoryArray(oracle->blkmem, &g, nvars);
915  SCIPdebugMessage("gradient evaluation yield invalid function value %g\n", nlval);
916  return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
917  }
918  else
919  {
920  *val += nlval;
921  for( i = 0; i < nvars; ++i )
922  if( !SCIPisFinite(g[i]) ) /*lint !e777*/
923  {
924  SCIPdebugMessage("gradient evaluation yield invalid gradient value %g\n", g[i]);
925  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
926  BMSfreeBlockMemoryArray(oracle->blkmem, &g, nvars);
927  return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
928  }
929  else
930  {
931  grad[cons->exprvaridxs[i]] += g[i];
932  }
933  }
934 
935  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
936  BMSfreeBlockMemoryArray(oracle->blkmem, &g, nvars);
937  }
938 
939  return SCIP_OKAY;
940 }
941 
942 /** collects nonzeros entries in colnz and increases the nzcount given indices of quadratic terms */
943 static
945  SCIP_NLPIORACLE* oracle, /**< NLPI oracle */
946  int** colnz, /**< indices of nonzero entries for each column */
947  int* collen, /**< space allocated to store indices of nonzeros for each column */
948  int* colnnz, /**< number of nonzero entries for each column */
949  int* nzcount, /**< counter for total number of nonzeros; should be increased whenever some colnnz is increased */
950  int length, /**< length of quadratic part */
951  SCIP_QUADELEM* quadelems /**< quadratic elements */
952  )
953 {
954  int pos;
955 
956  SCIPdebugMessage("%p hess lag sparsity set nzflag for quad\n", (void*)oracle);
957 
958  assert(oracle != NULL);
959  assert(colnz != NULL);
960  assert(collen != NULL);
961  assert(colnnz != NULL);
962  assert(nzcount != NULL);
963  assert(quadelems != NULL);
964  assert(length >= 0);
965 
966  for( ; length > 0; --length, ++quadelems )
967  {
968  assert(quadelems->idx1 <= quadelems->idx2);
969 
970  if( colnz[quadelems->idx2] == NULL || !SCIPsortedvecFindInt(colnz[quadelems->idx2], quadelems->idx1, colnnz[quadelems->idx2], &pos) )
971  {
972  SCIP_CALL( ensureIntArraySize(oracle->blkmem, &colnz[quadelems->idx2], &collen[quadelems->idx2], colnnz[quadelems->idx2]+1) );
973  SCIPsortedvecInsertInt(colnz[quadelems->idx2], quadelems->idx1, &colnnz[quadelems->idx2], NULL);
974  ++(*nzcount);
975  }
976  }
977 
978  return SCIP_OKAY;
979 }
980 
981 /** collects indices of nonzero entries in the lower-left part of the hessian matrix of an expression
982  * adds the indices to a given set of indices, avoiding duplicates */
983 static
985  SCIP_NLPIORACLE* oracle, /**< NLPI oracle */
986  int** colnz, /**< indices of nonzero entries for each column */
987  int* collen, /**< space allocated to store indices of nonzeros for each column */
988  int* colnnz, /**< number of nonzero entries for each column */
989  int* nzcount, /**< counter for total number of nonzeros; should be increased when nzflag is set to 1 the first time */
990  int* exprvaridx, /**< indices of variables from expression tree in NLP */
991  SCIP_EXPRTREE* exprtree, /**< expression tree */
992  int dim /**< dimension of matrix */
993  )
994 {
995  SCIP_Real* x;
996  SCIP_Bool* hesnz;
997  int i;
998  int j;
999  int nvars;
1000  int nn;
1001  int row;
1002  int col;
1003  int pos;
1004 
1005  assert(oracle != NULL);
1006  assert(colnz != NULL);
1007  assert(collen != NULL);
1008  assert(colnnz != NULL);
1009  assert(nzcount != NULL);
1010  assert(exprvaridx != NULL);
1011  assert(exprtree != NULL);
1012  assert(dim >= 0);
1013 
1014  SCIPdebugMessage("%p hess lag sparsity set nzflag for exprtree\n", (void*)oracle);
1015 
1016  nvars = SCIPexprtreeGetNVars(exprtree);
1017  nn = nvars * nvars;
1018 
1019  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &x, nvars) );
1020  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &hesnz, nn) );
1021 
1022  for( i = 0; i < nvars; ++i )
1023  x[i] = 2.0; /* hope that this value does not make much trouble for the evaluation routines */ /*lint !e644*/
1024 
1025  SCIP_CALL( SCIPexprintHessianSparsityDense(oracle->exprinterpreter, exprtree, x, hesnz) ); /*lint !e644*/
1026 
1027  for( i = 0; i < nvars; ++i ) /* rows */
1028  for( j = 0; j <= i; ++j ) /* cols */
1029  {
1030  if( !hesnz[i*nvars + j] )
1031  continue;
1032 
1033  row = MAX(exprvaridx[i], exprvaridx[j]);
1034  col = MIN(exprvaridx[i], exprvaridx[j]);
1035 
1036  assert(row < dim);
1037  assert(col <= row);
1038 
1039  if( colnz[row] == NULL || !SCIPsortedvecFindInt(colnz[row], col, colnnz[row], &pos) )
1040  {
1041  SCIP_CALL( ensureIntArraySize(oracle->blkmem, &colnz[row], &collen[row], colnnz[row]+1) );
1042  SCIPsortedvecInsertInt(colnz[row], col, &colnnz[row], NULL);
1043  ++(*nzcount);
1044  }
1045  }
1046 
1047  BMSfreeBlockMemoryArray(oracle->blkmem, &x, nvars);
1048  BMSfreeBlockMemoryArray(oracle->blkmem, &hesnz, nn);
1049 
1050  return SCIP_OKAY;
1051 }
1052 
1053 /** adds quadratic part into hessian structure */
1054 static
1056  SCIP_Real weight, /**< weight of quadratic part */
1057  int length, /**< number of elements in matrix of quadratic part */
1058  SCIP_QUADELEM* quadelems, /**< elements in matrix of quadratic part */
1059  int* hesoffset, /**< row offsets in sparse matrix that is to be filled */
1060  int* hescol, /**< column indices in sparse matrix that is to be filled */
1061  SCIP_Real* values /**< buffer for values of sparse matrix that is to be filled */
1062  )
1063 {
1064  int idx;
1065 
1066  SCIPdebugMessage("hess lag add quad\n");
1067 
1068  assert(length >= 0);
1069  assert(quadelems != NULL || length == 0);
1070  assert(hesoffset != NULL);
1071  assert(hescol != NULL);
1072  assert(values != NULL);
1073 
1074  for( ; length > 0; --length, ++quadelems ) /*lint !e613*/
1075  {
1076  assert(quadelems->idx1 <= quadelems->idx2); /*lint !e613*/
1077  if( !SCIPsortedvecFindInt(&hescol[hesoffset[quadelems->idx2]], quadelems->idx1, hesoffset[quadelems->idx2 + 1] - hesoffset[quadelems->idx2], &idx) ) /*lint !e613*/
1078  {
1079  SCIPerrorMessage("Could not find entry in hessian sparsity\n");
1080  return SCIP_ERROR;
1081  }
1082  values[hesoffset[quadelems->idx2] + idx] += weight * ((quadelems->idx1 == quadelems->idx2) ? 2 * quadelems->coef : quadelems->coef); /*lint !e613*/
1083  }
1084 
1085  return SCIP_OKAY;
1086 }
1087 
1088 /** adds hessian of an expression into hessian structure */
1089 static
1091  SCIP_NLPIORACLE* oracle, /**< oracle */
1092  SCIP_Real weight, /**< weight of quadratic part */
1093  const SCIP_Real* x, /**< point for which hessian should be returned */
1094  SCIP_Bool new_x, /**< whether point has been evaluated before */
1095  int* exprvaridx, /**< NLP indices for variables in expression tree */
1096  SCIP_EXPRTREE* exprtree, /**< expression tree */
1097  int* hesoffset, /**< row offsets in sparse matrix that is to be filled */
1098  int* hescol, /**< column indices in sparse matrix that is to be filled */
1099  SCIP_Real* values /**< buffer for values of sparse matrix that is to be filled */
1100  )
1101 {
1102  SCIP_Real* xx;
1103  SCIP_Real* h;
1104  SCIP_Real* hh;
1105  int i;
1106  int j;
1107  int nvars;
1108  int nn;
1109  int row;
1110  int col;
1111  int idx;
1112  SCIP_Real val;
1113 
1114  SCIPdebugMessage("%p hess lag add exprtree\n", (void*)oracle);
1115 
1116  assert(oracle != NULL);
1117  assert(x != NULL || new_x == FALSE);
1118 
1119  nvars = exprtree != NULL ? SCIPexprtreeGetNVars(exprtree) : 0;
1120  if( nvars == 0 )
1121  return SCIP_OKAY;
1122 
1123  assert(exprtree != NULL);
1124  assert(exprvaridx != NULL);
1125  assert(hesoffset != NULL);
1126  assert(hescol != NULL);
1127  assert(values != NULL);
1128 
1129  nn = nvars * nvars;
1130 
1131  xx = NULL;
1132  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &h, nn) );
1133 
1134  if( new_x )
1135  {
1136  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &xx, nvars) );
1137  for( i = 0; i < nvars; ++i )
1138  {
1139  assert(exprvaridx[i] >= 0);
1140  xx[i] = x[exprvaridx[i]]; /*lint !e613*/
1141  }
1142  }
1143 
1144  SCIP_CALL( SCIPexprintHessianDense(oracle->exprinterpreter, exprtree, xx, new_x, &val, h) ); /*lint !e644*/
1145  if( val != val ) /*lint !e777*/
1146  {
1147  SCIPdebugMessage("hessian evaluation yield invalid function value %g\n", val);
1148  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
1149  BMSfreeBlockMemoryArray(oracle->blkmem, &h, nn);
1150  return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
1151  }
1152 
1153  hh = h;
1154  for( i = 0; i < nvars; ++i ) /* rows */
1155  {
1156  for( j = 0; j <= i; ++j, ++hh ) /* cols */
1157  {
1158  if( !*hh )
1159  continue;
1160 
1161  if( !SCIPisFinite(*hh) ) /*lint !e777*/
1162  {
1163  SCIPdebugMessage("hessian evaluation yield invalid hessian value %g\n", *hh);
1164  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
1165  BMSfreeBlockMemoryArray(oracle->blkmem, &h, nn);
1166  return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
1167  }
1168 
1169  row = MAX(exprvaridx[i], exprvaridx[j]);
1170  col = MIN(exprvaridx[i], exprvaridx[j]);
1171 
1172  if( !SCIPsortedvecFindInt(&hescol[hesoffset[row]], col, hesoffset[row+1] - hesoffset[row], &idx) )
1173  {
1174  SCIPerrorMessage("Could not find entry (%d, %d) in hessian sparsity\n", row, col);
1175  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
1176  BMSfreeBlockMemoryArray(oracle->blkmem, &h, nn);
1177  return SCIP_ERROR;
1178  }
1179 
1180  values[hesoffset[row] + idx] += weight * *hh;
1181  }
1182  hh += nvars - j;
1183  }
1184 
1185  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, nvars);
1186  BMSfreeBlockMemoryArray(oracle->blkmem, &h, nn);
1187 
1188  return SCIP_OKAY;
1189 }
1190 
1191 /** prints a name, if available, makes sure it has not more than 64 characters, and adds a unique prefix if the longnames flag is set */
1192 static
1194  char* buffer, /**< buffer to print to, has to be not NULL */
1195  char* name, /**< name, or NULL */
1196  int idx, /**< index of var or cons which the name corresponds to */
1197  char prefix, /**< a letter (typically 'x' or 'e') to distinguish variable and equation names, if names[idx] is not available */
1198  const char* suffix, /**< a suffer to add to the name, or NULL */
1199  SCIP_Bool longnames /**< whether prefixes for long names should be added */
1200  )
1201 {
1202  assert(idx >= 0 && idx < 100000); /* to ensure that we do not exceed the size of the buffer */
1203 
1204  if( longnames )
1205  {
1206  if( name != NULL )
1207  sprintf(buffer, "%c%05d%.*s%s", prefix, idx, suffix ? (int)(57-strlen(suffix)) : 57, name, suffix ? suffix : "");
1208  else
1209  sprintf(buffer, "%c%05d", prefix, idx);
1210  }
1211  else
1212  {
1213  if( name != NULL )
1214  {
1215  assert(strlen(name) + (suffix ? strlen(suffix) : 0) <= 64);
1216  sprintf(buffer, "%s%s", name, suffix ? suffix : "");
1217  }
1218  else
1219  sprintf(buffer, "%c%d%s", prefix, idx, suffix ? suffix : "");
1220  }
1221 }
1222 
1223 /** prints a function */
1224 static
1226  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1227  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1228  FILE* file, /**< file to print to, has to be not NULL */
1229  SCIP_NLPIORACLECONS* cons, /**< constraint which function to print */
1230  SCIP_Bool longvarnames, /**< whether variable names need to be shorten to 64 characters */
1231  SCIP_Bool longequnames /**< whether equation names need to be shorten to 64 characters */
1232  )
1233 { /*lint --e{715}*/
1234  int i;
1235  char namebuf[70];
1236 
1237  SCIPdebugMessage("%p print function\n", (void*)oracle);
1238 
1239  assert(oracle != NULL);
1240  assert(file != NULL);
1241  assert(cons != NULL);
1242 
1243  for( i = 0; i < cons->nlinidxs; ++i )
1244  {
1245  printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->linidxs[i]] : NULL, cons->linidxs[i], 'x', NULL, longvarnames);
1246  SCIPmessageFPrintInfo(messagehdlr, file, "%+.20g*%s", cons->lincoefs[i], namebuf);
1247  if( i % 10 == 9 )
1248  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
1249  }
1250 
1251  for( i = 0; i < cons->nquadelems; ++i )
1252  {
1253  printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->quadelems[i].idx1] : NULL, cons->quadelems[i].idx1, 'x', NULL, longvarnames);
1254  SCIPmessageFPrintInfo(messagehdlr, file, "%+.20g*%s", cons->quadelems[i].coef, namebuf);
1255  printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->quadelems[i].idx2] : NULL, cons->quadelems[i].idx2, 'x', NULL, longvarnames);
1256  SCIPmessageFPrintInfo(messagehdlr, file, "*%s", namebuf);
1257  if( i % 10 == 9 )
1258  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
1259  }
1260 
1261  if( cons->exprtree != NULL )
1262  {
1263  char** varnames;
1264  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &varnames, SCIPexprtreeGetNVars(cons->exprtree)) ); /*lint !e666*/
1265 
1266  /* setup variable names */
1267  for( i = 0; i < SCIPexprtreeGetNVars(cons->exprtree); ++i )
1268  {
1269  assert(cons->exprvaridxs[i] < 1e+20);
1270  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &varnames[i], 70) ); /*lint !e866 !e506 !e644*/
1271  printName(varnames[i], oracle->varnames != NULL ? oracle->varnames[cons->exprvaridxs[i]] : NULL, cons->exprvaridxs[i], 'x', NULL, longvarnames);
1272  }
1273 
1274  SCIPmessageFPrintInfo(messagehdlr, file, " +");
1275  SCIPexprtreePrint(cons->exprtree, messagehdlr, file, (const char**)varnames, NULL);
1276 
1277  for( i = 0; i < SCIPexprtreeGetNVars(cons->exprtree); ++i )
1278  {
1279  BMSfreeBlockMemoryArray(oracle->blkmem, &varnames[i], 70); /*lint !e866*/
1280  }
1281  BMSfreeBlockMemoryArray(oracle->blkmem, &varnames, SCIPexprtreeGetNVars(cons->exprtree));
1282  }
1283 
1284  return SCIP_OKAY;
1285 }
1286 
1287 /** returns whether an expression is contains nonsmooth operands (min, max, abs, ...) */
1288 static
1290  SCIP_EXPR* expr /**< expression */
1291  )
1292 {
1293  int i;
1294 
1295  assert(expr != NULL);
1296  assert(SCIPexprGetChildren(expr) != NULL || SCIPexprGetNChildren(expr) == 0);
1297 
1298  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1299  {
1300  if( exprIsNonSmooth(SCIPexprGetChildren(expr)[i]) )
1301  return TRUE;
1302  }
1303 
1304  switch( SCIPexprGetOperator(expr) )
1305  {
1306  case SCIP_EXPR_MIN:
1307  case SCIP_EXPR_MAX:
1308  case SCIP_EXPR_ABS:
1309  case SCIP_EXPR_SIGN:
1310  case SCIP_EXPR_SIGNPOWER:
1311  return TRUE;
1312 
1313  default: ;
1314  } /*lint !e788*/
1315 
1316  return FALSE;
1317 }
1318 
1319 /**@} */
1320 
1321 /**@name public function */
1322 /**@{ */
1323 
1324 /** creates an NLPIORACLE data structure */
1326  BMS_BLKMEM* blkmem, /**< block memory */
1327  SCIP_NLPIORACLE** oracle /**< pointer to store NLPIORACLE data structure */
1328  )
1329 {
1330  assert(blkmem != NULL);
1331  assert(oracle != NULL);
1332 
1333  SCIPdebugMessage("%p oracle create\n", (void*)oracle);
1334 
1335  SCIP_ALLOC( BMSallocMemory(oracle) );
1336  BMSclearMemory(*oracle);
1337 
1338  (*oracle)->blkmem = blkmem;
1339  (*oracle)->infinity = SCIP_DEFAULT_INFINITY;
1340  (*oracle)->vardegreesuptodate = TRUE;
1341 
1342  SCIPdebugMessage("Oracle initializes expression interpreter %s\n", SCIPexprintGetName());
1343  SCIP_CALL( SCIPexprintCreate(blkmem, &(*oracle)->exprinterpreter) );
1344 
1345  /* create zero objective function */
1346  SCIP_CALL( createConstraint((*oracle)->blkmem, &(*oracle)->objective, 0, NULL, NULL, 0, NULL, NULL, NULL, 0.0, 0.0, NULL) );
1347 
1348  return SCIP_OKAY;
1349 }
1350 
1351 /** frees an NLPIORACLE data structure */
1353  SCIP_NLPIORACLE** oracle /**< pointer to NLPIORACLE data structure */
1354  )
1355 {
1356  assert(oracle != NULL);
1357  assert(*oracle != NULL);
1358 
1359  SCIPdebugMessage("%p oracle free\n", (void*)oracle);
1360 
1361  invalidateJacobiSparsity(*oracle);
1363 
1364  freeConstraint((*oracle)->blkmem, &(*oracle)->objective);
1365  freeConstraints(*oracle);
1366  freeVariables(*oracle);
1367 
1368  SCIP_CALL( SCIPexprintFree(&(*oracle)->exprinterpreter) );
1369 
1370  if( (*oracle)->name != NULL )
1371  {
1372  SCIP_CALL( SCIPnlpiOracleSetProblemName(*oracle, NULL) );
1373  }
1374 
1375  BMSfreeMemory(oracle);
1376 
1377  return SCIP_OKAY;
1378 }
1379 
1380 /** sets the value for infinity */
1382  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1383  SCIP_Real infinity /**< value to use for infinity */
1384  )
1385 {
1386  assert(oracle != NULL);
1387  assert(infinity > 0.0);
1388 
1389  SCIPdebugMessage("%p set infinity\n", (void*)oracle);
1390 
1391  oracle->infinity = infinity;
1392 
1393  return SCIP_OKAY;
1394 }
1395 
1396 /** gets the value for infinity */
1398  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
1399  )
1400 {
1401  assert(oracle != NULL);
1402 
1403  SCIPdebugMessage("%p get infinity\n", (void*)oracle);
1404 
1405  return oracle->infinity;
1406 }
1407 
1408 /** sets the problem name (used for printing) */
1410  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1411  const char* name /**< name of problem */
1412  )
1413 {
1414  assert(oracle != NULL);
1415 
1416  SCIPdebugMessage("%p set problem name\n", (void*)oracle);
1417 
1418  if( oracle->name != NULL )
1419  {
1420  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->name, strlen(oracle->name)+1);
1421  }
1422 
1423  if( name != NULL )
1424  {
1425  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &oracle->name, name, strlen(name)+1) );
1426  }
1427 
1428  return SCIP_OKAY;
1429 }
1430 
1431 /** gets the problem name, or NULL if none set */
1433  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
1434  )
1435 {
1436  assert(oracle != NULL);
1437 
1438  SCIPdebugMessage("%p get problem name\n", (void*)oracle);
1439 
1440  return oracle->name;
1441 }
1442 
1443 /** adds variables */
1445  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1446  int nvars, /**< number of variables to add */
1447  const SCIP_Real* lbs, /**< array with lower bounds of new variables, or NULL if all -infinity */
1448  const SCIP_Real* ubs, /**< array with upper bounds of new variables, or NULL if all +infinity */
1449  const char** varnames /**< array with names of new variables, or NULL if no names should be stored */
1450  )
1451 {
1452  int i;
1453 
1454  assert(oracle != NULL);
1455 
1456  SCIPdebugMessage("%p add vars\n", (void*)oracle);
1457 
1458  if( nvars == 0 )
1459  return SCIP_OKAY;
1460 
1461  assert(nvars > 0);
1462 
1463  SCIP_CALL( ensureVarsSize(oracle, oracle->nvars + nvars) );
1464 
1465  if( lbs != NULL )
1466  {
1467  BMScopyMemoryArray(&oracle->varlbs[oracle->nvars], lbs, nvars); /*lint !e866*/
1468  }
1469  else
1470  for( i = 0; i < nvars; ++i )
1471  oracle->varlbs[oracle->nvars+i] = -oracle->infinity;
1472 
1473  if( ubs != NULL )
1474  {
1475  BMScopyMemoryArray(&oracle->varubs[oracle->nvars], ubs, nvars); /*lint !e866*/
1476 
1477  /* ensure variable bounds are consistent */
1478  for( i = oracle->nvars; i < oracle->nvars + nvars; ++i )
1479  {
1480  if( oracle->varlbs[i] > oracle->varubs[i] )
1481  {
1482  assert(EPSEQ(oracle->varlbs[i], oracle->varubs[i], SCIP_DEFAULT_EPSILON));
1483  oracle->varlbs[i] = oracle->varubs[i];
1484  }
1485  }
1486  }
1487  else
1488  for( i = 0; i < nvars; ++i )
1489  oracle->varubs[oracle->nvars+i] = oracle->infinity;
1490 
1491  if( varnames != NULL )
1492  {
1493  if( oracle->varnames == NULL )
1494  {
1495  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->varnames, oracle->varssize) );
1496  BMSclearMemoryArray(oracle->varnames, oracle->nvars);
1497  }
1498 
1499  for( i = 0; i < nvars; ++i )
1500  {
1501  if( varnames[i] != NULL )
1502  {
1503  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &oracle->varnames[oracle->nvars+i], varnames[i], strlen(varnames[i])+1) ); /*lint !e866*/
1504  }
1505  else
1506  oracle->varnames[oracle->nvars+i] = NULL;
1507  }
1508  }
1509  else if( oracle->varnames != NULL )
1510  {
1511  BMSclearMemoryArray(&oracle->varnames[oracle->nvars], nvars); /*lint !e866*/
1512  }
1513 
1514  BMSclearMemoryArray(&oracle->vardegrees[oracle->nvars], nvars); /*lint !e866*/
1515 
1516  /* @TODO update sparsity pattern by extending heslagoffsets */
1518 
1519  oracle->nvars += nvars;
1520 
1521  return SCIP_OKAY;
1522 }
1523 
1524 /** adds constraints
1525  *
1526  * linear coefficients: row(=constraint) oriented matrix;
1527  * quadratic coefficients: row oriented matrix for each constraint
1528  */
1530  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1531  int nconss, /**< number of constraints to add */
1532  const SCIP_Real* lhss, /**< array with left-hand sides of constraints, or NULL if all -infinity */
1533  const SCIP_Real* rhss, /**< array with right-hand sides of constraints, or NULL if all +infinity */
1534  const int* nlininds, /**< number of linear coefficients for each constraint, may be NULL in case of no linear part */
1535  int* const* lininds, /**< indices of variables for linear coefficients for each constraint, may be NULL in case of no linear part */
1536  SCIP_Real* const* linvals, /**< values of linear coefficient for each constraint, may be NULL in case of no linear part */
1537  const int* nquadelems, /**< number of elements in matrix of quadratic part for each constraint,
1538  * may be NULL in case of no quadratic part in any constraint */
1539  SCIP_QUADELEM* const* quadelems, /**< quadratic elements specifying quadratic part for each constraint, entry of array may be NULL in case of no quadratic part,
1540  * may be NULL in case of no quadratic part in any constraint */
1541  int* const* exprvaridxs, /**< NULL if no nonquadratic parts, otherwise epxrvaridxs[.] maps variable indices in expression tree to indices in nlp */
1542  SCIP_EXPRTREE* const* exprtrees, /**< NULL if no nonquadratic parts, otherwise exprtrees[.] gives nonquadratic part,
1543  * or NULL if no nonquadratic part in this constraint */
1544  const char** consnames /**< names of new constraints, or NULL if no names should be stored */
1545  )
1546 { /*lint --e{715}*/
1547  SCIP_NLPIORACLECONS* cons;
1548  SCIP_Bool addednlcon; /* whether a nonlinear constraint was added */
1549  int c;
1550 
1551  assert(oracle != NULL);
1552 
1553  SCIPdebugMessage("%p add constraints\n", (void*)oracle);
1554 
1555  if( nconss == 0 )
1556  return SCIP_OKAY;
1557 
1558  assert(nconss > 0);
1559 
1560  addednlcon = FALSE;
1561 
1562  invalidateJacobiSparsity(oracle); /* @TODO we could also update (extend) the sparsity pattern */
1563 
1564  SCIP_CALL( ensureConssSize(oracle, oracle->nconss + nconss) );
1565  for( c = 0; c < nconss; ++c )
1566  {
1567  SCIP_CALL( createConstraint(oracle->blkmem, &cons,
1568  nlininds != NULL ? nlininds[c] : 0,
1569  lininds != NULL ? lininds[c] : NULL,
1570  linvals != NULL ? linvals[c] : NULL,
1571  nquadelems != NULL ? nquadelems[c] : 0,
1572  quadelems != NULL ? quadelems[c] : NULL,
1573  exprvaridxs != NULL ? exprvaridxs[c] : NULL,
1574  exprtrees != NULL ? exprtrees[c] : NULL,
1575  lhss != NULL ? lhss[c] : -oracle->infinity,
1576  rhss != NULL ? rhss[c] : oracle->infinity,
1577  consnames != NULL ? consnames[c] : NULL
1578  ) );
1579 
1580  if( cons->nquadelems > 0 )
1581  addednlcon = TRUE;
1582 
1583  if( cons->exprtree != NULL )
1584  {
1585  addednlcon = TRUE;
1586  SCIP_CALL( SCIPexprintCompile(oracle->exprinterpreter, cons->exprtree) );
1587  }
1588 
1589  /* keep variable degrees updated */
1590  if( oracle->vardegreesuptodate )
1591  updateVariableDegreesCons(oracle, cons);
1592 
1593  oracle->conss[oracle->nconss+c] = cons;
1594  }
1595  oracle->nconss += nconss;
1596 
1597  if( addednlcon == TRUE )
1599 
1600  return SCIP_OKAY;
1601 }
1602 
1603 /** sets or overwrites objective, a minimization problem is expected
1604  *
1605  * May change sparsity pattern.
1606  */
1608  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1609  const SCIP_Real constant, /**< constant part of objective */
1610  int nlin, /**< number of linear variable coefficients */
1611  const int* lininds, /**< indices of linear variables, or NULL if no linear part */
1612  const SCIP_Real* linvals, /**< coefficients of linear variables, or NULL if no linear part */
1613  int nquadelems, /**< number of entries in matrix of quadratic part */
1614  const SCIP_QUADELEM* quadelems, /**< entries in matrix of quadratic part, may be NULL in case of no quadratic part */
1615  const int* exprvaridxs, /**< maps variable indices in expression tree to indices in nlp, or NULL if no nonquadratic part */
1616  const SCIP_EXPRTREE* exprtree /**< expression tree of nonquadratic part, or NULL if no nonquadratic part */
1617  )
1618 { /*lint --e{715}*/
1619  assert(oracle != NULL);
1620  assert(REALABS(constant) < oracle->infinity);
1621 
1622  SCIPdebugMessage("%p set objective\n", (void*)oracle);
1623 
1624  if( nquadelems > 0 || oracle->objective->quadsize > 0 || exprtree != NULL || oracle->objective->exprtree != NULL )
1626 
1627  /* clear previous objective */
1628  freeConstraint(oracle->blkmem, &oracle->objective);
1629 
1630  SCIP_CALL( createConstraint(oracle->blkmem, &oracle->objective,
1631  nlin, lininds, linvals, nquadelems, quadelems, exprvaridxs, exprtree, constant, constant, NULL) );
1632 
1633  if( oracle->objective->exprtree != NULL )
1634  {
1635  SCIP_CALL( SCIPexprintCompile(oracle->exprinterpreter, oracle->objective->exprtree) );
1636  }
1637 
1638  oracle->vardegreesuptodate = FALSE;
1639 
1640  return SCIP_OKAY;
1641 }
1642 
1643 /** change variable bounds */
1645  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1646  int nvars, /**< number of variables to change bounds */
1647  const int* indices, /**< indices of variables to change bounds */
1648  const SCIP_Real* lbs, /**< new lower bounds, or NULL if all should be -infty */
1649  const SCIP_Real* ubs /**< new upper bounds, or NULL if all should be +infty */
1650  )
1651 {
1652  int i;
1653 
1654  assert(oracle != NULL);
1655  assert(indices != NULL || nvars == 0);
1656 
1657  SCIPdebugMessage("%p chg var bounds\n", (void*)oracle);
1658 
1659  for( i = 0; i < nvars; ++i )
1660  {
1661  assert(indices != NULL);
1662  assert(indices[i] >= 0);
1663  assert(indices[i] < oracle->nvars);
1664 
1665  oracle->varlbs[indices[i]] = (lbs != NULL ? lbs[i] : -oracle->infinity);
1666  oracle->varubs[indices[i]] = (ubs != NULL ? ubs[i] : oracle->infinity);
1667 
1668  if( oracle->varlbs[indices[i]] > oracle->varubs[indices[i]] )
1669  {
1670  /* inconsistent bounds; let's assume it's due to rounding and make them equal */
1671  assert(EPSEQ(oracle->varlbs[indices[i]], oracle->varubs[indices[i]], SCIP_DEFAULT_EPSILON));
1672  oracle->varlbs[indices[i]] = oracle->varubs[indices[i]];
1673  }
1674  }
1675 
1676  return SCIP_OKAY;
1677 }
1678 
1679 /** change constraint bounds */
1681  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1682  int nconss, /**< number of constraints to change bounds */
1683  const int* indices, /**< indices of constraints to change bounds */
1684  const SCIP_Real* lhss, /**< new left-hand sides, or NULL if all should be -infty */
1685  const SCIP_Real* rhss /**< new right-hand sides, or NULL if all should be +infty */
1686  )
1687 {
1688  int i;
1689 
1690  assert(oracle != NULL);
1691  assert(indices != NULL || nconss == 0);
1692 
1693  SCIPdebugMessage("%p chg cons sides\n", (void*)oracle);
1694 
1695  for( i = 0; i < nconss; ++i )
1696  {
1697  assert(indices != NULL);
1698  assert(indices[i] >= 0);
1699  assert(indices[i] < oracle->nconss);
1700 
1701  oracle->conss[indices[i]]->lhs = (lhss != NULL ? lhss[i] : -oracle->infinity);
1702  oracle->conss[indices[i]]->rhs = (rhss != NULL ? rhss[i] : oracle->infinity);
1703  if( oracle->conss[indices[i]]->lhs > oracle->conss[indices[i]]->rhs )
1704  {
1705  assert(EPSEQ(oracle->conss[indices[i]]->lhs, oracle->conss[indices[i]]->rhs, SCIP_DEFAULT_EPSILON));
1706  oracle->conss[indices[i]]->lhs = oracle->conss[indices[i]]->rhs;
1707  }
1708  }
1709 
1710  return SCIP_OKAY;
1711 }
1712 
1713 /** deletes a set of variables */
1715  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1716  int* delstats /**< deletion status of vars in input (1 if var should be deleted, 0 if not);
1717  * new position of var in output (-1 if var was deleted) */
1718  )
1719 { /*lint --e{715}*/
1720  int c;
1721  int lastgood; /* index of the last variable that should be kept */
1722  SCIP_NLPIORACLECONS* cons;
1723 
1724  assert(oracle != NULL);
1725 
1726  SCIPdebugMessage("%p del var set\n", (void*)oracle);
1727 
1728  invalidateJacobiSparsity(oracle);
1730 
1731  lastgood = oracle->nvars - 1;
1732  while( lastgood >= 0 && delstats[lastgood] == 1 )
1733  --lastgood;
1734  if( lastgood < 0 )
1735  {
1736  /* all variables should be deleted */
1737  assert(oracle->nconss == 0); /* we could relax this by checking that all constraints are constant */
1738  assert(oracle->objective->exprtree == NULL || SCIPexprtreeGetNVars(oracle->objective->exprtree) == 0);
1739  oracle->objective->nquadelems = 0;
1740  oracle->objective->nlinidxs = 0;
1741  for( c = 0; c < oracle->nvars; ++c )
1742  delstats[c] = -1;
1743  freeVariables(oracle);
1744  return SCIP_OKAY;
1745  }
1746 
1747  /* delete variables at the end */
1748  for( c = oracle->nvars - 1; c > lastgood; --c )
1749  {
1750  if( oracle->varnames && oracle->varnames[c] != NULL )
1751  {
1752  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[c], strlen(oracle->varnames[c])+1); /*lint !e866*/
1753  }
1754  delstats[c] = -1;
1755  }
1756 
1757  /* go through variables from the beginning on
1758  * if variable should be deleted, free it and move lastgood variable to this position
1759  * then update lastgood */
1760  for( c = 0; c <= lastgood; ++c )
1761  {
1762  if( delstats[c] == 0 )
1763  { /* variable should not be deleted and is kept on position c */
1764  delstats[c] = c;
1765  continue;
1766  }
1767  assert(delstats[c] == 1); /* variable should be deleted */
1768 
1769  if( oracle->varnames && oracle->varnames[c] != NULL )
1770  {
1771  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[c], strlen(oracle->varnames[c])+1); /*lint !e866*/
1772  }
1773  delstats[c] = -1;
1774 
1775  /* move constraint at position lastgood to position c */
1776  SCIP_CALL( moveVariable(oracle, lastgood, c) );
1777  delstats[lastgood] = c; /* mark that lastgood variable is now at position c */
1778 
1779  /* move lastgood forward, delete variables on the way */
1780  --lastgood;
1781  while( lastgood > c && delstats[lastgood] == 1)
1782  {
1783  if( oracle->varnames && oracle->varnames[lastgood] != NULL )
1784  {
1785  BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[lastgood], strlen(oracle->varnames[lastgood])+1); /*lint !e866*/
1786  }
1787  delstats[lastgood] = -1;
1788  --lastgood;
1789  }
1790  }
1791  assert(c == lastgood);
1792 
1793  for( c = -1; c < oracle->nconss; ++c )
1794  {
1795  cons = c < 0 ? oracle->objective : oracle->conss[c];
1796  assert(cons != NULL);
1797 
1798  /* update indices in linear part, sort indices, and then clear elements that are marked as deleted */
1799  mapIndices(delstats, cons->nlinidxs, cons->linidxs);
1800  SCIPsortIntReal(cons->linidxs, cons->lincoefs, cons->nlinidxs);
1801  clearDeletedLinearElements(oracle->blkmem, &cons->linidxs, &cons->lincoefs, &cons->nlinidxs);
1802 
1803  /* update indices in quadratic part, sort elements, and then clear elements that are marked as deleted */
1804  mapIndicesQuad(delstats, cons->quadsize, cons->quadelems);
1805  SCIPquadelemSort(cons->quadelems, cons->quadsize);
1806  clearDeletedQuadElements(oracle->blkmem, &cons->quadelems, &cons->quadsize);
1807 
1808  if( cons->exprtree != NULL )
1809  {
1810  mapIndices(delstats, SCIPexprtreeGetNVars(cons->exprtree), cons->exprvaridxs);
1811  /* assert that all variables from this expression have been deleted */
1812  assert(SCIPexprtreeGetNVars(cons->exprtree) == 0 || cons->exprvaridxs[SCIPexprtreeGetNVars(cons->exprtree)-1] == -1);
1813  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &cons->exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree));
1814  SCIP_CALL( SCIPexprtreeFree(&cons->exprtree) );
1815  }
1816  }
1817 
1818  oracle->nvars = lastgood+1;
1819 
1820  return SCIP_OKAY;
1821 }
1822 
1823 /** deletes a set of constraints */
1825  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1826  int* delstats /**< array with deletion status of rows in input (1 if row should be deleted, 0 if not);
1827  * new position of row in output (-1 if row was deleted) */
1828  )
1829 { /*lint --e{715}*/
1830  int c;
1831  int lastgood; /* index of the last constraint that should be kept */
1832 
1833  assert(oracle != NULL);
1834 
1835  SCIPdebugMessage("%p del cons set\n", (void*)oracle);
1836 
1837  invalidateJacobiSparsity(oracle);
1839  oracle->vardegreesuptodate = FALSE;
1840 
1841  lastgood = oracle->nconss - 1;
1842  while( lastgood >= 0 && delstats[lastgood] == 1)
1843  --lastgood;
1844  if( lastgood < 0 )
1845  {
1846  /* all constraints should be deleted */
1847  for( c = 0; c < oracle->nconss; ++c )
1848  delstats[c] = -1;
1849  freeConstraints(oracle);
1850  return SCIP_OKAY;
1851  }
1852 
1853  /* delete constraints at the end */
1854  for( c = oracle->nconss - 1; c > lastgood; --c )
1855  {
1856  freeConstraint(oracle->blkmem, &oracle->conss[c]);
1857  assert(oracle->conss[c] == NULL);
1858  delstats[c] = -1;
1859  }
1860 
1861  /* go through constraint from the beginning on
1862  * if constraint should be deleted, free it and move lastgood constraint to this position
1863  * then update lastgood */
1864  for( c = 0; c <= lastgood; ++c )
1865  {
1866  if( delstats[c] == 0 )
1867  {
1868  /* constraint should not be deleted and is kept on position c */
1869  delstats[c] = c;
1870  continue;
1871  }
1872  assert(delstats[c] == 1); /* constraint should be deleted */
1873 
1874  freeConstraint(oracle->blkmem, &oracle->conss[c]);
1875  assert(oracle->conss[c] == NULL);
1876  delstats[c] = -1;
1877 
1878  /* move constraint at position lastgood to position c */
1879  oracle->conss[c] = oracle->conss[lastgood];
1880  assert(oracle->conss[c] != NULL);
1881  delstats[lastgood] = c; /* mark that lastgood constraint is now at position c */
1882  oracle->conss[lastgood] = NULL;
1883 
1884  /* move lastgood forward, delete constraints on the way */
1885  --lastgood;
1886  while( lastgood > c && delstats[lastgood] == 1)
1887  {
1888  freeConstraint(oracle->blkmem, &oracle->conss[lastgood]);
1889  assert(oracle->conss[lastgood] == NULL);
1890  delstats[lastgood] = -1;
1891  --lastgood;
1892  }
1893  }
1894  assert(c == lastgood);
1895 
1896  oracle->nconss = lastgood+1;
1897 
1898  return SCIP_OKAY;
1899 }
1900 
1901 /** changes linear coefficients in one constraint or objective */
1903  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
1904  int considx, /**< index of constraint where linear coefficients should be changed, or -1 for objective */
1905  int nentries, /**< number of coefficients to change */
1906  const int* varidxs, /**< array with indices of variables which coefficients should be changed */
1907  const SCIP_Real* newcoefs /**< array with new coefficients of variables */
1908  )
1909 { /*lint --e{715}*/
1910  SCIP_NLPIORACLECONS* cons;
1911  SCIP_Bool needsort;
1912  int i;
1913 
1914  SCIPdebugMessage("%p chg linear coefs\n", (void*)oracle);
1915 
1916  assert(oracle != NULL);
1917  assert(varidxs != NULL || nentries == 0);
1918  assert(newcoefs != NULL || nentries == 0);
1919  assert(considx >= -1);
1920  assert(considx < oracle->nconss);
1921 
1922  if( nentries == 0 )
1923  return SCIP_OKAY;
1924 
1925  SCIPdebugMessage("change %d linear coefficients in cons %d\n", nentries, considx);
1926 
1927  needsort = FALSE;
1928 
1929  cons = considx < 0 ? oracle->objective : oracle->conss[considx];
1930 
1931  if( cons->linsize == 0 )
1932  {
1933  /* first time we have linear coefficients in this constraint (or objective) */
1934  assert(cons->linidxs == NULL);
1935  assert(cons->lincoefs == NULL);
1936 
1937  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->linidxs, varidxs, nentries) );
1938  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->lincoefs, newcoefs, nentries) );
1939  cons->linsize = nentries;
1940  cons->nlinidxs = nentries;
1941 
1942  needsort = TRUE;
1943  }
1944  else
1945  {
1946  int pos;
1947 
1948  for( i = 0; i < nentries; ++i )
1949  {
1950  assert(varidxs[i] >= 0); /*lint !e613*/
1951  assert(varidxs[i] < oracle->nvars); /*lint !e613*/
1952 
1953  if( SCIPsortedvecFindInt(cons->linidxs, varidxs[i], cons->nlinidxs, &pos) ) /*lint !e613*/
1954  {
1955  SCIPdebugMessage("replace coefficient of var %d at pos %d by %g\n", varidxs[i], pos, newcoefs[i]); /*lint !e613*/
1956 
1957  cons->lincoefs[pos] = newcoefs[i]; /*lint !e613*/
1958 
1959  /* remember that we need to sort/merge/squeeze array if coefficient became zero here */
1960  needsort |= (newcoefs[i] == 0.0); /*lint !e613 !e514*/
1961  }
1962  else if( newcoefs[i] != 0.0 ) /*lint !e613*/
1963  {
1964  /* append new entry */
1965  SCIPdebugMessage("add coefficient of var %d at pos %d, value %g\n", varidxs[i], cons->nlinidxs, newcoefs[i]); /*lint !e613*/
1966 
1967  SCIP_CALL( ensureConsLinSize(oracle->blkmem, cons, cons->nlinidxs + (nentries-i)) );
1968  cons->linidxs[cons->nlinidxs] = varidxs[i]; /*lint !e613*/
1969  cons->lincoefs[cons->nlinidxs] = newcoefs[i]; /*lint !e613*/
1970  ++cons->nlinidxs;
1971 
1972  needsort = TRUE;
1973  }
1974  }
1975  }
1976 
1977  if( needsort )
1978  {
1979  int oldlen;
1980 
1981  invalidateJacobiSparsity(oracle);
1982 
1983  oldlen = cons->nlinidxs;
1984  sortLinearCoefficients(&cons->nlinidxs, cons->linidxs, cons->lincoefs);
1985 
1986  /* if sorting removed an entry, then the var degrees are not uptodate anymore */
1987  oracle->vardegreesuptodate &= (cons->nlinidxs == oldlen); /*lint !e514*/
1988 
1989  /* increase variable degrees of variables to 1 */
1990  if( oracle->vardegreesuptodate )
1991  for( i = 0; i < cons->nlinidxs; ++i )
1992  oracle->vardegrees[varidxs[i]] = MAX(1, oracle->vardegrees[varidxs[i]]); /*lint !e613*/
1993  }
1994 
1995  return SCIP_OKAY;
1996 }
1997 
1998 /** changes (or adds) coefficients in the quadratic part of one constraint or objective */
2000  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2001  int considx, /**< index of constraint where quadratic coefficients should be changed, or -1 for objective */
2002  int nquadelems, /**< number of entries in quadratic constraint to change */
2003  const SCIP_QUADELEM* quadelems /**< new elements in quadratic matrix (replacing already existing ones or adding new ones) */
2004  )
2005 { /*lint --e{715}*/
2006  SCIP_NLPIORACLECONS* cons;
2007  SCIP_Bool needsort;
2008  int i;
2009 
2010  SCIPdebugMessage("%p chg quad coefs\n", (void*)oracle);
2011 
2012  assert(oracle != NULL);
2013  assert(quadelems != NULL || nquadelems == 0);
2014  assert(considx >= -1);
2015  assert(considx < oracle->nconss);
2016 
2017  if( nquadelems == 0 )
2018  return SCIP_OKAY;
2019 
2020  needsort = FALSE;
2021 
2022  cons = considx < 0 ? oracle->objective : oracle->conss[considx];
2023 
2024  if( cons->quadsize == 0 )
2025  {
2026  /* first time we have quadratic coefficients in this constraint (or objective) */
2027  assert(cons->quadelems == NULL);
2028 
2029  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->quadelems, quadelems, nquadelems) );
2030  cons->quadsize = nquadelems;
2031  cons->nquadelems = nquadelems;
2032 
2033  needsort = TRUE;
2034  }
2035  else
2036  {
2037  int pos;
2038 
2039  for( i = 0; i < nquadelems; ++i )
2040  {
2041  assert(quadelems[i].idx1 >= 0); /*lint !e613*/
2042  assert(quadelems[i].idx2 >= 0); /*lint !e613*/
2043  assert(quadelems[i].idx1 < oracle->nvars); /*lint !e613*/
2044  assert(quadelems[i].idx2 < oracle->nvars); /*lint !e613*/
2045 
2046  /* if we already have an entry for quadelems[i], then just replace the coefficient, otherwise append new entry */
2047  if( SCIPquadelemSortedFind(cons->quadelems, quadelems[i].idx1, quadelems[i].idx2, cons->nquadelems, &pos) ) /*lint !e613*/
2048  {
2049  SCIPdebugMessage("replace coefficient of var%d*var%d at pos %d by %g\n", quadelems[i].idx1, quadelems[i].idx2, pos, quadelems[i].coef); /*lint !e613*/
2050 
2051  cons->quadelems[pos].coef = quadelems[i].coef; /*lint !e613*/
2052 
2053  /* remember that we need to sort/merge/squeeze array if coefficient became zero here */
2054  needsort |= (quadelems[i].coef == 0.0); /*lint !e613 !e514*/
2055  }
2056  else
2057  {
2058  /* append new entry */
2059  SCIPdebugMessage("add coefficient of var%d*var%d at pos %d, value %g\n", quadelems[i].idx1, quadelems[i].idx2, cons->nquadelems, quadelems[i].coef); /*lint !e613*/
2060 
2061  SCIP_CALL( ensureConsQuadSize(oracle->blkmem, cons, cons->nquadelems + (nquadelems-i)) );
2062  cons->quadelems[cons->nquadelems] = quadelems[i]; /*lint !e613*/
2063  ++cons->nquadelems;
2064 
2065  needsort = TRUE;
2066  }
2067  }
2068  }
2069 
2070  if( needsort )
2071  {
2072  int oldsize;
2073 
2074  invalidateJacobiSparsity(oracle);
2076 
2077  oldsize = cons->nquadelems;
2078  SCIPquadelemSort(cons->quadelems, cons->nquadelems);
2079  SCIPquadelemSqueeze(cons->quadelems, cons->nquadelems, &cons->nquadelems);
2080 
2081  /* if sorting removed an entry, then the var degrees are not uptodate anymore */
2082  oracle->vardegreesuptodate &= (cons->nquadelems == oldsize); /*lint !e514*/
2083 
2084  /* increase variable degrees of variables to 2 */
2085  if( oracle->vardegreesuptodate )
2086  for( i = 0; i < cons->nquadelems; ++i )
2087  {
2088  oracle->vardegrees[cons->quadelems[i].idx1] = MAX(2, oracle->vardegrees[cons->quadelems[i].idx1]);
2089  oracle->vardegrees[cons->quadelems[i].idx2] = MAX(2, oracle->vardegrees[cons->quadelems[i].idx2]);
2090  }
2091  }
2092 
2093  return SCIP_OKAY;
2094 }
2095 
2096 /** replaces expression tree of one constraint or objective */
2098  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2099  int considx, /**< index of constraint where expression tree should be changed, or -1 for objective */
2100  const int* exprvaridxs, /**< problem indices of variables in expression tree */
2101  const SCIP_EXPRTREE* exprtree /**< new expression tree, or NULL */
2102  )
2103 {
2104  SCIP_NLPIORACLECONS* cons;
2105  int j;
2106 
2107  SCIPdebugMessage("%p chg exprtree\n", (void*)oracle);
2108 
2109  assert(oracle != NULL);
2110  assert(considx >= -1);
2111  assert(considx < oracle->nconss);
2112  assert((exprvaridxs != NULL) == (exprtree != NULL));
2113 
2115  invalidateJacobiSparsity(oracle);
2116 
2117  cons = considx < 0 ? oracle->objective : oracle->conss[considx];
2118 
2119  /* free previous expression tree */
2120  if( cons->exprtree != NULL )
2121  {
2122  BMSfreeBlockMemoryArray(oracle->blkmem, &cons->exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree));
2124  oracle->vardegreesuptodate = FALSE;
2125  }
2126 
2127  /* if user did not want to set new tree, then we are done */
2128  if( exprtree == NULL )
2129  return SCIP_OKAY;
2130 
2131  assert(oracle->exprinterpreter != NULL);
2132 
2133  /* install new expression tree */
2134  SCIP_CALL( SCIPexprtreeCopy(oracle->blkmem, &cons->exprtree, (SCIP_EXPRTREE*)exprtree) );
2135  SCIP_CALL( SCIPexprintCompile(oracle->exprinterpreter, cons->exprtree) );
2136  SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->exprvaridxs, exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree)) );
2137 
2138  /* increase variable degree to keep them up to date
2139  * could get more accurate degree via getMaxDegree function in exprtree, but no solver would use this information so far
2140  */
2141  if( oracle->vardegreesuptodate )
2142  for( j = 0; j < SCIPexprtreeGetNVars(cons->exprtree); ++j )
2143  {
2144  assert(cons->exprvaridxs[j] >= 0);
2145  assert(cons->exprvaridxs[j] < oracle->nvars);
2146  oracle->vardegrees[cons->exprvaridxs[j]] = INT_MAX;
2147  }
2148 
2149  return SCIP_OKAY;
2150 }
2151 
2152 /** changes one parameter of expression tree of one constraint or objective
2153  */
2155  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2156  int considx, /**< index of constraint where parameter should be changed in expression tree, or -1 for objective */
2157  int paramidx, /**< index of parameter */
2158  SCIP_Real paramval /**< new value of parameter */
2159  )
2160 {
2161  SCIPdebugMessage("%p chg expr param\n", (void*)oracle);
2162 
2163  assert(oracle != NULL);
2164  assert(considx >= -1);
2165  assert(considx < oracle->nconss);
2166  assert(paramidx >= 0);
2167  assert(considx >= 0 || oracle->objective->exprtree != NULL);
2168  assert(considx >= 0 || paramidx < SCIPexprtreeGetNParams(oracle->objective->exprtree));
2169  assert(considx == -1 || oracle->conss[considx]->exprtree != NULL);
2170  assert(considx == -1 || paramidx < SCIPexprtreeGetNParams(oracle->conss[considx]->exprtree));
2171 
2172  SCIPexprtreeSetParamVal(considx >= 0 ? oracle->conss[considx]->exprtree : oracle->objective->exprtree, paramidx, paramval);
2173 
2174  return SCIP_OKAY;
2175 }
2176 
2177 /** changes the constant value in the objective function
2178  */
2180  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2181  SCIP_Real objconstant /**< new value for objective constant */
2182  )
2183 {
2184  assert(oracle != NULL);
2185 
2186  SCIPdebugMessage("%p chg obj constant\n", (void*)oracle);
2187 
2188  oracle->objective->lhs = objconstant;
2189  oracle->objective->rhs = objconstant;
2190 
2191  return SCIP_OKAY;
2192 }
2193 
2194 /** gives the current number of variables */
2196  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2197  )
2198 {
2199  assert(oracle != NULL);
2200 
2201  return oracle->nvars;
2202 }
2203 
2204 /** gives the current number of constraints */
2206  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2207  )
2208 {
2209  assert(oracle != NULL);
2210 
2211  return oracle->nconss;
2212 }
2213 
2214 /** gives the variables lower bounds */
2216  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2217  )
2218 {
2219  assert(oracle != NULL);
2220 
2221  return oracle->varlbs;
2222 }
2223 
2224 /** gives the variables upper bounds */
2226  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2227  )
2228 {
2229  assert(oracle != NULL);
2230 
2231  return oracle->varubs;
2232 }
2233 
2234 /** gives the variables names, or NULL if not set */
2236  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2237  )
2238 {
2239  assert(oracle != NULL);
2240 
2241  return oracle->varnames;
2242 }
2243 
2244 /** Gives maximum degree of a variable w.r.t. objective and all constraints.
2245  * The degree of a variable is the degree of the summand where it appears in, and is infinity for nonpolynomial terms.
2246  */
2248  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2249  int varidx
2250  )
2251 {
2252  assert(oracle != NULL);
2253  assert(varidx >= 0);
2254  assert(varidx < oracle->nvars);
2255 
2256  updateVariableDegrees(oracle);
2257 
2258  return oracle->vardegrees[varidx];
2259 }
2260 
2261 /** Gives maximum degree of all variables w.r.t. objective and all constraints.
2262  * The degree of a variable is the degree of the summand where it appears in, and is infinity for nonpolynomial terms.
2263  */
2265  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2266  )
2267 {
2268  assert(oracle != NULL);
2269 
2270  updateVariableDegrees(oracle);
2271 
2272  return oracle->vardegrees;
2273 }
2274 
2275 /** gives left-hand side of a constraint */
2277  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2278  int considx /**< constraint index */
2279  )
2280 {
2281  assert(oracle != NULL);
2282  assert(considx >= 0);
2283  assert(considx < oracle->nconss);
2284 
2285  return oracle->conss[considx]->lhs;
2286 }
2287 
2288 /** gives right-hand side of a constraint */
2290  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2291  int considx /**< constraint index */
2292  )
2293 {
2294  assert(oracle != NULL);
2295  assert(considx >= 0);
2296  assert(considx < oracle->nconss);
2297 
2298  return oracle->conss[considx]->rhs;
2299 }
2300 
2301 /** gives name of a constraint, may be NULL */
2303  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2304  int considx /**< constraint index */
2305  )
2306 {
2307  assert(oracle != NULL);
2308  assert(considx >= 0);
2309  assert(considx < oracle->nconss);
2310 
2311  return oracle->conss[considx]->name;
2312 }
2313 
2314 /** gives maximum degree of a constraint or objective
2315  * The degree is the maximal degree of all summands,, and is infinity for nonpolynomial terms.
2316  */
2318  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2319  int considx /**< index of constraint for which the degree is requested, or -1 for objective */
2320  )
2321 {
2322  SCIP_NLPIORACLECONS* cons;
2323 
2324  assert(oracle != NULL);
2325  assert(considx >= -1);
2326  assert(considx < oracle->nconss);
2327 
2328  cons = considx < 0 ? oracle->objective : oracle->conss[considx];
2329 
2330  /* could do something more clever like exprtreeGetMaxDegree, but no solver uses this so far */
2331  if( cons->exprtree != NULL )
2332  return INT_MAX;
2333 
2334  if( cons->nquadelems > 0 )
2335  return 2;
2336 
2337  if( cons->nlinidxs > 0 )
2338  return 1;
2339 
2340  return 0;
2341 }
2342 
2343 /** Gives maximum degree over all constraints and the objective (or over all variables, resp.).
2344  * Thus, if this function returns 0, then the objective and all constraints are constant.
2345  * If it returns 1, then the problem in linear.
2346  * If it returns 2, then its a QP, QCP, or QCQP.
2347  * And if it returns > 2, then it is an NLP.
2348  */
2350  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2351  )
2352 {
2353  int i;
2354  int maxdegree;
2355 
2356  assert(oracle != NULL);
2357 
2358  SCIPdebugMessage("%p get max degree\n", (void*)oracle);
2359 
2360  updateVariableDegrees(oracle);
2361 
2362  maxdegree = 0;
2363  for( i = 0; i < oracle->nvars; ++i )
2364  if( oracle->vardegrees[i] > maxdegree )
2365  {
2366  maxdegree = oracle->vardegrees[i];
2367  if( maxdegree == INT_MAX )
2368  break;
2369  }
2370 
2371  return maxdegree;
2372 }
2373 
2374 /** Gives the evaluation capabilities that are shared among all expression trees in the problem. */
2376  SCIP_NLPIORACLE* oracle /**< pointer to NLPIORACLE data structure */
2377  )
2378 {
2379  int c;
2380  SCIP_EXPRINTCAPABILITY evalcapability;
2381 
2382  assert(oracle != NULL);
2383 
2384  if( oracle->objective->exprtree != NULL )
2385  evalcapability = SCIPexprintGetExprtreeCapability(oracle->exprinterpreter, oracle->objective->exprtree);
2386  else
2387  evalcapability = SCIP_EXPRINTCAPABILITY_ALL;
2388 
2389  for( c = 0; c < oracle->nconss; ++c )
2390  if( oracle->conss[c]->exprtree != NULL )
2391  evalcapability &= SCIPexprintGetExprtreeCapability(oracle->exprinterpreter, oracle->conss[c]->exprtree);
2392 
2393  return evalcapability;
2394 }
2395 
2396 /** evaluates the objective function in a given point */
2398  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2399  const SCIP_Real* x, /**< point where to evaluate */
2400  SCIP_Real* objval /**< pointer to store objective value */
2401  )
2402 {
2403  assert(oracle != NULL);
2404 
2405  SCIPdebugMessage("%p eval obj value\n", (void*)oracle);
2406 
2407  SCIP_CALL_QUIET( evalFunctionValue(oracle, oracle->objective, x, objval) );
2408 
2409  assert(oracle->objective->lhs == oracle->objective->rhs); /*lint !e777*/
2410  *objval += oracle->objective->lhs;
2411 
2412  return SCIP_OKAY;
2413 }
2414 
2415 /** evaluates one constraint function in a given point */
2417  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2418  int considx, /**< index of constraint to evaluate */
2419  const SCIP_Real* x, /**< point where to evaluate */
2420  SCIP_Real* conval /**< pointer to store constraint value */
2421  )
2422 {
2423  assert(oracle != NULL);
2424  assert(x != NULL || oracle->nvars == 0);
2425  assert(conval != NULL);
2426 
2427  SCIPdebugMessage("%p eval cons value\n", (void*)oracle);
2428 
2429  SCIP_CALL_QUIET( evalFunctionValue(oracle, oracle->conss[considx], x, conval) );
2430 
2431  return SCIP_OKAY;
2432 }
2433 
2434 /** evaluates all constraint functions in a given point */
2436  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2437  const SCIP_Real* x, /**< point where to evaluate */
2438  SCIP_Real* convals /**< buffer to store constraint values */
2439  )
2440 {
2441  int i;
2442 
2443  SCIPdebugMessage("%p eval cons values\n", (void*)oracle);
2444 
2445  assert(oracle != NULL);
2446  assert(x != NULL || oracle->nvars == 0);
2447  assert(convals != NULL);
2448 
2449  for( i = 0; i < oracle->nconss; ++i )
2450  {
2451  SCIP_CALL_QUIET( evalFunctionValue(oracle, oracle->conss[i], x, &convals[i]) );
2452  }
2453 
2454  return SCIP_OKAY;
2455 }
2456 
2457 /** computes the objective gradient in a given point
2458  *
2459  * @return SCIP_INVALIDDATA, if the function or its gradient could not be evaluated (domain error, etc.)
2460  */
2462  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2463  const SCIP_Real* x, /**< point where to evaluate */
2464  SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2465  SCIP_Real* objval, /**< pointer to store objective value */
2466  SCIP_Real* objgrad /**< pointer to store (dense) objective gradient */
2467  )
2468 {
2469  assert(oracle != NULL);
2470 
2471  SCIPdebugMessage("%p eval obj grad\n", (void*)oracle);
2472 
2473  SCIP_CALL_QUIET( evalFunctionGradient(oracle, oracle->objective, x, isnewx, objval, objgrad) );
2474 
2475  assert(oracle->objective->lhs == oracle->objective->rhs); /*lint !e777*/
2476  *objval += oracle->objective->lhs;
2477 
2478  return SCIP_OKAY;
2479 }
2480 
2481 /** computes a constraints gradient in a given point
2482  *
2483  * @return SCIP_INVALIDDATA, if the function or its gradient could not be evaluated (domain error, etc.)
2484  */
2486  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2487  const int considx, /**< index of constraint to compute gradient for */
2488  const SCIP_Real* x, /**< point where to evaluate */
2489  SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2490  SCIP_Real* conval, /**< pointer to store constraint value */
2491  SCIP_Real* congrad /**< pointer to store (dense) constraint gradient */
2492  )
2493 {
2494  assert(oracle != NULL);
2495  assert(x != NULL || oracle->nvars == 0);
2496  assert(conval != NULL);
2497 
2498  SCIPdebugMessage("%p eval cons grad\n", (void*)oracle);
2499 
2500  SCIP_CALL_QUIET( evalFunctionGradient(oracle, oracle->conss[considx], x, isnewx, conval, congrad) );
2501 
2502  return SCIP_OKAY;
2503 }
2504 
2505 /** gets sparsity pattern (rowwise) of Jacobian matrix
2506  *
2507  * Note that internal data is returned in *offset and *col, thus the user does not need to allocate memory there.
2508  * Adding or deleting constraints destroys the sparsity structure and make another call to this function necessary.
2509  */
2511  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2512  const int** offset, /**< pointer to store pointer that stores the offsets to each rows sparsity pattern in col, can be NULL */
2513  const int** col /**< pointer to store pointer that stores the indices of variables that appear in each row, offset[nconss] gives length of col, can be NULL */
2514  )
2515 {
2516  SCIP_NLPIORACLECONS* cons;
2517  SCIP_Bool* nzflag;
2518  int nnz;
2519  int maxnnz;
2520  int i;
2521  int j;
2522 
2523  assert(oracle != NULL);
2524 
2525  SCIPdebugMessage("%p get jacobian sparsity\n", (void*)oracle);
2526 
2527  if( oracle->jacoffsets != NULL )
2528  {
2529  assert(oracle->jaccols != NULL);
2530  if( offset != NULL )
2531  *offset = oracle->jacoffsets;
2532  if( col != NULL )
2533  *col = oracle->jaccols;
2534  return SCIP_OKAY;
2535  }
2536 
2537  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->jacoffsets, oracle->nconss + 1) );
2538 
2539  maxnnz = MIN(oracle->nvars, 10) * oracle->nconss; /* initial guess */
2540  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->jaccols, maxnnz) );
2541 
2542  if( maxnnz == 0 )
2543  {
2544  /* no variables */
2545  BMSclearMemoryArray(oracle->jacoffsets, oracle->nconss + 1);
2546  if( offset != NULL )
2547  *offset = oracle->jacoffsets;
2548  if( col != NULL )
2549  *col = oracle->jaccols;
2550  return SCIP_OKAY;
2551  }
2552  nnz = 0;
2553 
2554  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &nzflag, oracle->nvars) );
2555 
2556  for( i = 0; i < oracle->nconss; ++i )
2557  {
2558  oracle->jacoffsets[i] = nnz;
2559 
2560  cons = oracle->conss[i];
2561  assert(cons != NULL);
2562 
2563  if( cons->nquadelems == 0 && cons->exprtree == NULL )
2564  {
2565  /* for a linear constraint, we can just copy the linear indices from the constraint into the sparsity pattern */
2566  if( cons->nlinidxs > 0 )
2567  {
2568  SCIP_CALL( ensureIntArraySize(oracle->blkmem, &oracle->jaccols, &maxnnz, nnz + cons->nlinidxs) );
2569  BMScopyMemoryArray(&oracle->jaccols[nnz], cons->linidxs, cons->nlinidxs); /*lint !e866*/
2570  nnz += cons->nlinidxs;
2571  }
2572  continue;
2573  }
2574  else if( cons->nlinidxs == 0 && cons->nquadelems == 0 )
2575  {
2576  /* for a constraint with exprtree only, we can just copy the exprvaridxs from the constraint into the sparsity pattern */
2577  int nvars;
2578 
2579  assert(cons->exprtree != NULL); /* this had been the first case */
2580 
2581  nvars = SCIPexprtreeGetNVars(cons->exprtree);
2582  assert(cons->exprvaridxs != NULL || nvars == 0);
2583 
2584  if( nvars > 0 )
2585  {
2586  SCIP_CALL( ensureIntArraySize(oracle->blkmem, &oracle->jaccols, &maxnnz, nnz + nvars) );
2587  BMScopyMemoryArray(&oracle->jaccols[nnz], cons->exprvaridxs, nvars); /*lint !e866*/
2588  nnz += nvars;
2589  }
2590  continue;
2591  }
2592 
2593  /* check which variables appear in constraint i
2594  * @todo this could be done faster for very sparse constraint by assembling all appearing variables, sorting, and removing duplicates
2595  */
2596  BMSclearMemoryArray(nzflag, oracle->nvars); /*lint !e644*/
2597 
2598  for( j = 0; j < cons->nlinidxs; ++j )
2599  nzflag[cons->linidxs[j]] = TRUE;
2600 
2601  for( j = 0; j < cons->nquadelems; ++j )
2602  {
2603  nzflag[cons->quadelems[j].idx1] = TRUE;
2604  nzflag[cons->quadelems[j].idx2] = TRUE;
2605  }
2606 
2607  if( cons->exprvaridxs != NULL )
2608  {
2609  assert(cons->exprtree != NULL);
2610  for( j = SCIPexprtreeGetNVars(cons->exprtree)-1; j >= 0; --j )
2611  nzflag[cons->exprvaridxs[j]] = TRUE;
2612  }
2613 
2614  /* store variables indices in jaccols */
2615  for( j = 0; j < oracle->nvars; ++j )
2616  {
2617  if( nzflag[j] == FALSE )
2618  continue;
2619 
2620  SCIP_CALL( ensureIntArraySize(oracle->blkmem, &oracle->jaccols, &maxnnz, nnz + 1) );
2621  oracle->jaccols[nnz] = j;
2622  ++nnz;
2623  }
2624  }
2625 
2626  oracle->jacoffsets[oracle->nconss] = nnz;
2627 
2628  /* shrink jaccols array to nnz */
2629  if( nnz < maxnnz )
2630  {
2631  SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->jaccols, maxnnz, nnz) );
2632  }
2633 
2634  BMSfreeBlockMemoryArray(oracle->blkmem, &nzflag, oracle->nvars);
2635 
2636  if( offset != NULL )
2637  *offset = oracle->jacoffsets;
2638  if( col != NULL )
2639  *col = oracle->jaccols;
2640 
2641  return SCIP_OKAY;
2642 }
2643 
2644 /** evaluates the Jacobi matrix in a given point
2645  *
2646  * The values in the Jacobi matrix are returned in the same order as specified by the offset and col arrays obtained by SCIPnlpiOracleGetJacobianSparsity.
2647  * The user need to call SCIPnlpiOracleGetJacobianSparsity at least ones before using this function.
2648  *
2649  * @return SCIP_INVALIDDATA, if the Jacobian could not be evaluated (domain error, etc.)
2650  */
2652  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2653  const SCIP_Real* x, /**< point where to evaluate */
2654  SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2655  SCIP_Real* convals, /**< pointer to store constraint values, can be NULL */
2656  SCIP_Real* jacobi /**< pointer to store sparse jacobian values */
2657  )
2658 {
2659  SCIP_NLPIORACLECONS* cons;
2660  SCIP_RETCODE retcode;
2661  SCIP_Real* grad;
2662  SCIP_Real* xx;
2663  SCIP_Real nlval;
2664  int i;
2665  int j;
2666  int k;
2667  int l;
2668 
2669  SCIPdebugMessage("%p eval jacobian\n", (void*)oracle);
2670 
2671  assert(oracle != NULL);
2672  assert(jacobi != NULL);
2673 
2674  assert(oracle->jacoffsets != NULL);
2675  assert(oracle->jaccols != NULL);
2676 
2677  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &grad, oracle->nvars) );
2678  xx = NULL;
2679 
2680  retcode = SCIP_OKAY;
2681 
2682  j = oracle->jacoffsets[0];
2683  k = 0;
2684  for( i = 0; i < oracle->nconss; ++i )
2685  {
2686  cons = oracle->conss[i];
2687  assert(cons != NULL);
2688 
2689  if( cons->nquadelems == 0 && cons->exprtree == NULL )
2690  {
2691  /* for a linear constraint, we can just copy the linear coefs from the constraint into the jacobian */
2692  if( cons->nlinidxs > 0 )
2693  {
2694  BMScopyMemoryArray(&jacobi[k], cons->lincoefs, cons->nlinidxs); /*lint !e866*/
2695  j += cons->nlinidxs;
2696  k += cons->nlinidxs;
2697  }
2698  assert(j == oracle->jacoffsets[i+1]);
2699  continue;
2700  }
2701 
2702  if( cons->nlinidxs == 0 && cons->nquadelems == 0 )
2703  {
2704  /* for a constraint with exprtree only, we can just copy gradient of the exprtree from the constraint into jacobian */
2705  int nvars;
2706 
2707  assert(cons->exprtree != NULL); /* this had been the first case */
2708 
2709  nvars = SCIPexprtreeGetNVars(cons->exprtree);
2710  assert(nvars <= oracle->nvars);
2711  assert(cons->exprvaridxs != NULL || nvars == 0);
2712 
2713  if( nvars > 0 )
2714  {
2715  if( isnewx )
2716  {
2717  if( xx == NULL )
2718  {
2719  /* if no xx yet, alloc it; make it large enough in case we need it again */
2720  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &xx, oracle->nvars) );
2721  }
2722  for( l = 0; l < nvars; ++l )
2723  xx[l] = x[cons->exprvaridxs[l]]; /*lint !e613*/
2724  }
2725 
2726  SCIPdebugMessage("eval gradient of ");
2727  SCIPdebug( if( isnewx ) {printf("\nx ="); for( l = 0; l < nvars; ++l) printf(" %g", xx[l]); /*lint !e613*/ printf("\n");} )
2728 
2729  SCIP_CALL( SCIPexprintGrad(oracle->exprinterpreter, cons->exprtree, xx, isnewx, &nlval, grad) ); /*lint !e644*/
2730 
2731  SCIPdebug( printf("g ="); for( l = 0; l < nvars; ++l) printf(" %g", grad[l]); printf("\n"); )
2732 
2733  if( nlval != nlval || ABS(nlval) >= oracle->infinity ) /*lint !e777*/
2734  {
2735  SCIPdebugMessage("gradient evaluation yield invalid function value %g\n", nlval);
2736  retcode = SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
2737  break;
2738  }
2739  else
2740  {
2741  if( convals != NULL )
2742  convals[i] = nlval;
2743  for( l = 0; l < nvars; ++l )
2744  {
2745  assert(oracle->jaccols[j+l] == cons->exprvaridxs[l]);
2746  if( !SCIPisFinite(grad[l]) ) /*lint !e777*/
2747  {
2748  SCIPdebugMessage("gradient evaluation yield invalid gradient value %g\n", grad[l]);
2749  retcode = SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
2750  break;
2751  }
2752  else
2753  jacobi[k++] = grad[l];
2754  }
2755  if( l < nvars )
2756  break;
2757  j += nvars;
2758  }
2759  }
2760  else if( convals != NULL )
2761  {
2762  SCIPdebugMessage("eval value of constant ");
2763 
2764  SCIP_CALL( SCIPexprintEval(oracle->exprinterpreter, cons->exprtree, NULL, &convals[i]) );
2765  }
2766  continue;
2767  }
2768 
2769  /* do dense eval @todo could do it sparse */
2770  retcode = SCIPnlpiOracleEvalConstraintGradient(oracle, i, x, isnewx, (convals ? &convals[i] : &nlval), grad);
2771  if( retcode != SCIP_OKAY )
2772  break;
2773 
2774  while( j < oracle->jacoffsets[i+1] )
2775  jacobi[k++] = grad[oracle->jaccols[j++]];
2776  }
2777 
2778  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &xx, oracle->nvars);
2779  BMSfreeBlockMemoryArray(oracle->blkmem, &grad, oracle->nvars);
2780 
2781  return retcode;
2782 }
2783 
2784 /** gets sparsity pattern of the Hessian matrix of the Lagrangian
2785  *
2786  * Note that internal data is returned in *offset and *col, thus the user must not allocate memory there.
2787  * Adding or deleting variables, objective, or constraints may destroy the sparsity structure and make another call to this function necessary.
2788  * Only elements of the lower left triangle and the diagonal are counted.
2789  */
2791  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2792  const int** offset, /**< pointer to store pointer that stores the offsets to each rows sparsity pattern in col, can be NULL */
2793  const int** col /**< pointer to store pointer that stores the indices of variables that appear in each row, offset[nconss] gives length of col, can be NULL */
2794  )
2795 {
2796  int** colnz; /* nonzeros in Hessian corresponding to one column */
2797  int* collen; /* collen[i] is length of array colnz[i] */
2798  int* colnnz; /* colnnz[i] is number of entries in colnz[i] (<= collen[i]) */
2799  int nnz;
2800  int i;
2801  int j;
2802  int cnt;
2803 
2804  assert(oracle != NULL);
2805 
2806  SCIPdebugMessage("%p get hessian lag sparsity\n", (void*)oracle);
2807 
2808  if( oracle->heslagoffsets != NULL )
2809  {
2810  assert(oracle->heslagcols != NULL);
2811  if( offset != NULL )
2812  *offset = oracle->heslagoffsets;
2813  if( col != NULL )
2814  *col = oracle->heslagcols;
2815  return SCIP_OKAY;
2816  }
2817 
2818  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->heslagoffsets, oracle->nvars + 1) );
2819 
2820  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &colnz, oracle->nvars) );
2821  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &collen, oracle->nvars) );
2822  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &colnnz, oracle->nvars) );
2823  BMSclearMemoryArray(colnz, oracle->nvars); /*lint !e644*/
2824  BMSclearMemoryArray(collen, oracle->nvars); /*lint !e644*/
2825  BMSclearMemoryArray(colnnz, oracle->nvars); /*lint !e644*/
2826  nnz = 0;
2827 
2828  if( oracle->objective->nquadelems != 0 )
2829  {
2830  SCIP_CALL( hessLagSparsitySetNzFlagForQuad(oracle, colnz, collen, colnnz, &nnz, oracle->objective->nquadelems, oracle->objective->quadelems) );
2831  }
2832 
2833  if( oracle->objective->exprtree != NULL )
2834  {
2835  SCIP_CALL( hessLagSparsitySetNzFlagForExprtree(oracle, colnz, collen, colnnz, &nnz, oracle->objective->exprvaridxs, oracle->objective->exprtree, oracle->nvars) );
2836  }
2837 
2838  for( i = 0; i < oracle->nconss; ++i )
2839  {
2840  if( oracle->conss[i]->nquadelems != 0 )
2841  {
2842  SCIP_CALL( hessLagSparsitySetNzFlagForQuad(oracle, colnz, collen, colnnz, &nnz, oracle->conss[i]->nquadelems, oracle->conss[i]->quadelems) );
2843  }
2844 
2845  if( oracle->conss[i]->exprtree != NULL )
2846  {
2847  SCIP_CALL( hessLagSparsitySetNzFlagForExprtree(oracle, colnz, collen, colnnz, &nnz, oracle->conss[i]->exprvaridxs, oracle->conss[i]->exprtree, oracle->nvars) );
2848  }
2849  }
2850 
2851  SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->heslagcols, nnz) );
2852 
2853  /* set hessian sparsity from colnz, colnnz */
2854  cnt = 0;
2855  for( i = 0; i < oracle->nvars; ++i )
2856  {
2857  oracle->heslagoffsets[i] = cnt;
2858  for( j = 0; j < colnnz[i]; ++j )
2859  {
2860  assert(cnt < nnz);
2861  oracle->heslagcols[cnt++] = colnz[i][j];
2862  }
2863  BMSfreeBlockMemoryArrayNull(oracle->blkmem, &colnz[i], collen[i]); /*lint !e866*/
2864  collen[i] = 0;
2865  }
2866  oracle->heslagoffsets[oracle->nvars] = cnt;
2867  assert(cnt == nnz);
2868 
2869  BMSfreeBlockMemoryArray(oracle->blkmem, &colnz, oracle->nvars);
2870  BMSfreeBlockMemoryArray(oracle->blkmem, &colnnz, oracle->nvars);
2871  BMSfreeBlockMemoryArray(oracle->blkmem, &collen, oracle->nvars);
2872 
2873  if( offset != NULL )
2874  *offset = oracle->heslagoffsets;
2875  if( col != NULL )
2876  *col = oracle->heslagcols;
2877 
2878  return SCIP_OKAY;
2879 }
2880 
2881 /** evaluates the Hessian matrix of the Lagrangian in a given point
2882  *
2883  * The values in the Hessian matrix are returned in the same order as specified by the offset and col arrays obtained by SCIPnlpiOracleGetHessianLagSparsity.
2884  * The user must call SCIPnlpiOracleGetHessianLagSparsity at least ones before using this function.
2885  * Only elements of the lower left triangle and the diagonal are computed.
2886  *
2887  * @return SCIP_INVALIDDATA, if the Hessian could not be evaluated (domain error, etc.)
2888  */
2890  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2891  const SCIP_Real* x, /**< point where to evaluate */
2892  SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2893  SCIP_Real objfactor, /**< weight for objective function */
2894  const SCIP_Real* lambda, /**< weights (Lagrangian multipliers) for the constraints */
2895  SCIP_Real* hessian /**< pointer to store sparse hessian values */
2896  )
2897 { /*lint --e{715}*/
2898  int i;
2899 
2900  assert(oracle != NULL);
2901  assert(x != NULL);
2902  assert(lambda != NULL || oracle->nconss == 0);
2903  assert(hessian != NULL);
2904 
2905  assert(oracle->heslagoffsets != NULL);
2906  assert(oracle->heslagcols != NULL);
2907 
2908  SCIPdebugMessage("%p eval hessian lag\n", (void*)oracle);
2909 
2910  for( i = oracle->heslagoffsets[oracle->nvars] - 1; i >= 0; --i )
2911  hessian[i] = 0.0;
2912 
2913  if( objfactor != 0.0 )
2914  {
2915  SCIP_CALL( hessLagAddQuad(objfactor, oracle->objective->nquadelems, oracle->objective->quadelems, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2916  SCIP_CALL_QUIET( hessLagAddExprtree(oracle, objfactor, x, isnewx, oracle->objective->exprvaridxs, oracle->objective->exprtree, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2917  }
2918 
2919  for( i = 0; i < oracle->nconss; ++i )
2920  {
2921  assert( lambda != NULL ); /* for lint */
2922  if( lambda[i] == 0.0 )
2923  continue;
2924  SCIP_CALL( hessLagAddQuad(lambda[i], oracle->conss[i]->nquadelems, oracle->conss[i]->quadelems, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2925  SCIP_CALL_QUIET( hessLagAddExprtree(oracle, lambda[i], x, isnewx, oracle->conss[i]->exprvaridxs, oracle->conss[i]->exprtree, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2926  }
2927 
2928  return SCIP_OKAY;
2929 }
2930 
2931 /** prints the problem to a file. */
2933  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
2934  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2935  FILE* file /**< file to print to, or NULL for standard output */
2936  )
2937 { /*lint --e{777} */
2938  int i;
2939  SCIP_Real lhs;
2940  SCIP_Real rhs;
2941 
2942  assert(oracle != NULL);
2943 
2944  SCIPdebugMessage("%p print problem\n", (void*)oracle);
2945 
2946  if( file == NULL )
2947  file = stdout;
2948 
2949  SCIPmessageFPrintInfo(messagehdlr, file, "NLPI Oracle %s: %d variables and %d constraints\n", oracle->name ? oracle->name : "", oracle->nvars, oracle->nconss);
2950  for( i = 0; i < oracle->nvars; ++i )
2951  {
2952  if( oracle->varnames != NULL && oracle->varnames[i] != NULL )
2953  SCIPmessageFPrintInfo(messagehdlr, file, "%10s", oracle->varnames[i]);
2954  else
2955  SCIPmessageFPrintInfo(messagehdlr, file, "x%09d", i);
2956  SCIPmessageFPrintInfo(messagehdlr, file, ": [%8g, %8g]", oracle->varlbs[i], oracle->varubs[i]);
2957  if( oracle->vardegreesuptodate )
2958  SCIPmessageFPrintInfo(messagehdlr, file, "\t degree: %d", oracle->vardegrees[i]);
2959  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
2960  }
2961 
2962  SCIPmessageFPrintInfo(messagehdlr, file, "objective: ");
2963  SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->objective, FALSE, FALSE) );
2964  if( oracle->objective->lhs != 0.0 )
2965  SCIPmessageFPrintInfo(messagehdlr, file, "%+.20g", oracle->objective->lhs);
2966  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
2967 
2968  for( i = 0; i < oracle->nconss; ++i )
2969  {
2970  if( oracle->conss[i]->name != NULL )
2971  SCIPmessageFPrintInfo(messagehdlr, file, "%10s", oracle->conss[i]->name);
2972  else
2973  SCIPmessageFPrintInfo(messagehdlr, file, "con%07d", i);
2974 
2975  lhs = oracle->conss[i]->lhs;
2976  rhs = oracle->conss[i]->rhs;
2977  SCIPmessageFPrintInfo(messagehdlr, file, ": ");
2978  if( lhs > -oracle->infinity && rhs < oracle->infinity && lhs != rhs )
2979  SCIPmessageFPrintInfo(messagehdlr, file, "%.20g <= ", lhs);
2980 
2981  SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->conss[i], FALSE, FALSE) );
2982 
2983  if( lhs == rhs )
2984  SCIPmessageFPrintInfo(messagehdlr, file, " = %.20g", rhs);
2985  else if( rhs < oracle->infinity )
2986  SCIPmessageFPrintInfo(messagehdlr, file, " <= %.20g", rhs);
2987  else if( lhs > -oracle->infinity )
2988  SCIPmessageFPrintInfo(messagehdlr, file, " >= %.20g", lhs);
2989 
2990  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
2991  }
2992 
2993  return SCIP_OKAY;
2994 }
2995 
2996 /** prints the problem to a file in GAMS format
2997  * If there are variable (equation, resp.) names with more than 9 characters, then variable (equation, resp.) names are prefixed with an unique identifier.
2998  * This is to make it easier to identify variables solution output in the listing file.
2999  * Names with more than 64 characters are shorten to 64 letters due to GAMS limits.
3000  */
3002  SCIP_NLPIORACLE* oracle, /**< pointer to NLPIORACLE data structure */
3003  SCIP_Real* initval, /**< starting point values for variables or NULL */
3004  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3005  FILE* file /**< file to print to, or NULL for standard output */
3006  )
3007 { /*lint --e{777} */
3008  int i;
3009  int nllevel; /* level of nonlinearity of problem: linear = 0, quadratic, smooth nonlinear, nonsmooth */
3010  static const char* nllevelname[4] = { "LP", "QCP", "NLP", "DNLP" };
3011  char problemname[SCIP_MAXSTRLEN];
3012  char namebuf[70];
3013  SCIP_Bool havelongvarnames;
3014  SCIP_Bool havelongequnames;
3015 
3016  SCIPdebugMessage("%p print problem gams\n", (void*)oracle);
3017 
3018  assert(oracle != NULL);
3019 
3020  if( file == NULL )
3021  file = stdout;
3022 
3023  nllevel = 0;
3024 
3025  havelongvarnames = FALSE;
3026  for( i = 0; i < oracle->nvars; ++i )
3027  if( oracle->varnames != NULL && oracle->varnames[i] != NULL && strlen(oracle->varnames[i]) > 9 )
3028  {
3029  havelongvarnames = TRUE;
3030  break;
3031  }
3032 
3033  havelongequnames = FALSE;
3034  for( i = 0; i < oracle->nconss; ++i )
3035  if( oracle->conss[i]->name && strlen(oracle->conss[i]->name) > 9 )
3036  {
3037  havelongequnames = TRUE;
3038  break;
3039  }
3040 
3041  SCIPmessageFPrintInfo(messagehdlr, file, "$offlisting\n");
3042  SCIPmessageFPrintInfo(messagehdlr, file, "$offdigit\n");
3043  SCIPmessageFPrintInfo(messagehdlr, file, "* NLPI Oracle Problem %s\n", oracle->name ? oracle->name : "");
3044  SCIPmessageFPrintInfo(messagehdlr, file, "Variables ");
3045  for( i = 0; i < oracle->nvars; ++i )
3046  {
3047  printName(namebuf, oracle->varnames != NULL ? oracle->varnames[i] : NULL, i, 'x', NULL, havelongvarnames);
3048  SCIPmessageFPrintInfo(messagehdlr, file, "%s, ", namebuf);
3049  if( i % 10 == 9 )
3050  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3051  }
3052  SCIPmessageFPrintInfo(messagehdlr, file, "NLPIORACLEOBJVAR;\n\n");
3053  for( i = 0; i < oracle->nvars; ++i )
3054  {
3055  char* name;
3056  name = oracle->varnames != NULL ? oracle->varnames[i] : NULL;
3057  if( oracle->varlbs[i] == oracle->varubs[i] )
3058  {
3059  printName(namebuf, name, i, 'x', NULL, havelongvarnames);
3060  SCIPmessageFPrintInfo(messagehdlr, file, "%s.fx = %.20g;\t", namebuf, oracle->varlbs[i]);
3061  }
3062  else
3063  {
3064  if( oracle->varlbs[i] > -oracle->infinity )
3065  {
3066  printName(namebuf, name, i, 'x', NULL, havelongvarnames);
3067  SCIPmessageFPrintInfo(messagehdlr, file, "%s.lo = %.20g;\t", namebuf, oracle->varlbs[i]);
3068  }
3069  if( oracle->varubs[i] < oracle->infinity )
3070  {
3071  printName(namebuf, name, i, 'x', NULL, havelongvarnames);
3072  SCIPmessageFPrintInfo(messagehdlr, file, "%s.up = %.20g;\t", namebuf, oracle->varubs[i]);
3073  }
3074  }
3075  if( initval != NULL )
3076  {
3077  printName(namebuf, name, i, 'x', NULL, havelongvarnames);
3078  SCIPmessageFPrintInfo(messagehdlr, file, "%s.l = %.20g;\t", namebuf, initval[i]);
3079  }
3080  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3081  }
3082  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3083 
3084  SCIPmessageFPrintInfo(messagehdlr, file, "Equations ");
3085  for( i = 0; i < oracle->nconss; ++i )
3086  {
3087  printName(namebuf, oracle->conss[i]->name, i, 'e', NULL, havelongequnames);
3088  SCIPmessageFPrintInfo(messagehdlr, file, "%s, ", namebuf);
3089 
3090  if( oracle->conss[i]->lhs > -oracle->infinity && oracle->conss[i]->rhs < oracle->infinity && oracle->conss[i]->lhs != oracle->conss[i]->rhs )
3091  {
3092  /* ranged row: add second constraint */
3093  printName(namebuf, oracle->conss[i]->name, i, 'e', "_RNG", havelongequnames);
3094  SCIPmessageFPrintInfo(messagehdlr, file, "%s, ", namebuf);
3095  }
3096  if( i % 10 == 9 )
3097  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3098  }
3099  SCIPmessageFPrintInfo(messagehdlr, file, "NLPIORACLEOBJ;\n\n");
3100 
3101  SCIPmessageFPrintInfo(messagehdlr, file, "NLPIORACLEOBJ.. NLPIORACLEOBJVAR =E= ");
3102  SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->objective, havelongvarnames, havelongequnames) );
3103  if( oracle->objective->lhs != 0.0 )
3104  SCIPmessageFPrintInfo(messagehdlr, file, "%+.20g", oracle->objective->lhs);
3105  SCIPmessageFPrintInfo(messagehdlr, file, ";\n");
3106 
3107  for( i = 0; i < oracle->nconss; ++i )
3108  {
3109  SCIP_Real lhs;
3110  SCIP_Real rhs;
3111 
3112  printName(namebuf, oracle->conss[i]->name, i, 'e', NULL, havelongequnames);
3113  SCIPmessageFPrintInfo(messagehdlr, file, "%s.. ", namebuf);
3114 
3115  SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->conss[i], havelongvarnames, havelongequnames) );
3116 
3117  lhs = oracle->conss[i]->lhs;
3118  rhs = oracle->conss[i]->rhs;
3119 
3120  if( lhs == rhs )
3121  SCIPmessageFPrintInfo(messagehdlr, file, " =E= %.20g", rhs);
3122  else if( rhs < oracle->infinity )
3123  SCIPmessageFPrintInfo(messagehdlr, file, " =L= %.20g", rhs);
3124  else if( lhs > -oracle->infinity )
3125  SCIPmessageFPrintInfo(messagehdlr, file, " =G= %.20g", lhs);
3126  else
3127  SCIPmessageFPrintInfo(messagehdlr, file, " =N= 0");
3128  SCIPmessageFPrintInfo(messagehdlr, file, ";\n");
3129 
3130  if( lhs > -oracle->infinity && rhs < oracle->infinity && lhs != rhs )
3131  {
3132  printName(namebuf, oracle->conss[i]->name, i, 'e', "_RNG", havelongequnames);
3133  SCIPmessageFPrintInfo(messagehdlr, file, "%s.. ", namebuf);
3134 
3135  SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->conss[i], havelongvarnames, havelongequnames) );
3136 
3137  SCIPmessageFPrintInfo(messagehdlr, file, " =G= %.20g;\n", lhs);
3138  }
3139 
3140  if( nllevel <= 0 && oracle->conss[i]->nquadelems > 0 )
3141  nllevel = 1;
3142  if( nllevel <= 1 && oracle->conss[i]->exprtree != NULL )
3143  nllevel = 2;
3144  if( nllevel <= 2 && oracle->conss[i]->exprtree != NULL && exprIsNonSmooth(SCIPexprtreeGetRoot(oracle->conss[i]->exprtree)) )
3145  nllevel = 3;
3146  }
3147 
3148  (void) SCIPsnprintf(problemname, SCIP_MAXSTRLEN, "%s", oracle->name ? oracle->name : "m");
3149 
3150  SCIPmessageFPrintInfo(messagehdlr, file, "Model %s / all /;\n", problemname);
3151  SCIPmessageFPrintInfo(messagehdlr, file, "option limrow = 0;\n");
3152  SCIPmessageFPrintInfo(messagehdlr, file, "option limcol = 0;\n");
3153  SCIPmessageFPrintInfo(messagehdlr, file, "Solve %s minimizing NLPIORACLEOBJVAR using %s;\n", problemname, nllevelname[nllevel]);
3154 
3155  return SCIP_OKAY;
3156 }
3157 
3158 /**@} */
void SCIPquadelemSort(SCIP_QUADELEM *quadelems, int nquadelems)
Definition: expr.c:9193
SCIP_RETCODE SCIPnlpiOraclePrintProblemGams(SCIP_NLPIORACLE *oracle, SCIP_Real *initval, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlpioracle.c:3001
SCIP_RETCODE SCIPnlpiOracleEvalConstraintValues(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Real *convals)
Definition: nlpioracle.c:2435
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:449
const char * SCIPexprintGetName(void)
const SCIP_Real * SCIPnlpiOracleGetVarUbs(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2225
static void updateVariableDegrees(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:585
methods to interpret (evaluate) an expression tree "fast"
SCIP_RETCODE SCIPnlpiOracleGetJacobianSparsity(SCIP_NLPIORACLE *oracle, const int **offset, const int **col)
Definition: nlpioracle.c:2510
void SCIPexprtreePrint(SCIP_EXPRTREE *tree, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char **varnames, const char **paramnames)
Definition: expr.c:8756
SCIP_EXPRINTCAPABILITY SCIPnlpiOracleGetEvalCapability(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2375
SCIP_RETCODE SCIPnlpiOracleGetHessianLagSparsity(SCIP_NLPIORACLE *oracle, const int **offset, const int **col)
Definition: nlpioracle.c:2790
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2195
SCIP_EXPROP SCIPexprGetOperator(SCIP_EXPR *expr)
Definition: expr.c:5693
#define infinity
Definition: gastrans.c:71
static SCIP_Bool exprIsNonSmooth(SCIP_EXPR *expr)
Definition: nlpioracle.c:1289
#define SCIP_MAXSTRLEN
Definition: def.h:259
static SCIP_RETCODE ensureConssSize(SCIP_NLPIORACLE *oracle, int minsize)
Definition: nlpioracle.c:141
static SCIP_RETCODE ensureIntArraySize(BMS_BLKMEM *blkmem, int **intarray, int *len, int minsize)
Definition: nlpioracle.c:218
SCIP_RETCODE SCIPnlpiOracleSetObjective(SCIP_NLPIORACLE *oracle, const SCIP_Real constant, int nlin, const int *lininds, const SCIP_Real *linvals, int nquadelems, const SCIP_QUADELEM *quadelems, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree)
Definition: nlpioracle.c:1607
static SCIP_RETCODE hessLagAddExprtree(SCIP_NLPIORACLE *oracle, SCIP_Real weight, const SCIP_Real *x, SCIP_Bool new_x, int *exprvaridx, SCIP_EXPRTREE *exprtree, int *hesoffset, int *hescol, SCIP_Real *values)
Definition: nlpioracle.c:1090
static void freeVariables(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:519
SCIP_Real * lincoefs
Definition: nlpioracle.c:44
methods to store an NLP and request function, gradient, and hessian values
static SCIP_RETCODE createConstraint(BMS_BLKMEM *blkmem, SCIP_NLPIORACLECONS **cons, int nlinidxs, const int *linidxs, const SCIP_Real *lincoefs, int nquadelems, const SCIP_QUADELEM *quadelems, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree, SCIP_Real lhs, SCIP_Real rhs, const char *name)
Definition: nlpioracle.c:341
#define FALSE
Definition: def.h:64
static SCIP_RETCODE ensureVarsSize(SCIP_NLPIORACLE *oracle, int minsize)
Definition: nlpioracle.c:110
SCIP_Real SCIPnlpiOracleGetConstraintLhs(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2276
#define EPSEQ(x, y, eps)
Definition: def.h:174
static void printName(char *buffer, char *name, int idx, char prefix, const char *suffix, SCIP_Bool longnames)
Definition: nlpioracle.c:1193
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
static void freeConstraint(BMS_BLKMEM *blkmem, SCIP_NLPIORACLECONS **cons)
Definition: nlpioracle.c:420
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPnlpiOracleEvalObjectiveValue(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Real *objval)
Definition: nlpioracle.c:2397
SCIP_RETCODE SCIPexprtreeCopy(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **targettree, SCIP_EXPRTREE *sourcetree)
Definition: expr.c:8812
SCIP_RETCODE SCIPexprintCompile(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree)
static SCIP_RETCODE evalFunctionValue(SCIP_NLPIORACLE *oracle, SCIP_NLPIORACLECONS *cons, const SCIP_Real *x, SCIP_Real *val)
Definition: nlpioracle.c:739
static SCIP_RETCODE hessLagAddQuad(SCIP_Real weight, int length, SCIP_QUADELEM *quadelems, int *hesoffset, int *hescol, SCIP_Real *values)
Definition: nlpioracle.c:1055
static void invalidateJacobiSparsity(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:248
static SCIP_RETCODE printFunction(SCIP_NLPIORACLE *oracle, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_NLPIORACLECONS *cons, SCIP_Bool longvarnames, SCIP_Bool longequnames)
Definition: nlpioracle.c:1225
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_EXPRINTCAPABILITY SCIPexprintGetExprtreeCapability(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree)
static void mapIndices(int *indexmap, int nindices, int *indices)
Definition: nlpioracle.c:612
SCIP_Bool SCIPquadelemSortedFind(SCIP_QUADELEM *quadelems, int idx1, int idx2, int nquadelems, int *pos)
Definition: expr.c:9218
unsigned int SCIP_EXPRINTCAPABILITY
#define BMSfreeMemory(ptr)
Definition: memory.h:127
void SCIPexprtreeSetParamVal(SCIP_EXPRTREE *tree, int paramidx, SCIP_Real paramval)
Definition: expr.c:8642
SCIP_RETCODE SCIPnlpiOracleEvalObjectiveGradient(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *objval, SCIP_Real *objgrad)
Definition: nlpioracle.c:2461
const char * SCIPnlpiOracleGetProblemName(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:1432
SCIP_RETCODE SCIPnlpiOracleDelConsSet(SCIP_NLPIORACLE *oracle, int *delstats)
Definition: nlpioracle.c:1824
int * heslagoffsets
Definition: nlpioracle.c:80
SCIP_RETCODE SCIPnlpiOracleChgObjConstant(SCIP_NLPIORACLE *oracle, SCIP_Real objconstant)
Definition: nlpioracle.c:2179
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2205
static void mapIndicesQuad(int *indexmap, int nelems, SCIP_QUADELEM *elems)
Definition: nlpioracle.c:712
static void clearDeletedQuadElements(BMS_BLKMEM *blkmem, SCIP_QUADELEM **quadelems, int *nquadelems)
Definition: nlpioracle.c:674
public methods for expressions, expression trees, expression graphs, and related stuff ...
#define SCIP_DEFAULT_EPSILON
Definition: def.h:155
static int calcGrowSize(int num)
Definition: nlpioracle.c:94
SCIP_Real coef
Definition: type_expr.h:102
int * jacoffsets
Definition: nlpioracle.c:77
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:443
int SCIPnlpiOracleGetConstraintDegree(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2317
SCIP_RETCODE SCIPnlpiOracleChgExprtree(SCIP_NLPIORACLE *oracle, int considx, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree)
Definition: nlpioracle.c:2097
static void sortLinearCoefficients(int *nidxs, int *idxs, SCIP_Real *coefs)
Definition: nlpioracle.c:292
SCIP_RETCODE SCIPnlpiOracleCreate(BMS_BLKMEM *blkmem, SCIP_NLPIORACLE **oracle)
Definition: nlpioracle.c:1325
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_RETCODE SCIPexprintEval(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Real *val)
const SCIP_Real * SCIPnlpiOracleGetVarLbs(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2215
SCIP_RETCODE SCIPexprintCreate(BMS_BLKMEM *blkmem, SCIP_EXPRINT **exprint)
SCIP_RETCODE SCIPnlpiOracleChgVarBounds(SCIP_NLPIORACLE *oracle, int nvars, const int *indices, const SCIP_Real *lbs, const SCIP_Real *ubs)
Definition: nlpioracle.c:1644
static void invalidateHessianLagSparsity(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:271
SCIP_RETCODE SCIPnlpiOracleAddVars(SCIP_NLPIORACLE *oracle, int nvars, const SCIP_Real *lbs, const SCIP_Real *ubs, const char **varnames)
Definition: nlpioracle.c:1444
#define REALABS(x)
Definition: def.h:173
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8612
static SCIP_RETCODE evalFunctionGradient(SCIP_NLPIORACLE *oracle, SCIP_NLPIORACLECONS *cons, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *RESTRICT val, SCIP_Real *RESTRICT grad)
Definition: nlpioracle.c:820
#define SCIP_CALL(x)
Definition: def.h:350
static SCIP_RETCODE ensureConsLinSize(BMS_BLKMEM *blkmem, SCIP_NLPIORACLECONS *cons, int minsize)
Definition: nlpioracle.c:165
SCIP_Real SCIPnlpiOracleGetConstraintRhs(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2289
SCIP_EXPR * SCIPexprtreeGetRoot(SCIP_EXPRTREE *tree)
Definition: expr.c:8602
SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
SCIP_Real SCIPnlpiOracleGetInfinity(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:1397
SCIP_RETCODE SCIPnlpiOracleFree(SCIP_NLPIORACLE **oracle)
Definition: nlpioracle.c:1352
static SCIP_RETCODE moveVariable(SCIP_NLPIORACLE *oracle, int fromidx, int toidx)
Definition: nlpioracle.c:479
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:446
static void clearDeletedLinearElements(BMS_BLKMEM *blkmem, int **linidxs, SCIP_Real **coefs, int *nidxs)
Definition: nlpioracle.c:632
SCIP_RETCODE SCIPnlpiOracleEvalConstraintGradient(SCIP_NLPIORACLE *oracle, const int considx, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *conval, SCIP_Real *congrad)
Definition: nlpioracle.c:2485
#define SCIP_EXPRINTCAPABILITY_ALL
public data structures and miscellaneous methods
static SCIP_RETCODE hessLagSparsitySetNzFlagForQuad(SCIP_NLPIORACLE *oracle, int **colnz, int *collen, int *colnnz, int *nzcount, int length, SCIP_QUADELEM *quadelems)
Definition: nlpioracle.c:944
SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP_NLPIORACLE *oracle, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlpioracle.c:2932
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:5713
char ** varnames
Definition: nlpioracle.c:67
#define SCIP_Bool
Definition: def.h:61
SCIP_NLPIORACLECONS * objective
Definition: nlpioracle.c:75
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:435
SCIP_RETCODE SCIPnlpiOracleSetProblemName(SCIP_NLPIORACLE *oracle, const char *name)
Definition: nlpioracle.c:1409
static void updateVariableDegreesCons(SCIP_NLPIORACLE *oracle, SCIP_NLPIORACLECONS *cons)
Definition: nlpioracle.c:552
SCIP_RETCODE SCIPnlpiOracleAddConstraints(SCIP_NLPIORACLE *oracle, int nconss, const SCIP_Real *lhss, const SCIP_Real *rhss, const int *nlininds, int *const *lininds, SCIP_Real *const *linvals, const int *nquadelems, SCIP_QUADELEM *const *quadelems, int *const *exprvaridxs, SCIP_EXPRTREE *const *exprtrees, const char **consnames)
Definition: nlpioracle.c:1529
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:448
void SCIPquadelemSqueeze(SCIP_QUADELEM *quadelems, int nquadelems, int *nquadelemsnew)
Definition: expr.c:9270
#define MAX(x, y)
Definition: tclique_def.h:75
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:5703
SCIP_Real * varubs
Definition: nlpioracle.c:66
SCIP_RETCODE SCIPnlpiOracleEvalConstraintValue(SCIP_NLPIORACLE *oracle, int considx, const SCIP_Real *x, SCIP_Real *conval)
Definition: nlpioracle.c:2416
SCIP_Real * varlbs
Definition: nlpioracle.c:65
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8852
#define EPSLE(x, y, eps)
Definition: def.h:176
SCIP_RETCODE SCIPnlpiOracleChgLinearCoefs(SCIP_NLPIORACLE *oracle, int considx, int nentries, const int *varidxs, const SCIP_Real *newcoefs)
Definition: nlpioracle.c:1902
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
SCIP_RETCODE SCIPnlpiOracleChgQuadCoefs(SCIP_NLPIORACLE *oracle, int considx, int nquadelems, const SCIP_QUADELEM *quadelems)
Definition: nlpioracle.c:1999
SCIP_RETCODE SCIPexprintHessianDense(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Bool new_varvals, SCIP_Real *val, SCIP_Real *hessian)
static SCIP_RETCODE hessLagSparsitySetNzFlagForExprtree(SCIP_NLPIORACLE *oracle, int **colnz, int *collen, int *colnnz, int *nzcount, int *exprvaridx, SCIP_EXPRTREE *exprtree, int dim)
Definition: nlpioracle.c:984
SCIP_RETCODE SCIPnlpiOracleChgConsSides(SCIP_NLPIORACLE *oracle, int nconss, const int *indices, const SCIP_Real *lhss, const SCIP_Real *rhss)
Definition: nlpioracle.c:1680
#define BMSclearMemory(ptr)
Definition: memory.h:111
SCIP_RETCODE SCIPexprintGrad(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Bool new_varvals, SCIP_Real *val, SCIP_Real *gradient)
SCIP_Real infinity
Definition: nlpioracle.c:60
static void freeConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:453
static SCIP_RETCODE ensureConsQuadSize(BMS_BLKMEM *blkmem, SCIP_NLPIORACLECONS *cons, int minsize)
Definition: nlpioracle.c:192
#define SCIP_CALL_QUIET(x)
Definition: def.h:325
SCIP_RETCODE SCIPnlpiOracleDelVarSet(SCIP_NLPIORACLE *oracle, int *delstats)
Definition: nlpioracle.c:1714
char * SCIPnlpiOracleGetConstraintName(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2302
#define SCIP_DEFAULT_INFINITY
Definition: def.h:154
SCIP_QUADELEM * quadelems
Definition: nlpioracle.c:48
int * vardegrees
Definition: nlpioracle.c:68
SCIP_RETCODE SCIPnlpiOracleChgExprParam(SCIP_NLPIORACLE *oracle, int considx, int paramidx, SCIP_Real paramval)
Definition: nlpioracle.c:2154
int SCIPnlpiOracleGetVarDegree(SCIP_NLPIORACLE *oracle, int varidx)
Definition: nlpioracle.c:2247
SCIP_RETCODE SCIPnlpiOracleEvalHessianLag(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real objfactor, const SCIP_Real *lambda, SCIP_Real *hessian)
Definition: nlpioracle.c:2889
public methods for message output
SCIP_Bool vardegreesuptodate
Definition: nlpioracle.c:69
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
#define SCIP_Real
Definition: def.h:149
#define BMSallocMemory(ptr)
Definition: memory.h:101
SCIP_EXPRINT * exprinterpreter
Definition: nlpioracle.c:84
SCIP_RETCODE SCIPexprintHessianSparsityDense(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Bool *sparsity)
SCIP_RETCODE SCIPnlpiOracleSetInfinity(SCIP_NLPIORACLE *oracle, SCIP_Real infinity)
Definition: nlpioracle.c:1381
#define SCIPisFinite(x)
Definition: pub_misc.h:1768
int SCIPexprtreeGetNParams(SCIP_EXPRTREE *tree)
Definition: expr.c:8622
BMS_BLKMEM * blkmem
Definition: nlpioracle.c:59
SCIP_RETCODE SCIPnlpiOracleEvalJacobian(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *convals, SCIP_Real *jacobi)
Definition: nlpioracle.c:2651
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:433
SCIP_RETCODE SCIPexprintFree(SCIP_EXPRINT **exprint)
SCIP_EXPRTREE * exprtree
Definition: nlpioracle.c:51
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
char ** SCIPnlpiOracleGetVarNames(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2235
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
#define SCIP_ALLOC(x)
Definition: def.h:361
int * SCIPnlpiOracleGetVarDegrees(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2264
void SCIPsortedvecInsertInt(int *intarray, int keyval, int *len, int *pos)
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:439
int * heslagcols
Definition: nlpioracle.c:81
int SCIPnlpiOracleGetMaxDegree(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2349
SCIP_NLPIORACLECONS ** conss
Definition: nlpioracle.c:73
void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)