SCIP

    Solving Constraint Integer Programs

    heur_multistart.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 heur_multistart.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief multistart heuristic for convex and nonconvex MINLPs
    28 * @author Benjamin Mueller
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/scip_expr.h"
    35#include "scip/pub_expr.h"
    37#include "scip/heur_subnlp.h"
    38#include "scip/pub_heur.h"
    39#include "scip/pub_message.h"
    40#include "scip/pub_misc.h"
    41#include "scip/pub_misc_sort.h"
    42#include "scip/pub_nlp.h"
    43#include "scip/pub_var.h"
    44#include "scip/scip_general.h"
    45#include "scip/scip_heur.h"
    46#include "scip/scip_mem.h"
    47#include "scip/scip_message.h"
    48#include "scip/scip_nlp.h"
    49#include "scip/scip_nlpi.h"
    50#include "scip/scip_numerics.h"
    51#include "scip/scip_param.h"
    52#include "scip/scip_prob.h"
    54#include "scip/scip_sol.h"
    55#include "scip/scip_timing.h"
    56
    57
    58#define HEUR_NAME "multistart"
    59#define HEUR_DESC "multistart heuristic for convex and nonconvex MINLPs"
    60#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    61#define HEUR_PRIORITY -2100000
    62#define HEUR_FREQ 0
    63#define HEUR_FREQOFS 0
    64#define HEUR_MAXDEPTH -1
    65#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    66#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    67
    68#define DEFAULT_RANDSEED 131 /**< initial random seed */
    69#define DEFAULT_NRNDPOINTS 100 /**< default number of generated random points per call */
    70#define DEFAULT_MAXBOUNDSIZE 2e+4 /**< default maximum variable domain size for unbounded variables */
    71#define DEFAULT_MAXITER 300 /**< default number of iterations to reduce the violation of a point */
    72#define DEFAULT_MINIMPRFAC 0.05 /**< default minimum required improving factor to proceed in improvement of a point */
    73#define DEFAULT_MINIMPRITER 10 /**< default number of iteration when checking the minimum improvement */
    74#define DEFAULT_MAXRELDIST 0.15 /**< default maximum distance between two points in the same cluster */
    75#define DEFAULT_GRADLIMIT 5e+6 /**< default limit for gradient computations for all improvePoint() calls */
    76#define DEFAULT_MAXNCLUSTER 3 /**< default maximum number of considered clusters per heuristic call */
    77#define DEFAULT_ONLYNLPS TRUE /**< should the heuristic run only on continuous problems? */
    78
    79#define MINFEAS -1e+4 /**< minimum feasibility for a point; used for filtering and improving
    80 * feasibility */
    81#define MINIMPRFAC 0.95 /**< improvement factor used to discard randomly generated points with a
    82 * too large objective value */
    83#define GRADCOSTFAC_LINEAR 1.0 /**< gradient cost factor for the number of linear variables */
    84#define GRADCOSTFAC_NONLINEAR 3.0 /**< gradient cost factor for the number of nodes in nonlinear expression */
    85
    86/*
    87 * Data structures
    88 */
    89
    90/** primal heuristic data */
    91struct SCIP_HeurData
    92{
    93 int nrndpoints; /**< number of random points generated per execution call */
    94 SCIP_Real maxboundsize; /**< maximum variable domain size for unbounded variables */
    95 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    96 SCIP_HEUR* heursubnlp; /**< sub-NLP heuristic */
    97
    98 int maxiter; /**< number of iterations to reduce the maximum violation of a point */
    99 SCIP_Real minimprfac; /**< minimum required improving factor to proceed in the improvement of a single point */
    100 int minimpriter; /**< number of iteration when checking the minimum improvement */
    101
    102 SCIP_Real maxreldist; /**< maximum distance between two points in the same cluster */
    103 SCIP_Real gradlimit; /**< limit for gradient computations for all improvePoint() calls (0 for no limit) */
    104 int maxncluster; /**< maximum number of considered clusters per heuristic call */
    105 SCIP_Bool onlynlps; /**< should the heuristic run only on continuous problems? */
    106};
    107
    108
    109/*
    110 * Local methods
    111 */
    112
    113
    114/** returns an unique index of a variable in the range of 0,..,SCIPgetNVars(scip)-1 */
    115#ifndef NDEBUG
    116static
    118 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 */
    119 SCIP_VAR* var /**< variable */
    120 )
    121{
    122 assert(varindex != NULL);
    123 assert(var != NULL);
    124 assert(SCIPhashmapExists(varindex, (void*)var));
    125
    126 return SCIPhashmapGetImageInt(varindex, (void*)var);
    127}
    128#else
    129#define getVarIndex(varindex,var) (SCIPhashmapGetImageInt((varindex), (void*)(var)))
    130#endif
    131
    132/** samples and stores random points; stores points which have a better objective value than the current incumbent
    133 * solution
    134 */
    135static
    137 SCIP* scip, /**< SCIP data structure */
    138 SCIP_SOL** rndpoints, /**< array to store all random points */
    139 int nmaxrndpoints, /**< maximum number of random points to compute */
    140 SCIP_Real maxboundsize, /**< maximum variable domain size for unbounded variables */
    141 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    142 SCIP_Real bestobj, /**< objective value in the transformed space of the current incumbent */
    143 int* nstored /**< pointer to store the number of randomly generated points */
    144 )
    145{
    146 SCIP_VAR** vars;
    147 SCIP_SOL* sol;
    148 SCIP_Real val;
    149 SCIP_Real lb;
    150 SCIP_Real ub;
    151 int nvars;
    152 int niter;
    153 int i;
    154
    155 assert(scip != NULL);
    156 assert(rndpoints != NULL);
    157 assert(nmaxrndpoints > 0);
    158 assert(maxboundsize > 0.0);
    159 assert(randnumgen != NULL);
    160 assert(nstored != NULL);
    161
    162 vars = SCIPgetVars(scip);
    163 nvars = SCIPgetNVars(scip);
    164 *nstored = 0;
    165
    166 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
    167
    168 for( niter = 0; niter < 3 * nmaxrndpoints && *nstored < nmaxrndpoints; ++niter )
    169 {
    170 /* reset solution, in case the old one had infinite objective, which can give difficulties in updating the obj value */
    171 SCIP_CALL( SCIPclearSol(scip, sol) );
    172
    173 for( i = 0; i < nvars; ++i )
    174 {
    175 lb = MIN(SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    176 ub = MAX(SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    177
    178 if( SCIPisFeasEQ(scip, lb, ub) )
    179 val = (lb + ub) / 2.0;
    180 /* use a smaller domain for unbounded variables */
    181 else if( !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
    182 val = SCIPrandomGetReal(randnumgen, lb, ub);
    183 else if( !SCIPisInfinity(scip, -lb) )
    184 val = lb + SCIPrandomGetReal(randnumgen, 0.0, maxboundsize);
    185 else if( !SCIPisInfinity(scip, ub) )
    186 val = ub - SCIPrandomGetReal(randnumgen, 0.0, maxboundsize);
    187 else
    188 {
    189 assert(SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub));
    190 val = SCIPrandomGetReal(randnumgen, -0.5*maxboundsize, 0.5*maxboundsize);
    191 }
    192 assert(SCIPisFeasGE(scip, val, lb) && SCIPisFeasLE(scip, val, ub));
    193
    194 /* set solution value; round the sampled point for integer variables */
    195 if( SCIPvarIsIntegral(vars[i]) )
    196 val = SCIPfeasRound(scip, val);
    197 SCIP_CALL( SCIPsetSolVal(scip, sol, vars[i], val) );
    198 }
    199
    200 /* add solution if it is good enough */
    201 if( SCIPisLE(scip, SCIPgetSolTransObj(scip, sol), bestobj) )
    202 {
    203 SCIP_CALL( SCIPcreateSolCopy(scip, &rndpoints[*nstored], sol) );
    204 ++(*nstored);
    205 }
    206 }
    207 assert(*nstored <= nmaxrndpoints);
    208 SCIPdebugMsg(scip, "found %d randomly generated points\n", *nstored);
    209
    210 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    211
    212 return SCIP_OKAY;
    213}
    214
    215/** computes the minimum feasibility of a given point; a negative value means that there is an infeasibility */
    216static
    218 SCIP* scip, /**< SCIP data structure */
    219 SCIP_NLROW** nlrows, /**< array containing all nlrows */
    220 int nnlrows, /**< total number of nlrows */
    221 SCIP_SOL* sol, /**< solution */
    222 SCIP_Real* minfeas /**< buffer to store the minimum feasibility */
    223 )
    224{
    225 SCIP_Real tmp;
    226 int i;
    227
    228 assert(scip != NULL);
    229 assert(sol != NULL);
    230 assert(minfeas != NULL);
    231 assert(nlrows != NULL);
    232 assert(nnlrows > 0);
    233
    234 *minfeas = SCIPinfinity(scip);
    235
    236 for( i = 0; i < nnlrows; ++i )
    237 {
    238 assert(nlrows[i] != NULL);
    239
    240 SCIP_CALL( SCIPgetNlRowSolFeasibility(scip, nlrows[i], sol, &tmp) );
    241 if( tmp == SCIP_INVALID ) /*lint !e777*/
    242 {
    243 *minfeas = -SCIPinfinity(scip);
    244 return SCIP_OKAY;
    245 }
    246 *minfeas = MIN(*minfeas, tmp);
    247 }
    248
    249 return SCIP_OKAY;
    250}
    251
    252/** computes the gradient for a given point and nonlinear row */
    253static
    255 SCIP* scip, /**< SCIP data structure */
    256 SCIP_NLROW* nlrow, /**< nonlinear row */
    257 SCIP_SOL* sol, /**< solution to compute the gradient for */
    258 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 uniquely */
    259 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
    260 SCIP_Real* grad, /**< buffer to store the gradient; grad[varindex(i)] corresponds to SCIPgetVars(scip)[i] */
    261 SCIP_Real* norm /**< buffer to store ||grad||^2, or SCIP_INVALID if function not differentiable */
    262 )
    263{
    264 SCIP_EXPR* expr;
    265 SCIP_VAR* var;
    266 int i;
    267
    268 assert(scip != NULL);
    269 assert(nlrow != NULL);
    270 assert(varindex != NULL);
    271 assert(sol != NULL);
    272 assert(norm != NULL);
    273
    275 *norm = 0.0;
    276
    277 /* linear part */
    278 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
    279 {
    280 var = SCIPnlrowGetLinearVars(nlrow)[i];
    281 assert(var != NULL);
    282 assert(getVarIndex(varindex, var) >= 0 && getVarIndex(varindex, var) < SCIPgetNVars(scip));
    283
    284 grad[getVarIndex(varindex, var)] += SCIPnlrowGetLinearCoefs(nlrow)[i];
    285 }
    286
    287 /* expression part */
    288 expr = SCIPnlrowGetExpr(nlrow);
    289
    290 if( expr != NULL )
    291 {
    292 assert(exprit != NULL);
    293
    294 SCIP_CALL( SCIPevalExprGradient(scip, expr, sol, 0L) );
    295
    296 /* TODO: change this when nlrows store the vars */
    298 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
    299 {
    300 if( !SCIPisExprVar(scip, expr) )
    301 continue;
    302
    303 var = SCIPgetVarExprVar(expr);
    304 assert(var != NULL);
    305 assert(getVarIndex(varindex, var) >= 0 && getVarIndex(varindex, var) < SCIPgetNVars(scip));
    306
    307 if( SCIPexprGetDerivative(expr) == SCIP_INVALID ) /*lint !e777*/
    308 {
    309 *norm = SCIP_INVALID;
    310 return SCIP_OKAY;
    311 }
    312
    313 grad[getVarIndex(varindex, var)] += SCIPexprGetDerivative(expr);
    314 }
    315 }
    316
    317 /* compute ||grad||^2 */
    318 for( i = 0; i < SCIPgetNVars(scip); ++i )
    319 *norm += SQR(grad[i]);
    320
    321 return SCIP_OKAY;
    322}
    323
    324/** use consensus vectors to improve feasibility for a given starting point */
    325static
    327 SCIP* scip, /**< SCIP data structure */
    328 SCIP_NLROW** nlrows, /**< array containing all nlrows */
    329 int nnlrows, /**< total number of nlrows */
    330 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 */
    331 SCIP_SOL* point, /**< random generated point */
    332 int maxiter, /**< maximum number of iterations */
    333 SCIP_Real minimprfac, /**< minimum required improving factor to proceed in the improvement of a single point */
    334 int minimpriter, /**< number of iteration when checking the minimum improvement */
    335 SCIP_Real* minfeas, /**< pointer to store the minimum feasibility */
    336 SCIP_Real* nlrowgradcosts, /**< estimated costs for each gradient computation */
    337 SCIP_Real* gradcosts /**< pointer to store the estimated gradient costs */
    338 )
    339{
    340 SCIP_VAR** vars;
    341 SCIP_EXPRITER* exprit;
    342 SCIP_Real* grad;
    343 SCIP_Real* updatevec;
    344 SCIP_Real lastminfeas;
    345 int nvars;
    346 int r;
    347 int i;
    348
    349 assert(varindex != NULL);
    350 assert(point != NULL);
    351 assert(maxiter > 0);
    352 assert(minfeas != NULL);
    353 assert(nlrows != NULL);
    354 assert(nnlrows > 0);
    355 assert(nlrowgradcosts != NULL);
    356 assert(gradcosts != NULL);
    357
    358 *gradcosts = 0.0;
    359
    360 SCIP_CALL( getMinFeas(scip, nlrows, nnlrows, point, minfeas) );
    361#ifdef SCIP_DEBUG_IMPROVEPOINT
    362 printf("start minfeas = %e\n", *minfeas);
    363#endif
    364
    365 /* stop since start point is feasible */
    366 if( !SCIPisFeasLT(scip, *minfeas, 0.0) )
    367 {
    368#ifdef SCIP_DEBUG_IMPROVEPOINT
    369 printf("start point is feasible");
    370#endif
    371 return SCIP_OKAY;
    372 }
    373
    374 lastminfeas = *minfeas;
    375 vars = SCIPgetVars(scip);
    376 nvars = SCIPgetNVars(scip);
    377
    378 SCIP_CALL( SCIPallocBufferArray(scip, &grad, nvars) );
    379 SCIP_CALL( SCIPallocBufferArray(scip, &updatevec, nvars) );
    380 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
    381
    382 /* main loop */
    383 for( r = 0; r < maxiter && SCIPisFeasLT(scip, *minfeas, 0.0); ++r )
    384 {
    385 SCIP_Real feasibility;
    386 SCIP_Real activity;
    387 SCIP_Real nlrownorm;
    388 SCIP_Real scale;
    389 int nviolnlrows;
    390
    391 BMSclearMemoryArray(updatevec, nvars);
    392 nviolnlrows = 0;
    393
    394 for( i = 0; i < nnlrows; ++i )
    395 {
    396 int j;
    397
    398 SCIP_CALL( SCIPgetNlRowSolFeasibility(scip, nlrows[i], point, &feasibility) );
    399
    400 if( feasibility == SCIP_INVALID ) /*lint !e777*/
    401 {
    402#ifdef SCIP_DEBUG_IMPROVEPOINT
    403 printf("nlrow cannot be evaluated at current point -> skip nlrow\n");
    404#endif
    405 continue;
    406 }
    407
    408 /* do not consider non-violated constraints */
    409 if( SCIPisFeasGE(scip, feasibility, 0.0) )
    410 continue;
    411
    412 SCIP_CALL( computeGradient(scip, nlrows[i], point, varindex, exprit, grad, &nlrownorm) );
    413
    414 /* update estimated costs for computing gradients */
    415 *gradcosts += nlrowgradcosts[i];
    416
    417 /* skip nlrow if gradient is not available at the current point */
    418 if( nlrownorm == SCIP_INVALID ) /*lint !e777*/
    419 {
    420#ifdef SCIP_DEBUG_IMPROVEPOINT
    421 printf("gradient not available at current point -> skip nlrow\n");
    422#endif
    423 continue;
    424 }
    425
    426 /* increase number of violated differentiable nlrows */
    427 ++nviolnlrows;
    428
    429 /* stop if the gradient disappears at the current point */
    430 if( SCIPisZero(scip, nlrownorm) )
    431 {
    432#ifdef SCIP_DEBUG_IMPROVEPOINT
    433 printf("gradient vanished at current point -> stop\n");
    434#endif
    435 goto TERMINATE;
    436 }
    437
    438 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrows[i], point, &activity) );
    439 assert(activity != SCIP_INVALID); /*lint !e777*/
    440
    441 /* compute -g(x_k) / ||grad(g)(x_k)||^2 for a constraint g(x_k) <= 0 */
    442 scale = -feasibility / nlrownorm;
    443 if( !SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrows[i])) && SCIPisGT(scip, activity, SCIPnlrowGetRhs(nlrows[i])) )
    444 scale *= -1.0;
    445
    446 /* skip nonlinear row if the scale is too small or too large */
    447 if( SCIPisEQ(scip, scale, 0.0) || SCIPisHugeValue(scip, REALABS(scale)) )
    448 continue;
    449
    450 for( j = 0; j < nvars; ++j )
    451 updatevec[j] += scale * grad[j];
    452 }
    453
    454 /* if there are no violated differentiable rows, stop since start point is feasible or we have no direction for improvement */
    455 if( nviolnlrows == 0 )
    456 {
    457 assert(updatevec[i] == 0.0);
    458 goto TERMINATE;
    459 }
    460
    461 for( i = 0; i < nvars; ++i )
    462 {
    463 /* adjust point */
    464 updatevec[i] = SCIPgetSolVal(scip, point, vars[i]) + updatevec[i] / nviolnlrows;
    465 updatevec[i] = MIN(updatevec[i], SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    466 updatevec[i] = MAX(updatevec[i], SCIPvarGetLbLocal(vars[i])); /*lint !e666*/
    467
    468 SCIP_CALL( SCIPsetSolVal(scip, point, vars[i], updatevec[i]) );
    469 }
    470
    471 /* update feasibility */
    472 SCIP_CALL( getMinFeas(scip, nlrows, nnlrows, point, minfeas) );
    473
    474 /* check stopping criterion */
    475 if( r % minimpriter == 0 && r > 0 )
    476 {
    477 if( *minfeas <= MINFEAS
    478 || (*minfeas-lastminfeas) / MAX(REALABS(*minfeas), REALABS(lastminfeas)) < minimprfac ) /*lint !e666*/
    479 break;
    480 lastminfeas = *minfeas;
    481 }
    482 }
    483
    484TERMINATE:
    485#ifdef SCIP_DEBUG_IMPROVEPOINT
    486 printf("niter=%d minfeas=%e\n", r, *minfeas);
    487#endif
    488
    489 SCIPfreeExpriter(&exprit);
    490
    491 SCIPfreeBufferArray(scip, &updatevec);
    493
    494 return SCIP_OKAY;
    495}
    496
    497/** sorts points w.r.t their feasibilities; points with a feasibility which is too small (w.r.t. the geometric mean of
    498 * all feasibilities) will be filtered out
    499 */
    500static
    502 SCIP* scip, /**< SCIP data structure */
    503 SCIP_SOL** points, /**< array containing improved points */
    504 SCIP_Real* feasibilities, /**< array containing feasibility for each point (sorted) */
    505 int npoints, /**< total number of points */
    506 int* nusefulpoints /**< pointer to store the total number of useful points */
    507 )
    508{
    509 SCIP_Real minfeas;
    510 SCIP_Real meanfeas;
    511 int i;
    512
    513 assert(points != NULL);
    514 assert(feasibilities != NULL);
    515 assert(npoints > 0);
    516 assert(nusefulpoints != NULL);
    517
    518 /* sort points w.r.t their feasibilities; non-negative feasibility correspond to feasible points for the NLP */
    519 SCIPsortDownRealPtr(feasibilities, (void**)points, npoints);
    520 minfeas = feasibilities[npoints - 1];
    521
    522 /* check if all points are feasible */
    523 if( SCIPisFeasGE(scip, minfeas, 0.0) )
    524 {
    525 *nusefulpoints = npoints;
    526 return SCIP_OKAY;
    527 }
    528
    529 *nusefulpoints = 0;
    530
    531 /* compute shifted geometric mean of feasibilities (shift value = 1 - minfeas) */
    532 meanfeas = 1.0;
    533 for( i = 0; i < npoints; ++i )
    534 {
    535 assert(feasibilities[i] - minfeas + 1.0 > 0.0);
    536 meanfeas *= pow(feasibilities[i] - minfeas + 1.0, 1.0 / npoints);
    537 }
    538 meanfeas += minfeas - 1.0;
    539 SCIPdebugMsg(scip, "meanfeas = %e\n", meanfeas);
    540
    541 /* keep all points with which have a feasibility not much below the geometric mean of infeasibilities */
    542 for( i = 0; i < npoints; ++i )
    543 {
    544 if( SCIPisFeasLT(scip, feasibilities[i], 0.0)
    545 && (feasibilities[i] <= 1.05 * meanfeas || SCIPisLE(scip, feasibilities[i], MINFEAS)) )
    546 break;
    547
    548 ++(*nusefulpoints);
    549 }
    550
    551 return SCIP_OKAY;
    552}
    553
    554/** returns the relative distance between two points; considers a smaller bounded domain for unbounded variables */
    555static
    557 SCIP* scip, /**< SCIP data structure */
    558 SCIP_SOL* x, /**< first point */
    559 SCIP_SOL* y, /**< second point */
    560 SCIP_Real maxboundsize /**< maximum variable domain size for unbounded variables */
    561 )
    562{
    563 SCIP_VAR** vars;
    564 int nvars;
    565 SCIP_Real distance;
    566 SCIP_Real solx;
    567 SCIP_Real soly;
    568 SCIP_Real lb;
    569 SCIP_Real ub;
    570 int i;
    571
    572 assert(x != NULL);
    573 assert(y != NULL);
    574
    575 vars = SCIPgetVars(scip);
    576 nvars = SCIPgetNVars(scip);
    577 distance = 0.0;
    578
    579 if( nvars == 0 )
    580 return 0.0;
    581
    582 for( i = 0; i < nvars; ++i )
    583 {
    584 lb = SCIPvarGetLbLocal(vars[i]);
    585 ub = SCIPvarGetUbLocal(vars[i]);
    586 solx = SCIPgetSolVal(scip, x, vars[i]);
    587 soly = SCIPgetSolVal(scip, y, vars[i]);
    588
    589 /* adjust lower and upper bounds for unbounded variables*/
    590 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
    591 {
    592 lb = -maxboundsize / 2.0;
    593 ub = +maxboundsize / 2.0;
    594 }
    595 else if( SCIPisInfinity(scip, -lb) )
    596 {
    597 lb = ub - maxboundsize;
    598 }
    599 else if( SCIPisInfinity(scip, ub) )
    600 {
    601 ub = lb + maxboundsize;
    602 }
    603
    604 /* project solution values to the variable domain */
    605 solx = MIN(MAX(solx, lb), ub);
    606 soly = MIN(MAX(soly, lb), ub);
    607
    608 distance += REALABS(solx - soly) / MAX(1.0, ub - lb);
    609 }
    610
    611 return distance / nvars;
    612}
    613
    614/** cluster useful points with a greedy algorithm */
    615static
    617 SCIP* scip, /**< SCIP data structure */
    618 SCIP_SOL** points, /**< array containing improved points */
    619 int npoints, /**< total number of points */
    620 int* clusteridx, /**< array to store for each point the index of the cluster */
    621 int* ncluster, /**< pointer to store the total number of cluster */
    622 SCIP_Real maxboundsize, /**< maximum variable domain size for unbounded variables */
    623 SCIP_Real maxreldist, /**< maximum relative distance between any two points of the same cluster */
    624 int maxncluster /**< maximum number of clusters to compute */
    625 )
    626{
    627 int i;
    628
    629 assert(points != NULL);
    630 assert(npoints > 0);
    631 assert(clusteridx != NULL);
    632 assert(ncluster != NULL);
    633 assert(maxreldist >= 0.0);
    634 assert(maxncluster >= 0);
    635
    636 /* initialize cluster indices */
    637 for( i = 0; i < npoints; ++i )
    638 clusteridx[i] = INT_MAX;
    639
    640 *ncluster = 0;
    641
    642 for( i = 0; i < npoints && (*ncluster < maxncluster); ++i )
    643 {
    644 int j;
    645
    646 /* point is already assigned to a cluster */
    647 if( clusteridx[i] != INT_MAX )
    648 continue;
    649
    650 /* create a new cluster for i */
    651 clusteridx[i] = *ncluster;
    652
    653 for( j = i + 1; j < npoints; ++j )
    654 {
    655 if( clusteridx[j] == INT_MAX && getRelDistance(scip, points[i], points[j], maxboundsize) <= maxreldist )
    656 clusteridx[j] = *ncluster;
    657 }
    658
    659 ++(*ncluster);
    660 }
    661
    662#ifndef NDEBUG
    663 for( i = 0; i < npoints; ++i )
    664 {
    665 assert(clusteridx[i] >= 0);
    666 assert(clusteridx[i] < *ncluster || clusteridx[i] == INT_MAX);
    667 }
    668#endif
    669
    670 return SCIP_OKAY;
    671}
    672
    673/** calls the sub-NLP heuristic for a given cluster */
    674static
    676 SCIP* scip, /**< SCIP data structure */
    677 SCIP_HEUR* heur, /**< multi-start heuristic */
    678 SCIP_HEUR* nlpheur, /**< pointer to NLP local search heuristics */
    679 SCIP_SOL** points, /**< array containing improved points */
    680 int npoints, /**< total number of points */
    681 SCIP_Bool* success /**< pointer to store if we could find a solution */
    682 )
    683{
    684 SCIP_VAR** vars;
    685 SCIP_SOL* refpoint;
    686 SCIP_RESULT nlpresult;
    687 SCIP_Real val;
    688 int nbinvars;
    689 int nintvars;
    690 int nvars;
    691 int i;
    692
    693 assert(points != NULL);
    694 assert(npoints > 0);
    695
    696 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    697 *success = FALSE;
    698
    699 SCIP_CALL( SCIPcreateSol(scip, &refpoint, heur) );
    700
    701 /* compute reference point */
    702 for( i = 0; i < nvars; ++i )
    703 {
    704 int p;
    705
    706 val = 0.0;
    707
    708 for( p = 0; p < npoints; ++p )
    709 {
    710 assert(points[p] != NULL);
    711 val += SCIPgetSolVal(scip, points[p], vars[i]);
    712 }
    713
    714 SCIP_CALL( SCIPsetSolVal(scip, refpoint, vars[i], val / npoints) );
    715 }
    716
    717 /* round point for sub-NLP heuristic */
    718 SCIP_CALL( SCIProundSol(scip, refpoint, success) );
    719 SCIPdebugMsg(scip, "rounding of refpoint successfully? %u\n", *success);
    720
    721 /* round variables manually if the locks did not allow us to round them */
    722 if( !(*success) )
    723 {
    724 for( i = 0; i < nbinvars + nintvars; ++i )
    725 {
    726 val = SCIPgetSolVal(scip, refpoint, vars[i]);
    727
    728 if( !SCIPisFeasIntegral(scip, val) )
    729 {
    730 assert(SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(vars[i])));
    731 assert(SCIPisFeasIntegral(scip, SCIPvarGetUbLocal(vars[i])));
    732
    733 /* round and adjust value */
    734 val = SCIPround(scip, val);
    735 val = MIN(val, SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    736 val = MAX(val, SCIPvarGetLbLocal(vars[i])); /*lint !e666*/
    737 assert(SCIPisFeasIntegral(scip, val));
    738
    739 SCIP_CALL( SCIPsetSolVal(scip, refpoint, vars[i], val) );
    740 }
    741 }
    742 }
    743
    744 /* call sub-NLP heuristic */
    745 SCIP_CALL( SCIPapplyHeurSubNlp(scip, nlpheur, &nlpresult, refpoint, NULL) );
    746 SCIP_CALL( SCIPfreeSol(scip, &refpoint) );
    747
    748 /* let sub-NLP heuristic decide whether the solution is feasible or not */
    749 *success = nlpresult == SCIP_FOUNDSOL;
    750
    751 return SCIP_OKAY;
    752}
    753
    754/** recursive helper function to count the number of nodes in a sub-expr */
    755static
    757 SCIP_EXPR* expr /**< expression */
    758 )
    759{
    760 int sum;
    761 int i;
    762
    763 assert(expr != NULL);
    764
    765 sum = 0;
    766 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    767 {
    768 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
    769 sum += getExprSize(child);
    770 }
    771 return 1 + sum;
    772}
    773
    774/** main function of the multi-start heuristic (see @ref heur_multistart.h for more details); it consists of the
    775 * following four steps:
    776 *
    777 * 1. sampling points in the current domain; for unbounded variables we use a bounded box
    778 *
    779 * 2. reduce infeasibility by using a gradient descent method
    780 *
    781 * 3. cluster points; filter points with a too large infeasibility
    782 *
    783 * 4. compute start point for each cluster and use it in the sub-NLP heuristic (@ref heur_subnlp.h)
    784 */
    785static
    787 SCIP* scip, /**< SCIP data structure */
    788 SCIP_HEUR* heur, /**< heuristic */
    789 SCIP_HEURDATA* heurdata, /**< heuristic data */
    790 SCIP_RESULT* result /**< pointer to store the result */
    791 )
    792{
    793 SCIP_NLROW** nlrows;
    794 SCIP_SOL** points;
    795 SCIP_HASHMAP* varindex;
    796 SCIP_Real* feasibilities;
    797 SCIP_Real* nlrowgradcosts;
    798 int* clusteridx;
    799 SCIP_Real gradlimit;
    800 SCIP_Real bestobj;
    801 int nusefulpoints;
    802 int nrndpoints;
    803 int ncluster;
    804 int nnlrows;
    805 int npoints;
    806 int start;
    807 int i;
    808
    809 assert(scip != NULL);
    810 assert(heur != NULL);
    811 assert(result != NULL);
    812 assert(heurdata != NULL);
    813
    814 SCIPdebugMsg(scip, "call applyHeur()\n");
    815
    816 nlrows = SCIPgetNLPNlRows(scip);
    817 nnlrows = SCIPgetNNLPNlRows(scip);
    819
    820 SCIP_CALL( SCIPallocBufferArray(scip, &points, heurdata->nrndpoints) );
    821 SCIP_CALL( SCIPallocBufferArray(scip, &nlrowgradcosts, nnlrows) );
    822 SCIP_CALL( SCIPallocBufferArray(scip, &feasibilities, heurdata->nrndpoints) );
    823 SCIP_CALL( SCIPallocBufferArray(scip, &clusteridx, heurdata->nrndpoints) );
    825
    826 /* create an unique mapping of all variables to 0,..,SCIPgetNVars(scip)-1 */
    827 for( i = 0; i < SCIPgetNVars(scip); ++i )
    828 {
    829 SCIP_CALL( SCIPhashmapInsertInt(varindex, (void*)SCIPgetVars(scip)[i], i) );
    830 }
    831
    832 /* compute estimated costs of computing a gradient for each nlrow */
    833 for( i = 0; i < nnlrows; ++i )
    834 {
    835 nlrowgradcosts[i] = GRADCOSTFAC_LINEAR * SCIPnlrowGetNLinearVars(nlrows[i]);
    836 if( SCIPnlrowGetExpr(nlrows[i]) != NULL )
    837 nlrowgradcosts[i] += GRADCOSTFAC_NONLINEAR * getExprSize(SCIPnlrowGetExpr(nlrows[i]));
    838 }
    839
    840 /*
    841 * 1. sampling points in the current domain; for unbounded variables we use a bounded box
    842 */
    843 SCIP_CALL( sampleRandomPoints(scip, points, heurdata->nrndpoints, heurdata->maxboundsize, heurdata->randnumgen,
    844 bestobj, &nrndpoints) );
    845 assert(nrndpoints >= 0);
    846
    847 if( nrndpoints == 0 )
    848 goto TERMINATE;
    849
    850 /*
    851 * 2. improve points via consensus vectors
    852 */
    853 gradlimit = heurdata->gradlimit == 0.0 ? SCIPinfinity(scip) : heurdata->gradlimit;
    854 for( npoints = 0; npoints < nrndpoints && gradlimit >= 0 && !SCIPisStopped(scip); ++npoints )
    855 {
    856 SCIP_Real gradcosts;
    857
    858 SCIP_CALL( improvePoint(scip, nlrows, nnlrows, varindex, points[npoints],
    859 heurdata->maxiter, heurdata->minimprfac, heurdata->minimpriter, &feasibilities[npoints], nlrowgradcosts,
    860 &gradcosts) );
    861
    862 gradlimit -= gradcosts;
    863 SCIPdebugMsg(scip, "improve point %d / %d gradlimit = %g\n", npoints, nrndpoints, gradlimit);
    864 }
    865 assert(npoints >= 0 && npoints <= nrndpoints);
    866
    867 if( npoints == 0 )
    868 goto TERMINATE;
    869
    870 /*
    871 * 3. filter and cluster points
    872 */
    873 SCIP_CALL( filterPoints(scip, points, feasibilities, npoints, &nusefulpoints) );
    874 assert(nusefulpoints >= 0);
    875 SCIPdebugMsg(scip, "nusefulpoints = %d\n", nusefulpoints);
    876
    877 if( nusefulpoints == 0 )
    878 goto TERMINATE;
    879
    880 SCIP_CALL( clusterPointsGreedy(scip, points, nusefulpoints, clusteridx, &ncluster, heurdata->maxboundsize,
    881 heurdata->maxreldist, heurdata->maxncluster) );
    882 assert(ncluster >= 0 && ncluster <= heurdata->maxncluster);
    883 SCIPdebugMsg(scip, "ncluster = %d\n", ncluster);
    884
    885 SCIPsortIntPtr(clusteridx, (void**)points, nusefulpoints);
    886
    887 /*
    888 * 4. compute start point for each cluster and use it in the sub-NLP heuristic (@ref heur_subnlp.h)
    889 */
    890 start = 0;
    891 while( start < nusefulpoints && clusteridx[start] != INT_MAX && !SCIPisStopped(scip) )
    892 {
    893 SCIP_Bool success;
    894 int end;
    895
    896 end = start;
    897 while( end < nusefulpoints && clusteridx[start] == clusteridx[end] )
    898 ++end;
    899
    900 assert(end - start > 0);
    901
    902 /* call sub-NLP heuristic */
    903 SCIP_CALL( solveNLP(scip, heur, heurdata->heursubnlp, &points[start], end - start, &success) );
    904 SCIPdebugMsg(scip, "solveNLP result = %u\n", success);
    905
    906 if( success )
    907 *result = SCIP_FOUNDSOL;
    908
    909 /* go to the next cluster */
    910 start = end;
    911 }
    912
    913TERMINATE:
    914 /* free memory */
    915 for( i = nrndpoints - 1; i >= 0 ; --i )
    916 {
    917 assert(points[i] != NULL);
    918 SCIP_CALL( SCIPfreeSol(scip, &points[i]) );
    919 }
    920
    921 SCIPhashmapFree(&varindex);
    922 SCIPfreeBufferArray(scip, &clusteridx);
    923 SCIPfreeBufferArray(scip, &feasibilities);
    924 SCIPfreeBufferArray(scip, &nlrowgradcosts);
    925 SCIPfreeBufferArray(scip, &points);
    926
    927 return SCIP_OKAY;
    928}
    929
    930/*
    931 * Callback methods of primal heuristic
    932 */
    933
    934/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    935static
    936SCIP_DECL_HEURCOPY(heurCopyMultistart)
    937{ /*lint --e{715}*/
    938
    940
    941 /* call inclusion method of primal heuristic */
    943
    944 return SCIP_OKAY;
    945}
    946
    947/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    948static
    949SCIP_DECL_HEURFREE(heurFreeMultistart)
    950{ /*lint --e{715}*/
    951 SCIP_HEURDATA* heurdata;
    952
    953 /* free heuristic data */
    954 heurdata = SCIPheurGetData(heur);
    955
    956 SCIPfreeBlockMemory(scip, &heurdata);
    957 SCIPheurSetData(heur, NULL);
    958
    959 return SCIP_OKAY;
    960}
    961
    962/** initialization method of primal heuristic (called after problem was transformed) */
    963static
    964SCIP_DECL_HEURINIT(heurInitMultistart)
    965{ /*lint --e{715}*/
    966 SCIP_HEURDATA* heurdata;
    967
    968 assert( heur != NULL );
    969
    970 heurdata = SCIPheurGetData(heur);
    971 assert(heurdata != NULL);
    972
    973 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    975
    976 /* try to find sub-NLP heuristic */
    977 heurdata->heursubnlp = SCIPfindHeur(scip, "subnlp");
    978
    979 return SCIP_OKAY;
    980}
    981
    982/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    983static
    984SCIP_DECL_HEUREXIT(heurExitMultistart)
    985{ /*lint --e{715}*/
    986 SCIP_HEURDATA* heurdata;
    987
    988 assert( heur != NULL );
    989
    990 heurdata = SCIPheurGetData(heur);
    991 assert(heurdata != NULL);
    992 assert(heurdata->randnumgen != NULL);
    993
    994 SCIPfreeRandom(scip, &heurdata->randnumgen);
    995
    996 return SCIP_OKAY;
    997}
    998
    999/** execution method of primal heuristic */
    1000static
    1001SCIP_DECL_HEUREXEC(heurExecMultistart)
    1002{ /*lint --e{715}*/
    1003 SCIP_HEURDATA* heurdata;
    1004
    1005 assert( heur != NULL );
    1006
    1007 heurdata = SCIPheurGetData(heur);
    1008 assert(heurdata != NULL);
    1009
    1010 *result = SCIP_DIDNOTRUN;
    1011
    1012 /* check cases for which the heuristic is not applicable */
    1013 if( !SCIPisNLPConstructed(scip) || heurdata->heursubnlp == NULL || SCIPgetNNlpis(scip) <= 0 )
    1014 return SCIP_OKAY;
    1015
    1016 /* check whether the heuristic should be applied for a problem containing integer variables */
    1017 if( heurdata->onlynlps && (SCIPgetNBinVars(scip) > 0 || SCIPgetNIntVars(scip) > 0) )
    1018 return SCIP_OKAY;
    1019
    1020 *result = SCIP_DIDNOTFIND;
    1021
    1022 SCIP_CALL( applyHeur(scip, heur, heurdata, result) );
    1023
    1024 return SCIP_OKAY;
    1025}
    1026
    1027/*
    1028 * primal heuristic specific interface methods
    1029 */
    1030
    1031/** creates the multistart primal heuristic and includes it in SCIP */
    1033 SCIP* scip /**< SCIP data structure */
    1034 )
    1035{
    1036 SCIP_HEURDATA* heurdata;
    1037 SCIP_HEUR* heur;
    1038
    1039 /* create multistart primal heuristic data */
    1040 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1041 BMSclearMemory(heurdata);
    1042
    1043 /* include primal heuristic */
    1046 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecMultistart, heurdata) );
    1047
    1048 assert(heur != NULL);
    1049
    1050 /* set non fundamental callbacks via setter functions */
    1051 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyMultistart) );
    1052 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeMultistart) );
    1053 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitMultistart) );
    1054 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitMultistart) );
    1055
    1056 /* add multistart primal heuristic parameters */
    1057 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nrndpoints",
    1058 "number of random points generated per execution call",
    1059 &heurdata->nrndpoints, FALSE, DEFAULT_NRNDPOINTS, 0, INT_MAX, NULL, NULL) );
    1060
    1061 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxboundsize",
    1062 "maximum variable domain size for unbounded variables",
    1063 &heurdata->maxboundsize, FALSE, DEFAULT_MAXBOUNDSIZE, 0.0, SCIPinfinity(scip), NULL, NULL) );
    1064
    1065 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxiter",
    1066 "number of iterations to reduce the maximum violation of a point",
    1067 &heurdata->maxiter, FALSE, DEFAULT_MAXITER, 0, INT_MAX, NULL, NULL) );
    1068
    1069 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprfac",
    1070 "minimum required improving factor to proceed in improvement of a single point",
    1071 &heurdata->minimprfac, FALSE, DEFAULT_MINIMPRFAC, -SCIPinfinity(scip), SCIPinfinity(scip), NULL, NULL) );
    1072
    1073 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minimpriter",
    1074 "number of iteration when checking the minimum improvement",
    1075 &heurdata->minimpriter, FALSE, DEFAULT_MINIMPRITER, 1, INT_MAX, NULL, NULL) );
    1076
    1077 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxreldist",
    1078 "maximum distance between two points in the same cluster",
    1079 &heurdata->maxreldist, FALSE, DEFAULT_MAXRELDIST, 0.0, SCIPinfinity(scip), NULL, NULL) );
    1080
    1081 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gradlimit",
    1082 "limit for gradient computations for all improvePoint() calls (0 for no limit)",
    1083 &heurdata->gradlimit, FALSE, DEFAULT_GRADLIMIT, 0.0, SCIPinfinity(scip), NULL, NULL) );
    1084
    1085 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxncluster",
    1086 "maximum number of considered clusters per heuristic call",
    1087 &heurdata->maxncluster, FALSE, DEFAULT_MAXNCLUSTER, 0, INT_MAX, NULL, NULL) );
    1088
    1089 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/onlynlps",
    1090 "should the heuristic run only on continuous problems?",
    1091 &heurdata->onlynlps, FALSE, DEFAULT_ONLYNLPS, NULL, NULL) );
    1092
    1093 return SCIP_OKAY;
    1094}
    SCIP_VAR ** y
    Definition: circlepacking.c:64
    SCIP_Real * r
    Definition: circlepacking.c:59
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    #define NULL
    Definition: def.h:257
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define SQR(x)
    Definition: def.h:208
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
    Definition: heur_subnlp.c:1763
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludeHeurMultistart(SCIP *scip)
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_RETCODE SCIPevalExprGradient(SCIP *scip, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
    Definition: scip_expr.c:1692
    SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
    Definition: expriter.c:969
    SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
    Definition: expr.c:3972
    SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1457
    SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2362
    SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
    Definition: expriter.c:858
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
    Definition: expr_var.c:423
    void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2376
    SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
    Definition: expriter.c:501
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetNNlpis(SCIP *scip)
    Definition: scip_nlpi.c:205
    SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
    Definition: scip_nlp.c:110
    int SCIPgetNNLPNlRows(SCIP *scip)
    Definition: scip_nlp.c:341
    SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
    Definition: scip_nlp.c:319
    SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
    Definition: nlp.c:1914
    SCIP_RETCODE SCIPgetNlRowSolFeasibility(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *feasibility)
    Definition: scip_nlp.c:1558
    int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
    Definition: nlp.c:1864
    SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
    Definition: nlp.c:1874
    SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
    Definition: nlp.c:1894
    SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
    Definition: nlp.c:1884
    SCIP_RETCODE SCIPgetNlRowSolActivity(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *activity)
    Definition: scip_nlp.c:1522
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:882
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPclearSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1473
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3128
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2003
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeasRound(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    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)
    void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
    void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
    static SCIP_Real getRelDistance(SCIP *scip, SCIP_SOL *x, SCIP_SOL *y, SCIP_Real maxboundsize)
    static SCIP_RETCODE getMinFeas(SCIP *scip, SCIP_NLROW **nlrows, int nnlrows, SCIP_SOL *sol, SCIP_Real *minfeas)
    #define HEUR_TIMING
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_DECL_HEURCOPY(heurCopyMultistart)
    #define GRADCOSTFAC_NONLINEAR
    #define DEFAULT_ONLYNLPS
    #define DEFAULT_MINIMPRFAC
    #define DEFAULT_MAXNCLUSTER
    #define DEFAULT_MINIMPRITER
    #define HEUR_DISPCHAR
    static SCIP_RETCODE sampleRandomPoints(SCIP *scip, SCIP_SOL **rndpoints, int nmaxrndpoints, SCIP_Real maxboundsize, SCIP_RANDNUMGEN *randnumgen, SCIP_Real bestobj, int *nstored)
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    static int getVarIndex(SCIP_HASHMAP *varindex, SCIP_VAR *var)
    #define MINIMPRFAC
    #define HEUR_NAME
    static SCIP_DECL_HEUREXIT(heurExitMultistart)
    static SCIP_RETCODE filterPoints(SCIP *scip, SCIP_SOL **points, SCIP_Real *feasibilities, int npoints, int *nusefulpoints)
    static SCIP_DECL_HEURINIT(heurInitMultistart)
    #define DEFAULT_RANDSEED
    static SCIP_DECL_HEUREXEC(heurExecMultistart)
    static SCIP_RETCODE improvePoint(SCIP *scip, SCIP_NLROW **nlrows, int nnlrows, SCIP_HASHMAP *varindex, SCIP_SOL *point, int maxiter, SCIP_Real minimprfac, int minimpriter, SCIP_Real *minfeas, SCIP_Real *nlrowgradcosts, SCIP_Real *gradcosts)
    #define DEFAULT_MAXRELDIST
    #define GRADCOSTFAC_LINEAR
    static SCIP_RETCODE computeGradient(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_HASHMAP *varindex, SCIP_EXPRITER *exprit, SCIP_Real *grad, SCIP_Real *norm)
    static SCIP_RETCODE applyHeur(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_RESULT *result)
    #define DEFAULT_NRNDPOINTS
    static SCIP_RETCODE solveNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_HEUR *nlpheur, SCIP_SOL **points, int npoints, SCIP_Bool *success)
    #define HEUR_FREQ
    static SCIP_DECL_HEURFREE(heurFreeMultistart)
    #define DEFAULT_GRADLIMIT
    #define HEUR_USESSUBSCIP
    static SCIP_RETCODE clusterPointsGreedy(SCIP *scip, SCIP_SOL **points, int npoints, int *clusteridx, int *ncluster, SCIP_Real maxboundsize, SCIP_Real maxreldist, int maxncluster)
    #define MINFEAS
    #define DEFAULT_MAXITER
    static int getExprSize(SCIP_EXPR *expr)
    #define DEFAULT_MAXBOUNDSIZE
    multistart heuristic for convex and nonconvex MINLPs
    NLP local search primal heuristic using sub-SCIPs.
    memory allocation routines
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public functions to work with algebraic expressions
    public methods for primal heuristics
    public methods for message output
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for NLP management
    public methods for problem variables
    public functions to work with algebraic expressions
    general public methods
    public methods for primal heuristic plugins and divesets
    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 SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public methods for timing
    @ SCIP_EXPRITER_DFS
    Definition: type_expr.h:718
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63