Scippy

    SCIP

    Solving Constraint Integer Programs

    nlpi_filtersqp.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-2025 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_filtersqp.c
    26 * @ingroup DEFPLUGINS_NLPI
    27 * @brief filterSQP NLP interface
    28 * @author Stefan Vigerske
    29 *
    30 * @todo scaling
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    35#include <string.h>
    36#ifdef _WIN32
    37#include <windows.h>
    38#else
    39#include <sys/time.h>
    40#endif
    41
    42#include "scip/nlpi_filtersqp.h"
    43#include "scip/nlpioracle.h"
    44#include "scip/scip_general.h"
    45#include "scip/scip_message.h"
    46#include "scip/scip_mem.h"
    47#include "scip/scip_numerics.h"
    48#include "scip/scip_nlpi.h"
    50#include "scip/scip_solve.h"
    51#include "scip/pub_misc.h"
    52#include "scip/pub_message.h"
    53
    54/* fallback to non-thread version for windows, because pthread does not exist */
    55#if defined(_MSC_VER) && defined(SCIP_THREADSAFE)
    56#undef SCIP_THREADSAFE
    57#endif
    58
    59#ifdef SCIP_THREADSAFE
    60#include <pthread.h>
    61#endif
    62
    63#define NLPI_NAME "filtersqp" /**< short concise name of solver */
    64#define NLPI_DESC "Sequential Quadratic Programming trust region solver by R. Fletcher and S. Leyffer" /**< description of solver */
    65#define NLPI_PRIORITY -1000 /**< priority of NLP solver */
    66
    67#define RANDSEED 26051979 /**< initial random seed */
    68#define MAXPERTURB 0.01 /**< maximal perturbation of bounds in starting point heuristic */
    69#define MAXNRUNS 3 /**< maximal number of FilterSQP calls per NLP solve (several calls if increasing workspace or decreasing eps) */
    70#define WORKSPACEGROWTHFACTOR 2 /**< factor by which to increase workspace */
    71#define MINEPS 1e-14 /**< minimal FilterSQP epsilon */
    72#define OPTTOLFACTOR 0.5 /**< factor to apply to optimality tolerance, because FilterSQP do scaling */
    73
    74/*
    75 * Data structures
    76 */
    77
    78typedef int fint;
    79typedef double real;
    80typedef long ftnlen;
    81
    83{
    84 time_t sec; /**< seconds part of time since epoch */
    85 long usec; /**< micro-seconds part of time */
    86};
    87typedef struct SCIP_Time SCIP_TIME;
    88
    89struct SCIP_NlpiData
    90{
    91 SCIP_RANDNUMGEN* randnumgen; /**< random number generator, if we have to make up a starting point */
    92 SCIP_TIME starttime; /**< time at start of solve */
    93};
    94
    96{
    97 SCIP* scip; /**< SCIP data structure */
    98 SCIP_NLPIORACLE* oracle; /**< Oracle-helper to store and evaluate NLP */
    99
    100 int varssize; /**< length of variables-related arrays, if allocated */
    101 int conssize; /**< length of constraints-related arrays, if allocated */
    102
    103 SCIP_Real* initguess; /**< initial values for primal variables, or NULL if not known, size varssize */
    104 SCIP_Bool warmstart; /**< whether we could warmstart the next solve */
    105
    106 SCIP_Real* primalvalues; /**< primal values of variables in solution, size varssize */
    107 SCIP_Real* consdualvalues; /**< dual values of constraints in solution, size conssize */
    108 SCIP_Real* varlbdualvalues; /**< dual values of variable lower bounds in solution, size varssize */
    109 SCIP_Real* varubdualvalues; /**< dual values of variable upper bounds in solution, size varssize */
    110
    111 SCIP_NLPSOLSTAT solstat; /**< solution status from last NLP solve */
    112 SCIP_NLPTERMSTAT termstat; /**< termination status from last NLP solve */
    113 SCIP_Real solvetime; /**< time spend for last NLP solve */
    114 int niterations; /**< number of iterations for last NLP solve */
    115
    116 fint istat[14]; /**< integer solution statistics from last FilterSQP call */
    117 real rstat[7]; /**< real solution statistics from last FilterSQP call */
    118 real fmin; /**< lower bound on objective value */
    119 SCIP_Real maxtime; /**< time limit */
    120
    121 /* cached FilterSQP data */
    122 real* x; /**< variable values, size varssize */
    123 real* c; /**< constraint value, size conssize */
    124 real* lam; /**< duals, size varssize + conssize */
    125 real* bl; /**< variable lower bounds and constraint lhs, size varssize + conssize */
    126 real* bu; /**< variable upper bounds and constraint rhs, size varssize + conssize */
    127 real* s; /**< scaling factors, size varssize + conssize */
    128 char* cstype; /**< constraint linearity, size conssize */
    129 real* a; /**< gradients values, size la[0]-1 */
    130 fint* la; /**< gradients indices, size lasize */
    131 int lasize; /**< length of la array */
    132 fint* hessiannz; /**< nonzero information about Hessian, size hessiannzsize */
    133 int hessiannzsize;/**< length of hessiannz array */
    134 real* ws; /**< real workspace, size mxwk */
    135 fint* lws; /**< integer workspace, size mxiwk */
    136 fint mxwk; /**< size of real workspace */
    137 fint mxiwk; /**< size of integer workspace */
    138 real* evalbuffer; /**< buffer to cache evaluation results before passing it to FilterSQP, size evalbufsize */
    139 int evalbufsize; /**< size of evaluation buffer */
    140};
    141
    142/*
    143 * Local methods
    144 */
    145
    146#ifdef FNAME_LCASE_DECOR
    147# define F77_FUNC(name,NAME) name ## _
    148#endif
    149#ifdef FNAME_UCASE_DECOR
    150# define F77_FUNC(name,NAME) NAME ## _
    151#endif
    152#ifdef FNAME_LCASE_NODECOR
    153# define F77_FUNC(name,NAME) name
    154#endif
    155#ifdef FNAME_UCASE_NODECOR
    156# define F77_FUNC(name,NAME) NAME
    157#endif
    158
    159/** FilterSQP main routine.
    160 *
    161 * Array a has length nnza, which is the number of nonzeros in the gradient of the objective and the Jacobian.
    162 * The first entries of a is the objective gradient, next are the gradients of the constraints.
    163 *
    164 * Array la has length lamax, which is at least nnza+m+2.
    165 * la contains the index information of a row-oriented sparse matrix storage. It stores the number of nonzeros, the column indices, and the row starts:
    166 * la[0] must be set to nnza+1.
    167 * la[1]..la[nnza] are indices of the variables corresponding to the entries in a (colidx).
    168 * la[nnza+1]..la[nnza+1+m] contain the index where each row starts in a and la (rowstart).
    169 */
    170void F77_FUNC(filtersqp,FILTERSQP)(
    171 fint* n, /**< number of variables */
    172 fint* m, /**< number of constraints (excluding simple bounds) */
    173 fint* kmax, /**< maximum size of null-space (at most n) */
    174 fint* maxa, /**< maximum number of nonzero entries allowed in Jacobian */
    175 fint* maxf, /**< maximum size of the filter - typically 100 */
    176 fint* mlp, /**< maximum level parameter for resolving degeneracy in bqpd - typically 100 */
    177 fint* mxwk, /**< maximum size of real workspace ws */
    178 fint* mxiwk, /**< maximum size of integer workspace lws */
    179 fint* iprint, /**< print flag: 0 is quiet, higher is more */
    180 fint* nout, /**< output channel - 6 for screen */
    181 fint* ifail, /**< fail flag and warmstart indicator */
    182 real* rho, /**< initial trust-region radius - default 10 */
    183 real* x, /**< starting point and final solution (array of length n) */
    184 real* c, /**< final values of general constraints (array of length m) */
    185 real* f, /**< final objective value */
    186 real* fmin, /**< lower bound on objective value (as termination criteria) */
    187 real* bl, /**< lower bounds of variables and constraints (array of length n+m) */
    188 real* bu, /**< upper bounds of variables and constraints (array of length n+m) */
    189 real* s, /**< scaling factors (array of length n+m) */
    190 real* a, /**< objective gradient (always dense) and Jacobian (sparse or dense) entries */
    191 fint* la, /**< column indices and length of rows of entries in a (if sparse) or leading dimension of a (if dense) */
    192 real* ws, /**< real workspace (array of length mxwk) */
    193 fint* lws, /**< integer workspace (array of length mxiwk) */
    194 real* lam, /**< Lagrangian multipliers of simple bounds and general constraints (array of length n+m) */
    195 char* cstype, /**< indicator whether constraint is linear ('L') or nonlinear ('N') (array of length m) */
    196 real* user, /**< real workspace passed through to user routines */
    197 fint* iuser, /**< integer workspace passed through to user routines */
    198 fint* maxiter, /**< iteration limit for SQP solver */
    199 fint* istat, /**< integer space for solution statistics (array of length 14) */
    200 real* rstat, /**< real space for solution statitics (array of length 7) */
    201 ftnlen cstype_len /**< 1 ??? */
    202 );
    203
    204void F77_FUNC(objfun,OBJFUN)(real *x, fint *n, real *f, real *user, fint *iuser,
    205 fint *errflag);
    206
    207void F77_FUNC(confun,CONFUN)(real *x, fint *n, fint *m, real *c, real *a, fint *la,
    208 real *user, fint *iuser, fint *errflag);
    209
    210/* TODO what are the arguments of this function and does it need to be implemented?
    211 * it's not in the filterSQP manual, but its an undefined symbol in the filterSQP library
    212void F77_FUNC(objgrad,OBJGRAD)(fint *, fint *, fint *, real *, real *, fint *, fint
    213 *, real *, fint *, fint *);
    214*/
    215void F77_FUNC(objgrad,OBJGRAD)(void);
    216
    217void F77_FUNC(gradient,GRADIENT)(fint *n, fint *m, fint *mxa, real *x, real *a, fint *la,
    218 fint *maxa, real *user, fint *iuser, fint *errflag);
    219
    220void F77_FUNC(hessian,HESSIAN)(real *x, fint *n, fint *m, fint *phase, real *lam,
    221 real *ws, fint *lws, real *user, fint *iuser,
    222 fint *l_hess, fint *li_hess, fint *errflag);
    223
    224/** common block for problemname */
    225/*lint -esym(754,char_l,pname,*::char_l,*::pname) */
    226extern struct
    227{
    228 fint char_l;
    229 char pname[10];
    230} F77_FUNC(cpname,CPNAME);
    231/*lint -esym(752,cpname_) */
    232
    233/** common block for Hessian storage set to 0, i.e. NO Hessian */
    234/*lint -esym(754,*::phr,*::phc) */
    235extern struct
    236{
    238} F77_FUNC(hessc,HESSC);
    239/*lint -esym(754,phr,phc) */
    240
    241/** common block for upper bound on filter */
    242extern struct
    243{
    245} F77_FUNC(ubdc,UBDC);
    246
    247/** common block for infinity & epsilon */
    248extern struct
    249{
    251} F77_FUNC(nlp_eps_inf,NLP_EPS_INF);
    252
    253/** common block for printing from QP solver */
    254/*lint -esym(754,*::n_bqpd_calls,*::n_bqpd_prfint) */
    255extern struct
    256{
    258} F77_FUNC(bqpd_count,BQPD_COUNT);
    259/*lint -esym(752,bqpd_count_) */
    260/*lint -esym(754,n_bqpd_calls,n_bqpd_prfint) */
    261
    262/** common for scaling: scale_mode = 0 (none), 1 (variables), 2 (vars+cons) */
    263/*lint -esym(754,*::phe) */
    264extern struct
    265{
    267} F77_FUNC(scalec,SCALEC);
    268/*lint -esym(754,phe) */
    269
    270#ifdef SCIP_THREADSAFE
    271static pthread_mutex_t filtersqpmutex = PTHREAD_MUTEX_INITIALIZER; /*lint !e708*/
    272#endif
    273
    274static
    276{
    277 SCIP_TIME t;
    278#ifndef _WIN32
    279 struct timeval tp; /*lint !e86*/
    280#endif
    281
    282#ifdef _WIN32
    283 t.sec = time(NULL);
    284 t.usec = 0;
    285
    286#else
    287 (void) gettimeofday(&tp, NULL);
    288 t.sec = tp.tv_sec;
    289 t.usec = tp.tv_usec;
    290#endif
    291
    292 return t;
    293}
    294
    295/* gives time since starttime (in problem) */
    296static
    298 SCIP_NLPIDATA* nlpidata /**< NLPI data */
    299 )
    300{
    301 SCIP_TIME now;
    302
    303 assert(nlpidata != NULL);
    304
    305 now = gettime();
    306
    307 /* now should be after startime */
    308 assert(now.sec >= nlpidata->starttime.sec);
    309 assert(now.sec > nlpidata->starttime.sec || now.usec >= nlpidata->starttime.usec);
    310
    311 return (SCIP_Real)(now.sec - nlpidata->starttime.sec) + 1e-6 * (SCIP_Real)(now.usec - nlpidata->starttime.usec);
    312}
    313
    314static
    316 SCIP_NLPIDATA* nlpidata, /**< NLPI data */
    317 SCIP_NLPIPROBLEM* nlpiproblem /**< NLPI problem */
    318 )
    319{
    320 if( nlpiproblem->maxtime == SCIP_REAL_MAX ) /*lint !e777 */
    321 return FALSE;
    322
    323 return timeelapsed(nlpidata) >= nlpiproblem->maxtime;
    324}
    325
    326/** Objective function evaluation */ /*lint -e{715} */
    327void F77_FUNC(objfun,OBJFUN)(
    328 real* x, /**< value of current variables (array of length n) */
    329 fint* n, /**< number of variables */
    330 real* f, /**< buffer to store value of objective function */
    331 real* user, /**< user real workspace */
    332 fint* iuser, /**< user integer workspace */
    333 fint* errflag /**< set to 1 if arithmetic exception occurs, otherwise 0 */
    334 )
    335{ /*lint --e{715} */
    336 SCIP_NLPIPROBLEM* problem;
    337 real val;
    338
    339 problem = (SCIP_NLPIPROBLEM*)(void*)iuser;
    340 assert(problem != NULL);
    341
    342 if( SCIPisSolveInterrupted(problem->scip) || timelimitreached((SCIP_NLPIDATA*)(void*)user, problem) )
    343 {
    344 SCIPdebugMsg(problem->scip, "interrupted or timelimit reached, issuing arithmetic exception in objfun\n");
    345 *errflag = 1;
    346 return;
    347 }
    348
    349 *errflag = 1;
    350 if( SCIPnlpiOracleEvalObjectiveValue(problem->scip, problem->oracle, x, &val) == SCIP_OKAY && SCIPisFinite(val) )
    351 {
    352 *errflag = 0;
    353 *f = val;
    354 }
    355 else
    356 {
    357 SCIPdebugMsg(problem->scip, "arithmetic exception in objfun\n");
    358 }
    359}
    360
    361/** Constraint functions evaluation */ /*lint -e{715} */
    362void F77_FUNC(confun,CONFUN)(
    363 real* x, /**< value of current variables (array of length n) */
    364 fint* n, /**< number of variables */
    365 fint* m, /**< number of constraints */
    366 real* c, /**< buffer to store values of constraints (array of length m) */
    367 real* a, /**< Jacobian matrix entries */
    368 fint* la, /**< Jacobian index information */
    369 real* user, /**< user real workspace */
    370 fint* iuser, /**< user integer workspace */
    371 fint* errflag /**< set to 1 if arithmetic exception occurs, otherwise 0 */
    372 )
    373{ /*lint --e{715} */
    374 SCIP_NLPIPROBLEM* problem;
    375 real val;
    376 int j;
    377
    378 problem = (SCIP_NLPIPROBLEM*)(void*)iuser;
    379 assert(problem != NULL);
    380
    381 *errflag = 0;
    382 for( j = 0; j < *m; ++j )
    383 {
    384 if( SCIPnlpiOracleEvalConstraintValue(problem->scip, problem->oracle, j, x, &val) != SCIP_OKAY || !SCIPisFinite(val) )
    385 {
    386 *errflag = 1;
    387 SCIPdebugMsg(problem->scip, "arithmetic exception in confun for constraint %d\n", j);
    388 break;
    389 }
    390 c[j] = val;
    391 }
    392}
    393
    394/** Objective gradient and Jacobian evaluation
    395 *
    396 * \note If an arithmetic exception occurred, then the gradients must not be modified.
    397 */ /*lint -e{715} */
    398void
    399F77_FUNC(gradient,GRADIENT)(
    400 fint* n, /**< number of variables */
    401 fint* m, /**< number of constraints */
    402 fint* mxa, /**< actual number of entries in a */
    403 real* x, /**< value of current variables (array of length n) */
    404 real* a, /**< Jacobian matrix entries */
    405 fint* la, /**< Jacobian index information: column indices and pointers to start of each row */
    406 fint* maxa, /**< maximal size of a */
    407 real* user, /**< user real workspace */
    408 fint* iuser, /**< user integer workspace */
    409 fint* errflag /**< set to 1 if arithmetic exception occurs, otherwise 0 */
    410 )
    411{ /*lint --e{715} */
    412 SCIP_NLPIPROBLEM* problem;
    413 SCIP_Real dummy;
    414
    415 problem = (SCIP_NLPIPROBLEM*)(void*)iuser;
    416 assert(problem != NULL);
    417 assert(problem->evalbuffer != NULL);
    418 assert(problem->evalbufsize >= *maxa);
    419
    420 *errflag = 1;
    421
    422 if( SCIPnlpiOracleEvalObjectiveGradient(problem->scip, problem->oracle, x, TRUE, &dummy, problem->evalbuffer) == SCIP_OKAY )
    423 {
    424 if( SCIPnlpiOracleEvalJacobian(problem->scip, problem->oracle, x, TRUE, NULL, problem->evalbuffer+*n) == SCIP_OKAY )
    425 {
    426 BMScopyMemoryArray(a, problem->evalbuffer, *maxa);
    427 *errflag = 0;
    428 }
    429 else
    430 {
    431 SCIPdebugMsg(problem->scip, "arithmetic exception in gradient for constraints\n");
    432 }
    433 }
    434 else
    435 {
    436 SCIPdebugMsg(problem->scip, "arithmetic exception in gradient for objective\n");
    437 }
    438}
    439
    440/* Objective gradient evaluation */
    441/*
    442void F77_FUNC(objgrad,OBJGRAD)(
    443 fint*,
    444 fint*,
    445 fint*,
    446 real*,
    447 real*,
    448 fint*,
    449 fint*,
    450 real*,
    451 fint*,
    452 fint*
    453 )
    454*/
    455void F77_FUNC(objgrad,OBJGRAD)(void)
    456{
    457 SCIPerrorMessage("Objgrad not implemented. Should not be called.\n");
    458}
    459
    460/** Hessian of the Lagrangian evaluation
    461 *
    462 * phase = 1 : Hessian of the Lagrangian without objective Hessian
    463 *
    464 * phase = 2 : Hessian of the Lagrangian (including objective Hessian)
    465 *
    466 * \note If an arithmetic exception occurred, then the Hessian must not be modified.
    467 */ /*lint -e{715} */
    468void
    469F77_FUNC(hessian,HESSIAN)(
    470 real* x, /**< value of current variables (array of length n) */
    471 fint* n, /**< number of variables */
    472 fint* m, /**< number of constraints */
    473 fint* phase, /**< indicates what kind of Hessian matrix is required */
    474 real* lam, /**< Lagrangian multipliers (array of length n+m) */
    475 real* ws, /**< real workspace for Hessian, passed to Wdotd */
    476 fint* lws, /**< integer workspace for Hessian, passed to Wdotd */
    477 real* user, /**< user real workspace */
    478 fint* iuser, /**< user integer workspace */
    479 fint* l_hess, /**< space of Hessian real storage ws. On entry: maximal space allowed, on exit: actual amount used */
    480 fint* li_hess, /**< space of Hessian integer storage lws. On entry: maximal space allowed, on exit: actual amount used */
    481 fint* errflag /**< set to 1 if arithmetic exception occurs, otherwise 0 */
    482 )
    483{ /*lint --e{715} */
    484 SCIP_NLPIPROBLEM* problem;
    485 SCIP_Real* lambda;
    486 int nnz;
    487 int i;
    488
    489 problem = (SCIP_NLPIPROBLEM*)(void*)iuser;
    490 assert(problem != NULL);
    491 assert(problem->evalbuffer != NULL);
    492
    493 nnz = problem->hessiannz[0]-1;
    494 assert(problem->evalbufsize >= nnz);
    495
    496 *errflag = 1;
    497
    498 /* initialize lambda to -lam */
    499 BMSallocMemoryArray(&lambda, *m);
    500 for( i = 0; i < *m; ++i )
    501 lambda[i] = -lam[*n+i];
    502
    503 if( SCIPnlpiOracleEvalHessianLag(problem->scip, problem->oracle, x, TRUE, TRUE, (*phase == 1) ? 0.0 : 1.0, lambda,
    504 problem->evalbuffer, FALSE) == SCIP_OKAY )
    505 {
    506 *l_hess = nnz;
    507
    508 BMScopyMemoryArray(ws, problem->evalbuffer, nnz);
    509
    510 *errflag = 0;
    511
    512 /* copy the complete problem->hessiannz into lws */
    513 for( i = 0; i < nnz + *n + 2; ++i )
    514 lws[i] = problem->hessiannz[i];
    515 *li_hess = nnz + *n + 2;
    516 }
    517 else
    518 {
    519 SCIPdebugMsg(problem->scip, "arithmetic exception in hessian\n");
    520 }
    521
    522 BMSfreeMemoryArray(&lambda);
    523}
    524
    525
    526
    527static
    529 SCIP* scip, /**< SCIP data structure */
    530 SCIP_NLPIORACLE* oracle, /**< NLPI oracle */
    531 fint** la, /**< buffer to store pointer to sparsity structure */
    532 int* lasize, /**< buffer to store length of *la array */
    533 real** a /**< buffer to store pointer to value buffer */
    534 )
    535{
    536 const int* offset;
    537 const int* col;
    538 int nnz; /* number of nonzeros in Jacobian */
    539 int nvars;
    540 int ncons;
    541 int i;
    542 int c;
    543 int nnlnz;
    544
    545 assert(la != NULL);
    546 assert(lasize != NULL);
    547 assert(a != NULL);
    548 assert(*la == NULL);
    549 assert(*a == NULL);
    550
    551 nvars = SCIPnlpiOracleGetNVars(oracle);
    552 ncons = SCIPnlpiOracleGetNConstraints(oracle);
    553
    554 /* get jacobian sparsity in oracle format: offset are rowstarts in col and col are column indices */
    555 SCIP_CALL( SCIPnlpiOracleGetJacobianRowSparsity(scip, oracle, &offset, &col, NULL, &nnlnz) );
    556 nnz = offset[ncons];
    557
    558 /* la stores both column indices (first) and rowstarts (at the end) of the objective gradient and Jacobian
    559 * For the objective gradient, always n entries are taken, the Jacobian is stored sparse
    560 * la(0) = n+nnz+1 position where rowstarts start in la
    561 * la(j) column index of objective gradient or Jacobian row, rowwise
    562 * la(la(0)) position of first nonzero element for objective gradient in a()
    563 * la(la(0)+i) position of first nonzero element for constraint i gradient in a(), i=1..m
    564 * la(la(0)+m+1) = n+nnz first unused position in a
    565 * where n = nvars and m = ncons
    566 */
    567
    568 /* need space for la(0) and column indices and rowstarts (1+ncons+1 for objective, constraints, and end (offsets[ncons])) */
    569 *lasize = 1 + (nvars+nnz) + 1+ncons + 1;
    571
    572 (*la)[0] = nvars+nnz+1;
    573
    574 /* the objective gradient is stored in sparse form */
    575 for( i = 0; i < nvars; ++i )
    576 (*la)[1+i] = 1+i; /* shift by 1 for Fortran */
    577 (*la)[(*la)[0]] = 1; /* objective entries start at the beginning in a, shift by 1 for Fortran */
    578
    579 /* column indicies are as given by col */
    580 for( i = 0; i < nnz; ++i )
    581 (*la)[1+nvars+i] = col[i] + 1; /* shift by 1 for Fortran */
    582
    583 /* rowstarts are as given by offset, plus extra for objective gradient */
    584 for( c = 0; c <= ncons; ++c )
    585 (*la)[(*la)[0]+1+c] = offset[c] + nvars + 1; /* shift by nvars for objective, shift by 1 for Fortran */
    586
    587 SCIP_CALL( SCIPallocBlockMemoryArray(scip, a, nvars + nnz) );
    588
    589#ifdef SCIP_MORE_DEBUG /* enable for debugging Jacobian */
    590 for( i = 0; i < 1 + (nvars+nnz) + 1+ncons + 1; ++i )
    591 printf("la[%2d] = %2d\n", i, (*la)[i]);
    592#endif
    593
    594 return SCIP_OKAY;
    595}
    596
    597static
    599 SCIP* scip, /**< SCIP data structure */
    600 SCIP_NLPIORACLE* oracle, /**< NLPI oracle */
    601 fint** la, /**< buffer to store pointer to Hessian sparsity structure */
    602 int* lasize /**< buffer to store length of *la array */
    603 )
    604{
    605 const int* offset;
    606 const int* col;
    607 int nnz; /* number of nonzeros in Jacobian */
    608 int nvars;
    609 int i;
    610 int v;
    611
    612 assert(la != NULL);
    613 assert(lasize != NULL);
    614 assert(*la == NULL);
    615
    616 nvars = SCIPnlpiOracleGetNVars(oracle);
    617
    618 /* get Hessian sparsity in oracle format: offset are rowstarts in col and col are column indices */
    619 SCIP_CALL( SCIPnlpiOracleGetHessianLagSparsity(scip, oracle, &offset, &col, FALSE) );
    620 nnz = offset[nvars];
    621
    622 /* la stores both column indices (first) and rowstarts (at the end) of the (sparse) Hessian
    623 * la(0) = nnz+1 position where rowstarts start in la
    624 * la(j) column index of Hessian row, rowwise
    625 * la(la(0)+i) position of first nonzero element for row i, i = 0..n-1
    626 * la(la(0)+n) = nnz first unused position in Hessian
    627 * where n = nvars
    628 */
    629
    630 /* need space for la(0) and column indices and rowstarts
    631 * 1 for la(0)
    632 * nnz for column indices
    633 * nvars for rowstarts
    634 * 1 for first unused position
    635 */
    636 *lasize = 1 + nnz + nvars + 1;
    638
    639 (*la)[0] = nnz+1;
    640
    641 /* column indicies are as given by col */
    642 for( i = 0; i < nnz; ++i )
    643 (*la)[1+i] = col[i] + 1; /* shift by 1 for Fortran */
    644
    645 /* rowstarts are as given by offset */
    646 for( v = 0; v <= nvars; ++v )
    647 (*la)[(*la)[0]+v] = offset[v] + 1; /* shift by 1 for Fortran */
    648
    649 F77_FUNC(hessc,HESSC).phl = 1;
    650
    651#ifdef SCIP_MORE_DEBUG /* enable for debugging Hessian */
    652 for( i = 0; i < 1 + nnz + nvars + 1; ++i )
    653 printf("lw[%2d] = %2d\n", i, (*la)[i]);
    654#endif
    655
    656 return SCIP_OKAY;
    657}
    658
    659/** setup starting point for FilterSQP */
    660static
    662 SCIP_NLPIDATA* data, /**< NLPI data */
    663 SCIP_NLPIPROBLEM* problem, /**< NLPI problem */
    664 real* x, /**< array to store initial values */
    665 SCIP_Bool* success /**< whether we could setup a point in which functions could be evaluated */
    666 )
    667{
    668 int i;
    669 int n;
    670 SCIP_Real val;
    671
    672 assert(data != NULL);
    673 assert(problem != NULL);
    674 assert(x != NULL);
    675 assert(success != NULL);
    676
    677 n = SCIPnlpiOracleGetNVars(problem->oracle);
    678
    679 /* setup starting point */
    680 if( problem->initguess != NULL )
    681 {
    682 for( i = 0; i < n; ++i )
    683 x[i] = problem->initguess[i];
    684 }
    685 else
    686 {
    687 SCIP_Real lb;
    688 SCIP_Real ub;
    689
    690 SCIPdebugMsg(problem->scip, "FilterSQP started without initial primal values; make up something by projecting 0 onto variable bounds and perturb\n");
    691
    692 if( data->randnumgen == NULL )
    693 {
    694 SCIP_CALL( SCIPcreateRandom(problem->scip, &data->randnumgen, RANDSEED, TRUE) );
    695 }
    696
    697 for( i = 0; i < n; ++i )
    698 {
    699 lb = SCIPnlpiOracleGetVarLbs(problem->oracle)[i];
    700 ub = SCIPnlpiOracleGetVarUbs(problem->oracle)[i];
    701 if( lb > 0.0 )
    702 x[i] = SCIPrandomGetReal(data->randnumgen, lb, lb + MAXPERTURB*MIN(1.0, ub-lb));
    703 else if( ub < 0.0 )
    704 x[i] = SCIPrandomGetReal(data->randnumgen, ub - MAXPERTURB*MIN(1.0, ub-lb), ub);
    705 else
    706 x[i] = SCIPrandomGetReal(data->randnumgen, MAX(lb, -MAXPERTURB*MIN(1.0, ub-lb)), MIN(ub, MAXPERTURB*MIN(1.0, ub-lb)));
    707 }
    708 }
    709
    710 /* check whether objective and constraints can be evaluated and differentiated once in starting point
    711 * NOTE: this does not check whether hessian can be computed!
    712 */
    713 *success = SCIPnlpiOracleEvalObjectiveValue(problem->scip, problem->oracle, x, &val) == SCIP_OKAY && SCIPisFinite(val);
    714 *success &= SCIPnlpiOracleEvalObjectiveGradient(problem->scip, problem->oracle, x, FALSE, &val, problem->evalbuffer) == SCIP_OKAY; /*lint !e514*/
    715 i = 0;
    716 for( ; *success && i < SCIPnlpiOracleGetNConstraints(problem->oracle); ++i )
    717 *success = SCIPnlpiOracleEvalConstraintValue(problem->scip, problem->oracle, i, x, &val) == SCIP_OKAY && SCIPisFinite(val);
    718 *success &= SCIPnlpiOracleEvalJacobian(problem->scip, problem->oracle, x, FALSE, NULL, problem->evalbuffer) == SCIP_OKAY; /*lint !e514*/
    719
    720 if( !*success )
    721 {
    722 SCIPdebugMsg(problem->scip, "could not evaluate or constraint %d in %s starting point or Jacobian not available\n", i-1, problem->initguess != NULL ? "provided" : "made up");
    723
    724 if( problem->initguess != NULL )
    725 {
    726 /* forget given starting point and try to make up our own */
    727 SCIPfreeBlockMemoryArray(problem->scip, &problem->initguess, problem->varssize);
    728 SCIP_CALL( setupStart(data, problem, x, success) );
    729 }
    730 }
    731
    732 return SCIP_OKAY;
    733}
    734
    735/** sets the solstat and termstat to unknown and other, resp. */
    736static
    738 SCIP_NLPIPROBLEM* problem /**< data structure of problem */
    739 )
    740{
    741 assert(problem != NULL);
    742
    745}
    746
    747/** store NLP solve parameters in nlpiproblem */
    748static
    750 SCIP* scip, /**< SCIP data structure */
    751 SCIP_NLPIPROBLEM* nlpiproblem, /**< NLP */
    752 const SCIP_NLPPARAM param /**< solve parameters */
    753 )
    754{
    755 assert(scip != NULL);
    756 assert(nlpiproblem != NULL);
    757
    758 if( param.fastfail )
    759 {
    760 SCIPdebugMsg(scip, "fast fail parameter not supported by FilterSQP interface yet. Ignored.\n");
    761 }
    762
    763 nlpiproblem->fmin = param.lobjlimit;
    764
    765 nlpiproblem->maxtime = param.timelimit;
    766
    767 return SCIP_OKAY;
    768}
    769
    770/** processes results from FilterSQP call */
    771static
    773 SCIP_NLPIDATA* nlpidata, /**< NLPI data */
    774 SCIP_NLPIPROBLEM* problem, /**< NLPI problem */
    775 fint ifail, /**< fail flag from FilterSQP call */
    776 SCIP_Real feastol, /**< feasibility tolerance */
    777 SCIP_Real opttol, /**< optimality tolerance */
    778 real* x, /**< primal solution values from FilterSQP call, or NULL if stopped before filtersqp got called */
    779 real* lam /**< dual solution values from FilterSQP call, or NULL if stopped before filtersqp got called */
    780 )
    781{
    782 int i;
    783 int nvars;
    784 int ncons;
    785
    786 assert(problem != NULL);
    787 assert(ifail >= 0);
    788 assert((x != NULL) == (lam != NULL));
    789
    790 problem->solvetime = timeelapsed(nlpidata);
    791
    792 nvars = SCIPnlpiOracleGetNVars(problem->oracle);
    793 ncons = SCIPnlpiOracleGetNConstraints(problem->oracle);
    794
    795 if( ifail <= 8 && x != NULL )
    796 {
    797 /* FilterSQP terminated somewhat normally -> store away solution */
    798
    799 /* make sure we have memory for solution */
    800 if( problem->primalvalues == NULL )
    801 {
    802 assert(problem->varssize >= nvars); /* ensured in nlpiAddVariables */
    803 assert(problem->conssize >= ncons); /* ensured in nlpiAddConstraints */
    804 assert(problem->consdualvalues == NULL); /* if primalvalues == NULL, then also consdualvalues should be NULL */
    805 assert(problem->varlbdualvalues == NULL); /* if primalvalues == NULL, then also varlbdualvalues should be NULL */
    806 assert(problem->varubdualvalues == NULL); /* if primalvalues == NULL, then also varubdualvalues should be NULL */
    807
    808 SCIP_CALL( SCIPallocBlockMemoryArray(problem->scip, &problem->primalvalues, problem->varssize) );
    809 SCIP_CALL( SCIPallocBlockMemoryArray(problem->scip, &problem->consdualvalues, problem->conssize) );
    810 SCIP_CALL( SCIPallocBlockMemoryArray(problem->scip, &problem->varlbdualvalues, problem->varssize) );
    811 SCIP_CALL( SCIPallocBlockMemoryArray(problem->scip, &problem->varubdualvalues, problem->varssize) );
    812 }
    813 else
    814 {
    815 assert(problem->consdualvalues != NULL);
    816 assert(problem->varlbdualvalues != NULL);
    817 assert(problem->varubdualvalues != NULL);
    818 }
    819
    820 for( i = 0; i < nvars; ++i )
    821 {
    822 problem->primalvalues[i] = x[i];
    823
    824 /* if dual from FilterSQP is positive, then it belongs to the lower bound, otherwise to the upper bound */
    825 problem->varlbdualvalues[i] = MAX(0.0, lam[i]);
    826 problem->varubdualvalues[i] = MAX(0.0, -lam[i]);
    827 }
    828
    829 /* duals from FilterSQP are negated */
    830 for( i = 0; i < ncons; ++i )
    831 problem->consdualvalues[i] = -lam[nvars + i];
    832 }
    833
    834 /* translate ifail to solution and termination status and decide whether we could warmstart next */
    835 problem->warmstart = FALSE;
    836 switch( ifail )
    837 {
    838 case 0: /* successful run, solution found */
    839 assert(problem->rstat[4] <= feastol); /* should be feasible */
    840 problem->solstat = (problem->rstat[0] <= opttol ? SCIP_NLPSOLSTAT_LOCOPT : SCIP_NLPSOLSTAT_FEASIBLE);
    842 problem->warmstart = TRUE;
    843 break;
    844 case 1: /* unbounded, feasible point with f(x) <= fmin */
    845 assert(problem->rstat[4] <= feastol); /* should be feasible */
    847 if( problem->fmin == SCIP_REAL_MIN ) /*lint !e777*/
    848 problem->termstat = SCIP_NLPTERMSTAT_OKAY; /* fmin was not set */
    849 else
    851 break;
    852 case 2: /* linear constraints are inconsistent */
    855 break;
    856 case 3: /* (locally) nonlinear infeasible, minimal-infeasible solution found */
    857 /* problem->solstat = (problem->rstat[0] <= opttol ? SCIP_NLPSOLSTAT_LOCINFEASIBLE : SCIP_NLPSOLSTAT_UNKNOWN); */
    858 problem->solstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE; /* TODO FilterSQP does not set rstat[0] in this case, assuming local infeasibility is valid */
    860 problem->warmstart = TRUE;
    861 break;
    862 case 4: /* terminate at point with h(x) <= eps (constraint violation below epsilon) but QP infeasible */
    863 assert(problem->rstat[4] <= feastol); /* should be feasible */
    866 problem->warmstart = TRUE;
    867 break;
    868 case 5: /* termination with rho < eps (trust region radius below epsilon) */
    869 if( problem->rstat[4] <= feastol )
    871 else
    874 problem->warmstart = TRUE;
    875 break;
    876 case 6: /* termination with iter > max_iter */
    877 if( problem->rstat[4] <= feastol )
    879 else
    882 problem->warmstart = TRUE;
    883 break;
    884 case 7: /* crash in user routine (IEEE error) could not be resolved, or timelimit reached, or interrupted */
    886 if( problem->solvetime >= problem->maxtime )
    887 {
    889 problem->warmstart = TRUE;
    890 }
    891 else if( SCIPisSolveInterrupted(problem->scip) )
    893 else
    895 break;
    896 case 8: /* unexpect ifail from QP solver */
    897 if( problem->rstat[4] <= feastol )
    899 else
    902 break;
    903 case 9: /* not enough REAL workspace */
    906 break;
    907 case 10: /* not enough INTEGER workspace */
    910 break;
    911 default:
    914 break;
    915 }
    916
    917 return SCIP_OKAY;
    918}
    919
    920
    921/*
    922 * Callback methods of NLP solver interface
    923 */
    924
    925/** copy method of NLP interface (called when SCIP copies plugins) */
    926static
    927SCIP_DECL_NLPICOPY(nlpiCopyFilterSQP)
    928{
    930
    931 return SCIP_OKAY; /*lint !e527*/
    932} /*lint !e715*/
    933
    934/** destructor of NLP interface to free nlpi data */
    935static
    936SCIP_DECL_NLPIFREE(nlpiFreeFilterSQP)
    937{
    938 assert(nlpi != NULL);
    939 assert(nlpidata != NULL);
    940 assert(*nlpidata != NULL);
    941
    942 if( (*nlpidata)->randnumgen != NULL )
    943 {
    944 SCIPfreeRandom(scip, &(*nlpidata)->randnumgen);
    945 }
    946
    947 SCIPfreeBlockMemory(scip, nlpidata);
    948 assert(*nlpidata == NULL);
    949
    950 return SCIP_OKAY;
    951}
    952
    953/** creates a problem instance */
    954static
    955SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemFilterSQP)
    956{
    957 assert(nlpi != NULL);
    958 assert(problem != NULL);
    959
    961 (*problem)->scip = scip;
    962
    963 SCIP_CALL( SCIPnlpiOracleCreate(scip, &(*problem)->oracle) );
    964 SCIP_CALL( SCIPnlpiOracleSetProblemName(scip, (*problem)->oracle, name) );
    965
    966 (*problem)->fmin = SCIP_REAL_MIN;
    967 (*problem)->maxtime = SCIP_REAL_MAX;
    968
    969 invalidateSolution(*problem);
    970
    971 return SCIP_OKAY; /*lint !e527*/
    972} /*lint !e715*/
    973
    974/** free a problem instance */
    975static
    976SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemFilterSQP)
    977{
    978 assert(nlpi != NULL);
    979 assert(problem != NULL);
    980 assert(*problem != NULL);
    981
    982 if( (*problem)->oracle != NULL )
    983 {
    984 SCIP_CALL( SCIPnlpiOracleFree(scip, &(*problem)->oracle) );
    985 }
    986
    987 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->initguess, (*problem)->varssize);
    988 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->primalvalues, (*problem)->varssize);
    989 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->consdualvalues, (*problem)->conssize);
    990 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->varlbdualvalues, (*problem)->varssize);
    991 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->varubdualvalues, (*problem)->varssize);
    992 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->cstype, (*problem)->conssize);
    993 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->s, (*problem)->varssize + (*problem)->conssize); /*lint !e776 */
    994 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->bu, (*problem)->varssize + (*problem)->conssize); /*lint !e776 */
    995 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->bl, (*problem)->varssize + (*problem)->conssize); /*lint !e776 */
    996 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->x, (*problem)->varssize);
    997 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->c, (*problem)->conssize);
    998 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->lam, (*problem)->varssize + (*problem)->conssize); /*lint !e776 */
    999 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->a, (*problem)->la != NULL ? (*problem)->la[0]-1 : 0);
    1000 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->la, (*problem)->lasize);
    1001 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->hessiannz, (*problem)->hessiannzsize);
    1002 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->lws, (*problem)->mxiwk);
    1003 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->ws, (*problem)->mxwk);
    1004 SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->evalbuffer, (*problem)->evalbufsize);
    1005
    1006 SCIPfreeBlockMemory(scip, problem);
    1007 assert(*problem == NULL);
    1008
    1009 return SCIP_OKAY;
    1010} /*lint !e715*/
    1011
    1012/** add variables */
    1013static
    1014SCIP_DECL_NLPIADDVARS(nlpiAddVarsFilterSQP)
    1015{
    1016 int oldnvars;
    1017
    1018 assert(nlpi != NULL);
    1019 assert(problem != NULL);
    1020 assert(problem->oracle != NULL);
    1021
    1022 oldnvars = SCIPnlpiOracleGetNVars(problem->oracle);
    1023
    1024 SCIP_CALL( SCIPnlpiOracleAddVars(scip, problem->oracle, nvars, lbs, ubs, varnames) );
    1025
    1026 SCIPfreeBlockMemoryArrayNull(scip, &problem->initguess, problem->varssize);
    1027 invalidateSolution(problem);
    1028 problem->warmstart = FALSE;
    1029
    1030 /* increase variables-related arrays in problem, if necessary */
    1031 if( problem->varssize < SCIPnlpiOracleGetNVars(problem->oracle) )
    1032 {
    1033 int newsize = SCIPcalcMemGrowSize(scip, SCIPnlpiOracleGetNVars(problem->oracle));
    1034
    1035 if( problem->primalvalues != NULL )
    1036 {
    1037 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->primalvalues, problem->varssize, newsize) );
    1038 }
    1039
    1040 if( problem->varlbdualvalues != NULL )
    1041 {
    1042 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->varlbdualvalues, problem->varssize, newsize) );
    1043 }
    1044
    1045 if( problem->varubdualvalues != NULL )
    1046 {
    1047 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->varubdualvalues, problem->varssize, newsize) );
    1048 }
    1049
    1050 if( problem->x != NULL )
    1051 {
    1052 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->x, problem->varssize, newsize) );
    1053 }
    1054
    1055 if( problem->lam != NULL )
    1056 {
    1057 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->lam, problem->varssize + problem->conssize, newsize + problem->conssize) ); /*lint !e776*/
    1058 }
    1059
    1060 if( problem->bl != NULL )
    1061 {
    1062 assert(problem->bu != NULL);
    1063 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->bl, problem->varssize + problem->conssize, newsize + problem->conssize) ); /*lint !e776*/
    1064 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->bu, problem->varssize + problem->conssize, newsize + problem->conssize) ); /*lint !e776*/
    1065 }
    1066
    1067 if( problem->s != NULL )
    1068 {
    1069 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->s, problem->varssize + problem->conssize, newsize + problem->conssize) ); /*lint !e776*/
    1070 }
    1071
    1072 problem->varssize = newsize;
    1073 }
    1074
    1075 /* update variable bounds in FilterSQP data */
    1076 if( problem->bl != NULL )
    1077 {
    1078 int i;
    1079 int nconss;
    1080
    1081 nconss = SCIPnlpiOracleGetNConstraints(problem->oracle);
    1082
    1083 /* bl and bu have first variable bounds and then constraint sides
    1084 * copy the constraint sides to their new position before putting in the new variable bounds
    1085 */
    1086 for( i = nconss-1; i >= 0; --i )
    1087 {
    1088 problem->bl[oldnvars+nvars+i] = problem->bl[oldnvars+i];
    1089 problem->bu[oldnvars+nvars+i] = problem->bu[oldnvars+i];
    1090 }
    1091
    1092 /* set bounds of new variable */
    1093 for( i = 0; i < nvars; ++i )
    1094 {
    1095 problem->bl[oldnvars+i] = lbs[i];
    1096 problem->bu[oldnvars+i] = ubs[i];
    1097 }
    1098 }
    1099
    1100 /* gradients information is out of date now (objective gradient is stored in dense form) */
    1101 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1102 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1103
    1104 /* Hessian information is out of date now (no new entries in Hessian, but also empty cols shows up in sparsity info) */
    1105 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1106
    1107 return SCIP_OKAY;
    1108} /*lint !e715*/
    1109
    1110
    1111/** add constraints */
    1112static
    1113SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsFilterSQP)
    1114{
    1115 int oldnconss;
    1116
    1117 assert(nlpi != NULL);
    1118 assert(problem != NULL);
    1119 assert(problem->oracle != NULL);
    1120
    1121 oldnconss = SCIPnlpiOracleGetNConstraints(problem->oracle);
    1122
    1123 SCIP_CALL( SCIPnlpiOracleAddConstraints(scip, problem->oracle, nconss, lhss, rhss, nlininds, lininds, linvals, exprs, names) );
    1124
    1125 invalidateSolution(problem);
    1126 problem->warmstart = FALSE;
    1127
    1128 /* increase constraints-related arrays in problem, if necessary */
    1129 if( SCIPnlpiOracleGetNConstraints(problem->oracle) > problem->conssize )
    1130 {
    1131 int newsize = SCIPcalcMemGrowSize(scip, SCIPnlpiOracleGetNConstraints(problem->oracle));
    1132
    1133 if( problem->consdualvalues != NULL )
    1134 {
    1135 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->consdualvalues, problem->conssize, newsize) );
    1136 }
    1137
    1138 if( problem->c != NULL )
    1139 {
    1140 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->c, problem->conssize, newsize) );
    1141 }
    1142
    1143 if( problem->lam != NULL )
    1144 {
    1145 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->lam, problem->varssize + problem->conssize, problem->varssize + newsize) ); /*lint !e776*/
    1146 }
    1147
    1148 if( problem->bl != NULL )
    1149 {
    1150 assert(problem->bu != NULL);
    1151 assert(problem->cstype != NULL);
    1152 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->bl, problem->varssize + problem->conssize, problem->varssize + newsize) ); /*lint !e776*/
    1153 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->bu, problem->varssize + problem->conssize, problem->varssize + newsize) ); /*lint !e776*/
    1154 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->cstype, problem->conssize, newsize) );
    1155 }
    1156
    1157 if( problem->s != NULL )
    1158 {
    1159 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &problem->s, problem->varssize + problem->conssize, problem->varssize + newsize) ); /*lint !e776*/
    1160 }
    1161
    1162 problem->conssize = newsize;
    1163 }
    1164
    1165 /* update constraint sides and type in FilterSQP data */
    1166 if( problem->bl != NULL )
    1167 {
    1168 int i;
    1169 int nvars;
    1170
    1171 nvars = SCIPnlpiOracleGetNVars(problem->oracle);
    1172
    1173 for( i = 0; i < nconss; ++i )
    1174 {
    1175 problem->bl[nvars+oldnconss+i] = lhss[i];
    1176 problem->bu[nvars+oldnconss+i] = rhss[i];
    1177 problem->cstype[oldnconss+i] = SCIPnlpiOracleIsConstraintNonlinear(problem->oracle, oldnconss+i) ? 'N' : 'L';
    1178 }
    1179 }
    1180
    1181 /* gradients information is out of date now */
    1182 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1183 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1184
    1185 /* Hessian information is out of date now */
    1186 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1187
    1188 return SCIP_OKAY;
    1189} /*lint !e715*/
    1190
    1191/** sets or overwrites objective, a minimization problem is expected */
    1192static
    1193SCIP_DECL_NLPISETOBJECTIVE( nlpiSetObjectiveFilterSQP )
    1194{
    1195 assert(nlpi != NULL);
    1196 assert(problem != NULL);
    1197 assert(problem->oracle != NULL);
    1198
    1199 SCIP_CALL( SCIPnlpiOracleSetObjective(scip, problem->oracle,
    1200 constant, nlins, lininds, linvals, expr) );
    1201
    1202 invalidateSolution(problem);
    1203
    1204 /* gradients info (la,a) should still be ok, as objective gradient is stored in dense form */
    1205
    1206 /* Hessian information is out of date now */
    1207 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1208
    1209 return SCIP_OKAY;
    1210} /*lint !e715*/
    1211
    1212/** change variable bounds */
    1213static
    1214SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsFilterSQP)
    1215{
    1216 assert(nlpi != NULL);
    1217 assert(problem != NULL);
    1218 assert(problem->oracle != NULL);
    1219
    1220 SCIP_CALL( SCIPnlpiOracleChgVarBounds(scip, problem->oracle, nvars, indices, lbs, ubs) );
    1221
    1222 invalidateSolution(problem);
    1223
    1224 /* update bounds in FilterSQP data */
    1225 if( problem->bl != NULL )
    1226 {
    1227 int i;
    1228
    1229 for( i = 0; i < nvars; ++i )
    1230 {
    1231 problem->bl[indices[i]] = lbs[i];
    1232 problem->bu[indices[i]] = ubs[i];
    1233 }
    1234 }
    1235
    1236 return SCIP_OKAY;
    1237} /*lint !e715*/
    1238
    1239/** change constraint bounds */
    1240static
    1241SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesFilterSQP)
    1242{
    1243 assert(nlpi != NULL);
    1244 assert(problem != NULL);
    1245 assert(problem->oracle != NULL);
    1246
    1247 SCIP_CALL( SCIPnlpiOracleChgConsSides(scip, problem->oracle, nconss, indices, lhss, rhss) );
    1248
    1249 invalidateSolution(problem);
    1250
    1251 /* update constraint sense in FilterSQP data */
    1252 if( problem->bl != NULL )
    1253 {
    1254 int i;
    1255 int nvars;
    1256
    1257 nvars = SCIPnlpiOracleGetNVars(problem->oracle);
    1258
    1259 for( i = 0; i < nconss; ++i )
    1260 {
    1261 problem->bl[nvars+indices[i]] = lhss[i];
    1262 problem->bu[nvars+indices[i]] = rhss[i];
    1263 }
    1264 }
    1265
    1266 return SCIP_OKAY;
    1267} /*lint !e715*/
    1268
    1269/** delete a set of variables */
    1270static
    1271SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetFilterSQP)
    1272{
    1273 assert(nlpi != NULL);
    1274 assert(problem != NULL);
    1275 assert(problem->oracle != NULL);
    1276
    1277 SCIP_CALL( SCIPnlpiOracleDelVarSet(scip, problem->oracle, dstats) );
    1278
    1279 /* @TODO keep initguess and bl, bu for remaining variables? */
    1280
    1281 SCIPfreeBlockMemoryArrayNull(scip, &problem->initguess, problem->varssize);
    1282 invalidateSolution(problem);
    1283 problem->warmstart = FALSE;
    1284
    1285 SCIPfreeBlockMemoryArrayNull(scip, &problem->bl, problem->varssize + problem->conssize); /*lint !e776 */
    1286 SCIPfreeBlockMemoryArrayNull(scip, &problem->bu, problem->varssize + problem->conssize); /*lint !e776 */
    1287 SCIPfreeBlockMemoryArrayNull(scip, &problem->cstype, problem->conssize); /* because we assume that cstype is allocated iff bl is allocated */
    1288
    1289 /* gradients information is out of date now (objective gradient is stored in dense form) */
    1290 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1291 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1292
    1293 /* Hessian information is out of date now */
    1294 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1295
    1296 return SCIP_OKAY;
    1297} /*lint !e715*/
    1298
    1299/** delete a set of constraints */
    1300static
    1301SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetFilterSQP)
    1302{
    1303 assert(nlpi != NULL);
    1304 assert(problem != NULL);
    1305 assert(problem->oracle != NULL);
    1306
    1307 SCIP_CALL( SCIPnlpiOracleDelConsSet(scip, problem->oracle, dstats) );
    1308
    1309 invalidateSolution(problem);
    1310 problem->warmstart = FALSE;
    1311
    1312 SCIPfreeBlockMemoryArrayNull(scip, &problem->bl, problem->varssize + problem->conssize); /*lint !e776 */
    1313 SCIPfreeBlockMemoryArrayNull(scip, &problem->bu, problem->varssize + problem->conssize); /*lint !e776 */
    1314 SCIPfreeBlockMemoryArrayNull(scip, &problem->cstype, problem->conssize); /* because we assume that cstype is allocated iff bl is allocated */
    1315
    1316 /* gradients information is out of date now */
    1317 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1318 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1319
    1320 /* Hessian information is out of date now */
    1321 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1322
    1323 return SCIP_OKAY;
    1324} /*lint !e715*/
    1325
    1326/** changes (or adds) linear coefficients in a constraint or objective */
    1327static
    1328SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsFilterSQP)
    1329{
    1330 assert(nlpi != NULL);
    1331 assert(problem != NULL);
    1332 assert(problem->oracle != NULL);
    1333
    1334 SCIP_CALL( SCIPnlpiOracleChgLinearCoefs(scip, problem->oracle, idx, nvals, varidxs, vals) );
    1335
    1336 invalidateSolution(problem);
    1337
    1338 /* gradients information (la,a) may have changed if elements were added or removed
    1339 * (we only care that sparsity doesn't change, not about actual values in a)
    1340 * TODO free only if coefficients were added or removed (SCIPnlpiOracleChgLinearCoefs() could give feedback)
    1341 */
    1342 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1343 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1344
    1345 /* Hessian information should still be ok */
    1346
    1347 return SCIP_OKAY;
    1348} /*lint !e715*/
    1349
    1350/** replaces the expression of a constraint or objective */
    1351static
    1352SCIP_DECL_NLPICHGEXPR(nlpiChgExprFilterSQP)
    1353{
    1354 assert(nlpi != NULL);
    1355 assert(problem != NULL);
    1356 assert(problem->oracle != NULL);
    1357
    1358 SCIP_CALL( SCIPnlpiOracleChgExpr(scip, problem->oracle, idxcons, expr) );
    1359
    1360 invalidateSolution(problem);
    1361
    1362 /* update constraint linearity in FilterSQP data, as we might have changed from linear to nonlinear now */
    1363 if( problem->cstype != NULL && idxcons >= 0 )
    1364 problem->cstype[idxcons] = expr != NULL ? 'N' : 'L';
    1365
    1366 /* gradients information (la,a) may have changed */
    1367 SCIPfreeBlockMemoryArrayNull(scip, &problem->a, problem->la != NULL ? problem->la[0]-1 : 0);
    1368 SCIPfreeBlockMemoryArrayNull(scip, &problem->la, problem->lasize);
    1369
    1370 /* Hessian information may have changed */
    1371 SCIPfreeBlockMemoryArrayNull(scip, &problem->hessiannz, problem->hessiannzsize);
    1372
    1373 return SCIP_OKAY;
    1374} /*lint !e715*/
    1375
    1376/** change the constant offset in the objective */
    1377static
    1378SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantFilterSQP)
    1379{
    1380 assert(nlpi != NULL);
    1381 assert(problem != NULL);
    1382 assert(problem->oracle != NULL);
    1383
    1384 SCIP_CALL( SCIPnlpiOracleChgObjConstant(scip, problem->oracle, objconstant) );
    1385
    1386 invalidateSolution(problem);
    1387
    1388 return SCIP_OKAY;
    1389} /*lint !e715*/
    1390
    1391/** sets initial guess for primal variables */
    1392static
    1393SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessFilterSQP)
    1394{
    1395 assert(nlpi != NULL);
    1396 assert(problem != NULL);
    1397 assert(problem->oracle != NULL);
    1398
    1399 if( primalvalues != NULL )
    1400 {
    1401 if( problem->initguess == NULL )
    1402 {
    1403 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->initguess, problem->varssize) );
    1404 }
    1405 assert(SCIPnlpiOracleGetNVars(problem->oracle) <= problem->varssize);
    1406 BMScopyMemoryArray(problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle));
    1407 }
    1408 else
    1409 {
    1410 SCIPfreeBlockMemoryArrayNull(scip, &problem->initguess, problem->varssize);
    1411 }
    1412
    1413 return SCIP_OKAY;
    1414} /*lint !e715*/
    1415
    1416/** tries to solve NLP */
    1417static
    1418SCIP_DECL_NLPISOLVE(nlpiSolveFilterSQP)
    1419{
    1420 SCIP_NLPIDATA* data;
    1421 SCIP_Bool success;
    1422 fint n;
    1423 fint m;
    1424 fint kmax;
    1425 fint maxa;
    1426 fint maxf;
    1427 fint mlp;
    1428 fint lh1;
    1429 fint nout;
    1430 fint ifail;
    1431 fint maxiter;
    1432 fint iprint;
    1433 real rho;
    1434 real f;
    1435 real* user;
    1436 fint* iuser;
    1437 ftnlen cstype_len = 1;
    1438 fint minmxwk;
    1439 fint minmxiwk;
    1440 int nruns;
    1441 int i;
    1442
    1443 SCIPdebugMsg(scip, "solve with parameters " SCIP_NLPPARAM_PRINT(param));
    1444
    1445 data = SCIPnlpiGetData(nlpi);
    1446 assert(data != NULL);
    1447
    1448 SCIP_CALL( SCIPnlpiOracleResetEvalTime(scip, problem->oracle) );
    1449
    1450 if( param.timelimit == 0.0 )
    1451 {
    1452 /* there is nothing we can do if we are not given any time */
    1453 problem->niterations = 0;
    1454 problem->solvetime = 0.0;
    1455 problem->termstat = SCIP_NLPTERMSTAT_TIMELIMIT;
    1456 problem->solstat = SCIP_NLPSOLSTAT_UNKNOWN;
    1457
    1458 return SCIP_OKAY;
    1459 }
    1460
    1461 /* start measuring time */
    1462 data->starttime = gettime();
    1463
    1464 SCIP_CALL( handleNlpParam(scip, problem, param) );
    1465
    1466 iprint = param.verblevel;
    1467
    1468 /* if warmstart parameter is disabled, then we will not warmstart */
    1469 if( !param.warmstart )
    1470 problem->warmstart = FALSE;
    1471
    1472 n = SCIPnlpiOracleGetNVars(problem->oracle);
    1473 m = SCIPnlpiOracleGetNConstraints(problem->oracle);
    1474 kmax = n; /* maximal nullspace dimension */
    1475 maxf = 100; /* maximal filter length */
    1476 mlp = 100; /* maximum level of degeneracy */
    1477
    1478 /* TODO eventually, the output should be redirected to the message handler,
    1479 * but even to just redirect to some other file, we would have to open the output-unit in Fortran
    1480 */
    1481 nout = 6; /* output to stdout for now */
    1482 ifail = problem->warmstart ? -1 : 0; /* -1 for warmstart, otherwise 0 */
    1483 rho = 10.0; /* initial trust-region radius */
    1484
    1485 user = (real*)data;
    1486 iuser = (fint*)problem;
    1487 if( problem->warmstart ) /* if warmstart, then need to keep istat[0] */
    1488 memset(problem->istat+1, 0, sizeof(problem->istat)-sizeof(*problem->istat));
    1489 else
    1490 memset(problem->istat, 0, sizeof(problem->istat));
    1491 memset(problem->rstat, 0, sizeof(problem->rstat));
    1492 problem->niterations = 0;
    1493
    1494 if( problem->x == NULL )
    1495 {
    1496 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->x, problem->varssize) );
    1497 }
    1498 if( problem->c == NULL )
    1499 {
    1500 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->c, problem->conssize) );
    1501 }
    1502 if( problem->lam == NULL )
    1503 {
    1504 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &problem->lam, problem->varssize + problem->conssize) ); /*lint !e776 */
    1505 }
    1506 else
    1507 {
    1508 BMSclearMemoryArray(problem->lam, problem->varssize + problem->conssize);
    1509 }
    1510 if( problem->s == NULL )
    1511 {
    1512 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->s, problem->varssize + problem->conssize) );
    1513 }
    1514
    1515 if( problem->la == NULL )
    1516 {
    1517 /* allocate la, a and initialize la for Objective Gradient and Jacobian */
    1518 SCIP_CALL( setupGradients(scip, problem->oracle, &problem->la, &problem->lasize, &problem->a) );
    1519 }
    1520 /* maximal number entries in a = nvars+nnz */
    1521 maxa = problem->la[0]-1;
    1522
    1523 if( problem->hessiannz == NULL )
    1524 {
    1525 /* allocate and initialize problem->hessiannz for Hessian */
    1526 SCIP_CALL( setupHessian(scip, problem->oracle, &problem->hessiannz, &problem->hessiannzsize) );
    1527 }
    1528
    1529 /* setup variable bounds, constraint sides, and constraint types */
    1530 if( problem->bl == NULL )
    1531 {
    1532 assert(problem->bu == NULL);
    1533 assert(problem->cstype == NULL);
    1534
    1535 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->bl, problem->varssize + problem->conssize) );
    1536 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->bu, problem->varssize + problem->conssize) );
    1537 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &problem->cstype, problem->conssize) );
    1538
    1539 BMScopyMemoryArray(problem->bl, SCIPnlpiOracleGetVarLbs(problem->oracle), n);
    1540 BMScopyMemoryArray(problem->bu, SCIPnlpiOracleGetVarUbs(problem->oracle), n);
    1541 for( i = 0; i < m; ++i )
    1542 {
    1543 problem->bl[n+i] = SCIPnlpiOracleGetConstraintLhs(problem->oracle, i);
    1544 problem->bu[n+i] = SCIPnlpiOracleGetConstraintRhs(problem->oracle, i);
    1545 problem->cstype[i] = SCIPnlpiOracleIsConstraintNonlinear(problem->oracle, i) ? 'N' : 'L';
    1546 }
    1547 }
    1548
    1549 /* buffer for evaluation results (used in setupStart already) */
    1550 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &problem->evalbuffer, &problem->evalbufsize, MAX3(n, problem->hessiannz[0], maxa)) );
    1551
    1552 /* setup starting point */
    1553 SCIP_CALL( setupStart(data, problem, problem->x, &success) );
    1554 if( !success )
    1555 {
    1556 /* FilterSQP would crash if starting point cannot be evaluated, so give up */
    1557 SCIP_CALL( processSolveOutcome(data, problem, 7, param.feastol, param.opttol, NULL, NULL) );
    1558 return SCIP_OKAY;
    1559 }
    1560
    1561 /* setup workspace */
    1562 /* initial guess of real workspace size */
    1563 /* FilterSQP manual: mxwk = 21*n + 8*m + mlp + 8*maxf + kmax*(kmax+9)/2 + nprof, with nprof = 20*n as a good guess */
    1564 /* Bonmin: mxwk = 21*n + 8*m + mlp + 8*maxf + lh1 + kmax*(kmax+9)/2 + mxwk0,
    1565 * with lh1 = nnz_h+8+2*n+m and mxwk0 = 2000000 (parameter) */
    1566 lh1 = problem->hessiannz[0]-1 + 8 + 2*n + m;
    1567 minmxwk = 21*n + 8*m + mlp + 8*maxf + lh1 + kmax*(kmax+9)/2 + MAX(20*n,2000);
    1568 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &problem->ws, &problem->mxwk, minmxwk) );
    1569
    1570 /* initial guess of integer workspace size */
    1571 /* FilterSQP manual: mxiwk = 13*n + 4*m + mlp + 100 + kmax */
    1572 /* Bonmin: mxiwk = 13*n + 4*m + mlp + lh1 + kmax + 113 + mxiwk0, with mxiwk0 = 500000 (parameter) */
    1573 minmxiwk = 13*n + 4*m + mlp + lh1 + 100 + kmax + 113 + MAX(5*n,5000);
    1574 if( !problem->warmstart ) /* if warmstart, then lws should remain untouched (n and m didn't change anyway) */
    1575 {
    1576 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &problem->lws, &problem->mxiwk, minmxiwk) );
    1577 }
    1578 assert(problem->lws != NULL);
    1579 /* in case of some evalerrors, not clearing ws could lead to valgrind warnings about use of uninitialized memory */
    1580 BMSclearMemoryArray(problem->ws, problem->mxwk);
    1581
    1582 /* from here on we are not thread-safe: if intended for multithread use, then protect filtersqp call with mutex
    1583 * NOTE: we need to make sure that we do not return from nlpiSolve before unlocking the mutex
    1584 */
    1585#ifdef SCIP_THREADSAFE
    1586 (void) pthread_mutex_lock(&filtersqpmutex);
    1587#endif
    1588
    1589 /* initialize global variables from filtersqp */
    1590 /* FilterSQP eps is tolerance for both feasibility and optimality, and also for trust-region radius, etc. */
    1591 F77_FUNC(nlp_eps_inf,NLP_EPS_INF).eps = MIN(param.feastol, param.opttol * OPTTOLFACTOR);
    1592 F77_FUNC(nlp_eps_inf,NLP_EPS_INF).infty = SCIPinfinity(scip);
    1593 F77_FUNC(ubdc,UBDC).ubd = 100.0;
    1594 F77_FUNC(ubdc,UBDC).tt = 1.25;
    1595 F77_FUNC(scalec,SCALEC).scale_mode = 0;
    1596
    1597 for( nruns = 1; ; ++nruns )
    1598 {
    1599 maxiter = param.iterlimit - problem->niterations;
    1600
    1601 F77_FUNC(filtersqp,FILTERSQP)(
    1602 &n, &m, &kmax, &maxa,
    1603 &maxf, &mlp, &problem->mxwk, &problem->mxiwk,
    1604 &iprint, &nout, &ifail, &rho,
    1605 problem->x, problem->c, &f, &problem->fmin, problem->bl,
    1606 problem->bu, problem->s, problem->a, problem->la, problem->ws,
    1607 problem->lws, problem->lam, problem->cstype, user,
    1608 iuser, &maxiter, problem->istat,
    1609 problem->rstat, cstype_len);
    1610
    1611 problem->niterations += problem->istat[1];
    1612
    1613 assert(ifail <= 10);
    1614 /* if ifail >= 8 (probably the workspace was too small), then retry with larger workspace
    1615 * if ifail == 0 (local optimal), but absolute violation of KKT too large, then retry with small eps
    1616 */
    1617 if( ifail < 8 && (ifail != 0 || problem->rstat[0] <= param.opttol) )
    1618 break;
    1619
    1620 if( param.verblevel > 0 )
    1621 {
    1622 SCIPinfoMessage(scip, NULL, "FilterSQP terminated with status %d in run %d, absolute KKT violation is %g\n", ifail, nruns, problem->rstat[0]);
    1623 }
    1624
    1625 /* if iteration or time limit exceeded or solve is interrupted, then don't retry */
    1626 if( problem->niterations >= param.iterlimit || SCIPisSolveInterrupted(scip) || timelimitreached(data, problem) )
    1627 {
    1628 if( param.verblevel > 0 )
    1629 {
    1630 SCIPinfoMessage(scip, NULL, "Time or iteration limit reached or interrupted, not retrying\n");
    1631 }
    1632 break;
    1633 }
    1634
    1635 /* if maximal number of runs reached, then stop */
    1636 if( nruns >= MAXNRUNS )
    1637 {
    1638 if( param.verblevel > 0 )
    1639 {
    1640 SCIPinfoMessage(scip, NULL, "Run limit reached, not retrying\n");
    1641 }
    1642 break;
    1643 }
    1644
    1645 if( ifail == 0 )
    1646 {
    1647 SCIP_Real epsfactor;
    1648
    1649 if( F77_FUNC(nlp_eps_inf,NLP_EPS_INF).eps <= MINEPS )
    1650 {
    1651 if( param.verblevel > 0 )
    1652 {
    1653 SCIPinfoMessage(scip, NULL, "Already reached minimal epsilon, not retrying\n");
    1654 }
    1655 break;
    1656 }
    1657
    1658 epsfactor = param.opttol / problem->rstat[0];
    1659 assert(epsfactor < 1.0); /* because of the if's above */
    1660 epsfactor *= OPTTOLFACTOR;
    1661
    1662 F77_FUNC(nlp_eps_inf,NLP_EPS_INF).eps = MAX(MINEPS, F77_FUNC(nlp_eps_inf,NLP_EPS_INF).eps * epsfactor);
    1663 if( param.verblevel > 0 )
    1664 {
    1665 SCIPinfoMessage(scip, NULL, "Continue with eps = %g\n", F77_FUNC(nlp_eps_inf,NLP_EPS_INF).eps);
    1666 }
    1667 ifail = -1; /* do warmstart */
    1668
    1669 continue;
    1670 }
    1671
    1672 /* increase real workspace, if ifail = 9 (real workspace too small) or ifail = 8 (unexpected ifail from QP solver, often also when workspace too small) */
    1673 if( ifail == 8 || ifail == 9 )
    1674 {
    1675 int newsize = SCIPcalcMemGrowSize(scip, WORKSPACEGROWTHFACTOR*problem->mxwk);
    1676 if( BMSreallocBlockMemoryArray(SCIPblkmem(scip), &problem->ws, problem->mxwk, newsize) == NULL )
    1677 {
    1678 /* realloc failed: give up NLP solve */
    1679 problem->mxwk = 0;
    1680 break;
    1681 }
    1682 problem->mxwk = newsize;
    1683 }
    1684
    1685 /* increase integer workspace, if ifail = 10 (integer workspace too small) or ifail = 8 (unexpected ifail from QP solver, often also when workspace too small) */
    1686 if( ifail == 8 || ifail == 10 )
    1687 {
    1688 int newsize = SCIPcalcMemGrowSize(scip, WORKSPACEGROWTHFACTOR*problem->mxiwk);
    1689 if( BMSreallocBlockMemoryArray(SCIPblkmem(scip), &problem->lws, problem->mxiwk, newsize) == NULL )
    1690 {
    1691 /* realloc failed: give up NLP solve */
    1692 problem->mxiwk = 0;
    1693 break;
    1694 }
    1695 problem->mxiwk = newsize;
    1696
    1697 /* better don't try warmstart for the next trial; warmstart requires that lws is untouched, does extending count as touching? */
    1698 ifail = 0;
    1699 }
    1700
    1701 /* reset starting point, in case it was overwritten by failed solve (return can only be SCIP_OKAY, because randnumgen must exist already)
    1702 * NOTE: If initguess is NULL (no user-given starting point), then this will result in a slightly different starting point as in the previous setupStart() call (random numbers)
    1703 * However, as no point was given, it shouldn't matter which point we actually start from.
    1704 */
    1705 (void) setupStart(data, problem, problem->x, &success);
    1706 assert(success);
    1707 }
    1708
    1709#ifdef SCIP_THREADSAFE
    1710 (void) pthread_mutex_unlock(&filtersqpmutex);
    1711#endif
    1712
    1713 SCIP_CALL( processSolveOutcome(data, problem, ifail, param.feastol, param.opttol, problem->x, problem->lam) );
    1714
    1715 return SCIP_OKAY; /*lint !e527*/
    1716} /*lint !e715*/
    1717
    1718/** gives solution status */
    1719static
    1720SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatFilterSQP)
    1721{
    1722 assert(problem != NULL);
    1723
    1724 return problem->solstat;
    1725} /*lint !e715*/
    1726
    1727/** gives termination reason */
    1728static
    1729SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatFilterSQP)
    1730{
    1731 assert(problem != NULL);
    1732
    1733 return problem->termstat;
    1734} /*lint !e715*/
    1735
    1736/** gives primal and dual solution values */
    1737static
    1738SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionFilterSQP)
    1739{
    1740 assert(problem != NULL);
    1741
    1742 if( primalvalues != NULL )
    1743 {
    1744 assert(problem->primalvalues != NULL);
    1745
    1746 *primalvalues = problem->primalvalues;
    1747 }
    1748
    1749 if( consdualvalues != NULL )
    1750 {
    1751 assert(problem->consdualvalues != NULL);
    1752
    1753 *consdualvalues = problem->consdualvalues;
    1754 }
    1755
    1756 if( varlbdualvalues != NULL )
    1757 {
    1758 assert(problem->varlbdualvalues != NULL);
    1759
    1760 *varlbdualvalues = problem->varlbdualvalues;
    1761 }
    1762
    1763 if( varubdualvalues != NULL )
    1764 {
    1765 assert(problem->varubdualvalues != NULL);
    1766
    1767 *varubdualvalues = problem->varubdualvalues;
    1768 }
    1769
    1770 if( objval != NULL )
    1771 {
    1772 if( problem->primalvalues != NULL )
    1773 {
    1774 /* TODO store last solution value instead of reevaluating the objective function */
    1775 SCIP_CALL( SCIPnlpiOracleEvalObjectiveValue(scip, problem->oracle, problem->primalvalues, objval) );
    1776 }
    1777 else
    1778 *objval = SCIP_INVALID;
    1779 }
    1780
    1781 return SCIP_OKAY; /*lint !e527*/
    1782} /*lint !e715*/
    1783
    1784/** gives solve statistics */
    1785static
    1786SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsFilterSQP)
    1787{
    1788 assert(problem != NULL);
    1789 assert(statistics != NULL);
    1790
    1791 statistics->niterations = problem->niterations;
    1792 statistics->totaltime = problem->solvetime;
    1793 statistics->evaltime = SCIPnlpiOracleGetEvalTime(scip, problem->oracle);
    1794 statistics->consviol = problem->rstat[4];
    1795 statistics->boundviol = 0.0;
    1796
    1797 return SCIP_OKAY; /*lint !e527*/
    1798} /*lint !e715*/
    1799
    1800/*
    1801 * NLP solver interface specific interface methods
    1802 */
    1803
    1804/** create solver interface for filterSQP solver and include it into SCIP, if filterSQP is available */
    1806 SCIP* scip /**< SCIP data structure */
    1807 )
    1808{
    1809 SCIP_NLPIDATA* nlpidata;
    1810
    1811 /* create filterSQP solver interface data */
    1813
    1814 /* create solver interface */
    1817 nlpiCopyFilterSQP, nlpiFreeFilterSQP, NULL,
    1818 nlpiCreateProblemFilterSQP, nlpiFreeProblemFilterSQP, NULL,
    1819 nlpiAddVarsFilterSQP, nlpiAddConstraintsFilterSQP, nlpiSetObjectiveFilterSQP,
    1820 nlpiChgVarBoundsFilterSQP, nlpiChgConsSidesFilterSQP, nlpiDelVarSetFilterSQP, nlpiDelConstraintSetFilterSQP,
    1821 nlpiChgLinearCoefsFilterSQP, nlpiChgExprFilterSQP,
    1822 nlpiChgObjConstantFilterSQP, nlpiSetInitialGuessFilterSQP, nlpiSolveFilterSQP, nlpiGetSolstatFilterSQP, nlpiGetTermstatFilterSQP,
    1823 nlpiGetSolutionFilterSQP, nlpiGetStatisticsFilterSQP,
    1824 nlpidata) );
    1825
    1827
    1828 return SCIP_OKAY;
    1829}
    1830
    1831/** gets string that identifies filterSQP */
    1833 void
    1834 )
    1835{
    1836 return "filterSQP"; /* TODO version number? */
    1837}
    1838
    1839/** gets string that describes filterSQP */
    1841 void
    1842 )
    1843{
    1844 return NLPI_DESC;
    1845}
    1846
    1847/** returns whether filterSQP is available, i.e., whether it has been linked in */
    1849 void
    1850 )
    1851{
    1852 return TRUE;
    1853}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    #define NULL
    Definition: def.h:248
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define MAX3(x, y, z)
    Definition: def.h:228
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_REAL_MIN
    Definition: def.h:159
    #define SCIP_CALL(x)
    Definition: def.h:355
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludeNlpSolverFilterSQP(SCIP *scip)
    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 SCIPnlpiOracleGetJacobianRowSparsity(SCIP *scip, SCIP_NLPIORACLE *oracle, const int **rowoffsets, const int **cols, const SCIP_Bool **colnlflags, int *nnlnz)
    Definition: nlpioracle.c:2264
    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_Bool SCIPnlpiOracleIsConstraintNonlinear(SCIP_NLPIORACLE *oracle, int considx)
    Definition: nlpioracle.c:2084
    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 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
    int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1933
    int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:1943
    SCIP_RETCODE SCIPnlpiOracleEvalJacobian(SCIP *scip, SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *convals, SCIP_Real *jacobi)
    Definition: nlpioracle.c:2543
    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
    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
    const char * SCIPgetSolverDescFilterSQP(void)
    const char * SCIPgetSolverNameFilterSQP(void)
    SCIP_Bool SCIPisFilterSQPAvailableFilterSQP(void)
    SCIP_RETCODE SCIPincludeExternalCodeInformation(SCIP *scip, const char *name, const char *description)
    Definition: scip_general.c:769
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocClearBlockMemory(scip, ptr)
    Definition: scip_mem.h:91
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
    Definition: scip_mem.h:107
    #define SCIPallocClearBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:97
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    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_NLPIDATA * SCIPnlpiGetData(SCIP_NLPI *nlpi)
    Definition: nlpi.c:712
    SCIP_Bool SCIPisSolveInterrupted(SCIP *scip)
    Definition: scip_solve.c:3580
    SCIP_Real SCIPinfinity(SCIP *scip)
    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)
    #define BMSallocMemoryArray(ptr, num)
    Definition: memory.h:123
    #define BMSfreeMemoryArray(ptr)
    Definition: memory.h:147
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    static SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatFilterSQP)
    long ftnlen
    static SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsFilterSQP)
    double real
    #define NLPI_PRIORITY
    static SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantFilterSQP)
    static SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemFilterSQP)
    #define MAXPERTURB
    static SCIP_RETCODE handleNlpParam(SCIP *scip, SCIP_NLPIPROBLEM *nlpiproblem, const SCIP_NLPPARAM param)
    #define RANDSEED
    fint phe
    static SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionFilterSQP)
    static SCIP_DECL_NLPISOLVE(nlpiSolveFilterSQP)
    static SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveFilterSQP)
    real tt
    #define OPTTOLFACTOR
    real ubd
    static SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemFilterSQP)
    static SCIP_TIME gettime(void)
    static SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsFilterSQP)
    fint phr
    fint scale_mode
    #define WORKSPACEGROWTHFACTOR
    static SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetFilterSQP)
    #define NLPI_NAME
    static SCIP_DECL_NLPIADDVARS(nlpiAddVarsFilterSQP)
    static SCIP_RETCODE setupGradients(SCIP *scip, SCIP_NLPIORACLE *oracle, fint **la, int *lasize, real **a)
    real eps
    static SCIP_Real timeelapsed(SCIP_NLPIDATA *nlpidata)
    static SCIP_DECL_NLPICHGEXPR(nlpiChgExprFilterSQP)
    static SCIP_RETCODE processSolveOutcome(SCIP_NLPIDATA *nlpidata, SCIP_NLPIPROBLEM *problem, fint ifail, SCIP_Real feastol, SCIP_Real opttol, real *x, real *lam)
    real infty
    void F77_FUNC(filtersqp, FILTERSQP)
    static SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsFilterSQP)
    #define MINEPS
    int fint
    fint phc
    fint n_bqpd_prfint
    static SCIP_RETCODE setupHessian(SCIP *scip, SCIP_NLPIORACLE *oracle, fint **la, int *lasize)
    static SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesFilterSQP)
    static SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsFilterSQP)
    static SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetFilterSQP)
    static SCIP_DECL_NLPIFREE(nlpiFreeFilterSQP)
    static SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatFilterSQP)
    static SCIP_RETCODE setupStart(SCIP_NLPIDATA *data, SCIP_NLPIPROBLEM *problem, real *x, SCIP_Bool *success)
    static SCIP_Bool timelimitreached(SCIP_NLPIDATA *nlpidata, SCIP_NLPIPROBLEM *nlpiproblem)
    fint n_bqpd_calls
    fint phl
    #define MAXNRUNS
    static SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessFilterSQP)
    #define NLPI_DESC
    static void invalidateSolution(SCIP_NLPIPROBLEM *problem)
    static SCIP_DECL_NLPICOPY(nlpiCopyFilterSQP)
    filterSQP 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
    #define SCIPisFinite(x)
    Definition: pub_misc.h:82
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for NLPI solver interfaces
    public methods for numerical tolerances
    public methods for random numbers
    public solving methods
    SCIP_Real timelimit
    Definition: type_nlpi.h:72
    SCIP_NLPPARAM_FASTFAIL fastfail
    Definition: type_nlpi.h:75
    SCIP_Real lobjlimit
    Definition: type_nlpi.h:68
    SCIP_Real * primalvalues
    SCIP_Real * varubdualvalues
    SCIP_NLPIORACLE * oracle
    Definition: nlpi_conopt.c:78
    SCIP_Real solvetime
    Definition: nlpi_conopt.c:86
    SCIP_NLPTERMSTAT termstat
    Definition: nlpi_conopt.c:85
    SCIP_Real * consdualvalues
    SCIP_Real * varlbdualvalues
    SCIP_Real * initguess
    Definition: nlpi_conopt.c:82
    SCIP_NLPSOLSTAT solstat
    Definition: nlpi_conopt.c:84
    time_t sec
    #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_LOBJLIMIT
    Definition: type_nlpi.h:176
    @ SCIP_NLPTERMSTAT_ITERLIMIT
    Definition: type_nlpi.h:175
    @ SCIP_NLPTERMSTAT_OUTOFMEMORY
    Definition: type_nlpi.h:180
    @ SCIP_NLPTERMSTAT_INTERRUPT
    Definition: type_nlpi.h:177
    @ 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_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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63