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