Scippy

SCIP

Solving Constraint Integer Programs

heur_dualval.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_dualval.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief dualval primal heuristic
28 * @author Tobias Buchwald
29 *
30 * This heuristic tries to find solutions by taking the LP or NLP, rounding solution values, fixing the variables to the
31 * rounded values and then changing some of the values. To determine which variable is changed we give each variable a
32 * ranking dependent on its dualvalue. We work with a transformed problem that is always feasible and has objective = 0
33 * iff the original problem is also feasible. Thus we cannot expect to find really good solutions.
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
39#include "scip/type_expr.h"
40#include "scip/cons_indicator.h"
41#include "scip/cons_knapsack.h"
42#include "scip/cons_linear.h"
43#include "scip/cons_logicor.h"
44#include "scip/cons_setppc.h"
45#include "scip/cons_varbound.h"
46#include "scip/heur_dualval.h"
47#include "scip/pub_cons.h"
48#include "scip/pub_event.h"
49#include "scip/pub_heur.h"
50#include "scip/pub_message.h"
51#include "scip/pub_misc.h"
52#include "scip/pub_misc_sort.h"
53#include "scip/pub_nlp.h"
54#include "scip/pub_sol.h"
55#include "scip/pub_var.h"
56#include "scip/scip_branch.h"
57#include "scip/scip_cons.h"
58#include "scip/scip_copy.h"
59#include "scip/scip_event.h"
60#include "scip/scip_exact.h"
61#include "scip/scip_general.h"
62#include "scip/scip_heur.h"
63#include "scip/scip_lp.h"
64#include "scip/scip_mem.h"
65#include "scip/scip_message.h"
66#include "scip/scip_nlp.h"
67#include "scip/scip_nlpi.h"
68#include "scip/scip_numerics.h"
69#include "scip/scip_param.h"
70#include "scip/scip_prob.h"
71#include "scip/scip_sol.h"
72#include "scip/scip_solve.h"
74#include "scip/scip_var.h"
75#include <string.h>
76
77#define HEUR_NAME "dualval"
78#define HEUR_DESC "primal heuristic using dual values"
79#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
80#define HEUR_PRIORITY -10
81#define HEUR_FREQ -1
82#define HEUR_FREQOFS 0
83#define HEUR_MAXDEPTH -1
84#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
85#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
86
87#define EVENTHDLR_NAME "lpsol_dualval"
88#define EVENTHDLR_DESC "event handler for lp solution found"
89
90/* default values for user parameters */
91/* boolean parameters */
92#define DEFAULT_FORCEIMPROVEMENTS FALSE /**< exit if objective doesn't improve */
93#define DEFAULT_ONLYCHEAPER TRUE /**< add constraint to ensure that discrete vars are improving */
94#define DEFAULT_ONLYLEAVES FALSE /**< disable the heuristic if it was not called at a leaf of the B&B tree */
95#define DEFAULT_RELAXINDICATORS FALSE /**< relax the indicator variables by introducing continuous copies */
96#define DEFAULT_RELAXCONTVARS FALSE /**< enable relaxation of continous variables */
97
98/* integer parameters */
99#define DEFAULT_HEURVERBLEVEL 0 /**< verblevel of the heuristic, default is 0 to display nothing */
100#define DEFAULT_NLPVERBLEVEL 0 /**< verblevel of the nlp solver, can be 0 or 1 */
101#define DEFAULT_RANKVALUE 10 /**< number of ranks that should be displayed when the heuristic is called */
102#define DEFAULT_MAXCALLS 25 /**< maximal number of recursive calls of the heuristic (if dynamicdepth is off) */
103#define DEFAULT_DYNAMICDEPTH 0 /**< says if and how the recursion depth is computed at runtime */
104#define DEFAULT_MAXEQUALRANKS 50 /**< maximal number of variables that may have maximal rank, quit if there are more, turn off by setting -1 */
105
106/* real value parameters */
107#define DEFAULT_MINGAP 5.0 /**< minimal gap for which we still run the heuristic, if gap is less we return without doing anything */
108#define DEFAULT_LAMBDASLACK 1.0 /**< value added to objective of slack variables, must not be zero */
109#define DEFAULT_LAMBDAOBJ 0.0 /**< scaling factor for the objective function */
110
111
112/**primal heuristic data */
113struct SCIP_HeurData
114{
115 SCIP* subscip; /**< copy of CIP */
116 SCIP_VAR** integervars; /**< array of all binary and integer variables of the original scip */
117 SCIP_HASHMAP* varsciptosubscip; /**< mapping variables in SCIP to sub-SCIP variables */
118 SCIP_HASHMAP* varsubsciptoscip; /**< mapping variables in sub-SCIP to SCIP variables */
119 SCIP_HASHMAP* origsubscipConsMap; /**< maps constraints from the transformed problem to corresponding constraints in subproblem */
120 SCIP_HASHMAP* switchedvars; /**< stores the last value of switched var to avoid cycling */
121 SCIP_HASHMAP* switchedvars2; /**< stores the second last value of switched vars to avoid cycling */
122 SCIP_HASHMAP* relaxcons; /**< maps subscip variables to their relaxation constraints */
123 SCIP_HASHMAP* relaxconsindi; /**< maps indicator variables and their copies to relaxation constraint */
124 SCIP_HASHMAP* slacktoindivarsmap; /**< maps slack variables of indicator constraint to indicator variable */
125 SCIP_HASHMAP* indicators; /**< maps indicator variables to their indicator constraint */
126 SCIP_HASHMAP* conss2nlrow; /**< maps constraint to the corresponding nlrow */
127 SCIP_HASHMAP* dualvalues; /**< maps constraints of the subscip to their dual values */
128 SCIP_HASHMAP* slack2var; /**< maps slack variables to the variable they actually relax */
129 SCIP_HASHMAP* indicopymap; /**< maps indicator variables to their copy variables */
130 SCIP_HASHMAP* indicopymapback; /**< maps copy variables to their indicator variables */
131 SCIP_HASHMAP* slackvarlbMap; /**< mapping used indicators to slack variables lower bound*/
132 SCIP_HASHMAP* slackvarubMap; /**< mapping used indicators to slack variables upper bound*/
133 SCIP_CONS* objbound; /**< contraint for upper bound of the objective function */
134 SCIP_Real prevobjective; /**< stores objective value (of the original) so we know if it improved */
135 SCIP_Real mingap; /**< don't run the heuristic if the gap is less than mingap */
136 SCIP_Real lambdaslack; /**< the value added to the objective function */
137 SCIP_Real lambdaobj; /**< the value the original objective function is scaled with */
138 int integervarssize; /**< size of integervars array */
139 int nintegervars; /**< number of integer variables in the original problem */
140 int heurverblevel; /**< verblevel, range is 0 to 4 */
141 int nlpverblevel; /**< sets verblevel of the included nlp */
142 int rankvalue; /**< print out the 'rankvalue' highest ranks during iterations */
143 int maxcalls; /**< maximum number of allowed iterations */
144 int nonimprovingRounds; /**< nr of rounds, where the algorithm has not improved */
145 int dynamicdepth; /**< how should the number of calls be computed? */
146 int maxequalranks; /**< maximum number of variables that may have maximal (absolute) rank */
147 int nvars; /**< number of active transformed variables in SCIP */
148 int nsubvars; /**< number of original variables in sub-SCIP */
149 int usedcalls; /**< number of currently used iterations */
150 SCIP_Bool isnlp; /**< tells us, whether we have nonlinearities in our program or not */
151 SCIP_Bool forceimprovements; /**< whether we exit on nonimproving objective in the relaxation or not */
152 SCIP_Bool prevInfeasible; /**< will tell us if the previous call led to an infeasible fixing */
153 SCIP_Bool solfound; /**< parameter says, if we already found a solution and have to go back */
154 SCIP_Bool subscipisvalid; /**< whether all constraints have been copied */
155 SCIP_Bool switchdifferent; /**< tells us that we want to go up one level and switch another variable */
156 SCIP_Bool triedsetupsubscip; /**< whether we have tried to setup a sub-SCIP */
157 SCIP_Bool onlycheaper; /**< add constraint to ensure that discrete vars are improving */
158 SCIP_Bool onlyleaves; /**< don't use heuristic if we are not in a leaf of the B&B tree */
159 SCIP_Bool relaxindicators; /**< additionally relax indicator variables */
160 SCIP_Bool relaxcontvars; /**< additionally relax continous variables */
161};
162
163/*
164 * event handler method
165 */
166
167/** initialization method of event handler (called after problem was transformed) */
168static
169SCIP_DECL_EVENTINIT(eventInitLPsol)
170{ /*lint --e{715}*/
171 assert(scip != NULL);
172 assert(eventhdlr != NULL);
173
174 /* notify SCIP that your event handler wants to react on the event type best solution found */
176
177 return SCIP_OKAY;
178}
179
180/** deinitialization method of event handler (called before transformed problem is freed) */
181static
182SCIP_DECL_EVENTEXIT(eventExitLPsol)
183{ /*lint --e{715}*/
184 assert(scip != NULL);
185 assert(eventhdlr != NULL);
186
187 /* notify SCIP that your event handler wants to drop the event type best solution found */
189
190 return SCIP_OKAY;
191}
192
193/** execution method of event handler */
194static
195SCIP_DECL_EVENTEXEC(eventExecLPsol)
196{ /*lint --e{715}*/
197 int i;
198 int nsubconss;
199 SCIP_HEURDATA* heurdata;
200 SCIP_CONS** subconss;
201 SCIP_Real* dualval;
202
203 assert(eventhdlr != NULL);
204 assert(event != NULL);
205 assert(scip != NULL);
207
208 heurdata = (SCIP_HEURDATA* )SCIPeventhdlrGetData(eventhdlr);
209 nsubconss = SCIPgetNOrigConss(heurdata->subscip);
210 subconss = SCIPgetOrigConss(heurdata->subscip);
211
212 /* free memory of all entries and clear the hashmap before filling it */
213 for( i = 0; i < nsubconss; i++ )
214 {
215 dualval = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, subconss[i]);
216 if( dualval != NULL )
217 SCIPfreeBlockMemoryArray(heurdata->subscip, &dualval, 1);
218 }
219 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->dualvalues) );
220
221 /* insert dualvalues from LP into a hashmap */
222 for( i = 0; i < nsubconss; i++ )
223 {
224 SCIP_CONS* transcons = NULL;
225 SCIP_CALL( SCIPgetTransformedCons(heurdata->subscip, subconss[i], &transcons) );
226
227 if( transcons == NULL )
228 continue;
229
230 if( SCIPconsGetHdlr(transcons) != SCIPfindConshdlr(heurdata->subscip, "linear") )
231 continue;
232
233 SCIP_CALL( SCIPallocBlockMemoryArray(heurdata->subscip, &dualval, 1) ); /*lint !e506*/
234 *dualval = -SCIPgetDualsolLinear(heurdata->subscip, transcons );
235 SCIP_CALL( SCIPhashmapInsert(heurdata->dualvalues, subconss[i], dualval) );
236 }
237 if( heurdata->heurverblevel > 2 )
238 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "LP solved event!\n");
239
240 return SCIP_OKAY;
241}
242
243/** includes event handler for best solution found */
244static
246 SCIP* scip, /**< SCIP data structure */
247 SCIP_HEURDATA* heurdata /**< heuristic data */
248 )
249{
250 SCIP_EVENTHDLRDATA* eventhdlrdata;
251 SCIP_EVENTHDLR* eventhdlr = NULL;
252
253 eventhdlrdata = (SCIP_EVENTHDLRDATA*)heurdata;
254
255 /* create event handler */
256 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecLPsol, eventhdlrdata) );
257 assert(eventhdlr != NULL);
258
259 SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitLPsol) );
260 SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitLPsol) );
261
262 return SCIP_OKAY;
263}
264
265/*
266 * Local methods
267 */
268
269/** releases all variables or constraints from given hash map */
270static
272 SCIP* scip, /**< SCIP data structure */
273 SCIP_HASHMAP* hashmap, /**< hashmap */
274 SCIP_Bool isvarmap /**< are the entries variables or constraints? */
275 )
276{
277 int nentries;
278 int i;
279
280 assert(scip != NULL);
281 assert(hashmap != NULL);
282
283 nentries = SCIPhashmapGetNEntries(hashmap);
284
285 for( i = 0; i < nentries; ++i )
286 {
287 SCIP_HASHMAPENTRY* entry;
288 entry = SCIPhashmapGetEntry(hashmap, i);
289
290 if( entry != NULL )
291 {
292 if( isvarmap )
293 {
294 SCIP_VAR* var;
295 var = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
296
297 SCIP_CALL( SCIPreleaseVar(scip, &var) );
298 }
299 else
300 {
301 SCIP_CONS* cons;
302 cons = (SCIP_CONS*) SCIPhashmapEntryGetImage(entry);
303
304 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
305 }
306 }
307 }
308
309 return SCIP_OKAY;
310}
311
312/** releases all NLP rows from given hash map */
313static
315 SCIP* scip, /**< SCIP data structure */
316 SCIP_HASHMAP* hashmap /**< hashmap */
317 )
318{
319 int nentries;
320 int i;
321
322 assert(scip != NULL);
323 assert(hashmap != NULL);
324
325 nentries = SCIPhashmapGetNEntries(hashmap);
326
327 for( i = 0; i < nentries; ++i )
328 {
329 SCIP_HASHMAPENTRY* entry;
330 entry = SCIPhashmapGetEntry(hashmap, i);
331 if( entry != NULL )
332 {
333 SCIP_NLROW* nlrow;
334 nlrow = (SCIP_NLROW*) SCIPhashmapEntryGetImage(entry);
335
336 SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
337 }
338 }
339
340 return SCIP_OKAY;
341}
342
343
344/** adds linear constraints from a SCIP instance to its NLP */
345static
347 SCIP* scip, /**< SCIP data structure */
348 SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
349 SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
350 SCIP_Bool addcontconss, /**< whether to add continuous linear constraints to NLP */
351 SCIP_HEURDATA* heurdata /**< heuristic data structure */
352 )
353{
354 SCIP_CONS** conss;
355 SCIP_VAR** vars;
356 SCIP_NLROW* nlrow;
357 int nconss;
358 int i;
359 int j;
360 int nvars;
361 SCIP_Bool iscombinatorial;
362
363 assert(scip != NULL);
364 assert(conshdlr != NULL);
365
366 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
367 conss = SCIPconshdlrGetConss(conshdlr);
368
369 if( nconss == 0 )
370 return SCIP_OKAY;
371
372 for( i = 0; i < nconss; ++i )
373 {
374 /* skip local and redundant constraints */
375 if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
376 continue;
377
378 /* under some circumstances, this method may be called even though the problem has been shown to be
379 * infeasible in presolve already.
380 * this infeasibility may come from a linear constraint with lhs > rhs
381 * the NLP does not allow such constraints, so we skip them here
382 */
383 if( !SCIPisRelLE(scip, SCIPgetLhsLinear(scip, conss[i]), SCIPgetRhsLinear(scip, conss[i])) )
384 continue;
385
386 nvars = SCIPgetNVarsLinear(scip, conss[i]);
387 vars = SCIPgetVarsLinear(scip, conss[i]);
388
389 /* check if constraint should be added, only need this check if we do not wanna any constraint anyway */
390 if( !addcombconss || !addcontconss )
391 {
392 iscombinatorial = TRUE;
393
394 for( j = 0; j < nvars; ++j )
395 {
396 if( !SCIPvarIsIntegral(vars[j]) )
397 {
398 iscombinatorial = FALSE;
399 break;
400 }
401 }
402
403 /* skip constraint, if not of interest */
404 if( (iscombinatorial && !addcombconss) || (!iscombinatorial && !addcontconss) )
405 continue;
406 }
407
408 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
409 SCIPgetNVarsLinear(scip, conss[i]), SCIPgetVarsLinear(scip, conss[i]), SCIPgetValsLinear(scip, conss[i]), NULL,
410 SCIPgetLhsLinear(scip, conss[i]), SCIPgetRhsLinear(scip, conss[i]),
412
413 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
414 SCIP_CALL( SCIPhashmapInsert(heurdata->conss2nlrow, conss[i], nlrow) );
415 SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
416 }
417
418 return SCIP_OKAY;
419}
420
421/** adds variable bound constraints from a SCIP instance to its NLP */
422static
424 SCIP* scip, /**< SCIP data structure */
425 SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
426 SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
427 SCIP_Bool addcontconss, /**< whether to add continuous linear constraints to NLP */
428 SCIP_HEURDATA* heurdata /**< heuristic data structure */
429 )
430{
431 SCIP_CONS** conss;
432 int nconss;
433 SCIP_NLROW* nlrow;
434 int i;
435 SCIP_VAR* vars[2];
436 SCIP_Real coefs[2];
437 SCIP_Bool iscombinatorial;
438
439 assert(scip != NULL);
440 assert(conshdlr != NULL);
441
442 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
443 conss = SCIPconshdlrGetConss(conshdlr);
444
445 if( nconss == 0 )
446 return SCIP_OKAY;
447
448 for( i = 0; i < nconss; ++i )
449 {
450 /* skip local and redundant constraints */
451 if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
452 continue;
453
454 vars[0] = SCIPgetVarVarbound(scip, conss[i]);
455 vars[1] = SCIPgetVbdvarVarbound(scip, conss[i]);
456
457 iscombinatorial = SCIPvarIsIntegral(vars[0]) && SCIPvarIsIntegral(vars[1]);
458
459 /* skip constraint, if not of interest */
460 if( (iscombinatorial && !addcombconss) || (!iscombinatorial && !addcontconss) )
461 continue;
462
463 coefs[0] = 1.0;
464 coefs[1] = SCIPgetVbdcoefVarbound(scip, conss[i]);
465
466 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
467 2, vars, coefs, NULL,
468 SCIPgetLhsVarbound(scip, conss[i]), SCIPgetRhsVarbound(scip, conss[i]),
470
471 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
472 SCIP_CALL( SCIPhashmapInsert(heurdata->conss2nlrow, conss[i], nlrow) );
473 }
474
475 return SCIP_OKAY;
476}
477
478
479/** adds logic-or constraints to NLP */
480static
482 SCIP* scip, /**< SCIP data structure */
483 SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
484 SCIP_HEURDATA* heurdata /**< heuristic data structure */
485 )
486{
487 SCIP_CONS** conss;
488 int nconss;
489 SCIP_NLROW* nlrow;
490 int i;
491 int j;
492 SCIP_Real* coefs;
493 int coefssize;
494 int nvars;
495
496 assert(scip != NULL);
497 assert(conshdlr != NULL);
498
499 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
500 if( !nconss )
501 return SCIP_OKAY;
502
503 conss = SCIPconshdlrGetConss(conshdlr);
504
505 coefs = NULL;
506 coefssize = 0;
507
508 for( i = 0; i < nconss; ++i )
509 {
510 /* skip local and redundant constraints */
511 if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
512 continue;
513
514 nvars = SCIPgetNVarsLogicor(scip, conss[i]);
515
516 if( coefssize < nvars )
517 {
518 if( coefs == NULL )
519 {
520 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
521 }
522 else
523 {
524 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
525 }
526 for( j = coefssize; j < nvars; ++j )
527 coefs[j] = 1.0;
528 coefssize = nvars;
529 }
530
531 /* logic or constraints: 1 == sum_j x_j */
532 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
533 nvars, SCIPgetVarsLogicor(scip, conss[i]), coefs, NULL,
534 1.0, SCIPinfinity(scip),
536
537 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
538 SCIP_CALL( SCIPhashmapInsert(heurdata->conss2nlrow, conss[i], nlrow) );
539 }
540
542
543 return SCIP_OKAY;
544}
545
546/** adds setppc constraints to NLP */
547static
549 SCIP* scip, /**< SCIP data structure */
550 SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
551 SCIP_HEURDATA* heurdata /**< heuristic data structure */
552 )
553{
554 SCIP_CONS** conss;
555 int nconss;
556 SCIP_NLROW* nlrow;
557 int i;
558 int j;
559 SCIP_Real* coefs;
560 int coefssize;
561 int nvars;
562 SCIP_Real lhs;
563 SCIP_Real rhs;
564
565 assert(scip != NULL);
566 assert(conshdlr != NULL);
567
568 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
569 if( nconss == 0 )
570 return SCIP_OKAY;
571
572 conss = SCIPconshdlrGetConss(conshdlr);
573
574 coefs = NULL;
575 coefssize = 0;
576
577 for( i = 0; i < nconss; ++i )
578 {
579 /* skip local and redundant constraints */
580 if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
581 continue;
582
583 nvars = SCIPgetNVarsSetppc(scip, conss[i]);
584
585 if( coefssize < nvars )
586 {
587 if( coefs == NULL )
588 {
589 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
590 }
591 else
592 {
593 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
594 }
595 for( j = coefssize; j < nvars; ++j )
596 coefs[j] = 1.0;
597 coefssize = nvars;
598 }
599
600 /* setppc constraint: 1 ~ sum_j x_j */
601
602 switch( SCIPgetTypeSetppc(scip, conss[i]) )
603 {
605 lhs = 1.0;
606 rhs = 1.0;
607 break;
608
610 lhs = -SCIPinfinity(scip);
611 rhs = 1.0;
612 break;
613
615 lhs = 1.0;
616 rhs = SCIPinfinity(scip);
617 break;
618
619 default:
620 SCIPerrorMessage("unexpected setppc type\n");
621 return SCIP_ERROR;
622 }
623
624 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
625 nvars, SCIPgetVarsSetppc(scip, conss[i]), coefs, NULL,
626 lhs, rhs,
628
629 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
630 SCIP_CALL( SCIPhashmapInsert(heurdata->conss2nlrow, conss[i], nlrow) );
631 }
632
634
635 return SCIP_OKAY;
636}
637
638/** adds knapsack constraints to NLP */
639static
641 SCIP* scip, /**< SCIP data structure */
642 SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
643 SCIP_HEURDATA* heurdata /**< heuristic data structure */
644 )
645{
646 SCIP_CONS** conss;
647 int nconss;
648 SCIP_NLROW* nlrow;
649 int i;
650 int j;
651 SCIP_Real* coefs;
652 int coefssize;
653 int nvars;
654
655 assert(scip != NULL);
656 assert(conshdlr != NULL);
657
658 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
659 if( nconss == 0 )
660 return SCIP_OKAY;
661
662 conss = SCIPconshdlrGetConss(conshdlr);
663 assert(conss != NULL);
664
665 coefs = NULL;
666 coefssize = 0;
667
668 for( i = 0; i < nconss; ++i )
669 {
670 SCIP_Longint* weights;
671
672 /* skip local and redundant constraints */
673 if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
674 continue;
675
676 nvars = SCIPgetNVarsKnapsack(scip, conss[i]);
677
678 if( coefssize < nvars )
679 {
680 if( coefs == NULL )
681 {
682 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
683 }
684 else
685 {
686 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
687 }
688 coefssize = nvars;
689 }
690
691 weights = SCIPgetWeightsKnapsack(scip, conss[i]);
692 for( j = 0; j < nvars; ++j )
693 coefs[j] = (SCIP_Real)weights[j]; /*lint !e613*/
694
695 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
696 nvars, SCIPgetVarsKnapsack(scip, conss[i]), coefs, NULL,
699
700 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
701 SCIP_CALL( SCIPhashmapInsert(heurdata->conss2nlrow, conss[i], nlrow) );
702 }
703
705
706 return SCIP_OKAY;
707}
708
709
710/** adds combinatorial and/or continuous variants of linear constraints from a SCIP instance to its NLP */
711static
713 SCIP* scip, /**< SCIP data structure */
714 SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
715 SCIP_Bool addcontconss, /**< whether to add continuous linear constraints to NLP */
716 SCIP_HEURDATA* heurdata /**< heuristic data structure */
717 )
718{
719 SCIP_CONSHDLR* conshdlr;
720
721 /* add linear constraints */
722 conshdlr = SCIPfindConshdlr(scip, "linear");
723 if( conshdlr != NULL )
724 {
725 SCIP_CALL( addLinearConstraints(scip, conshdlr, addcombconss, addcontconss, heurdata) );
726 }
727
728 /* add varbound constraints */
729 conshdlr = SCIPfindConshdlr(scip, "varbound");
730 if( conshdlr != NULL )
731 {
732 SCIP_CALL( addVarboundConstraints(scip, conshdlr, addcombconss, addcontconss, heurdata) );
733 }
734
735 if( addcombconss )
736 {
737 /* add logic-or constraints */
738 conshdlr = SCIPfindConshdlr(scip, "logicor");
739 if( conshdlr != NULL )
740 {
741 SCIP_CALL( addLogicOrConstraints(scip, conshdlr, heurdata) );
742 }
743
744 /* add setppc constraints */
745 conshdlr = SCIPfindConshdlr(scip, "setppc");
746 if( conshdlr != NULL )
747 {
748 SCIP_CALL( addSetppcConstraints(scip, conshdlr, heurdata) );
749 }
750
751 /* add knapsack constraints */
752 conshdlr = SCIPfindConshdlr(scip, "knapsack");
753 if( conshdlr != NULL )
754 {
755 SCIP_CALL( addKnapsackConstraints(scip, conshdlr, heurdata) );
756 }
757 }
758
759 return SCIP_OKAY;
760}
761
762
763
764/** creates a SCIP_SOL in our SCIP space out of the SCIP_SOL from a sub-SCIP */
765static
767 SCIP* scip, /**< SCIP data structure */
768 SCIP_HEUR* heur, /**< heuristic data structure */
769 SCIP_SOL** sol, /**< buffer to store solution value; if pointing to NULL, a new solution
770 * is created, otherwise values in the given one are overwritten */
771 SCIP_SOL* subsol /**< solution of sub-SCIP */
772 )
773{
774 SCIP_HEURDATA* heurdata;
775 SCIP_VAR** vars;
776 SCIP_VAR** subvars;
777 SCIP_VAR* var;
778 SCIP_VAR* subvar;
779 SCIP_Real scalar;
780 SCIP_Real constant;
781 SCIP_Real val;
782 int i;
783 int nvars;
784
785 heurdata = SCIPheurGetData(heur);
786 assert( heurdata != NULL );
787 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nvars, NULL, NULL, NULL, NULL) );
788
789 if( *sol == NULL )
790 {
791 SCIP_CALL( SCIPcreateOrigSol(scip, sol, heur) );
792 }
793
794 vars = SCIPgetOrigVars(scip);
795 nvars = SCIPgetNOrigVars(scip);
796
797 for( i = 0; i < nvars; ++i )
798 {
799 var = vars[i];
800
801 constant = 0;
802 scalar = 1.0;
803 var = SCIPvarGetTransVar(var);
804 val = 0;
805
806 if( REALABS(scalar) > 0 )
807 {
808 SCIP_Real transval = 0.0;
809
810 subvar = (SCIP_VAR*) SCIPhashmapGetImage(heurdata->varsciptosubscip, (void*)var);
811 if( subvar == NULL )
812 {
813 SCIPdebugMsg(scip, "return14 : abort building solution since a variable was not in our list\n");
814
815 SCIP_CALL( SCIPfreeSol(scip, sol) );
816 return SCIP_OKAY;
817 }
818
819 if( SCIPvarIsBinary(subvar) )
820 transval = SCIPvarGetLbGlobal(subvar);
821 else
822 {
823 SCIP_Real tconstant = 0.0;
824 SCIP_Real tscalar = 1.0;
825 SCIP_CALL( SCIPgetProbvarSum(heurdata->subscip, &subvar, &tscalar, &tconstant) );
826
827 transval = 0.0;
828
829 if( REALABS(tscalar) > 0.0 )
830 {
831 assert(subvar != NULL);
832 transval = SCIPgetSolVal(heurdata->subscip, subsol, subvar);
833 }
834
835 /* recompute aggregations */
836 transval = tscalar * transval + tconstant;
837 }
838 val = scalar * transval + constant;
839 }
840 else
841 {
842 /* recompute aggregations */
843 val = scalar * val + constant;
844 }
845
846 assert( val != SCIP_INVALID ); /*lint !e777*/
847 SCIP_CALL( SCIPsetSolVal(scip, *sol, vars[i], val) );
848 }
849
850 return SCIP_OKAY;
851}
852
853
854
855/** creates copy of CIP from problem in SCIP */
856static
858 SCIP* scip, /**< SCIP data structure */
859 SCIP_HEURDATA* heurdata /**< heuristic data structure */
860 )
861{
862 SCIP_HASHMAP* varsmap;
863 SCIP_HASHMAP* conssmap;
864 SCIP_CONSHDLR* conshdlrindicator;
865 SCIP_CONSHDLR* conshdlrindi;
866 SCIP_CONSHDLR* conshdlrlin;
867 SCIP_CONSHDLR* conshdlrnonlin;
868 SCIP_CONSHDLR* conshdlrvarbound;
869 SCIP_CONSHDLR* conshdlrknapsack;
870 SCIP_CONSHDLR* conshdlrlogicor;
871 SCIP_CONSHDLR* conshdlrsetppc;
872 SCIP_CONSHDLR* currentconshdlr;
873 SCIP_CONS** conss;
874 SCIP_CONS* subcons;
875 SCIP_CONS* transcons;
876 SCIP_CONS* linindicons;
877 SCIP_CONS* indicons;
878 SCIP_CONS* cons = NULL;
879 SCIP_VAR** vars;
880 SCIP_VAR** subvars;
881 SCIP_VAR* var;
882 SCIP_VAR* tmpvar;
883 SCIP_VAR* subvar;
884 SCIP_VAR* slackvarpos;
885 SCIP_VAR* slackvarneg;
886 SCIP_VAR* indislackvarpos;
887 SCIP_VAR* indislackvarneg;
888 SCIP_VAR* indicatorcopy;
889 char probname[SCIP_MAXSTRLEN];
890 char varname[SCIP_MAXSTRLEN];
891 char consname[SCIP_MAXSTRLEN];
892 SCIP_Real varobjective;
893 int nconss;
894 int nconsindicator;
895 int i;
896 int j;
897 int k;
898 int nvars;
899 int ncontvars;
900 SCIP_Bool feasible;
901 SCIP_Bool success;
902
903 assert( heurdata != NULL );
904 assert( heurdata->subscip == NULL );
905
906 heurdata->usedcalls = 0;
907 heurdata->solfound = FALSE;
908 heurdata->nonimprovingRounds = 0;
909
910 /* we can't change the vartype in some constraints, so we have to check that only the right constraints are present */
911 conshdlrindi = SCIPfindConshdlr(scip, "indicator");
912 conshdlrlin = SCIPfindConshdlr(scip, "linear");
913 conshdlrnonlin = SCIPfindConshdlr(scip, "nonlinear");
914 conshdlrvarbound = SCIPfindConshdlr(scip, "varbound");
915 conshdlrknapsack = SCIPfindConshdlr(scip, "knapsack");
916 conshdlrlogicor = SCIPfindConshdlr(scip, "logicor");
917 conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
918
919 nconss = SCIPgetNOrigConss(scip);
920 conss = SCIPgetOrigConss(scip);
921
922 /* for each constraint ask if it has an allowed type */
923 for( i = 0; i < nconss; i++ )
924 {
925 cons = conss[i];
926 currentconshdlr = SCIPconsGetHdlr(cons);
927
928 if( currentconshdlr == conshdlrindi ||
929 currentconshdlr == conshdlrnonlin ||
930 currentconshdlr == conshdlrvarbound ||
931 currentconshdlr == conshdlrknapsack ||
932 currentconshdlr == conshdlrlogicor ||
933 currentconshdlr == conshdlrsetppc ||
934 currentconshdlr == conshdlrlin )
935 {
936 continue;
937 }
938 else
939 {
940 return SCIP_OKAY;
941 }
942 }
943
944 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, &ncontvars) );
945
946 if( heurdata->dynamicdepth == 1 )
947 {
948 heurdata->maxcalls = (int)SCIPfloor(scip, sqrt((double)(nvars - ncontvars)));
949 }
950
951 heurdata->triedsetupsubscip = TRUE;
952
953 /* initializing the subproblem */
954 SCIP_CALL( SCIPcreate(&heurdata->subscip) );
955
956 /* create variable hash mapping scip -> subscip */
957 SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
958
959 SCIP_CALL( SCIPhashmapCreate(&heurdata->switchedvars, SCIPblkmem(scip), heurdata->maxcalls) );
960 SCIP_CALL( SCIPhashmapCreate(&heurdata->switchedvars2, SCIPblkmem(scip), heurdata->maxcalls) );
961
962 /* create sub-SCIP copy of CIP, copy interesting plugins */
963 success = TRUE;
964 SCIP_CALL( SCIPcopyPlugins(scip, heurdata->subscip, TRUE, FALSE, TRUE, FALSE, TRUE,
965 FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, &success) );
966
967 if( success == FALSE )
968 {
969 SCIPdebugMsg(scip, "In heur_dualval: failed to copy some plugins to sub-SCIP, continue anyway\n");
970 }
971
972 /* copy parameter settings */
973 SCIP_CALL( SCIPcopyParamSettings(scip, heurdata->subscip) );
974
975 /* even when solving exactly, sub-SCIP heuristics should be run in floating-point mode, since the exactsol constraint
976 * handler is in place to perform a final repair step
977 */
978 SCIP_CALL( SCIPenableExactSolving(heurdata->subscip, FALSE) );
979
980 /* disable bound limits */
981 SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/primal", SCIP_INVALID) );
982 SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/dual", SCIP_INVALID) );
983
984 /* create problem in sub-SCIP */
985
986 /* get name of the original problem and add "dualval" */
987 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_dualval", SCIPgetProbName(scip));
988 SCIP_CALL( SCIPcreateProb(heurdata->subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
989
990 SCIP_CALL( SCIPincludeEventHdlrLPsol(heurdata->subscip, heurdata) );
991
992 /* copy all variables */
993 SCIP_CALL( SCIPcopyVars(scip, heurdata->subscip, varsmap, NULL, NULL, NULL, 0, TRUE) );
994
995 /* copy as many constraints as possible */
997 SCIP_CALL( SCIPcopyConss(scip, heurdata->subscip, varsmap, conssmap, TRUE, FALSE, &heurdata->subscipisvalid) );
998
999 SCIP_CALL( SCIPhashmapCreate(&heurdata->origsubscipConsMap, SCIPblkmem(scip), SCIPgetNConss(scip)) );
1000
1001 nconss = SCIPgetNOrigConss(scip);
1002 conss = SCIPgetOrigConss(scip);
1003
1004 /* fill constraint mapping from original scip to the subscip */
1005 for( i = 0; i < nconss; ++i )
1006 {
1007 transcons = NULL;
1008 SCIP_CALL( SCIPgetTransformedCons(scip, conss[i], &transcons) );
1009
1010 subcons = (SCIP_CONS*)SCIPhashmapGetImage(conssmap, transcons);
1011 assert( subcons != NULL );
1012
1013 SCIP_CALL( SCIPcaptureCons(heurdata->subscip, subcons) );
1014 SCIP_CALL( SCIPhashmapInsert(heurdata->origsubscipConsMap, transcons, subcons) );
1015 }
1016
1017 SCIP_CALL( SCIPhashmapCreate(&heurdata->conss2nlrow, SCIPblkmem(scip), SCIPgetNConss(scip)) );
1018
1019 if( !heurdata->subscipisvalid )
1020 {
1021 SCIPdebugMsg(scip, "In heur_dualval: failed to copy some constraints to sub-SCIP, continue anyway\n");
1022 }
1023
1024 SCIP_CALL( SCIPgetVarsData(heurdata->subscip, &subvars, &heurdata->nsubvars, NULL, NULL, NULL, NULL) );
1025 heurdata->nvars = nvars;
1026
1027 /* create hashmaps from scip transformed vars to subscip original vars, and vice versa
1028 * capture variables in SCIP and sub-SCIP
1029 * catch global bound change events */
1030 SCIP_CALL( SCIPhashmapCreate(&heurdata->varsubsciptoscip, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
1031 SCIP_CALL( SCIPhashmapCreate(&heurdata->varsciptosubscip, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
1032
1033 /* we need to get all subscip variables, also those which are copies of fixed variables from the main scip,
1034 * therefore we iterate over the hashmap */
1035 for( i = 0; i < SCIPhashmapGetNEntries(varsmap); ++i )
1036 {
1037 SCIP_HASHMAPENTRY* entry;
1038 entry = SCIPhashmapGetEntry(varsmap, i);
1039 if( entry != NULL )
1040 {
1041 var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
1042 subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
1043
1044 assert( SCIPvarGetProbindex(subvar) >= 0 );
1045 assert( SCIPvarGetProbindex(subvar) <= heurdata->nsubvars );
1046
1047 if( SCIPvarIsActive(var) )
1048 {
1049 assert( SCIPvarGetProbindex(var) <= heurdata->nvars );
1050 /* assert that we have no mapping for this var yet */
1051 assert( SCIPhashmapGetImage(heurdata->varsciptosubscip,var) == NULL );
1052 SCIP_CALL( SCIPhashmapInsert(heurdata->varsciptosubscip, var, subvar) );
1053 }
1054
1055 assert( SCIPhashmapGetImage(heurdata->varsubsciptoscip, subvar) == NULL );
1056 SCIP_CALL( SCIPhashmapInsert(heurdata->varsubsciptoscip, subvar, var) );
1057
1058 SCIP_CALL( SCIPcaptureVar(scip, var) );
1059 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, subvar) );
1060
1061 assert( SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetLbGlobal(subvar)) );
1062 assert( SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), SCIPvarGetUbGlobal(subvar)) );
1063 }
1064 }
1065
1066 /* we map all slack variables of indicator constraints to their indicator variables */
1067 conshdlrindicator = SCIPfindConshdlr(scip, "indicator");
1068 nconsindicator = SCIPconshdlrGetNConss(conshdlrindicator);
1069
1070 SCIP_CALL( SCIPhashmapCreate(&heurdata->slacktoindivarsmap, SCIPblkmem(scip), nconsindicator) );
1071 SCIP_CALL( SCIPhashmapCreate(&heurdata->indicators, SCIPblkmem(scip), nconsindicator) );
1072 SCIP_CALL( SCIPhashmapCreate(&heurdata->indicopymap, SCIPblkmem(scip), nconsindicator) );
1073 SCIP_CALL( SCIPhashmapCreate(&heurdata->indicopymapback, SCIPblkmem(scip), nconsindicator) );
1074 SCIP_CALL( SCIPhashmapCreate(&heurdata->slackvarlbMap, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
1075 SCIP_CALL( SCIPhashmapCreate(&heurdata->slackvarubMap, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
1076
1077 for( i = 0; i < nconsindicator; i++ )
1078 {
1079 SCIP_CONS** indicatorconss = SCIPconshdlrGetConss(conshdlrindicator);
1080 SCIP_CONS* currcons;
1081
1082 currcons = indicatorconss[i];
1083 assert(currcons != NULL);
1084
1085 SCIP_CALL( SCIPhashmapInsert(heurdata->slacktoindivarsmap, SCIPgetSlackVarIndicator(currcons),
1086 SCIPgetBinaryVarIndicator(currcons)) );
1087 SCIP_CALL( SCIPhashmapInsert(heurdata->indicators, SCIPgetBinaryVarIndicator(currcons), currcons) );
1088 SCIP_CALL( SCIPcaptureCons(scip, currcons) );
1090 }
1091
1092 /* we introduce slackvariables s+ and s- for each constraint to ensure that the problem is feasible
1093 * we want to minimize over the sum of these variables, so set the objective to 1 */
1094 SCIP_CALL( SCIPhashmapCreate(&heurdata->relaxcons, SCIPblkmem(scip), nvars) );
1095 SCIP_CALL( SCIPhashmapCreate(&heurdata->relaxconsindi, SCIPblkmem(scip), nvars) );
1096 SCIP_CALL( SCIPhashmapCreate(&heurdata->slack2var, SCIPblkmem(scip), nvars) );
1097
1098 vars = SCIPgetOrigVars(scip);
1099 nvars = SCIPgetNOrigVars(scip);
1100
1101 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->integervars), nvars) );
1102 BMSclearMemoryArray(heurdata->integervars, nvars);
1103 heurdata->integervarssize = nvars;
1104 j = 0;
1105
1106 /* here we relax the variables (or indicator constraints, since indicator variables cannot be relaxed) */
1107 for( i = 0; i < nvars; ++i )
1108 {
1109 var = SCIPvarGetTransVar(vars[i]);
1110 assert( var != NULL );
1111
1112 if( ! SCIPvarIsActive(var) )
1113 continue;
1114
1115 if( ! SCIPvarIsIntegral(var) )
1116 continue;
1117
1118 heurdata->integervars[j++] = vars[i];
1119
1120 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
1121 if( var == NULL )
1122 continue;
1123
1124 /* in this case our variable is an indicator variable */
1125 if( SCIPhashmapGetImage(heurdata->indicators, SCIPhashmapGetImage(heurdata->varsubsciptoscip, var)) != NULL )
1126 {
1127 /* we have to find all the indicator constraints of this variable */
1128 for( k = 0; k < nconsindicator; k++ )
1129 {
1130 SCIP_CONS** indicatorconss = SCIPconshdlrGetConss(conshdlrindicator);
1131 SCIP_CONS* currcons;
1132 SCIP_VAR* negatedvar;
1133 SCIP_VAR* indicatorbinvar;
1134
1135 currcons = indicatorconss[k];
1136 assert(currcons != NULL);
1137
1138 indicatorbinvar = SCIPgetBinaryVarIndicator(currcons);
1139 assert(indicatorbinvar != NULL);
1140
1141 SCIP_CALL( SCIPgetNegatedVar(scip, (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsubsciptoscip, var), &negatedvar) );
1142
1143 if( indicatorbinvar == SCIPhashmapGetImage(heurdata->varsubsciptoscip, var) || indicatorbinvar == negatedvar )
1144 {
1145 /* case that we have a negated variable */
1146 if( SCIPvarIsNegated(indicatorbinvar) )
1147 {
1148 assert(indicatorbinvar == negatedvar);
1149 varobjective = SCIPvarGetObj(negatedvar);
1150 }
1151 else
1152 {
1153 assert(indicatorbinvar != negatedvar);
1154 varobjective = SCIPvarGetObj(indicatorbinvar);
1155 }
1156
1157 varobjective = heurdata->lambdaobj * REALABS(varobjective);
1158
1159 indicons = currcons;
1160 assert( indicons != NULL );
1161
1162 indicons = (SCIP_CONS*)SCIPhashmapGetImage(conssmap, indicons);
1163
1164 assert( indicons != NULL );
1165 linindicons = SCIPgetLinearConsIndicator(indicons);
1166
1167 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_pos3", SCIPconsGetName(linindicons));
1168 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &slackvarpos, varname, 0.0, SCIPinfinity(heurdata->subscip),
1169 heurdata->lambdaslack *100 + varobjective, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1170 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarpos) );
1171
1172 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_neg3", SCIPconsGetName(linindicons));
1173 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &slackvarneg, varname, 0.0, SCIPinfinity(heurdata->subscip),
1174 heurdata->lambdaslack * 100 + varobjective, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1175 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarneg) );
1176
1177 /* make a copy of the indicator to relax it if this parameter is set true */
1178 if( heurdata->relaxindicators )
1179 {
1180 SCIP_CONS* imagecons;
1181
1182 indicatorbinvar = SCIPgetBinaryVarIndicator(indicons);
1183
1184 SCIP_CALL( SCIPgetNegatedVar(heurdata->subscip, indicatorbinvar, &negatedvar) );
1185
1186 if( SCIPhashmapGetImage(heurdata->indicopymap, indicatorbinvar) == NULL &&
1187 SCIPhashmapGetImage(heurdata->indicopymap, negatedvar) == NULL)
1188 {
1189 SCIP_Bool negated = FALSE;
1190
1191 if (SCIPvarIsNegated(indicatorbinvar))
1192 {
1193 indicatorbinvar = negatedvar;
1194 negated = TRUE;
1195 }
1196
1197 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "indicopy_%s", SCIPvarGetName(indicatorbinvar));
1198 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &indicatorcopy, varname, SCIPvarGetLbGlobal(indicatorbinvar), SCIPvarGetUbGlobal(indicatorbinvar),
1199 SCIPvarGetObj(indicatorbinvar), SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1200
1201 SCIP_CALL( SCIPaddVar(heurdata->subscip, indicatorcopy) );
1202
1203 SCIP_CALL( SCIPhashmapInsert(heurdata->indicopymap, indicatorbinvar, indicatorcopy) );
1204 SCIP_CALL( SCIPhashmapInsert(heurdata->indicopymapback, indicatorcopy, indicatorbinvar) );
1205 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, indicatorbinvar) );
1206
1207 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_pos1", SCIPvarGetName(indicatorbinvar));
1208 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &indislackvarpos, varname, 0.0, SCIPinfinity(heurdata->subscip),
1209 heurdata->lambdaslack * 100 + varobjective, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1210 SCIP_CALL( SCIPaddVar(heurdata->subscip, indislackvarpos) );
1211
1212 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_neg1", SCIPvarGetName(indicatorbinvar));
1213 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &indislackvarneg, varname, 0.0, SCIPinfinity(heurdata->subscip),
1214 heurdata->lambdaslack * 100 + varobjective, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
1215 SCIP_CALL( SCIPaddVar(heurdata->subscip, indislackvarneg) );
1216
1217 /* create linking constraint */
1218 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "linking_%s", SCIPvarGetName(indicatorbinvar));
1219 cons = NULL;
1220 SCIP_CALL( SCIPcreateConsLinear( heurdata->subscip, &cons, consname, 0, NULL, NULL, 0.0, 0.0,
1222 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, indicatorbinvar, 1.0) );
1223 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, indicatorcopy, -1.0) );
1224 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, indislackvarpos, 1.0) );
1225 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, indislackvarneg, -1.0) );
1226
1227 SCIP_CALL( SCIPhashmapInsert(heurdata->relaxconsindi, indicatorbinvar, cons) );
1228 SCIP_CALL( SCIPhashmapInsert(heurdata->relaxconsindi, indicatorcopy, cons) );
1229
1230 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1231 SCIP_CALL( SCIPcaptureCons(heurdata->subscip, cons) );
1232
1233 assert( SCIPhashmapGetImage(heurdata->indicopymap, indicatorbinvar) != NULL );
1234
1235 if ( negated )
1236 {
1237 SCIP_CALL( SCIPgetNegatedVar(heurdata->subscip, indicatorcopy, &indicatorcopy) );
1238 }
1239
1240 SCIP_CALL( SCIPchgVarType(heurdata->subscip, indicatorbinvar, SCIP_VARTYPE_CONTINUOUS, &feasible) );
1241
1242 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, indislackvarpos, var) );
1243 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, indislackvarneg, var) );
1244 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1245 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1246 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &indislackvarpos) );
1247 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &indislackvarneg) );
1248 }
1249 else
1250 {
1251 if (!SCIPvarIsNegated(indicatorbinvar))
1252 indicatorcopy = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->indicopymap, indicatorbinvar);
1253 else
1254 {
1255 indicatorcopy = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->indicopymap, negatedvar);
1256 SCIP_CALL( SCIPgetNegatedVar(heurdata->subscip, indicatorcopy, &indicatorcopy) );
1257 }
1258 }
1259
1260 cons = NULL;
1261 SCIP_CALL( SCIPcreateConsIndicatorLinCons(heurdata->subscip, &cons, SCIPconsGetName(indicons), indicatorcopy,
1263 SCIPconsIsSeparated(indicons), SCIPconsIsEnforced(indicons), SCIPconsIsChecked(indicons),
1264 SCIPconsIsPropagated(indicons), SCIPconsIsLocal(indicons), SCIPconsIsDynamic(indicons),
1265 SCIPconsIsRemovable(indicons), SCIPconsIsStickingAtNode(indicons)) );
1266 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1267
1268 /* delete old indicator constraints so we can relax the indicator variables */
1269 imagecons = (SCIP_CONS*) SCIPhashmapGetImage(heurdata->origsubscipConsMap, (void*)(currcons));
1270 assert(imagecons != NULL);
1271 SCIP_CALL( SCIPreleaseCons(heurdata->subscip, &imagecons) );
1272 SCIP_CALL( SCIPhashmapRemove(heurdata->origsubscipConsMap, currcons) );
1273 SCIP_CALL( SCIPhashmapInsert(heurdata->origsubscipConsMap, currcons, cons) );
1275 SCIP_CALL( SCIPdelCons(heurdata->subscip, indicons) );
1276 }
1277
1278 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarpos, var) );
1279 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarneg, var) );
1280 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1281 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1282
1283 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, linindicons, slackvarpos, 1.0) );
1284 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, linindicons, slackvarneg, -1.0) );
1285 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &slackvarpos) );
1286 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &slackvarneg) );
1287 }
1288 }
1289 continue;
1290 }
1291
1292 if( heurdata->relaxindicators )
1293 {
1294 /* relax the old indicator variables*/
1295 for( k = 0; k < nvars; k++ )
1296 {
1297 if( SCIPhashmapGetImage(heurdata->indicators, vars[k]) == NULL )
1298 continue;
1299
1300 tmpvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, vars[k]);
1301 SCIP_CALL( SCIPchgVarType(heurdata->subscip, tmpvar, SCIP_VARTYPE_CONTINUOUS, &feasible) );
1302 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, tmpvar, -SCIPinfinity(heurdata->subscip)) );
1303 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, tmpvar, SCIPinfinity(heurdata->subscip)) );
1304 }
1305
1306 /* we map all slack variables of indicator constraints to their indicator variables */
1307 conshdlrindicator = SCIPfindConshdlr(scip, "indicator");
1308 nconsindicator = SCIPconshdlrGetNConss(conshdlrindicator);
1309
1310 /* delete old hashmaps and fill with the new indicators*/
1311 SCIP_CALL( releaseHashmapEntries(scip, heurdata->slacktoindivarsmap, TRUE) );
1312 SCIP_CALL( releaseHashmapEntries(scip, heurdata->indicators, FALSE) );
1313 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->slacktoindivarsmap) );
1314 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->indicators) );
1315
1316 /* fill hashmaps with new values */
1317 for( k = 0; k < nconsindicator; k++ )
1318 {
1319 SCIP_CONS** indicatorconss = SCIPconshdlrGetConss(conshdlrindicator);
1320 SCIP_CONS* currcons;
1321
1322 currcons = indicatorconss[k];
1323 assert(currcons != NULL);
1324
1326 SCIP_CALL( SCIPcaptureCons(scip, currcons) );
1327
1328 SCIP_CALL( SCIPhashmapInsert(heurdata->slacktoindivarsmap, SCIPgetSlackVarIndicator(currcons),
1329 SCIPgetBinaryVarIndicator(currcons)) );
1330 SCIP_CALL( SCIPhashmapInsert(heurdata->indicators, SCIPgetBinaryVarIndicator(currcons), currcons) );
1331 }
1332 }
1333
1334 /* in this case, we have a normal variable */
1335 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "relax_%s", SCIPvarGetName(var));
1336 cons = NULL;
1337 SCIP_CALL( SCIPcreateConsLinear( heurdata->subscip, &cons, consname, 0, NULL, NULL, 0.0, 0.0,
1339
1340 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_pos0", SCIPvarGetName(var));
1341 SCIP_CALL( SCIPcreateVar( heurdata->subscip, &slackvarpos, varname, 0.0, SCIPinfinity(heurdata->subscip),
1342 heurdata->lambdaslack * 100, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL,NULL) );
1343 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarpos) );
1344
1345 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_neg0", SCIPvarGetName(var));
1346 SCIP_CALL( SCIPcreateVar(heurdata->subscip, &slackvarneg, varname, 0.0, SCIPinfinity(heurdata->subscip),
1347 heurdata->lambdaslack * 100, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL,NULL) );
1348 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarneg) );
1349
1350 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, var, 1.0) );
1351 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, slackvarpos, 1.0) );
1352 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, slackvarneg, -1.0) );
1353
1354 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1355
1356 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarpos, var) );
1357 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarneg, var) );
1358 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1359 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1360 SCIP_CALL( SCIPhashmapInsert(heurdata->relaxcons, var, cons) );
1361 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &slackvarpos) );
1362 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &slackvarneg) );
1363
1364 /* if the var is no indicator, relax it to a continuous variable */
1365 if( SCIPhashmapGetImage(heurdata->indicators, SCIPhashmapGetImage(heurdata->varsubsciptoscip, var)) == NULL )
1366 {
1367 SCIP_CALL( SCIPchgVarType(heurdata->subscip, var, SCIP_VARTYPE_CONTINUOUS, &feasible) );
1368 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, var, -SCIPinfinity(heurdata->subscip)) );
1369 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, var, SCIPinfinity(heurdata->subscip)) );
1370 }
1371 }
1372
1373 /* set up relaxation constraints for continuous variables */
1374 if( heurdata->relaxcontvars )
1375 {
1376 for( i = 0; i < nvars; ++i )
1377 {
1378 var = SCIPvarGetTransVar(vars[i]);
1379 assert( var != NULL );
1380
1381 if( ! SCIPvarIsActive(var) )
1382 continue;
1383
1384 if( SCIPvarIsIntegral(var) )
1385 continue;
1386
1388 continue;
1389
1391 continue;
1392
1393 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
1394 if( var == NULL )
1395 continue;
1396
1397 /* in this case, we have a normal variable */
1398 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "relax_ub_%s", SCIPvarGetName(var));
1399 cons = NULL;
1400 SCIP_CALL( SCIPcreateConsLinear( heurdata->subscip, &cons, consname, 0, NULL, NULL, -SCIPinfinity(heurdata->subscip), SCIPvarGetUbGlobal(var),
1402
1403 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_pos2", SCIPvarGetName(var));
1404 SCIP_CALL( SCIPcreateVar( heurdata->subscip, &slackvarpos, varname, 0.0, SCIPinfinity(heurdata->subscip),
1405 heurdata->lambdaslack, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL,NULL) );
1406 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarpos) );
1407
1408 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, var, 1.0) );
1409 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, slackvarpos, -1.0) );
1410
1411 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1412 SCIP_CALL( SCIPreleaseCons(heurdata->subscip, &cons) );
1413 SCIP_CALL( SCIPhashmapInsert(heurdata->slackvarubMap, var, slackvarpos) );
1414 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarpos, var) );
1415 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1416
1417 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "relax_lb_%s", SCIPvarGetName(var));
1418 cons = NULL;
1419 SCIP_CALL( SCIPcreateConsLinear( heurdata->subscip, &cons, consname, 0, NULL, NULL, SCIPvarGetLbGlobal(var), SCIPinfinity(heurdata->subscip),
1421
1422 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "relax_%s_neg2", SCIPvarGetName(var));
1423 SCIP_CALL( SCIPcreateVar( heurdata->subscip, &slackvarneg, varname, 0.0, SCIPinfinity(heurdata->subscip),
1424 heurdata->lambdaslack, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL,NULL) );
1425 SCIP_CALL( SCIPaddVar(heurdata->subscip, slackvarneg) );
1426
1427 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, var, 1.0) );
1428 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, slackvarneg, 1.0) );
1429
1430 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1431 SCIP_CALL( SCIPreleaseCons(heurdata->subscip, &cons) );
1432 SCIP_CALL( SCIPhashmapInsert(heurdata->slackvarlbMap, var, slackvarneg) );
1433 SCIP_CALL( SCIPhashmapInsert(heurdata->slack2var, slackvarneg, var) );
1434 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, var) );
1435
1436 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, var, -SCIPinfinity(heurdata->subscip)) );
1437 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, var, SCIPinfinity(heurdata->subscip)) );
1438 }
1439 }
1440
1441 /* if we have a solution add constraint that the next solution must not be worse than the current one */
1442 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "objbound");
1443 SCIP_CALL( SCIPcreateConsLinear( heurdata->subscip, &cons, consname, 0, NULL, NULL, -SCIPinfinity(scip),
1445 heurdata->objbound = cons;
1446
1447 for( i = 0; i < nvars; ++i )
1448 {
1449 var = SCIPvarGetTransVar(vars[i]);
1450 assert( var != NULL );
1451
1452 if( !SCIPvarIsActive(var) )
1453 continue;
1454
1455 subvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
1456 if( subvar == NULL )
1457 continue;
1458
1459 SCIP_CALL( SCIPaddCoefLinear(heurdata->subscip, cons, subvar, SCIPvarGetObj(var)) );
1460
1461 SCIP_CALL( SCIPchgVarObj(heurdata->subscip, subvar, heurdata->lambdaobj * SCIPvarGetObj(subvar) ) );
1462 }
1463
1464 SCIP_CALL( SCIPaddCons(heurdata->subscip, cons) );
1465 SCIP_CALL( SCIPreleaseCons(heurdata->subscip, &cons) );
1466
1467 /* do not need varsmap and conssmap anymore */
1468 SCIPhashmapFree(&conssmap);
1469 SCIPhashmapFree(&varsmap);
1470
1471 /* enable SCIP output if needed */
1472 if( heurdata->heurverblevel > 3 )
1473 {
1474 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 4) );
1475 }
1476 else
1477 {
1478 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 0) );
1479 }
1480
1481 heurdata->nintegervars = j;
1482
1483 return SCIP_OKAY;
1484}
1485
1486
1487/** free sub-SCIP data structure */
1488static
1490 SCIP* scip, /**< SCIP data structure */
1491 SCIP_HEURDATA* heurdata /**< heuristic data structure */
1492 )
1493{
1494 assert(scip != NULL);
1495 assert(heurdata != NULL);
1496 assert(heurdata->subscip != NULL);
1497
1498 heurdata->nsubvars = 0;
1499 heurdata->nvars = 0;
1500
1501 /* free sub-SCIP */
1502 SCIP_CALL( SCIPfree(&heurdata->subscip) );
1503
1504 return SCIP_OKAY;
1505}
1506
1507
1508/** create a solution from the values of current nonlinear program */
1509static
1511 SCIP* scip, /**< SCIP data structure */
1512 SCIP_HEUR* heur, /**< heuristic data structure */
1513 SCIP_SOL** sol /**< buffer to store solution value; if pointing to NULL a new solution is
1514 * created, otherwise values in the given one are overwritten */
1515 )
1516{
1517 SCIP_HEURDATA* heurdata;
1518 SCIP_VAR** subvars;
1519 SCIP_VAR* subvar;
1520 int i;
1521 int nsubvars;
1522
1523 assert(scip != NULL);
1524 assert(heur != NULL);
1525 assert(sol != NULL);
1526
1527 heurdata = SCIPheurGetData(heur);
1528 assert(heurdata != NULL);
1529
1530 if( *sol == NULL )
1531 {
1532 SCIP_CALL( SCIPcreateSol(scip, sol, heur) );
1533 }
1534
1535 /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
1536 * since constraint copying may have required the copy of variables that are fixed in the main SCIP */
1537 assert(heurdata->nsubvars <= SCIPgetNOrigVars(heurdata->subscip));
1538
1539 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, NULL, NULL, NULL, NULL) );
1540
1541 /* set solution values */
1542 for( i = 0; i < nsubvars; ++i )
1543 {
1544 subvar = subvars[i];
1545 assert(subvar != NULL);
1546
1547 subvar = SCIPvarGetTransVar(subvar);
1548
1549 if( !SCIPvarIsActive(subvar) )
1550 continue;
1551
1552 assert(SCIPvarGetNLPSol(subvar) != SCIP_INVALID);/*lint !e777*/
1553 SCIP_CALL( SCIPsetSolVal(scip, *sol, subvar, SCIPvarGetNLPSol(subvar)) );
1554 }
1555
1556 return SCIP_OKAY;
1557}
1558
1559#define BIG_VALUE 1E+10
1560
1561/** method to fix the (relaxed) discrete variables */
1562static
1564 SCIP* scip, /**< SCIP data structure */
1565 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1566 SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from;
1567 * if NULL, then LP solution is used */
1568 SCIP_SOL** transsol /**< pointer to new created solution with fixed values as solution value */
1569 )
1570{
1571 SCIP_Real fixval;
1572 SCIP_VAR* var;
1573 SCIP_VAR* subvar;
1574 SCIP_CONS* rcons;
1575 int i;
1576
1577 SCIP_CALL( SCIPcreateOrigSol(scip, transsol, NULL) );
1578
1579 /* fix discrete variables */
1580 for( i = 0; i < heurdata->nintegervars; i++ )
1581 {
1582 var = heurdata->integervars[i];
1583 assert(var != NULL);
1584
1585 var = SCIPvarGetTransVar(var);
1586 assert(var != NULL);
1587 subvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
1588
1589 if( subvar == NULL )
1590 continue;
1591
1592 if ( SCIPhashmapGetImage(heurdata->indicopymap, subvar) != NULL )
1593 subvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->indicopymap, subvar);
1594
1595 /* if we do not really have a startpoint, we set to 0.0 here and project on bounds below */
1596 if( refpoint == NULL && SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1597 fixval = 0.0;
1598 else
1599 {
1600 /* get value of the variables (NULL as refpoint gives the current LP solution, otherwise the start point) */
1601 fixval = SCIPgetSolVal(scip, refpoint, heurdata->integervars[i]);
1602
1603 /* take care that we do not fix variables to very large values (project on bounds below) */
1604 if( REALABS(fixval) > BIG_VALUE )
1605 fixval = 0.0;
1606 else
1607 {
1608 /* round fractional variables to the nearest integer, use exact integral value, if the variable is only
1609 * integral within numerical tolerances */
1610 fixval = SCIPfloor(scip, fixval + 0.5);
1611 }
1612 }
1613
1614 /* adjust value to the global bounds of the corresponding SCIP variable */
1615 fixval = MAX(fixval, SCIPvarGetLbGlobal(heurdata->integervars[i])); /*lint !e666*/
1616 fixval = MIN(fixval, SCIPvarGetUbGlobal(heurdata->integervars[i])); /*lint !e666*/
1617
1618 SCIP_CALL( SCIPsetSolVal(scip, *transsol, heurdata->integervars[i], fixval) );
1619
1620 /* adjust the relaxation constraints to the new fixval */
1621 rcons = (SCIP_CONS*) SCIPhashmapGetImage(heurdata->relaxcons, subvar);
1622
1623 fixval = MAX(fixval, SCIPvarGetLbGlobal(subvar));/*lint !e666*/
1624 fixval = MIN(fixval, SCIPvarGetUbGlobal(subvar));/*lint !e666*/
1625 if( rcons == NULL )
1626 {
1627 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, fixval) );
1628 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, fixval) );
1629 continue;
1630 }
1631
1632 SCIP_CALL( SCIPchgLhsLinear(heurdata->subscip, rcons, fixval) );
1633 SCIP_CALL( SCIPchgRhsLinear(heurdata->subscip, rcons, fixval) );
1634 }
1635
1636 return SCIP_OKAY;
1637}
1638
1639/** method to free memory before leaving the heuristic or jumping up in the recursion */
1640static
1642 SCIP* scip, /**< scip data structure */
1643 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1644 SCIP_SOL* transsol, /**< sol that has to be freed */
1645 SCIP_Real* absranks, /**< array of absolute rank values */
1646 SCIP_Real* ranks, /**< array of rank values */
1647 SCIP_VAR** sortedvars, /**< array of corresponding variables */
1648 SCIP_Bool beforeswitching, /**< did we call this method before or after switching variables? */
1649 SCIP_Bool clearswitchedvars /**< says if we should clear switchedvars or not */
1650 )
1651{
1652 SCIP_VAR** subvars;
1653 SCIP_VAR* subvar;
1654 SCIP_VAR* var;
1655 SCIP_Real* val;
1656 int nsubvars;
1657 int nsubbinvars;
1658 int nsubintvars;
1659 int i;
1660
1661 if( clearswitchedvars )
1662 {
1663 /* free memory of the solution values in the hashmaps */
1664 for( i = 0; i < heurdata->nintegervars; i++ )
1665 {
1666 var = heurdata->integervars[i];
1667
1668 if( SCIPhashmapGetImage(heurdata->slacktoindivarsmap, var) != NULL )
1669 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->slacktoindivarsmap, var);
1670
1671 val = (SCIP_Real*)SCIPhashmapGetImage(heurdata->switchedvars, var);
1672 if( val != NULL )
1673 {
1674 SCIPfreeBlockMemoryArray(heurdata->subscip, &val, 1);
1675 }
1676
1677 val = (SCIP_Real*)SCIPhashmapGetImage(heurdata->switchedvars2, var);
1678 if( val != NULL )
1679 {
1680 SCIPfreeBlockMemoryArray(heurdata->subscip, &val, 1);
1681 }
1682 }
1683
1684 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->switchedvars) );
1685 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->switchedvars2) );
1686 }
1687
1688 SCIPfreeBufferArrayNull( scip, &ranks );
1689 SCIPfreeBufferArrayNull( scip, &absranks );
1690 SCIPfreeBufferArrayNull( scip, &sortedvars );
1691
1692 if( transsol != NULL )
1693 {
1694 SCIP_CALL( SCIPfreeSol(scip, &transsol) );
1695 }
1696
1697 if( beforeswitching )
1698 {
1699 SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1700 }
1701
1702 /* undo fixing of discrete variables in sub-SCIP */
1703 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1704
1705 /* set bounds of discrete variables to original values */
1706 for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1707 {
1708 subvar = subvars[i];
1709 assert(SCIPvarGetProbindex(subvar) == i);
1710
1711 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsubsciptoscip, subvar);
1712
1713 if (SCIPhashmapGetImage(heurdata->indicopymapback, subvar) != NULL)
1714 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsubsciptoscip, SCIPhashmapGetImage(heurdata->indicopymapback, subvar));
1715
1716 assert(var != NULL);
1717
1718 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
1719 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
1720 }
1721
1722 return SCIP_OKAY;
1723}
1724
1725/** computes the ranks, saves them into an array and sorts the variables according to absolute ranks */
1726static
1728 SCIP* scip, /**< scip data structure */
1729 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1730 SCIP_Real* absranks, /**< array of absolute rank values */
1731 SCIP_Real* ranks, /**< array of rank values */
1732 SCIP_VAR** sortedvars /**< array of corresponding variables */
1733 )
1734{
1735 SCIP_CONSHDLR* conshdlrindicator;
1736 SCIP_CONS* relaxcons;
1737 SCIP_CONS* indicons;
1738 SCIP_CONS* subcons;
1739 SCIP_CONS* transcons;
1740 SCIP_VAR* var;
1741 SCIP_Real* dualvalue;
1742 int nconsindicator;
1743 int j;
1744 int k;
1745
1746 conshdlrindicator = SCIPfindConshdlr(scip, "indicator");
1747 nconsindicator = SCIPconshdlrGetNConss(conshdlrindicator);
1748
1749 /* Now we compute the rank of each variable */
1750 for( j = 0; j < heurdata->nintegervars; j++ )
1751 {
1752 sortedvars[j] = heurdata->integervars[j];
1753 ranks[j] = 0;
1754 absranks[j] = 0;
1755
1756 if( sortedvars[j] == NULL )
1757 break;
1758
1759 var = SCIPvarGetTransVar(sortedvars[j]);
1760 assert(var != NULL);
1761
1762 /* globally fixed variables get rank 0 */
1764 {
1765 ranks[j] = 0;
1766 continue;
1767 }
1768 else
1769 {
1770 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
1771 assert(var != NULL);
1772 relaxcons = (SCIP_CONS*)SCIPhashmapGetImage(heurdata->relaxcons, (void*)(var));
1773
1774 /* get ranks */
1775 if( relaxcons != NULL )
1776 {
1777 SCIP_CALL( SCIPgetTransformedCons(heurdata->subscip, relaxcons, &transcons) );
1778 dualvalue = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, (void*)transcons);
1779
1780 if( dualvalue == NULL )
1781 dualvalue = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, (void*)(relaxcons));
1782
1783 if( dualvalue == NULL )
1784 continue;
1785
1786 assert(dualvalue != NULL);
1787 ranks[j] = (*dualvalue);
1788 }
1789 else /* if we have an indicator variable */
1790 {
1791 assert(ranks[j] == 0.0);
1792
1793 if (SCIPhashmapGetImage(heurdata->relaxconsindi, (void*)(var)) != NULL)
1794 {
1795 subcons = (SCIP_CONS*)SCIPhashmapGetImage(heurdata->relaxconsindi, (void*)(var));
1796
1797 dualvalue = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, (void*)(subcons));
1798
1799 if( dualvalue == NULL )
1800 continue;
1801
1802 assert(dualvalue != NULL);
1803
1804 ranks[j] = (*dualvalue);
1805 }
1806
1807 /* compute the rank of the indicators, we take the highest dualvalue of an indicator constraint */
1808 for( k = 0; k < nconsindicator; k++ )
1809 {
1810 SCIP_CONS** indicatorconss = SCIPconshdlrGetConss(conshdlrindicator);
1811 SCIP_CONS* currcons;
1812 SCIP_VAR* indicatorbinvar;
1813
1814 currcons = indicatorconss[k];
1815 assert(currcons != NULL);
1816
1817 indicatorbinvar = SCIPgetBinaryVarIndicator(currcons);
1818 assert(indicatorbinvar != NULL);
1819
1820 if( indicatorbinvar == (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsubsciptoscip, var)
1821 || (SCIPvarIsNegated(indicatorbinvar) && indicatorbinvar == SCIPvarGetNegatedVar(var)) )
1822 {
1823 indicons = currcons;
1824 assert(indicons != NULL);
1825
1826 subcons = (SCIP_CONS*)SCIPhashmapGetImage(heurdata->origsubscipConsMap, (void*)(indicons));
1827 assert(subcons != NULL);
1828
1829 subcons = SCIPgetLinearConsIndicator(subcons);
1830 assert(subcons != NULL);
1831
1832 dualvalue = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, (void*)(subcons));
1833
1834 if( dualvalue == NULL )
1835 continue;
1836
1837 assert(dualvalue != NULL);
1838
1839 if( REALABS(ranks[j]) < REALABS(*dualvalue) )
1840 ranks[j] = (*dualvalue);
1841 }
1842 }
1843 }
1844 }
1845
1846 /* take the absolute value of each rank */
1847 absranks[j] = REALABS(ranks[j]);
1848 }
1849
1850 SCIPsortDownRealRealPtr(absranks, ranks, (void**)sortedvars, heurdata->nintegervars);
1851
1852 return SCIP_OKAY;
1853}
1854
1855/** compute maximal slack of a variable */
1856static
1858 SCIP* scip, /**< scip data structure */
1859 SCIP_HEURDATA* heurdata /**< heuristic data structure */
1860 )
1861{
1862 SCIP_VAR* maxvar;
1863 SCIP_VAR* subvar;
1864 SCIP_SOL* bestsol;
1865 SCIP_Real maxslack;
1866 int i;
1867 int nsubvars;
1868 SCIP_Bool maxslackset;
1869
1870 /* compute maximal slack */
1871 nsubvars = SCIPgetNOrigVars(heurdata->subscip);
1872
1873 /* save information about maximal violation */
1874 maxvar = NULL;
1875 maxslack = -SCIPinfinity(heurdata->subscip);
1876 maxslackset = FALSE;
1877
1878 bestsol = SCIPgetBestSol(heurdata->subscip);
1879
1880 /* search for variable with maximal slack */
1881 for( i = 0; i < nsubvars; i++ )
1882 {
1883 subvar = SCIPgetOrigVars(heurdata->subscip)[i];
1884 if( subvar == NULL)
1885 continue;
1886
1887 /* if variable is slack */
1888 if( SCIPhashmapGetImage(heurdata->slack2var, subvar) != NULL )
1889 {
1890 if( heurdata->isnlp )
1891 {
1892 if( maxslack < SCIPvarGetNLPSol(subvar) )
1893 {
1894 maxslack = SCIPvarGetNLPSol(subvar);
1895 maxvar = subvar;
1896 maxslackset = TRUE;
1897 }
1898 }
1899 else
1900 {
1901 assert(bestsol != NULL);
1902 if( maxslack < SCIPgetSolVal(heurdata->subscip, bestsol, subvar) )
1903 {
1904 maxslack = SCIPgetSolVal(heurdata->subscip, bestsol, subvar);
1905 maxvar = subvar;
1906 maxslackset = TRUE;
1907 }
1908 }
1909 }
1910 }
1911
1912 if( ! maxslackset )
1913 {
1914 maxslack = 0;
1915 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "could not find a variable with maximal slack!\n");
1916 }
1917
1918 assert(maxslack >= 0);
1919
1920 if( heurdata->heurverblevel > 0 && maxslackset )
1921 {
1922 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "maximum slack: %f %s\n", maxslack, SCIPvarGetName(maxvar));
1923 }
1924
1925 return maxslack;
1926}
1927
1928/** method called after a solution is found which is feasible in the original problem, stores it and cleans up */
1929static
1931 SCIP* scip, /**< SCIP data structure */
1932 SCIP_HEUR* heur, /**< heuristic data */
1933 SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found,
1934 * no solution found, or fixing is infeasible (cutoff) */
1935 SCIP_SOL* transsol, /**< solution to fix variables */
1936 SCIP_SOL* bestsol /**< solution we create a original scip solution from */
1937 )
1938{
1939 SCIP_HEURDATA* heurdata;
1940 SCIP_SOL* sol = NULL;
1941 SCIP_Bool stored;
1942 SCIP_Real primalobj;
1943
1944 /* get heuristic's data */
1945 heurdata = SCIPheurGetData(heur);
1946 assert(heurdata != NULL);
1947 SCIP_CALL( createSolFromSubScipSol(scip, heur, &sol, bestsol) );
1948
1949 /* if this happens, there was an ipopt error - stop the heuristic for there is no good starting point */
1950 if( heurdata->isnlp && SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
1951 {
1952 *result = SCIP_DIDNOTFIND;
1953 heurdata->solfound = TRUE;
1954
1955 /* here we can be sure that we are in the nlp case */
1956 assert( heurdata->isnlp );
1957 SCIP_CALL( SCIPfreeSol(heurdata->subscip, &bestsol) );
1958
1959 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
1960
1961 /* don't use the heuristic anymore if IPOPT doesn't give proper solution
1962 * (normally then this happens in most ipopt runs that may follow) */
1963 SCIPheurSetFreq(heur, -1);
1964
1965 SCIPdebugMsg(scip, "return10 : turn off heuristic, ipopt error\n");
1966
1967 if( heurdata->heurverblevel > 1 )
1968 {
1969 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "turn off heuristic due to ipopt error");
1970 }
1971
1972 return SCIP_OKAY;
1973 }
1974
1975 primalobj = SCIPinfinity(scip);
1976
1977 /* if there is a solution, try to add solution to storage and free it */
1978 if( sol != NULL )
1979 {
1980 primalobj = SCIPsolGetOrigObj(sol);
1981
1982 if( heurdata->heurverblevel > 0 )
1983 {
1984 SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
1985 }
1986 else
1987 {
1988 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1989 }
1990 }
1991 else
1992 stored = FALSE;
1993
1994 if( stored && heurdata->heurverblevel > 1 )
1995 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "accepted solution\n");
1996
1997 if( heurdata->isnlp )
1998 SCIP_CALL( SCIPfreeSol(heurdata->subscip, &bestsol) );
1999
2000 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
2001
2002 if( !stored )
2003 {
2004 *result = SCIP_DIDNOTFIND;
2005 heurdata->solfound = TRUE;
2006
2007 if( heurdata->heurverblevel >= 1 )
2008 {
2009 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "return9 : found solution that was not stored, objective %f\n", primalobj);/*lint !e644*/
2010 }
2011
2012 return SCIP_OKAY;
2013 }
2014
2015 heurdata->prevInfeasible = FALSE;
2016 heurdata->solfound = TRUE;
2017 *result = SCIP_FOUNDSOL;
2018
2019 if( heurdata->heurverblevel >= 1 )
2020 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "return 9 : found and stored new solution, objective %lf\n", primalobj);
2021
2022 return SCIP_OKAY;
2023}
2024
2025/** main procedure of the dualval heuristic */
2027 SCIP* scip, /**< original SCIP data structure */
2028 SCIP_HEUR* heur, /**< heuristic data structure */
2029 SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found, no solution
2030 * found, or fixing is infeasible (cutoff) */
2031 SCIP_SOL* refpoint /**< point to take fixation of discrete variables from; if NULL, then LP
2032 * solution is used */
2033 )
2034{
2035 SCIP_HEURDATA* heurdata;
2036 SCIP_NLROW* nlrow;
2037 SCIP_SOL* transsol;
2038 SCIP_SOL* bestsol;
2039 SCIP_CONS** subconss;
2040 SCIP_CONS* rcons;
2041 SCIP_VAR** subvars;
2042 SCIP_VAR** sortedvars;
2043 SCIP_VAR* var;
2044 SCIP_VAR* subvar;
2045 SCIP_VAR* v;
2046 SCIP_RETCODE retcode;
2047 SCIP_Real* absranks;
2048 SCIP_Real* ranks;
2049 SCIP_Real* startpoint;
2050 SCIP_Real* dualval;
2051 SCIP_Real* lastval;
2052 SCIP_Real* seclastval;
2053 SCIP_Real* newval;
2055 SCIP_Real maxslack;
2056 SCIP_Real objvalue;
2057 int i;
2058 int k;
2059 int nsubvars;
2060 int nsubbinvars;
2061 int nsubintvars;
2062 int nsubconss;
2063 int maxequalranks;
2064
2065 assert(scip != NULL);
2066 assert(heur != NULL);
2067
2068 /* dio not run without nlp solver */
2069 if( SCIPgetNNlpis(scip) <= 0 )
2070 return SCIP_OKAY;
2071
2072 /* get heuristic's data */
2073 heurdata = SCIPheurGetData(heur);
2074 assert(heurdata != NULL);
2075
2076 /* don't use the heuristic, if the gap is small so we don't expect to get better solutions than already found */
2077 if( SCIPgetGap(scip) * 100 < heurdata->mingap )
2078 {
2079 SCIPdebugMsg(scip, "return13 : gap is less than mingap\n");
2080 return SCIP_OKAY;
2081 }
2082
2083 /* in the mode 'onlyleaves' don't run the heuristic if we are not in a leaf of the B&B tree */
2084 if( heurdata->onlyleaves && (SCIPgetNLPBranchCands(scip) != 0 || SCIPgetNPseudoBranchCands(scip) != 0) )
2085 return SCIP_OKAY;
2086
2087 /* try to setup subscip if not tried before */
2088 if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
2089 {
2090 SCIP_CALL( createSubSCIP(scip, heurdata) );
2091 }
2092
2093 /* quit the recursion if we have found a solution */
2094 if( heurdata->solfound )
2095 {
2096 SCIPdebugMsg(scip, "return1 : already found solution \n");
2097 return SCIP_OKAY;
2098 }
2099
2100 *result = SCIP_DIDNOTRUN;
2101
2102 /* not initialized */
2103 if( heurdata->subscip == NULL )
2104 {
2105 SCIPdebugMsg(scip, "return2 : subscip is NULL\n");
2106 return SCIP_OKAY;
2107 }
2108
2109 assert(heurdata->nsubvars > 0);
2110 assert(heurdata->varsubsciptoscip != NULL);
2111
2112 /* fix discrete variables in sub-SCIP */
2113 SCIP_CALL( fixDiscreteVars(scip, heurdata, refpoint, &transsol) );
2115
2116 if( heurdata->onlycheaper && !SCIPisInfinity(scip, bound) )
2117 {
2118 SCIP_CALL( SCIPchgRhsLinear( heurdata->subscip, heurdata->objbound, bound) );
2119 }
2120
2121 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", 1) );
2122 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "propagating/maxroundsroot", 0) );
2123
2124 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
2125 SCIP_CALL( SCIPpresolve(heurdata->subscip) );
2126
2127 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
2128 {
2129 SCIPdebugMsg(scip, "return 4 : subscip is infeasible\n");
2130
2131 *result = SCIP_DIDNOTFIND;
2132 heurdata->prevInfeasible = TRUE;
2133 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
2134
2135 return SCIP_OKAY;
2136 }
2137
2138 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
2139 retcode = SCIPsolve(heurdata->subscip);
2140 heurdata->isnlp = TRUE;
2141
2142 bestsol = NULL;
2143
2144 /* we have no dualvalues, so give up */
2145 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_OPTIMAL)
2146 {
2147 *result = SCIP_DIDNOTFIND;
2148 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
2149
2150 return SCIP_OKAY;
2151 }
2152
2153 /* If no NLP was constructed, then there were no nonlinearities after presolve.
2154 * So we increase the nodelimit to 1 and hope that SCIP will find some solution to this probably linear subproblem.
2155 */
2156 if( ! SCIPisNLPConstructed(heurdata->subscip) && retcode == SCIP_OKAY )
2157 {
2158 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
2159 SCIP_CALL( SCIPsolve(heurdata->subscip) );
2160 heurdata->isnlp = FALSE;
2161 bestsol = SCIPgetBestSol(heurdata->subscip);
2162 }
2163
2164 if( heurdata->isnlp )
2165 {
2166 /* add non-combinatorial linear constraints from subscip into subNLP */
2167 SCIP_CALL( addLinearConstraintsToNlp(heurdata->subscip, FALSE, TRUE, heurdata) );
2168
2169 SCIP_CALL( SCIPallocBufferArray(scip, &startpoint, SCIPgetNNLPVars(heurdata->subscip)) );
2170
2171 /* set starting values (=refpoint, if not NULL; otherwise LP solution (or pseudo solution)) */
2172 for( i = 0; i < SCIPgetNNLPVars(heurdata->subscip); ++i )
2173 {
2174 SCIP_Real scalar = 1.0;
2175 SCIP_Real constant = 0.0;
2176
2177 subvar = SCIPgetNLPVars(heurdata->subscip)[i];
2178
2179 /* gets corresponding original variable */
2180 SCIP_CALL( SCIPvarGetOrigvarSum(&subvar, &scalar, &constant) );
2181 if( subvar == NULL )
2182 {
2183 startpoint[i] = constant;
2184 continue;
2185 }
2186
2187 var = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsubsciptoscip, subvar);
2188 if( var == NULL || REALABS( SCIPgetSolVal(scip, refpoint, var) ) > 1.0e+12 )
2189 {
2190 SCIP_Real tmpmax;
2191 tmpmax = MAX( 0.0, SCIPvarGetLbGlobal(subvar) );/*lint !e666*/
2192 startpoint[i] = MIN( tmpmax, SCIPvarGetUbGlobal(subvar) );/*lint !e666*/
2193 }
2194 else
2195 /* scalar*subvar+constant corresponds to nlpvar[i], so nlpvar[i] gets value scalar*varval+constant */
2196 startpoint[i] = scalar * SCIPgetSolVal(scip, refpoint, var) + constant;
2197 }
2198
2199 SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, startpoint) );
2200
2201 /* don't need startpoint array anymore */
2202 SCIPfreeBufferArray( scip, &startpoint );
2203
2204 SCIP_CALL( SCIPsolveNLP(heurdata->subscip, .verblevel = (unsigned short)heurdata->nlpverblevel) ); /*lint !e666*/
2205 assert(SCIPisNLPConstructed(heurdata->subscip));
2206
2207 /* in this case there was an error in ipopt, we try to give another startpoint */
2208 if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
2209 {
2210 SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, NULL) );
2211 SCIP_CALL( SCIPsolveNLP(heurdata->subscip, .verblevel = (unsigned short)heurdata->nlpverblevel) ); /*lint !e666*/
2212 assert(SCIPisNLPConstructed(heurdata->subscip));
2213 }
2214
2215 nsubconss = SCIPgetNOrigConss(heurdata->subscip);
2216 subconss = SCIPgetOrigConss(heurdata->subscip);
2217
2218 /* free memory of all entries and clear the hashmap before filling it */
2219 for( i = 0; i < nsubconss; i++ )
2220 {
2221 dualval = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, subconss[i]);
2222 SCIPfreeBlockMemoryArray(heurdata->subscip, &dualval, 1);
2223 }
2224 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->dualvalues) );
2225
2226 /* save the dualvalues from our nlp solution */
2227 for( i = 0; i < nsubconss; i++ )
2228 {
2229 SCIP_CONS* transcons;
2230
2231 SCIP_CALL( SCIPgetTransformedCons(heurdata->subscip, subconss[i], &transcons) );
2232
2233 if( transcons == NULL )
2234 continue;
2235
2236 if( SCIPconsGetHdlr(transcons) != SCIPfindConshdlr(heurdata->subscip, "linear") )
2237 continue;
2238
2239 nlrow = (SCIP_NLROW*)SCIPhashmapGetImage(heurdata->conss2nlrow, transcons);
2240
2241 if (nlrow != NULL)
2242 {
2243 SCIP_CALL( SCIPallocBlockMemoryArray(heurdata->subscip, &dualval, 1) ); /*lint !e506*/
2244 *dualval = SCIPnlrowGetDualsol(nlrow);
2245 }
2246 else
2247 {
2248 SCIP_CALL( SCIPallocBlockMemoryArray(heurdata->subscip, &dualval, 1) ); /*lint !e506*/
2249 *dualval = 0;
2250 }
2251
2252 SCIP_CALL( SCIPhashmapInsert(heurdata->dualvalues, subconss[i], dualval) );
2253 }
2254
2255 bestsol = NULL;
2256 SCIP_CALL( createSolFromNLP(heurdata->subscip, heur, &bestsol) );
2257 }
2258
2259 /* if we are infeasible, we can't do anything*/
2260 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
2261 {
2262 SCIPdebugMsg(scip, "return4 : the subscip is infeasible\n");
2263
2264 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
2265
2266 return SCIP_OKAY;
2267 }
2268
2269 maxslack = maximalslack(scip, heurdata);
2270 SCIPdebugMsg(scip, "origObj: %f\n", SCIPgetSolOrigObj(heurdata->subscip, bestsol));
2271 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
2272 objvalue = 0.0;
2273 assert(bestsol != NULL);
2274
2275 /* save information about maximal violation */
2276 for( i = 0; i < nsubvars; i++ )
2277 {
2278 subvar = SCIPgetOrigVars(heurdata->subscip)[i];
2279
2280 if( SCIPhashmapGetImage(heurdata->slack2var, subvar) == NULL )
2281 objvalue += SCIPvarGetObj(subvar) * SCIPgetSolVal(heurdata->subscip, bestsol, subvar);
2282 }
2283
2284 /* we stop the heuristic if it does not come "closer" to a feasible solution*/
2285 if( heurdata->forceimprovements )
2286 {
2287 if( SCIPisGE(scip, SCIPgetSolOrigObj(heurdata->subscip, bestsol) - objvalue, heurdata->prevobjective) && maxslack > 0 )
2288 {
2289 heurdata->nonimprovingRounds++;
2290 SCIPdebugMsg(scip, "nonimpr rounds %d prevobj %f \n", heurdata->nonimprovingRounds, heurdata->prevobjective);
2291
2292 /* leave, if we have not improved some iterations*/
2293 if( heurdata->nonimprovingRounds > heurdata->maxcalls/8 )
2294 {
2295 *result = SCIP_DIDNOTFIND;
2296
2297 if( heurdata->isnlp )
2298 {
2299 SCIP_CALL( SCIPfreeSol(heurdata->subscip, &bestsol) );
2300 }
2301
2302 SCIP_CALL( freeMemory(scip, heurdata, transsol, NULL, NULL, NULL, TRUE, TRUE) );
2303
2304 heurdata->solfound = TRUE;
2305 heurdata->switchdifferent = TRUE;
2306
2307 SCIPdebugMsg(scip, "return11 : solution did not improve\n");
2308
2309 return SCIP_OKAY;
2310 }
2311 }
2312 }
2313
2314 heurdata->prevobjective = SCIPgetSolOrigObj(heurdata->subscip, bestsol) - objvalue;
2315
2316 /* in this case we found a feasible solution, store it, clean up and stop the heuristic*/
2317 if( SCIPisFeasLE(heurdata->subscip, maxslack, 0.0) )
2318 return storeSolution(scip, heur, result, transsol, bestsol);
2319
2320 SCIP_CALL( SCIPallocBufferArray(scip, &ranks, heurdata->nintegervars) );
2321 SCIP_CALL( SCIPallocBufferArray(scip, &sortedvars, heurdata->nintegervars) );
2322 SCIP_CALL( SCIPallocBufferArray(scip, &absranks, heurdata->nintegervars) );
2323
2324 /* compute ranks and sort them in non-increasing order */
2325 SCIP_CALL( computeRanks(scip, heurdata, absranks, ranks, sortedvars) );
2326
2327 /* print out the highest ranks */
2328 if( heurdata->heurverblevel > 1 )
2329 {
2330 k = heurdata->rankvalue;
2331
2332 if( heurdata->nintegervars < heurdata->rankvalue )
2333 k = heurdata->nintegervars;
2334
2335 for( i = 0; i < k; i++ )
2336 {
2337 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "%i. rank: %f name: %s\n", i, ranks[i], SCIPvarGetName(sortedvars[i]));
2338 }
2339 }
2340
2341 /* free solution */
2342 if( heurdata->isnlp )
2343 SCIP_CALL( SCIPfreeSol(heurdata->subscip, &bestsol) );
2344
2345 /* we don't allow more than a third of the variables to have the same rank */
2346 maxequalranks = MIN(heurdata->maxequalranks, heurdata->nintegervars/3);
2347
2348 if( heurdata->maxequalranks >= 0 && SCIPisFeasEQ(heurdata->subscip, REALABS(ranks[0]), REALABS(ranks[maxequalranks])) )
2349 {
2350 *result = SCIP_DIDNOTFIND;
2351
2352 SCIPdebugMsg(scip, "return12 : equal maxranks\n");
2353
2354 SCIP_CALL( freeMemory(scip, heurdata, transsol, absranks, ranks, sortedvars, TRUE, TRUE ) );
2355 return SCIP_OKAY;
2356 }
2357
2358 /* now we can start switching the variable values */
2359 SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
2360
2361 /* set bounds of fixed discrete variables to original values so we can switch */
2362 for( k = 0; k < heurdata->nintegervars; ++k )
2363 {
2364 var = heurdata->integervars[k];
2365 if( var == NULL )
2366 break;
2367
2368 var = SCIPvarGetTransVar(var);
2369 subvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->varsciptosubscip, var);
2370
2371 rcons = (SCIP_CONS*) SCIPhashmapGetImage(heurdata->relaxcons, subvar);
2372 if( rcons != NULL )
2373 continue;
2374
2375 assert(var != NULL);
2376 assert(subvar != NULL);
2377
2378 if ( SCIPhashmapGetImage(heurdata->indicopymap, subvar) != NULL )
2379 subvar = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->indicopymap, subvar);
2380
2381 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(heurdata->integervars[k])) );
2382 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(heurdata->integervars[k])) );
2383 }
2384
2385 /* switch variable with maximum ranking if possible */
2386 for( i = 0; i < heurdata->nintegervars; i++ )
2387 {
2388 v = sortedvars[i];
2389 SCIP_CALL( SCIPallocBlockMemoryArray(heurdata->subscip, &newval, 1) ); /*lint !e506*/
2390
2391 /* compute the new value of the variable */
2392
2393 /* if we have an indicator constraint, we turn it off */
2394 if( SCIPhashmapGetImage(heurdata->slacktoindivarsmap, v) != NULL )
2395 {
2396 /* get the indicator var of this constraint */
2397 v = (SCIP_VAR*)SCIPhashmapGetImage(heurdata->slacktoindivarsmap, v);
2398
2399 /* set the value to 0 */
2400 SCIP_CALL( SCIPsetSolVal(scip, transsol, v, 0.0) );
2401 if( heurdata->heurverblevel > 1 )
2402 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Setting value of %s%s to 0\n", SCIPvarIsNegated(v) ? "(negated) " : " ", SCIPvarGetName(v));
2403
2404 *newval = 0.0;
2405 SCIP_CALL( SCIPhashmapInsert(heurdata->switchedvars, v, newval) );
2406 }
2407 else
2408 {
2409 /* ignore fixed vars in input */
2411 {
2412 SCIPfreeBlockMemoryArray(heurdata->subscip, &newval, 1);
2413 continue;
2414 }
2415
2416 if( ranks[i] > 0 )
2417 {
2418 if( SCIPvarIsBinary(v) && SCIPisEQ(scip, 1.0, SCIPgetSolVal(scip, transsol, v)) )
2419 {
2420 SCIPfreeBlockMemoryArray(heurdata->subscip, &newval, 1);
2421 continue;
2422 }
2423
2424 *newval = SCIPgetSolVal(scip, transsol, v) + 1;
2425 }
2426 else
2427 {
2428 if( SCIPvarIsBinary(v) && SCIPisEQ(scip, 0.0, SCIPgetSolVal(scip, transsol, v)) )
2429 {
2430 SCIPfreeBlockMemoryArray(heurdata->subscip, &newval, 1);
2431 continue;
2432 }
2433
2434 *newval = SCIPgetSolVal(scip, transsol, v) - 1;
2435 }
2436 }
2437 lastval = (SCIP_Real*)SCIPhashmapGetImage(heurdata->switchedvars, v);
2438 seclastval = (SCIP_Real*)SCIPhashmapGetImage(heurdata->switchedvars2, v);
2439
2440 /* we don't want to set a variable to a value it already had,or set a binary variable more than once */
2441 if( (lastval != NULL && (SCIPvarIsBinary(v) || SCIPisFeasEQ(scip, *lastval, *newval))) || (seclastval != NULL && SCIPisFeasEQ(scip, *seclastval, *newval)) )
2442 {
2443 SCIPfreeBlockMemoryArray(heurdata->subscip, &newval, 1);
2444 continue;
2445 }
2446 else /* update the switchedvars values, switchedvars2 is the second last and switchedvars the last value */
2447 {
2448 if( seclastval != NULL )
2449 SCIPfreeBlockMemoryArray(heurdata->subscip, &seclastval, 1);
2450
2451 SCIP_CALL( SCIPhashmapRemove(heurdata->switchedvars2, v) );
2452 SCIP_CALL( SCIPhashmapInsert(heurdata->switchedvars2, v, lastval) );
2453 SCIP_CALL( SCIPhashmapRemove(heurdata->switchedvars, v) );
2454 SCIP_CALL( SCIPhashmapInsert(heurdata->switchedvars, v, newval) );
2455
2456 if( heurdata->heurverblevel > 1 )
2457 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Setting value of %s from %f to %f\n", SCIPvarGetName(v), SCIPgetSolVal(scip, transsol, v), *newval);
2458
2459 SCIP_CALL( SCIPsetSolVal(scip, transsol, v, *newval) );
2460 }
2461
2462 /* if we have exceeded our iterations limit give up without any solution */
2463 if( heurdata->usedcalls >= heurdata->maxcalls )
2464 {
2465 SCIPdebugMsg(scip, "return5 : reached iteration limit\n");
2466
2467 SCIP_CALL( freeMemory(scip, heurdata, transsol, absranks, ranks, sortedvars, FALSE, TRUE) );
2468 *result = SCIP_DIDNOTFIND;
2469 return SCIP_OKAY;
2470 }
2471
2472 heurdata->usedcalls++;
2473
2474 if( heurdata->heurverblevel > 1 )
2475 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "----- Total Calls: %d\n", heurdata->usedcalls);
2476
2477 /* recursive call of the heuristic */
2478 SCIP_CALL( SCIPapplyHeurDualval(scip, heur, result, transsol) );
2479
2480 /* just to go up in the recursion */
2481 if( *result == SCIP_DIDNOTFIND || heurdata->solfound || heurdata->prevInfeasible )
2482 {
2483 SCIPdebugMsg(scip, "return6 : go up\n");
2484
2485 /* here we only go up one step and try another switch (switch the same variables again is forbidden
2486 * since they are contained in switchedvars) */
2487 if( heurdata->switchdifferent )
2488 {
2489 heurdata->switchdifferent = FALSE;
2490 heurdata->solfound = FALSE;
2491 *result = SCIP_DIDNOTRUN;
2492 heurdata->nonimprovingRounds -= 2;
2493 }
2494
2495 if( heurdata->prevInfeasible )
2496 {
2497 heurdata->prevInfeasible = FALSE;
2498 heurdata->solfound = FALSE;
2499 *result = SCIP_DIDNOTRUN;
2500 heurdata->nonimprovingRounds++;
2501 }
2502
2503 SCIP_CALL( freeMemory(scip, heurdata, transsol, absranks, ranks, sortedvars, FALSE, FALSE) );
2504 return SCIP_OKAY;
2505 }
2506 }
2507
2508 if( heurdata->subscip == NULL )
2509 {
2510 /* something horrible must have happened that we decided to give up completely on this heuristic */
2511 *result = SCIP_DIDNOTFIND;
2512 SCIPdebugMsg(scip, "return7 : subscip was set NULL\n");
2513
2514 SCIP_CALL( freeMemory(scip, heurdata, transsol, absranks, ranks, sortedvars, FALSE, TRUE) );
2515 return SCIP_OKAY;
2516 }
2517 assert(!SCIPisTransformed(heurdata->subscip));
2518
2519 SCIPdebugMsg(scip, "return8 : cannot switch any variable\n");
2520
2521 SCIP_CALL( freeMemory(scip, heurdata, transsol, absranks, ranks, sortedvars, FALSE, TRUE) );
2522
2523 *result = SCIP_DIDNOTFIND;
2524 return SCIP_OKAY;
2525}
2526
2527/*
2528 * Callback methods of primal heuristic
2529 */
2530
2531/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
2532static
2533SCIP_DECL_HEURCOPY(heurCopyDualval)
2534{ /*lint --e{715}*/
2535 assert(scip != NULL);
2536 assert(heur != NULL);
2537 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2538
2539 /* call inclusion method of primal heuristic */
2541
2542 return SCIP_OKAY;
2543}
2544
2545/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
2546static
2547SCIP_DECL_HEURFREE(heurFreeDualval)
2548{
2549 SCIP_HEURDATA* heurdata;
2550
2551 assert(scip != NULL);
2552 assert(heur != NULL);
2553
2554 heurdata = SCIPheurGetData(heur);
2555
2556 SCIPfreeBlockMemory(scip, &heurdata);
2557
2558 return SCIP_OKAY;
2559}
2560
2561
2562/** initialization method of primal heuristic (called after problem was transformed) */
2563static
2564SCIP_DECL_HEURINIT(heurInitDualval)
2565{ /*lint --e{715}*/
2566 SCIP_HEURDATA* heurdata;
2567
2568 assert(scip != NULL);
2569 assert(heur != NULL);
2570
2571 /* skip setting up sub-SCIP if heuristic is disabled or we do not want to run the heuristic */
2572 if( SCIPheurGetFreq(heur) < 0 )
2573 return SCIP_OKAY;
2574
2575 SCIP_CALL( SCIPsetIntParam(scip, "presolving/maxrestarts", 0) );
2576
2577 heurdata = SCIPheurGetData(heur);
2578 assert(heurdata != NULL);
2579 assert(heurdata->subscip == NULL);
2580 assert(!heurdata->triedsetupsubscip);
2581
2582 /* create sub-SCIP for later use */
2583 SCIP_CALL( createSubSCIP(scip, heurdata) );
2584
2585 /* creating sub-SCIP may fail if the solver interfaces did not copy into subscip */
2586 if( heurdata->subscip == NULL )
2587 return SCIP_OKAY;
2588
2589 /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
2590 if( SCIPheurGetFreqofs(heur) == 0 )
2592
2593 SCIP_CALL( SCIPhashmapCreate(&heurdata->dualvalues, SCIPblkmem(scip), 512) );
2594
2595 return SCIP_OKAY;
2596}
2597
2598/** deinitialization method of primal heuristic (called before transformed problem is freed) */
2599static
2600SCIP_DECL_HEUREXIT(heurExitDualval)
2601{ /*lint --e{715}*/
2602 SCIP_HEURDATA* heurdata;
2603 SCIP_CONS** subconss;
2604 SCIP_Real* dualval;
2605 int i;
2606 int nsubconss;
2607
2608 assert(scip != NULL);
2609 assert(heur != NULL);
2610
2611 heurdata = SCIPheurGetData(heur);
2612 assert(heurdata != NULL);
2613
2614 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->integervars, heurdata->integervarssize);
2615
2616 if( heurdata->subscip != NULL)
2617 {
2618 nsubconss = SCIPgetNOrigConss(heurdata->subscip);
2619 subconss = SCIPgetOrigConss(heurdata->subscip);
2620
2621 /* free memory of all entries and clear the hashmap before filling it */
2622 for( i = 0; i < nsubconss; i++ )
2623 {
2624 dualval = (SCIP_Real*)SCIPhashmapGetImage(heurdata->dualvalues, subconss[i]);
2625 SCIPfreeBlockMemoryArrayNull(heurdata->subscip, &dualval, 1);
2626 }
2627 SCIP_CALL( SCIPhashmapRemoveAll(heurdata->dualvalues) );
2628 SCIPhashmapFree(&heurdata->dualvalues);
2629
2630 if( heurdata->varsciptosubscip != NULL )
2631 {
2632 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->varsciptosubscip, TRUE) );
2633
2634 SCIPhashmapFree(&heurdata->varsciptosubscip);
2635 }
2636 if( heurdata->origsubscipConsMap != NULL )
2637 {
2638 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->origsubscipConsMap, FALSE) );
2639
2640 SCIPhashmapFree(&heurdata->origsubscipConsMap);
2641 }
2642 if( heurdata->relaxcons != NULL )
2643 {
2644 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->relaxcons, FALSE) );
2645
2646 SCIPhashmapFree(&heurdata->relaxcons);
2647 }
2648 if( heurdata->conss2nlrow != NULL )
2649 {
2650 SCIP_CALL( releaseHashmapNLPRows(heurdata->subscip, heurdata->conss2nlrow) );
2651
2652 SCIPhashmapFree(&heurdata->conss2nlrow);
2653 }
2654 if( heurdata->slack2var != NULL )
2655 {
2656 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->slack2var, TRUE) );
2657
2658 SCIPhashmapFree(&heurdata->slack2var);
2659 }
2660 if( heurdata->indicopymap != NULL )
2661 {
2662 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->indicopymap, TRUE) );
2663
2664 SCIPhashmapFree(&heurdata->indicopymap);
2665 }
2666 if( heurdata->indicopymapback != NULL )
2667 {
2668 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->indicopymapback, TRUE) );
2669
2670 SCIPhashmapFree(&heurdata->indicopymapback);
2671 }
2672 if( heurdata->relaxconsindi != NULL )
2673 {
2674 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->relaxconsindi, FALSE) );
2675
2676 SCIPhashmapFree(&heurdata->relaxconsindi);
2677 }
2678 if( heurdata->slackvarlbMap != NULL )
2679 {
2680 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->slackvarlbMap, TRUE) );
2681
2682 SCIPhashmapFree(&heurdata->slackvarlbMap);
2683 }
2684 if( heurdata->slackvarubMap != NULL )
2685 {
2686 SCIP_CALL( releaseHashmapEntries(heurdata->subscip, heurdata->slackvarubMap, TRUE) );
2687
2688 SCIPhashmapFree(&heurdata->slackvarubMap);
2689 }
2690
2691 if( heurdata->subscip != NULL )
2692 {
2693 SCIP_CALL( freeSubSCIP(scip, heurdata) );
2694 }
2695 }
2696
2697 if( heurdata->varsubsciptoscip != NULL )
2698 {
2699 SCIP_CALL( releaseHashmapEntries(scip, heurdata->varsubsciptoscip, TRUE) );
2700
2701 SCIPhashmapFree(&heurdata->varsubsciptoscip);
2702 }
2703 if( heurdata->slacktoindivarsmap != NULL )
2704 {
2705 SCIP_CALL( releaseHashmapEntries(scip, heurdata->slacktoindivarsmap, TRUE) );
2706
2707 SCIPhashmapFree(&heurdata->slacktoindivarsmap);
2708 }
2709 if( heurdata->indicators != NULL )
2710 {
2711 SCIP_CALL( releaseHashmapEntries(scip, heurdata->indicators, FALSE) );
2712
2713 SCIPhashmapFree(&heurdata->indicators);
2714 }
2715 if( heurdata->switchedvars != NULL )
2716 {
2717 SCIPhashmapFree(&heurdata->switchedvars);
2718 }
2719 if( heurdata->switchedvars2 != NULL )
2720 {
2721 SCIPhashmapFree(&heurdata->switchedvars2);
2722 }
2723
2724 /* reset some flags and counters */
2725 heurdata->triedsetupsubscip = FALSE;
2726 heurdata->usedcalls = 0;
2727 heurdata->solfound = FALSE;
2728 heurdata->prevInfeasible = FALSE;
2729
2730 assert(heurdata->subscip == NULL);
2731 assert(heurdata->varsubsciptoscip == NULL);
2732 assert(heurdata->varsciptosubscip == NULL);
2733
2734 return SCIP_OKAY;
2735}
2736
2737/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
2738static
2739SCIP_DECL_HEURINITSOL(heurInitsolDualval)
2740{
2741 SCIP_HEURDATA* heurdata;
2742
2743 assert(scip != NULL);
2744 assert(heur != NULL);
2745
2746 /* skip setting up sub-SCIP if heuristic is disabled or we do not want to run the heuristic */
2747 if( SCIPheurGetFreq(heur) < 0 )
2748 return SCIP_OKAY;
2749
2750 heurdata = SCIPheurGetData(heur);
2751 assert(heurdata != NULL);
2752
2753 /* creating sub-SCIP may fail if the solver interfaces did not copy into subscip */
2754 if( heurdata->subscip == NULL )
2755 return SCIP_OKAY;
2756
2757 /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
2758 if( SCIPheurGetFreqofs(heur) == 0 )
2760
2761 return SCIP_OKAY;
2762}
2763
2764
2765/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
2766static
2767SCIP_DECL_HEUREXITSOL(heurExitsolDualval)
2768{
2769 assert(scip != NULL);
2770 assert(heur != NULL);
2771
2773
2774 return SCIP_OKAY;
2775}
2776
2777
2778/** execution method of primal heuristic */
2779static
2780SCIP_DECL_HEUREXEC(heurExecDualval)
2781{ /*lint --e{715}*/
2782 SCIP_HEURDATA* heurdata;
2783
2784 assert(scip != NULL);
2785 assert(heur != NULL);
2786 assert(result != NULL);
2787
2788 /* get heuristic's data */
2789 heurdata = SCIPheurGetData(heur);
2790 assert(heurdata != NULL);
2791
2792 /* obviously, we did not do anything yet */
2793 *result = SCIP_DIDNOTRUN;
2794
2795 /* init data */
2796 heurdata->usedcalls = 0;
2797 heurdata->prevInfeasible = FALSE;
2798 heurdata->solfound = FALSE;
2799 heurdata->nonimprovingRounds = 0;
2800 heurdata->prevobjective = INT_MAX;
2801
2802 SCIP_CALL( SCIPapplyHeurDualval(scip, heur, result, NULL) );
2803
2804 /* SCIP does not like cutoff as return, so we say didnotfind, since we did not find a solution */
2805 if( *result == SCIP_CUTOFF )
2806 *result = SCIP_DIDNOTFIND;
2807
2808 /* reset timing, if it was changed temporary (at the root node) */
2809 if( heurtiming != HEUR_TIMING )
2811
2812 return SCIP_OKAY;
2813}
2814
2815
2816/* primal heuristic specific interface methods */
2817
2818/** creates the dualval primal heuristic and includes it in SCIP */
2820 SCIP* scip /**< SCIP data structure */
2821 )
2822{
2823 SCIP_HEURDATA* heurdata = NULL;
2824 SCIP_HEUR* heur = NULL;
2825
2826 /* create dualval primal heuristic data */
2827 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
2828 BMSclearMemory(heurdata);
2829
2830 /* include primal heuristic */
2833 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDualval, heurdata) );
2834
2835 assert(heur != NULL);
2836
2837 /* primal heuristic is safe to use in exact solving mode */
2838 SCIPheurMarkExact(heur);
2839
2840 /* set non fundamental callbacks via setter functions */
2841 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDualval) );
2842 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDualval) );
2843 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitDualval) );
2844 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitDualval) );
2845 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolDualval) );
2846 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolDualval) );
2847
2848 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/forceimprovements",
2849 "exit if objective doesn't improve",
2850 &heurdata->forceimprovements, TRUE, DEFAULT_FORCEIMPROVEMENTS, NULL, NULL) );
2851
2852 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/onlycheaper",
2853 "add constraint to ensure that discrete vars are improving",
2854 &heurdata->onlycheaper, TRUE, DEFAULT_ONLYCHEAPER, NULL, NULL) );
2855
2856 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/onlyleaves",
2857 "disable the heuristic if it was not called at a leaf of the B&B tree",
2858 &heurdata->onlyleaves, FALSE, DEFAULT_ONLYLEAVES, NULL, NULL) );
2859
2860 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/relaxindicators",
2861 "relax the indicator variables by introducing continuous copies",
2862 &heurdata->relaxindicators, FALSE, DEFAULT_RELAXINDICATORS, NULL, NULL) );
2863
2864 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/relaxcontvars",
2865 "relax the continous variables",
2866 &heurdata->relaxcontvars, FALSE, DEFAULT_RELAXCONTVARS, NULL, NULL) );
2867
2868 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/heurverblevel",
2869 "verblevel of the heuristic, default is 0 to display nothing",
2870 &heurdata->heurverblevel, FALSE, DEFAULT_HEURVERBLEVEL, 0, 4, NULL, NULL) );
2871
2872 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nlpverblevel",
2873 "verblevel of the nlp solver, can be 0 or 1",
2874 &heurdata->nlpverblevel, FALSE, DEFAULT_NLPVERBLEVEL, 0, 1, NULL, NULL) );
2875
2876 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/rankvalue",
2877 "number of ranks that should be displayed when the heuristic is called",
2878 &heurdata->rankvalue, FALSE, DEFAULT_RANKVALUE, 0, INT_MAX, NULL, NULL) );
2879
2880 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxcalls",
2881 "maximal number of recursive calls of the heuristic (if dynamicdepth is off)",
2882 &heurdata->maxcalls, FALSE, DEFAULT_MAXCALLS, 0, INT_MAX, NULL, NULL) );
2883
2884 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/dynamicdepth",
2885 "says if and how the recursion depth is computed at runtime",
2886 &heurdata->dynamicdepth, FALSE, DEFAULT_DYNAMICDEPTH, 0, 1, NULL, NULL) );
2887
2888 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxequalranks",
2889 "maximal number of variables that may have maximal rank, quit if there are more, turn off by setting -1",
2890 &heurdata->maxequalranks, FALSE, DEFAULT_MAXEQUALRANKS, -1, INT_MAX, NULL, NULL) );
2891
2892 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/mingap",
2893 "minimal gap for which we still run the heuristic, if gap is less we return without doing anything",
2894 &heurdata->mingap, FALSE, DEFAULT_MINGAP, 0.0, 100.0, NULL, NULL) );
2895
2896 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lambdaslack",
2897 "value added to objective of slack variables, must not be zero",
2898 &heurdata->lambdaslack, FALSE, DEFAULT_LAMBDASLACK, 0.1, SCIPinfinity(scip), NULL, NULL) );
2899
2900 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lambdaobj",
2901 "scaling factor for the objective function",
2902 &heurdata->lambdaobj, FALSE, DEFAULT_LAMBDAOBJ, 0.0, 1.0, NULL, NULL) );
2903
2904 return SCIP_OKAY;
2905}
static long bound
constraint handler for indicator constraints
Constraint handler for knapsack constraints of the form , x binary and .
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
Constraint handler for the set partitioning / packing / covering constraints .
Constraint handler for variable bound constraints .
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#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 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_RETCODE SCIPcreateConsIndicatorLinCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, SCIP_CONS *lincons, SCIP_VAR *slackvar, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9596
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9619
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9642
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
@ SCIP_SETPPCTYPE_PARTITIONING
Definition: cons_setppc.h:87
@ SCIP_SETPPCTYPE_COVERING
Definition: cons_setppc.h:89
@ SCIP_SETPPCTYPE_PACKING
Definition: cons_setppc.h:88
SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip_copy.c:276
SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global)
Definition: scip_copy.c:1167
SCIP_RETCODE SCIPcopyConss(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool *valid)
Definition: scip_copy.c:1716
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:2547
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:647
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:402
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:370
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:562
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2753
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1242
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3712
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip_prob.c:2811
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3420
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3620
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2838
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition: scip_prob.c:3739
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip_prob.c:119
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3613
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3584
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3592
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3603
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3676
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3482
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPapplyHeurDualval(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint)
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 SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:545
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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:487
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 SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip_param.c:603
SCIP_RETCODE SCIPincludeHeurDualval(SCIP *scip)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:436
int SCIPgetNPseudoBranchCands(SCIP *scip)
Definition: scip_branch.c:766
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4778
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4812
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4735
void SCIPconsAddUpgradeLocks(SCIP_CONS *cons, int nlocks)
Definition: cons.c:8828
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8486
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPgetTransformedCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
Definition: scip_cons.c:1674
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1138
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:406
SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
Definition: scip_event.c:185
SCIP_RETCODE SCIPsetEventhdlrInit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)))
Definition: scip_event.c:171
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:293
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:333
SCIP_RETCODE SCIPenableExactSolving(SCIP *scip, SCIP_Bool enable)
Definition: scip_exact.c:151
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip_heur.c:247
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
void SCIPheurSetFreq(SCIP_HEUR *heur, int freq)
Definition: heur.c:1562
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1507
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:231
int SCIPheurGetFreqofs(SCIP_HEUR *heur)
Definition: heur.c:1573
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition: heur.c:1457
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1552
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:174
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
int SCIPgetNNlpis(SCIP *scip)
Definition: scip_nlpi.c:205
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip_nlp.c:574
#define SCIPsolveNLP(...)
Definition: scip_nlp.h:361
SCIP_RETCODE SCIPsetNLPInitialGuess(SCIP *scip, SCIP_Real *initialguess)
Definition: scip_nlp.c:474
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip_nlp.c:201
SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
Definition: scip_nlp.c:179
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_Real SCIPnlrowGetDualsol(SCIP_NLROW *nlrow)
Definition: nlp.c:1966
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
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_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
Definition: sol.c:4170
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:831
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:4109
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1892
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_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip_solve.c:2449
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip_solve.c:3462
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2635
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Real SCIPgetGap(SCIP *scip)
SCIP_Bool SCIPisRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18320
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:23868
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:2499
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:6141
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:10113
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:2166
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:23443
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:6230
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:120
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:23672
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:5372
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:24691
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1853
void SCIPsortDownRealRealPtr(SCIP_Real *realarray1, SCIP_Real *realarray2, void **ptrarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
static SCIP_DECL_EVENTEXEC(eventExecLPsol)
Definition: heur_dualval.c:195
#define DEFAULT_RANKVALUE
Definition: heur_dualval.c:101
#define DEFAULT_ONLYCHEAPER
Definition: heur_dualval.c:93
static SCIP_RETCODE createSolFromSubScipSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_SOL *subsol)
Definition: heur_dualval.c:766
static SCIP_RETCODE addSetppcConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:548
static SCIP_DECL_HEUREXIT(heurExitDualval)
#define DEFAULT_LAMBDAOBJ
Definition: heur_dualval.c:109
#define DEFAULT_MINGAP
Definition: heur_dualval.c:107
#define DEFAULT_HEURVERBLEVEL
Definition: heur_dualval.c:99
static SCIP_RETCODE addLogicOrConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:481
#define HEUR_TIMING
Definition: heur_dualval.c:84
static SCIP_RETCODE createSolFromNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol)
#define HEUR_FREQOFS
Definition: heur_dualval.c:82
static SCIP_RETCODE computeRanks(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real *absranks, SCIP_Real *ranks, SCIP_VAR **sortedvars)
#define HEUR_DESC
Definition: heur_dualval.c:78
static SCIP_RETCODE freeMemory(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *transsol, SCIP_Real *absranks, SCIP_Real *ranks, SCIP_VAR **sortedvars, SCIP_Bool beforeswitching, SCIP_Bool clearswitchedvars)
#define DEFAULT_RELAXINDICATORS
Definition: heur_dualval.c:95
static SCIP_DECL_HEUREXEC(heurExecDualval)
static SCIP_RETCODE releaseHashmapNLPRows(SCIP *scip, SCIP_HASHMAP *hashmap)
Definition: heur_dualval.c:314
static SCIP_RETCODE addLinearConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool addcombconss, SCIP_Bool addcontconss, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:346
#define DEFAULT_FORCEIMPROVEMENTS
Definition: heur_dualval.c:92
#define HEUR_DISPCHAR
Definition: heur_dualval.c:79
#define HEUR_MAXDEPTH
Definition: heur_dualval.c:83
#define HEUR_PRIORITY
Definition: heur_dualval.c:80
static SCIP_RETCODE storeSolution(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *transsol, SCIP_SOL *bestsol)
#define DEFAULT_LAMBDASLACK
Definition: heur_dualval.c:108
static SCIP_DECL_EVENTEXIT(eventExitLPsol)
Definition: heur_dualval.c:182
#define HEUR_NAME
Definition: heur_dualval.c:77
static SCIP_DECL_HEURINIT(heurInitDualval)
#define DEFAULT_RELAXCONTVARS
Definition: heur_dualval.c:96
static SCIP_DECL_HEURCOPY(heurCopyDualval)
#define DEFAULT_MAXCALLS
Definition: heur_dualval.c:102
static SCIP_Real maximalslack(SCIP *scip, SCIP_HEURDATA *heurdata)
static SCIP_RETCODE SCIPincludeEventHdlrLPsol(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:245
static SCIP_RETCODE createSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:857
static SCIP_DECL_HEUREXITSOL(heurExitsolDualval)
#define BIG_VALUE
static SCIP_DECL_HEURFREE(heurFreeDualval)
static SCIP_RETCODE fixDiscreteVars(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *refpoint, SCIP_SOL **transsol)
static SCIP_RETCODE addKnapsackConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:640
#define DEFAULT_DYNAMICDEPTH
Definition: heur_dualval.c:103
static SCIP_DECL_HEURINITSOL(heurInitsolDualval)
#define DEFAULT_ONLYLEAVES
Definition: heur_dualval.c:94
static SCIP_RETCODE freeSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
#define DEFAULT_NLPVERBLEVEL
Definition: heur_dualval.c:100
static SCIP_RETCODE releaseHashmapEntries(SCIP *scip, SCIP_HASHMAP *hashmap, SCIP_Bool isvarmap)
Definition: heur_dualval.c:271
#define EVENTHDLR_DESC
Definition: heur_dualval.c:88
#define DEFAULT_MAXEQUALRANKS
Definition: heur_dualval.c:104
#define HEUR_FREQ
Definition: heur_dualval.c:81
static SCIP_RETCODE addVarboundConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool addcombconss, SCIP_Bool addcontconss, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:423
#define HEUR_USESSUBSCIP
Definition: heur_dualval.c:85
static SCIP_RETCODE addLinearConstraintsToNlp(SCIP *scip, SCIP_Bool addcombconss, SCIP_Bool addcontconss, SCIP_HEURDATA *heurdata)
Definition: heur_dualval.c:712
static SCIP_DECL_EVENTINIT(eventInitLPsol)
Definition: heur_dualval.c:169
#define EVENTHDLR_NAME
Definition: heur_dualval.c:87
primal heuristic that uses dualvalues for successive switching variable values
memory allocation routines
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
public methods for managing constraints
public methods for managing events
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for NLP management
public methods for primal CIP solutions
public methods for problem variables
public methods for branching rule plugins and branching
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for event handler plugins and event handlers
public methods for exact solving
general public methods
public methods for primal heuristic plugins and divesets
public methods for the LP relaxation, rows and columns
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 solving methods
public methods for querying solving statistics
public methods for SCIP variables
#define SCIP_EVENTTYPE_FIRSTLPSOLVED
Definition: type_event.h:101
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:160
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:102
type and macro definitions related to algebraic expressions
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:61
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition: type_nlpi.h:162
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_FOUNDSOL
Definition: type_result.h:56
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:43
@ SCIP_STATUS_INFEASIBLE
Definition: type_stat.h:44
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:81
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64