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