SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_mpec.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_mpec.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief mpec primal heuristic
28 * @author Felipe Serrano
29 * @author Benjamin Mueller
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
35#include "scip/pub_expr.h"
36#include "scip/expr_var.h"
37#include "scip/expr_sum.h"
38#include "scip/expr_pow.h"
39#include "scip/heur_mpec.h"
40#include "scip/heur_subnlp.h"
41#include "scip/pub_cons.h"
42#include "scip/pub_heur.h"
43#include "scip/pub_message.h"
44#include "scip/pub_misc.h"
45#include "scip/pub_nlp.h"
46#include "scip/pub_var.h"
47#include "scip/scip_cons.h"
48#include "scip/scip_general.h"
49#include "scip/scip_heur.h"
50#include "scip/scip_mem.h"
51#include "scip/scip_message.h"
52#include "scip/scip_nlp.h"
53#include "scip/scip_nlpi.h"
54#include "scip/scip_numerics.h"
55#include "scip/scip_param.h"
56#include "scip/scip_prob.h"
57#include "scip/scip_sol.h"
59#include "scip/scip_timing.h"
60
61
62#define HEUR_NAME "mpec"
63#define HEUR_DESC "regularization heuristic for convex and nonconvex MINLPs"
64#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
65#define HEUR_PRIORITY -2050000
66#define HEUR_FREQ 50
67#define HEUR_FREQOFS 0
68#define HEUR_MAXDEPTH -1
69#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
70#define HEUR_USESSUBSCIP TRUE /**< disable the heuristic in sub-SCIPs, even though it does not use any */
71
72#define DEFAULT_INITTHETA 0.125 /**< default initial regularization right-hand side value (< 0.25) */
73#define DEFAULT_SIGMA 0.5 /**< default regularization update factor (< 1) */
74#define DEFAULT_MAXITER 100 /**< default maximum number of iterations of the MPEC loop */
75#define DEFAULT_MAXNLPITER 500 /**< default maximum number of NLP iterations per solve */
76#define DEFAULT_MINGAPLEFT 0.05 /**< default minimum amount of gap left in order to call the heuristic */
77#define DEFAULT_SUBNLPTRIGGER 1e-3 /**< default maximum integrality violation before triggering a sub-NLP call */
78#define DEFAULT_MAXNLPCOST 1e+8 /**< default maximum cost available for solving NLPs per call of the heuristic */
79#define DEFAULT_MINIMPROVE 0.01 /**< default factor by which heuristic should at least improve the incumbent */
80#define DEFAULT_MAXNUNSUCC 10 /**< default maximum number of consecutive calls for which the heuristic did not find an improving solution */
81
82/*
83 * Data structures
84 */
85
86/** primal heuristic data */
87struct SCIP_HeurData
88{
89 SCIP_NLPI* nlpi; /**< nlpi used to create the nlpi problem */
90 SCIP_NLPIPROBLEM* nlpiprob; /**< nlpi problem representing the NLP relaxation */
91 SCIP_HASHMAP* var2idx; /**< mapping between variables and nlpi indices */
92 SCIP_HEUR* subnlp; /**< sub-NLP heuristic */
93
94 SCIP_Real inittheta; /**< initial regularization right-hand side value */
95 SCIP_Real sigma; /**< regularization update factor */
96 SCIP_Real subnlptrigger; /**< maximum number of NLP iterations per solve */
97 SCIP_Real maxnlpcost; /**< maximum cost available for solving NLPs per call of the heuristic */
98 SCIP_Real minimprove; /**< factor by which heuristic should at least improve the incumbent */
99 SCIP_Real mingapleft; /**< minimum amount of gap left in order to call the heuristic */
100 int maxiter; /**< maximum number of iterations of the MPEC loop */
101 int maxnlpiter; /**< maximum number of NLP iterations per solve */
102 int nunsucc; /**< number of consecutive calls for which the heuristic did not find an
103 * improving solution */
104 int maxnunsucc; /**< maximum number of consecutive calls for which the heuristic did not
105 * find an improving solution */
106};
107
108
109/*
110 * Local methods
111 */
112
113/** creates the data structure for generating the current NLP relaxation */
114static
116 SCIP* scip, /**< SCIP data structure */
117 SCIP_HEURDATA* heurdata /**< heuristic data */
118 )
119{
121
122 assert(heurdata != NULL);
123 assert(heurdata->nlpi != NULL);
124
125 /* NLP has been already created */
126 if( heurdata->nlpiprob != NULL )
127 return SCIP_OKAY;
128
129 /* compute cutoff value to ensure minimum improvement */
130 if( SCIPgetNSols(scip) > 0 )
131 {
133
135
137 {
138 cutoff = (1.0 - heurdata->minimprove) * SCIPgetUpperbound(scip)
139 + heurdata->minimprove * SCIPgetLowerbound(scip);
140 }
141 else
142 {
143 if( SCIPgetUpperbound(scip) >= 0.0 )
144 cutoff = ( 1.0 - heurdata->minimprove ) * SCIPgetUpperbound(scip);
145 else
146 cutoff = ( 1.0 + heurdata->minimprove ) * SCIPgetUpperbound(scip);
147 }
148 cutoff = MIN(upperbound, cutoff);
149 SCIPdebugMsg(scip, "set objective limit %g in [%g,%g]\n", cutoff, SCIPgetLowerbound(scip),
151 }
152
155 heurdata->var2idx, NULL, NULL, cutoff, TRUE, FALSE) );
156
157 return SCIP_OKAY;
158}
159
160/** frees the data structures for the NLP relaxation */
161static
163 SCIP* scip, /**< SCIP data structure */
164 SCIP_HEURDATA* heurdata /**< heuristic data */
165 )
166{
167 assert(heurdata != NULL);
168
169 /* NLP has not been created yet */
170 if( heurdata->nlpiprob == NULL )
171 return SCIP_OKAY;
172
173 assert(heurdata->nlpi != NULL);
174 assert(heurdata->var2idx != NULL);
175
176 SCIPhashmapFree(&heurdata->var2idx);
177 SCIP_CALL( SCIPfreeNlpiProblem(scip, heurdata->nlpi, &heurdata->nlpiprob) );
178
179 return SCIP_OKAY;
180}
181
182/** adds or updates the regularization constraints to the NLP; for a given parameter theta we add for each non-fixed
183 * binary variable z the constraint z*(1-z) <= theta; if these constraint are already present we update the theta on
184 * the right-hand side
185 */
186static
188 SCIP* scip, /**< SCIP data structure */
189 SCIP_HEURDATA* heurdata, /**< heuristic data */
190 SCIP_VAR** binvars, /**< array containing all non-fixed binary variables */
191 int nbinvars, /**< total number of non-fixed binary variables */
192 SCIP_Real theta, /**< regularization parameter */
193 SCIP_Bool update /**< should the regularization constraints be added or updated? */
194 )
195{
196 int i;
197
198 assert(binvars != NULL);
199 assert(nbinvars > 0);
200
201 /* add or update regularization for each non-fixed binary variables */
202 if( !update )
203 {
204 SCIP_NLROW** nlrows;
205
206 SCIP_CALL( SCIPallocBufferArray(scip, &nlrows, nbinvars) );
207
208 for( i = 0; i < nbinvars; ++i )
209 {
210 SCIP_Real one = 1.0;
211 SCIP_Real minusone = -1.0;
212 SCIP_EXPR* varexpr;
213 SCIP_EXPR* powexpr;
214 SCIP_EXPR* sumexpr;
215 char name[SCIP_MAXSTRLEN];
216
217 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_reg", SCIPvarGetName(binvars[i]));
218
219 /* -binvars[i]^2 */
220 SCIP_CALL( SCIPcreateExprVar(scip, &varexpr, binvars[i], NULL, NULL) );
221 SCIP_CALL( SCIPcreateExprPow(scip, &powexpr, varexpr, 2.0, NULL, NULL) );
222 SCIP_CALL( SCIPcreateExprSum(scip, &sumexpr, 1, &powexpr, &minusone, 0.0, NULL, NULL) );
223
224 /* binvars[i] - binvars[i]^2 <= theta */
225 SCIP_CALL( SCIPcreateNlRow(scip, &nlrows[i], name, 0.0, 1, &binvars[i], &one, sumexpr, -SCIPinfinity(scip), theta, SCIP_EXPRCURV_CONCAVE) );
226
227 SCIP_CALL( SCIPreleaseExpr(scip, &sumexpr) );
228 SCIP_CALL( SCIPreleaseExpr(scip, &powexpr) );
229 SCIP_CALL( SCIPreleaseExpr(scip, &varexpr) );
230 }
231
232 SCIP_CALL( SCIPaddNlpiProblemNlRows(scip, heurdata->nlpi, heurdata->nlpiprob, heurdata->var2idx, nlrows, nbinvars) );
233
234 for( i = nbinvars-1; i >= 0; --i )
235 {
236 SCIP_CALL( SCIPreleaseNlRow(scip, &nlrows[i]) );
237 }
238
239 SCIPfreeBufferArray(scip, &nlrows);
240 }
241 else
242 {
243 int startidx = SCIPgetNNLPNlRows(scip) + 1; /* the cutoff is a separate constraint */
244 SCIP_Real* lhss;
245 SCIP_Real* rhss;
246 int* indices;
247
248 SCIP_CALL( SCIPallocBufferArray(scip, &lhss, nbinvars) );
249 SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nbinvars) );
250 SCIP_CALL( SCIPallocBufferArray(scip, &indices, nbinvars) );
251
252 for( i = 0; i < nbinvars; ++i )
253 {
254 lhss[i] = -SCIPinfinity(scip);
255 rhss[i] = theta;
256 indices[i] = startidx + i;
257 }
258
259 SCIP_CALL( SCIPchgNlpiConsSides(scip, heurdata->nlpi, heurdata->nlpiprob, nbinvars, indices, lhss, rhss) );
260
261 SCIPfreeBufferArray(scip, &indices);
264 }
265
266 return SCIP_OKAY;
267}
268
269/** recursive helper function to count the number of nodes in a sub-expr */
270static
272 SCIP_EXPR* expr /**< expression */
273 )
274{
275 int sum;
276 int i;
277
278 assert(expr != NULL);
279
280 sum = 0;
281 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
282 {
283 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
284 sum += getExprSize(child);
285 }
286 return 1 + sum;
287}
288
289/** main execution function of the MPEC heuristic */
290static
292 SCIP* scip, /**< SCIP data structure */
293 SCIP_HEUR* heur, /**< MPEC heuristic */
294 SCIP_HEURDATA* heurdata, /**< heuristic data */
295 SCIP_RESULT* result /**< pointer to store the result */
296 )
297{
298 SCIP_NLPSTATISTICS nlpstatistics;
299 SCIP_NLPPARAM nlpparam = SCIP_NLPPARAM_DEFAULT(scip); /*lint !e446*/
300 SCIP_VAR** binvars = NULL;
301 SCIP_Real* initguess = NULL;
302 SCIP_Real* ubs = NULL;
303 SCIP_Real* lbs = NULL;
304 int* indices = NULL;
305 SCIP_Real theta = heurdata->inittheta;
306 SCIP_Real nlpcostperiter = 0.0;
307 SCIP_Real nlpcostleft = heurdata->maxnlpcost;
308 SCIP_Bool reinit = TRUE;
309 SCIP_Bool fixed = FALSE;
310 SCIP_Bool subnlpcalled = FALSE;
311 int nbinvars = 0;
312 int i;
313
314 assert(heurdata->nlpiprob != NULL);
315 assert(heurdata->var2idx != NULL);
316 assert(heurdata->nlpi != NULL);
317 assert(result != NULL);
318
320
321 /* collect all non-fixed binary variables */
322 for( i = 0; i < SCIPgetNBinVars(scip); ++i )
323 {
326
328 binvars[nbinvars++] = var;
329 }
330
331 /* all binary variables are fixed */
332 SCIPdebugMsg(scip, "nbinvars %d\n", nbinvars);
333 if( nbinvars == 0 )
334 goto TERMINATE;
335
337 SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nbinvars) );
338 SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nbinvars) );
339 SCIP_CALL( SCIPallocBufferArray(scip, &indices, nbinvars) );
340
341 /* compute estimate cost for each NLP iteration */
342 for( i = 0; i < SCIPgetNNLPNlRows(scip); ++i )
343 {
345 assert(nlrow != NULL);
346
347 nlpcostperiter += 1.0 * SCIPnlrowGetNLinearVars(nlrow);
348
349 if( SCIPnlrowGetExpr(nlrow) != NULL )
350 nlpcostperiter += 3.0 * getExprSize(SCIPnlrowGetExpr(nlrow));
351 }
352
353 /* set initial guess */
354 for( i = 0; i < SCIPgetNVars(scip); ++i )
355 {
357 initguess[i] = SCIPgetSolVal(scip, NULL, var);
358 /* SCIPdebugMsg(scip, "set initial value for %s to %g\n", SCIPvarGetName(var), initguess[i]); */
359 }
360 SCIP_CALL( SCIPsetNlpiInitialGuess(scip, heurdata->nlpi, heurdata->nlpiprob, initguess, NULL, NULL, NULL) );
361
362 /* set parameters of NLP solver */
363 nlpparam.feastol /= 10.0;
364 nlpparam.opttol /= 10.0;
365 nlpparam.iterlimit = heurdata->maxnlpiter;
366
367 /* main loop */
368 for( i = 0; i < heurdata->maxiter && *result != SCIP_FOUNDSOL && nlpcostleft > 0.0 && !SCIPisStopped(scip); ++i )
369 {
370 SCIP_Real* primal = NULL;
371 SCIP_Bool binaryfeasible;
372 SCIP_Bool regularfeasible;
373 SCIP_NLPSOLSTAT solstat;
374 SCIP_Real maxviolbin = 0.0;
375 SCIP_Real maxviolreg = 0.0;
376 int j;
377
378 /* add or update regularization */
379 SCIP_CALL( addRegularScholtes(scip, heurdata, binvars, nbinvars, theta, i > 0) );
380
381 /* solve NLP */
382 SCIP_CALL( SCIPsolveNlpiParam(scip, heurdata->nlpi, heurdata->nlpiprob, nlpparam) );
383 solstat = SCIPgetNlpiSolstat(scip, heurdata->nlpi, heurdata->nlpiprob);
384
385 /* give up if an error occurred or no primal values are accessible */
386 if( solstat > SCIP_NLPSOLSTAT_LOCINFEASIBLE )
387 {
388 SCIPdebugMsg(scip, "error occurred during NLP solve -> stop!\n");
389 break;
390 }
391
392 /* update nlpcostleft */
393 SCIP_CALL( SCIPgetNlpiStatistics(scip, heurdata->nlpi, heurdata->nlpiprob, &nlpstatistics) );
394 nlpcostleft -= nlpstatistics.niterations * nlpcostperiter * nbinvars;
395 SCIPdebugMsg(scip, "nlpcostleft = %e\n", nlpcostleft);
396
397 SCIP_CALL( SCIPgetNlpiSolution(scip, heurdata->nlpi, heurdata->nlpiprob, &primal, NULL, NULL, NULL, NULL) );
398 assert(primal != NULL);
399
400 /* check for binary feasibility */
401 binaryfeasible = TRUE;
402 regularfeasible = TRUE;
403 for( j = 0; j < nbinvars; ++j )
404 {
405 int idx = SCIPhashmapGetImageInt(heurdata->var2idx, (void*)binvars[j]);
406 binaryfeasible = binaryfeasible && SCIPisFeasIntegral(scip, primal[idx]);
407 regularfeasible = regularfeasible && SCIPisLE(scip, primal[idx] - SQR(primal[idx]), theta);
408
409 maxviolreg = MAX(maxviolreg, primal[idx] - SQR(primal[idx]) - theta);
410 maxviolbin = MAX(maxviolbin, MIN(primal[idx], 1.0-primal[idx]));
411 }
412 SCIPdebugMsg(scip, "maxviol-regularization %g maxviol-integrality %g\n", maxviolreg, maxviolbin);
413
414 /* call sub-NLP heuristic when the maximum binary infeasibility is small enough (or this is the last iteration
415 * because we reached the nlpcost limit)
416 */
417 if( !subnlpcalled && heurdata->subnlp != NULL
418 && (SCIPisLE(scip, maxviolbin, heurdata->subnlptrigger) || nlpcostleft <= 0.0)
419 && !SCIPisStopped(scip) )
420 {
421 SCIP_SOL* refpoint;
422 SCIP_RESULT subnlpresult;
423
424 SCIPdebugMsg(scip, "call sub-NLP heuristic because binary infeasibility is small enough\n");
425 SCIP_CALL( SCIPcreateSol(scip, &refpoint, heur) );
426
427 for( j = 0; j < SCIPgetNVars(scip); ++j )
428 {
430 SCIP_Real val = SCIPvarIsBinary(var) ? SCIPfeasRound(scip, primal[j]) : primal[j];
431 SCIP_CALL( SCIPsetSolVal(scip, refpoint, var, val) );
432 }
433
434 SCIP_CALL( SCIPapplyHeurSubNlp(scip, heurdata->subnlp, &subnlpresult, refpoint, NULL) );
435 SCIP_CALL( SCIPfreeSol(scip, &refpoint) );
436 SCIPdebugMsg(scip, "result of sub-NLP call: %d\n", subnlpresult);
437
438 /* stop MPEC heuristic when the sub-NLP heuristic has found a feasible solution */
439 if( subnlpresult == SCIP_FOUNDSOL )
440 {
441 SCIPdebugMsg(scip, "sub-NLP found a feasible solution -> stop!\n");
442 break;
443 }
444
445 subnlpcalled = TRUE;
446 }
447
448 /* NLP feasible + binary feasible -> add solution and stop */
449 if( solstat <= SCIP_NLPSOLSTAT_FEASIBLE && binaryfeasible )
450 {
451 SCIP_SOL* sol;
452 SCIP_Bool stored;
453
454 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
455
456 for( j = 0; j < SCIPgetNVars(scip); ++j )
457 {
459 assert(j == SCIPhashmapGetImageInt(heurdata->var2idx, (void*)var));
460 SCIP_CALL( SCIPsetSolVal(scip, sol, var, primal[j]) );
461 }
462
463#ifdef SCIP_DEBUG
464 SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, TRUE, FALSE, &stored) );
465#else
467#endif
468 SCIPdebugMsg(scip, "found a solution (stored = %u)\n", stored);
469
470 if( stored )
472 break;
473 }
474
475 /* NLP feasible + binary infeasible -> reduce theta */
476 else if( solstat <= SCIP_NLPSOLSTAT_FEASIBLE && !binaryfeasible )
477 {
478 BMScopyMemoryArray(initguess, primal, SCIPgetNVars(scip));
479 SCIP_CALL( SCIPsetNlpiInitialGuess(scip, heurdata->nlpi, heurdata->nlpiprob, initguess, NULL, NULL, NULL) );
480 SCIPdebugMsg(scip, "update theta from %g -> %g\n", theta, theta*heurdata->sigma);
481
482 if( !reinit )
483 {
484 SCIPdebugMsg(scip, "reinit fixed the infeasibility\n");
485 reinit = TRUE;
486 }
487
488 theta *= heurdata->sigma;
489
490 /* unfix binary variables */
491 if( fixed )
492 {
493 SCIPdebugMsg(scip, "unfixing binary variables\n");
494 for( j = 0; j < nbinvars; ++j )
495 {
496 lbs[j] = 0.0;
497 ubs[j] = 1.0;
498 indices[j] = SCIPhashmapGetImageInt(heurdata->var2idx, (void*)binvars[j]);
499 }
500 SCIP_CALL( SCIPchgNlpiVarBounds(scip, heurdata->nlpi, heurdata->nlpiprob, nbinvars, indices, lbs, ubs) );
501 fixed = FALSE;
502 }
503 }
504
505 /* NLP infeasible + regularization feasible -> stop (give up) */
506 else if( solstat > SCIP_NLPSOLSTAT_FEASIBLE && regularfeasible )
507 {
508 SCIPdebugMsg(scip, "NLP is infeasible but regularization constraints are satisfied -> stop!\n");
509 break;
510 }
511
512 /* NLP infeasible + binary infeasible -> set initial point / fix binary variables */
513 else
514 {
515 assert(solstat > SCIP_NLPSOLSTAT_FEASIBLE && !regularfeasible);
516
517 SCIPdebugMsg(scip, "NLP solution is not feasible for the NLP and the binary variables\n");
518
519 /* stop if fixing did not resolve the infeasibility */
520 if( fixed )
521 {
522 SCIPdebugMsg(scip, "fixing variables did not resolve infeasibility -> stop!\n");
523 break;
524 }
525
526 /* fix variables if reinit is FALSE; otherwise set another initial point */
527 if( !reinit )
528 {
529 int nfixedvars = 0;
530
531 /* fix binary variables */
532 for( j = 0; j < nbinvars; ++j )
533 {
534 int idx = SCIPhashmapGetImageInt(heurdata->var2idx, (void*)binvars[j]);
535 indices[j] = idx;
536
537 if( SCIPisFeasLE(scip, primal[idx] - SQR(primal[idx]), theta) )
538 {
539 lbs[j] = 0.0;
540 ubs[j] = 1.0;
541 }
542 else
543 {
544 lbs[j] = primal[idx] >= 0.5 ? 0.0 : 1.0;
545 ubs[j] = primal[idx] >= 0.5 ? 0.0 : 1.0;
546 ++nfixedvars;
547 /* SCIPdebugMsg(scip, "fix binary variable %s = %g\n", SCIPvarGetName(binvars[j]), ubs[j]); */
548 }
549 }
550 SCIPdebugMsg(scip, "fixed %d binary variables\n", nfixedvars);
551 SCIP_CALL( SCIPchgNlpiVarBounds(scip, heurdata->nlpi, heurdata->nlpiprob, nbinvars, indices, lbs, ubs) );
552 fixed = TRUE;
553 }
554 else
555 {
556 SCIPdebugMsg(scip, "update initial guess\n");
557
558 /* set initial point */
559 for( j = 0; j < nbinvars; ++j )
560 {
561 int idx = SCIPhashmapGetImageInt(heurdata->var2idx, (void*)binvars[j]);
562 initguess[idx] = primal[idx] >= 0.5 ? 0.0 : 1.0;
563 /* SCIPdebugMsg(scip, "update init guess for %s to %g\n", SCIPvarGetName(binvars[j]), initguess[idx]); */
564 }
565 SCIP_CALL( SCIPsetNlpiInitialGuess(scip, heurdata->nlpi, heurdata->nlpiprob, initguess, NULL, NULL, NULL) );
566 reinit = FALSE;
567 }
568 }
569 }
570
571TERMINATE:
572 SCIPfreeBufferArrayNull(scip, &indices);
575 SCIPfreeBufferArrayNull(scip, &initguess);
576 SCIPfreeBufferArray(scip, &binvars);
577
578 return SCIP_OKAY;
579}
580
581
582/*
583 * Callback methods of primal heuristic
584 */
585
586/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
587static
589{ /*lint --e{715}*/
590
592
593 /* call inclusion method of primal heuristic */
595
596 return SCIP_OKAY;
597}
598
599/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
600static
602{ /*lint --e{715}*/
604 assert(heurdata != NULL);
605
607 SCIPheurSetData(heur, NULL);
608
609 return SCIP_OKAY;
610}
611
612/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
613static
614SCIP_DECL_HEURINITSOL(heurInitsolMpec)
615{ /*lint --e{715}*/
617
618 assert(heurdata != NULL);
619 assert(heurdata->nlpi == NULL);
620
621 if( SCIPgetNNlpis(scip) > 0 )
622 {
623 heurdata->nlpi = SCIPgetNlpis(scip)[0];
624 heurdata->subnlp = SCIPfindHeur(scip, "subnlp");
625 }
626
627 return SCIP_OKAY;
628}
629
630
631/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
632static
633SCIP_DECL_HEUREXITSOL(heurExitsolMpec)
634{ /*lint --e{715}*/
636
637 assert(heurdata != NULL);
638 heurdata->nlpi = NULL;
639
640 return SCIP_OKAY;
641}
642
643/** execution method of primal heuristic */
644static
646{ /*lint --e{715}*/
648 SCIP_CONSHDLR* sosonehdlr = SCIPfindConshdlr(scip, "SOS1");
649 SCIP_CONSHDLR* sostwohdlr = SCIPfindConshdlr(scip, "SOS2");
650
651 assert(heurdata != NULL);
652
654
655 if( SCIPgetNIntVars(scip) > 0 || SCIPgetNBinVars(scip) == 0
656 || heurdata->nlpi == NULL || !SCIPisNLPConstructed(scip)
657 || heurdata->mingapleft > SCIPgetGap(scip)
658 || heurdata->nunsucc > heurdata->maxnunsucc )
659 return SCIP_OKAY;
660
661 /* skip heuristic if constraints without a nonlinear representation are present */
662 if( (sosonehdlr != NULL && SCIPconshdlrGetNConss(sosonehdlr) > 0) ||
663 (sostwohdlr != NULL && SCIPconshdlrGetNConss(sostwohdlr) > 0) )
664 {
665 return SCIP_OKAY;
666 }
667
669
670 /* call MPEC method */
674
675 /* update number of unsuccessful calls */
676 heurdata->nunsucc = (*result == SCIP_FOUNDSOL) ? 0 : heurdata->nunsucc + 1;
677
678 return SCIP_OKAY;
679}
680
681
682/*
683 * primal heuristic specific interface methods
684 */
685
686/** creates the mpec primal heuristic and includes it in SCIP */
688 SCIP* scip /**< SCIP data structure */
689 )
690{
692 SCIP_HEUR* heur = NULL;
693
694 /* create mpec primal heuristic data */
697
698 /* include primal heuristic */
702
703 assert(heur != NULL);
704
705 /* set non fundamental callbacks via setter functions */
706 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyMpec) );
707 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeMpec) );
708 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolMpec) );
709 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolMpec) );
710
711 /* add mpec primal heuristic parameters */
712 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/inittheta",
713 "initial regularization right-hand side value",
714 &heurdata->inittheta, FALSE, DEFAULT_INITTHETA, 0.0, 0.25, NULL, NULL) );
715
716 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/sigma",
717 "regularization update factor",
718 &heurdata->sigma, FALSE, DEFAULT_SIGMA, 0.0, 1.0, NULL, NULL) );
719
720 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/subnlptrigger",
721 "maximum number of NLP iterations per solve",
722 &heurdata->subnlptrigger, FALSE, DEFAULT_SUBNLPTRIGGER, 0.0, 1.0, NULL, NULL) );
723
724 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxnlpcost",
725 "maximum cost available for solving NLPs per call of the heuristic",
726 &heurdata->maxnlpcost, FALSE, DEFAULT_MAXNLPCOST, 0.0, SCIPinfinity(scip), NULL, NULL) );
727
728 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
729 "factor by which heuristic should at least improve the incumbent",
730 &heurdata->minimprove, FALSE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
731
732 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/mingapleft",
733 "minimum amount of gap left in order to call the heuristic",
734 &heurdata->mingapleft, FALSE, DEFAULT_MINGAPLEFT, 0.0, SCIPinfinity(scip), NULL, NULL) );
735
736 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxiter",
737 "maximum number of iterations of the MPEC loop",
738 &heurdata->maxiter, FALSE, DEFAULT_MAXITER, 0, INT_MAX, NULL, NULL) );
739
740 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnlpiter",
741 "maximum number of NLP iterations per solve",
742 &heurdata->maxnlpiter, FALSE, DEFAULT_MAXNLPITER, 0, INT_MAX, NULL, NULL) );
743
744 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnunsucc",
745 "maximum number of consecutive calls for which the heuristic did not find an improving solution",
746 &heurdata->maxnunsucc, FALSE, DEFAULT_MAXNUNSUCC, 0, INT_MAX, NULL, NULL) );
747
748 return SCIP_OKAY;
749}
#define DEFAULT_MINIMPROVE
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define SQR(x)
Definition def.h:208
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
power and signed power expression handlers
sum expression handler
variable expression handler
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_var.c:397
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_sum.c:1117
SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_pow.c:3186
SCIP_Bool SCIPisStopped(SCIP *scip)
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
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
#define SCIPdebugMsg
SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
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 SCIPincludeHeurMpec(SCIP *scip)
Definition heur_mpec.c:687
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4782
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3872
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
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 SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:231
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:247
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition scip_heur.c:263
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 SCIPfreeBufferArrayNull(scip, ptr)
Definition scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPaddNlpiProblemNlRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_NLROW **nlrows, int nnlrows)
Definition scip_nlpi.c:870
SCIP_RETCODE SCIPcreateNlpiProblemFromNlRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **nlpiprob, const char *name, SCIP_NLROW **nlrows, int nnlrows, SCIP_HASHMAP *var2idx, SCIP_HASHMAP *nlrow2idx, SCIP_Real *nlscore, SCIP_Real cutoffbound, SCIP_Bool setobj, SCIP_Bool onlyconvex)
Definition scip_nlpi.c:449
int SCIPgetNNlpis(SCIP *scip)
Definition scip_nlpi.c:205
SCIP_NLPI ** SCIPgetNlpis(SCIP *scip)
Definition scip_nlpi.c:192
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
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition nlp.c:1864
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition scip_nlp.c:1058
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition nlp.c:1894
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition scip_nlp.c:954
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition scip_sol.c:4114
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Real SCIPgetGap(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
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 SCIPisInfinity(SCIP *scip, SCIP_Real val)
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_Real SCIPsumepsilon(SCIP *scip)
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
SCIPfreeSol(scip, &heurdata->sol))
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIPcreateSol(scip, &heurdata->sol, heur))
SCIP_Bool cutoff
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
#define DEFAULT_SUBNLPTRIGGER
Definition heur_mpec.c:77
#define DEFAULT_MAXNUNSUCC
Definition heur_mpec.c:80
#define DEFAULT_MAXNLPITER
Definition heur_mpec.c:75
#define DEFAULT_MINGAPLEFT
Definition heur_mpec.c:76
static SCIP_RETCODE createNLP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition heur_mpec.c:115
#define DEFAULT_MAXNLPCOST
Definition heur_mpec.c:78
static SCIP_RETCODE heurExec(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_RESULT *result)
Definition heur_mpec.c:291
#define DEFAULT_SIGMA
Definition heur_mpec.c:73
static SCIP_RETCODE freeNLP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition heur_mpec.c:162
static SCIP_RETCODE addRegularScholtes(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **binvars, int nbinvars, SCIP_Real theta, SCIP_Bool update)
Definition heur_mpec.c:187
#define DEFAULT_INITTHETA
Definition heur_mpec.c:72
#define DEFAULT_MAXITER
Definition heur_mpec.c:74
static int getExprSize(SCIP_EXPR *expr)
Definition heur_mpec.c:271
mpec primal heuristic
SCIP_VAR * var
NLP local search primal heuristic using sub-SCIPs.
memory allocation routines
#define BMSclearMemory(ptr)
Definition memory.h:129
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
public methods for managing constraints
public functions to work with algebraic expressions
public methods for primal heuristics
public methods for message output
public data structures and miscellaneous methods
public methods for NLP management
public methods for problem variables
public methods for constraint handler plugins and constraints
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 solutions
public methods for querying solving statistics
public methods for timing
SCIP_Real feastol
Definition type_nlpi.h:69
SCIP_Real opttol
Definition type_nlpi.h:70
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
@ SCIP_EXPRCURV_CONCAVE
Definition type_expr.h:64
#define SCIP_DECL_HEURINITSOL(x)
Definition type_heur.h:132
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXITSOL(x)
Definition type_heur.h:143
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
struct SCIP_NlpiProblem SCIP_NLPIPROBLEM
Definition type_nlpi.h:53
struct SCIP_NlpStatistics SCIP_NLPSTATISTICS
Definition type_nlpi.h:196
struct SCIP_Nlpi SCIP_NLPI
Definition type_nlpi.h:51
#define SCIP_NLPPARAM_DEFAULT(scip)
Definition type_nlpi.h:126
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition type_nlpi.h:168
@ SCIP_NLPSOLSTAT_LOCINFEASIBLE
Definition type_nlpi.h:163
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition type_nlpi.h:162
struct SCIP_NlpParam SCIP_NLPPARAM
Definition type_nlpi.h:81
@ 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_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64