SCIP Doxygen Documentation
Loading...
Searching...
No Matches
nlpi_conopt.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 nlpi_conopt.c
26 * @ingroup DEFPLUGINS_NLPI
27 * @brief CONOPT NLP interface
28 * @author Ksenia Bestuzheva
29 *
30 * NLP interface for the CONOPT solver.
31 *
32 * This file can only be compiled if CONOPT is available.
33 * Otherwise, to resolve public functions, use nlpi_conopt_dummy.c.
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
38#include "scip/nlpi_conopt.h"
39#include "scip/nlpioracle.h"
40#include "scip/scip_mem.h"
41#include "scip/scip_numerics.h"
42#include "scip/scip_nlp.h"
43#include "scip/scip_nlpi.h"
45#include "scip/pub_misc.h"
46#include "scip/pub_message.h"
47#include "scip/type_clock.h"
48#include "scip/scip_general.h"
49
50#include "scip/scip_message.h"
51#include "scip/scip_timing.h"
52
53#include "conopt.h"
54
55#define NLPI_NAME "conopt" /**< short concise name of solver */
56#define NLPI_DESC "CONOPT interface" /**< description of solver */
57#define NLPI_PRIORITY 2000 /**< priority of NLP solver */
58
59#define DEFAULT_RANDSEED 107 /**< initial random seed */
60#define MAXPERTURB 0.01 /**< maximal perturbation of bounds in starting point heuristic */
61
62/*
63 * Data structures
64 */
65
66struct SCIP_NlpiData
67{
68 SCIP_CLOCK* solvetime; /**< clock for measuring solving time */
69 int license_int_1; /**< integer 1 of CONOPT license */
70 int license_int_2; /**< integer 2 of CONOPT license */
71 int license_int_3; /**< integer 3 of CONOPT license */
72 char license_text[81]; /**< text of CONOPT license */
73};
74
76{
77 SCIP* scip; /**< SCIP data structure */
78 SCIP_NLPIORACLE* oracle; /**< Oracle-helper to store and evaluate NLP */
79 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
80
81 SCIP_Bool firstrun; /**< whether the next NLP solve will be the first one (with the current problem structure) */
82 SCIP_Real* initguess; /**< initial values for primal variables, or NULL if not known */
83
84 SCIP_NLPSOLSTAT solstat; /**< solution status from last NLP solve */
85 SCIP_NLPTERMSTAT termstat; /**< termination status from last NLP solve */
86 SCIP_Real solvetime; /**< time spend for last NLP solve */
87 int niterations; /**< number of iterations for last NLP solve */
88 SCIP_Real objval; /**< objective value from last run */
89
90 SCIP_Real* lastprimal; /**< primal solution from last run, if available */
91 SCIP_Real* lastdualcons; /**< dual solution from last run, if available */
92 SCIP_Real* lastduallb; /**< dual solution for lower bounds from last run, if available */
93 SCIP_Real* lastdualub; /**< dual solution for upper bounds from last run, if available */
94 int varsolsize; /**< size of solution values arrays corresponding to variables */
95 int conssolsize; /**< size of solution values array corresponding to constraints */
96
97 coiHandle_t CntVect; /**< pointer to CONOPT Control Vector */
98
99 /* options that will be passed to CONOPT via callbacks */
100 int verblevel; /**< verbosity level, same as in SCIP_NlpParam: 0 off, 1 normal, 2 debug, > 2 more debug */
101 SCIP_Real opttol; /**< optimality tolerance */
102
103 /* statistics */
104 int ncalls; /**< overall number of solver calls */
105 int nsuccess; /**< number of successes (optimal or feasible solution found or proven unbounded) */
106 int nlocinfeas; /**< number of calls resulting in local infeasibility */
107 int nother; /**< number of other calls */
108 int nlimit; /**< number of calls where the solver terminated due to a time or iteration limit */
109};
110
111/*
112 * Local methods
113 */
114
115/** Implementations of CONOPT callbacks */
116
117/** CONOPT callback to pass solution back to SCIP
118 *
119 * The dual values are multiplied by -1, since CONOPT's definition of marginal values is 'by
120 * how much the objective increases if we increase the constraint side by +eps', which, for
121 * minimisation problems (which is always the case here), is the negative of what SCIP expects.
122 */
123static int COI_CALLCONV Solution(
124 const double XVAL[], /**< solution values of the variables (provided by CONOPT) */
125 const double XMAR[], /**< marginal values (provided by CONOPT) */
126 const int XBAS[], /**< basis indicators for the variables (provided by CONOPT) */
127 const int XSTA[], /**< status values for the variables (provided by CONOPT) */
128 const double YVAL[], /**< values of the left hand sides of all rows in the optimal solution (provided by CONOPT) */
129 const double YMAR[], /**< marginal values corresponding to rows (provided by CONOPT) */
130 const int YBAS[], /**< basis indicators for the rows or constraints (provided by CONOPT) */
131 const int YSTA[], /**< status values for the rows or constraints (provided by CONOPT) */
132 int NUMVAR, /**< number of variables (provided by CONOPT) */
133 int NUMCON, /**< number of constraints (provided by CONOPT) */
134 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
135 )
136{
137 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
138 int noraclevars;
139 int noracleconss;
140
141 assert(problem != NULL);
142 assert(problem->oracle != NULL);
143
144 noraclevars = SCIPnlpiOracleGetNVars(problem->oracle);
145 noracleconss = SCIPnlpiOracleGetNConstraints(problem->oracle);
146
147 /* number of SCIP variables always less or equal, since CONOPT variables can also contain slack variables */
148 assert(NUMVAR >= noraclevars);
149
150 /* CONOPT has one more constraint than oracle (the objective) */
151 assert(NUMCON == noracleconss + 1);
152
153 /* copy values from CONOPT into SCIP arrays. Note that in CONOPT, there is one
154 * extra constraint (the objective) and slack variables that are not explicitly
155 * present in SCIP, which the code below does not copy */
156 if( problem->lastprimal == NULL )
157 {
158 if( NUMVAR > 0 )
159 {
160 if( SCIPduplicateBlockMemoryArray(problem->scip, &problem->lastprimal, XVAL, noraclevars) != SCIP_OKAY ||
161 SCIPallocClearBlockMemoryArray(problem->scip, &problem->lastduallb, noraclevars) != SCIP_OKAY ||
162 SCIPallocClearBlockMemoryArray(problem->scip, &problem->lastdualub, noraclevars) != SCIP_OKAY )
163 {
164 SCIPerrorMessage("Failed to allocate memory for a solution from CONOPT\n");
165 return 1;
166 }
167 problem->varsolsize = noraclevars;
168 }
169 if( NUMCON > 0 )
170 {
171 if( SCIPduplicateBlockMemoryArray(problem->scip, &problem->lastdualcons, YMAR, noracleconss) != SCIP_OKAY )
172 {
173 SCIPerrorMessage("Failed to allocate memory for a solution from CONOPT\n");
174 return 1;
175 }
176 problem->conssolsize = noracleconss;
177 }
178 }
179 else
180 {
181 assert(noraclevars <= problem->varsolsize);
182 assert(noracleconss <= problem->conssolsize);
183 BMScopyMemoryArray(problem->lastprimal, XVAL, noraclevars);
184 BMSclearMemoryArray(problem->lastduallb, noraclevars);
185 BMSclearMemoryArray(problem->lastdualub, noraclevars);
186 BMScopyMemoryArray(problem->lastdualcons, YMAR, noracleconss);
187 }
188
189 /* replace initial guess with the obtained solution */
190 if( problem->lastprimal != NULL )
191 {
192 if( problem->initguess == NULL )
193 {
194 if( SCIPduplicateMemoryArray(problem->scip, &problem->initguess, problem->lastprimal, noraclevars) != SCIP_OKAY )
195 {
196 SCIPerrorMessage("Failed to allocate memory for an initial guess from\n");
197 return 1;
198 }
199 }
200 else
201 BMScopyMemoryArray(problem->initguess, problem->lastprimal, noraclevars);
202 }
203
204 /* get dual multipliers for variable bounds */
205 for( int i = 0; i < noraclevars; i++ )
206 {
207 if( XBAS[i] == 0 ) /* Xi is at lower bound */
208 problem->lastduallb[i] = -XMAR[i];
209 else if( XBAS[i] == 1 ) /* Xi is at upper bound */
210 problem->lastdualub[i] = -XMAR[i];
211 }
212
213 for( int i = 0; i < NUMCON-1; i++ )
214 (problem->lastdualcons[i]) *= -1;
215
216 return 0;
217} /*lint !e715*/
218
219/** CONOPT callback to pass variable bounds, constraint types and sides
220 * and Jacobian structure and constant values to CONOPT
221 */
222static int COI_CALLCONV ReadMatrix(
223 double LOWER[], /**< lower bounds on the variables (set to CONOPT's minus infinity before callback is issued */
224 double CURR[], /**< initial values of the variables (set to zero before callback is issued */
225 double UPPER[], /**< upper bounds on the variables (set to CONOPT's plus infinity before callback is issued */
226 int VSTA[], /**< initial status values for the variable (used if coidef_inistat() was called with IniStat = 1 or 2) */
227 int TYPE[], /**< constraint types (equation, inequality, free) */
228 double RHS[], /**< right hand sides values of constraints (default is zero) */
229 int ESTA[], /**< initial status values for constraint slacks (used if coidef_inistat() was called with IniStat = 1 or 2) */
230 int COLSTA[], /**< starting indices of Jacobian columns in ROWNO */
231 int ROWNO[], /**< row numbers of Jacobian nonzeros */
232 double VALUE[], /**< values of the Jacobian elements (defined for all constant Jacobian elements) */
233 int NLFLAG[], /**< flags marking nonlinear Jacobian elements (following the same sparse representation as ROWNO) */
234 int NUMVAR, /**< number of variables as defined in COIDEF_NumVar() */
235 int NUMCON, /**< number of constraints as defined in COIDEF_NumCon() */
236 int NUMNZ, /**< number of Jacobian elements as defined in COIDEF_NumNz() */
237 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
238 )
239{
240 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
241 SCIP* scip;
242 SCIP_NLPIORACLE* oracle;
243 const SCIP_Real* lbs;
244 const SCIP_Real* ubs;
245 int norigvars;
246 int nslackvars = 0;
247 int njacnlnnz;
248 int* rangeconsidxs = NULL;
249 const SCIP_Bool* jacrownlflags;
250 const int* jaccoloffsets;
251 const int* jacrows;
252 int nobjnz;
253 const int* objnz;
254 const SCIP_Bool* objnlflags;
255 int nobjnlnz;
256 int objnzcnt = 0;
257 int* nrownz;
258 SCIP_RETCODE retcode;
259
260 assert(problem != NULL);
261
262 oracle = problem->oracle;
263 assert(oracle != NULL);
264
265 scip = problem->scip;
266 assert(scip != NULL);
267
268 SCIPdebugMsg(scip, "NLP sizes passed to CONOPT: NUMVAR = %d, NUMCON = %d, NUMNZ = %d\n", NUMVAR, NUMCON, NUMNZ);
269
270 norigvars = SCIPnlpiOracleGetNVars(oracle);
271 lbs = SCIPnlpiOracleGetVarLbs(oracle);
272 ubs = SCIPnlpiOracleGetVarUbs(oracle);
273
274 /* save indices of range constraints if there are any */
275 if( NUMVAR - norigvars > 0 )
276 {
277 retcode = SCIPallocBufferArray(scip, &rangeconsidxs, NUMVAR - norigvars);
278 if( retcode != SCIP_OKAY )
279 {
280 SCIPerrorMessage("No memory in a callback of CONOPT\n");
281 return 1;
282 }
283 }
284
285 /* add all 'normal' (i.e. non-slack) variables here */
286 for( int i = 0; i < norigvars; i++ )
287 {
288 if( !SCIPisInfinity(scip, -lbs[i]) )
289 LOWER[i] = lbs[i];
290 if( !SCIPisInfinity(scip, ubs[i]) )
291 UPPER[i] = ubs[i];
292 }
293
294 /* specify initial values of original variables,
295 * (if there is a previous solution, it is stored in initguess) */
296 if( problem->initguess != NULL )
297 {
298 BMScopyMemoryArray(CURR, problem->initguess, norigvars);
299
300 /* some values may have been set outside the bounds - project them */
301 for( int i = 0; i < norigvars; ++i )
302 {
303 if( lbs[i] > CURR[i] )
304 CURR[i] = SCIPrandomGetReal(problem->randnumgen, lbs[i], lbs[i] + MAXPERTURB*MIN(1.0, ubs[i]-lbs[i]));
305 else if( ubs[i] < CURR[i] )
306 CURR[i] = SCIPrandomGetReal(problem->randnumgen, ubs[i] - MAXPERTURB*MIN(1.0, ubs[i]-lbs[i]), ubs[i]);
307 }
308 }
309 else
310 {
311 /* if no initial guess given, project 0 onto variable bounds */
312 assert(problem->randnumgen != NULL);
313
314 SCIPdebugMsg(scip, "CONOPT started without initial primal values; make up starting guess by projecting 0 onto variable bounds\n");
315
316 for( int i = 0; i < norigvars; ++i )
317 {
318 if( lbs[i] > 0.0 )
319 CURR[i] = SCIPrandomGetReal(problem->randnumgen, lbs[i], lbs[i] + MAXPERTURB*MIN(1.0, ubs[i]-lbs[i]));
320 else if( ubs[i] < 0.0 )
321 CURR[i] = SCIPrandomGetReal(problem->randnumgen, ubs[i] - MAXPERTURB*MIN(1.0, ubs[i]-lbs[i]), ubs[i]);
322 else
323 CURR[i] = SCIPrandomGetReal(problem->randnumgen,
324 MAX(lbs[i], -MAXPERTURB*MIN(1.0, ubs[i]-lbs[i])), MIN(ubs[i], MAXPERTURB*MIN(1.0, ubs[i]-lbs[i])));
325 }
326 }
327
328 for( int i = 0; i < NUMCON-1; i++ )
329 {
332
333 assert(lhs <= rhs);
334
335 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
336 {
337 TYPE[i] = 0; /* an equality or a ranged row modelled as equality */
338
339 if( !SCIPisEQ(scip, lhs, rhs) )
340 {
341 assert(rangeconsidxs != NULL);
342
343 /* range constraint lhs <= g(x) <= rhs: reformulate as g(x) - s = 0 and lhs <= s <= rhs */
344 RHS[i] = 0.0;
345 LOWER[norigvars + nslackvars] = lhs;
346 UPPER[norigvars + nslackvars] = rhs;
347
348 /* set initial value of slack variable */
349 if( lhs > 0.0 )
350 CURR[norigvars + nslackvars] = SCIPrandomGetReal(problem->randnumgen, lhs, lhs + MAXPERTURB*MIN(1.0, rhs-lhs));
351 else if( rhs < 0.0 )
352 CURR[norigvars + nslackvars] = SCIPrandomGetReal(problem->randnumgen, rhs - MAXPERTURB*MIN(1.0, rhs-lhs), rhs);
353 else
354 CURR[norigvars + nslackvars] = SCIPrandomGetReal(problem->randnumgen,
355 MAX(lhs, -MAXPERTURB*MIN(1.0, rhs-lhs)), MIN(rhs, MAXPERTURB*MIN(1.0, rhs-lhs)));
356
357 rangeconsidxs[nslackvars] = i;
358 nslackvars++;
359 }
360 else
361 RHS[i] = lhs;
362 }
363 else if( !SCIPisInfinity(scip, -lhs) )
364 {
365 TYPE[i] = 1;
366 RHS[i] = lhs;
367 }
368 else if( !SCIPisInfinity(scip, rhs) )
369 {
370 TYPE[i] = 2;
371 RHS[i] = rhs;
372 }
373 else
374 TYPE[i] = 3;
375 }
376 assert(norigvars + nslackvars == NUMVAR);
377
378 /* the last constraint is the objective */
379 TYPE[NUMCON-1] = 3; /* objective must be a free row */
380 RHS[NUMCON-1] = 0.0;
381
382 /* Jacobian information */
383
384 retcode = SCIPnlpiOracleGetJacobianColSparsity(scip, oracle, &jaccoloffsets, &jacrows, &jacrownlflags, &njacnlnnz);
385 if( retcode != SCIP_OKAY )
386 {
387 SCIPerrorMessage("Error in Jacobian sparsity computation\n");
388 return 2;
389 }
390 assert(jaccoloffsets == NULL || jaccoloffsets[norigvars] <= NUMNZ);
391
392 /* move structure info into COLSTA and ROWNO; while doing so, also add nonzeroes for the objective
393 * (which CONOPT sees as the last constraint, i.e. constraint with index NUMCON-1) */
394 retcode = SCIPallocCleanBufferArray(scip, &nrownz, NUMCON);
395 if( retcode != SCIP_OKAY )
396 {
397 SCIPerrorMessage("No memory in a callback of CONOPT\n");
398 return 1;
399 }
400
401 retcode = SCIPnlpiOracleGetObjGradientNnz(scip, oracle, &objnz, &objnlflags, &nobjnz, &nobjnlnz);
402 assert(nobjnz > 0 || objnz == NULL);
403 if( retcode != SCIP_OKAY )
404 {
405 SCIPerrorMessage("Error in the ReadMatrix callback of CONOPT\n");
406 return 2;
407 }
408
409 for( int i = 0; i < norigvars; i++ )
410 {
411 /* starts of columns get shifted by how many objective nonzeros were added */
412 COLSTA[i] = jaccoloffsets != NULL ? jaccoloffsets[i] + objnzcnt : objnzcnt;
413
414 if( jaccoloffsets != NULL )
415 {
416 /* nonzeroes of constraints */
417 for( int j = jaccoloffsets[i]; j < jaccoloffsets[i+1]; j++ )
418 {
419 ROWNO[j+objnzcnt] = jacrows[j];
420 NLFLAG[j+objnzcnt] = jacrownlflags[j] ? 1 : 0;
421 if( NLFLAG[j+objnzcnt] == 0 )
422 {
423 /* for linear terms, compute the (constant) Jacobian values */
424 VALUE[j+objnzcnt] = SCIPnlpiOracleGetConstraintLinearCoef(oracle, jacrows[j], nrownz[jacrows[j]]);
425 ++(nrownz[jacrows[j]]);
426 }
427 }
428 }
429
430 /* nonzeroes of objective */
431 if( objnz != NULL && objnzcnt < nobjnz && i == objnz[objnzcnt] )
432 {
433 int idx = jaccoloffsets != NULL ? jaccoloffsets[i+1] + objnzcnt : objnzcnt;
434
435 ROWNO[idx] = NUMCON - 1;
436 NLFLAG[idx] = objnlflags[objnzcnt] ? 1 : 0;
437 if( NLFLAG[idx] == 0 )
438 {
439 /* in the oracle, index -1 is used for the objective */
440 VALUE[idx] = SCIPnlpiOracleGetConstraintLinearCoef(oracle, -1, nrownz[NUMCON-1]);
441 ++(nrownz[NUMCON-1]);
442 }
443 ++objnzcnt;
444 }
445 }
446 assert(COLSTA[0] == 0);
447 COLSTA[norigvars] = jaccoloffsets != NULL ? jaccoloffsets[norigvars] + objnzcnt : objnzcnt;
448 BMSclearMemoryArray(nrownz, NUMCON);
450
451 if( nslackvars > 0 )
452 {
453 /* add a nonzero for each slack variable */
454 for( int i = 0; i < nslackvars; i++ )
455 {
456 COLSTA[norigvars+i] = COLSTA[norigvars] + i; /* for each slack var, only one nonzero is added */
457 ROWNO[COLSTA[norigvars+i]] = rangeconsidxs[i];
458 NLFLAG[COLSTA[norigvars+i]] = 0;
459 VALUE[COLSTA[norigvars+i]] = -1.0;
460 }
461 SCIPfreeBufferArray(scip, &rangeconsidxs);
462 COLSTA[NUMVAR] = NUMNZ;
463 }
464
465#ifndef NDEBUG
466 for( int i = 0; i < NUMNZ; ++i )
467 assert(ROWNO[i] >= 0 && ROWNO[i] < NUMCON);
468#endif
469
470#ifdef STRUCTURE_DEBUG
471 SCIPdebugMsg(scip, "Jacobian structure information:\n");
472 SCIPdebugMsg(scip, "COLSTA = ");
473 for( int i = 0; i <= NUMVAR; i++ )
474 SCIPdebugMsgPrint(scip, "%d, ", COLSTA[i]);
475 SCIPdebugMsgPrint(scip, "\n");
476
477 SCIPdebugMsg(scip, "ROWNO = ");
478 for( int i = 0; i < NUMNZ; i++ )
479 SCIPdebugMsgPrint(scip, "%d, ", ROWNO[i]);
480 SCIPdebugMsgPrint(scip, "\n");
481
482 SCIPdebugMsg(scip, "NLFLAG = ");
483 for( int i = 0; i < NUMNZ; i++ )
484 SCIPdebugMsgPrint(scip, "%d, ", NLFLAG[i]);
485 SCIPdebugMsgPrint(scip, "\n");
486
487 SCIPdebugMsg(scip, "VALUE = ");
488 for( int i = 0; i < NUMNZ; i++ )
489 if( VALUE[i] == 1.234e34 ) /*lint !e777*/ /* CONOPT's special value for "undefined" */
490 SCIPdebugMsgPrint(scip, "undef, ");
491 else
492 SCIPdebugMsgPrint(scip, "%g, ", VALUE[i]);
493 SCIPdebugMsgPrint(scip, "\n");
494 /*
495 for( int i = 0; i < NUMVAR; i++ )
496 {
497 SCIPdebugMsg(scip, "var %d:", i);
498 for( int j = COLSTA[i]; j < COLSTA[i+1]; ++j )
499 SCIPdebugMsgPrint(scip, " %d", ROWNO[j]);
500 SCIPdebugMsgPrint(scip, "\n");
501 }
502 */
503 fflush(stdout);
504#endif
505
506 return 0;
507} /*lint !e715*/
508
509/** callback for CONOPT's standard output */
510static int COI_CALLCONV Message(
511 int SMSG, /**< number of lines in the message that should go to the Screen file, between 0 and 30 */
512 int DMSG, /**< number of lines in the message that should go to the Status file, between 0 and 30 */
513 int NMSG, /**< number of lines in the message that should go to the Documentation file, between 0 and 30 */
514 char* MSGV[], /**< array with the lengths of the individual message lines, the lengths are between 1 and 132 */
515 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
516 )
517{
518 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
519
520 assert(problem != NULL);
521 assert(problem->scip != NULL);
522 assert(NMSG <= DMSG); /* conopt docu says that NMSG is always <= DMSG */
523
524 switch( problem->verblevel )
525 {
526 case 0:
527 break;
528 case 1:
529 for( int i = 0; i < SMSG; i++ )
530 SCIPinfoMessage(problem->scip, NULL, "%s\n", MSGV[i]);
531 break;
532 default:
533 for( int i = 0; i < SMSG || i < DMSG; i++ )
534 SCIPinfoMessage(problem->scip, NULL, "%s\n", MSGV[i]);
535 break;
536 }
537
538 return 0;
539} /*lint !e715*/
540
541/** callback for CONOPT's standard error output */
542static int COI_CALLCONV ErrMsg(
543 int ROWNO, /**< number of row */
544 int COLNO, /**< number of column */
545 int POSNO, /**< number of a Jacobian element */
546 const char* MSG, /**< the message */
547 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
548 )
549{
550 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
551
552 if( problem->verblevel > 0 )
553 {
554 if( ROWNO == -1 && COLNO == -1 )
555 SCIPinfoMessage(problem->scip, NULL, "\nCONOPT error/warning: Jacobian element %d: ", POSNO);
556 else if( ROWNO == -1 )
557 SCIPinfoMessage(problem->scip, NULL, "\nCONOPT error/warning: variable %d: ", COLNO);
558 else if( COLNO == -1 )
559 SCIPinfoMessage(problem->scip, NULL, "\nCONOPT error/warning: constraint %d: ", ROWNO);
560 else
561 SCIPinfoMessage(problem->scip, NULL, "\nCONOPT error/warning: variable %d appearing in constraint %d: ", COLNO, ROWNO);
562 SCIPinfoMessage(problem->scip, NULL, "%s\n", MSG);
563 }
564
565 return 0;
566}
567
568/** callback for CONOPT to report the solving statuses */
569static int COI_CALLCONV Status(
570 int MODSTA, /**< model status (corresponds to SCIP's solstat) */
571 int SOLSTA, /**< solver status (corresponds to SCIP's termstat) */
572 int ITER, /**< number of iterations */
573 double OBJVAL, /**< objective value */
574 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
575 )
576{
577 SCIP* scip;
578 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
579 SCIP_Bool other = FALSE;
580 SCIP_Bool limit = FALSE;
581
582 assert(problem != NULL);
583
584 scip = problem->scip;
585 assert(scip != NULL);
586
587 SCIPdebugMsg(scip, "CONOPT has finished optimizing\n");
588 SCIPdebugMsg(scip, "Iteration count = %8d\n", ITER);
589 SCIPdebugMsg(scip, "Objective value = %10f\n", OBJVAL);
590
591 problem->niterations = ITER;
592 problem->objval = OBJVAL;
593 ++(problem->ncalls);
594
595 switch( MODSTA )
596 {
597 case 1:
598 SCIPdebugMsg(scip, "NLP problem solved to global optimality\n");
600 ++(problem->nsuccess);
601 break;
602 case 2:
603 SCIPdebugMsg(scip, "NLP problem solved to local optimality\n");
605 ++(problem->nsuccess);
606 break;
607 case 3:
608 SCIPdebugMsg(scip, "NLP problem unbounded\n");
610 ++(problem->nsuccess);
611 break;
612 case 4:
613 SCIPdebugMsg(scip, "NLP problem infeasible\n");
615 ++(problem->nsuccess);
616 break;
617 case 5:
618 SCIPdebugMsg(scip, "NLP problem locally infeasible\n");
620 ++(problem->nlocinfeas);
621 break;
622 case 7: /* intermediate non-optimal */
624 break;
625 case 6: /* intermediate infeasible */
626 case 12: /* unknown error */
627 case 13:
628 SCIPdebugMsg(scip, "NLP problem status unknown (CONOPT status %d)\n", MODSTA);
630 other = TRUE;
631 break;
632 default:
633 SCIPerrorMessage("CONOPT returned an unexpected solution status %d\n", MODSTA);
635 other = TRUE;
636 }
637
638 switch( SOLSTA )
639 {
640 case 1:
642 SCIPdebugMsg(scip, "CONOPT terminated with normal status.\n");
643 break;
644 case 2:
646 SCIPdebugMsg(scip, "CONOPT terminated due to an iteration limit.\n");
647 limit = TRUE;
648 break;
649 case 3:
651 SCIPdebugMsg(scip, "CONOPT terminated due to a time limit.\n");
652 limit = TRUE;
653 break;
654 case 4: /* terminated by solver */
656 SCIPdebugMsg(scip, "CONOPT terminated due to numerical trouble.\n");
657 break;
658 case 5:
660 SCIPdebugMsg(scip, "CONOPT terminated due to evaluation errors.\n");
661 break;
662 case 8:
664 SCIPdebugMsg(scip, "CONOPT interrupted by user.\n");
665 break;
666 case 6: /* unknown */
667 case 9: /* error: setup failure */
668 case 10: /* error: solver failure */
669 case 11: /* error: internal solver error */
670 case 13: /* error: general system error */
671 SCIPdebugMsg(scip, "CONOPT terminated with status %d\n", SOLSTA);
673 break;
674 default:
675 SCIPerrorMessage("CONOPT returned an unexpected termination status %d\n", SOLSTA);
677 }
678
679 if( other )
680 {
681 if( limit )
682 ++(problem->nlimit);
683 else
684 ++(problem->nother);
685 }
686
687 return 0;
688}
689
690/** CONOPT callback for function and Jacobian evaluation
691 *
692 * The callback has three modes, indicated by MODE:
693 *
694 * 1: Only evaluate the sum of the nonlinear and linear terms in row ROWNO and return the value in G.
695 * 2: Only evaluate the nonlinear Jacobian elements in row ROWNO and return them in JAC.
696 * 3: Perform both option 1 and 2.
697 */
698static int COI_CALLCONV FDEval(
699 const double X[], /**< point of evaluation (provided by CONOPT) */
700 double* G, /**< value of the function */
701 double JAC[], /**< vector of Jacobian values */
702 int ROWNO, /**< number of the row for which nonlinearities are to be evaluated (provided by CONOPT) */
703 const int JACNUM[], /**< list of column numbers for the nonlinear nonzero Jacobian elements in
704 * the current row (provided by CONOPT when MODE = 2 or 3) */
705 int MODE, /**< indicator for mode of evaluation (provided by CONOPT) */
706 int IGNERR, /**< indicator whether CONOPT assumes the point to be safe (0) or potentially unsafe (1) */
707 int* ERRCNT, /**< scalar function evaluation error indicator (set to 1 if a function value cannot be computed */
708 int NUMVAR, /**< number of variables (provided by CONOPT) */
709 int NUMJAC, /**< number of nonlinear nonzero Jacobian elements in the current row */
710 int THREAD, /**< only relevant in multi-threading environments */
711 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
712 )
713{
714 SCIP_RETCODE retcode;
715 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
716
717 assert(problem != NULL);
718 assert(ROWNO <= SCIPnlpiOracleGetNConstraints(problem->oracle));
719
720 if( MODE == 1 )
721 {
722 /* the last 'constraint' is the objective */
723 retcode = ROWNO < SCIPnlpiOracleGetNConstraints(problem->oracle) ?
724 SCIPnlpiOracleEvalConstraintValue(problem->scip, problem->oracle, ROWNO, X, G) :
725 SCIPnlpiOracleEvalObjectiveValue(problem->scip, problem->oracle, X, G);
726 if( retcode != SCIP_OKAY || *G == SCIP_INVALID ) /*lint !e777*/
727 *ERRCNT = 1;
728 }
729
730 if( MODE == 2 || MODE == 3 )
731 {
732 /* the last 'constraint' is the objective */
733 retcode = ROWNO < SCIPnlpiOracleGetNConstraints(problem->oracle) ?
734 SCIPnlpiOracleEvalConstraintGradient(problem->scip, problem->oracle, ROWNO, X, TRUE, G, JAC) :
735 SCIPnlpiOracleEvalObjectiveGradient(problem->scip, problem->oracle, X, TRUE, G, JAC);
736 if( retcode != SCIP_OKAY )
737 *ERRCNT = 1;
738 }
739
740 return 0;
741} /*lint !e715*/
742
743/** CONOPT callback for function and Jacobian interval evaluation
744 *
745 * The callback has three modes, indicated by MODE:
746 *
747 * 1: Only evaluate the bounds on the sum of the nonlinear terms in row ROWNO and return the interval in [GMIN, GMAX].
748 * 2: Only evaluate the bounds on the nonlinear Jacobian elements in row ROWNO and return the intervals in [JMIN, JMAX].
749 * 3: Perform both option 1 and 2.
750 */
751static int COI_CALLCONV FDInterval(
752 const double XMIN[], /**< lower bound on variables (provided by CONOPT) */
753 const double XMAX[], /**< upper bound on variables (provided by CONOPT) */
754 double* GMIN, /**< buffer for lower bound on function value in constraint ROWNO */
755 double* GMAX, /**< buffer for lower bound on function value in constraint ROWNO */
756 double JMIN[], /**< buffer for lower bound on the derivatives of the function in constraint ROWNO */
757 double JMAX[], /**< buffer for upper bound on the derivatives of the function in constraint ROWNO */
758 int ROWNO, /**< number of the row for which nonlinearities are to be evaluated (provided by CONOPT) */
759 const int JACNUM[], /**< list of column numbers for the nonlinear nonzero Jacobian elements in
760 * the current row (provided by CONOPT when MODE = 2 or 3) */
761 int MODE, /**< indicator for mode of evaluation (provided by CONOPT) */
762 double PINF, /**< plus infinity (provided by CONOPT) */
763 int NUMVAR, /**< number of variables (provided by CONOPT) */
764 int NUMJAC, /**< number of nonlinear nonzero Jacobian elements in the current row */
765 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
766 )
767{
768 SCIP_RETCODE retcode;
769 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
770
771 assert(problem != NULL);
772 assert(ROWNO <= SCIPnlpiOracleGetNConstraints(problem->oracle));
773
774 /* currently do not having interval derivatives, so just return for MODE == 2
775 * (CONOPT has initialized JMIN/JMAX to -/+PINF)
776 */
777 if( MODE == 2 )
778 return 0;
779
780 if( ROWNO < SCIPnlpiOracleGetNConstraints(problem->oracle) )
781 {
782 retcode = SCIPnlpiOracleEvalConstraintInterval(problem->scip, problem->oracle, PINF, ROWNO, XMIN, XMAX, GMIN, GMAX);
783 }
784 else
785 {
786 retcode = SCIPnlpiOracleEvalObjectiveInterval(problem->scip, problem->oracle, PINF, XMIN, XMAX, GMIN, GMAX);
787 }
788
789 if( retcode != SCIP_OKAY )
790 {
791 *GMIN = -PINF;
792 *GMAX = PINF;
793 }
794
795 return 0;
796} /*lint !e715*/
797
798/** CONOPT callback to pass some of the options (not supported via COIDEF_* functions) to CONOPT */
799static int COI_CALLCONV Option(
800 int NCALL, /**< number of callback call (provided by CONOPT) */
801 double* RVAL, /**< pointer to set the value of a real option */
802 int* IVAL, /**< pointer to set the value of an integer option */
803 int* LVAL, /**< pointer to set the value of a binary option */
804 char* NAME, /**< pointer to set the name of the option */
805 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
806 )
807{
808 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
809
810 assert(problem != NULL);
811
812 switch( NCALL )
813 {
814 case 0: /* information about stopping criteria */
815 strcpy(NAME, "LOCNPT");
816 if( problem->verblevel >= 2 )
817 *IVAL = 1;
818 else
819 *IVAL = 0;
820 break;
821 case 1: /* optimality tolerance */
822 strcpy(NAME, "RTREDG");
823 *RVAL = problem->opttol;
824 break;
825 case 2: /* turn definitional constraints off for now (conopt#103) */
826 strcpy(NAME, "Flg_NoDefc");
827 *LVAL = 1;
828 break;
829 default:
830 *NAME = '\0';
831 }
832
833 return 0;
834} /*lint !e715*/
835
836/** CONOPT callback to define structure of the Hessian of the Lagrangian */
837static int COI_CALLCONV LagrStr(
838 int HSRW[], /**< row numbers of the lower triangular part of the Hessian */
839 int HSCL[], /**< column numbers of the lower triangular part of the Hessian; elements must be
840 * sorted column-wise, and within each column, row-wise */
841 int* NODRV, /**< can be set to 1 if the derivatives could not be computed */
842 int NUMVAR, /**< number of variables as defined in coidef_numvar() (provided by CONOPT) */
843 int NUMCON, /**< number of constraints as defined in coidef_numcon() (provided by CONOPT) */
844 int NHESS, /**< number of nonzero elements in the Hessian (provided by CONOPT) */
845 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
846 )
847{
848 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
849 const int* hessoffsets;
850 const int* rows;
851 int col = 0;
852
853 assert(problem != NULL);
854
855 if( SCIPnlpiOracleGetHessianLagSparsity(problem->scip, problem->oracle, &hessoffsets, &rows, TRUE) != SCIP_OKAY )
856 {
857 *NODRV = 1;
858 return 0;
859 }
860
861 for( int i = 0; i < NHESS; i++ )
862 {
863 /* check if it's time to switch to the next row (this will also skip empty rows) */
864 while( i == hessoffsets[col+1] )
865 col++;
866
867 HSRW[i] = rows[i];
868 HSCL[i] = col;
869 }
870
871 return 0;
872} /*lint !e715*/
873
874/** CONOPT callback to compute the Hessian of the Lagrangian
875 *
876 * the Lagrangian is written as L = sum_{r in rows}U[r] * function(r)
877 */
878static int COI_CALLCONV LagrVal(
879 const double X[], /**< point in which the Hessian should be computed (provided by CONOPT) */
880 const double U[], /**< vector of weights on the individual constraints (provided by CONOPT) */
881 const int HSRW[], /**< row numbers of the lower triangular part of the Hessian (provided by CONOPT) */
882 const int HSCL[], /**< column numbers of the lower triangular part of the Hessian; elements must be
883 * sorted column-wise, and within each column, row-wise (provided by CONOPT) */
884 double HSVL[], /**< values of Hessian entries */
885 int* NODRV, /**< can be set to 1 if the derivatives could not be computed */
886 int NUMVAR, /**< number of variables as defined in coidef_numvar() (provided by CONOPT) */
887 int NUMCON, /**< number of constraints as defined in coidef_numcon() (provided by CONOPT) */
888 int NHESS, /**< number of nonzero elements in the Hessian (provided by CONOPT) */
889 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
890 )
891{
892 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
893
894 assert(problem != NULL);
895
896 /* TODO better handling for isnew? */
897 if( SCIPnlpiOracleEvalHessianLag(problem->scip, problem->oracle, X, TRUE, TRUE, U[NUMCON-1], U, HSVL, TRUE)
898 != SCIP_OKAY )
899 *NODRV = 1;
900
901 return 0;
902} /*lint !e715*/
903
904/* NLPI local methods */
905
906/** frees solution arrays and sets the solstat and termstat to unknown and other, resp. */
907static
909 SCIP_NLPIPROBLEM* problem /**< data structure of problem */
910 )
911{
912 assert(problem != NULL);
913
914 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastprimal), problem->varsolsize);
915 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastdualcons), problem->conssolsize);
916 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastduallb), problem->varsolsize);
917 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastdualub), problem->varsolsize);
918 problem->varsolsize = 0;
919 problem->conssolsize = 0;
920
923}
924
926 SCIP* scip, /**< SCIP data structure */
927 SCIP_NLPIDATA* data, /**< pointer to NLPIDATA structure */
928 SCIP_NLPIPROBLEM* problem /**< pointer to NLPI problem structure */
929 )
930{
931 int COI_Error = 0; /* CONOPT error counter */
932 int nrangeconss = 0;
933 int nconss;
934 int nvars;
935 const int* jacoffsets;
936 const int* hessoffsets;
937 int nnlnz;
938 const int* objgradnz;
939 const SCIP_Bool* objnl;
940 int nobjgradnz;
941 int nobjgradnls;
942
943 assert(data != NULL);
944 assert(problem != NULL);
945 assert(problem->oracle != NULL);
946
947 if( data->solvetime == NULL )
948 if( data->solvetime == NULL )
949 {
950 SCIP_CALL( SCIPcreateClock(scip, &(data->solvetime)) );
951 }
952
953 nconss = SCIPnlpiOracleGetNConstraints(problem->oracle);
955
956 /* count range constraints: because CONOPT doesn't support them directly, will need to add a slack variable for each ranged constraint */
957 for( int i = 0; i < nconss; i++ )
958 {
961
962 if( !SCIPisInfinity(problem->scip, -lhs) && !SCIPisInfinity(problem->scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
963 nrangeconss++;
964 }
965
966 /* tell CONOPT that we may have empty columns */
967 COI_Error += COIDEF_EmptyCol(problem->CntVect, 1);
968
969 /* inform CONOPT about problem sizes */
970 COI_Error += COIDEF_NumVar(problem->CntVect, nvars + nrangeconss);
971 COI_Error += COIDEF_NumCon(problem->CntVect, nconss + 1); /* objective counts as another constraint here */
972
973 /* jacobian information */
974 SCIP_CALL( SCIPnlpiOracleGetJacobianColSparsity(scip, problem->oracle, &jacoffsets, NULL, NULL, &nnlnz) );
975 SCIP_CALL( SCIPnlpiOracleGetObjGradientNnz(scip, problem->oracle, &objgradnz, &objnl, &nobjgradnz, &nobjgradnls) );
976
977 /* each slack var adds a Jacobian nnz; objective also counts as constraint */
978 COI_Error += COIDEF_NumNz(problem->CntVect, jacoffsets != NULL ? jacoffsets[nvars] + nrangeconss + nobjgradnz :
979 nrangeconss + nobjgradnz);
980
981 /* Jacobian nonzeroes include those of constraints and objective */
982 COI_Error += COIDEF_NumNlNz(problem->CntVect, nnlnz + nobjgradnls);
983
984 /* hessian sparsity information */
986 COI_Error += COIDEF_NumHess(problem->CntVect, hessoffsets[nvars]);
987
988 /* tell CONOPT to minimise the objective (the oracle always gives a minimisation problem) */
989 COI_Error += COIDEF_OptDir(problem->CntVect, -1);
990
991 /* oracle gives objective as a constraint, hence use ObjCon (not ObjVar) here;
992 * we treat objective as the last constraint, hence index nconss */
993 COI_Error += COIDEF_ObjCon(problem->CntVect, nconss);
994
995 /* register callback routines */
996 COI_Error += COIDEF_Message(problem->CntVect, Message);
997 COI_Error += COIDEF_ErrMsg(problem->CntVect, ErrMsg);
998 COI_Error += COIDEF_Status(problem->CntVect, Status);
999 COI_Error += COIDEF_Solution(problem->CntVect, Solution);
1000 COI_Error += COIDEF_ReadMatrix(problem->CntVect, ReadMatrix);
1001 COI_Error += COIDEF_FDEval(problem->CntVect, FDEval);
1002 COI_Error += COIDEF_FDInterval(problem->CntVect, FDInterval);
1003 COI_Error += COIDEF_Option(problem->CntVect, Option);
1004 COI_Error += COIDEF_2DLagrStr(problem->CntVect, LagrStr);
1005 COI_Error += COIDEF_2DLagrVal(problem->CntVect, LagrVal);
1006
1007 /* tell CONOPT that our function evaluations include the linear terms */
1008 COI_Error += COIDEF_FVincLin(problem->CntVect, 1);
1009
1010 /* pass the problem pointer to CONOPT, so that it may be used in CONOPT callbacks */
1011 COI_Error += COIDEF_UsrMem(problem->CntVect, (void*)problem);
1012
1013 /* register license, if available */
1014 if( data->license_text[0] != '\0' )
1015 COI_Error += COIDEF_License(problem->CntVect, data->license_int_1, data->license_int_2, data->license_int_3, data->license_text);
1016
1017 if( COI_Error )
1018 SCIPinfoMessage(scip, NULL, "Error %d encountered during initialising CONOPT\n", COI_Error);
1019
1020 return SCIP_OKAY;
1021}
1022
1024 SCIP_NLPIPROBLEM* problem, /**< pointer to problem data structure */
1025 const SCIP_NLPPARAM param /**< NLP solve parameters */
1026 )
1027{
1028 int COI_Error = 0; /* CONOPT error counter */
1029
1030 assert(problem != NULL);
1031
1032 if( param.warmstart )
1033 {
1034 SCIPdebugMsg(problem->scip, "warmstart parameter not supported by CONOPT interface yet. Ignored.\n");
1035 }
1036 if( param.lobjlimit > -SCIP_REAL_MAX )
1037 {
1038 SCIPwarningMessage(problem->scip, "lobjlimit parameter not supported by CONOPT interface yet. Ignored.\n");
1039 }
1040 if( param.fastfail )
1041 {
1042 SCIPdebugMsg(problem->scip, "fastfail parameter not supported by CONOPT interface yet. Ignored.\n");
1043 }
1044
1045 /* options that we can set directly */
1046 COI_Error += COIDEF_ItLim(problem->CntVect, param.iterlimit);
1047 COI_Error += COIDEF_ResLim(problem->CntVect, param.timelimit);
1048
1049 /* options that need to be handled in callbacks */
1050 problem->verblevel = param.verblevel;
1051 problem->opttol = param.opttol;
1052
1053 if( COI_Error )
1054 SCIPinfoMessage(problem->scip, NULL, "Errors encountered during setting parameters, %d\n", COI_Error);
1055}
1056
1057
1058/*
1059 * Callback methods of NLP solver interface
1060 */
1061
1062/** copy method of NLP interface (called when SCIP copies plugins) */
1063static
1064SCIP_DECL_NLPICOPY(nlpiCopyConopt)
1065{
1066 SCIP_NLPI* targetnlpi;
1067 SCIP_NLPIDATA* sourcenlpidata;
1068
1070
1071 /* if license is set in source NLPI, maybe set via SCIPsetLicenseConopt(),
1072 * then pass it on to the copy
1073 */
1074 sourcenlpidata = SCIPnlpiGetData(sourcenlpi);
1075 assert(sourcenlpidata != NULL);
1076 if( sourcenlpidata->license_text[0] != '\0' )
1077 {
1078 targetnlpi = SCIPfindNlpi(scip, NLPI_NAME);
1079 assert(targetnlpi != NULL);
1080
1081 SCIPsetLicenseConopt(targetnlpi, sourcenlpidata->license_int_1,
1082 sourcenlpidata->license_int_2, sourcenlpidata->license_int_3, sourcenlpidata->license_text);
1083 }
1084
1085 return SCIP_OKAY; /*lint !e527*/
1086} /*lint !e715*/
1087
1088/** destructor of NLP interface to free nlpi data */
1089static
1090SCIP_DECL_NLPIFREE(nlpiFreeConopt)
1091{
1092 assert(nlpi != NULL);
1093 assert(nlpidata != NULL);
1094 assert(*nlpidata != NULL);
1095
1096 if( (*nlpidata)->solvetime != NULL )
1097 if( (*nlpidata)->solvetime != NULL )
1098 {
1099 SCIP_CALL( SCIPfreeClock(scip, &((*nlpidata)->solvetime)) );
1100 }
1101
1102 SCIPfreeBlockMemory(scip, nlpidata);
1103 assert(*nlpidata == NULL);
1104
1105 return SCIP_OKAY;
1106} /*lint !e715*/
1107
1108#ifdef SCIP_DISABLED_CODE
1109/** gets pointer for NLP solver */
1110static
1111SCIP_DECL_NLPIGETSOLVERPOINTER(nlpiGetSolverPointerXyz)
1112{
1113 SCIPerrorMessage("method of xyz nonlinear solver is not implemented\n");
1114 SCIPABORT();
1115
1116 return NULL; /*lint !e527*/
1117} /*lint !e715*/
1118#else
1119#define nlpiGetSolverPointerConopt NULL
1120#endif
1121
1122/** create a problem instance */
1123static
1124SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemConopt)
1125{
1126 assert(nlpi != NULL);
1127 assert(problem != NULL);
1128
1130 assert(*problem != NULL);
1131
1132 (*problem)->firstrun = TRUE;
1133 (*problem)->scip = scip;
1134
1135 /* initialize oracle */
1136 SCIP_CALL( SCIPnlpiOracleCreate(scip, &(*problem)->oracle) );
1137 SCIP_CALL( SCIPnlpiOracleSetProblemName(scip, (*problem)->oracle, name) );
1138
1139 if( COI_Create(&((*problem)->CntVect)) || (*problem)->CntVect == NULL )
1140 {
1141 SCIPerrorMessage("Could not create CONOPT control vector\n");
1142 return SCIP_ERROR;
1143 }
1144
1145 /* create random number generator */
1146 SCIP_CALL( SCIPcreateRandom(scip, &(*problem)->randnumgen, DEFAULT_RANDSEED, TRUE) );
1147
1148 return SCIP_OKAY; /*lint !e527*/
1149} /*lint !e715*/
1150
1151/** free a problem instance */
1152static
1153SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemConopt)
1154{
1155 assert(nlpi != NULL);
1156 assert(problem != NULL);
1157 assert(*problem != NULL);
1158
1159 invalidateSolution(*problem);
1160
1161 if( (*problem)->oracle != NULL )
1162 {
1163 SCIP_CALL( SCIPnlpiOracleFree(scip, &(*problem)->oracle) );
1164 }
1165
1166 SCIPfreeRandom(scip, &(*problem)->randnumgen);
1167 SCIPfreeMemoryArrayNull(scip, &(*problem)->initguess);
1168
1169 if( COI_Free(&((*problem)->CntVect)) )
1170 {
1171 SCIPerrorMessage("Error when freeing CONOPT control vector\n");
1172 return SCIP_ERROR;
1173 }
1174
1175 SCIPfreeBlockMemory(scip, problem);
1176 *problem = NULL;
1177
1178#ifdef PRINT_NLPSTATS
1179 SCIPinfoMessage(scip, NULL, "\nNLP solver CONOPT stats: ncalls = %d, nsuccess = %d, nlimit = %d, nlocinfeas = %d, nother = %d\n",
1180 (*problem)->ncalls, (*problem)->nsuccess, (*problem)->nlimit, (*problem)->nlocinfeas, (*problem)->nother);
1181#endif
1182
1183 return SCIP_OKAY;
1184} /*lint !e715*/
1185
1186#ifdef SCIP_DISABLED_CODE
1187/** gets pointer to solver-internal problem instance */
1188static
1189SCIP_DECL_NLPIGETPROBLEMPOINTER(nlpiGetProblemPointerXyz)
1190{
1191 SCIPerrorMessage("method of xyz nonlinear solver is not implemented\n");
1192 SCIPABORT();
1193
1194 return NULL; /*lint !e527*/
1195} /*lint !e715*/
1196#else
1197#define nlpiGetProblemPointerConopt NULL
1198#endif
1199
1200/** add variables */
1201static
1202SCIP_DECL_NLPIADDVARS(nlpiAddVarsConopt)
1203{
1204 assert(nlpi != NULL);
1205 assert(problem != NULL);
1206 assert(problem->oracle != NULL);
1207
1208 SCIP_CALL( SCIPnlpiOracleAddVars(scip, problem->oracle, nvars, lbs, ubs, varnames) );
1209
1210 invalidateSolution(problem);
1211 problem->firstrun = TRUE;
1212
1213 return SCIP_OKAY; /*lint !e527*/
1214} /*lint !e715*/
1215
1216
1217/** add constraints */
1218static
1219SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsConopt)
1220{
1221 assert(nlpi != NULL);
1222 assert(problem != NULL);
1223 assert(problem->oracle != NULL);
1224
1225 SCIP_CALL( SCIPnlpiOracleAddConstraints(scip, problem->oracle, nconss, lhss, rhss,
1226 nlininds, lininds, linvals, exprs, names) );
1227
1228 invalidateSolution(problem);
1229 problem->firstrun = TRUE;
1230
1231 return SCIP_OKAY; /*lint !e527*/
1232} /*lint !e715*/
1233
1234/** sets or overwrites objective, a minimization problem is expected */
1235static
1236SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveConopt)
1237{
1238 assert(nlpi != NULL);
1239 assert(problem != NULL);
1240 assert(problem->oracle != NULL);
1241
1242 SCIP_CALL( SCIPnlpiOracleSetObjective(scip, problem->oracle, constant, nlins, lininds, linvals, expr) );
1243
1244 invalidateSolution(problem);
1245 problem->firstrun = TRUE;
1246
1247 return SCIP_OKAY; /*lint !e527*/
1248} /*lint !e715*/
1249
1250/** change variable bounds */
1251static
1252SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsConopt)
1253{
1254 assert(nlpi != NULL);
1255 assert(problem != NULL);
1256 assert(problem->oracle != NULL);
1257
1258 SCIP_CALL( SCIPnlpiOracleChgVarBounds(scip, problem->oracle, nvars, indices, lbs, ubs) );
1259
1260 invalidateSolution(problem);
1261
1262 return SCIP_OKAY; /*lint !e527*/
1263} /*lint !e715*/
1264
1265/** change constraint bounds */
1266static
1267SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesConopt)
1268{
1269 SCIP_NLPIORACLE* oracle;
1270
1271 assert(nlpi != NULL);
1272 assert(problem != NULL);
1273
1274 oracle = problem->oracle;
1275 assert(oracle != NULL);
1276
1277 /* check if any range constraints appear or disappear; if they do, this means new slack variables,
1278 * and thus a change in problem structure */
1279 for( int i = 0; i < nconss; ++i )
1280 {
1281 SCIP_Real oldlhs;
1282 SCIP_Real oldrhs;
1283
1284 assert(indices != NULL);
1285 assert(indices[i] >= 0);
1286 assert(indices[i] < SCIPnlpiOracleGetNConstraints(oracle));
1287
1288 oldlhs = SCIPnlpiOracleGetConstraintLhs(oracle, indices[i]);
1289 oldrhs = SCIPnlpiOracleGetConstraintRhs(oracle, indices[i]);
1290
1291 if( !SCIPisInfinity(scip, -oldlhs) && !SCIPisInfinity(scip, oldrhs) && SCIPisLT(scip, oldlhs, oldrhs) )
1292 {
1293 /* the old constraint is a range constraint, check if this changes with the new sides */
1294 if( lhss == NULL || rhss == NULL || SCIPisInfinity(scip, -lhss[i]) || SCIPisInfinity(scip, rhss[i]) ||
1295 SCIPisEQ(scip, lhss[i], rhss[i]) )
1296 {
1297 problem->firstrun = TRUE;
1298 break;
1299 }
1300 }
1301 else
1302 {
1303 /* the old constraint is not a range constraint, check if this changes with the new sides */
1304 if( lhss != NULL && rhss != NULL && !SCIPisInfinity(scip, -lhss[i]) && !SCIPisInfinity(scip, rhss[i]) &&
1305 SCIPisLT(scip, lhss[i], rhss[i]) )
1306 {
1307 problem->firstrun = TRUE;
1308 break;
1309 }
1310 }
1311 }
1312
1313 SCIP_CALL( SCIPnlpiOracleChgConsSides(scip, oracle, nconss, indices, lhss, rhss) );
1314
1315 invalidateSolution(problem);
1316
1317 return SCIP_OKAY; /*lint !e527*/
1318} /*lint !e715*/
1319
1320/** delete a set of variables */
1321static
1322SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetConopt)
1323{
1324 assert(nlpi != NULL);
1325 assert(problem != NULL);
1326 assert(problem->oracle != NULL);
1327
1328 SCIP_CALL( SCIPnlpiOracleDelVarSet(scip, problem->oracle, dstats) );
1329
1330 invalidateSolution(problem);
1331 problem->firstrun = TRUE;
1332
1333 return SCIP_OKAY; /*lint !e527*/
1334} /*lint !e715*/
1335
1336/** delete a set of constraints */
1337static
1338SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetConopt)
1339{
1340 assert(nlpi != NULL);
1341 assert(problem != NULL);
1342 assert(problem->oracle != NULL);
1343
1344 SCIP_CALL( SCIPnlpiOracleDelConsSet(scip, problem->oracle, dstats) );
1345
1346 invalidateSolution(problem);
1347 problem->firstrun = TRUE;
1348
1349 return SCIP_OKAY; /*lint !e527*/
1350} /*lint !e715*/
1351
1352/** changes (or adds) linear coefficients in a constraint or objective */
1353static
1354SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsConopt)
1355{
1356 assert(nlpi != NULL);
1357 assert(problem != NULL);
1358 assert(problem->oracle != NULL);
1359
1360 SCIP_CALL( SCIPnlpiOracleChgLinearCoefs(scip, problem->oracle, idx, nvals, varidxs, vals) );
1361
1362 invalidateSolution(problem);
1363 problem->firstrun = TRUE;
1364
1365 return SCIP_OKAY; /*lint !e527*/
1366} /*lint !e715*/
1367
1368/** replaces the expression tree of a constraint or objective */
1369static
1370SCIP_DECL_NLPICHGEXPR(nlpiChgExprConopt)
1371{
1372 assert(nlpi != NULL);
1373 assert(problem != NULL);
1374 assert(problem->oracle != NULL);
1375
1376 SCIP_CALL( SCIPnlpiOracleChgExpr(scip, problem->oracle, idxcons, expr) );
1377
1378 invalidateSolution(problem);
1379 problem->firstrun = TRUE;
1380
1381 return SCIP_OKAY; /*lint !e527*/
1382} /*lint !e715*/
1383
1384/** change the constant offset in the objective */
1385static
1386SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantConopt)
1387{
1388 assert(nlpi != NULL);
1389 assert(problem != NULL);
1390 assert(problem->oracle != NULL);
1391
1392 SCIP_CALL( SCIPnlpiOracleChgObjConstant(scip, problem->oracle, objconstant) );
1393
1394 return SCIP_OKAY; /*lint !e527*/
1395} /*lint !e715*/
1396
1397/** sets initial guess */
1398static
1399SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessConopt)
1400{
1401 assert(nlpi != NULL);
1402 assert(problem != NULL);
1403 assert(problem->oracle != NULL);
1404
1405 if( primalvalues != NULL )
1406 {
1407 if( !problem->initguess )
1408 {
1409 SCIP_CALL( SCIPduplicateMemoryArray(scip, &problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle)) );
1410 }
1411 else
1412 BMScopyMemoryArray(problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle));
1413 }
1414 else
1415 SCIPfreeMemoryArrayNull(scip, &problem->initguess);
1416
1417 return SCIP_OKAY;
1418} /*lint !e715*/
1419
1420/** try to solve NLP
1421 *
1422 * Note that SCIP will already have reset a timelimit of SCIP_REAL_MAX to the time remaining for the SCIP solve in SCIPnlpiSolve().
1423 */
1424static
1425SCIP_DECL_NLPISOLVE(nlpiSolveConopt)
1426{
1427 SCIP_NLPIDATA* data;
1428 int COI_Error; /* CONOPT error counter */
1429
1430 assert(nlpi != NULL);
1431 assert(problem != NULL);
1432
1433 data = SCIPnlpiGetData(nlpi);
1434 assert(data != NULL);
1435
1436 SCIPdebugMsg(scip, "solve with parameters " SCIP_NLPPARAM_PRINT(param));
1437
1438 SCIP_CALL( SCIPnlpiOracleResetEvalTime(scip, problem->oracle) );
1439
1440 if( param.timelimit == 0.0 )
1441 {
1442 /* there is nothing we can do if we are not given any time */
1443 problem->niterations = 0;
1444 problem->solvetime = 0.0;
1445 problem->termstat = SCIP_NLPTERMSTAT_TIMELIMIT;
1446 problem->solstat = SCIP_NLPSOLSTAT_UNKNOWN;
1447
1448 return SCIP_OKAY;
1449 }
1450
1451 problem->niterations = -1;
1452 problem->solvetime = -1.0;
1453
1454 /* set CONOPT parameters */
1455 handleConoptParam(problem, param);
1456
1457 /* initialize Conopt data if necessary */
1458 if( problem->firstrun )
1459 {
1460 SCIP_CALL( initConopt(scip, data, problem) );
1461 problem->firstrun = FALSE;
1462 }
1463
1464 /* measure time */
1465 SCIP_CALL( SCIPresetClock(scip, data->solvetime) );
1466 SCIP_CALL( SCIPstartClock(scip, data->solvetime) );
1467
1468 /* optimize */
1469 COI_Error = COI_Solve(problem->CntVect);
1470
1471 /* CONOPT may return either a positive error code, which is one of its own error codes,
1472 * or a negative error code that is a SCIP_RETCODE returned from one of the callbacks */
1473 if( COI_Error )
1474 {
1475 switch( COI_Error )
1476 {
1477 case -1:
1478 SCIPdebugMsg(scip, "Insufficient memory in CONOPT callback\n");
1479 break;
1480 case -2:
1481 SCIPdebugMsg(scip, "Problem structure computation error in CONOPT's ReadMatrix callback\n");
1482 break;
1483 default:
1484 SCIPdebugMsg(scip, "Errors encountered in CONOPT during solution, %d\n", COI_Error);
1485 }
1486 }
1487
1488 /* store statistics (some statistics are passed back to SCIP by the Status callback) */
1489 problem->solvetime = SCIPgetClockTime(scip, data->solvetime);
1490
1491 return SCIP_OKAY; /*lint !e527*/
1492} /*lint !e715*/
1493
1494/** gives solution status */
1495static
1496SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatConopt)
1497{
1498 assert(nlpi != NULL);
1499 assert(problem != NULL);
1500
1501 return problem->solstat;
1502} /*lint !e715*/
1503
1504/** gives termination reason */
1505static
1506SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatConopt)
1507{
1508 assert(nlpi != NULL);
1509 assert(problem != NULL);
1510
1511 return problem->termstat;
1512} /*lint !e715*/
1513
1514/** gives primal and dual solution values */
1515static
1516SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionConopt)
1517{
1518 assert(problem != NULL);
1519
1520 if( primalvalues != NULL )
1521 *primalvalues = problem->lastprimal;
1522
1523 if( consdualvalues != NULL )
1524 *consdualvalues = problem->lastdualcons;
1525
1526 if( varlbdualvalues != NULL )
1527 *varlbdualvalues = problem->lastduallb;
1528
1529 if( varubdualvalues != NULL )
1530 *varubdualvalues = problem->lastdualub;
1531
1532 if( objval != NULL )
1533 *objval = problem->objval;
1534
1535 return SCIP_OKAY; /*lint !e527*/
1536} /*lint !e715*/
1537
1538/** gives solve statistics */
1539static
1540SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsConopt)
1541{
1542 assert(nlpi != NULL);
1543 assert(problem != NULL);
1544 assert(statistics != NULL);
1545
1546 statistics->niterations = problem->niterations;
1547 statistics->totaltime = problem->solvetime;
1548 statistics->evaltime = SCIPnlpiOracleGetEvalTime(scip, problem->oracle);
1549 statistics->consviol = SCIP_INVALID; /* TODO currently unavailable in CONOPT; might change */
1550 statistics->boundviol = 0.0;
1551
1552 return SCIP_OKAY;
1553} /*lint !e715*/
1554
1555/*
1556 * NLP solver interface specific interface methods
1557 */
1558
1559/** create solver interface for Conopt solver and includes it into SCIP */
1561 SCIP* scip /**< SCIP data structure */
1562 )
1563{
1564 SCIP_NLPIDATA* nlpidata;
1565
1566 /* create Conopt solver interface data */
1568
1569#if defined(CONOPT_LICENSE_INT_1) && defined(CONOPT_LICENSE_INT_2) && defined(CONOPT_LICENSE_INT_3) && \
1570 defined(CONOPT_LICENSE_TEXT)
1571 nlpidata->license_int_1 = CONOPT_LICENSE_INT_1;
1572 nlpidata->license_int_2 = CONOPT_LICENSE_INT_2;
1573 nlpidata->license_int_3 = CONOPT_LICENSE_INT_3;
1574 (void) SCIPsnprintf(nlpidata->license_text, (int)sizeof(nlpidata->license_text), "%s", CONOPT_LICENSE_TEXT);
1575#endif
1576
1577 /* create and include solver interface */
1580 nlpiCopyConopt, nlpiFreeConopt, nlpiGetSolverPointerConopt,
1581 nlpiCreateProblemConopt, nlpiFreeProblemConopt, nlpiGetProblemPointerConopt,
1582 nlpiAddVarsConopt, nlpiAddConstraintsConopt, nlpiSetObjectiveConopt,
1583 nlpiChgVarBoundsConopt, nlpiChgConsSidesConopt, nlpiDelVarSetConopt, nlpiDelConstraintSetConopt,
1584 nlpiChgLinearCoefsConopt, nlpiChgExprConopt, nlpiChgObjConstantConopt,
1585 nlpiSetInitialGuessConopt, nlpiSolveConopt,
1586 nlpiGetSolstatConopt, nlpiGetTermstatConopt, nlpiGetSolutionConopt, nlpiGetStatisticsConopt,
1587 nlpidata) );
1588
1590
1591 return SCIP_OKAY;
1592}
1593
1594/** sets the license to be passed to CONOPT's COIDEF_License */
1596 SCIP_NLPI* nlpi, /**< CONOPT NLPI */
1597 int integer_1, /**< CONOPT_LICENSE_INT_1 */
1598 int integer_2, /**< CONOPT_LICENSE_INT_2 */
1599 int integer_3, /**< CONOPT_LICENSE_INT_3 */
1600 const char* text /**< CONOPT_LICENSE_TEXT */
1601 )
1602{
1603 SCIP_NLPIDATA* data;
1604 assert(nlpi != NULL);
1605
1606 data = SCIPnlpiGetData(nlpi);
1607 assert(data != NULL);
1608
1609 data->license_int_1 = integer_1;
1610 data->license_int_2 = integer_2;
1611 data->license_int_3 = integer_3;
1612 (void) SCIPsnprintf(data->license_text, (int)sizeof(data->license_text), "%s", text);
1613}
1614
1615#define STR_HELPER(x) #x
1616#define STR(x) STR_HELPER(x)
1617
1618/** gets string that identifies CONOPT */
1620 void
1621 )
1622{
1623 return "CONOPT " STR(CONOPT_VERSION_MAJOR) "." STR(CONOPT_VERSION_MINOR) "." STR(CONOPT_VERSION_PATCH);
1624}
1625
1626/** gets string that describes CONOPT */
1628 void
1629 )
1630{
1631 return "Feasible path solver for large-scale nonlinear problems (conopt.com)";
1632}
1633
1634/** returns whether CONOPT is available, i.e., whether it has been linked in */
1636 void
1637 )
1638{
1639 return TRUE;
1640}
#define DEFAULT_RANDSEED
#define NULL
Definition def.h:257
#define SCIP_REAL_MAX
Definition def.h:167
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIPABORT()
Definition def.h:336
#define SCIP_CALL(x)
Definition def.h:364
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPincludeNlpSolverConopt(SCIP *scip)
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 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_RETCODE SCIPnlpiOracleDelVarSet(SCIP *scip, SCIP_NLPIORACLE *oracle, int *delstats)
SCIP_RETCODE SCIPnlpiOracleCreate(SCIP *scip, SCIP_NLPIORACLE **oracle)
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 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_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)
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
SCIP_RETCODE SCIPnlpiOracleChgExpr(SCIP *scip, SCIP_NLPIORACLE *oracle, int considx, SCIP_EXPR *expr)
void SCIPsetLicenseConopt(SCIP_NLPI *nlpi, int integer_1, int integer_2, int integer_3, const char *text)
const char * SCIPgetSolverDescConopt(void)
SCIP_Bool SCIPisConoptAvailableConopt(void)
const char * SCIPgetSolverNameConopt(void)
SCIP_RETCODE SCIPincludeExternalCodeInformation(SCIP *scip, const char *name, const char *description)
#define SCIPfreeCleanBufferArray(scip, ptr)
Definition scip_mem.h:146
#define SCIPallocCleanBufferArray(scip, ptr, num)
Definition scip_mem.h:142
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition scip_mem.h:81
#define SCIPallocClearBlockMemory(scip, ptr)
Definition scip_mem.h:91
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:97
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:76
#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 SCIPincludeNlpi(SCIP *scip, const char *name, const char *description, int priority, SCIP_DECL_NLPICOPY((*nlpicopy)), SCIP_DECL_NLPIFREE((*nlpifree)), SCIP_DECL_NLPIGETSOLVERPOINTER((*nlpigetsolverpointer)), SCIP_DECL_NLPICREATEPROBLEM((*nlpicreateproblem)), SCIP_DECL_NLPIFREEPROBLEM((*nlpifreeproblem)), SCIP_DECL_NLPIGETPROBLEMPOINTER((*nlpigetproblempointer)), SCIP_DECL_NLPIADDVARS((*nlpiaddvars)), SCIP_DECL_NLPIADDCONSTRAINTS((*nlpiaddconstraints)), SCIP_DECL_NLPISETOBJECTIVE((*nlpisetobjective)), SCIP_DECL_NLPICHGVARBOUNDS((*nlpichgvarbounds)), SCIP_DECL_NLPICHGCONSSIDES((*nlpichgconssides)), SCIP_DECL_NLPIDELVARSET((*nlpidelvarset)), SCIP_DECL_NLPIDELCONSSET((*nlpidelconsset)), SCIP_DECL_NLPICHGLINEARCOEFS((*nlpichglinearcoefs)), SCIP_DECL_NLPICHGEXPR((*nlpichgexpr)), SCIP_DECL_NLPICHGOBJCONSTANT((*nlpichgobjconstant)), SCIP_DECL_NLPISETINITIALGUESS((*nlpisetinitialguess)), SCIP_DECL_NLPISOLVE((*nlpisolve)), SCIP_DECL_NLPIGETSOLSTAT((*nlpigetsolstat)), SCIP_DECL_NLPIGETTERMSTAT((*nlpigettermstat)), SCIP_DECL_NLPIGETSOLUTION((*nlpigetsolution)), SCIP_DECL_NLPIGETSTATISTICS((*nlpigetstatistics)), SCIP_NLPIDATA *nlpidata)
Definition scip_nlpi.c:113
SCIP_NLPI * SCIPfindNlpi(SCIP *scip, const char *name)
Definition scip_nlpi.c:179
SCIP_NLPIDATA * SCIPnlpiGetData(SCIP_NLPI *nlpi)
Definition nlpi.c:712
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition scip_timing.c:76
SCIP_RETCODE SCIPresetClock(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_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition misc.c:10245
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
SCIPfreeRandom(scip, &heurdata->randnumgen)
SCIP_Real objval
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
#define NLPI_PRIORITY
Definition nlpi_all.c:43
#define NLPI_NAME
Definition nlpi_all.c:41
#define NLPI_DESC
Definition nlpi_all.c:42
static int COI_CALLCONV LagrStr(int HSRW[], int HSCL[], int *NODRV, int NUMVAR, int NUMCON, int NHESS, void *USRMEM)
#define STR(x)
#define MAXPERTURB
Definition nlpi_conopt.c:60
static void handleConoptParam(SCIP_NLPIPROBLEM *problem, const SCIP_NLPPARAM param)
static int COI_CALLCONV ReadMatrix(double LOWER[], double CURR[], double UPPER[], int VSTA[], int TYPE[], double RHS[], int ESTA[], int COLSTA[], int ROWNO[], double VALUE[], int NLFLAG[], int NUMVAR, int NUMCON, int NUMNZ, void *USRMEM)
static int COI_CALLCONV FDInterval(const double XMIN[], const double XMAX[], double *GMIN, double *GMAX, double JMIN[], double JMAX[], int ROWNO, const int JACNUM[], int MODE, double PINF, int NUMVAR, int NUMJAC, void *USRMEM)
static int COI_CALLCONV FDEval(const double X[], double *G, double JAC[], int ROWNO, const int JACNUM[], int MODE, int IGNERR, int *ERRCNT, int NUMVAR, int NUMJAC, int THREAD, void *USRMEM)
static int COI_CALLCONV LagrVal(const double X[], const double U[], const int HSRW[], const int HSCL[], double HSVL[], int *NODRV, int NUMVAR, int NUMCON, int NHESS, void *USRMEM)
#define nlpiGetSolverPointerConopt
#define nlpiGetProblemPointerConopt
static int COI_CALLCONV Solution(const double XVAL[], const double XMAR[], const int XBAS[], const int XSTA[], const double YVAL[], const double YMAR[], const int YBAS[], const int YSTA[], int NUMVAR, int NUMCON, void *USRMEM)
static int COI_CALLCONV ErrMsg(int ROWNO, int COLNO, int POSNO, const char *MSG, void *USRMEM)
static SCIP_RETCODE initConopt(SCIP *scip, SCIP_NLPIDATA *data, SCIP_NLPIPROBLEM *problem)
static int COI_CALLCONV Status(int MODSTA, int SOLSTA, int ITER, double OBJVAL, void *USRMEM)
static int COI_CALLCONV Message(int SMSG, int DMSG, int NMSG, char *MSGV[], void *USRMEM)
static int COI_CALLCONV Option(int NCALL, double *RVAL, int *IVAL, int *LVAL, char *NAME, void *USRMEM)
static void invalidateSolution(SCIP_NLPIPROBLEM *problem)
CONOPT NLP interface.
methods to store an NLP and request function, gradient, and Hessian values
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
public data structures and miscellaneous methods
general public methods
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for NLPI solver interfaces
public methods for numerical tolerances
public methods for random numbers
public methods for timing
@ RHS
SCIP_Real timelimit
Definition type_nlpi.h:72
SCIP_Bool warmstart
Definition type_nlpi.h:77
SCIP_Real opttol
Definition type_nlpi.h:70
SCIP_NLPPARAM_FASTFAIL fastfail
Definition type_nlpi.h:75
SCIP_Real lobjlimit
Definition type_nlpi.h:68
unsigned short verblevel
Definition type_nlpi.h:74
SCIP_Real * lastprimal
Definition nlpi_conopt.c:90
SCIP_Real * lastduallb
Definition nlpi_conopt.c:92
coiHandle_t CntVect
Definition nlpi_conopt.c:97
SCIP_Real * lastdualcons
Definition nlpi_conopt.c:91
SCIP_Bool firstrun
Definition nlpi_conopt.c:81
SCIP_NLPIORACLE * oracle
Definition nlpi_conopt.c:78
SCIP_RANDNUMGEN * randnumgen
Definition nlpi_conopt.c:79
SCIP_Real solvetime
Definition nlpi_conopt.c:86
SCIP_NLPTERMSTAT termstat
Definition nlpi_conopt.c:85
SCIP_Real * lastdualub
Definition nlpi_conopt.c:93
SCIP_Real objval
Definition nlpi_conopt.c:88
SCIP_Real * initguess
Definition nlpi_conopt.c:82
SCIP_NLPSOLSTAT solstat
Definition nlpi_conopt.c:84
type definitions for clocks and timing issues
struct SCIP_Clock SCIP_CLOCK
Definition type_clock.h:49
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
#define SCIP_DECL_NLPISOLVE(x)
Definition type_nlpi.h:487
struct SCIP_NlpiProblem SCIP_NLPIPROBLEM
Definition type_nlpi.h:53
#define SCIP_DECL_NLPICHGLINEARCOEFS(x)
Definition type_nlpi.h:422
#define SCIP_DECL_NLPICHGOBJCONSTANT(x)
Definition type_nlpi.h:453
#define SCIP_NLPPARAM_PRINT(param)
Definition type_nlpi.h:142
#define SCIP_DECL_NLPIGETSOLUTION(x)
Definition type_nlpi.h:535
#define SCIP_DECL_NLPISETOBJECTIVE(x)
Definition type_nlpi.h:334
#define SCIP_DECL_NLPICREATEPROBLEM(x)
Definition type_nlpi.h:245
#define SCIP_DECL_NLPIGETSTATISTICS(x)
Definition type_nlpi.h:552
#define SCIP_DECL_NLPIDELCONSSET(x)
Definition type_nlpi.h:405
#define SCIP_DECL_NLPICHGCONSSIDES(x)
Definition type_nlpi.h:373
struct SCIP_Nlpi SCIP_NLPI
Definition type_nlpi.h:51
#define SCIP_DECL_NLPIDELVARSET(x)
Definition type_nlpi.h:390
#define SCIP_DECL_NLPICHGEXPR(x)
Definition type_nlpi.h:439
#define SCIP_DECL_NLPIADDVARS(x)
Definition type_nlpi.h:287
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition type_nlpi.h:168
#define SCIP_DECL_NLPISETINITIALGUESS(x)
Definition type_nlpi.h:471
#define SCIP_DECL_NLPIFREEPROBLEM(x)
Definition type_nlpi.h:257
@ SCIP_NLPTERMSTAT_OKAY
Definition type_nlpi.h:173
@ SCIP_NLPTERMSTAT_TIMELIMIT
Definition type_nlpi.h:174
@ SCIP_NLPTERMSTAT_NUMERICERROR
Definition type_nlpi.h:178
@ SCIP_NLPTERMSTAT_OTHER
Definition type_nlpi.h:182
@ SCIP_NLPTERMSTAT_EVALERROR
Definition type_nlpi.h:179
@ SCIP_NLPTERMSTAT_ITERLIMIT
Definition type_nlpi.h:175
@ SCIP_NLPTERMSTAT_INTERRUPT
Definition type_nlpi.h:177
#define SCIP_DECL_NLPICOPY(x)
Definition type_nlpi.h:205
#define SCIP_DECL_NLPIGETSOLVERPOINTER(x)
Definition type_nlpi.h:233
#define SCIP_DECL_NLPIGETSOLSTAT(x)
Definition type_nlpi.h:501
#define SCIP_DECL_NLPICHGVARBOUNDS(x)
Definition type_nlpi.h:354
#define SCIP_DECL_NLPIGETPROBLEMPOINTER(x)
Definition type_nlpi.h:272
#define SCIP_DECL_NLPIFREE(x)
Definition type_nlpi.h:215
#define SCIP_DECL_NLPIADDCONSTRAINTS(x)
Definition type_nlpi.h:310
@ SCIP_NLPSOLSTAT_UNBOUNDED
Definition type_nlpi.h:165
@ SCIP_NLPSOLSTAT_GLOBINFEASIBLE
Definition type_nlpi.h:164
@ SCIP_NLPSOLSTAT_LOCINFEASIBLE
Definition type_nlpi.h:163
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition type_nlpi.h:162
@ SCIP_NLPSOLSTAT_LOCOPT
Definition type_nlpi.h:161
@ SCIP_NLPSOLSTAT_GLOBOPT
Definition type_nlpi.h:160
@ SCIP_NLPSOLSTAT_UNKNOWN
Definition type_nlpi.h:166
#define SCIP_DECL_NLPIGETTERMSTAT(x)
Definition type_nlpi.h:514
struct SCIP_NlpParam SCIP_NLPPARAM
Definition type_nlpi.h:81
enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
Definition type_nlpi.h:184
struct SCIP_NlpiData SCIP_NLPIDATA
Definition type_nlpi.h:52
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39