Skip to content

Commit 4508ae7

Browse files
committed
Merge remote-tracking branch 'origin/v9-minor'
2 parents 8beff14 + d672eb9 commit 4508ae7

File tree

5 files changed

+124
-139
lines changed

5 files changed

+124
-139
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ Performance improvements
141141
Examples and applications
142142
-------------------------
143143

144+
- in example Binpacking implement Farkas pricing for packings because branching can actually lead to infeasible restricted master LPs
145+
144146
Unit tests
145147
----------
146148

examples/Binpacking/src/branch_ryanfoster.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,14 @@ SCIP_DECL_BRANCHEXECLP(branchExeclpRyanFoster)
204204

205205
if( bestvalue < value )
206206
{
207-
/* there is no variable with (fractional) LP value > 0 that contains exactly one of the items */
208-
if( SCIPisEQ(scip, pairweights[i][j], pairweights[i][i])
209-
&& SCIPisEQ(scip, pairweights[i][j], pairweights[j][j]) )
210-
continue;
211-
212207
bestvalue = value;
213208
id1 = j;
214209
id2 = i;
215210
}
216211
}
217212
}
218213

219-
assert( bestvalue > 0.0 );
214+
assert( SCIPisFeasPositive(scip, bestvalue) );
220215
assert( id1 >= 0 && id1 < nitems);
221216
assert( id2 >= 0 && id2 < nitems);
222217

examples/Binpacking/src/cons_samediff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
#define CONSHDLR_NAME "samediff"
5050
#define CONSHDLR_DESC "stores the local branching decisions"
5151
#define CONSHDLR_ENFOPRIORITY 0 /**< priority of the constraint handler for constraint enforcing */
52-
#define CONSHDLR_CHECKPRIORITY 9999999 /**< priority of the constraint handler for checking feasibility */
52+
#define CONSHDLR_CHECKPRIORITY -9999999 /**< priority of the constraint handler for checking feasibility */
5353
#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
5454
#define CONSHDLR_EAGERFREQ 1 /**< frequency for using all instead of only the useful constraints in separation,
5555
* propagation and enforcement, -1 for no eager evaluations, 0 for first only */

examples/Binpacking/src/pricer_binpacking.c

Lines changed: 120 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -50,28 +50,16 @@
5050
*
5151
* To solve the above integer program, we create a new SCIP instance within SCIP and use the usual functions to create
5252
* 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.
5556
*
5657
* Since we also want to generate new variables during search, we have to care that we do not generate variables over
5758
* and over again. For example, if we branched or fixed a certain packing to zero, we have to make sure that we do not
5859
* generate the corresponding variables at that node again. For this, we have to add constraints forbidding to generate
5960
* variables which are locally fixed to zero. See the function addFixedVarsConss() for more details. While using the
6061
* \ref BINPACKING_BRANCHING "Ryan/Foster branching", we also have to ensure that these branching decisions are respected. This is
6162
* 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.
7563
*/
7664

7765
/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
@@ -338,6 +326,7 @@ static
338326
SCIP_RETCODE initPricing(
339327
SCIP* scip, /**< SCIP data structure */
340328
SCIP_PRICERDATA* pricerdata, /**< pricer data */
329+
SCIP_Bool isfarkas, /**< whether we perform Farkas pricing */
341330
SCIP* subscip, /**< pricing SCIP data structure */
342331
SCIP_VAR** vars /**< variable array for the items */
343332
)
@@ -387,8 +376,8 @@ SCIP_RETCODE initPricing(
387376
}
388377

389378
/* dual value in original SCIP */
390-
dual = SCIPgetDualsolSetppc(scip, cons);
391-
379+
dual = isfarkas ? SCIPgetDualfarkasSetppc(scip, cons) : SCIPgetDualsolSetppc(scip, cons);
380+
392381
SCIP_CALL( SCIPcreateVarBasic(subscip, &var, SCIPconsGetName(cons), 0.0, 1.0, dual, SCIP_VARTYPE_BINARY) );
393382
SCIP_CALL( SCIPaddVar(subscip, var) );
394383

@@ -417,99 +406,15 @@ SCIP_RETCODE initPricing(
417406
return SCIP_OKAY;
418407
}
419408

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 */
428410
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+
)
488417
{
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}*/
513418
SCIP* subscip;
514419
SCIP_PRICERDATA* pricerdata;
515420
SCIP_CONS** conss;
@@ -529,6 +434,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
529434

530435
assert(scip != NULL);
531436
assert(pricer != NULL);
437+
assert(result != NULL);
532438

533439
(*result) = SCIP_DIDNOTRUN;
534440

@@ -571,7 +477,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
571477
SCIP_CALL( SCIPallocBufferArray(scip, &vars, nitems) );
572478

573479
/* initialization local pricing problem */
574-
SCIP_CALL( initPricing(scip, pricerdata, subscip, vars) );
480+
SCIP_CALL( initPricing(scip, pricerdata, isfarkas, subscip, vars) );
575481

576482
SCIPdebugMsg(scip, "solve pricer problem\n");
577483

@@ -582,8 +488,9 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
582488
nsols = SCIPgetNSols(subscip);
583489
addvar = FALSE;
584490

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
587494
*/
588495
for( s = 0; s < nsols; ++s )
589496
{
@@ -605,8 +512,8 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
605512
continue;
606513
}
607514

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) )
610517
{
611518
SCIP_VAR* var;
612519
SCIP_VARDATA* vardata;
@@ -648,7 +555,7 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
648555

649556
SCIP_CALL( SCIPvardataCreateBinpacking(scip, &vardata, consids, nconss) );
650557

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 */
652559
SCIP_CALL( SCIPcreateVarBinpacking(scip, &var, name, 1.0, FALSE, TRUE, vardata) );
653560

654561
/* add the new variable to the pricer store */
@@ -690,27 +597,110 @@ SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
690597
return SCIP_OKAY;
691598
}
692599

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+
693697
/** farkas pricing method of variable pricer for infeasible LPs */
694698
static
695699
SCIP_DECL_PRICERFARKAS(pricerFarkasBinpacking)
696700
{ /*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) );
712702

713-
return SCIP_OKAY; /*lint !e527*/
703+
return SCIP_OKAY;
714704
}
715705

716706
/**@} */

examples/maketestallexamples.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ set -e
1414
EXAMPLES=$(for f in *;do if [[ -d $f ]]; then echo $f;fi; done)
1515
# Sudoku doesn't have a test
1616
EXAMPLES=$(echo "$EXAMPLES" |grep -v Sudoku)
17-
# Binpacking tests are known to fail, #3712
18-
EXAMPLES=$(echo "$EXAMPLES" |grep -v Binpacking)
1917

2018
LPSOLVERS=(spx2)
2119
OPTS=(dbg)

0 commit comments

Comments
 (0)