Scippy

    SCIP

    Solving Constraint Integer Programs

    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 to pass some of the options (not supported via COIDEF_* functions) to CONOPT */
    744static int COI_CALLCONV Option(
    745 int NCALL, /**< number of callback call (provided by CONOPT) */
    746 double* RVAL, /**< pointer to set the value of a real option */
    747 int* IVAL, /**< pointer to set the value of an integer option */
    748 int* LVAL, /**< pointer to set the value of a binary option */
    749 char* NAME, /**< pointer to set the name of the option */
    750 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
    751 )
    752{
    753 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
    754
    755 assert(problem != NULL);
    756
    757 switch( NCALL )
    758 {
    759 case 0: /* information about stopping criteria */
    760 strcpy(NAME, "LOCNPT");
    761 if( problem->verblevel >= 2 )
    762 *IVAL = 1;
    763 else
    764 *IVAL = 0;
    765 break;
    766 case 1: /* optimality tolerance */
    767 strcpy(NAME, "RTREDG");
    768 *RVAL = problem->opttol;
    769 break;
    770 case 2: /* turn definitional constraints off for now (conopt#103) */
    771 strcpy(NAME, "Flg_NoDefc");
    772 *LVAL = 1;
    773 break;
    774 default:
    775 *NAME = '\0';
    776 }
    777
    778 return 0;
    779} /*lint !e715*/
    780
    781/** CONOPT callback to define structure of the Hessian of the Lagrangian */
    782static int COI_CALLCONV LagrStr(
    783 int HSRW[], /**< row numbers of the lower triangular part of the Hessian */
    784 int HSCL[], /**< column numbers of the lower triangular part of the Hessian; elements must be
    785 * sorted column-wise, and within each column, row-wise */
    786 int* NODRV, /**< can be set to 1 if the derivatives could not be computed */
    787 int NUMVAR, /**< number of variables as defined in coidef_numvar() (provided by CONOPT) */
    788 int NUMCON, /**< number of constraints as defined in coidef_numcon() (provided by CONOPT) */
    789 int NHESS, /**< number of nonzero elements in the Hessian (provided by CONOPT) */
    790 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
    791 )
    792{
    793 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
    794 const int* hessoffsets;
    795 const int* rows;
    796 int col = 0;
    797
    798 assert(problem != NULL);
    799
    800 if( SCIPnlpiOracleGetHessianLagSparsity(problem->scip, problem->oracle, &hessoffsets, &rows, TRUE) != SCIP_OKAY )
    801 {
    802 *NODRV = 1;
    803 return 0;
    804 }
    805
    806 for( int i = 0; i < NHESS; i++ )
    807 {
    808 /* check if it's time to switch to the next row (this will also skip empty rows) */
    809 while( i == hessoffsets[col+1] )
    810 col++;
    811
    812 HSRW[i] = rows[i];
    813 HSCL[i] = col;
    814 }
    815
    816 return 0;
    817} /*lint !e715*/
    818
    819/** CONOPT callback to compute the Hessian of the Lagrangian
    820 *
    821 * the Lagrangian is written as L = sum_{r in rows}U[r] * function(r)
    822 */
    823static int COI_CALLCONV LagrVal(
    824 const double X[], /**< point in which the Hessian should be computed (provided by CONOPT) */
    825 const double U[], /**< vector of weights on the individual constraints (provided by CONOPT) */
    826 const int HSRW[], /**< row numbers of the lower triangular part of the Hessian (provided by CONOPT) */
    827 const int HSCL[], /**< column numbers of the lower triangular part of the Hessian; elements must be
    828 * sorted column-wise, and within each column, row-wise (provided by CONOPT) */
    829 double HSVL[], /**< values of Hessian entries */
    830 int* NODRV, /**< can be set to 1 if the derivatives could not be computed */
    831 int NUMVAR, /**< number of variables as defined in coidef_numvar() (provided by CONOPT) */
    832 int NUMCON, /**< number of constraints as defined in coidef_numcon() (provided by CONOPT) */
    833 int NHESS, /**< number of nonzero elements in the Hessian (provided by CONOPT) */
    834 void* USRMEM /**< user memory pointer (i.e. pointer to SCIP_NLPIPROBLEM) */
    835 )
    836{
    837 SCIP_NLPIPROBLEM* problem = (SCIP_NLPIPROBLEM*)USRMEM;
    838
    839 assert(problem != NULL);
    840
    841 /* TODO better handling for isnew? */
    842 if( SCIPnlpiOracleEvalHessianLag(problem->scip, problem->oracle, X, TRUE, TRUE, U[NUMCON-1], U, HSVL, TRUE)
    843 != SCIP_OKAY )
    844 *NODRV = 1;
    845
    846 return 0;
    847} /*lint !e715*/
    848
    849/* NLPI local methods */
    850
    851/** frees solution arrays and sets the solstat and termstat to unknown and other, resp. */
    852static
    854 SCIP_NLPIPROBLEM* problem /**< data structure of problem */
    855 )
    856{
    857 assert(problem != NULL);
    858
    859 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastprimal), problem->varsolsize);
    860 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastdualcons), problem->conssolsize);
    861 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastduallb), problem->varsolsize);
    862 SCIPfreeBlockMemoryArrayNull(problem->scip, &(problem->lastdualub), problem->varsolsize);
    863 problem->varsolsize = 0;
    864 problem->conssolsize = 0;
    865
    868}
    869
    871 SCIP* scip, /**< SCIP data structure */
    872 SCIP_NLPIDATA* data, /**< pointer to NLPIDATA structure */
    873 SCIP_NLPIPROBLEM* problem /**< pointer to NLPI problem structure */
    874 )
    875{
    876 int COI_Error = 0; /* CONOPT error counter */
    877 int nrangeconss = 0;
    878 int nconss;
    879 int nvars;
    880 const int* jacoffsets;
    881 const int* hessoffsets;
    882 int nnlnz;
    883 const int* objgradnz;
    884 const SCIP_Bool* objnl;
    885 int nobjgradnz;
    886 int nobjgradnls;
    887
    888 assert(data != NULL);
    889 assert(problem != NULL);
    890 assert(problem->oracle != NULL);
    891
    892 if( data->solvetime == NULL )
    893 if( data->solvetime == NULL )
    894 {
    895 SCIP_CALL( SCIPcreateClock(scip, &(data->solvetime)) );
    896 }
    897
    898 nconss = SCIPnlpiOracleGetNConstraints(problem->oracle);
    899 nvars = SCIPnlpiOracleGetNVars(problem->oracle);
    900
    901 /* count range constraints: because CONOPT doesn't support them directly, will need to add a slack variable for each ranged constraint */
    902 for( int i = 0; i < nconss; i++ )
    903 {
    906
    907 if( !SCIPisInfinity(problem->scip, -lhs) && !SCIPisInfinity(problem->scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
    908 nrangeconss++;
    909 }
    910
    911 /* tell CONOPT that we may have empty columns */
    912 COI_Error += COIDEF_EmptyCol(problem->CntVect, 1);
    913
    914 /* inform CONOPT about problem sizes */
    915 COI_Error += COIDEF_NumVar(problem->CntVect, nvars + nrangeconss);
    916 COI_Error += COIDEF_NumCon(problem->CntVect, nconss + 1); /* objective counts as another constraint here */
    917
    918 /* jacobian information */
    919 SCIP_CALL( SCIPnlpiOracleGetJacobianColSparsity(scip, problem->oracle, &jacoffsets, NULL, NULL, &nnlnz) );
    920 SCIP_CALL( SCIPnlpiOracleGetObjGradientNnz(scip, problem->oracle, &objgradnz, &objnl, &nobjgradnz, &nobjgradnls) );
    921
    922 /* each slack var adds a Jacobian nnz; objective also counts as constraint */
    923 COI_Error += COIDEF_NumNz(problem->CntVect, jacoffsets != NULL ? jacoffsets[nvars] + nrangeconss + nobjgradnz :
    924 nrangeconss + nobjgradnz);
    925
    926 /* Jacobian nonzeroes include those of constraints and objective */
    927 COI_Error += COIDEF_NumNlNz(problem->CntVect, nnlnz + nobjgradnls);
    928
    929 /* hessian sparsity information */
    931 COI_Error += COIDEF_NumHess(problem->CntVect, hessoffsets[nvars]);
    932
    933 /* tell CONOPT to minimise the objective (the oracle always gives a minimisation problem) */
    934 COI_Error += COIDEF_OptDir(problem->CntVect, -1);
    935
    936 /* oracle gives objective as a constraint, hence use ObjCon (not ObjVar) here;
    937 * we treat objective as the last constraint, hence index nconss */
    938 COI_Error += COIDEF_ObjCon(problem->CntVect, nconss);
    939
    940 /* register callback routines */
    941 COI_Error += COIDEF_Message(problem->CntVect, Message);
    942 COI_Error += COIDEF_ErrMsg(problem->CntVect, ErrMsg);
    943 COI_Error += COIDEF_Status(problem->CntVect, Status);
    944 COI_Error += COIDEF_Solution(problem->CntVect, Solution);
    945 COI_Error += COIDEF_ReadMatrix(problem->CntVect, ReadMatrix);
    946 COI_Error += COIDEF_FDEval(problem->CntVect, FDEval);
    947 COI_Error += COIDEF_Option(problem->CntVect, Option);
    948 COI_Error += COIDEF_2DLagrStr(problem->CntVect, LagrStr);
    949 COI_Error += COIDEF_2DLagrVal(problem->CntVect, LagrVal);
    950
    951 /* tell CONOPT that our function evaluations include the linear terms */
    952 COI_Error += COIDEF_FVincLin(problem->CntVect, 1);
    953
    954 /* pass the problem pointer to CONOPT, so that it may be used in CONOPT callbacks */
    955 COI_Error += COIDEF_UsrMem(problem->CntVect, (void*)problem);
    956
    957 /* register license, if available */
    958 if( data->license_text[0] != '\0' )
    959 COI_Error += COIDEF_License(problem->CntVect, data->license_int_1, data->license_int_2, data->license_int_3, data->license_text);
    960
    961 if( COI_Error )
    962 SCIPinfoMessage(scip, NULL, "Error %d encountered during initialising CONOPT\n", COI_Error);
    963
    964 return SCIP_OKAY;
    965}
    966
    968 SCIP_NLPIPROBLEM* problem, /**< pointer to problem data structure */
    969 const SCIP_NLPPARAM param /**< NLP solve parameters */
    970 )
    971{
    972 int COI_Error = 0; /* CONOPT error counter */
    973
    974 assert(problem != NULL);
    975
    976 if( param.warmstart )
    977 {
    978 SCIPdebugMsg(problem->scip, "warmstart parameter not supported by CONOPT interface yet. Ignored.\n");
    979 }
    980 if( param.lobjlimit > -SCIP_REAL_MAX )
    981 {
    982 SCIPwarningMessage(problem->scip, "lobjlimit parameter not supported by CONOPT interface yet. Ignored.\n");
    983 }
    984 if( param.fastfail )
    985 {
    986 SCIPdebugMsg(problem->scip, "fastfail parameter not supported by CONOPT interface yet. Ignored.\n");
    987 }
    988
    989 /* options that we can set directly */
    990 COI_Error += COIDEF_ItLim(problem->CntVect, param.iterlimit);
    991 COI_Error += COIDEF_ResLim(problem->CntVect, param.timelimit);
    992
    993 /* options that need to be handled in callbacks */
    994 problem->verblevel = param.verblevel;
    995 problem->opttol = param.opttol;
    996
    997 if( COI_Error )
    998 SCIPinfoMessage(problem->scip, NULL, "Errors encountered during setting parameters, %d\n", COI_Error);
    999}
    1000
    1001
    1002/*
    1003 * Callback methods of NLP solver interface
    1004 */
    1005
    1006/** copy method of NLP interface (called when SCIP copies plugins) */
    1007static
    1008SCIP_DECL_NLPICOPY(nlpiCopyConopt)
    1009{
    1010 SCIP_NLPI* targetnlpi;
    1011 SCIP_NLPIDATA* sourcenlpidata;
    1012
    1014
    1015 /* if license is set in source NLPI, maybe set via SCIPsetLicenseConopt(),
    1016 * then pass it on to the copy
    1017 */
    1018 sourcenlpidata = SCIPnlpiGetData(sourcenlpi);
    1019 assert(sourcenlpidata != NULL);
    1020 if( sourcenlpidata->license_text[0] != '\0' )
    1021 {
    1022 targetnlpi = SCIPfindNlpi(scip, NLPI_NAME);
    1023 assert(targetnlpi != NULL);
    1024
    1025 SCIPsetLicenseConopt(targetnlpi, sourcenlpidata->license_int_1,
    1026 sourcenlpidata->license_int_2, sourcenlpidata->license_int_3, sourcenlpidata->license_text);
    1027 }
    1028
    1029 return SCIP_OKAY; /*lint !e527*/
    1030} /*lint !e715*/
    1031
    1032/** destructor of NLP interface to free nlpi data */
    1033static
    1034SCIP_DECL_NLPIFREE(nlpiFreeConopt)
    1035{
    1036 assert(nlpi != NULL);
    1037 assert(nlpidata != NULL);
    1038 assert(*nlpidata != NULL);
    1039
    1040 if( (*nlpidata)->solvetime != NULL )
    1041 if( (*nlpidata)->solvetime != NULL )
    1042 {
    1043 SCIP_CALL( SCIPfreeClock(scip, &((*nlpidata)->solvetime)) );
    1044 }
    1045
    1046 SCIPfreeBlockMemory(scip, nlpidata);
    1047 assert(*nlpidata == NULL);
    1048
    1049 return SCIP_OKAY;
    1050} /*lint !e715*/
    1051
    1052#ifdef SCIP_DISABLED_CODE
    1053/** gets pointer for NLP solver */
    1054static
    1055SCIP_DECL_NLPIGETSOLVERPOINTER(nlpiGetSolverPointerXyz)
    1056{
    1057 SCIPerrorMessage("method of xyz nonlinear solver is not implemented\n");
    1058 SCIPABORT();
    1059
    1060 return NULL; /*lint !e527*/
    1061} /*lint !e715*/
    1062#else
    1063#define nlpiGetSolverPointerConopt NULL
    1064#endif
    1065
    1066/** create a problem instance */
    1067static
    1068SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemConopt)
    1069{
    1070 assert(nlpi != NULL);
    1071 assert(problem != NULL);
    1072
    1074 assert(*problem != NULL);
    1075
    1076 (*problem)->firstrun = TRUE;
    1077 (*problem)->scip = scip;
    1078
    1079 /* initialize oracle */
    1080 SCIP_CALL( SCIPnlpiOracleCreate(scip, &(*problem)->oracle) );
    1081 SCIP_CALL( SCIPnlpiOracleSetProblemName(scip, (*problem)->oracle, name) );
    1082
    1083 if( COI_Create(&((*problem)->CntVect)) || (*problem)->CntVect == NULL )
    1084 {
    1085 SCIPerrorMessage("Could not create CONOPT control vector\n");
    1086 return SCIP_ERROR;
    1087 }
    1088
    1089 /* create random number generator */
    1090 SCIP_CALL( SCIPcreateRandom(scip, &(*problem)->randnumgen, DEFAULT_RANDSEED, TRUE) );
    1091
    1092 return SCIP_OKAY; /*lint !e527*/
    1093} /*lint !e715*/
    1094
    1095/** free a problem instance */
    1096static
    1097SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemConopt)
    1098{
    1099 assert(nlpi != NULL);
    1100 assert(problem != NULL);
    1101 assert(*problem != NULL);
    1102
    1103 invalidateSolution(*problem);
    1104
    1105 if( (*problem)->oracle != NULL )
    1106 {
    1107 SCIP_CALL( SCIPnlpiOracleFree(scip, &(*problem)->oracle) );
    1108 }
    1109
    1110 SCIPfreeRandom(scip, &(*problem)->randnumgen);
    1111 SCIPfreeMemoryArrayNull(scip, &(*problem)->initguess);
    1112
    1113 if( COI_Free(&((*problem)->CntVect)) )
    1114 {
    1115 SCIPerrorMessage("Error when freeing CONOPT control vector\n");
    1116 return SCIP_ERROR;
    1117 }
    1118
    1119 SCIPfreeBlockMemory(scip, problem);
    1120 *problem = NULL;
    1121
    1122#ifdef PRINT_NLPSTATS
    1123 SCIPinfoMessage(scip, NULL, "\nNLP solver CONOPT stats: ncalls = %d, nsuccess = %d, nlimit = %d, nlocinfeas = %d, nother = %d\n",
    1124 (*problem)->ncalls, (*problem)->nsuccess, (*problem)->nlimit, (*problem)->nlocinfeas, (*problem)->nother);
    1125#endif
    1126
    1127 return SCIP_OKAY;
    1128} /*lint !e715*/
    1129
    1130#ifdef SCIP_DISABLED_CODE
    1131/** gets pointer to solver-internal problem instance */
    1132static
    1133SCIP_DECL_NLPIGETPROBLEMPOINTER(nlpiGetProblemPointerXyz)
    1134{
    1135 SCIPerrorMessage("method of xyz nonlinear solver is not implemented\n");
    1136 SCIPABORT();
    1137
    1138 return NULL; /*lint !e527*/
    1139} /*lint !e715*/
    1140#else
    1141#define nlpiGetProblemPointerConopt NULL
    1142#endif
    1143
    1144/** add variables */
    1145static
    1146SCIP_DECL_NLPIADDVARS(nlpiAddVarsConopt)
    1147{
    1148 assert(nlpi != NULL);
    1149 assert(problem != NULL);
    1150 assert(problem->oracle != NULL);
    1151
    1152 SCIP_CALL( SCIPnlpiOracleAddVars(scip, problem->oracle, nvars, lbs, ubs, varnames) );
    1153
    1154 invalidateSolution(problem);
    1155 problem->firstrun = TRUE;
    1156
    1157 return SCIP_OKAY; /*lint !e527*/
    1158} /*lint !e715*/
    1159
    1160
    1161/** add constraints */
    1162static
    1163SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsConopt)
    1164{
    1165 assert(nlpi != NULL);
    1166 assert(problem != NULL);
    1167 assert(problem->oracle != NULL);
    1168
    1169 SCIP_CALL( SCIPnlpiOracleAddConstraints(scip, problem->oracle, nconss, lhss, rhss,
    1170 nlininds, lininds, linvals, exprs, names) );
    1171
    1172 invalidateSolution(problem);
    1173 problem->firstrun = TRUE;
    1174
    1175 return SCIP_OKAY; /*lint !e527*/
    1176} /*lint !e715*/
    1177
    1178/** sets or overwrites objective, a minimization problem is expected */
    1179static
    1180SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveConopt)
    1181{
    1182 assert(nlpi != NULL);
    1183 assert(problem != NULL);
    1184 assert(problem->oracle != NULL);
    1185
    1186 SCIP_CALL( SCIPnlpiOracleSetObjective(scip, problem->oracle, constant, nlins, lininds, linvals, expr) );
    1187
    1188 invalidateSolution(problem);
    1189 problem->firstrun = TRUE;
    1190
    1191 return SCIP_OKAY; /*lint !e527*/
    1192} /*lint !e715*/
    1193
    1194/** change variable bounds */
    1195static
    1196SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsConopt)
    1197{
    1198 assert(nlpi != NULL);
    1199 assert(problem != NULL);
    1200 assert(problem->oracle != NULL);
    1201
    1202 SCIP_CALL( SCIPnlpiOracleChgVarBounds(scip, problem->oracle, nvars, indices, lbs, ubs) );
    1203
    1204 invalidateSolution(problem);
    1205
    1206 return SCIP_OKAY; /*lint !e527*/
    1207} /*lint !e715*/
    1208
    1209/** change constraint bounds */
    1210static
    1211SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesConopt)
    1212{
    1213 SCIP_NLPIORACLE* oracle;
    1214
    1215 assert(nlpi != NULL);
    1216 assert(problem != NULL);
    1217
    1218 oracle = problem->oracle;
    1219 assert(oracle != NULL);
    1220
    1221 /* check if any range constraints appear or disappear; if they do, this means new slack variables,
    1222 * and thus a change in problem structure */
    1223 for( int i = 0; i < nconss; ++i )
    1224 {
    1225 SCIP_Real oldlhs;
    1226 SCIP_Real oldrhs;
    1227
    1228 assert(indices != NULL);
    1229 assert(indices[i] >= 0);
    1230 assert(indices[i] < SCIPnlpiOracleGetNConstraints(oracle));
    1231
    1232 oldlhs = SCIPnlpiOracleGetConstraintLhs(oracle, indices[i]);
    1233 oldrhs = SCIPnlpiOracleGetConstraintRhs(oracle, indices[i]);
    1234
    1235 if( !SCIPisInfinity(scip, -oldlhs) && !SCIPisInfinity(scip, oldrhs) && SCIPisLT(scip, oldlhs, oldrhs) )
    1236 {
    1237 /* the old constraint is a range constraint, check if this changes with the new sides */
    1238 if( lhss == NULL || rhss == NULL || SCIPisInfinity(scip, -lhss[i]) || SCIPisInfinity(scip, rhss[i]) ||
    1239 SCIPisEQ(scip, lhss[i], rhss[i]) )
    1240 {
    1241 problem->firstrun = TRUE;
    1242 break;
    1243 }
    1244 }
    1245 else
    1246 {
    1247 /* the old constraint is not a range constraint, check if this changes with the new sides */
    1248 if( lhss != NULL && rhss != NULL && !SCIPisInfinity(scip, -lhss[i]) && !SCIPisInfinity(scip, rhss[i]) &&
    1249 SCIPisLT(scip, lhss[i], rhss[i]) )
    1250 {
    1251 problem->firstrun = TRUE;
    1252 break;
    1253 }
    1254 }
    1255 }
    1256
    1257 SCIP_CALL( SCIPnlpiOracleChgConsSides(scip, oracle, nconss, indices, lhss, rhss) );
    1258
    1259 invalidateSolution(problem);
    1260
    1261 return SCIP_OKAY; /*lint !e527*/
    1262} /*lint !e715*/
    1263
    1264/** delete a set of variables */
    1265static
    1266SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetConopt)
    1267{
    1268 assert(nlpi != NULL);
    1269 assert(problem != NULL);
    1270 assert(problem->oracle != NULL);
    1271
    1272 SCIP_CALL( SCIPnlpiOracleDelVarSet(scip, problem->oracle, dstats) );
    1273
    1274 invalidateSolution(problem);
    1275 problem->firstrun = TRUE;
    1276
    1277 return SCIP_OKAY; /*lint !e527*/
    1278} /*lint !e715*/
    1279
    1280/** delete a set of constraints */
    1281static
    1282SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetConopt)
    1283{
    1284 assert(nlpi != NULL);
    1285 assert(problem != NULL);
    1286 assert(problem->oracle != NULL);
    1287
    1288 SCIP_CALL( SCIPnlpiOracleDelConsSet(scip, problem->oracle, dstats) );
    1289
    1290 invalidateSolution(problem);
    1291 problem->firstrun = TRUE;
    1292
    1293 return SCIP_OKAY; /*lint !e527*/
    1294} /*lint !e715*/
    1295
    1296/** changes (or adds) linear coefficients in a constraint or objective */
    1297static
    1298SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsConopt)
    1299{
    1300 assert(nlpi != NULL);
    1301 assert(problem != NULL);
    1302 assert(problem->oracle != NULL);
    1303
    1304 SCIP_CALL( SCIPnlpiOracleChgLinearCoefs(scip, problem->oracle, idx, nvals, varidxs, vals) );
    1305
    1306 invalidateSolution(problem);
    1307 problem->firstrun = TRUE;
    1308
    1309 return SCIP_OKAY; /*lint !e527*/
    1310} /*lint !e715*/
    1311
    1312/** replaces the expression tree of a constraint or objective */
    1313static
    1314SCIP_DECL_NLPICHGEXPR(nlpiChgExprConopt)
    1315{
    1316 assert(nlpi != NULL);
    1317 assert(problem != NULL);
    1318 assert(problem->oracle != NULL);
    1319
    1320 SCIP_CALL( SCIPnlpiOracleChgExpr(scip, problem->oracle, idxcons, expr) );
    1321
    1322 invalidateSolution(problem);
    1323 problem->firstrun = TRUE;
    1324
    1325 return SCIP_OKAY; /*lint !e527*/
    1326} /*lint !e715*/
    1327
    1328/** change the constant offset in the objective */
    1329static
    1330SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantConopt)
    1331{
    1332 assert(nlpi != NULL);
    1333 assert(problem != NULL);
    1334 assert(problem->oracle != NULL);
    1335
    1336 SCIP_CALL( SCIPnlpiOracleChgObjConstant(scip, problem->oracle, objconstant) );
    1337
    1338 return SCIP_OKAY; /*lint !e527*/
    1339} /*lint !e715*/
    1340
    1341/** sets initial guess */
    1342static
    1343SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessConopt)
    1344{
    1345 assert(nlpi != NULL);
    1346 assert(problem != NULL);
    1347 assert(problem->oracle != NULL);
    1348
    1349 if( primalvalues != NULL )
    1350 {
    1351 if( !problem->initguess )
    1352 {
    1353 SCIP_CALL( SCIPduplicateMemoryArray(scip, &problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle)) );
    1354 }
    1355 else
    1356 BMScopyMemoryArray(problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle));
    1357 }
    1358 else
    1359 SCIPfreeMemoryArrayNull(scip, &problem->initguess);
    1360
    1361 return SCIP_OKAY;
    1362} /*lint !e715*/
    1363
    1364/** try to solve NLP
    1365 *
    1366 * Note that SCIP will already have reset a timelimit of SCIP_REAL_MAX to the time remaining for the SCIP solve in SCIPnlpiSolve().
    1367 */
    1368static
    1369SCIP_DECL_NLPISOLVE(nlpiSolveConopt)
    1370{
    1371 SCIP_NLPIDATA* data;
    1372 int COI_Error; /* CONOPT error counter */
    1373
    1374 assert(nlpi != NULL);
    1375 assert(problem != NULL);
    1376
    1377 data = SCIPnlpiGetData(nlpi);
    1378 assert(data != NULL);
    1379
    1380 SCIPdebugMsg(scip, "solve with parameters " SCIP_NLPPARAM_PRINT(param));
    1381
    1382 SCIP_CALL( SCIPnlpiOracleResetEvalTime(scip, problem->oracle) );
    1383
    1384 if( param.timelimit == 0.0 )
    1385 {
    1386 /* there is nothing we can do if we are not given any time */
    1387 problem->niterations = 0;
    1388 problem->solvetime = 0.0;
    1389 problem->termstat = SCIP_NLPTERMSTAT_TIMELIMIT;
    1390 problem->solstat = SCIP_NLPSOLSTAT_UNKNOWN;
    1391
    1392 return SCIP_OKAY;
    1393 }
    1394
    1395 problem->niterations = -1;
    1396 problem->solvetime = -1.0;
    1397
    1398 /* set CONOPT parameters */
    1399 handleConoptParam(problem, param);
    1400
    1401 /* initialize Conopt data if necessary */
    1402 if( problem->firstrun )
    1403 {
    1404 SCIP_CALL( initConopt(scip, data, problem) );
    1405 problem->firstrun = FALSE;
    1406 }
    1407
    1408 /* measure time */
    1409 SCIP_CALL( SCIPresetClock(scip, data->solvetime) );
    1410 SCIP_CALL( SCIPstartClock(scip, data->solvetime) );
    1411
    1412 /* optimize */
    1413 COI_Error = COI_Solve(problem->CntVect);
    1414
    1415 /* CONOPT may return either a positive error code, which is one of its own error codes,
    1416 * or a negative error code that is a SCIP_RETCODE returned from one of the callbacks */
    1417 if( COI_Error )
    1418 {
    1419 switch( COI_Error )
    1420 {
    1421 case -1:
    1422 SCIPdebugMsg(scip, "Insufficient memory in CONOPT callback\n");
    1423 break;
    1424 case -2:
    1425 SCIPdebugMsg(scip, "Problem structure computation error in CONOPT's ReadMatrix callback\n");
    1426 break;
    1427 default:
    1428 SCIPdebugMsg(scip, "Errors encountered in CONOPT during solution, %d\n", COI_Error);
    1429 }
    1430 }
    1431
    1432 /* store statistics (some statistics are passed back to SCIP by the Status callback) */
    1433 problem->solvetime = SCIPgetClockTime(scip, data->solvetime);
    1434
    1435 return SCIP_OKAY; /*lint !e527*/
    1436} /*lint !e715*/
    1437
    1438/** gives solution status */
    1439static
    1440SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatConopt)
    1441{
    1442 assert(nlpi != NULL);
    1443 assert(problem != NULL);
    1444
    1445 return problem->solstat;
    1446} /*lint !e715*/
    1447
    1448/** gives termination reason */
    1449static
    1450SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatConopt)
    1451{
    1452 assert(nlpi != NULL);
    1453 assert(problem != NULL);
    1454
    1455 return problem->termstat;
    1456} /*lint !e715*/
    1457
    1458/** gives primal and dual solution values */
    1459static
    1460SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionConopt)
    1461{
    1462 assert(problem != NULL);
    1463
    1464 if( primalvalues != NULL )
    1465 *primalvalues = problem->lastprimal;
    1466
    1467 if( consdualvalues != NULL )
    1468 *consdualvalues = problem->lastdualcons;
    1469
    1470 if( varlbdualvalues != NULL )
    1471 *varlbdualvalues = problem->lastduallb;
    1472
    1473 if( varubdualvalues != NULL )
    1474 *varubdualvalues = problem->lastdualub;
    1475
    1476 if( objval != NULL )
    1477 *objval = problem->objval;
    1478
    1479 return SCIP_OKAY; /*lint !e527*/
    1480} /*lint !e715*/
    1481
    1482/** gives solve statistics */
    1483static
    1484SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsConopt)
    1485{
    1486 assert(nlpi != NULL);
    1487 assert(problem != NULL);
    1488 assert(statistics != NULL);
    1489
    1490 statistics->niterations = problem->niterations;
    1491 statistics->totaltime = problem->solvetime;
    1492 statistics->evaltime = SCIPnlpiOracleGetEvalTime(scip, problem->oracle);
    1493 statistics->consviol = SCIP_INVALID; /* TODO currently unavailable in CONOPT; might change */
    1494 statistics->boundviol = 0.0;
    1495
    1496 return SCIP_OKAY;
    1497} /*lint !e715*/
    1498
    1499/*
    1500 * NLP solver interface specific interface methods
    1501 */
    1502
    1503/** create solver interface for Conopt solver and includes it into SCIP */
    1505 SCIP* scip /**< SCIP data structure */
    1506 )
    1507{
    1508 SCIP_NLPIDATA* nlpidata;
    1509
    1510 /* create Conopt solver interface data */
    1512
    1513#if defined(CONOPT_LICENSE_INT_1) && defined(CONOPT_LICENSE_INT_2) && defined(CONOPT_LICENSE_INT_3) && \
    1514 defined(CONOPT_LICENSE_TEXT)
    1515 nlpidata->license_int_1 = CONOPT_LICENSE_INT_1;
    1516 nlpidata->license_int_2 = CONOPT_LICENSE_INT_2;
    1517 nlpidata->license_int_3 = CONOPT_LICENSE_INT_3;
    1518 (void) SCIPsnprintf(nlpidata->license_text, (int)sizeof(nlpidata->license_text), "%s", CONOPT_LICENSE_TEXT);
    1519#endif
    1520
    1521 /* create and include solver interface */
    1524 nlpiCopyConopt, nlpiFreeConopt, nlpiGetSolverPointerConopt,
    1525 nlpiCreateProblemConopt, nlpiFreeProblemConopt, nlpiGetProblemPointerConopt,
    1526 nlpiAddVarsConopt, nlpiAddConstraintsConopt, nlpiSetObjectiveConopt,
    1527 nlpiChgVarBoundsConopt, nlpiChgConsSidesConopt, nlpiDelVarSetConopt, nlpiDelConstraintSetConopt,
    1528 nlpiChgLinearCoefsConopt, nlpiChgExprConopt, nlpiChgObjConstantConopt,
    1529 nlpiSetInitialGuessConopt, nlpiSolveConopt,
    1530 nlpiGetSolstatConopt, nlpiGetTermstatConopt, nlpiGetSolutionConopt, nlpiGetStatisticsConopt,
    1531 nlpidata) );
    1532
    1534
    1535 return SCIP_OKAY;
    1536}
    1537
    1538/** sets the license to be passed to CONOPT's COIDEF_License */
    1540 SCIP_NLPI* nlpi, /**< CONOPT NLPI */
    1541 int integer_1, /**< CONOPT_LICENSE_INT_1 */
    1542 int integer_2, /**< CONOPT_LICENSE_INT_2 */
    1543 int integer_3, /**< CONOPT_LICENSE_INT_3 */
    1544 const char* text /**< CONOPT_LICENSE_TEXT */
    1545 )
    1546{
    1547 SCIP_NLPIDATA* data;
    1548 assert(nlpi != NULL);
    1549
    1550 data = SCIPnlpiGetData(nlpi);
    1551 assert(data != NULL);
    1552
    1553 data->license_int_1 = integer_1;
    1554 data->license_int_2 = integer_2;
    1555 data->license_int_3 = integer_3;
    1556 (void) SCIPsnprintf(data->license_text, (int)sizeof(data->license_text), "%s", text);
    1557}
    1558
    1559#define STR_HELPER(x) #x
    1560#define STR(x) STR_HELPER(x)
    1561
    1562/** gets string that identifies CONOPT */
    1564 void
    1565 )
    1566{
    1567 return "CONOPT " STR(CONOPT_VERSION_MAJOR) "." STR(CONOPT_VERSION_MINOR) "." STR(CONOPT_VERSION_PATCH);
    1568}
    1569
    1570/** gets string that describes CONOPT */
    1572 void
    1573 )
    1574{
    1575 return "Feasible path solver for large-scale nonlinear problems (conopt.com)";
    1576}
    1577
    1578/** returns whether CONOPT is available, i.e., whether it has been linked in */
    1580 void
    1581 )
    1582{
    1583 return TRUE;
    1584}
    #define NULL
    Definition: def.h:255
    #define SCIP_REAL_MAX
    Definition: def.h:165
    #define SCIP_INVALID
    Definition: def.h:185
    #define SCIP_Bool
    Definition: def.h:98
    #define MIN(x, y)
    Definition: def.h:231
    #define SCIP_Real
    Definition: def.h:163
    #define TRUE
    Definition: def.h:100
    #define FALSE
    Definition: def.h:101
    #define MAX(x, y)
    Definition: def.h:227
    #define SCIPABORT()
    Definition: def.h:334
    #define SCIP_CALL(x)
    Definition: def.h:362
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPincludeNlpSolverConopt(SCIP *scip)
    Definition: nlpi_conopt.c:1504
    SCIP_RETCODE SCIPnlpiOracleEvalObjectiveValue(SCIP *scip, SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Real *objval)
    Definition: nlpioracle.c:2124
    SCIP_RETCODE SCIPnlpiOracleChgLinearCoefs(SCIP *scip, SCIP_NLPIORACLE *oracle, int considx, int nentries, const int *varidxs, const SCIP_Real *newcoefs)
    Definition: nlpioracle.c:1774
    SCIP_RETCODE SCIPnlpiOracleGetHessianLagSparsity(SCIP *scip, SCIP_NLPIORACLE *oracle, const int **offset, const int **allnz, SCIP_Bool colwise)
    Definition: nlpioracle.c:2670
    SCIP_RETCODE SCIPnlpiOracleChgVarBounds(SCIP *scip, SCIP_NLPIORACLE *oracle, int nvars, const int *indices, const SCIP_Real *lbs, const SCIP_Real *ubs)
    Definition: nlpioracle.c:1474
    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)
    Definition: nlpioracle.c:1384
    SCIP_RETCODE SCIPnlpiOracleDelVarSet(SCIP *scip, SCIP_NLPIORACLE *oracle, int *delstats)
    Definition: nlpioracle.c:1546
    SCIP_RETCODE SCIPnlpiOracleCreate(SCIP *scip, SCIP_NLPIORACLE **oracle)
    Definition: nlpioracle.c:1200
    SCIP_RETCODE SCIPnlpiOracleEvalObjectiveGradient(SCIP *scip, SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *objval, SCIP_Real *objgrad)
    Definition: nlpioracle.c:2205
    SCIP_RETCODE SCIPnlpiOracleResetEvalTime(SCIP *scip, SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:2821
    SCIP_RETCODE SCIPnlpiOracleSetObjective(SCIP *scip, SCIP_NLPIORACLE *oracle, const SCIP_Real constant, int nlin, const int *lininds, const SCIP_Real *linvals, SCIP_EXPR *expr)
    Definition: nlpioracle.c:1445
    SCIP_Real SCIPnlpiOracleGetConstraintRhs(SCIP_NLPIORACLE *oracle, int considx)
    Definition: nlpioracle.c:2038
    SCIP_Real SCIPnlpiOracleGetEvalTime(SCIP *scip, SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:2837
    SCIP_RETCODE SCIPnlpiOracleChgConsSides(SCIP *scip, SCIP_NLPIORACLE *oracle, int nconss, const int *indices, const SCIP_Real *lhss, const SCIP_Real *rhss)
    Definition: nlpioracle.c:1511
    SCIP_Real SCIPnlpiOracleGetConstraintLhs(SCIP_NLPIORACLE *oracle, int considx)
    Definition: nlpioracle.c:2025
    SCIP_RETCODE SCIPnlpiOracleGetJacobianColSparsity(SCIP *scip, SCIP_NLPIORACLE *oracle, const int **coloffsets, const int **rows, const SCIP_Bool **rownlflags, int *nnlnz)
    Definition: nlpioracle.c:2318
    SCIP_RETCODE SCIPnlpiOracleAddVars(SCIP *scip, SCIP_NLPIORACLE *oracle, int nvars, const SCIP_Real *lbs, const SCIP_Real *ubs, const char **varnames)
    Definition: nlpioracle.c:1298
    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)
    Definition: nlpioracle.c:2770
    SCIP_RETCODE SCIPnlpiOracleEvalConstraintGradient(SCIP *scip, SCIP_NLPIORACLE *oracle, const int considx, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *conval, SCIP_Real *congrad)
    Definition: nlpioracle.c:2234
    int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1933
    int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1943
    SCIP_RETCODE SCIPnlpiOracleGetObjGradientNnz(SCIP *scip, SCIP_NLPIORACLE *oracle, const int **nz, const SCIP_Bool **nlnz, int *nnz, int *nnlnz)
    Definition: nlpioracle.c:2410
    SCIP_RETCODE SCIPnlpiOracleDelConsSet(SCIP *scip, SCIP_NLPIORACLE *oracle, int *delstats)
    Definition: nlpioracle.c:1688
    SCIP_RETCODE SCIPnlpiOracleSetProblemName(SCIP *scip, SCIP_NLPIORACLE *oracle, const char *name)
    Definition: nlpioracle.c:1262
    SCIP_RETCODE SCIPnlpiOracleChgObjConstant(SCIP *scip, SCIP_NLPIORACLE *oracle, SCIP_Real objconstant)
    Definition: nlpioracle.c:1916
    SCIP_RETCODE SCIPnlpiOracleEvalConstraintValue(SCIP *scip, SCIP_NLPIORACLE *oracle, int considx, const SCIP_Real *x, SCIP_Real *conval)
    Definition: nlpioracle.c:2149
    SCIP_Real SCIPnlpiOracleGetConstraintLinearCoef(SCIP_NLPIORACLE *oracle, int considx, int varpos)
    Definition: nlpioracle.c:2064
    const SCIP_Real * SCIPnlpiOracleGetVarLbs(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1953
    const SCIP_Real * SCIPnlpiOracleGetVarUbs(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1963
    SCIP_RETCODE SCIPnlpiOracleFree(SCIP *scip, SCIP_NLPIORACLE **oracle)
    Definition: nlpioracle.c:1230
    SCIP_RETCODE SCIPnlpiOracleChgExpr(SCIP *scip, SCIP_NLPIORACLE *oracle, int considx, SCIP_EXPR *expr)
    Definition: nlpioracle.c:1870
    void SCIPsetLicenseConopt(SCIP_NLPI *nlpi, int integer_1, int integer_2, int integer_3, const char *text)
    Definition: nlpi_conopt.c:1539
    const char * SCIPgetSolverDescConopt(void)
    Definition: nlpi_conopt.c:1571
    SCIP_Bool SCIPisConoptAvailableConopt(void)
    Definition: nlpi_conopt.c:1579
    const char * SCIPgetSolverNameConopt(void)
    Definition: nlpi_conopt.c:1563
    SCIP_RETCODE SCIPincludeExternalCodeInformation(SCIP *scip, const char *name, const char *description)
    Definition: scip_general.c:769
    #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)
    Definition: scip_timing.c:144
    SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:127
    SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:319
    SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:161
    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)
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    static SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesConopt)
    Definition: nlpi_conopt.c:1211
    static SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsConopt)
    Definition: nlpi_conopt.c:1298
    static int COI_CALLCONV LagrStr(int HSRW[], int HSCL[], int *NODRV, int NUMVAR, int NUMCON, int NHESS, void *USRMEM)
    Definition: nlpi_conopt.c:782
    #define NLPI_PRIORITY
    Definition: nlpi_conopt.c:57
    #define STR(x)
    Definition: nlpi_conopt.c:1560
    #define MAXPERTURB
    Definition: nlpi_conopt.c:60
    static SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemConopt)
    Definition: nlpi_conopt.c:1097
    static void handleConoptParam(SCIP_NLPIPROBLEM *problem, const SCIP_NLPPARAM param)
    Definition: nlpi_conopt.c:967
    static SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantConopt)
    Definition: nlpi_conopt.c:1330
    static SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsConopt)
    Definition: nlpi_conopt.c:1163
    static SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveConopt)
    Definition: nlpi_conopt.c:1180
    static SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatConopt)
    Definition: nlpi_conopt.c:1440
    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)
    Definition: nlpi_conopt.c:222
    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)
    Definition: nlpi_conopt.c:698
    #define NLPI_NAME
    Definition: nlpi_conopt.c:55
    static SCIP_DECL_NLPICHGEXPR(nlpiChgExprConopt)
    Definition: nlpi_conopt.c:1314
    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)
    Definition: nlpi_conopt.c:823
    static SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemConopt)
    Definition: nlpi_conopt.c:1068
    #define nlpiGetSolverPointerConopt
    Definition: nlpi_conopt.c:1063
    static SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetConopt)
    Definition: nlpi_conopt.c:1266
    #define nlpiGetProblemPointerConopt
    Definition: nlpi_conopt.c:1141
    static SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetConopt)
    Definition: nlpi_conopt.c:1282
    static SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsConopt)
    Definition: nlpi_conopt.c:1196
    #define DEFAULT_RANDSEED
    Definition: nlpi_conopt.c:59
    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)
    Definition: nlpi_conopt.c:123
    static int COI_CALLCONV ErrMsg(int ROWNO, int COLNO, int POSNO, const char *MSG, void *USRMEM)
    Definition: nlpi_conopt.c:542
    static SCIP_RETCODE initConopt(SCIP *scip, SCIP_NLPIDATA *data, SCIP_NLPIPROBLEM *problem)
    Definition: nlpi_conopt.c:870
    static int COI_CALLCONV Status(int MODSTA, int SOLSTA, int ITER, double OBJVAL, void *USRMEM)
    Definition: nlpi_conopt.c:569
    static SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatConopt)
    Definition: nlpi_conopt.c:1450
    static SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionConopt)
    Definition: nlpi_conopt.c:1460
    static SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessConopt)
    Definition: nlpi_conopt.c:1343
    static SCIP_DECL_NLPIADDVARS(nlpiAddVarsConopt)
    Definition: nlpi_conopt.c:1146
    static SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsConopt)
    Definition: nlpi_conopt.c:1484
    static SCIP_DECL_NLPIFREE(nlpiFreeConopt)
    Definition: nlpi_conopt.c:1034
    static int COI_CALLCONV Message(int SMSG, int DMSG, int NMSG, char *MSGV[], void *USRMEM)
    Definition: nlpi_conopt.c:510
    static int COI_CALLCONV Option(int NCALL, double *RVAL, int *IVAL, int *LVAL, char *NAME, void *USRMEM)
    Definition: nlpi_conopt.c:744
    static SCIP_DECL_NLPICOPY(nlpiCopyConopt)
    Definition: nlpi_conopt.c:1008
    #define NLPI_DESC
    Definition: nlpi_conopt.c:56
    static SCIP_DECL_NLPISOLVE(nlpiSolveConopt)
    Definition: nlpi_conopt.c:1369
    static void invalidateSolution(SCIP_NLPIPROBLEM *problem)
    Definition: nlpi_conopt.c:853
    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 opttol
    Definition: nlpi_conopt.c:101
    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
    #define SCIP_NLPPARAM_PRINT(param)
    Definition: type_nlpi.h:142
    enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
    Definition: type_nlpi.h:168
    @ 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_NLPIGETSOLVERPOINTER(x)
    Definition: type_nlpi.h:233
    #define SCIP_DECL_NLPIGETPROBLEMPOINTER(x)
    Definition: type_nlpi.h:272
    @ 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
    enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
    Definition: type_nlpi.h:184
    struct SCIP_NlpiData SCIP_NLPIDATA
    Definition: type_nlpi.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63