Scippy

    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-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 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#include <string.h>
    57
    58
    59#define HEUR_NAME "multistart"
    60#define HEUR_DESC "multistart heuristic for convex and nonconvex MINLPs"
    61#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    62#define HEUR_PRIORITY -2100000
    63#define HEUR_FREQ 0
    64#define HEUR_FREQOFS 0
    65#define HEUR_MAXDEPTH -1
    66#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    67#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    68
    69#define DEFAULT_RANDSEED 131 /**< initial random seed */
    70#define DEFAULT_NRNDPOINTS 100 /**< default number of generated random points per call */
    71#define DEFAULT_MAXBOUNDSIZE 2e+4 /**< default maximum variable domain size for unbounded variables */
    72#define DEFAULT_MAXITER 300 /**< default number of iterations to reduce the violation of a point */
    73#define DEFAULT_MINIMPRFAC 0.05 /**< default minimum required improving factor to proceed in improvement of a point */
    74#define DEFAULT_MINIMPRITER 10 /**< default number of iteration when checking the minimum improvement */
    75#define DEFAULT_MAXRELDIST 0.15 /**< default maximum distance between two points in the same cluster */
    76#define DEFAULT_GRADLIMIT 5e+6 /**< default limit for gradient computations for all improvePoint() calls */
    77#define DEFAULT_MAXNCLUSTER 3 /**< default maximum number of considered clusters per heuristic call */
    78#define DEFAULT_ONLYNLPS TRUE /**< should the heuristic run only on continuous problems? */
    79
    80#define MINFEAS -1e+4 /**< minimum feasibility for a point; used for filtering and improving
    81 * feasibility */
    82#define MINIMPRFAC 0.95 /**< improvement factor used to discard randomly generated points with a
    83 * too large objective value */
    84#define GRADCOSTFAC_LINEAR 1.0 /**< gradient cost factor for the number of linear variables */
    85#define GRADCOSTFAC_NONLINEAR 3.0 /**< gradient cost factor for the number of nodes in nonlinear expression */
    86
    87/*
    88 * Data structures
    89 */
    90
    91/** primal heuristic data */
    92struct SCIP_HeurData
    93{
    94 int nrndpoints; /**< number of random points generated per execution call */
    95 SCIP_Real maxboundsize; /**< maximum variable domain size for unbounded variables */
    96 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    97 SCIP_HEUR* heursubnlp; /**< sub-NLP heuristic */
    98
    99 int maxiter; /**< number of iterations to reduce the maximum violation of a point */
    100 SCIP_Real minimprfac; /**< minimum required improving factor to proceed in the improvement of a single point */
    101 int minimpriter; /**< number of iteration when checking the minimum improvement */
    102
    103 SCIP_Real maxreldist; /**< maximum distance between two points in the same cluster */
    104 SCIP_Real gradlimit; /**< limit for gradient computations for all improvePoint() calls (0 for no limit) */
    105 int maxncluster; /**< maximum number of considered clusters per heuristic call */
    106 SCIP_Bool onlynlps; /**< should the heuristic run only on continuous problems? */
    107};
    108
    109
    110/*
    111 * Local methods
    112 */
    113
    114
    115/** returns an unique index of a variable in the range of 0,..,SCIPgetNVars(scip)-1 */
    116#ifndef NDEBUG
    117static
    119 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 */
    120 SCIP_VAR* var /**< variable */
    121 )
    122{
    123 assert(varindex != NULL);
    124 assert(var != NULL);
    125 assert(SCIPhashmapExists(varindex, (void*)var));
    126
    127 return SCIPhashmapGetImageInt(varindex, (void*)var);
    128}
    129#else
    130#define getVarIndex(varindex,var) (SCIPhashmapGetImageInt((varindex), (void*)(var)))
    131#endif
    132
    133/** samples and stores random points; stores points which have a better objective value than the current incumbent
    134 * solution
    135 */
    136static
    138 SCIP* scip, /**< SCIP data structure */
    139 SCIP_SOL** rndpoints, /**< array to store all random points */
    140 int nmaxrndpoints, /**< maximum number of random points to compute */
    141 SCIP_Real maxboundsize, /**< maximum variable domain size for unbounded variables */
    142 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    143 SCIP_Real bestobj, /**< objective value in the transformed space of the current incumbent */
    144 int* nstored /**< pointer to store the number of randomly generated points */
    145 )
    146{
    147 SCIP_VAR** vars;
    148 SCIP_SOL* sol;
    149 SCIP_Real val;
    150 SCIP_Real lb;
    151 SCIP_Real ub;
    152 int nvars;
    153 int niter;
    154 int i;
    155
    156 assert(scip != NULL);
    157 assert(rndpoints != NULL);
    158 assert(nmaxrndpoints > 0);
    159 assert(maxboundsize > 0.0);
    160 assert(randnumgen != NULL);
    161 assert(nstored != NULL);
    162
    163 vars = SCIPgetVars(scip);
    164 nvars = SCIPgetNVars(scip);
    165 *nstored = 0;
    166
    167 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
    168
    169 for( niter = 0; niter < 3 * nmaxrndpoints && *nstored < nmaxrndpoints; ++niter )
    170 {
    171 /* reset solution, in case the old one had infinite objective, which can give difficulties in updating the obj value */
    172 SCIP_CALL( SCIPclearSol(scip, sol) );
    173
    174 for( i = 0; i < nvars; ++i )
    175 {
    176 lb = MIN(SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    177 ub = MAX(SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    178
    179 if( SCIPisFeasEQ(scip, lb, ub) )
    180 val = (lb + ub) / 2.0;
    181 /* use a smaller domain for unbounded variables */
    182 else if( !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
    183 val = SCIPrandomGetReal(randnumgen, lb, ub);
    184 else if( !SCIPisInfinity(scip, -lb) )
    185 val = lb + SCIPrandomGetReal(randnumgen, 0.0, maxboundsize);
    186 else if( !SCIPisInfinity(scip, ub) )
    187 val = ub - SCIPrandomGetReal(randnumgen, 0.0, maxboundsize);
    188 else
    189 {
    190 assert(SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub));
    191 val = SCIPrandomGetReal(randnumgen, -0.5*maxboundsize, 0.5*maxboundsize);
    192 }
    193 assert(SCIPisFeasGE(scip, val, lb) && SCIPisFeasLE(scip, val, ub));
    194
    195 /* set solution value; round the sampled point for integer variables */
    196 if( SCIPvarIsIntegral(vars[i]) )
    197 val = SCIPfeasRound(scip, val);
    198 SCIP_CALL( SCIPsetSolVal(scip, sol, vars[i], val) );
    199 }
    200
    201 /* add solution if it is good enough */
    202 if( SCIPisLE(scip, SCIPgetSolTransObj(scip, sol), bestobj) )
    203 {
    204 SCIP_CALL( SCIPcreateSolCopy(scip, &rndpoints[*nstored], sol) );
    205 ++(*nstored);
    206 }
    207 }
    208 assert(*nstored <= nmaxrndpoints);
    209 SCIPdebugMsg(scip, "found %d randomly generated points\n", *nstored);
    210
    211 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    212
    213 return SCIP_OKAY;
    214}
    215
    216/** computes the minimum feasibility of a given point; a negative value means that there is an infeasibility */
    217static
    219 SCIP* scip, /**< SCIP data structure */
    220 SCIP_NLROW** nlrows, /**< array containing all nlrows */
    221 int nnlrows, /**< total number of nlrows */
    222 SCIP_SOL* sol, /**< solution */
    223 SCIP_Real* minfeas /**< buffer to store the minimum feasibility */
    224 )
    225{
    226 SCIP_Real tmp;
    227 int i;
    228
    229 assert(scip != NULL);
    230 assert(sol != NULL);
    231 assert(minfeas != NULL);
    232 assert(nlrows != NULL);
    233 assert(nnlrows > 0);
    234
    235 *minfeas = SCIPinfinity(scip);
    236
    237 for( i = 0; i < nnlrows; ++i )
    238 {
    239 assert(nlrows[i] != NULL);
    240
    241 SCIP_CALL( SCIPgetNlRowSolFeasibility(scip, nlrows[i], sol, &tmp) );
    242 if( tmp == SCIP_INVALID ) /*lint !e777*/
    243 {
    244 *minfeas = -SCIPinfinity(scip);
    245 return SCIP_OKAY;
    246 }
    247 *minfeas = MIN(*minfeas, tmp);
    248 }
    249
    250 return SCIP_OKAY;
    251}
    252
    253/** computes the gradient for a given point and nonlinear row */
    254static
    256 SCIP* scip, /**< SCIP data structure */
    257 SCIP_NLROW* nlrow, /**< nonlinear row */
    258 SCIP_SOL* sol, /**< solution to compute the gradient for */
    259 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 uniquely */
    260 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
    261 SCIP_Real* grad, /**< buffer to store the gradient; grad[varindex(i)] corresponds to SCIPgetVars(scip)[i] */
    262 SCIP_Real* norm /**< buffer to store ||grad||^2, or SCIP_INVALID if function not differentiable */
    263 )
    264{
    265 SCIP_EXPR* expr;
    266 SCIP_VAR* var;
    267 int i;
    268
    269 assert(scip != NULL);
    270 assert(nlrow != NULL);
    271 assert(varindex != NULL);
    272 assert(sol != NULL);
    273 assert(norm != NULL);
    274
    276 *norm = 0.0;
    277
    278 /* linear part */
    279 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
    280 {
    281 var = SCIPnlrowGetLinearVars(nlrow)[i];
    282 assert(var != NULL);
    283 assert(getVarIndex(varindex, var) >= 0 && getVarIndex(varindex, var) < SCIPgetNVars(scip));
    284
    285 grad[getVarIndex(varindex, var)] += SCIPnlrowGetLinearCoefs(nlrow)[i];
    286 }
    287
    288 /* expression part */
    289 expr = SCIPnlrowGetExpr(nlrow);
    290
    291 if( expr != NULL )
    292 {
    293 assert(exprit != NULL);
    294
    295 SCIP_CALL( SCIPevalExprGradient(scip, expr, sol, 0L) );
    296
    297 /* TODO: change this when nlrows store the vars */
    299 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
    300 {
    301 if( !SCIPisExprVar(scip, expr) )
    302 continue;
    303
    304 var = SCIPgetVarExprVar(expr);
    305 assert(var != NULL);
    306 assert(getVarIndex(varindex, var) >= 0 && getVarIndex(varindex, var) < SCIPgetNVars(scip));
    307
    308 if( SCIPexprGetDerivative(expr) == SCIP_INVALID ) /*lint !e777*/
    309 {
    310 *norm = SCIP_INVALID;
    311 return SCIP_OKAY;
    312 }
    313
    314 grad[getVarIndex(varindex, var)] += SCIPexprGetDerivative(expr);
    315 }
    316 }
    317
    318 /* compute ||grad||^2 */
    319 for( i = 0; i < SCIPgetNVars(scip); ++i )
    320 *norm += SQR(grad[i]);
    321
    322 return SCIP_OKAY;
    323}
    324
    325/** use consensus vectors to improve feasibility for a given starting point */
    326static
    328 SCIP* scip, /**< SCIP data structure */
    329 SCIP_NLROW** nlrows, /**< array containing all nlrows */
    330 int nnlrows, /**< total number of nlrows */
    331 SCIP_HASHMAP* varindex, /**< maps variables to indicies between 0,..,SCIPgetNVars(scip)-1 */
    332 SCIP_SOL* point, /**< random generated point */
    333 int maxiter, /**< maximum number of iterations */
    334 SCIP_Real minimprfac, /**< minimum required improving factor to proceed in the improvement of a single point */
    335 int minimpriter, /**< number of iteration when checking the minimum improvement */
    336 SCIP_Real* minfeas, /**< pointer to store the minimum feasibility */
    337 SCIP_Real* nlrowgradcosts, /**< estimated costs for each gradient computation */
    338 SCIP_Real* gradcosts /**< pointer to store the estimated gradient costs */
    339 )
    340{
    341 SCIP_VAR** vars;
    342 SCIP_EXPRITER* exprit;
    343 SCIP_Real* grad;
    344 SCIP_Real* updatevec;
    345 SCIP_Real lastminfeas;
    346 int nvars;
    347 int r;
    348 int i;
    349
    350 assert(varindex != NULL);
    351 assert(point != NULL);
    352 assert(maxiter > 0);
    353 assert(minfeas != NULL);
    354 assert(nlrows != NULL);
    355 assert(nnlrows > 0);
    356 assert(nlrowgradcosts != NULL);
    357 assert(gradcosts != NULL);
    358
    359 *gradcosts = 0.0;
    360
    361 SCIP_CALL( getMinFeas(scip, nlrows, nnlrows, point, minfeas) );
    362#ifdef SCIP_DEBUG_IMPROVEPOINT
    363 printf("start minfeas = %e\n", *minfeas);
    364#endif
    365
    366 /* stop since start point is feasible */
    367 if( !SCIPisFeasLT(scip, *minfeas, 0.0) )
    368 {
    369#ifdef SCIP_DEBUG_IMPROVEPOINT
    370 printf("start point is feasible");
    371#endif
    372 return SCIP_OKAY;
    373 }
    374
    375 lastminfeas = *minfeas;
    376 vars = SCIPgetVars(scip);
    377 nvars = SCIPgetNVars(scip);
    378
    379 SCIP_CALL( SCIPallocBufferArray(scip, &grad, nvars) );
    380 SCIP_CALL( SCIPallocBufferArray(scip, &updatevec, nvars) );
    381 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
    382
    383 /* main loop */
    384 for( r = 0; r < maxiter && SCIPisFeasLT(scip, *minfeas, 0.0); ++r )
    385 {
    386 SCIP_Real feasibility;
    387 SCIP_Real activity;
    388 SCIP_Real nlrownorm;
    389 SCIP_Real scale;
    390 int nviolnlrows;
    391
    392 BMSclearMemoryArray(updatevec, nvars);
    393 nviolnlrows = 0;
    394
    395 for( i = 0; i < nnlrows; ++i )
    396 {
    397 int j;
    398
    399 SCIP_CALL( SCIPgetNlRowSolFeasibility(scip, nlrows[i], point, &feasibility) );
    400
    401 if( feasibility == SCIP_INVALID ) /*lint !e777*/
    402 {
    403#ifdef SCIP_DEBUG_IMPROVEPOINT
    404 printf("nlrow cannot be evaluated at current point -> skip nlrow\n");
    405#endif
    406 continue;
    407 }
    408
    409 /* do not consider non-violated constraints */
    410 if( SCIPisFeasGE(scip, feasibility, 0.0) )
    411 continue;
    412
    413 SCIP_CALL( computeGradient(scip, nlrows[i], point, varindex, exprit, grad, &nlrownorm) );
    414
    415 /* update estimated costs for computing gradients */
    416 *gradcosts += nlrowgradcosts[i];
    417
    418 /* skip nlrow if gradient is not available at the current point */
    419 if( nlrownorm == SCIP_INVALID ) /*lint !e777*/
    420 {
    421#ifdef SCIP_DEBUG_IMPROVEPOINT
    422 printf("gradient not available at current point -> skip nlrow\n");
    423#endif
    424 continue;
    425 }
    426
    427 /* increase number of violated differentiable nlrows */
    428 ++nviolnlrows;
    429
    430 /* stop if the gradient disappears at the current point */
    431 if( SCIPisZero(scip, nlrownorm) )
    432 {
    433#ifdef SCIP_DEBUG_IMPROVEPOINT
    434 printf("gradient vanished at current point -> stop\n");
    435#endif
    436 goto TERMINATE;
    437 }
    438
    439 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrows[i], point, &activity) );
    440 assert(activity != SCIP_INVALID); /*lint !e777*/
    441
    442 /* compute -g(x_k) / ||grad(g)(x_k)||^2 for a constraint g(x_k) <= 0 */
    443 scale = -feasibility / nlrownorm;
    444 if( !SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrows[i])) && SCIPisGT(scip, activity, SCIPnlrowGetRhs(nlrows[i])) )
    445 scale *= -1.0;
    446
    447 /* skip nonlinear row if the scale is too small or too large */
    448 if( SCIPisEQ(scip, scale, 0.0) || SCIPisHugeValue(scip, REALABS(scale)) )
    449 continue;
    450
    451 for( j = 0; j < nvars; ++j )
    452 updatevec[j] += scale * grad[j];
    453 }
    454
    455 /* if there are no violated differentiable rows, stop since start point is feasible or we have no direction for improvement */
    456 if( nviolnlrows == 0 )
    457 {
    458 assert(updatevec[i] == 0.0);
    459 goto TERMINATE;
    460 }
    461
    462 for( i = 0; i < nvars; ++i )
    463 {
    464 /* adjust point */
    465 updatevec[i] = SCIPgetSolVal(scip, point, vars[i]) + updatevec[i] / nviolnlrows;
    466 updatevec[i] = MIN(updatevec[i], SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    467 updatevec[i] = MAX(updatevec[i], SCIPvarGetLbLocal(vars[i])); /*lint !e666*/
    468
    469 SCIP_CALL( SCIPsetSolVal(scip, point, vars[i], updatevec[i]) );
    470 }
    471
    472 /* update feasibility */
    473 SCIP_CALL( getMinFeas(scip, nlrows, nnlrows, point, minfeas) );
    474
    475 /* check stopping criterion */
    476 if( r % minimpriter == 0 && r > 0 )
    477 {
    478 if( *minfeas <= MINFEAS
    479 || (*minfeas-lastminfeas) / MAX(REALABS(*minfeas), REALABS(lastminfeas)) < minimprfac ) /*lint !e666*/
    480 break;
    481 lastminfeas = *minfeas;
    482 }
    483 }
    484
    485TERMINATE:
    486#ifdef SCIP_DEBUG_IMPROVEPOINT
    487 printf("niter=%d minfeas=%e\n", r, *minfeas);
    488#endif
    489
    490 SCIPfreeExpriter(&exprit);
    491
    492 SCIPfreeBufferArray(scip, &updatevec);
    494
    495 return SCIP_OKAY;
    496}
    497
    498/** sorts points w.r.t their feasibilities; points with a feasibility which is too small (w.r.t. the geometric mean of
    499 * all feasibilities) will be filtered out
    500 */
    501static
    503 SCIP* scip, /**< SCIP data structure */
    504 SCIP_SOL** points, /**< array containing improved points */
    505 SCIP_Real* feasibilities, /**< array containing feasibility for each point (sorted) */
    506 int npoints, /**< total number of points */
    507 int* nusefulpoints /**< pointer to store the total number of useful points */
    508 )
    509{
    510 SCIP_Real minfeas;
    511 SCIP_Real meanfeas;
    512 int i;
    513
    514 assert(points != NULL);
    515 assert(feasibilities != NULL);
    516 assert(npoints > 0);
    517 assert(nusefulpoints != NULL);
    518
    519 /* sort points w.r.t their feasibilities; non-negative feasibility correspond to feasible points for the NLP */
    520 SCIPsortDownRealPtr(feasibilities, (void**)points, npoints);
    521 minfeas = feasibilities[npoints - 1];
    522
    523 /* check if all points are feasible */
    524 if( SCIPisFeasGE(scip, minfeas, 0.0) )
    525 {
    526 *nusefulpoints = npoints;
    527 return SCIP_OKAY;
    528 }
    529
    530 *nusefulpoints = 0;
    531
    532 /* compute shifted geometric mean of feasibilities (shift value = 1 - minfeas) */
    533 meanfeas = 1.0;
    534 for( i = 0; i < npoints; ++i )
    535 {
    536 assert(feasibilities[i] - minfeas + 1.0 > 0.0);
    537 meanfeas *= pow(feasibilities[i] - minfeas + 1.0, 1.0 / npoints);
    538 }
    539 meanfeas += minfeas - 1.0;
    540 SCIPdebugMsg(scip, "meanfeas = %e\n", meanfeas);
    541
    542 /* keep all points with which have a feasibility not much below the geometric mean of infeasibilities */
    543 for( i = 0; i < npoints; ++i )
    544 {
    545 if( SCIPisFeasLT(scip, feasibilities[i], 0.0)
    546 && (feasibilities[i] <= 1.05 * meanfeas || SCIPisLE(scip, feasibilities[i], MINFEAS)) )
    547 break;
    548
    549 ++(*nusefulpoints);
    550 }
    551
    552 return SCIP_OKAY;
    553}
    554
    555/** returns the relative distance between two points; considers a smaller bounded domain for unbounded variables */
    556static
    558 SCIP* scip, /**< SCIP data structure */
    559 SCIP_SOL* x, /**< first point */
    560 SCIP_SOL* y, /**< second point */
    561 SCIP_Real maxboundsize /**< maximum variable domain size for unbounded variables */
    562 )
    563{
    564 SCIP_VAR** vars;
    565 int nvars;
    566 SCIP_Real distance;
    567 SCIP_Real solx;
    568 SCIP_Real soly;
    569 SCIP_Real lb;
    570 SCIP_Real ub;
    571 int i;
    572
    573 assert(x != NULL);
    574 assert(y != NULL);
    575
    576 vars = SCIPgetVars(scip);
    577 nvars = SCIPgetNVars(scip);
    578 distance = 0.0;
    579
    580 if( nvars == 0 )
    581 return 0.0;
    582
    583 for( i = 0; i < nvars; ++i )
    584 {
    585 lb = SCIPvarGetLbLocal(vars[i]);
    586 ub = SCIPvarGetUbLocal(vars[i]);
    587 solx = SCIPgetSolVal(scip, x, vars[i]);
    588 soly = SCIPgetSolVal(scip, y, vars[i]);
    589
    590 /* adjust lower and upper bounds for unbounded variables*/
    591 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
    592 {
    593 lb = -maxboundsize / 2.0;
    594 ub = +maxboundsize / 2.0;
    595 }
    596 else if( SCIPisInfinity(scip, -lb) )
    597 {
    598 lb = ub - maxboundsize;
    599 }
    600 else if( SCIPisInfinity(scip, ub) )
    601 {
    602 ub = lb + maxboundsize;
    603 }
    604
    605 /* project solution values to the variable domain */
    606 solx = MIN(MAX(solx, lb), ub);
    607 soly = MIN(MAX(soly, lb), ub);
    608
    609 distance += REALABS(solx - soly) / MAX(1.0, ub - lb);
    610 }
    611
    612 return distance / nvars;
    613}
    614
    615/** cluster useful points with a greedy algorithm */
    616static
    618 SCIP* scip, /**< SCIP data structure */
    619 SCIP_SOL** points, /**< array containing improved points */
    620 int npoints, /**< total number of points */
    621 int* clusteridx, /**< array to store for each point the index of the cluster */
    622 int* ncluster, /**< pointer to store the total number of cluster */
    623 SCIP_Real maxboundsize, /**< maximum variable domain size for unbounded variables */
    624 SCIP_Real maxreldist, /**< maximum relative distance between any two points of the same cluster */
    625 int maxncluster /**< maximum number of clusters to compute */
    626 )
    627{
    628 int i;
    629
    630 assert(points != NULL);
    631 assert(npoints > 0);
    632 assert(clusteridx != NULL);
    633 assert(ncluster != NULL);
    634 assert(maxreldist >= 0.0);
    635 assert(maxncluster >= 0);
    636
    637 /* initialize cluster indices */
    638 for( i = 0; i < npoints; ++i )
    639 clusteridx[i] = INT_MAX;
    640
    641 *ncluster = 0;
    642
    643 for( i = 0; i < npoints && (*ncluster < maxncluster); ++i )
    644 {
    645 int j;
    646
    647 /* point is already assigned to a cluster */
    648 if( clusteridx[i] != INT_MAX )
    649 continue;
    650
    651 /* create a new cluster for i */
    652 clusteridx[i] = *ncluster;
    653
    654 for( j = i + 1; j < npoints; ++j )
    655 {
    656 if( clusteridx[j] == INT_MAX && getRelDistance(scip, points[i], points[j], maxboundsize) <= maxreldist )
    657 clusteridx[j] = *ncluster;
    658 }
    659
    660 ++(*ncluster);
    661 }
    662
    663#ifndef NDEBUG
    664 for( i = 0; i < npoints; ++i )
    665 {
    666 assert(clusteridx[i] >= 0);
    667 assert(clusteridx[i] < *ncluster || clusteridx[i] == INT_MAX);
    668 }
    669#endif
    670
    671 return SCIP_OKAY;
    672}
    673
    674/** calls the sub-NLP heuristic for a given cluster */
    675static
    677 SCIP* scip, /**< SCIP data structure */
    678 SCIP_HEUR* heur, /**< multi-start heuristic */
    679 SCIP_HEUR* nlpheur, /**< pointer to NLP local search heuristics */
    680 SCIP_SOL** points, /**< array containing improved points */
    681 int npoints, /**< total number of points */
    682 SCIP_Bool* success /**< pointer to store if we could find a solution */
    683 )
    684{
    685 SCIP_VAR** vars;
    686 SCIP_SOL* refpoint;
    687 SCIP_RESULT nlpresult;
    688 SCIP_Real val;
    689 int nbinvars;
    690 int nintvars;
    691 int nvars;
    692 int i;
    693
    694 assert(points != NULL);
    695 assert(npoints > 0);
    696
    697 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    698 *success = FALSE;
    699
    700 SCIP_CALL( SCIPcreateSol(scip, &refpoint, heur) );
    701
    702 /* compute reference point */
    703 for( i = 0; i < nvars; ++i )
    704 {
    705 int p;
    706
    707 val = 0.0;
    708
    709 for( p = 0; p < npoints; ++p )
    710 {
    711 assert(points[p] != NULL);
    712 val += SCIPgetSolVal(scip, points[p], vars[i]);
    713 }
    714
    715 SCIP_CALL( SCIPsetSolVal(scip, refpoint, vars[i], val / npoints) );
    716 }
    717
    718 /* round point for sub-NLP heuristic */
    719 SCIP_CALL( SCIProundSol(scip, refpoint, success) );
    720 SCIPdebugMsg(scip, "rounding of refpoint successfully? %u\n", *success);
    721
    722 /* round variables manually if the locks did not allow us to round them */
    723 if( !(*success) )
    724 {
    725 for( i = 0; i < nbinvars + nintvars; ++i )
    726 {
    727 val = SCIPgetSolVal(scip, refpoint, vars[i]);
    728
    729 if( !SCIPisFeasIntegral(scip, val) )
    730 {
    731 assert(SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(vars[i])));
    732 assert(SCIPisFeasIntegral(scip, SCIPvarGetUbLocal(vars[i])));
    733
    734 /* round and adjust value */
    735 val = SCIPround(scip, val);
    736 val = MIN(val, SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
    737 val = MAX(val, SCIPvarGetLbLocal(vars[i])); /*lint !e666*/
    738 assert(SCIPisFeasIntegral(scip, val));
    739
    740 SCIP_CALL( SCIPsetSolVal(scip, refpoint, vars[i], val) );
    741 }
    742 }
    743 }
    744
    745 /* call sub-NLP heuristic */
    746 SCIP_CALL( SCIPapplyHeurSubNlp(scip, nlpheur, &nlpresult, refpoint, NULL) );
    747 SCIP_CALL( SCIPfreeSol(scip, &refpoint) );
    748
    749 /* let sub-NLP heuristic decide whether the solution is feasible or not */
    750 *success = nlpresult == SCIP_FOUNDSOL;
    751
    752 return SCIP_OKAY;
    753}
    754
    755/** recursive helper function to count the number of nodes in a sub-expr */
    756static
    758 SCIP_EXPR* expr /**< expression */
    759 )
    760{
    761 int sum;
    762 int i;
    763
    764 assert(expr != NULL);
    765
    766 sum = 0;
    767 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    768 {
    769 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
    770 sum += getExprSize(child);
    771 }
    772 return 1 + sum;
    773}
    774
    775/** main function of the multi-start heuristic (see @ref heur_multistart.h for more details); it consists of the
    776 * following four steps:
    777 *
    778 * 1. sampling points in the current domain; for unbounded variables we use a bounded box
    779 *
    780 * 2. reduce infeasibility by using a gradient descent method
    781 *
    782 * 3. cluster points; filter points with a too large infeasibility
    783 *
    784 * 4. compute start point for each cluster and use it in the sub-NLP heuristic (@ref heur_subnlp.h)
    785 */
    786static
    788 SCIP* scip, /**< SCIP data structure */
    789 SCIP_HEUR* heur, /**< heuristic */
    790 SCIP_HEURDATA* heurdata, /**< heuristic data */
    791 SCIP_RESULT* result /**< pointer to store the result */
    792 )
    793{
    794 SCIP_NLROW** nlrows;
    795 SCIP_SOL** points;
    796 SCIP_HASHMAP* varindex;
    797 SCIP_Real* feasibilities;
    798 SCIP_Real* nlrowgradcosts;
    799 int* clusteridx;
    800 SCIP_Real gradlimit;
    801 SCIP_Real bestobj;
    802 int nusefulpoints;
    803 int nrndpoints;
    804 int ncluster;
    805 int nnlrows;
    806 int npoints;
    807 int start;
    808 int i;
    809
    810 assert(scip != NULL);
    811 assert(heur != NULL);
    812 assert(result != NULL);
    813 assert(heurdata != NULL);
    814
    815 SCIPdebugMsg(scip, "call applyHeur()\n");
    816
    817 nlrows = SCIPgetNLPNlRows(scip);
    818 nnlrows = SCIPgetNNLPNlRows(scip);
    820
    821 SCIP_CALL( SCIPallocBufferArray(scip, &points, heurdata->nrndpoints) );
    822 SCIP_CALL( SCIPallocBufferArray(scip, &nlrowgradcosts, nnlrows) );
    823 SCIP_CALL( SCIPallocBufferArray(scip, &feasibilities, heurdata->nrndpoints) );
    824 SCIP_CALL( SCIPallocBufferArray(scip, &clusteridx, heurdata->nrndpoints) );
    826
    827 /* create an unique mapping of all variables to 0,..,SCIPgetNVars(scip)-1 */
    828 for( i = 0; i < SCIPgetNVars(scip); ++i )
    829 {
    830 SCIP_CALL( SCIPhashmapInsertInt(varindex, (void*)SCIPgetVars(scip)[i], i) );
    831 }
    832
    833 /* compute estimated costs of computing a gradient for each nlrow */
    834 for( i = 0; i < nnlrows; ++i )
    835 {
    836 nlrowgradcosts[i] = GRADCOSTFAC_LINEAR * SCIPnlrowGetNLinearVars(nlrows[i]);
    837 if( SCIPnlrowGetExpr(nlrows[i]) != NULL )
    838 nlrowgradcosts[i] += GRADCOSTFAC_NONLINEAR * getExprSize(SCIPnlrowGetExpr(nlrows[i]));
    839 }
    840
    841 /*
    842 * 1. sampling points in the current domain; for unbounded variables we use a bounded box
    843 */
    844 SCIP_CALL( sampleRandomPoints(scip, points, heurdata->nrndpoints, heurdata->maxboundsize, heurdata->randnumgen,
    845 bestobj, &nrndpoints) );
    846 assert(nrndpoints >= 0);
    847
    848 if( nrndpoints == 0 )
    849 goto TERMINATE;
    850
    851 /*
    852 * 2. improve points via consensus vectors
    853 */
    854 gradlimit = heurdata->gradlimit == 0.0 ? SCIPinfinity(scip) : heurdata->gradlimit;
    855 for( npoints = 0; npoints < nrndpoints && gradlimit >= 0 && !SCIPisStopped(scip); ++npoints )
    856 {
    857 SCIP_Real gradcosts;
    858
    859 SCIP_CALL( improvePoint(scip, nlrows, nnlrows, varindex, points[npoints],
    860 heurdata->maxiter, heurdata->minimprfac, heurdata->minimpriter, &feasibilities[npoints], nlrowgradcosts,
    861 &gradcosts) );
    862
    863 gradlimit -= gradcosts;
    864 SCIPdebugMsg(scip, "improve point %d / %d gradlimit = %g\n", npoints, nrndpoints, gradlimit);
    865 }
    866 assert(npoints >= 0 && npoints <= nrndpoints);
    867
    868 if( npoints == 0 )
    869 goto TERMINATE;
    870
    871 /*
    872 * 3. filter and cluster points
    873 */
    874 SCIP_CALL( filterPoints(scip, points, feasibilities, npoints, &nusefulpoints) );
    875 assert(nusefulpoints >= 0);
    876 SCIPdebugMsg(scip, "nusefulpoints = %d\n", nusefulpoints);
    877
    878 if( nusefulpoints == 0 )
    879 goto TERMINATE;
    880
    881 SCIP_CALL( clusterPointsGreedy(scip, points, nusefulpoints, clusteridx, &ncluster, heurdata->maxboundsize,
    882 heurdata->maxreldist, heurdata->maxncluster) );
    883 assert(ncluster >= 0 && ncluster <= heurdata->maxncluster);
    884 SCIPdebugMsg(scip, "ncluster = %d\n", ncluster);
    885
    886 SCIPsortIntPtr(clusteridx, (void**)points, nusefulpoints);
    887
    888 /*
    889 * 4. compute start point for each cluster and use it in the sub-NLP heuristic (@ref heur_subnlp.h)
    890 */
    891 start = 0;
    892 while( start < nusefulpoints && clusteridx[start] != INT_MAX && !SCIPisStopped(scip) )
    893 {
    894 SCIP_Bool success;
    895 int end;
    896
    897 end = start;
    898 while( end < nusefulpoints && clusteridx[start] == clusteridx[end] )
    899 ++end;
    900
    901 assert(end - start > 0);
    902
    903 /* call sub-NLP heuristic */
    904 SCIP_CALL( solveNLP(scip, heur, heurdata->heursubnlp, &points[start], end - start, &success) );
    905 SCIPdebugMsg(scip, "solveNLP result = %u\n", success);
    906
    907 if( success )
    908 *result = SCIP_FOUNDSOL;
    909
    910 /* go to the next cluster */
    911 start = end;
    912 }
    913
    914TERMINATE:
    915 /* free memory */
    916 for( i = nrndpoints - 1; i >= 0 ; --i )
    917 {
    918 assert(points[i] != NULL);
    919 SCIP_CALL( SCIPfreeSol(scip, &points[i]) );
    920 }
    921
    922 SCIPhashmapFree(&varindex);
    923 SCIPfreeBufferArray(scip, &clusteridx);
    924 SCIPfreeBufferArray(scip, &feasibilities);
    925 SCIPfreeBufferArray(scip, &nlrowgradcosts);
    926 SCIPfreeBufferArray(scip, &points);
    927
    928 return SCIP_OKAY;
    929}
    930
    931/*
    932 * Callback methods of primal heuristic
    933 */
    934
    935/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    936static
    937SCIP_DECL_HEURCOPY(heurCopyMultistart)
    938{ /*lint --e{715}*/
    939 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    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:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    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:1762
    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:424
    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:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:884
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPclearSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1475
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3123
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2005
    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:24268
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63