SCIP Doxygen Documentation
Loading...
Searching...
No Matches
pricer_coloring.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 pricer_coloring.c
26 * @brief variable pricer for the vertex coloring problem
27 * @author Gerald Gamrath
28 * @author Rolf van der Hulst
29 *
30 * This file implements the pricer for the coloring algorithm.
31 *
32 * It computes maximal stable sets in the current graph whose corresponding variables can improve
33 * the current LP solution. This is done by computing a maximum weighted stable set in the current
34 * graph with dual-variables of the node constraints as weights. A variable can improve the
35 * solution, if the weight of the corresponding stable set is larger than 1, since it then has
36 * negative reduced costs, which are given by (1 - weight of the set).
37 *
38 * The pricer first tries to compute such a stable set using a a greedy-method. If it fails, the tclique-algorithm is
39 * used on the complementary graph. This is a branch-and-bound based algorithm for maximal cliques,
40 * included in SCIP. In this case, not only the best solution is added to the LP, but also all other
41 * stable sets found during the branch-and-bound process that could improve the current LP solution
42 * are added, limited to a maximal number that can be changed by a parameter.
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46
47#include "pricer_coloring.h"
48#include "reader_col.h"
49#include "cons_storeGraph.h"
50#include <stdlib.h>
51
52
53#define PRICER_NAME "coloring"
54#define PRICER_DESC "pricer for coloring"
55#define PRICER_PRIORITY 5000000
56#define PRICER_DELAY TRUE /* only call pricer if all problem variables have non-negative reduced costs */
57
58/* defines for rounding for tclique */
59#define MAXDNOM 10000LL
60#define MINDELTA 1e-12
61#define MAXDELTA 1e-09
62
63
64/* default values for parameters */
65#define DEFAULT_MAXVARSROUND 1
66#define DEFAULT_USETCLIQUE TRUE
67#define DEFAULT_USEGREEDY TRUE
68#define DEFAULT_ONLYBEST FALSE
69#define DEFAULT_MAXROUNDSROOT -1
70#define DEFAULT_MAXROUNDSNODE -1
71#define DEFAULT_MAXTCLIQUENODES INT_MAX
72
73
74/*
75 * Data structures
76 */
77
78
79/** variable pricer data */
80struct SCIP_PricerData
81{
82 SCIP* scip; /* SCIP data structure */
83 int maxvarsround; /* maximal number of variables created each round */
84 int oldmaxvarsround; /* maximal number of variables created each round, old value before parameter was changed */
85 int nstablesetsfound; /* number of improving stable sets found in the current round so far */
86 SCIP_CONS** constraints; /* array containing all node constraints */
87 SCIP_Real scalefactor; /* the factor used for scaling the rational values to integers for the tclique-weights */
88 SCIP_Real* pi; /* array of the dual solutions */
89 SCIP_Bool onlybest; /* determines whether the maxvarsround variables with the best reduced costs should be added
90 (onlybest = true) or the first maxvarsround variables which are found are added (false) */
91 SCIP_Bool usegreedy; /* determines whether a greedy method is used for finding variables with neg. reduced costs */
92 SCIP_Bool usetclique; /* determines whether the tclique method is used for finding improving variables */
93 int** improvingstablesets; /* array to store the maxvarsround stable sets with the most negative reduced costs */
94 int improvingstablesetssize; /* size of each improvingstablesets array */
95 int* nstablesetnodes; /* array which stores the lengths of the stable sets in improvingstablesets */
96 int actindex; /* the index at which the current stable set was inserted into improvingstablesets */
97 SCIP_NODE* bbnode; /* the current B&B-tree node, used for limiting the number of pricing rounds */
98 int noderounds; /* the number of remaining pricing rounds at the current node */
99 int maxroundsroot; /* maximum number of pricing rounds in the root, -1 for infinity, attention: positive value may lead to a non-optimal solution */
100 int maxroundsnode; /* maximum number of pricing rounds in the B&B-nodes, -1 for infinity, attention: positive value may lead to a non-optimal solution */
101 int maxtcliquenodes; /* maximum number of nodes used in the tclique algorithm for solving the stable set problem */
102 SCIP_Real lowerbound; /* lower bound computed by the pricer */
103};
104
105
106/*
107 * Local methods
108 */
109
110/** returns whether the graph has an uncolored node
111 */
112static
114 TCLIQUE_GRAPH* graph, /**< the graph that should be colored */
115 SCIP_Bool* colored /**< array of booleans, colored[i] == TRUE iff node i is colored */
116 )
117{
118 int i;
119
120 assert(graph != NULL);
121 assert(colored != NULL);
122
123 for ( i = 0; i < tcliqueGetNNodes(graph); i++)
124 {
125 /* node not yet colored */
126 if (!colored[i])
127 {
128 return TRUE;
129 }
130 }
131 return FALSE;
132}
133
134/** sorts the nodes from 0 to nnodes-1 w.r.t. the given weights */
135static
137 SCIP* scip, /**< SCIP data structure */
138 SCIP_Real* weights, /**< the weights for sorting */
139 int nnodes, /**< the number of nodes */
140 int* sortednodes /**< the array that will be overwritten with the sorted node numbers */
141 )
142{
143 int i;
144 SCIP_Real* values;
145
146 assert(scip != NULL);
147 assert(weights != NULL);
148
149 /* create array with indices and copy the weights-array */
151 for ( i = 0; i < nnodes; i++)
152 {
153 sortednodes[i] = i;
154 values[i] = weights[i];
155 }
156
157 /* sort the nodes w.r.t. the computed values */
158 SCIPsortDownRealInt(values, sortednodes, nnodes);
159 SCIPfreeBufferArray(scip, &values);
160
161 return SCIP_OKAY;
162}
163
164/** computes a stable set with a greedy-method. attention: the weight of the maximum stable set is not computed! */
165static
167 SCIP* scip, /**< SCIP data structure */
168 TCLIQUE_GRAPH* graph, /**< pointer to graph data structure */
169 SCIP_Bool* colored, /**< array for marking yet colored nodes */
170 int* maxstablesetnodes, /**< pointer to store nodes of the maximum weight stableset */
171 int* nmaxstablesetnodes /**< pointer to store number of nodes in the maximum weight stableset */
172 )
173{
174 SCIP_Bool indnode;
175 int nnodes;
176 int i;
177 int j;
178 int* degrees;
179 int* sortednodes;
180 SCIP_Real* values; /* values for sorting the nodes: deg(v)+w(v)*nnodes */
181
182 assert(scip != NULL);
183 assert(graph != NULL);
184 assert(maxstablesetnodes != NULL);
185 assert(nmaxstablesetnodes != NULL);
186
187 /* get number of nodes */
188 nnodes = tcliqueGetNNodes(graph);
189 *nmaxstablesetnodes = 0;
190
191 /* get the degrees for the nodes in the graph */
192 degrees = tcliqueGetDegrees(graph);
194 SCIP_CALL( SCIPallocBufferArray(scip, &sortednodes, nnodes) );
195
196 /* set values to the nodes which are used for sorting them */
197 /* value = degree of the node + weight of the node * number of nodes, therefore the yet colored nodes
198 (which have weight 0) have lower values than the not yet colored nodes which have weight 1 */
199 for ( i = 0; i < nnodes; i++ )
200 {
201 sortednodes[i] = i;
202 values[i] = ( colored[i] == TRUE ? degrees[i] : degrees[i]+nnodes );
203 }
204
205 /* sort the nodes w.r.t. the computed values */
206 SCIPsortDownRealInt(values, sortednodes, nnodes);
207
208 /* insert first node */
209 maxstablesetnodes[0] = sortednodes[0];
210 (*nmaxstablesetnodes) = 1;
211 for ( i = 1; i < nnodes; i++)
212 {
213 /* check whether node is independent to nodes in the set */
214 indnode = TRUE;
215 for ( j = 0; j < (*nmaxstablesetnodes); j++ )
216 {
217 if ( tcliqueIsEdge(graph, sortednodes[i], maxstablesetnodes[j]) )
218 {
219 indnode = FALSE;
220 break;
221 }
222 }
223 if ( indnode == TRUE )
224 {
225 /* node is independent, thus add it to the set */
226 maxstablesetnodes[*nmaxstablesetnodes] = sortednodes[i];
227 (*nmaxstablesetnodes) = (*nmaxstablesetnodes)+1;
228 }
229
230 }
231 SCIPfreeBufferArray(scip, &sortednodes);
232 SCIPfreeBufferArray(scip, &values);
233
234 return SCIP_OKAY;
235}
236
237/** Calculates a good scalar value to use in order to scale the dual weights to integer values without large loss of precision */
238static
240 SCIP_PRICERDATA* pricerdata, /**< pricer data */
241 int nnodes /**< number of nodes */
242 )
243{
244 SCIP_Real maxsum = 0.0;
245 SCIP_Real maxscale;
246 SCIP_Bool scalesuccess;
247 int i;
248
249 /* calculate largest possible sum in maximum clique problem */
250 for ( i = 0; i < nnodes; ++i )
251 maxsum += pricerdata->pi[i];
252
253 /* Calculate largest possible scalar value so that this sum is still representable using the type of TCLIQUE_WEIGHT (int).
254 * A buffer of nnodes+1 is used for roundoff errors. */
255 if ( maxsum == 0.0 )
256 maxscale = 1e20;
257 else
258 maxscale = (INT_MAX - nnodes - 1) / maxsum;
259
260 SCIP_CALL( SCIPcalcIntegralScalar(pricerdata->pi, nnodes, -MINDELTA, MAXDELTA, MAXDNOM, maxscale,
261 &pricerdata->scalefactor, &scalesuccess) );
262
263 /* if no nice denominator can be found, use the largest possible scaling value to reduce numerical issues */
264 if ( ! scalesuccess )
265 pricerdata->scalefactor = maxscale;
266
267 return SCIP_OKAY;
268}
269
270/** get scaled weight */
271static
273 SCIP_Real val, /**< value to be scaled */
274 SCIP_Real scalefactor, /**< scaling factor */
275 SCIP_Real mindelta /**< minimal delta value */
276 )
277{
278 SCIP_Real scaledval;
279 SCIP_Real downval;
280 SCIP_Real upval;
281 TCLIQUE_WEIGHT intval;
282
283 scaledval = val * scalefactor;
284 downval = EPSFLOOR(scaledval, 0.0); /*lint !e835*/
285 upval = EPSCEIL(scaledval, 0.0); /*lint !e835*/
286
287 if ( SCIPrelDiff(scaledval, upval) >= mindelta )
288 intval = (TCLIQUE_WEIGHT) upval;
289 else
290 intval = (TCLIQUE_WEIGHT) downval;
291
292 return intval;
293}
294
295/** generates improving variables using a stable set found by the algorithm for maximum weight clique,
296 * decides whether to stop generating cliques with the algorithm for maximum weight clique
297 */
298static
299TCLIQUE_NEWSOL(tcliqueNewsolPricer)
300{
301 SCIP_PRICERDATA* pricerdata;
302 int i;
303
304 assert(acceptsol != NULL);
305 assert(stopsolving != NULL);
306
307 pricerdata = (SCIP_PRICERDATA*)tcliquedata;
308
309 assert(pricerdata != NULL);
310 assert(pricerdata->scip != NULL);
311 assert(pricerdata->nstablesetsfound >= 0);
312 assert(pricerdata->scalefactor > 0);
313
314 *acceptsol = FALSE;
315 *stopsolving = FALSE;
316
317 /* if the stable set was already created in a former pricing round, we don't have to add it a second time */
318 if ( !COLORprobStableSetIsNew(pricerdata->scip, cliquenodes, ncliquenodes) )
319 return;
320
321 /* compute the index, at which the new stable set will be stored in the improvingstablesets-array */
322 pricerdata->actindex = (pricerdata->actindex+1)%(pricerdata->maxvarsround);
323
324 /* write the new improving stable set into the improvingstablesets-array */
325 pricerdata->nstablesetnodes[pricerdata->actindex] = ncliquenodes;
326 for ( i = 0; i < ncliquenodes; i++ )
327 pricerdata->improvingstablesets[pricerdata->actindex][i] = cliquenodes[i];
328
329 /* accept the solution as new incumbent */
330 *acceptsol = TRUE;
331
332 /* stop solving if we found maxvarsround variables and we are not proving optimality */
333 if ( ! pricerdata->onlybest && pricerdata->actindex+1 >= pricerdata->maxvarsround )
334 *stopsolving = TRUE;
335
336}/*lint !e715*/
337
338
339/*
340 * Callback methods of variable pricer
341 */
342
343/** copy method for pricer plugins (called when SCIP copies plugins) */
344static
345SCIP_DECL_PRICERCOPY(pricerCopyColoring)
346{ /*lint --e{715}*/
347 assert(scip != NULL);
348 assert(pricer != NULL);
349
351
352 return SCIP_OKAY;
353}
354
355
356/** destructor of variable pricer to free user data (called when SCIP is exiting) */
357static
358SCIP_DECL_PRICERFREE(pricerFreeColoring)
359{
360 SCIP_PRICERDATA* pricerdata;
361
362 assert(scip != NULL);
363
364 /* get pricerdata */
365 pricerdata = SCIPpricerGetData(pricer);
366
367 /* free memory for pricerdata*/
368 if ( pricerdata != NULL )
369 {
370 SCIPfreeBlockMemory(scip, &pricerdata);
371 }
372
373 SCIPpricerSetData(pricer, NULL);
374 return SCIP_OKAY;
375}
376
377
378
379/** solving process initialization method of variable pricer (called when branch and bound process is about to begin) */
380static
381SCIP_DECL_PRICERINITSOL(pricerInitsolColoring)
382{
383 SCIP_PRICERDATA* pricerdata;
384
385 assert(scip != NULL);
386 assert(pricer != NULL);
387
388 pricerdata = SCIPpricerGetData(pricer);
389 assert(pricerdata != NULL);
390
391 /* set maximal number of variables to be priced in each round */
392 SCIP_CALL( SCIPsetIntParam(scip, "pricers/coloring/maxvarsround",
393 MAX(5,COLORprobGetNStableSets(scip))*MAX(50,COLORprobGetNNodes(scip))/50) ); /*lint !e666*/
394
395 pricerdata->bbnode = NULL;
396
397 /* allocate memory */
399
400 return SCIP_OKAY;
401}
402
403
404
405/** solving process deinitialization method of variable pricer (called before branch and bound process data is freed) */
406static
407SCIP_DECL_PRICEREXITSOL(pricerExitsolColoring)
408{
409 SCIP_PRICERDATA* pricerdata;
410 int i;
411
412 assert(scip != NULL);
413 assert(pricer != NULL);
414
415 pricerdata = SCIPpricerGetData(pricer);
416 assert(pricerdata != NULL);
417
418 /* free memory */
419 for ( i = 0; i < pricerdata->maxvarsround; i++ )
420 {
421 SCIPfreeBlockMemoryArray(scip, &(pricerdata->improvingstablesets[i]), pricerdata->improvingstablesetssize);
422 }
423 SCIPfreeBlockMemoryArray(scip, &(pricerdata->improvingstablesets), pricerdata->maxvarsround);
424 SCIPfreeBlockMemoryArray(scip, &(pricerdata->nstablesetnodes), pricerdata->maxvarsround);
426
427 return SCIP_OKAY;
428}
429
430
431
432
433/** reduced cost pricing method of variable pricer for feasible LPs */
434static
435SCIP_DECL_PRICERREDCOST(pricerRedcostColoring)
436{
437 SCIP_PRICERDATA* pricerdata; /* the data of the pricer */
438
439 TCLIQUE_GRAPH* graph; /* the current graph */
440 TCLIQUE_GRAPH* cgraph; /* the complementary graph, used for tclique-algorithm */
441 int nnodes; /* number of nodes in the graph */
442
443 int* sortednodes; /* array of the nodes, sorted in specific way, atm by decreasing dual-solution*/
444 SCIP_Real maxstablesetweightreal;/* weigth of the maximal stable set computed by the greedy */
445 SCIP_Bool indnode; /* boolean for greedy: is node independant? */
446
447 int* maxstablesetnodes; /* pointer to store nodes of the maximum weight clique */
448 int nmaxstablesetnodes; /* number of nodes in the maximum weight clique */
449 TCLIQUE_WEIGHT maxstablesetweight; /* weight of the maximum weight clique */
450 TCLIQUE_STATUS status; /* status of clique-computation */
451 SCIP_Real maxredcost;
452
453 SCIP_VAR* var; /* pointer to the new created variable */
454 int setnumber; /* index of the new created variable */
455
456 int i;
457 int j;
458
459 assert(scip != NULL);
460 assert(pricer != NULL);
461
462 /* get pricer data */
463 pricerdata = SCIPpricerGetData(pricer);
464 assert(pricerdata != NULL);
465
466 /* count down number of remaining pricing rounds at the current node */
467 if ( pricerdata->bbnode == SCIPgetCurrentNode(scip) )
468 {
469 if ( pricerdata->noderounds > 0 )
470 pricerdata->noderounds--;
471 }
472 else
473 {
474 if ( pricerdata->bbnode == NULL )
475 {
476 pricerdata->noderounds = pricerdata->maxroundsroot;
477 pricerdata->lowerbound = - SCIPinfinity(scip);
478 }
479 else
480 {
481 pricerdata->noderounds = pricerdata->maxroundsnode;
482 pricerdata->lowerbound = - SCIPinfinity(scip);
483 }
484 pricerdata->bbnode = SCIPgetCurrentNode(scip);
485 }
486 /* stop pricing if limit for pricing rounds reached */
487 if ( pricerdata->noderounds == 0 )
488 {
489 SCIPdebugMessage("maxrounds reached, pricing interrupted\n");
490
491 /* set result and lowerbound pointer */
493 *lowerbound = pricerdata->lowerbound;
494
495 return SCIP_OKAY;
496 }
497
498 /* set result pointer */
500
501 /* get graph and number of nodes */
503 assert(graph != NULL);
504 nnodes = tcliqueGetNNodes(graph);
505
507
508 /* get constraints */
509 pricerdata->constraints = COLORprobGetConstraints(scip);
510
511 /* get dual solutions and save them in pi */
512 for ( i = 0; i < nnodes; i++)
513 {
514 pricerdata->pi[i] = SCIPgetDualsolSetppc(scip, pricerdata->constraints[i]);
515 }
516 pricerdata->nstablesetsfound = 0;
517 /* ......greedy-heuristic........ */
518 if ( pricerdata->usegreedy )
519 {
520 SCIP_CALL( SCIPallocBufferArray(scip, &sortednodes, nnodes) );
521 SCIP_CALL( SCIPallocBufferArray(scip, &maxstablesetnodes, nnodes) );
522 SCIP_CALL( sortNodes(scip, pricerdata->pi, nnodes, sortednodes) );
523
524 SCIPdebugMessage("starting greedy...\n");
525
526 /* insert first node */
527 maxstablesetnodes[0] = sortednodes[0];
528 nmaxstablesetnodes = 1;
529 maxstablesetweightreal = pricerdata->pi[sortednodes[0]];
530
531 for ( i = 1; i < nnodes; i++ )
532 {
533 /* test if node is independant to nodes in stable set */
534 indnode = TRUE;
535 for ( j = 0; j < nmaxstablesetnodes; j++ )
536 {
537 if ( tcliqueIsEdge(graph, sortednodes[i], maxstablesetnodes[j]) )
538 {
539 indnode = FALSE;
540 break;
541 }
542 }
543 /* if node is independant to nodes in stable set, insert it into stable set*/
544 if ( indnode )
545 {
546 maxstablesetnodes[nmaxstablesetnodes] = sortednodes[i];
547 nmaxstablesetnodes = nmaxstablesetnodes+1;
548 maxstablesetweightreal = maxstablesetweightreal + pricerdata->pi[sortednodes[i]];
549 }
550 }
551
552
553 SCIPdebugMessage("value of the greedy-heuristik: %f \n", maxstablesetweightreal);
554 setnumber = -1;
555 if ( SCIPisFeasGT(scip, maxstablesetweightreal, 1.0) && COLORprobStableSetIsNew(scip, maxstablesetnodes, nmaxstablesetnodes) )
556 {
557 SCIP_CALL( COLORprobAddNewStableSet(scip, maxstablesetnodes, nmaxstablesetnodes, &setnumber) );
558
559 assert(setnumber >= 0);
560 pricerdata->nstablesetnodes[pricerdata->nstablesetsfound] = nmaxstablesetnodes;
561 for ( i = 0; i < nmaxstablesetnodes; i++ )
562 {
563 pricerdata->improvingstablesets[pricerdata->nstablesetsfound][i] = maxstablesetnodes[i];
564 }
565 pricerdata->nstablesetsfound += 1;
566
567 /* create variable for the stable set and add it to SCIP */
569 TRUE, TRUE, NULL, NULL, NULL, NULL, (SCIP_VARDATA*)(size_t)setnumber) ); /*lint !e571*/
570
575
576 /* add variable to the constraints in which it appears */
577 for ( i = 0; i < nmaxstablesetnodes; i++ )
578 {
579 /* add variable to node constraints of nodes in the set */
580 SCIP_CALL( SCIPaddCoefSetppc(scip, pricerdata->constraints[maxstablesetnodes[i]], var) );
581 }
582 }
583
584 SCIPfreeBufferArray(scip, &maxstablesetnodes);
585 SCIPfreeBufferArray(scip, &sortednodes);
586
587 SCIPdebugMessage("%d vars created via greedy\n", pricerdata->nstablesetsfound);
588 }
589
590
591 /* solve with tclique-algorithm */
592 /* only use tclique if the greedy found no improving stable set */
593 if ( pricerdata->nstablesetsfound == 0 && pricerdata->usetclique )
594 {
595 SCIPdebugMessage("starting tclique algorithm...\n");
596 maxredcost = 0;
597
598 /* get the complementary graph from the current cons */
600 SCIP_CALL( SCIPallocBufferArray(scip, &maxstablesetnodes, nnodes) );
601
602 /* get dual solutions and set weight of nodes */
603 /* clamp solutions to [0,1] for safety; numerical errors may be problematic */
604 for ( i = 0; i < nnodes; i++ )
605 {
606 SCIP_Real dualsol;
607
608 dualsol = SCIPgetDualsolSetppc(scip, pricerdata->constraints[i]);
609 pricerdata->pi[i] = MAX( MIN(dualsol, 1.0), 0.0);
610 }
611 SCIP_CALL( calculateScalingValue(pricerdata, nnodes) );
612
613 /* change the weights for the nodes in the graph to the dual solution value * scalefactor */
614 for ( i = 0; i < nnodes; i++ )
615 {
616 tcliqueChangeWeight(cgraph, i, getScaledDualWeight(pricerdata->pi[i], pricerdata->scalefactor, -MINDELTA)); /*lint !e712 !e747*/
617 }
618 /* clear the improvingstablesets array */
619 pricerdata->actindex = -1;
620 for ( i = 0; i < pricerdata->maxvarsround; i++ )
621 pricerdata->nstablesetnodes[i] = 0;
622
623 /* compute maximal clique */
624 tcliqueMaxClique(NULL, NULL, NULL, NULL, cgraph, tcliqueNewsolPricer, (TCLIQUE_DATA*)pricerdata, maxstablesetnodes,
625 &(nmaxstablesetnodes), &maxstablesetweight, 0,
626 getScaledDualWeight(1.0, pricerdata->scalefactor, -MINDELTA), pricerdata->maxtcliquenodes, 0, INT_MAX, -1,
627 NULL, &status);
628 assert(status == TCLIQUE_OPTIMAL || status == TCLIQUE_USERABORT);
629
630 /* if only the best variable should be priced per round, take the one which is given as return value from
631 * tcliqueMaxClique and put it into improvingstablesets array so that it will be inserted into the LP */
632 if ( pricerdata->onlybest && pricerdata->maxvarsround == 1 )
633 {
634 pricerdata->nstablesetnodes[0] = nmaxstablesetnodes;
635 for ( i = 0; i < nmaxstablesetnodes; i++ )
636 pricerdata->improvingstablesets[0][i] = maxstablesetnodes[i];
637 }
638
639 SCIPfreeBufferArray(scip, &maxstablesetnodes);
640
641 /* insert all variables in the array improvingstablesets into the LP */
642 for ( i = 0; i < pricerdata->maxvarsround; i++ )
643 {
644 if ( pricerdata->nstablesetnodes[i] > 0 )
645 {
646 maxstablesetweightreal = 0;
647 for ( j = 0; j < pricerdata->nstablesetnodes[i]; j++ )
648 maxstablesetweightreal += pricerdata->pi[pricerdata->improvingstablesets[i][j]];
649
650 if ( maxredcost < maxstablesetweightreal )
651 maxredcost = maxstablesetweightreal;
652
653 if ( SCIPisFeasGT(scip, maxstablesetweightreal, 1.0) )
654 {
655 setnumber = -1;
656
657 /* insert new variable */
658 SCIP_CALL( COLORprobAddNewStableSet(pricerdata->scip, pricerdata->improvingstablesets[i],
659 pricerdata->nstablesetnodes[i], &setnumber) );
660
661 /* only insert, if there yet is no variable for this stable set */
662 if ( setnumber >= 0 )
663 {
664 /* create variable for the stable set and add it to SCIP */
665 SCIP_CALL( SCIPcreateVar(pricerdata->scip, &var, NULL, 0.0, 1.0, 1.0, SCIP_VARTYPE_BINARY,
666 TRUE, TRUE, NULL, NULL, NULL, NULL, (SCIP_VARDATA*)(size_t)setnumber) ); /*lint !e571*/
667
668 SCIP_CALL( COLORprobAddVarForStableSet(pricerdata->scip, setnumber, var) );
670 SCIP_CALL( SCIPaddPricedVar(pricerdata->scip, var, 1.0) );
672
673 pricerdata->nstablesetsfound += 1;
674
675 /* add variable to the constraints in which it appears */
676 for ( j = 0; j < pricerdata->nstablesetnodes[i]; j++ )
677 {
678 /* add variable to node constraints of nodes in the set */
679 SCIP_CALL( SCIPaddCoefSetppc(pricerdata->scip,
680 pricerdata->constraints[pricerdata->improvingstablesets[i][j]], var) );
681 }
682 }
683 }
684 }
685 }
686
687 if ( status == TCLIQUE_OPTIMAL && SCIPisFeasGT(scip, maxredcost, 1.0) )
688 {
690 {
691 assert( maxredcost > 0.0 );
692 pricerdata->lowerbound = MAX(pricerdata->lowerbound, SCIPgetLPObjval(scip) / maxredcost); /*lint !e666*/
693 SCIP_CALL( SCIPupdateLocalLowerbound(scip,pricerdata->lowerbound) );
694 }
695 }
696 }
697
698 return SCIP_OKAY;
699}/*lint !e715*/
700
701
702/** farkas pricing method of variable pricer for infeasible LPs */
703static
704SCIP_DECL_PRICERFARKAS(pricerFarkasColoring)
705{
706 TCLIQUE_GRAPH* graph;
707 int nnodes; /* number of nodes */
708 int* maxstablesetnodes; /* array containig the nodes of the max stable set */
709 int nmaxstablesetnodes; /* number of nodes in stable set */
710 int setnumber; /* number of already found stable sets */
711 SCIP_VAR* var; /* var for the actual stable set */
712 SCIP_CONS** constraints; /* array of added constraints */
713 SCIP_Bool* colored; /* array for marking of yet colored nodes
714 colored_i = true iff node i is already colored */
715 int** stablesets;
716 int* nstablesetelements;
717 int nstablesets;
718 int i;
719 int j;
720 assert(scip != NULL);
721
723 assert(graph != NULL);
724
726 assert(nnodes > 0);
727
728 /* get the node-constraits */
729 constraints = COLORprobGetConstraints(scip);
730 assert(constraints != NULL);
731
732 /* get all yet computed stable sets */
733 COLORprobGetStableSets(scip, &stablesets, &nstablesetelements, &nstablesets);
734 assert(stablesets != NULL && nstablesetelements != NULL);
735 assert(nstablesets >= 0);
736 assert(nnodes == tcliqueGetNNodes(graph));
737
738 /* allocate memory for arrays */
740 SCIP_CALL( SCIPallocBufferArray( scip, &maxstablesetnodes, nnodes) );
741 nmaxstablesetnodes = 0;
742
743 /* fill colored-array with FALSE */
744 BMSclearMemoryArray(colored, nnodes);
745
746 /* go through all stable sets and set colored to true for nodes in them */
747 for ( i = 0; i < nstablesets; i++ )
748 {
752 {
753 for ( j = 0; j < nstablesetelements[i]; j++ )
754 {
755 colored[stablesets[i][j]] = TRUE;
756 }
757 }
758 }
759
760 /* create maximal Stable Sets until all Nodes are covered */
761 while ( hasUncoloredNode(graph, colored) )
762 {
763 SCIP_CALL( greedyStableSet(scip, graph, colored, maxstablesetnodes, &nmaxstablesetnodes) );
764 SCIPsortDownInt(maxstablesetnodes, nmaxstablesetnodes);
765 SCIP_CALL( COLORprobAddNewStableSet(scip, maxstablesetnodes, nmaxstablesetnodes, &setnumber) );
766 assert(setnumber != -1);
767
768 /* create variable for the stable set and add it to SCIP */
770 TRUE, TRUE, NULL, NULL, NULL, NULL, (SCIP_VARDATA*) (size_t) setnumber) ); /*lint !e571*/
775
776 for ( i = 0; i < nmaxstablesetnodes; i++ )
777 {
778 /* add variable to node constraints of nodes in the set */
779 SCIP_CALL( SCIPaddCoefSetppc(scip, constraints[maxstablesetnodes[i]], var) );
780 /* mark node as colored */
781 colored[maxstablesetnodes[i]] = TRUE;
782 }
783 }
784 /* free memory */
785 SCIPfreeBufferArray(scip, &maxstablesetnodes);
786 SCIPfreeBufferArray(scip, &colored);
787
788 return SCIP_OKAY;
789}/*lint !e715*/
790
791/** method to call, when the maximal number of variables priced in each round is changed */
792static
793SCIP_DECL_PARAMCHGD(paramChgdMaxvarsround)
794{
795 SCIP_PARAMDATA* paramdata;
796 SCIP_PRICERDATA* pricerdata;
797 int i;
798
799 paramdata = SCIPparamGetData(param);
800 assert(paramdata != NULL);
801 pricerdata = (SCIP_PRICERDATA*) paramdata;
802
803 if( pricerdata->maxvarsround == pricerdata->oldmaxvarsround )
804 return SCIP_OKAY;
805
806 if ( pricerdata->maxvarsround <= 1 )
807 pricerdata->maxvarsround = 2;
808
809 if ( pricerdata->maxvarsround == pricerdata->oldmaxvarsround && pricerdata->nstablesetnodes != NULL )
810 return SCIP_OKAY;
811
812 /* free old memory */
813 if ( pricerdata -> oldmaxvarsround > 0 )
814 {
815 /* free memory */
816 for ( i = 0; i < pricerdata->oldmaxvarsround; i++ )
817 {
818 SCIPfreeBlockMemoryArray(scip, &(pricerdata->improvingstablesets[i]), pricerdata->improvingstablesetssize);
819 }
820 SCIPfreeBlockMemoryArray(scip, &(pricerdata->improvingstablesets), pricerdata->oldmaxvarsround);
821 SCIPfreeBlockMemoryArray(scip, &(pricerdata->nstablesetnodes), pricerdata->oldmaxvarsround);
822 }
823
824 /* allocate memory of the new size */
825 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(pricerdata->nstablesetnodes), pricerdata->maxvarsround) );
826 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(pricerdata->improvingstablesets), pricerdata->maxvarsround) );
827 pricerdata->improvingstablesetssize = COLORprobGetNNodes(scip);
828 for ( i = 0; i < pricerdata->maxvarsround; i++ )
829 {
830 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(pricerdata->improvingstablesets[i]), pricerdata->improvingstablesetssize) ); /*lint !e866*/
831 }
832
833 SCIPdebugMessage("maxvarsround changed from %d to %d\n", pricerdata->oldmaxvarsround, pricerdata->maxvarsround);
834
835 pricerdata->oldmaxvarsround = pricerdata->maxvarsround;
836
837 return SCIP_OKAY;
838}
839
840
841/*
842 * variable pricer specific interface methods
843 */
844
845/** creates the coloring variable pricer and includes it in SCIP */
847 SCIP* scip /**< SCIP data structure */
848 )
849{
850 SCIP_PRICERDATA* pricerdata;
851 SCIP_PRICER* pricer;
852
853 SCIP_CALL( SCIPallocBlockMemory(scip, &pricerdata) );
854 pricerdata->scip = scip;
855
856 pricerdata->maxvarsround = 0;
857 pricerdata->oldmaxvarsround = 0;
858
859
860 pricer = NULL;
861 /* include variable pricer */
863 pricerRedcostColoring, pricerFarkasColoring, pricerdata) );
864 assert(pricer != NULL);
865
866 /* include non-fundamental callbacks via setter functions */
867 SCIP_CALL( SCIPsetPricerCopy(scip, pricer, pricerCopyColoring) );
868 SCIP_CALL( SCIPsetPricerFree(scip, pricer, pricerFreeColoring) );
869 SCIP_CALL( SCIPsetPricerInitsol(scip, pricer, pricerInitsolColoring) );
870 SCIP_CALL( SCIPsetPricerExitsol(scip, pricer, pricerExitsolColoring) );
871
873 "pricers/coloring/maxvarsround",
874 "maximum number of variables that the coloring variable pricer creates each round",
875 &pricerdata->maxvarsround, TRUE, DEFAULT_MAXVARSROUND, -1, INT_MAX, paramChgdMaxvarsround, (SCIP_PARAMDATA*)pricerdata) );
876
878 "pricers/coloring/usetclique",
879 "should the tclique-algorithm be used to solve the pricing-problem to optimality? WARNING: computed (optimal) solutions are not necessarily optimal if this is set to FALSE.",
880 &pricerdata->usetclique, TRUE, DEFAULT_USETCLIQUE, NULL, NULL) );
881
883 "pricers/coloring/usegreedy",
884 "should a greedy method be used to compute improving stable sets before potential use of tclique",
885 &pricerdata->usegreedy, FALSE, DEFAULT_USEGREEDY, NULL, NULL) );
886
888 "pricers/coloring/onlybest",
889 "should the best variables be addded to the problem instead of adding the first found variables?",
890 &pricerdata->onlybest, FALSE, DEFAULT_ONLYBEST, NULL, NULL) );
891
893 "pricers/coloring/maxroundsroot",
894 "maximum number of pricing rounds in the root node (-1: no limit)",
895 &pricerdata->maxroundsroot, TRUE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
896
898 "pricers/coloring/maxroundsnode",
899 "maximum number of pricing rounds in each node (except root node)(-1: no limit)",
900 &pricerdata->maxroundsnode, TRUE, DEFAULT_MAXROUNDSNODE, -1, INT_MAX, NULL, NULL) );
901
903 "pricers/coloring/maxtcliquenodes",
904 "maximum number of B&B-nodes used in the tclique-algorithm",
905 &pricerdata->maxtcliquenodes, TRUE, DEFAULT_MAXTCLIQUENODES, 0, INT_MAX, NULL, NULL) );
906
907 return SCIP_OKAY;
908}
#define DEFAULT_USETCLIQUE
#define DEFAULT_MAXROUNDSROOT
#define MAXDNOM
TCLIQUE_GRAPH * COLORconsGetCurrentGraph(SCIP *scip)
TCLIQUE_GRAPH * COLORconsGetComplementaryGraph(SCIP *scip)
constraint handler for storing the graph at each node of the tree
#define NULL
Definition def.h:257
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define EPSCEIL(x, eps)
Definition def.h:201
#define EPSFLOOR(x, eps)
Definition def.h:200
#define SCIP_CALL(x)
Definition def.h:364
#define nnodes
Definition gastrans.c:74
SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_Real SCIPgetDualsolSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddPricedVar(SCIP *scip, SCIP_VAR *var, SCIP_Real score)
Definition scip_prob.c:1984
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition scip_prob.c:4289
SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
Definition misc.c:9641
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11162
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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition scip_param.c:487
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition scip_lp.c:253
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPsetPricerFree(SCIP *scip, SCIP_PRICER *pricer,)
void SCIPpricerSetData(SCIP_PRICER *pricer, SCIP_PRICERDATA *pricerdata)
Definition pricer.c:532
SCIP_PRICERDATA * SCIPpricerGetData(SCIP_PRICER *pricer)
Definition pricer.c:522
SCIP_RETCODE SCIPsetPricerCopy(SCIP *scip, SCIP_PRICER *pricer,)
const char * SCIPpricerGetName(SCIP_PRICER *pricer)
Definition pricer.c:619
SCIP_RETCODE SCIPincludePricerBasic(SCIP *scip, SCIP_PRICER **pricerptr, const char *name, const char *desc, int priority, SCIP_Bool delay, SCIP_DECL_PRICERREDCOST((*pricerredcost)), SCIP_DECL_PRICERFARKAS((*pricerfarkas)), SCIP_PRICERDATA *pricerdata)
SCIP_RETCODE SCIPsetPricerExitsol(SCIP *scip, SCIP_PRICER *pricer,)
SCIP_RETCODE SCIPsetPricerInitsol(SCIP *scip, SCIP_PRICER *pricer,)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition scip_tree.c:91
SCIP_NODE * SCIPgetRootNode(SCIP *scip)
Definition scip_tree.c:110
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition var.c:23578
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition scip_var.c:120
SCIP_RETCODE SCIPchgVarUbLazy(SCIP *scip, SCIP_VAR *var, SCIP_Real lazyub)
Definition scip_var.c:6362
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23738
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
void SCIPsortDownInt(int *intarray, int len)
return SCIP_OKAY
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_VAR * var
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition paramset.c:676
static SCIP_RETCODE greedyStableSet(SCIP *scip, TCLIQUE_GRAPH *graph, SCIP_Bool *colored, int *maxstablesetnodes, int *nmaxstablesetnodes)
#define MAXDELTA
#define DEFAULT_MAXVARSROUND
#define PRICER_PRIORITY
#define PRICER_NAME
static SCIP_RETCODE calculateScalingValue(SCIP_PRICERDATA *pricerdata, int nnodes)
#define MINDELTA
static TCLIQUE_WEIGHT getScaledDualWeight(SCIP_Real val, SCIP_Real scalefactor, SCIP_Real mindelta)
SCIP_RETCODE SCIPincludePricerColoring(SCIP *scip)
#define DEFAULT_ONLYBEST
#define DEFAULT_USEGREEDY
#define PRICER_DELAY
#define DEFAULT_MAXTCLIQUENODES
static SCIP_RETCODE sortNodes(SCIP *scip, SCIP_Real *weights, int nnodes, int *sortednodes)
static SCIP_Bool hasUncoloredNode(TCLIQUE_GRAPH *graph, SCIP_Bool *colored)
#define DEFAULT_MAXROUNDSNODE
#define PRICER_DESC
variable pricer for the vertex coloring problem
SCIP_CONS ** COLORprobGetConstraints(SCIP *scip)
SCIP_RETCODE COLORprobAddNewStableSet(SCIP *scip, int *stablesetnodes, int nstablesetnodes, int *setindex)
int COLORprobGetNNodes(SCIP *scip)
SCIP_VAR * COLORprobGetVarForStableSet(SCIP *scip, int setindex)
void COLORprobGetStableSets(SCIP *scip, int ***stablesets, int **nelements, int *nstablesets)
SCIP_Bool COLORprobStableSetIsNew(SCIP *scip, int *stablesetnodes, int nstablesetnodes)
SCIP_RETCODE COLORprobAddVarForStableSet(SCIP *scip, int setindex, SCIP_VAR *var)
int COLORprobGetNStableSets(SCIP *scip)
#define SCIPdebugMessage
Definition pub_message.h:96
file reader for vertex coloring instances
SCIP * scip
Definition cons_sos1.c:237
@ TCLIQUE_USERABORT
Definition tclique.h:65
@ TCLIQUE_OPTIMAL
Definition tclique.h:66
void tcliqueChangeWeight(TCLIQUE_GRAPH *tcliquegraph, int node, TCLIQUE_WEIGHT weight)
int * tcliqueGetDegrees(TCLIQUE_GRAPH *tcliquegraph)
enum TCLIQUE_Status TCLIQUE_STATUS
Definition tclique.h:68
int TCLIQUE_WEIGHT
Definition tclique.h:48
void tcliqueMaxClique(TCLIQUE_GETNNODES((*getnnodes)), TCLIQUE_GETWEIGHTS((*getweights)), TCLIQUE_ISEDGE((*isedge)), TCLIQUE_SELECTADJNODES((*selectadjnodes)), TCLIQUE_GRAPH *tcliquegraph, TCLIQUE_NEWSOL((*newsol)), TCLIQUE_DATA *tcliquedata, int *maxcliquenodes, int *nmaxcliquenodes, TCLIQUE_WEIGHT *maxcliqueweight, TCLIQUE_WEIGHT maxfirstnodeweight, TCLIQUE_WEIGHT minweight, int maxntreenodes, int backtrackfreq, int maxnzeroextensions, int fixednode, int *ntreenodes, TCLIQUE_STATUS *status)
struct TCLIQUE_Graph TCLIQUE_GRAPH
Definition tclique.h:49
struct TCLIQUE_Data TCLIQUE_DATA
Definition tclique.h:50
#define TCLIQUE_NEWSOL(x)
Definition tclique.h:88
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
struct SCIP_ParamData SCIP_PARAMDATA
#define SCIP_DECL_PARAMCHGD(x)
#define SCIP_DECL_PRICERFREE(x)
Definition type_pricer.h:63
#define SCIP_DECL_PRICERREDCOST(x)
#define SCIP_DECL_PRICERFARKAS(x)
#define SCIP_DECL_PRICEREXITSOL(x)
#define SCIP_DECL_PRICERINITSOL(x)
Definition type_pricer.h:90
struct SCIP_Pricer SCIP_PRICER
Definition type_pricer.h:44
struct SCIP_PricerData SCIP_PRICERDATA
Definition type_pricer.h:45
#define SCIP_DECL_PRICERCOPY(x)
Definition type_pricer.h:55
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_SUCCESS
Definition type_result.h:58
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_VarData SCIP_VARDATA
Definition type_var.h:167
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64