SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cutsel_dynamic.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 cutsel_dynamic.c
26 * @ingroup DEFPLUGINS_CUTSEL
27 * @brief dynamic cut selector
28 * @author Christoph Graczyk
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include "scip/scip_cutsel.h"
34#include "scip/scip_cut.h"
35#include "scip/scip_lp.h"
37#include "scip/cutsel_dynamic.h"
38
39
40#define CUTSEL_NAME "dynamic"
41#define CUTSEL_DESC "dynamic orthogonality for hybrid cutsel"
42#define CUTSEL_PRIORITY 7000
43
44#define RANDSEED 0x5EED
45
46#define DEFAULT_EFFICACYWEIGHT 1.0 /**< weight of efficacy in score calculation */
47#define DEFAULT_DIRCUTOFFDISTWEIGHT 0.0 /**< weight of directed cutoff distance in score calculation */
48#define DEFAULT_OBJPARALWEIGHT 0.0 /**< weight of objective parallelism in score calculation */
49#define DEFAULT_INTSUPPORTWEIGHT 0.0 /**< weight of integral support in cut score calculation */
50#define DEFAULT_MINORTHO 0.9 /**< minimal orthogonality in percent for a cut to enter the LP */
51#define DEFAULT_MINGAIN 0.01 /**< minimal efficacy gain for a cut to enter the LP */
52#define DEFAULT_MAXDEPTH (-1) /**< maximum depth at which this cutselector is used (-1 : all nodes) */
53#define DEFAULT_FILTERMODE 'd' /**< filtering strategy during cut selection (
54 * 'd'ynamic- and 'f'ull dynamic parallelism) */
55
56
57/*
58 * Data structures
59 */
60
61/** cut selector data */
62struct SCIP_CutselData
63{
64 SCIP_RANDNUMGEN* randnumgen; /**< random generator for tiebreaking */
65 SCIP_Real objparalweight; /**< weight of objective parallelism in cut score calculation */
66 SCIP_Real efficacyweight; /**< weight of efficacy in cut score calculation */
67 SCIP_Real dircutoffdistweight;/**< weight of directed cutoff distance in cut score calculation */
68 SCIP_Real intsupportweight; /**< weight of integral support in cut score calculation */
69 SCIP_Real mingain; /**< minimal projection efficacy gain for a cut to enter the LP in percent */
70 SCIP_Real minortho; /**< minimal orthogonality for a cut to enter the LP */
71 int maxdepth; /**< maximum depth at which this cutselector is used (-1 : all nodes) */
72 char filtermode; /**< filtering strategy during cut selection (
73 * 'd'ynamic- and 'f'ull dynamic parallelism) */
74};
75
76/*
77 * Local methods
78 */
79
80/* put your local methods here, and declare them static */
81
82/** returns the maximum score of cuts; if scores is not NULL, then stores the individual score of each cut in scores */
83static
85 SCIP* scip, /**< SCIP data structure */
86 SCIP_ROW** cuts, /**< array with cuts to score */
87 SCIP_RANDNUMGEN* randnumgen, /**< random number generator for tie-breaking, or NULL */
88 SCIP_Real dircutoffdistweight,/**< weight of directed cutoff distance in cut score calculation */
89 SCIP_Real efficacyweight, /**< weight of efficacy in cut score calculation */
90 SCIP_Real objparalweight, /**< weight of objective parallelism in cut score calculation */
91 SCIP_Real intsupportweight, /**< weight of integral support in cut score calculation */
92 int* currentncuts, /**< current number of cuts in cuts array */
93 SCIP_Real* scores /**< array to store the score of cuts or NULL */
94 )
95{
96 SCIP_Real maxscore = 0.0;
98 int i;
99 int ncuts = *currentncuts;
100
102
103 /* if there is an incumbent and the factor is not 0.0, compute directed cutoff distances for the incumbent */
104 if( sol != NULL && dircutoffdistweight > 0.0 )
105 {
106 for( i = ncuts-1; i >= 0; --i )
107 {
108 SCIP_Real score;
109 SCIP_Real objparallelism;
110 SCIP_Real intsupport;
111 SCIP_Real efficacy;
112
113 if( intsupportweight > 0.0 )
114 intsupport = intsupportweight * SCIPgetRowNumIntCols(scip, cuts[i]) / (SCIP_Real) SCIProwGetNNonz(cuts[i]);
115 else
116 intsupport = 0.0;
117
118 if( objparalweight > 0.0 )
119 objparallelism = objparalweight * SCIPgetRowObjParallelism(scip, cuts[i]);
120 else
121 objparallelism = 0.0;
122
123 efficacy = SCIPgetCutEfficacy(scip, NULL, cuts[i]);
124
125 if( SCIProwIsLocal(cuts[i]) )
126 {
127 score = dircutoffdistweight * efficacy;
128 }
129 else
130 {
131 score = SCIPgetCutLPSolCutoffDistance(scip, sol, cuts[i]);
132 score = dircutoffdistweight * MAX(score, efficacy);
133 }
134
135 score += objparallelism + intsupport + efficacyweight * efficacy;
136
137 /* add small term to prefer global pool cuts */
138 if( SCIProwIsInGlobalCutpool(cuts[i]) )
139 score += 1e-4;
140
141 if( randnumgen != NULL)
142 {
143 score += SCIPrandomGetReal(randnumgen, 0.0, 1e-6);
144 }
145
146 maxscore = MAX(maxscore, score);
147
148 if( SCIPisLE(scip, score, 0.0) || efficacy == 0.0 ) /*lint !e777*/
149 {
150 --ncuts;
151 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
152 if( scores != NULL )
153 SCIPswapReals(&scores[i], &scores[ncuts]);
154 }
155 else if( scores != NULL )
156 {
157 scores[i] = score;
158 }
159 }
160 }
161 else
162 {
163 /* in case there is no solution add the directed cutoff distance weight to the efficacy weight
164 * since the efficacy underestimates the directed cuttoff distance
165 */
166 efficacyweight += dircutoffdistweight;
167
168 /*lint -e{850} i is modified in the body of the for loop */
169 for( i = ncuts-1; i >= 0; --i )
170 {
171 SCIP_Real score;
172 SCIP_Real objparallelism;
173 SCIP_Real intsupport;
174 SCIP_Real efficacy;
175
176 if( intsupportweight > 0.0 )
177 intsupport = intsupportweight * SCIPgetRowNumIntCols(scip, cuts[i]) / (SCIP_Real) SCIProwGetNNonz(cuts[i]);
178 else
179 intsupport = 0.0;
180
181 if( objparalweight > 0.0 )
182 objparallelism = objparalweight * SCIPgetRowObjParallelism(scip, cuts[i]);
183 else
184 objparallelism = 0.0;
185
186 efficacy = SCIPgetCutEfficacy(scip, NULL, cuts[i]);
187
188 score = objparallelism + intsupport + efficacyweight * efficacy;
189
190 /* add small term to prefer global pool cuts */
191 if( SCIProwIsInGlobalCutpool(cuts[i]) )
192 score += 1e-4;
193
194 if( randnumgen != NULL)
195 {
196 score += SCIPrandomGetReal(randnumgen, 0.0, 1e-6);
197 }
198
199 maxscore = MAX(maxscore, score);
200
201 if( SCIPisLE(scip, score, 0.0) || efficacy == 0.0 ) /*lint !e777*/
202 {
203 --ncuts;
204 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
205 if( scores != NULL )
206 SCIPswapReals(&scores[i], &scores[ncuts]);
207 }
208 else if( scores != NULL )
209 {
210 scores[i] = score;
211 }
212 }
213 }
214 *currentncuts = ncuts;
215}
216
217/** compute projectioncut score for cuts from a given bestcut. **/
218static
220 SCIP* scip, /**< SCIP data structure */
221 SCIP_ROW* bestcut, /**< cut to filter orthogonality with */
222 SCIP_ROW* cut, /**< cut to perform scoring on */
223 SCIP_Real* score /**< score for cut */
224 )
225{
226 SCIP_Real efficacy;
227 SCIP_Real currentbestefficacy;
228 SCIP_Real cosineangle;
229
230 SCIPdebugMsg(scip, "\ncomputeProjectionScore.\n\n");
231 currentbestefficacy = SCIPgetCutEfficacy(scip, NULL, bestcut);
232 SCIPdebugMsg(scip, "currentbestefficacy = %g\n", currentbestefficacy);
233
234 efficacy = SCIPgetCutEfficacy(scip, NULL, cut);
235 SCIPdebugMsg(scip, "efficacy[%s] = %g\n", SCIProwGetName(cut), efficacy);
236
237 cosineangle = SCIProwGetParallelism(bestcut, cut, 'e');
238 if( SCIPisEQ(scip, cosineangle, 1.0))
239 *score = -SCIPinfinity(scip);
240 else
241 {
242 *score = sqrt(currentbestefficacy * currentbestefficacy + efficacy * efficacy
243 - 2.0 * fabs(currentbestefficacy) * fabs(efficacy) * cosineangle)
244 / sqrt((1.0 - (cosineangle * cosineangle)));
245 *score -= currentbestefficacy;
246 }
247 SCIPdebugMsg(scip, "Projectionscore[%s] = %g\n", SCIProwGetName(cut), *score);
248 return SCIP_OKAY;
249}
250
251/** move the cut with the highest score to the first position in the array; there must be at least one cut */
252static
254 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
255 SCIP_Real* scores, /**< array with scores of cuts to perform selection algorithm */
256 int ncuts /**< number of cuts in given array */
257 )
258{
259 int i;
260 int bestpos;
261 SCIP_Real bestscore;
262
263 assert(ncuts > 0);
264 assert(cuts != NULL);
265 assert(scores != NULL);
266
267 bestscore = scores[0];
268 bestpos = 0;
269
270 for( i = 1; i < ncuts; ++i )
271 {
272 if( scores[i] > bestscore )
273 {
274 bestpos = i;
275 bestscore = scores[i];
276 }
277 }
278
279 SCIPswapPointers((void**) &cuts[bestpos], (void**) &cuts[0]);
280 SCIPswapReals(&scores[bestpos], &scores[0]);
281}
282
283/** filters the given array of cuts to enforce a maximum parallelism constraint
284 * w.r.t the given cut; moves filtered cuts to the end of the array and returns number of selected cuts */
285static
287 SCIP* scip, /**< SCIP data structure */
288 SCIP_ROW* bestcut, /**< cut to filter orthogonality with */
289 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
290 SCIP_Real* scores, /**< array with scores of cuts to perform selection algorithm */
291 SCIP_Real mingain, /**< minimum gain enforced on the two-cut efficacy */
292 SCIP_Real maxparall, /**< maximal parallelism for all cuts that are not good */
293 int ncuts /**< number of cuts in given array */
294 )
295{
296 int i;
297 SCIP_Bool filter;
298 SCIP_Real bestcutefficacy;
299
300 SCIPdebugMsg(scip, "\nfilterWithDynamicParallelism.\n\n");
301
302 assert(bestcut != NULL);
303 assert(ncuts == 0 || cuts != NULL);
304 assert(ncuts == 0 || scores != NULL);
305
306 bestcutefficacy = SCIPgetCutEfficacy(scip, NULL, bestcut);
307 assert(bestcutefficacy > 0.0); /* ensured in scoring() */
308
309 /*lint -e{850} i is modified in the body of the for loop */
310 for( i = ncuts-1; i >= 0; --i )
311 {
312 SCIP_Real thisparall;
313 SCIP_Real cosine;
314 SCIP_Real currentcutefficacy;
315 SCIP_Real minmaxparall;
316
317 currentcutefficacy = SCIPgetCutEfficacy(scip, NULL, cuts[i]);
318 assert(currentcutefficacy > 0.0); /* ensured in scoring() */
319
320 if( SCIPisGE(scip, bestcutefficacy, currentcutefficacy))
321 {
322 cosine = SCIProwGetParallelism(bestcut, cuts[i], 'e');
323 thisparall = cosine * bestcutefficacy / currentcutefficacy;
324 SCIPdebugMsg(scip, "Thisparall(%g) = cosine(%g) * (bestcutefficacy(%g)/ currentcutefficacy(%g))\n\n", thisparall,
325 cosine, bestcutefficacy, currentcutefficacy);
326 }
327 else
328 {
329 cosine = SCIProwGetParallelism(cuts[i], bestcut, 'e');
330 thisparall = cosine * currentcutefficacy / bestcutefficacy;
331 SCIPdebugMsg(scip, "Thisparall(%g) = cosine(%g) * (currentcutefficacy(%g) / bestcutefficacy(%g))\n\n", thisparall,
332 cosine, currentcutefficacy, bestcutefficacy);
333 }
334
335 /* compute the max-minimum angle for given the given cuts to enforce
336 * norm(d) >= (1+mingain)*eff1 for non-negative cosine angle */
337 minmaxparall = MAX( (bestcutefficacy * bestcutefficacy
338 + currentcutefficacy * currentcutefficacy
339 - (1 + mingain) * bestcutefficacy * (1 + mingain) * bestcutefficacy * (1 - cosine * cosine))
340 / (2 * bestcutefficacy * currentcutefficacy),
341 maxparall );
342 filter = ( SCIPisGE(scip, thisparall, 1.0) || SCIPisGT(scip, cosine, minmaxparall) );
343
344 SCIPdebugMsg(scip, "Filter = %u\n", filter);
345
346 if( filter )
347 {
348 --ncuts;
349 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
350 SCIPswapReals(&scores[i], &scores[ncuts]);
351 }
352 }
353
354 return ncuts;
355}
356
357
358/*
359 * Callback methods of cut selector
360 */
361
362/** copy method for cut selector plugin (called when SCIP copies plugins) */
363static
364SCIP_DECL_CUTSELCOPY(cutselCopyDynamic)
365{ /*lint --e{715}*/
366 assert(scip != NULL);
367 assert(cutsel != NULL);
368
370
371 /* call inclusion method of cut selector */
373
374 return SCIP_OKAY;
375}
376
377/** destructor of cut selector to free user data (called when SCIP is exiting) */
378/**! [SnippetCutselFreeDynamic] */
379static
380SCIP_DECL_CUTSELFREE(cutselFreeDynamic)
381{ /*lint --e{715}*/
382 SCIP_CUTSELDATA* cutseldata;
383
384 cutseldata = SCIPcutselGetData(cutsel);
385
386 SCIPfreeBlockMemory(scip, &cutseldata);
387
388 SCIPcutselSetData(cutsel, NULL);
389
390 return SCIP_OKAY;
391}
392/**! [SnippetCutselFreeDynamic] */
393
394/** initialization method of cut selector (called after problem was transformed) */
395static
396SCIP_DECL_CUTSELINIT(cutselInitDynamic)
397{ /*lint --e{715}*/
398 SCIP_CUTSELDATA* cutseldata;
399
400 cutseldata = SCIPcutselGetData(cutsel);
401 assert(cutseldata != NULL);
402
403 SCIP_CALL( SCIPcreateRandom(scip, &(cutseldata)->randnumgen, RANDSEED, TRUE) );
404
405 return SCIP_OKAY;
406}
407
408/** deinitialization method of cut selector (called before transformed problem is freed) */
409static
410SCIP_DECL_CUTSELEXIT(cutselExitDynamic)
411{ /*lint --e{715}*/
412 SCIP_CUTSELDATA* cutseldata;
413
414 cutseldata = SCIPcutselGetData(cutsel);
415 assert(cutseldata != NULL);
416 assert(cutseldata->randnumgen != NULL);
417
418 SCIPfreeRandom(scip, &cutseldata->randnumgen);
419
420 return SCIP_OKAY;
421}
422
423/** cut selection method of cut selector */
424static
425SCIP_DECL_CUTSELSELECT(cutselSelectDynamic)
426{ /*lint --e{715}*/
427 SCIP_CUTSELDATA *cutseldata;
428
429 assert(cutsel != NULL);
430 assert(result != NULL);
431
433
434 cutseldata = SCIPcutselGetData(cutsel);
435 assert(cutseldata != NULL);
436 if (cutseldata->maxdepth != -1 && cutseldata->maxdepth < SCIPgetDepth(scip))
437 {
439 return SCIP_OKAY;
440 }
441
442 SCIP_CALL( SCIPselectCutsDynamic(scip, cuts, forcedcuts, cutseldata->randnumgen, cutseldata->filtermode,
443 cutseldata->mingain, 1-cutseldata->minortho, cutseldata->dircutoffdistweight, cutseldata->efficacyweight,
444 cutseldata->objparalweight, cutseldata->intsupportweight, ncuts, nforcedcuts,
445 maxnselectedcuts, nselectedcuts) );
446
447 return SCIP_OKAY;
448}
449
450
451/*
452 * cut selector specific interface methods
453 */
454
455/** creates the dynamic cut selector and includes it in SCIP */
457 SCIP* scip /**< SCIP data structure */
458 )
459{
460 SCIP_CUTSELDATA* cutseldata;
461 SCIP_CUTSEL* cutsel;
462
463 /* create dynamic cut selector data */
464 SCIP_CALL( SCIPallocBlockMemory(scip, &cutseldata) );
465 BMSclearMemory(cutseldata);
466
467 SCIP_CALL( SCIPincludeCutselBasic(scip, &cutsel, CUTSEL_NAME, CUTSEL_DESC, CUTSEL_PRIORITY, cutselSelectDynamic, cutseldata) );
468
469 assert(cutsel != NULL);
470
471 /* set non fundamental callbacks via setter functions */
472 SCIP_CALL( SCIPsetCutselCopy(scip, cutsel, cutselCopyDynamic) );
473
474 SCIP_CALL( SCIPsetCutselFree(scip, cutsel, cutselFreeDynamic) );
475 SCIP_CALL( SCIPsetCutselInit(scip, cutsel, cutselInitDynamic) );
476 SCIP_CALL( SCIPsetCutselExit(scip, cutsel, cutselExitDynamic) );
477
478 /* add dynamic cut selector parameters */
480 "cutselection/" CUTSEL_NAME "/efficacyweight",
481 "weight of efficacy in cut score calculation",
482 &cutseldata->efficacyweight, FALSE,
484
486 "cutselection/" CUTSEL_NAME "/dircutoffdistweight",
487 "weight of directed cutoff distance in cut score calculation",
488 &cutseldata->dircutoffdistweight, FALSE,
490
492 "cutselection/" CUTSEL_NAME "/objparalweight",
493 "weight of objective parallelism in cut score calculation",
494 &cutseldata->objparalweight, FALSE,
496
498 "cutselection/" CUTSEL_NAME "/intsupportweight",
499 "weight of integral support in cut score calculation",
500 &cutseldata->intsupportweight, FALSE,
502
504 "cutselection/" CUTSEL_NAME "/mingain",
505 "minimal efficacy gain for a cut to enter the LP",
506 &cutseldata->mingain, FALSE,
507 DEFAULT_MINGAIN, 0.0, 1.0, NULL, NULL) );
508
510 "cutselection/" CUTSEL_NAME "/filtermode",
511 "filtering strategy during cut selection",
512 &cutseldata->filtermode, FALSE,
513 DEFAULT_FILTERMODE, "df", NULL, NULL) );
514
516 "cutselection/" CUTSEL_NAME "/minortho",
517 "minimal orthogonality for a cut to enter the LP",
518 &cutseldata->minortho, FALSE,
519 DEFAULT_MINORTHO, 0.0, 1.0, NULL, NULL) );
520
522 "cutselection/" CUTSEL_NAME "/maxdepth",
523 "maximum depth at which this cutselector is employed",
524 &cutseldata->maxdepth, FALSE,
526
527 return SCIP_OKAY;
528}
529
530
531/** perform a cut selection algorithm for the given array of cuts
532 *
533 * This is the selection method of the dynamic cut selector which implements
534 * the dynamic orthognality filtering based on the ratio of efficacies.
535 * The input cuts array gets re-sorted s.t the selected cuts come first and the remaining
536 * ones are the end.
537 */
539 SCIP* scip, /**< SCIP data structure */
540 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
541 SCIP_ROW** forcedcuts, /**< array with forced cuts */
542 SCIP_RANDNUMGEN* randnumgen, /**< random number generator for tie-breaking, or NULL */
543 char filtermode, /**< filtering strategy during cut selection (
544 * 'd'ynamic- and 'f'ull dynamic parallelism) */
545 SCIP_Real mingain, /**< minimum efficacy gain in percentage to filter cuts */
546 SCIP_Real maxparall, /**< maximal parallelism for all cuts that are not good */
547 SCIP_Real dircutoffdistweight,/**< weight of directed cutoff distance in cut score calculation */
548 SCIP_Real efficacyweight, /**< weight of efficacy in cut score calculation */
549 SCIP_Real objparalweight, /**< weight of objective parallelism in cut score calculation */
550 SCIP_Real intsupportweight, /**< weight of integral support in cut score calculation */
551 int ncuts, /**< number of cuts in cuts array */
552 int nforcedcuts, /**< number of forced cuts */
553 int maxselectedcuts, /**< maximal number of cuts from cuts array to select */
554 int* nselectedcuts /**< pointer to return number of selected cuts from cuts array */
555 )
556{
557 SCIP_ROW* selectedcut;
558 SCIP_Real* scores;
559 SCIP_Real* forcedscores;
560 SCIP_Real* scoresptr;
561 int ngoodforcedcuts;
562 int i;
563
564 assert(cuts != NULL && ncuts > 0);
565 assert(forcedcuts != NULL || nforcedcuts == 0);
566 assert(nselectedcuts != NULL);
567
568 *nselectedcuts = 0;
569 ngoodforcedcuts = 0;
570
571 SCIP_CALL( SCIPallocBufferArray(scip, &scores, ncuts) );
572
573 /* compute scores of cuts and max score of cuts and forced cuts (used to define goodscore) */
574 scoring(scip, cuts, randnumgen, dircutoffdistweight, efficacyweight, objparalweight, intsupportweight, &ncuts,
575 scores);
576 scoresptr = scores;
577
578 SCIPdebugMsg(scip, "nforcedcuts = %i.\n", nforcedcuts);
579
580 /* perform cut selection algorithm for the cuts */
581
582 /* forced cuts are going to be selected so use them to filter cuts */
583 for( i = 0; i < nforcedcuts && ncuts > 0; ++i )
584 ncuts = filterWithDynamicParallelism(scip, forcedcuts[i], cuts, scores, mingain, maxparall, ncuts);
585
586 /* if all cuts are already filtered, we can stop */
587 if( ncuts <= 0 )
588 goto TERMINATE;
589
590 /* if the maximal number of cuts was selected, we can stop here */
591 if( *nselectedcuts == maxselectedcuts )
592 goto TERMINATE;
593
594 if( filtermode == 'f' && nforcedcuts > 0 )
595 {
596 SCIP_CALL( SCIPallocBufferArray(scip, &forcedscores, nforcedcuts) );
597 ngoodforcedcuts = nforcedcuts;
598 scoring(scip, forcedcuts, randnumgen, dircutoffdistweight, efficacyweight, objparalweight, intsupportweight,
599 &ngoodforcedcuts, forcedscores);
600
601 if( ngoodforcedcuts != 0 )
602 {
603 selectBestCut(forcedcuts, forcedscores, ngoodforcedcuts);
604 SCIPfreeBufferArray(scip, &forcedscores);
605 SCIPdebugMsg(scip, "best forced cut: %s.\n", SCIProwGetName(forcedcuts[0]));
606
607 for( i = 0; i < ncuts; i++ )
608 {
609 SCIP_CALL( computeProjectionScore(scip, forcedcuts[0], cuts[i], &scores[i]) );
610 SCIPdebugMsg(scip, "scores[%i] = %g\n", i, scores[i]);
611 }
612 }
613 }
614
615 if( ngoodforcedcuts == 0 )
616 {
617 assert(filtermode == 'd' || ngoodforcedcuts == 0);
618 selectBestCut(cuts, scores, ncuts);
619
620 selectedcut = cuts[0];
621 SCIPdebugMsg(scip, "selectedcut = %s.\n", SCIProwGetName(selectedcut));
622
623 ++(*nselectedcuts);
624
625 /* if the maximal number of cuts was selected, we can stop here */
626 if( *nselectedcuts == maxselectedcuts )
627 goto TERMINATE;
628
629 /* move the pointers to the next position and filter the remaining cuts to enforce the dynamic parallelism constraint */
630 ++cuts;
631 ++scores;
632 --ncuts;
633
634 ncuts = filterWithDynamicParallelism(scip, selectedcut, cuts, scores, mingain, maxparall, ncuts);
635
636 if( filtermode == 'f' )
637 {
638 for( i = 0; i < ncuts; i++ )
639 {
640 SCIP_CALL( computeProjectionScore(scip, selectedcut, cuts[i], &scores[i]) );
641 }
642 }
643 }
644
645 SCIPdebugMsg(scip, "ncuts after forced cut filter = %i.\n", ncuts);
646
647 /* now greedily select the remaining cuts */
648 while( ncuts > 0 )
649 {
650 selectBestCut(cuts, scores, ncuts);
651 selectedcut = cuts[0];
652 SCIPdebugMsg(scip, "selectedcut = %s.\n", SCIProwGetName(selectedcut));
653
654 ++(*nselectedcuts);
655
656 /* if the maximal number of cuts was selected, we can stop here */
657 if( *nselectedcuts == maxselectedcuts )
658 goto TERMINATE;
659
660 /* move the pointers to the next position and filter the remaining cuts to enforce the dynamic parallelism constraint */
661 ++cuts;
662 ++scores;
663 --ncuts;
664
665 ncuts = filterWithDynamicParallelism(scip, selectedcut, cuts, scores, mingain, maxparall, ncuts);
666
667 if( filtermode == 'f' )
668 {
669 for( i = 0; i < ncuts; i++ )
670 {
671 SCIP_CALL( computeProjectionScore(scip, selectedcut, cuts[i], &scores[i]) );
672 SCIPdebugMsg(scip, "nonforcedscores[%i] = %g\n", i, scores[i]);
673 }
674 }
675 }
676
677 TERMINATE:
678 SCIPfreeBufferArray(scip, &scoresptr);
679 return SCIP_OKAY;
680}
#define DEFAULT_EFFICACYWEIGHT
#define DEFAULT_INTSUPPORTWEIGHT
#define DEFAULT_MAXDEPTH
#define DEFAULT_MINGAIN
#define DEFAULT_OBJPARALWEIGHT
#define RANDSEED
static int filterWithDynamicParallelism(SCIP *scip, SCIP_ROW *bestcut, SCIP_ROW **cuts, SCIP_Real *scores, SCIP_Real mingain, SCIP_Real maxparall, int ncuts)
static void selectBestCut(SCIP_ROW **cuts, SCIP_Real *scores, int ncuts)
#define CUTSEL_DESC
#define DEFAULT_FILTERMODE
#define CUTSEL_PRIORITY
static SCIP_RETCODE computeProjectionScore(SCIP *scip, SCIP_ROW *bestcut, SCIP_ROW *cut, SCIP_Real *score)
#define DEFAULT_MINORTHO
#define DEFAULT_DIRCUTOFFDISTWEIGHT
static void scoring(SCIP *scip, SCIP_ROW **cuts, SCIP_RANDNUMGEN *randnumgen, SCIP_Real dircutoffdistweight, SCIP_Real efficacyweight, SCIP_Real objparalweight, SCIP_Real intsupportweight, int *currentncuts, SCIP_Real *scores)
#define CUTSEL_NAME
dynamic cut selector
#define NULL
Definition def.h:257
#define SCIP_MAXTREEDEPTH
Definition def.h:306
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPselectCutsDynamic(SCIP *scip, SCIP_ROW **cuts, SCIP_ROW **forcedcuts, SCIP_RANDNUMGEN *randnumgen, char filtermode, SCIP_Real mingain, SCIP_Real maxparall, SCIP_Real dircutoffdistweight, SCIP_Real efficacyweight, SCIP_Real objparalweight, SCIP_Real intsupportweight, int ncuts, int nforcedcuts, int maxselectedcuts, int *nselectedcuts)
SCIP_RETCODE SCIPincludeCutselDynamic(SCIP *scip)
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:167
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition misc.c:10511
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition misc.c:10498
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition scip_cut.c:94
SCIP_Real SCIPgetCutLPSolCutoffDistance(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition scip_cut.c:72
SCIP_RETCODE SCIPsetCutselInit(SCIP *scip, SCIP_CUTSEL *cutsel,)
SCIP_RETCODE SCIPincludeCutselBasic(SCIP *scip, SCIP_CUTSEL **cutsel, const char *name, const char *desc, int priority, SCIP_DECL_CUTSELSELECT((*cutselselect)), SCIP_CUTSELDATA *cutseldata)
Definition scip_cutsel.c:98
SCIP_RETCODE SCIPsetCutselCopy(SCIP *scip, SCIP_CUTSEL *cutsel,)
SCIP_RETCODE SCIPsetCutselExit(SCIP *scip, SCIP_CUTSEL *cutsel,)
SCIP_CUTSELDATA * SCIPcutselGetData(SCIP_CUTSEL *cutsel)
Definition cutsel.c:419
void SCIPcutselSetData(SCIP_CUTSEL *cutsel, SCIP_CUTSELDATA *cutseldata)
Definition cutsel.c:429
const char * SCIPcutselGetName(SCIP_CUTSEL *cutsel)
Definition cutsel.c:159
SCIP_RETCODE SCIPsetCutselFree(SCIP *scip, SCIP_CUTSEL *cutsel,)
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition lp.c:7970
int SCIProwGetNNonz(SCIP_ROW *row)
Definition lp.c:17607
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition lp.c:17885
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition lp.c:17795
const char * SCIProwGetName(SCIP_ROW *row)
Definition lp.c:17745
SCIP_Real SCIPgetRowObjParallelism(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:2154
int SCIPgetRowNumIntCols(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1832
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition misc.c:10245
return SCIP_OKAY
SCIPfreeRandom(scip, &heurdata->randnumgen)
int maxdepth
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
#define BMSclearMemory(ptr)
Definition memory.h:129
public methods for cuts and aggregation rows
public methods for cut selector plugins
public methods for the LP relaxation, rows and columns
public methods for random numbers
#define SCIP_DECL_CUTSELEXIT(x)
Definition type_cutsel.h:86
#define SCIP_DECL_CUTSELSELECT(x)
#define SCIP_DECL_CUTSELFREE(x)
Definition type_cutsel.h:70
struct SCIP_Cutsel SCIP_CUTSEL
Definition type_cutsel.h:52
struct SCIP_CutselData SCIP_CUTSELDATA
Definition type_cutsel.h:53
#define SCIP_DECL_CUTSELINIT(x)
Definition type_cutsel.h:78
#define SCIP_DECL_CUTSELCOPY(x)
Definition type_cutsel.h:62
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_SUCCESS
Definition type_result.h:58
@ 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