50
50
*
51
51
* To solve the above integer program, we create a new SCIP instance within SCIP and use the usual functions to create
52
52
* variables and constraints. Besides, we need the current dual solutions to all set covering constraints (each stands
53
- * for one item) which are the objective coefficients of the binary variables. Therefore, we use the function
54
- * SCIPgetDualsolSetppc() which returns the dual solutions for the given set covering constraint.
53
+ * for one item) which are the objective coefficients of the binary variables. Therefore, we use the functions
54
+ * SCIPgetDualsolSetppc() and SCIPgetDualfarkasSetppc() which return the dual solution or ray for the given set
55
+ * covering constraint for a feasible or infeasible restricted master LP.
55
56
*
56
57
* Since we also want to generate new variables during search, we have to care that we do not generate variables over
57
58
* and over again. For example, if we branched or fixed a certain packing to zero, we have to make sure that we do not
58
59
* generate the corresponding variables at that node again. For this, we have to add constraints forbidding to generate
59
60
* variables which are locally fixed to zero. See the function addFixedVarsConss() for more details. While using the
60
61
* \ref BINPACKING_BRANCHING "Ryan/Foster branching", we also have to ensure that these branching decisions are respected. This is
61
62
* realized within the function addBranchingDecisionConss().
62
- *
63
- * @note In case of this binpacking example, the master LP should not get infeasible after branching, because of the way
64
- * branching is performed. Therefore, the Farkas pricing is not implemented.
65
- * 1. In case of Ryan/Foster branching, the two items are selected in a way such that the sum of the LP values of
66
- * all columns/packings containing both items is fractional. Hence, it exists at least one column/packing which
67
- * contains both items and also at least one column/packing for each item containing this but not the other
68
- * item. That means, branching in the "same" direction stays LP feasible since there exists at least one
69
- * column/packing with both items and branching in the "differ" direction stays LP feasible since there exists
70
- * at least one column/packing containing one item, but not the other.
71
- * 2. In case of variable branching, we only branch on fractional variables. If a variable is fixed to one, there
72
- * is no issue. If a variable is fixed to zero, then we know that for each item which is part of that
73
- * column/packing, there exists at least one other column/packing containing this particular item due to the
74
- * covering constraints.
75
63
*/
76
64
77
65
/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
@@ -338,6 +326,7 @@ static
338
326
SCIP_RETCODE initPricing (
339
327
SCIP * scip , /**< SCIP data structure */
340
328
SCIP_PRICERDATA * pricerdata , /**< pricer data */
329
+ SCIP_Bool isfarkas , /**< whether we perform Farkas pricing */
341
330
SCIP * subscip , /**< pricing SCIP data structure */
342
331
SCIP_VAR * * vars /**< variable array for the items */
343
332
)
@@ -387,8 +376,8 @@ SCIP_RETCODE initPricing(
387
376
}
388
377
389
378
/* dual value in original SCIP */
390
- dual = SCIPgetDualsolSetppc (scip , cons );
391
-
379
+ dual = isfarkas ? SCIPgetDualfarkasSetppc ( scip , cons ) : SCIPgetDualsolSetppc (scip , cons );
380
+
392
381
SCIP_CALL ( SCIPcreateVarBasic (subscip , & var , SCIPconsGetName (cons ), 0.0 , 1.0 , dual , SCIP_VARTYPE_BINARY ) );
393
382
SCIP_CALL ( SCIPaddVar (subscip , var ) );
394
383
@@ -417,99 +406,15 @@ SCIP_RETCODE initPricing(
417
406
return SCIP_OKAY ;
418
407
}
419
408
420
- /**@} */
421
-
422
- /**name Callback methods
423
- *
424
- * @{
425
- */
426
-
427
- /** destructor of variable pricer to free user data (called when SCIP is exiting) */
409
+ /** perform packing pricing */
428
410
static
429
- SCIP_DECL_PRICERFREE (pricerFreeBinpacking )
430
- {
431
- SCIP_PRICERDATA * pricerdata ;
432
-
433
- assert (scip != NULL );
434
- assert (pricer != NULL );
435
-
436
- pricerdata = SCIPpricerGetData (pricer );
437
-
438
- if ( pricerdata != NULL )
439
- {
440
- /* free memory */
441
- SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> conss , pricerdata -> nitems );
442
- SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> weights , pricerdata -> nitems );
443
- SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> ids , pricerdata -> nitems );
444
-
445
- SCIPfreeBlockMemory (scip , & pricerdata );
446
- }
447
-
448
- return SCIP_OKAY ;
449
- }
450
-
451
-
452
- /** initialization method of variable pricer (called after problem was transformed) */
453
- static
454
- SCIP_DECL_PRICERINIT (pricerInitBinpacking )
455
- { /*lint --e{715}*/
456
- SCIP_PRICERDATA * pricerdata ;
457
- SCIP_CONS * cons ;
458
- int c ;
459
-
460
- assert (scip != NULL );
461
- assert (pricer != NULL );
462
-
463
- pricerdata = SCIPpricerGetData (pricer );
464
- assert (pricerdata != NULL );
465
-
466
- /* get transformed constraints */
467
- for ( c = 0 ; c < pricerdata -> nitems ; ++ c )
468
- {
469
- cons = pricerdata -> conss [c ];
470
-
471
- /* release original constraint */
472
- SCIP_CALL ( SCIPreleaseCons (scip , & pricerdata -> conss [c ]) );
473
-
474
- /* get transformed constraint */
475
- SCIP_CALL ( SCIPgetTransformedCons (scip , cons , & pricerdata -> conss [c ]) );
476
-
477
- /* capture transformed constraint */
478
- SCIP_CALL ( SCIPcaptureCons (scip , pricerdata -> conss [c ]) );
479
- }
480
-
481
- return SCIP_OKAY ;
482
- }
483
-
484
-
485
- /** solving process deinitialization method of variable pricer (called before branch and bound process data is freed) */
486
- static
487
- SCIP_DECL_PRICEREXITSOL (pricerExitsolBinpacking )
411
+ SCIP_RETCODE doPricing (
412
+ SCIP * scip , /**< SCIP data structure */
413
+ SCIP_PRICER * pricer , /**< variable pricer structure */
414
+ SCIP_Bool isfarkas , /**< whether we perform Farkas pricing */
415
+ SCIP_RESULT * result /**< pointer to store the result */
416
+ )
488
417
{
489
- SCIP_PRICERDATA * pricerdata ;
490
- int c ;
491
-
492
- assert (scip != NULL );
493
- assert (pricer != NULL );
494
-
495
- pricerdata = SCIPpricerGetData (pricer );
496
- assert (pricerdata != NULL );
497
-
498
- /* get release constraints */
499
- for ( c = 0 ; c < pricerdata -> nitems ; ++ c )
500
- {
501
- /* release constraint */
502
- SCIP_CALL ( SCIPreleaseCons (scip , & (pricerdata -> conss [c ])) );
503
- }
504
-
505
- return SCIP_OKAY ;
506
- }
507
-
508
-
509
- /** reduced cost pricing method of variable pricer for feasible LPs */
510
- static
511
- SCIP_DECL_PRICERREDCOST (pricerRedcostBinpacking )
512
- { /*lint --e{715}*/
513
418
SCIP * subscip ;
514
419
SCIP_PRICERDATA * pricerdata ;
515
420
SCIP_CONS * * conss ;
@@ -529,6 +434,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
529
434
530
435
assert (scip != NULL );
531
436
assert (pricer != NULL );
437
+ assert (result != NULL );
532
438
533
439
(* result ) = SCIP_DIDNOTRUN ;
534
440
@@ -571,7 +477,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
571
477
SCIP_CALL ( SCIPallocBufferArray (scip , & vars , nitems ) );
572
478
573
479
/* initialization local pricing problem */
574
- SCIP_CALL ( initPricing (scip , pricerdata , subscip , vars ) );
480
+ SCIP_CALL ( initPricing (scip , pricerdata , isfarkas , subscip , vars ) );
575
481
576
482
SCIPdebugMsg (scip , "solve pricer problem\n" );
577
483
@@ -582,8 +488,9 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
582
488
nsols = SCIPgetNSols (subscip );
583
489
addvar = FALSE;
584
490
585
- /* loop over all solutions and create the corresponding column to master if the reduced cost are negative for master,
586
- * that is the objective value i greater than 1.0
491
+ /* loop over all solutions and create the corresponding column to master if the reduced cost is negative for a
492
+ * feasible dual solution of the restricted master LP, that is, the objective value is greater than 1.0 if the LP is
493
+ * feasible or greater than 0.0 if the LP is infeasible
587
494
*/
588
495
for ( s = 0 ; s < nsols ; ++ s )
589
496
{
@@ -605,8 +512,8 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
605
512
continue ;
606
513
}
607
514
608
- /* check if the solution has a value greater than 1.0 */
609
- if ( SCIPisFeasGT (subscip , SCIPgetSolOrigObj (subscip , sol ), 1.0 ) )
515
+ /* check if the solution has a value greater than 1.0 in redcost pricing or greater than 0.0 in Farkas pricing */
516
+ if ( SCIPisFeasGT (subscip , SCIPgetSolOrigObj (subscip , sol ), isfarkas ? 0.0 : 1.0 ) )
610
517
{
611
518
SCIP_VAR * var ;
612
519
SCIP_VARDATA * vardata ;
@@ -648,7 +555,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
648
555
649
556
SCIP_CALL ( SCIPvardataCreateBinpacking (scip , & vardata , consids , nconss ) );
650
557
651
- /* create variable for a new column with objective function coefficient 0 .0 */
558
+ /* create variable for a new column with objective function coefficient 1 .0 */
652
559
SCIP_CALL ( SCIPcreateVarBinpacking (scip , & var , name , 1.0 , FALSE, TRUE, vardata ) );
653
560
654
561
/* add the new variable to the pricer store */
@@ -690,27 +597,110 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
690
597
return SCIP_OKAY ;
691
598
}
692
599
600
+ /**@} */
601
+
602
+ /**name Callback methods
603
+ *
604
+ * @{
605
+ */
606
+
607
+ /** destructor of variable pricer to free user data (called when SCIP is exiting) */
608
+ static
609
+ SCIP_DECL_PRICERFREE (pricerFreeBinpacking )
610
+ {
611
+ SCIP_PRICERDATA * pricerdata ;
612
+
613
+ assert (scip != NULL );
614
+ assert (pricer != NULL );
615
+
616
+ pricerdata = SCIPpricerGetData (pricer );
617
+
618
+ if ( pricerdata != NULL )
619
+ {
620
+ /* free memory */
621
+ SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> conss , pricerdata -> nitems );
622
+ SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> weights , pricerdata -> nitems );
623
+ SCIPfreeBlockMemoryArrayNull (scip , & pricerdata -> ids , pricerdata -> nitems );
624
+
625
+ SCIPfreeBlockMemory (scip , & pricerdata );
626
+ }
627
+
628
+ return SCIP_OKAY ;
629
+ }
630
+
631
+
632
+ /** initialization method of variable pricer (called after problem was transformed) */
633
+ static
634
+ SCIP_DECL_PRICERINIT (pricerInitBinpacking )
635
+ { /*lint --e{715}*/
636
+ SCIP_PRICERDATA * pricerdata ;
637
+ SCIP_CONS * cons ;
638
+ int c ;
639
+
640
+ assert (scip != NULL );
641
+ assert (pricer != NULL );
642
+
643
+ pricerdata = SCIPpricerGetData (pricer );
644
+ assert (pricerdata != NULL );
645
+
646
+ /* get transformed constraints */
647
+ for ( c = 0 ; c < pricerdata -> nitems ; ++ c )
648
+ {
649
+ cons = pricerdata -> conss [c ];
650
+
651
+ /* release original constraint */
652
+ SCIP_CALL ( SCIPreleaseCons (scip , & pricerdata -> conss [c ]) );
653
+
654
+ /* get transformed constraint */
655
+ SCIP_CALL ( SCIPgetTransformedCons (scip , cons , & pricerdata -> conss [c ]) );
656
+
657
+ /* capture transformed constraint */
658
+ SCIP_CALL ( SCIPcaptureCons (scip , pricerdata -> conss [c ]) );
659
+ }
660
+
661
+ return SCIP_OKAY ;
662
+ }
663
+
664
+
665
+ /** solving process deinitialization method of variable pricer (called before branch and bound process data is freed) */
666
+ static
667
+ SCIP_DECL_PRICEREXITSOL (pricerExitsolBinpacking )
668
+ {
669
+ SCIP_PRICERDATA * pricerdata ;
670
+ int c ;
671
+
672
+ assert (scip != NULL );
673
+ assert (pricer != NULL );
674
+
675
+ pricerdata = SCIPpricerGetData (pricer );
676
+ assert (pricerdata != NULL );
677
+
678
+ /* get release constraints */
679
+ for ( c = 0 ; c < pricerdata -> nitems ; ++ c )
680
+ {
681
+ /* release constraint */
682
+ SCIP_CALL ( SCIPreleaseCons (scip , & (pricerdata -> conss [c ])) );
683
+ }
684
+
685
+ return SCIP_OKAY ;
686
+ }
687
+
688
+ /** reduced cost pricing method of variable pricer for feasible LPs */
689
+ static
690
+ SCIP_DECL_PRICERREDCOST (pricerRedcostBinpacking )
691
+ { /*lint --e{715}*/
692
+ SCIP_CALL ( doPricing (scip , pricer , FALSE, result ) );
693
+
694
+ return SCIP_OKAY ;
695
+ }
696
+
693
697
/** farkas pricing method of variable pricer for infeasible LPs */
694
698
static
695
699
SCIP_DECL_PRICERFARKAS (pricerFarkasBinpacking )
696
700
{ /*lint --e{715}*/
697
- /** @note In case of this binpacking example, the master LP should not get infeasible after branching, because of the
698
- * way branching is performed. Therefore, the Farkas pricing is not implemented.
699
- * 1. In case of Ryan/Foster branching, the two items are selected in a way such that the sum of the LP values
700
- * of all columns/packings containing both items is fractional. Hence, it exists at least one
701
- * column/packing which contains both items and also at least one column/packing for each item containing
702
- * this but not the other item. That means, branching in the "same" direction stays LP feasible since there
703
- * exists at least one column/packing with both items and branching in the "differ" direction stays LP
704
- * feasible since there exists at least one column/packing containing one item, but not the other.
705
- * 2. In case of variable branching, we only branch on fractional variables. If a variable is fixed to one,
706
- * there is no issue. If a variable is fixed to zero, then we know that for each item which is part of
707
- * that column/packing, there exists at least one other column/packing containing this particular item due
708
- * to the covering constraints.
709
- */
710
- SCIPwarningMessage (scip , "Current master LP is infeasible, but Farkas pricing was not implemented\n" );
711
- SCIPABORT ();
701
+ SCIP_CALL ( doPricing (scip , pricer , TRUE, result ) );
712
702
713
- return SCIP_OKAY ; /*lint !e527*/
703
+ return SCIP_OKAY ;
714
704
}
715
705
716
706
/**@} */
0 commit comments