SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_padm.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_padm.c
26 * @brief PADM primal heuristic
27 * @author Dieter Weninger
28 * @author Katrin Halbig
29 *
30 * Primal heuristic based on ideas published in the papers
31 * "A Decomposition Heuristic for Mixed-Integer Supply Chain Problems" by Martin Schmidt, Lars Schewe, and Dieter Weninger,
32 * and "Exploiting user-supplied Decompositions inside Heuristics" by Katrin Halbig, Adrian Göß and Dieter Weninger.
33 *
34 * The penalty alternating direction method (PADM) heuristic is a construction heuristic which additionally needs a
35 * user decomposition with linking variables only.
36 *
37 * PADM splits the problem into several sub-SCIPs according to the decomposition, whereby the linking variables get
38 * copied and the difference is penalized. Then the sub-SCIPs are solved on an alternating basis until they arrive at
39 * the same values of the linking variables (ADM-loop). If they don't reconcile after a couple of iterations,
40 * the penalty parameters are increased (penalty-loop) and the sub-SCIPs are solved again on an alternating basis.
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
46#include "scip/cons_linear.h"
47#include "scip/debug.h"
48#include "scip/heur_padm.h"
49#include "scip/heuristics.h"
50#include "scip/pub_cons.h"
51#include "scip/pub_tree.h"
52#include "scip/pub_heur.h"
53#include "scip/pub_message.h"
54#include "scip/pub_misc.h"
56#include "scip/pub_sol.h"
57#include "scip/pub_var.h"
58#include "scip/scipdefplugins.h"
59#include "scip/scip_branch.h"
60#include "scip/scip_cons.h"
61#include "scip/scip_copy.h"
62#include "scip/scip_dcmp.h"
63#include "scip/scip_general.h"
64#include "scip/scip_heur.h"
65#include "scip/scip_lp.h"
66#include "scip/scip_mem.h"
67#include "scip/scip_message.h"
68#include "scip/scip_nodesel.h"
69#include "scip/scip_numerics.h"
70#include "scip/scip_param.h"
71#include "scip/scip_prob.h"
73#include "scip/scip_sol.h"
74#include "scip/scip_solve.h"
76#include "scip/scip_table.h"
77#include "scip/scip_timing.h"
78#include "scip/scip_tree.h"
79#include "scip/scip_var.h"
80
81#define HEUR_NAME "padm"
82#define HEUR_DESC "penalty alternating direction method primal heuristic"
83#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
84#define HEUR_PRIORITY 70000
85#define HEUR_FREQ 0
86#define HEUR_FREQOFS 0
87#define HEUR_MAXDEPTH -1
88#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE | SCIP_HEURTIMING_AFTERNODE
89#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
90
91#define COUPLINGSIZE 3
92#define DEFAULT_MINNODES 50LL
93#define DEFAULT_MAXNODES 5000LL
94#define DEFAULT_NODEFAC 0.8
95#define DEFAULT_ADMIT 4
96#define DEFAULT_PENALTYIT 100
97#define DEFAULT_GAP 2.0
98
99/*
100 * Data structures
101 */
102
103/** data related to one problem (see below) */
104typedef struct Problem PROBLEM;
105
106/** data related to one block */
107typedef struct Block
108{
109 PROBLEM* problem; /**< the problem this block belongs to */
110 SCIP* subscip; /**< sub-SCIP representing this block */
111 int number; /**< component number */
112 SCIP_VAR** subvars; /**< variables belonging to this block (without slack variables) */
113 int nsubvars; /**< number of variables belonging to this block (without slack variables) */
114 SCIP_VAR** slackspos; /**< positive slack variables */
115 SCIP_VAR** slacksneg; /**< negative slack variables */
116 SCIP_CONS** couplingcons; /**< coupling contraints */
117 int ncoupling; /**< number of coupling contraints (equal to positive/negative slack variables) */
118 SCIP_Real size; /**< share of total problem */
120
121/** data related to one problem */
122struct Problem
123{
124 SCIP* scip; /**< the SCIP instance this problem belongs to */
125 char* name; /**< name of the problem */
126 BLOCK* blocks; /**< blocks into which the problem will be divided */
127 int nblocks; /**< number of blocks */
128};
129
130/** set data structure */
131typedef struct set
132{
133 int size; /**< size of the set */
134 int* indexes; /**< set of indexes */
136
137/** data of one linking variable related to one block */
138typedef struct blockinfo
139{
140 int block; /**< index of this block */
141 int otherblock; /**< index of the other connected block */
142 int linkvaridx; /**< linking variable index */
143 SCIP_Real linkvarval; /**< value of linking variable */
144 SCIP_VAR* linkvar; /**< linking variable */
145 SCIP_Real slackposobjcoeff; /**< penalty coefficient of positive slack variable */
146 SCIP_VAR* slackposvar; /**< positive slack variable */
147 SCIP_Real slacknegobjcoeff; /**< penalty coefficient of negative slack variable */
148 SCIP_VAR* slacknegvar; /**< negative slack variable */
149 SCIP_CONS* couplingCons; /**< coupling contraint (equation) */
151
152/** returns TRUE iff both keys are equal */
153static
155{ /*lint --e{715}*/
156 BLOCKINFO* binfo1;
157 BLOCKINFO* binfo2;
158
159 binfo1 = (BLOCKINFO*) key1;
160 binfo2 = (BLOCKINFO*) key2;
161
162 if( binfo1->block != binfo2->block || binfo1->otherblock != binfo2->otherblock ||
163 binfo1->linkvaridx != binfo2->linkvaridx )
164 return FALSE;
165
166 return TRUE;
167}
168
169/** returns the hash value of the key */
170static
171SCIP_DECL_HASHKEYVAL(indexesHashval)
172{ /*lint --e{715}*/
173 BLOCKINFO* binfo;
174 binfo = (BLOCKINFO*) key;
175
176 return SCIPhashFour(SCIPrealHashCode((double)binfo->block), SCIPrealHashCode((double)binfo->otherblock),
177 SCIPrealHashCode((double)binfo->linkvaridx), SCIPrealHashCode((double)binfo->linkvaridx));
178}
179
180/** primal heuristic data */
181struct SCIP_HeurData
182{
183 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in all subproblems */
184 SCIP_Longint minnodes; /**< minimum number of nodes to regard in one subproblem */
185 int admiterations; /**< maximal number of ADM iterations in each penalty loop */
186 int penaltyiterations; /**< maximal number of penalty iterations */
187 int timing; /**< should the heuristic run before or after the processing of the node?
188 (0: before, 1: after, 2: both) */
189 SCIP_Real nodefac; /**< factor to control nodelimits of subproblems */
190 SCIP_Real gap; /**< mipgap at start */
191 SCIP_Bool reoptimize; /**< should the problem get reoptimized with the original objective function? */
192 SCIP_Bool scaling; /**< enable sigmoid rescaling of penalty parameters */
193 SCIP_Bool assignlinking; /**< should linking constraints be assigned? */
194 SCIP_Bool original; /**< should the original problem be used? */
195};
196
197/*
198 * Local methods
199 */
200
201/** initializes one block */
202static
204 PROBLEM* problem /**< problem structure */
205 )
206{
207 BLOCK* block;
208
209 assert(problem != NULL);
210 assert(problem->scip != NULL);
211
212 block = &problem->blocks[problem->nblocks];
213
214 block->problem = problem;
215 block->subscip = NULL;
216 block->subvars = NULL;
217 block->nsubvars = 0;
218 block->number = problem->nblocks;
219 block->slackspos = NULL;
220 block->slacksneg = NULL;
221 block->couplingcons = NULL;
222 block->ncoupling = 0;
223 block->size = 0;
224
225 ++problem->nblocks;
226
227 return SCIP_OKAY;
228}
229
230/** frees component structure */
231static
233 BLOCK* block /**< block structure */
234 )
235{
236 assert(block != NULL);
237
238 block->ncoupling = 0;
239
240 if( block->subvars != NULL )
241 {
242 SCIPfreeBufferArray(block->problem->scip, &(block->subvars));
243 }
244
245 if( block->subscip != NULL )
246 {
247 SCIP_CALL( SCIPfree(&block->subscip) );
248 }
249
250 return SCIP_OKAY;
251}
252
253/** initializes subproblem structure */
254static
256 SCIP* scip, /**< SCIP data structure */
257 PROBLEM** problem, /**< pointer to problem structure */
258 int nblocks /**< number of blocks */
259 )
260{
261 char name[SCIP_MAXSTRLEN];
262
263 assert(scip != NULL);
264 assert(problem != NULL);
265
267 assert(*problem != NULL);
268
269 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPgetProbName(scip));
270
271 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*problem)->name, name, strlen(name) + 1) );
272
273 SCIPdebugMessage("initialized problem <%s>\n", (*problem)->name);
274
275 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*problem)->blocks, nblocks) );
276
277 (*problem)->scip = scip;
278 (*problem)->nblocks = 0;
279
280 return SCIP_OKAY;
281}
282
283/** frees subproblem structure */
284static
286 PROBLEM** problem, /**< pointer to problem to free */
287 int nblocks /**< number of blocks in decomposition */
288 )
289{
290 SCIP* scip;
291 int c;
292
293 assert(problem != NULL);
294 assert(*problem != NULL);
295
296 scip = (*problem)->scip;
297 assert(scip != NULL);
298
299 /* free all blocks */
300 for( c = nblocks - 1; c >= 0; --c )
301 {
302 SCIP_CALL( freeBlock(&(*problem)->blocks[c]) );
303 }
304 if( (*problem)->blocks != NULL )
305 {
306 SCIPfreeBlockMemoryArray(scip, &(*problem)->blocks, nblocks);
307 }
308
309 /* free problem name */
310 SCIPfreeMemoryArray(scip, &(*problem)->name);
311
312 /* free PROBLEM struct and set the pointer to NULL */
313 SCIPfreeBlockMemory(scip, problem);
314 *problem = NULL;
315
316 return SCIP_OKAY;
317}
318
319/** creates a sub-SCIP for the given variables and constraints */
320static
322 SCIP* scip, /**< main SCIP data structure */
323 SCIP** subscip /**< pointer to store created sub-SCIP */
324 )
325{
326 SCIP_Real infvalue;
327
328 /* create a new SCIP instance */
329 SCIP_CALL( SCIPcreate(subscip) );
330
332
333 /* copy value for infinity */
334 SCIP_CALL( SCIPgetRealParam(scip, "numerics/infinity", &infvalue) );
335 SCIP_CALL( SCIPsetRealParam(*subscip, "numerics/infinity", infvalue) );
336
337 SCIP_CALL( SCIPcopyLimits(scip, *subscip) );
338
339 /* avoid recursive calls */
340 SCIP_CALL( SCIPsetSubscipsOff(*subscip, TRUE) );
341
342 /* disable cutting plane separation */
344
345 /* disable expensive presolving */
347
348 /* disable expensive techniques */
349 SCIP_CALL( SCIPsetIntParam(*subscip, "misc/usesymmetry", 0) );
350
351 /* do not abort subproblem on CTRL-C */
352 SCIP_CALL( SCIPsetBoolParam(*subscip, "misc/catchctrlc", FALSE) );
353
354#ifdef SCIP_DEBUG
355 /* for debugging, enable full output */
356 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 5) );
357 SCIP_CALL( SCIPsetIntParam(*subscip, "display/freq", 100000000) );
358#else
359 /* disable statistic timing inside sub SCIP and output to console */
360 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 0) );
361 SCIP_CALL( SCIPsetBoolParam(*subscip, "timing/statistictiming", FALSE) );
362#endif
363
364 return SCIP_OKAY;
365}
366
367/** copies the given constraints and the corresponding variables to the given sub-SCIP */
368static
370 SCIP* scip, /**< source SCIP */
371 SCIP* subscip, /**< target SCIP */
372 const char* name, /**< name for copied problem */
373 SCIP_CONS** conss, /**< constraints to copy */
374 SCIP_HASHMAP* varmap, /**< hashmap used for the copy process of variables */
375 SCIP_HASHMAP* consmap, /**< hashmap used for the copy process of constraints */
376 int nconss, /**< number of constraints to copy */
377 SCIP_Bool useorigprob, /**< do we use the original problem? */
378 SCIP_Bool* success /**< pointer to store whether copying was successful */
379 )
380{
381 SCIP_CONS* newcons;
382 int i;
383
384 assert(scip != NULL);
385 assert(subscip != NULL);
386 assert(conss != NULL);
387 assert(consmap != NULL);
388 assert(success != NULL);
389
390 *success = TRUE;
391 newcons = NULL;
392
393 /* create problem in sub-SCIP */
394 SCIP_CALL( SCIPcopyProb(scip, subscip, varmap, consmap, FALSE, name) );
395
396 /* copy constraints */
397 for( i = 0; i < nconss; ++i )
398 {
399 assert(conss[i] != NULL);
400
401 /* do not check this if we use the original problem
402 * Since constraints can be deleted etc. during presolving, these assertions would fail.
403 */
404 if( !useorigprob )
405 {
406 assert(!SCIPconsIsModifiable(conss[i]));
407 assert(SCIPconsIsActive(conss[i]));
408 assert(!SCIPconsIsDeleted(conss[i]));
409 }
410
411 /* copy the constraint */
412 SCIP_CALL( SCIPgetConsCopy(scip, subscip, conss[i], &newcons, SCIPconsGetHdlr(conss[i]), varmap, consmap, NULL,
415 SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]), FALSE, FALSE, success) );
416
417 /* abort if constraint was not successfully copied */
418 if( !(*success) || newcons == NULL)
419 return SCIP_OKAY;
420
421 SCIP_CALL( SCIPaddCons(subscip, newcons) );
422 SCIP_CALL( SCIPreleaseCons(subscip, &newcons) );
423 }
424
425 return SCIP_OKAY;
426}
427
428/** creates the subscip for a given block */
429static
431 BLOCK* block, /**< block structure */
432 SCIP_HASHMAP* varmap, /**< variable hashmap used to improve performance */
433 SCIP_HASHMAP* consmap, /**< constraint hashmap used to improve performance */
434 SCIP_CONS** conss, /**< constraints contained in this block */
435 int nconss, /**< number of constraints contained in this block */
436 SCIP_Bool useorigprob, /**< do we use the original problem? */
437 SCIP_Bool* success /**< pointer to store whether the copying process was successful */
438 )
439{
440 char name[SCIP_MAXSTRLEN];
441 PROBLEM* problem;
442 SCIP* scip;
443 SCIP_VAR** subscipvars;
444 int nsubscipvars;
445 int i;
446
447 assert(block != NULL);
448 assert(varmap != NULL);
449 assert(consmap != NULL);
450 assert(conss != NULL);
451 assert(success != NULL);
452
453 problem = block->problem;
454 assert(problem != NULL);
455
456 scip = problem->scip;
457 assert(scip != NULL);
458
459 (*success) = TRUE;
460
461 SCIP_CALL( createSubscip(scip, &block->subscip) );
462
463 if( block->subscip != NULL )
464 {
465 /* get name of the original problem and add "comp_nr" */
466 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", problem->name, block->number);
467
468 SCIP_CALL( copyToSubscip(scip, block->subscip, name, conss, varmap, consmap, nconss, useorigprob, success) );
469
470 if( !(*success) )
471 {
472 SCIP_CALL( SCIPfree(&block->subscip) );
473 block->subscip = NULL;
474 }
475 else
476 {
477 /* save variables of subscip (without slack variables) */
478 nsubscipvars = SCIPgetNOrigVars(block->subscip);
479 subscipvars = SCIPgetOrigVars(block->subscip);
480 SCIP_CALL( SCIPallocBufferArray(scip, &(block->subvars), nsubscipvars) );
481 block->nsubvars = nsubscipvars;
482 for( i = 0; i < nsubscipvars; i++ )
483 block->subvars[i] = subscipvars[i];
484
485 /* calculate size of sub-SCIP with focus on the number of integer variables
486 * we use this value to determine the nodelimit
487 */
490 }
491 }
492 else
493 (*success) = FALSE;
494
495 SCIPdebugMsg(scip, "created subscip of block %d\n", block->number);
496
497 return SCIP_OKAY;
498}
499
500/** creates problem structure and split it into blocks */
501static
503 SCIP* scip, /**< SCIP data structure */
504 SCIP_CONS** sortedconss, /**< array of (checked) constraints sorted by blocks */
505 int nconss, /**< number of constraints */
506 int* consssize, /**< number of constraints per block (and border at index 0) */
507 int nblocks, /**< number of blocks */
508 PROBLEM** problem, /**< pointer to store problem structure */
509 SCIP_Bool useorigprob, /**< do we use the original problem? */
510 SCIP_Bool* success /**< pointer to store whether the process was successful */
511 )
512{
513 BLOCK* block;
514 SCIP_HASHMAP* varmap;
515 SCIP_HASHMAP* consmap;
516 SCIP_CONS** blockconss;
517 int nhandledconss;
518 int nblockconss;
519 int b;
520
521 (*success) = TRUE;
522
523 /* init subproblem data structure */
524 SCIP_CALL( initProblem(scip, problem, nblocks) );
525 assert((*problem)->blocks != NULL);
526
527 /* hashmap mapping from original constraints to constraints in the sub-SCIPs (for performance reasons) */
528 SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), nconss) );
529
530 for( b = 0; b < nblocks; b++ )
531 {
532 SCIP_CALL( initBlock(*problem) );
533 }
534
535 /* loop over all blocks and create subscips */
536 nhandledconss = 0;
537 for( b = 0; b < nblocks; b++ )
538 {
539 block = &(*problem)->blocks[b];
540
542
543 /* get block constraints */
544 blockconss = &(sortedconss[nhandledconss]);
545 nblockconss = consssize[b + 1];
546
547 /* build subscip for block */
548 SCIP_CALL( blockCreateSubscip(block, varmap, consmap, blockconss, nblockconss, useorigprob, success) );
549
550 SCIPhashmapFree(&varmap);
551 nhandledconss += nblockconss;
552
553 if( !(*success) )
554 break;
555 }
556
557 SCIPhashmapFree(&consmap);
558
559 if( !(*success) )
560 {
561 /* free subproblem data structure since not all blocks could be copied */
562 SCIP_CALL( freeProblem(problem, nblocks) );
563 }
564
565 return SCIP_OKAY;
566}
567
568/** copies labels to newdecomp and assigns linking constraints if possible*/
569static
571 SCIP* scip, /**< SCIP data structure */
572 SCIP_DECOMP* newdecomp, /**< decomposition with (partially) assigned linking constraints */
573 SCIP_VAR** vars, /**< array of variables */
574 SCIP_CONS** sortedconss, /**< sorted array of constraints */
575 int* varlabels, /**< array of variable labels */
576 int* conslabels, /**< sorted array of constraint labels */
577 int nvars, /**< number of variables */
578 int nconss, /**< number of constraints */
579 int nlinkconss /**< number of linking constraints */
580 )
581{
582 assert(scip != NULL);
583 assert(vars != NULL);
584 assert(sortedconss != NULL);
585 assert(varlabels != NULL);
586 assert(conslabels != NULL);
587
588 /* copy the labels */
589 SCIP_CALL( SCIPdecompSetVarsLabels(newdecomp, vars, varlabels, nvars) );
590 SCIP_CALL( SCIPdecompSetConsLabels(newdecomp, sortedconss, conslabels, nconss) );
591
592 SCIPdebugMsg(scip, "try to assign %d linking constraints\n", nlinkconss);
593
594 /* reassign linking constraints */
595 SCIP_CALL( SCIPassignDecompLinkConss(scip, newdecomp, &sortedconss[0], nlinkconss, NULL) );
596
597 SCIP_CALL( SCIPcomputeDecompVarsLabels(scip, newdecomp, sortedconss, nconss) );
598
600
601 SCIPdecompGetConsLabels(newdecomp, sortedconss, conslabels, nconss);
602 SCIPdecompGetVarsLabels(newdecomp, vars, varlabels, nvars);
603
604 SCIPsortIntPtr(conslabels, (void**)sortedconss, nconss);
605
606 return SCIP_OKAY;
607}
608
609/** computes feasible solution from last stored solution of the block*/
610static
612 SCIP* subscip, /**< SCIP data structure */
613 BLOCK* block /**< block structure*/
614 )
615{
616 SCIP_SOL** sols;
617 SCIP_SOL* sol; /* solution of block that will be repaired */
618 SCIP_SOL* newsol;
619 SCIP_VAR** blockvars;
620 SCIP_VAR** consvars;
621 SCIP_Real* blockvals;
622 int nsols;
623 int nvars;
624 int c;
625 SCIP_Bool success;
626
627 assert(subscip != NULL);
628 assert(block != NULL);
629
630 nsols = SCIPgetNSols(subscip);
631
632 /* no solution in solution candidate storage found */
633 if( nsols == 0 )
634 return SCIP_OKAY;
635
636 SCIP_CALL( SCIPallocBufferArray(subscip, &consvars, COUPLINGSIZE) );
637
638 sols = SCIPgetSols(subscip);
639 sol = sols[nsols - 1];
640
641 /* copy the solution */
642 nvars = SCIPgetNVars(subscip);
643 blockvars = SCIPgetVars(subscip);
644 SCIP_CALL( SCIPallocBufferArray(subscip, &blockvals, nvars) );
645 SCIP_CALL( SCIPgetSolVals(subscip, sol, nvars, blockvars, blockvals) );
646 SCIP_CALL( SCIPcreateOrigSol(subscip, &newsol, NULL) );
647 SCIP_CALL( SCIPsetSolVals(subscip, newsol, nvars, blockvars, blockvals) );
648
649 /* correct each coupling constraint;
650 * orig_var + slackpos - slackneg == side
651 * adapt slack variables so that constraint is feasible */
652 for( c = 0; c < block->ncoupling; c++ )
653 {
654 SCIP_Real solval; /* old solution values of variables; [0] original variable, [1] slackpos, [2] slackneg */
655 SCIP_Real side; /* current right hand side */
656 SCIP_Real diff;
657
658 SCIP_CALL( SCIPgetConsVars(subscip, block->couplingcons[c], consvars, COUPLINGSIZE, &success) );
659 solval = SCIPgetSolVal(subscip, sol, consvars[0]);
660
661 side = SCIPgetRhsLinear(subscip, block->couplingcons[c]);
662 assert(SCIPisEQ(subscip, SCIPgetRhsLinear(subscip, block->couplingcons[c]), SCIPgetLhsLinear(subscip, block->couplingcons[c])));
663
664 diff = side - solval;
665
666 /* slackpos is strict positiv */
667 if( diff > 0 )
668 {
669 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], diff) );
670 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], 0.0) );
671 }
672 /* slackneg is strict positiv */
673 else if( diff < 0 )
674 {
675 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], -diff) );
676 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], 0.0) );
677 }
678 /* no slack variable necessary */
679 else
680 {
681 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], 0.0) );
682 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], 0.0) );
683 }
684 }
685
686 SCIPdebugMsg(subscip, "Try adding solution with objective value %.2f\n", SCIPgetSolOrigObj(subscip, newsol));
687 SCIP_CALL( SCIPaddSolFree(subscip, &newsol, &success) );
688
689 if( !success )
690 SCIPdebugMsg(subscip, "Correcting solution failed\n"); /* maybe not better than old solutions */
691 else
692 {
693 SCIPdebugMsg(subscip, "Correcting solution successful\n");
694 }
695
696 SCIPfreeBufferArray(subscip, &blockvals);
697 SCIPfreeBufferArray(subscip, &consvars);
698
699 return SCIP_OKAY;
700}
701
702/** reoptimizes the heuristic solution with original objective function
703 *
704 * Since the main algorithm of padm ignores the objective function, this method can be called to obtain better solutions.
705 * It copies the main scip, fixes the linking variables at the values of the already found solution
706 * and solves the new problem with small limits.
707 */
708static
710 SCIP* scip, /**< SCIP data structure */
711 SCIP_HEUR* heur, /**< pointer to heuristic*/
712 SCIP_SOL* sol, /**< heuristic solution */
713 SCIP_VAR** vars, /**< pointer to variables */
714 int nvars, /**< number of variables */
715 SCIP_VAR** linkvars, /**< pointer to linking variables */
716 int nlinkvars, /**< number of linking variables */
717 SCIP_SOL** newsol, /**< pointer to store improved solution */
718 SCIP_Bool* success /**< pointer to store whether reoptimization was successful */
719 )
720{
721 SCIP* scipcopy;
722 SCIP_SOL* startsol;
723 SCIP_HASHMAP* varmap;
724 SCIP_VAR** subvars;
725 SCIP_STATUS status;
726 SCIP_Real* linkvals;
727 SCIP_Real time;
728 int v;
729
730 assert(scip != NULL);
731 assert(heur != NULL);
732 assert(sol != NULL);
733 assert(vars != NULL);
734 assert(linkvars != NULL);
735
736 SCIP_CALL( SCIPallocBufferArray(scip, &linkvals, nlinkvars) );
738
739 SCIP_CALL( SCIPgetSolVals(scip, sol, nlinkvars, linkvars, linkvals) );
740
741 /* initializing the problem copy*/
742 SCIP_CALL( SCIPcreate(&scipcopy) );
743
744 /* - create the variable mapping hash map
745 * - create a problem copy of main SCIP
746 */
747 if( SCIPheurGetData(heur)->original )
748 {
750 SCIP_CALL( SCIPcopyOrigConsCompression(scip, scipcopy, varmap, NULL, "reopt_padm", linkvars, linkvals, nlinkvars,
751 FALSE, FALSE, TRUE, success) );
752 }
753 else
754 {
755 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scipcopy), SCIPgetNVars(scip)) );
756 SCIP_CALL( SCIPcopyConsCompression(scip, scipcopy, varmap, NULL, "reopt_padm", linkvars, linkvals, nlinkvars,
757 TRUE, FALSE, FALSE, TRUE, success) );
758 }
759 for( v = 0; v < nvars; v++ )
760 {
761 subvars[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
762 }
763
764 /* do not abort subproblem on CTRL-C */
765 SCIP_CALL( SCIPsetBoolParam(scipcopy, "misc/catchctrlc", FALSE) );
766
767 /* forbid recursive call of heuristics and separators solving sub-SCIPs */
768 SCIP_CALL( SCIPsetSubscipsOff(scipcopy, TRUE) );
769
770#ifdef SCIP_DEBUG
771 /* for debugging, enable full output */
772 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/verblevel", 5) );
773 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/freq", 100000000) );
774#else
775 /* disable statistic timing inside sub SCIP and output to console */
776 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/verblevel", 0) );
777 SCIP_CALL( SCIPsetBoolParam(scipcopy, "timing/statistictiming", FALSE) );
778#endif
779
780 /* disable cutting plane separation */
782
783 /* disable expensive presolving but enable components presolver */
785 SCIP_CALL( SCIPsetIntParam(scipcopy, "constraints/components/maxprerounds", 1) );
786 SCIP_CALL( SCIPsetLongintParam(scipcopy, "constraints/components/nodelimit", 0LL) );
787
788 /* disable expensive techniques */
789 SCIP_CALL( SCIPsetIntParam(scipcopy, "misc/usesymmetry", 0) );
790
791 /* speed up sub-SCIP by not checking dual LP feasibility */
792 SCIP_CALL( SCIPsetBoolParam(scipcopy, "lp/checkdualfeas", FALSE) );
793
794 /* add heuristic solution as start solution */
795 SCIP_CALL( SCIPtransformProb(scipcopy) );
796 *success = FALSE;
798 {
799 SCIP_CALL( SCIPcreateSol(scipcopy, &startsol, heur) );
800 for( v = 0; v < nvars; v++ )
801 {
802 SCIP_VAR* subvar;
803 subvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
804 if( subvar != NULL )
805 {
806 SCIP_CALL( SCIPsetSolVal(scipcopy, startsol, subvar, SCIPgetSolVal(scip, sol, vars[v])) );
807 }
808 }
809
810 SCIP_CALL( SCIPtrySolFree(scipcopy, &startsol, FALSE, FALSE, FALSE, FALSE, FALSE, success) );
811 if( *success )
812 SCIPdebugMsg(scip, "set start solution\n");
813 else
814 SCIPdebugMsg(scip, "start solution for reoptimizing is not feasible\n");
815 }
816
817 /* set limits; do not use more time than the heuristic has already used */
818 SCIP_CALL( SCIPcopyLimits(scip, scipcopy) );
819 SCIP_CALL( SCIPsetLongintParam(scipcopy, "limits/nodes", 1LL) );
820 SCIP_CALL( SCIPgetRealParam(scipcopy, "limits/time", &time) );
821 if( SCIPheurGetTime(heur) < time - 1.0 )
822 {
823 SCIP_CALL( SCIPsetRealParam(scipcopy, "limits/time", SCIPheurGetTime(heur) + 1.0) );
824 }
825 if( *success )
826 {
827 SCIP_CALL( SCIPsetIntParam(scipcopy, "limits/bestsol", 2) ); /* first solution is start solution */
828 }
829 else
830 {
831 SCIP_CALL( SCIPsetIntParam(scipcopy, "limits/bestsol", 1) );
832 }
833
834 /* reoptimize problem */
835 SCIP_CALL_ABORT( SCIPsolve(scipcopy) );
836 status = SCIPgetStatus(scipcopy);
837
838 /* copy solution to main scip */
839 if( status == SCIP_STATUS_BESTSOLLIMIT || status == SCIP_STATUS_OPTIMAL )
840 {
841 SCIP_SOL* solcopy;
842
843 solcopy = SCIPgetBestSol(scipcopy);
844 SCIP_CALL( SCIPtranslateSubSol(scip, scipcopy, solcopy, heur, subvars, newsol) );
845
846 SCIPdebugMsg(scip, "Objective value of reoptimized solution %.2f\n", SCIPgetSolOrigObj(scip, *newsol));
847 *success = TRUE;
848 }
849 else
850 {
851 *success = FALSE;
852 }
853
854 /* free data */
855 SCIPhashmapFree(&varmap);
856 SCIP_CALL( SCIPfree(&scipcopy) );
857 SCIPfreeBufferArray(scip, &subvars);
858 SCIPfreeBufferArray(scip, &linkvals);
859
860 return SCIP_OKAY;
861}
862
863/** rescales the penalty parameters
864 *
865 * A sigmoid function is a function with an "S"-shaped graph, e.g. S(x) = x/(1+|x|).
866 * In order to avoid numerical instabilities due to large penalty parameters we rescale them
867 * using the sigmoid function
868 * S(x) = (x - shift)/(flatness + |x - shift|) * (range/2) + offset.
869 * The parameters are mapped into the more controllable interval [lowestslack, range + lowestslack].
870 */
871static
873 PROBLEM* problem, /**< block structure */
874 SET* linkvartoblocks, /**< linking variable to blocks set */
875 SET* blocktolinkvars, /**< block to linking variable set */
876 SCIP_HASHTABLE* htable, /**< hashtable containing blockinfo*/
877 SCIP_Real maxpenalty /**< maximum penalty parameter */
878 )
879{
880 SCIP_Real shift;
881 SCIP_Real lowestslack;
882 SCIP_Real range;
883 SCIP_Real offset;
884 SCIP_Real flatness;
885 int b;
886 int i;
887 int k;
888
889 shift = maxpenalty / 2.0;
890 lowestslack = 0.1;
891 range = 10.0;
892 offset = range / 2.0 + lowestslack;
893 flatness = maxpenalty / 10.0;
894
895 for( b = 0; b < problem->nblocks; b++ )
896 {
897 for( i = 0; i < blocktolinkvars[b].size; i++ )
898 {
899 int linkvaridx;
900 linkvaridx = blocktolinkvars[b].indexes[i];
901
902 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
903 {
904 int b2;
905 b2 = linkvartoblocks[linkvaridx].indexes[k];
906
907 if( b2 != b )
908 {
909 BLOCKINFO binfo;
910 BLOCKINFO* binfoout;
911 SCIP_Real oldcoeff;
912
913 binfo.block = b;
914 binfo.otherblock = b2;
915 binfo.linkvaridx = linkvaridx;
916 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
917 assert(binfoout != NULL);
918
919 /* scale coefficient of positive slack variable */
920 oldcoeff = binfoout->slackposobjcoeff;
921 binfoout->slackposobjcoeff = ((oldcoeff - shift) / (flatness + REALABS(oldcoeff - shift))) * range / 2.0 + offset;
922
923 /* scale coefficient of negative slack variable */
924 oldcoeff = binfoout->slacknegobjcoeff;
925 binfoout->slacknegobjcoeff = ((oldcoeff - shift) / (flatness + REALABS(oldcoeff - shift))) * range / 2.0 + offset;
926 }
927 }
928 }
929 }
930 return SCIP_OKAY;
931}
932
933/** returns the available time limit that is left */
934static
936 SCIP* scip, /**< SCIP data structure */
937 SCIP_Real* time /**< pointer to store remaining time */
938 )
939{
940 SCIP_Real timelim;
941 SCIP_Real solvingtime;
942
943 assert(scip != NULL);
944
945 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelim) );
946 solvingtime = SCIPgetSolvingTime(scip);
947
948 if( !SCIPisInfinity(scip, timelim) )
949 *time = MAX(0.0, (timelim - solvingtime));
950 else
951 *time = SCIPinfinity(scip);
952
953 return SCIP_OKAY;
954}
955
956/*
957 * Callback methods of primal heuristic
958 */
959
960/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
961static
963{ /*lint --e{715}*/
964 assert(scip != NULL);
965 assert(heur != NULL);
966
968
969 /* call inclusion method of primal heuristic */
971
972 return SCIP_OKAY;
973}
974
975
976/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
977static
979{ /*lint --e{715}*/
981
983 SCIPheurSetData(heur, NULL);
984
985 assert(heurdata != NULL);
986
988
989 return SCIP_OKAY;
990}
991
992
993/** execution method of primal heuristic */
994static SCIP_DECL_HEUREXEC(heurExecPADM)
995{ /*lint --e{715}*/
996 char name[SCIP_MAXSTRLEN];
997 char info[SCIP_MAXSTRLEN];
999 PROBLEM* problem;
1000 SCIP_DECOMP** alldecomps;
1001 SCIP_DECOMP* decomp;
1002 SCIP_DECOMP* assigneddecomp;
1003 SCIP_VAR** vars;
1004 SCIP_VAR** linkvars;
1005 SCIP_VAR** tmpcouplingvars;
1006 SCIP_CONS** conss;
1007 SCIP_CONS** sortedconss;
1008 SET* linkvartoblocks;
1009 SET* blocktolinkvars;
1010 BLOCKINFO* blockinfolist;
1011 SCIP_HASHTABLE* htable;
1012 int* varlabels;
1013 int* conslabels;
1014 int* consssize;
1015 int* alllinkvartoblocks; /* for efficient memory allocation */
1016 SCIP_Bool* varonlyobj;
1017 SCIP_Real* tmpcouplingcoef;
1018 SCIP_Real gap;
1019 SCIP_Real maxpenalty;
1020 SCIP_Real slackthreshold;
1021 SCIP_Real memory; /* in MB */
1022 SCIP_Real timeleft;
1023 SCIP_STATUS status;
1024 SCIP_Bool solutionsdiffer;
1025 SCIP_Bool solved;
1026 SCIP_Bool doscaling;
1027 SCIP_Bool istimeleft;
1028 SCIP_Bool success;
1029 SCIP_Bool avoidmemout;
1030 SCIP_Bool disablemeasures;
1031 int maxgraphedge;
1032 int ndecomps;
1033 int nconss;
1034 int nvars;
1035 int nblocks;
1036 int numlinkvars;
1037 int nentries;
1038 int aiter;
1039 int piter;
1040 int increasedslacks;
1041 int blockinfolistfill;
1042 SCIP_Longint nodesleft;
1043 int i;
1044 int b;
1045 int k;
1046 int j;
1047
1048 assert(scip != NULL);
1049 assert(heur != NULL);
1050 assert(result != NULL);
1051
1052 heurdata = SCIPheurGetData(heur);
1053 assert(heurdata != NULL);
1054
1056
1057 problem = NULL;
1058 assigneddecomp = NULL;
1059 sortedconss = NULL;
1060 varlabels = NULL;
1061 conslabels = NULL;
1062 consssize = NULL;
1063 alllinkvartoblocks = NULL;
1064 linkvars = NULL;
1065 linkvartoblocks = NULL;
1066 blocktolinkvars = NULL;
1067 tmpcouplingvars = NULL;
1068 tmpcouplingcoef = NULL;
1069 varonlyobj = NULL;
1070 blockinfolist = NULL;
1071 htable = NULL;
1072
1073 nodesleft = heurdata->maxnodes;
1074 gap = heurdata->gap;
1075
1076 if( (heurtiming & SCIP_HEURTIMING_BEFORENODE) && heurdata->timing !=1 )
1077 {
1078 SCIPdebugMsg(scip, "Initialize padm heuristic before node\n");
1079 }
1080 else if( (heurtiming & SCIP_HEURTIMING_AFTERNODE) && heurdata->timing >=1 )
1081 {
1082 SCIPdebugMsg(scip, "Initialize padm heuristic after node\n");
1083 }
1084 else
1085 {
1086 return SCIP_OKAY;
1087 }
1088
1089#ifdef PADM_WRITE_PROBLEMS
1090 SCIP_CALL( SCIPwriteOrigProblem(scip, "orig_problem", NULL, FALSE) );
1091 SCIP_CALL( SCIPwriteTransProblem(scip, "trans_problem", NULL, FALSE) );
1092#endif
1093
1094 /* take original problem (This is only for testing and not recommended!) */
1095 if( heurdata->original )
1096 {
1097 /* multiaggregation of variables has to be switched off */
1098 if( !SCIPdoNotMultaggr(scip) )
1099 {
1100 SCIPwarningMessage(scip, "Heuristic %s does not support multiaggregation when the original problem is used.\nPlease turn multiaggregation off to use this feature.\n", HEUR_NAME);
1101 return SCIP_OKAY;
1102 }
1103
1104 SCIPgetDecomps(scip, &alldecomps, &ndecomps, TRUE);
1105 if( ndecomps == 0)
1106 return SCIP_OKAY;
1107
1108 /* it takes the first decomposition */
1109 decomp = alldecomps[0];
1110 SCIPdebugMsg(scip, "First original decomposition is selected\n");
1111 assert(decomp != NULL);
1112
1113 nconss = SCIPgetNOrigConss(scip);
1114 conss = SCIPgetOrigConss(scip);
1117 }
1118 /* take transformed problem */
1119 else
1120 {
1121 SCIPgetDecomps(scip, &alldecomps, &ndecomps, FALSE);
1122 if( ndecomps == 0)
1123 return SCIP_OKAY;
1124
1125 /* it takes the first decomposition */
1126 decomp = alldecomps[0];
1127 SCIPdebugMsg(scip, "First transformed decomposition is selected\n");
1128 assert(decomp != NULL);
1129
1130 nconss = SCIPgetNConss(scip);
1131 conss = SCIPgetConss(scip);
1134 }
1135
1136 nblocks = SCIPdecompGetNBlocks(decomp);
1137
1138 /* if problem has no constraints, no variables or less than two blocks, return */
1139 if( nconss == 0 || nvars == 0 || nblocks <= 1 )
1140 {
1141 SCIPdebugMsg(scip, "problem has no constraints, no variables or less than two blocks\n");
1142 goto TERMINATE;
1143 }
1144
1145 /* estimate required memory for all blocks and terminate if not enough memory is available */
1146 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memory) );
1147 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
1148 if( avoidmemout && (((SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip))/1048576.0) * nblocks >= memory) )
1149 {
1150 SCIPdebugMsg(scip, "The estimated memory usage for %d blocks is too large.\n", nblocks);
1151 goto TERMINATE;
1152 }
1153
1154 /* we do not need the block decomposition graph and expensive measures of the decomposition statistics */
1155 SCIP_CALL( SCIPgetIntParam(scip, "decomposition/maxgraphedge", &maxgraphedge) );
1156 if( !SCIPisParamFixed(scip, "decomposition/maxgraphedge") )
1157 {
1158 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", 0) );
1159 }
1160 SCIP_CALL( SCIPgetBoolParam(scip, "decomposition/disablemeasures", &disablemeasures) );
1161 if( !SCIPisParamFixed(scip, "decomposition/disablemeasures") )
1162 {
1163 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", TRUE) );
1164 }
1165
1166 /* don't change problem by sorting constraints */
1167 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
1168
1169 SCIP_CALL( SCIPallocBufferArray(scip, &varlabels, nvars) );
1170 SCIP_CALL( SCIPallocBufferArray(scip, &conslabels, nconss) );
1171 SCIP_CALL( SCIPallocBufferArray(scip, &consssize, nblocks + 1) );
1172
1173 SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
1174 SCIPdecompGetVarsLabels(decomp, vars, varlabels, nvars);
1175
1176 /* sort constraints by blocks */
1177 SCIPsortIntPtr(conslabels, (void**)sortedconss, nconss);
1178
1179 /* try to assign linking constraints */
1180 if( heurdata->assignlinking && conslabels[0] == SCIP_DECOMP_LINKCONS )
1181 {
1182 /* create new decomposition; don't change the decompositions in the decompstore */
1183 SCIP_CALL( SCIPcreateDecomp(scip, &assigneddecomp, nblocks, heurdata->original, SCIPdecompUseBendersLabels(decomp)) );
1184
1185 SCIP_CALL( assignLinking(scip, assigneddecomp, vars, sortedconss, varlabels, conslabels, nvars, nconss, SCIPdecompGetNBorderConss(decomp)) );
1186 assert(SCIPdecompGetNBlocks(decomp) >= SCIPdecompGetNBlocks(assigneddecomp));
1187 decomp = assigneddecomp;
1188
1189 /* number of blocks can get smaller (since assigning constraints can lead to empty blocks) */
1190 nblocks = SCIPdecompGetNBlocks(decomp);
1191 }
1192 else
1193 {
1194 /* The decomposition statistics were computed during transformation of the decomposition store.
1195 * Since propagators can have changed the number of constraints/variables,
1196 * the statistics are no longer up-to-date and have to be recomputed.
1197 */
1199 nblocks = SCIPdecompGetNBlocks(decomp);
1200 }
1201
1202 /* reset parameters */
1203 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", maxgraphedge) );
1204 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", disablemeasures) );
1205
1206 /* @note the terms 'linking' and 'border' (constraints/variables) are used interchangeably */
1207
1208 if( SCIPdecompGetNBorderConss(decomp) != 0 )
1209 {
1210 SCIPdebugMsg(scip, "No support for linking contraints\n");
1211 goto TERMINATE;
1212 }
1213
1214 /* get number of linking variables */
1215 numlinkvars = SCIPdecompGetNBorderVars(decomp);
1216 SCIPdebugMsg(scip, "%d linking variables\n", numlinkvars);
1217
1218 if( numlinkvars == 0 )
1219 {
1220 SCIPdebugMsg(scip, "No linking variables\n");
1221 goto TERMINATE;
1222 }
1223
1225
1226 /* get for every block the number of constraints (first entry belongs to border) */
1227 SCIP_CALL( SCIPdecompGetConssSize(decomp, consssize, nblocks + 1) );
1228
1229 /* create blockproblems */
1230 SCIP_CALL( createAndSplitProblem(scip, sortedconss, nconss, consssize, nblocks, &problem, heurdata->original, &success) );
1231
1232 if( !success )
1233 {
1234 SCIPdebugMsg(scip, "Some subscips could not be created successfully.\n");
1235 goto TERMINATE;
1236 }
1237
1238 SCIP_CALL( SCIPallocBufferArray(scip, &linkvartoblocks, numlinkvars) );
1239 SCIP_CALL( SCIPallocBufferArray(scip, &blocktolinkvars, problem->nblocks) );
1240
1241 /* set pointer to NULL for safe memory release */
1242 for( i = 0; i < numlinkvars; i++ )
1243 linkvartoblocks[i].indexes = NULL;
1244 for( i = 0; i < problem->nblocks; i++ )
1245 blocktolinkvars[i].indexes = NULL;
1246
1247 /* extract linking variables and init linking variable to blocks set */
1248 SCIP_CALL( SCIPallocBufferArray(scip, &alllinkvartoblocks, problem->nblocks * numlinkvars) );
1249 SCIP_CALL( SCIPallocBufferArray(scip, &linkvars, numlinkvars) );
1250
1251 b = 0;
1252 for( i = 0; i < nvars; i++ )
1253 {
1254 if( varlabels[i] == SCIP_DECOMP_LINKVAR )
1255 {
1256 linkvars[b] = vars[i];
1257 linkvartoblocks[b].indexes = &alllinkvartoblocks[b * problem->nblocks];
1258 linkvartoblocks[b].size = 0;
1259 b++;
1260 }
1261 }
1262
1263 /* fill linking variable to blocks set */
1264 for( i = 0; i < numlinkvars; i++ )
1265 {
1266 SCIP_VAR* var;
1267 const char* vname;
1268
1269 assert(linkvartoblocks[i].indexes != NULL);
1270
1271 vname = SCIPvarGetName(linkvars[i]);
1272 k = 0;
1273 for( b = 0; b < problem->nblocks; b++ )
1274 {
1275 var = SCIPfindVar((problem->blocks[b]).subscip, vname);
1276 if( var != NULL )
1277 {
1278 linkvartoblocks[i].indexes[k] = b;
1279 linkvartoblocks[i].size = k + 1;
1280 k++;
1281 }
1282 }
1283 }
1284
1285 /* check whether there is enough time left */
1286 SCIP_CALL( getTimeLeft(scip, &timeleft) );
1287 if( timeleft <= 0 )
1288 {
1289 SCIPdebugMsg(scip, "no time left\n");
1290 goto TERMINATE;
1291 }
1292
1293 /* init varonlyobj; true if variable is only part of the objective function */
1294 SCIP_CALL( SCIPallocBufferArray(scip, &varonlyobj, numlinkvars) );
1295 for( i = 0; i < numlinkvars; ++i)
1296 varonlyobj[i] = TRUE;
1297
1298 /* init and fill block to linking variables set */
1299 for( b = 0; b < problem->nblocks; b++ )
1300 {
1301 SCIP_CALL( SCIPallocBufferArray(scip, &(blocktolinkvars[b].indexes), numlinkvars) );
1302 blocktolinkvars[b].size = 0;
1303
1304 k = 0;
1305 for( i = 0; i < numlinkvars; i++ )
1306 {
1307 SCIP_VAR* var;
1308 const char* vname;
1309
1310 vname = SCIPvarGetName(linkvars[i]);
1311 var = SCIPfindVar((problem->blocks[b]).subscip, vname);
1312 if( var != NULL )
1313 {
1314 varonlyobj[i] = FALSE;
1315 blocktolinkvars[b].indexes[k] = i;
1316 blocktolinkvars[b].size = k + 1;
1317 k++;
1318 }
1319 }
1320 }
1321
1322 /* init arrays for slack variables and coupling constraints */
1323 for( b = 0; b < problem->nblocks; b++ )
1324 {
1325 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).slackspos), blocktolinkvars[b].size * (nblocks - 1)) );
1326 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).slacksneg), blocktolinkvars[b].size * (nblocks - 1)) );
1327 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).couplingcons), blocktolinkvars[b].size * (nblocks - 1)) );
1328 }
1329
1330 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcouplingvars, COUPLINGSIZE) );
1331 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcouplingcoef, COUPLINGSIZE) );
1332 tmpcouplingcoef[0] = 1.0;
1333 tmpcouplingcoef[1] = 1.0;
1334 tmpcouplingcoef[2] = -1.0;
1335
1336 /* count hashtable entries */
1337 nentries = 0;
1338 for( b = 0; b < problem->nblocks; b++ )
1339 {
1340 for( i = 0; i < blocktolinkvars[b].size; i++ )
1341 {
1342 int linkvaridx = blocktolinkvars[b].indexes[i];
1343 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1344 {
1345 if( linkvartoblocks[linkvaridx].indexes[k] != b )
1346 nentries++;
1347 }
1348 }
1349 }
1350
1351 SCIP_CALL( SCIPallocBufferArray(scip, &blockinfolist, nentries) );
1352 SCIP_CALL( SCIPhashtableCreate(&htable, SCIPblkmem(scip), 1, SCIPhashGetKeyStandard, indexesEqual, indexesHashval, (void*) scip) );
1353 blockinfolistfill = 0;
1354
1355 /* extend submips */
1356 SCIPdebugMsg(scip, "Extending %d block models\n", problem->nblocks);
1357 for( b = 0; b < problem->nblocks; b++ )
1358 {
1359 SCIP_VAR** blockvars;
1360 int nblockvars;
1361
1362 blockvars = SCIPgetVars((problem->blocks[b]).subscip);
1363 nblockvars = SCIPgetNVars((problem->blocks[b]).subscip);
1364
1365 /* set objective function of each block to zero */
1366 for( i = 0; i < nblockvars; i++ )
1367 {
1368 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, blockvars[i], 0.0) );
1369 }
1370
1371 /* add two slack variables for each linking variable in block */
1372 for( i = 0; i < blocktolinkvars[b].size; i++ )
1373 {
1374 int linkvaridx;
1375 linkvaridx = blocktolinkvars[b].indexes[i];
1376
1377 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1378 {
1379 int b2;
1380 b2 = linkvartoblocks[linkvaridx].indexes[k];
1381
1382 /* handle different blocks with common linking variable */
1383 if( b2 != b )
1384 {
1385 BLOCKINFO* binfo;
1386 binfo = &blockinfolist[blockinfolistfill];
1387 blockinfolistfill++;
1388 binfo->block = b;
1389 binfo->otherblock = b2;
1390 binfo->linkvaridx = linkvaridx;
1391 binfo->linkvar = SCIPfindVar((problem->blocks[b]).subscip, SCIPvarGetName(linkvars[linkvaridx]));
1392 j = (problem->blocks[b]).ncoupling;
1393
1394 /* create positive slack variable */
1395 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_slackpos_block_%d", SCIPvarGetName(linkvars[linkvaridx]), b2);
1396 (problem->blocks[b]).slackspos[j] = NULL;
1397 SCIP_CALL( SCIPcreateVarBasic((problem->blocks[b]).subscip,
1398 &((problem->blocks[b]).slackspos[j]), name,
1400 SCIP_CALL( SCIPaddVar((problem->blocks[b]).subscip, (problem->blocks[b]).slackspos[j]) );
1401 assert((problem->blocks[b]).slackspos[j] != NULL);
1402 binfo->slackposobjcoeff = 1.0;
1403 binfo->slackposvar = (problem->blocks[b]).slackspos[j];
1404
1405 /* create negative slack variable */
1406 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_slackneg_block_%d", SCIPvarGetName(linkvars[linkvaridx]), b2);
1407 (problem->blocks[b]).slacksneg[j] = NULL;
1408 SCIP_CALL( SCIPcreateVarBasic((problem->blocks[b]).subscip,
1409 &((problem->blocks[b]).slacksneg[j]), name,
1411 SCIP_CALL( SCIPaddVar((problem->blocks[b]).subscip, (problem->blocks[b]).slacksneg[j]) );
1412 assert((problem->blocks[b]).slacksneg[j] != NULL);
1413 binfo->slacknegobjcoeff = 1.0;
1414 binfo->slacknegvar = (problem->blocks[b]).slacksneg[j];
1415
1416 /* fill variables for linking constraint */
1417 tmpcouplingvars[0] = binfo->linkvar;
1418 tmpcouplingvars[1] = binfo->slackposvar;
1419 tmpcouplingvars[2] = binfo->slacknegvar;
1420
1421 /* create linking constraint */
1422 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_coupling_block_%d",
1423 SCIPvarGetName(linkvars[linkvaridx]), b2);
1424 (problem->blocks[b]).couplingcons[j] = NULL;
1425
1426 /* create linking constraint with initial side equal to zero (or lower bound of linking variable) */
1427 if( heurtiming & SCIP_HEURTIMING_BEFORENODE )
1428 {
1429 SCIP_Real initval;
1430 SCIP_Real lb;
1431
1432 lb = SCIPvarGetLbOriginal(binfo->linkvar);
1433 initval = MAX(lb, 0.0);
1434
1435 SCIP_CALL( SCIPcreateConsBasicLinear((problem->blocks[b]).subscip, &((problem->blocks[b]).couplingcons[j]),
1436 name, COUPLINGSIZE, tmpcouplingvars, tmpcouplingcoef, initval, initval) );
1437
1438 /* set initial value of linking variable */
1439 binfo->linkvarval = initval;
1440 }
1441
1442 /* create linking constraint with initial side equal to LP solution (rounded if variable is integer) */
1443 if( heurtiming & SCIP_HEURTIMING_AFTERNODE )
1444 {
1445 SCIP_Real initval;
1446
1447 initval = SCIPvarGetLPSol(linkvars[linkvaridx]);
1448 if( SCIPvarIsIntegral(binfo->linkvar) )
1449 initval = SCIPround(scip, initval);
1450
1451 SCIP_CALL( SCIPcreateConsBasicLinear((problem->blocks[b]).subscip, &((problem->blocks[b]).couplingcons[j]),
1452 name, COUPLINGSIZE, tmpcouplingvars, tmpcouplingcoef, initval, initval) );
1453
1454 /* set initial value of linking variable */
1455 binfo->linkvarval = initval;
1456 }
1457
1458 SCIP_CALL( SCIPaddCons((problem->blocks[b]).subscip, (problem->blocks[b]).couplingcons[j]) );
1459 assert((problem->blocks[b]).couplingcons[j] != NULL);
1460 binfo->couplingCons = (problem->blocks[b]).couplingcons[j];
1461
1462 (problem->blocks[b]).ncoupling++;
1463
1464 /* feed hashtable */
1465 SCIP_CALL( SCIPhashtableSafeInsert(htable, (void*) binfo) );
1466 }
1467 }
1468 }
1469 }
1470 assert(nentries == SCIPhashtableGetNElements(htable));
1471
1472#ifdef PADM_WRITE_PROBLEMS
1473 /* write extended submips */
1474 for( b = 0; b < problem->nblocks; b++ )
1475 {
1476 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "extended_block_%d.lp", b);
1477 SCIP_CALL( SCIPwriteOrigProblem((problem->blocks[b]).subscip, name, NULL, FALSE) );
1478 }
1479#endif
1480
1481 /* determine threshold for penalty coefficients via maximum norm */
1482 slackthreshold = SCIP_REAL_MIN;
1483 for( i = 0; i < nvars; i++ )
1484 {
1485 SCIP_Real obj;
1486
1488 if( obj > slackthreshold )
1489 slackthreshold = obj;
1490 }
1491
1492 /* ------------------------------------------------------------------------------------------------- */
1493
1494 /* check whether there is enough time left */
1495 SCIP_CALL( getTimeLeft(scip, &timeleft) );
1496 if( timeleft <= 0 )
1497 {
1498 SCIPdebugMsg(scip, "no time left\n");
1499 goto TERMINATE;
1500 }
1501
1502 SCIPdebugMsg(scip, "Starting iterations\n");
1503 SCIPdebugMsg(scip, "PIt\tADMIt\tSlacks\tInfo\n");
1504
1505 piter = 0;
1506 increasedslacks = 0;
1507 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "-");
1508 solved = FALSE;
1509 istimeleft = TRUE;
1510
1511 /* Penalty loop */
1512 while( !solved && piter < heurdata->penaltyiterations && istimeleft )
1513 {
1514 piter++;
1515 solutionsdiffer = TRUE;
1516 aiter = 0;
1517
1518 /* Alternating direction method loop */
1519 while( solutionsdiffer && aiter < heurdata->admiterations && istimeleft )
1520 {
1521 aiter++;
1522 solutionsdiffer = FALSE;
1523 SCIPdebugMsg(scip, "%d\t%d\t%d\t%s\n", piter, aiter, increasedslacks, info);
1524
1525 /* Loop through the blocks and solve each sub-SCIP, potentially multiple times */
1526 for( b = 0; b < problem->nblocks; b++ )
1527 {
1528 for( i = 0; i < blocktolinkvars[b].size; i++ )
1529 {
1530 int linkvaridx;
1531 linkvaridx = blocktolinkvars[b].indexes[i];
1532
1533 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1534 {
1535 int b2;
1536 b2 = linkvartoblocks[linkvaridx].indexes[k];
1537
1538 if( b2 != b )
1539 {
1540 BLOCKINFO binfo;
1541 BLOCKINFO* binfoout;
1542 BLOCKINFO binfo2;
1543 BLOCKINFO* binfo2out;
1544
1545 SCIP_CONS* couplingcons;
1546 SCIP_Real newrhs;
1547
1548 binfo.block = b;
1549 binfo.otherblock = b2;
1550 binfo.linkvaridx = linkvaridx;
1551
1552 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void *)&binfo);
1553 assert(binfoout != NULL);
1554 couplingcons = binfoout->couplingCons;
1555
1556 /* interchange blocks b and b2 for getting new right hand side */
1557 binfo2.block = b2;
1558 binfo2.otherblock = b;
1559 binfo2.linkvaridx = linkvaridx;
1560 binfo2out = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo2);
1561 assert(binfo2out != NULL);
1562 newrhs = binfo2out->linkvarval;
1563
1564 /* change side of coupling constraint equation with linking variable value of the other block */
1565 SCIP_CALL( SCIPchgLhsLinear((problem->blocks[b]).subscip, couplingcons, newrhs) );
1566 SCIP_CALL( SCIPchgRhsLinear((problem->blocks[b]).subscip, couplingcons, newrhs) );
1567
1568 /* change penalty coefficients of slack variables */
1569 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slackposvar, binfoout->slackposobjcoeff) );
1570 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slacknegvar, binfoout->slacknegobjcoeff) );
1571 }
1572 }
1573 }
1574
1575 /* increase slack penalty coeffs until each subproblem can be solved to optimality */
1576 do
1577 {
1579 int iteration;
1580
1581#ifdef PADM_WRITE_PROBLEMS
1582 SCIPdebugMsg(scip, "write subscip of block %d in piter=%d and aiter=%d\n", b, piter, aiter);
1583 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "blockproblem_%d_%d_%d.lp", b, piter, aiter);
1584 SCIP_CALL( SCIPwriteOrigProblem((problem->blocks[b]).subscip, name, NULL, FALSE) );
1585#endif
1586
1587 SCIP_CALL( SCIPsetRealParam((problem->blocks[b]).subscip, "limits/gap", gap) );
1588
1589 /* reuse old solution if available */
1590 SCIP_CALL( reuseSolution((problem->blocks[b]).subscip, &problem->blocks[b]) );
1591
1592 /* update time and memory limit of subproblem */
1593 SCIP_CALL( SCIPcopyLimits(scip, (problem->blocks[b]).subscip) );
1594
1595 /* stop if there are not enough nodes left */
1596 if( nodesleft < heurdata->minnodes )
1597 {
1598 SCIPdebugMsg(scip, "Node limit reached.\n");
1599 goto TERMINATE;
1600 }
1601
1602 /* update node limit of subproblem
1603 * in the first iterations we have a smaller node limit
1604 */
1605 iteration = ((piter - 1) * heurdata->admiterations) + aiter;
1606 nnodes = (SCIP_Longint)SCIPceil(scip, (problem->blocks[b]).size * nodesleft * ( 1 - pow(heurdata->nodefac, (double)iteration) ));
1607 nnodes = MAX( heurdata->minnodes, nnodes );
1608 SCIP_CALL( SCIPsetLongintParam((problem->blocks[b]).subscip, "limits/nodes", nnodes) );
1609
1610 /* solve block
1611 *
1612 * errors in solving the subproblem should not kill the overall solving process;
1613 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1614 */
1615 SCIP_CALL_ABORT( SCIPsolve((problem->blocks[b]).subscip) );
1616 status = SCIPgetStatus((problem->blocks[b]).subscip);
1617
1618 /* subtract used nodes from the total nodelimit */
1619 nodesleft -= (SCIP_Longint)SCIPceil(scip, SCIPgetNNodes((problem->blocks[b]).subscip) * (problem->blocks[b]).size);
1620
1621 /* check solution if one of the four cases occurs
1622 * - solution is optimal
1623 * - solution reached gaplimit
1624 * - node limit reached with at least one feasible solution
1625 * - time limit is reached but best solution needs no slack variables (no dual solution available)
1626 */
1627 if( status == SCIP_STATUS_OPTIMAL || status == SCIP_STATUS_GAPLIMIT ||
1628 (status == SCIP_STATUS_NODELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0) ||
1629 (status == SCIP_STATUS_TIMELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0 &&
1630 SCIPisEQ(scip, SCIPgetSolOrigObj((problem->blocks[b]).subscip, SCIPgetBestSol((problem->blocks[b]).subscip)), 0.0) ) )
1631 {
1632 SCIPdebugMsg(scip, "Block is optimal or reached gaplimit or nodelimit.\n");
1633
1634 if( status == SCIP_STATUS_TIMELIMIT )
1635 {
1636 SCIPdebugMsg(scip, "Block reached time limit with at least one feasible solution.\n");
1637 istimeleft = FALSE;
1638 }
1639
1640 for( i = 0; i < blocktolinkvars[b].size; i++ )
1641 {
1642 int linkvaridx;
1643 linkvaridx = blocktolinkvars[b].indexes[i];
1644
1645 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1646 {
1647 int b2;
1648 b2 = linkvartoblocks[linkvaridx].indexes[k];
1649
1650 if( b2 != b )
1651 {
1652 SCIP_SOL* sol;
1653 BLOCKINFO binfo;
1654 BLOCKINFO* binfoout;
1655 SCIP_VAR* var;
1656 SCIP_Real val;
1657
1658 binfo.block = b;
1659 binfo.otherblock = b2;
1660 binfo.linkvaridx = linkvaridx;
1661 binfoout = (BLOCKINFO *)SCIPhashtableRetrieve(htable, (void *)&binfo);
1662 assert(binfoout != NULL);
1663
1664 sol = SCIPgetBestSol((problem->blocks[b]).subscip);
1665 assert(sol != NULL);
1666 var = binfoout->linkvar;
1667 val = SCIPgetSolVal((problem->blocks[b]).subscip, sol, var);
1668
1669 if( !EPSEQ(binfoout->linkvarval, val, SCIP_DEFAULT_EPSILON) )
1670 solutionsdiffer = TRUE;
1671
1672 binfoout->linkvarval = val;
1673 }
1674 }
1675 }
1676 }
1677 else if( status == SCIP_STATUS_UNBOUNDED )
1678 {
1679 SCIPdebugMsg(scip, "Block is unbounded.\n");
1680 for( i = 0; i < blocktolinkvars[b].size; i++ )
1681 {
1682 int linkvaridx;
1683 linkvaridx = blocktolinkvars[b].indexes[i];
1684
1685 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1686 {
1687 int b2;
1688 b2 = linkvartoblocks[linkvaridx].indexes[k];
1689
1690 if( b2 != b )
1691 {
1692 BLOCKINFO binfo;
1693 BLOCKINFO* binfoout;
1694
1695 binfo.block = b;
1696 binfo.otherblock = b2;
1697 binfo.linkvaridx = linkvaridx;
1698 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
1699 assert(binfoout != NULL);
1700
1701 /* increase penalty coefficients to obtain a bounded subproblem */
1702 binfoout->slackposobjcoeff *= 10.0;
1703 binfoout->slacknegobjcoeff *= 10.0;
1704 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slackposvar, binfoout->slackposobjcoeff) );
1705 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slacknegvar, binfoout->slacknegobjcoeff) );
1706 }
1707 }
1708 }
1709 }
1710 else if( status == SCIP_STATUS_TIMELIMIT )
1711 {
1712 SCIPdebugMsg(scip, "Block reached time limit. No optimal solution available.\n");
1713 goto TERMINATE;
1714 }
1715 else
1716 {
1717 SCIPdebugMsg(scip, "Block solving status %d not supported\n", status);
1718 goto TERMINATE;
1719 }
1720
1721 /* free solving data in order to change problem */
1722 SCIP_CALL( SCIPfreeTransform((problem->blocks[b]).subscip) );
1723 }
1724 while( status != SCIP_STATUS_OPTIMAL && status != SCIP_STATUS_GAPLIMIT &&
1725 !(status == SCIP_STATUS_NODELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0) &&
1726 !(status == SCIP_STATUS_TIMELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0 &&
1727 SCIPisEQ(scip, SCIPgetSolOrigObj((problem->blocks[b]).subscip, SCIPgetBestSol((problem->blocks[b]).subscip)), 0.0) ) );
1728 }
1729 }
1730
1731 /* check wether problem has been solved and if not update penalty coeffs */
1732 doscaling = FALSE;
1733 solved = TRUE;
1734 increasedslacks = 0;
1735 maxpenalty = SCIP_REAL_MIN;
1736 for( b = 0; b < problem->nblocks; b++ )
1737 {
1738 for( i = 0; i < blocktolinkvars[b].size; i++ )
1739 {
1740 int linkvaridx;
1741 linkvaridx = blocktolinkvars[b].indexes[i];
1742
1743 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
1744 {
1745 int b2;
1746 b2 = linkvartoblocks[linkvaridx].indexes[k];
1747
1748 if( b2 != b )
1749 {
1750 SCIP_SOL* sol;
1751 BLOCKINFO binfo;
1752 BLOCKINFO* binfoout;
1753 SCIP_Real slackposval;
1754 SCIP_Real slacknegval;
1755
1756 binfo.block = b;
1757 binfo.otherblock = b2;
1758 binfo.linkvaridx = linkvaridx;
1759 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
1760 assert(binfoout != NULL);
1761
1762 sol = SCIPgetBestSol((problem->blocks[b]).subscip);
1763 slackposval = SCIPgetSolVal((problem->blocks[b]).subscip, sol, binfoout->slackposvar);
1764 slacknegval = SCIPgetSolVal((problem->blocks[b]).subscip, sol, binfoout->slacknegvar);
1765
1766 /* increase penalty coefficient of positive slack variable */
1767 if( SCIPisGT(scip, slackposval, 0.0) )
1768 {
1769 binfoout->slackposobjcoeff *= 10.0;
1770
1771 if( binfoout->slackposobjcoeff > slackthreshold )
1772 doscaling = TRUE;
1773
1774 if( binfoout->slackposobjcoeff > maxpenalty )
1775 maxpenalty = binfoout->slackposobjcoeff;
1776
1777 solved = FALSE;
1778 increasedslacks++;
1779 }
1780
1781 /* increase penalty coefficient of negative slack variable */
1782 if( SCIPisGT(scip, slacknegval, 0.0) )
1783 {
1784 binfoout->slacknegobjcoeff *= 10.0;
1785
1786 if( binfoout->slacknegobjcoeff > slackthreshold )
1787 doscaling = TRUE;
1788
1789 if( binfoout->slacknegobjcoeff > maxpenalty )
1790 maxpenalty = binfoout->slacknegobjcoeff;
1791
1792 solved = FALSE;
1793 increasedslacks++;
1794 }
1795 }
1796 }
1797 }
1798 }
1799
1800 /* should sigmoid scaling be applied to the penalty parameters? */
1801 if( doscaling && heurdata->scaling )
1802 {
1803 SCIPdebugMsg(scip, "rescale penalty parameters\n");
1804
1805 /* reset counter */
1806 increasedslacks = 0;
1807
1808 /* rescale penalty parameters */
1809 SCIP_CALL( scalePenalties(problem, linkvartoblocks, blocktolinkvars, htable, maxpenalty) );
1810 }
1811
1812 /* adapt in some cases the gap parameter */
1813 if( (aiter == 1 && solutionsdiffer == FALSE) || (doscaling && heurdata->scaling) )
1814 {
1815 SCIP_Real mingap = 0.001; //todo
1816 SCIP_Real newgap = MAX(gap * 0.5, mingap);
1817
1818 if( newgap >= mingap )
1819 {
1820 if( doscaling && heurdata->scaling )
1821 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "scale, %f", newgap);
1822 else
1823 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "%f", newgap);
1824
1825 gap = newgap;
1826 }
1827 }
1828
1829 /* free solution process data */
1830 if( !solved )
1831 for( b = 0; b < problem->nblocks; b++ )
1832 {
1833 SCIP_CALL( SCIPfreeTransform((problem->blocks[b]).subscip) );
1834 }
1835 }
1836
1837 /* copy solution if present */
1838 if( solved )
1839 {
1840 SCIP_SOL* newsol;
1841 SCIP_Real* blocksolvals;
1842
1843 assert(increasedslacks == 0);
1844
1845 SCIP_CALL( SCIPallocBufferArray(scip, &blocksolvals, nvars) );
1846 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
1847
1848 for( b = 0; b < problem->nblocks; b++ )
1849 {
1850 SCIP_SOL* blocksol;
1851 SCIP_VAR** blockvars;
1852 int nblockvars;
1853
1854 /* get solution of block variables (without slack variables) */
1855 blocksol = SCIPgetBestSol((problem->blocks[b]).subscip);
1856 assert(blocksol != NULL);
1857 blockvars = (problem->blocks[b]).subvars;
1858 nblockvars = (problem->blocks[b]).nsubvars;
1859 SCIP_CALL( SCIPgetSolVals((problem->blocks[b]).subscip, blocksol, nblockvars, blockvars, blocksolvals) );
1860
1861 for( i = 0; i < nblockvars; i++ )
1862 {
1863 SCIP_VAR* origvar;
1864 SCIP_Real solval;
1865
1866 origvar = SCIPfindVar(scip, SCIPvarGetName(blockvars[i]));
1867 solval = blocksolvals[i];
1868 SCIP_CALL_ABORT( SCIPsetSolVal(scip, newsol, origvar, solval) );
1869 }
1870 }
1871
1872 /* treat variables with no constraints; set value of variable to bound */
1873 for( i = 0; i < numlinkvars; i++ )
1874 {
1875 if( varonlyobj[i] )
1876 {
1877 SCIP_Real fixedvalue;
1878 if( SCIPvarGetObj(linkvars[i]) < 0 )
1879 {
1880 fixedvalue = SCIPvarGetUbLocal(linkvars[i]);
1881 if( SCIPisInfinity(scip, fixedvalue) )
1882 break; // todo: maybe we should return the status UNBOUNDED instead
1883 }
1884 else
1885 {
1886 fixedvalue = SCIPvarGetLbLocal(linkvars[i]);
1887 if( SCIPisInfinity(scip, fixedvalue) )
1888 break; // todo: maybe we should return the status UNBOUNDED instead
1889 }
1890 SCIP_CALL_ABORT( SCIPsetSolVal(scip, newsol, linkvars[i], fixedvalue) );
1891 }
1892 }
1893
1894 SCIPdebugMsg(scip, "Objective value %.2f\n", SCIPgetSolOrigObj(scip, newsol));
1895
1896 /* fix linking variables and reoptimize with original objective function */
1897 if( heurdata->reoptimize )
1898 {
1899 SCIP_SOL* improvedsol = NULL;
1900 SCIP_CALL( reoptimize(scip, heur, newsol, vars, nvars, linkvars, numlinkvars, &improvedsol, &success) );
1901 assert(improvedsol != NULL || success == FALSE);
1902
1903 if( success )
1904 {
1905 SCIP_CALL( SCIPtrySolFree(scip, &improvedsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
1906 if( !success )
1907 {
1908 SCIPdebugMsg(scip, "Reoptimizing solution failed\n");
1909 }
1910 else
1911 {
1912 SCIPdebugMsg(scip, "Reoptimizing solution successful\n");
1914 }
1915 }
1916 }
1917
1918 /* if reoptimization is turned off or reoptimization found no solution, try initial solution */
1919 if( *result != SCIP_FOUNDSOL )
1920 {
1921 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
1922 if( !success )
1923 {
1924 SCIPdebugMsg(scip, "Solution copy failed\n");
1925 }
1926 else
1927 {
1928 SCIPdebugMsg(scip, "Solution copy successful\n");
1930 }
1931 }
1932 else
1933 {
1934 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
1935 }
1936
1937 SCIPfreeBufferArray(scip, &blocksolvals);
1938 }
1939 else
1940 {
1941 SCIPdebugMsg(scip, "maximum number of penalty loops reached\n");
1943 }
1944
1945TERMINATE:
1946 /* release variables, constraints and free memory */
1947 if( problem != NULL )
1948 {
1949 for( b = 0; b < problem->nblocks; b++ )
1950 {
1951 BLOCK curr_block = problem->blocks[b];
1952 for( i = 0; i < (problem->blocks[b]).ncoupling; i++ )
1953 {
1954 SCIP_CALL( SCIPreleaseCons(curr_block.subscip, &curr_block.couplingcons[i]) );
1955 SCIP_CALL( SCIPreleaseVar(curr_block.subscip, &curr_block.slackspos[i]) );
1956 SCIP_CALL( SCIPreleaseVar(curr_block.subscip, &curr_block.slacksneg[i]) );
1957 }
1958 }
1959 }
1960
1961 if( htable != NULL )
1962 SCIPhashtableFree(&htable);
1963
1964 if( blockinfolist != NULL )
1965 SCIPfreeBufferArray(scip, &blockinfolist);
1966
1967 if( tmpcouplingcoef != NULL )
1968 SCIPfreeBufferArray(scip, &tmpcouplingcoef);
1969
1970 if( tmpcouplingvars != NULL )
1971 SCIPfreeBufferArray(scip, &tmpcouplingvars);
1972
1973 if( problem != NULL )
1974 {
1975 for( b = problem->nblocks - 1; b >= 0; b-- )
1976 {
1977 if( problem->blocks[b].couplingcons != NULL )
1978 {
1979 SCIPfreeBufferArray(scip, &problem->blocks[b].couplingcons);
1980 SCIPfreeBufferArray(scip, &problem->blocks[b].slacksneg);
1981 SCIPfreeBufferArray(scip, &problem->blocks[b].slackspos);
1982 }
1983 }
1984 }
1985
1986 if( varonlyobj != NULL )
1987 SCIPfreeBufferArray(scip, &varonlyobj);
1988
1989 if( problem != NULL && blocktolinkvars != NULL )
1990 {
1991 for( b = problem->nblocks -1; b >= 0; b-- )
1992 {
1993 if( blocktolinkvars[b].indexes != NULL )
1994 SCIPfreeBufferArray(scip, &(blocktolinkvars[b].indexes));
1995 }
1996 }
1997
1998 if( linkvars != NULL )
1999 SCIPfreeBufferArray(scip, &linkvars);
2000
2001 if( alllinkvartoblocks != NULL )
2002 SCIPfreeBufferArray(scip, &alllinkvartoblocks);
2003
2004 if( blocktolinkvars != NULL )
2005 SCIPfreeBufferArray(scip, &blocktolinkvars);
2006
2007 if( linkvartoblocks != NULL )
2008 SCIPfreeBufferArray(scip, &linkvartoblocks);
2009
2010 if( assigneddecomp != NULL )
2011 SCIPfreeDecomp(scip, &assigneddecomp);
2012
2013 if( consssize != NULL )
2014 SCIPfreeBufferArray(scip, &consssize);
2015
2016 if( conslabels != NULL )
2017 SCIPfreeBufferArray(scip, &conslabels);
2018
2019 if( varlabels != NULL )
2020 SCIPfreeBufferArray(scip, &varlabels);
2021
2022 if( sortedconss != NULL )
2023 SCIPfreeBufferArray(scip, &sortedconss);
2024
2025 if( problem != NULL )
2026 {
2027 SCIP_CALL( freeProblem(&problem, nblocks) );
2028 }
2029
2030 SCIPdebugMsg(scip, "Leave padm heuristic\n");
2031 return SCIP_OKAY;
2032}
2033
2034/*
2035 * primal heuristic specific interface methods
2036 */
2037
2038/** creates the PADM primal heuristic and includes it in SCIP */
2040 SCIP* scip /**< SCIP data structure */
2041 )
2042{
2044 SCIP_HEUR* heur = NULL;
2045
2046 /* create PADM primal heuristic data */
2048
2049 /* include primal heuristic */
2053
2054 assert(heur != NULL);
2055
2056 /* primal heuristic is safe to use in exact solving mode */
2057 SCIPheurMarkExact(heur);
2058
2059 /* set non fundamental callbacks via setter functions */
2060 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyPADM) );
2061 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreePADM) );
2062
2063 /* add padm primal heuristic parameters */
2064 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
2065 "maximum number of nodes to regard in all subproblems",
2066 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
2067
2068 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
2069 "minimum number of nodes to regard in one subproblem",
2070 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
2071
2072 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodefac",
2073 "factor to control nodelimits of subproblems", &heurdata->nodefac, TRUE, DEFAULT_NODEFAC, 0.0, 0.99, NULL, NULL) );
2074
2075 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/admiterations",
2076 "maximal number of ADM iterations in each penalty loop", &heurdata->admiterations, TRUE, DEFAULT_ADMIT, 1, 100, NULL, NULL) );
2077
2078 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/penaltyiterations",
2079 "maximal number of penalty iterations", &heurdata->penaltyiterations, TRUE, DEFAULT_PENALTYIT, 1, 100000, NULL, NULL) );
2080
2081 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gap",
2082 "mipgap at start", &heurdata->gap, TRUE, DEFAULT_GAP, 0.0, 16.0, NULL, NULL) );
2083
2084 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reoptimize",
2085 "should the problem get reoptimized with the original objective function?", &heurdata->reoptimize, FALSE, TRUE, NULL, NULL) );
2086
2087 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/scaling",
2088 "enable sigmoid rescaling of penalty parameters", &heurdata->scaling, TRUE, TRUE, NULL, NULL) );
2089
2090 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/assignlinking",
2091 "should linking constraints be assigned?", &heurdata->assignlinking, FALSE, TRUE, NULL, NULL) );
2092
2093 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/original",
2094 "should the original problem be used? This is only for testing and not recommended!", &heurdata->original, TRUE, FALSE, NULL, NULL) );
2095
2096 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/timing",
2097 "should the heuristic run before or after the processing of the node? (0: before, 1: after, 2: both)",
2098 &heurdata->timing, FALSE, 0, 0, 2, NULL, NULL) );
2099
2100 return SCIP_OKAY;
2101}
SCIP_VAR ** b
struct Problem PROBLEM
#define DEFAULT_MAXNODES
Constraint handler for linear constraints in their most general form, .
methods for debugging
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define SCIP_DEFAULT_EPSILON
Definition def.h:173
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define EPSEQ(x, y, eps)
Definition def.h:192
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIP_REAL_MIN
Definition def.h:168
#define REALABS(x)
Definition def.h:191
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
#define DEFAULT_MINNODES
#define nnodes
Definition gastrans.c:74
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_RETCODE SCIPcopyOrigConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition scip_copy.c:3134
SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition scip_copy.c:2962
SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, 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_Bool global, SCIP_Bool *valid)
Definition scip_copy.c:1581
SCIP_RETCODE SCIPcopyProb(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, const char *name)
Definition scip_copy.c:529
SCIP_RETCODE SCIPtranslateSubSol(SCIP *scip, SCIP *subscip, SCIP_SOL *subsol, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_SOL **newsol)
Definition scip_copy.c:1398
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition scip_copy.c:3293
void SCIPgetDecomps(SCIP *scip, SCIP_DECOMP ***decomps, int *ndecomps, SCIP_Bool original)
Definition scip_dcmp.c:263
SCIP_RETCODE SCIPdecompSetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
Definition dcmp.c:124
int SCIPdecompGetNBlocks(SCIP_DECOMP *decomp)
Definition dcmp.c:279
SCIP_RETCODE SCIPcomputeDecompVarsLabels(SCIP *scip, SCIP_DECOMP *decomp, SCIP_CONS **conss, int nconss)
Definition scip_dcmp.c:455
SCIP_RETCODE SCIPdecompSetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
Definition dcmp.c:173
SCIP_RETCODE SCIPassignDecompLinkConss(SCIP *scip, SCIP_DECOMP *decomp, SCIP_CONS **conss, int nconss, int *nskipconss)
Definition scip_dcmp.c:550
void SCIPfreeDecomp(SCIP *scip, SCIP_DECOMP **decomp)
Definition scip_dcmp.c:234
SCIP_RETCODE SCIPcomputeDecompStats(SCIP *scip, SCIP_DECOMP *decomp, SCIP_Bool uselimits)
Definition scip_dcmp.c:1136
void SCIPdecompGetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
Definition dcmp.c:198
SCIP_RETCODE SCIPdecompGetConssSize(SCIP_DECOMP *decomp, int *consssize, int nlabels)
Definition dcmp.c:349
SCIP_RETCODE SCIPcreateDecomp(SCIP *scip, SCIP_DECOMP **decomp, int nblocks, SCIP_Bool original, SCIP_Bool benderslabels)
Definition scip_dcmp.c:218
int SCIPdecompGetNBorderVars(SCIP_DECOMP *decomp)
Definition dcmp.c:379
void SCIPdecompGetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
Definition dcmp.c:149
SCIP_Bool SCIPdecompUseBendersLabels(SCIP_DECOMP *decomp)
Definition dcmp.c:269
int SCIPdecompGetNBorderConss(SCIP_DECOMP *decomp)
Definition dcmp.c:394
SCIP_RETCODE SCIPfree(SCIP **scip)
SCIP_RETCODE SCIPcreate(SCIP **scip)
SCIP_STATUS SCIPgetStatus(SCIP *scip)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
const char * SCIPgetProbName(SCIP *scip)
Definition scip_prob.c:1242
SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition scip_prob.c:742
int SCIPgetNOrigBinVars(SCIP *scip)
Definition scip_prob.c:2867
int SCIPgetNOrigConss(SCIP *scip)
Definition scip_prob.c:3712
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition scip_prob.c:2811
int SCIPgetNOrigIntVars(SCIP *scip)
Definition scip_prob.c:2896
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition scip_prob.c:3666
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
int SCIPgetNConss(SCIP *scip)
Definition scip_prob.c:3620
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
int SCIPgetNOrigVars(SCIP *scip)
Definition scip_prob.c:2838
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition scip_prob.c:3739
SCIP_RETCODE SCIPwriteTransProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition scip_prob.c:789
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition scip_prob.c:3189
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
#define SCIPhashFour(a, b, c, d)
Definition pub_misc.h:573
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2567
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
static INLINE uint32_t SCIPrealHashCode(double x)
Definition pub_misc.h:593
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition misc.c:2755
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition scip_param.c:250
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:111
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition scip_param.c:219
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 SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition scip_param.c:904
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition scip_param.c:307
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition scip_param.c:956
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 SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition scip_param.c:269
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition scip_param.c:429
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition scip_param.c:603
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition scip_param.c:985
SCIP_RETCODE SCIPincludeHeurPADM(SCIP *scip)
Definition heur_padm.c:2039
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition scip_cons.c:2577
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition scip_heur.c:122
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition heur.c:1457
SCIP_Real SCIPheurGetTime(SCIP_HEUR *heur)
Definition heur.c:1655
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition heur.c:1378
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition scip_mem.c:126
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition scip_mem.c:100
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:76
#define SCIPfreeMemoryArray(scip, ptr)
Definition scip_mem.h:80
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_RETCODE SCIPaddSolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool *stored)
Definition scip_sol.c:3914
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition scip_sol.c:829
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_sol.c:1844
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_sol.c:1660
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition scip_sol.c:2936
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition scip_sol.c:4114
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition scip_solve.c:232
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
SCIP_RETCODE SCIPsolve(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24052
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Bool SCIPdoNotMultaggr(SCIP *scip)
Definition scip_var.c:10919
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24696
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition scip_var.c:184
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:5372
void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
SCIPfreeSol(scip, &heurdata->sol))
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIPcreateSol(scip, &heurdata->sol, heur))
int c
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_RETCODE getTimeLeft(SCIP *scip, SCIP_Real *time)
Definition heur_padm.c:935
static SCIP_RETCODE initProblem(SCIP *scip, PROBLEM **problem, int nblocks)
Definition heur_padm.c:255
static SCIP_RETCODE blockCreateSubscip(BLOCK *block, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_CONS **conss, int nconss, SCIP_Bool useorigprob, SCIP_Bool *success)
Definition heur_padm.c:430
static SCIP_RETCODE initBlock(PROBLEM *problem)
Definition heur_padm.c:203
#define DEFAULT_NODEFAC
Definition heur_padm.c:94
#define COUPLINGSIZE
Definition heur_padm.c:91
static SCIP_RETCODE createSubscip(SCIP *scip, SCIP **subscip)
Definition heur_padm.c:321
struct set SET
#define DEFAULT_ADMIT
Definition heur_padm.c:95
static SCIP_RETCODE assignLinking(SCIP *scip, SCIP_DECOMP *newdecomp, SCIP_VAR **vars, SCIP_CONS **sortedconss, int *varlabels, int *conslabels, int nvars, int nconss, int nlinkconss)
Definition heur_padm.c:570
struct Block BLOCK
static SCIP_RETCODE copyToSubscip(SCIP *scip, SCIP *subscip, const char *name, SCIP_CONS **conss, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, int nconss, SCIP_Bool useorigprob, SCIP_Bool *success)
Definition heur_padm.c:369
static SCIP_RETCODE reuseSolution(SCIP *subscip, BLOCK *block)
Definition heur_padm.c:611
static SCIP_RETCODE createAndSplitProblem(SCIP *scip, SCIP_CONS **sortedconss, int nconss, int *consssize, int nblocks, PROBLEM **problem, SCIP_Bool useorigprob, SCIP_Bool *success)
Definition heur_padm.c:502
static SCIP_RETCODE scalePenalties(PROBLEM *problem, SET *linkvartoblocks, SET *blocktolinkvars, SCIP_HASHTABLE *htable, SCIP_Real maxpenalty)
Definition heur_padm.c:872
#define DEFAULT_PENALTYIT
Definition heur_padm.c:96
static SCIP_RETCODE freeBlock(BLOCK *block)
Definition heur_padm.c:232
struct blockinfo BLOCKINFO
static SCIP_RETCODE reoptimize(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol, SCIP_VAR **vars, int nvars, SCIP_VAR **linkvars, int nlinkvars, SCIP_SOL **newsol, SCIP_Bool *success)
Definition heur_padm.c:709
static SCIP_RETCODE freeProblem(PROBLEM **problem, int nblocks)
Definition heur_padm.c:285
#define DEFAULT_GAP
Definition heur_padm.c:97
PADM primal heuristic.
static SCIP_VAR ** vars
methods commonly used by primal heuristics
memory allocation routines
public methods for managing constraints
public methods for primal heuristics
public methods for message output
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for selecting k-medians
public methods for primal CIP solutions
public methods for branch and bound tree
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 decompositions
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 node selector plugins
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for random numbers
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for statistics table plugins
public methods for timing
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
default SCIP plugins
PROBLEM * problem
Definition heur_padm.c:109
SCIP_VAR ** subvars
Definition heur_padm.c:112
int ncoupling
Definition heur_padm.c:117
SCIP_VAR ** slacksneg
Definition heur_padm.c:115
SCIP_VAR ** slackspos
Definition heur_padm.c:114
SCIP_Real size
Definition heur_padm.c:118
SCIP_CONS ** couplingcons
Definition heur_padm.c:116
int nsubvars
Definition heur_padm.c:113
int number
Definition heur_padm.c:111
SCIP * subscip
Definition heur_padm.c:110
SCIP_Real slackposobjcoeff
Definition heur_padm.c:145
SCIP_VAR * slackposvar
Definition heur_padm.c:146
int otherblock
Definition heur_padm.c:141
int linkvaridx
Definition heur_padm.c:142
SCIP_CONS * couplingCons
Definition heur_padm.c:149
SCIP_VAR * slacknegvar
Definition heur_padm.c:148
SCIP_VAR * linkvar
Definition heur_padm.c:144
SCIP_Real slacknegobjcoeff
Definition heur_padm.c:147
SCIP_Real linkvarval
Definition heur_padm.c:143
int size
Definition heur_padm.c:133
int * indexes
Definition heur_padm.c:134
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECOMP_LINKVAR
Definition type_dcmp.h:44
struct SCIP_Decomp SCIP_DECOMP
Definition type_dcmp.h:40
#define SCIP_DECOMP_LINKCONS
Definition type_dcmp.h:45
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
@ SCIP_PARAMSETTING_OFF
@ SCIP_PARAMSETTING_FAST
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_FOUNDSOL
Definition type_result.h:56
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
@ SCIP_STATUS_OPTIMAL
Definition type_stat.h:43
@ SCIP_STATUS_BESTSOLLIMIT
Definition type_stat.h:60
@ SCIP_STATUS_UNBOUNDED
Definition type_stat.h:45
@ SCIP_STATUS_GAPLIMIT
Definition type_stat.h:56
@ SCIP_STATUS_TIMELIMIT
Definition type_stat.h:54
@ SCIP_STATUS_NODELIMIT
Definition type_stat.h:49
enum SCIP_Status SCIP_STATUS
Definition type_stat.h:64
#define SCIP_HEURTIMING_AFTERNODE
Definition type_timing.h:98
#define SCIP_HEURTIMING_BEFORENODE
Definition type_timing.h:80
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71