/** method for either Farkas or Redcost pricing */ static SCIP_RETCODE pricing( SCIP* scip, /**< SCIP data structure */ SCIP_PRICER* pricer, /**< pricer */ SCIP_Real* lowerbound, /**< lowerbound pointer */ SCIP_Bool farkas /**< TRUE: Farkas pricing; FALSE: Redcost pricing */ ) { SCIP_PRICERDATA* pricerdata; /* the data of the pricer */ SCIP_PROBDATA* probdata; GRAPH* graph; SCIP_VAR* var; PATH* path; SCIP_Real* edgecosts; /* edgecosts of the current subproblem */ char varname[SCIP_MAXSTRLEN]; SCIP_Real newlowerbound = -SCIPinfinity(scip); SCIP_Real redcost; /* reduced cost */ int tail; int e; int t; int i; assert(scip != NULL); assert(pricer != NULL); /* get pricer data */ pricerdata = SCIPpricerGetData(pricer); assert(pricerdata != NULL); /* get problem data */ probdata = SCIPgetProbData(scip); assert(probdata != NULL); SCIPdebugMessage("solstat=%d\n", SCIPgetLPSolstat(scip)); if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL ) newlowerbound = SCIPgetSolTransObj(scip, NULL); SCIPdebug( SCIP_CALL( SCIPprintSol(scip, NULL, NULL, FALSE) ) ); # if 0 if ( pricerdata->lowerbound <= 4 ) { char label[SCIP_MAXSTRLEN]; (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "X%g.gml", pricerdata->lowerbound); SCIP_CALL( SCIPprobdataPrintGraph(scip, label , NULL, TRUE) ); pricerdata->lowerbound++; } #endif /* get the graph*/ graph = SCIPprobdataGetGraph(probdata); /* get dual solutions and save them in mi and pi */ for( t = 0; t < pricerdata->realnterms; ++t ) { if( farkas ) { pricerdata->mi[t] = SCIPgetDualfarkasLinear(scip, pricerdata->pathcons[t]); } else { pricerdata->mi[t] = SCIPgetDualsolLinear(scip, pricerdata->pathcons[t]); assert(!SCIPisNegative(scip, pricerdata->mi[t])); } } for( e = 0; e < pricerdata->nedges; ++e ) { if( !pricerdata->bigt ) { for( t = 0; t < pricerdata->realnterms; ++t ) { if( farkas ) { pricerdata->pi[t * pricerdata->nedges + e] = SCIPgetDualfarkasLinear( scip, pricerdata->edgecons[t * pricerdata->nedges + e]); } else { pricerdata->pi[t * pricerdata->nedges + e] = SCIPgetDualsolLinear( scip, pricerdata->edgecons[t * pricerdata->nedges + e]); } } } else { if( farkas ) { pricerdata->pi[e] = SCIPgetDualfarkasLinear( scip, pricerdata->edgecons[e]); } else { pricerdata->pi[e] = SCIPgetDualsolLinear( scip, pricerdata->edgecons[e]); } } } SCIP_CALL( SCIPallocMemoryArray(scip, &path, graph->knots) ); SCIP_CALL( SCIPallocMemoryArray(scip, &edgecosts, pricerdata->nedges) ); if( pricerdata->bigt ) { for( e = 0; e < pricerdata->nedges; ++e ) { edgecosts[e] = (-pricerdata->pi[e]); } } /* find shortest r-t (r root, t terminal) paths and create corresponding variables iff reduced cost < 0 */ for( t = 0; t < pricerdata->realnterms; ++t ) { for( e = 0; e < pricerdata->nedges; ++e ) { if( !pricerdata->bigt ) { edgecosts[e] = (-pricerdata->pi[t * pricerdata->nedges + e]); } assert(!SCIPisNegative(scip, edgecosts[e])); } for( i = 0; i < graph->knots; i++ ) graph->mark[i] = 1; graph_path_exec(scip, graph, FSP_MODE, pricerdata->root, edgecosts, path); /* compute reduced cost of shortest path to terminal t */ redcost = 0.0; tail = pricerdata->realterms[t]; while( tail != pricerdata->root ) { redcost += edgecosts[path[tail].edge]; tail = graph->tail[path[tail].edge]; } redcost -= pricerdata->mi[t]; if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL ) { newlowerbound += redcost; } /* check if reduced cost < 0 */ if( SCIPisNegative(scip, redcost) ) { /* create variable to the shortest path (having reduced cost < 0) */ var = NULL; sprintf(varname, "PathVar%d_%d", t, pricerdata->ncreatedvars[t]); ++(pricerdata->ncreatedvars[t]); SCIP_CALL( SCIPcreateVarBasic(scip, &var, varname, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS) ); SCIP_CALL( SCIPaddPricedVar(scip, var, -redcost) ); tail = pricerdata->realterms[t]; while( tail != pricerdata->root ) { /* add variable to constraints */ if( !pricerdata->bigt ) { SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->edgecons[t * pricerdata->nedges + path[tail].edge], var, 1.0) ); } else { SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->edgecons[path[tail].edge], var, 1.0) ); } tail = graph->tail[path[tail].edge]; } SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->pathcons[t], var, 1.0) ); } } if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL ) *lowerbound = newlowerbound; SCIPfreeMemoryArray(scip, &edgecosts); SCIPfreeMemoryArray(scip, &path); return SCIP_OKAY; }
/** reduced cost pricing method of variable pricer for feasible LPs */ static SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking) { /*lint --e{715}*/ SCIP* subscip; SCIP_PRICERDATA* pricerdata; SCIP_CONS** conss; SCIP_VAR** vars; int* ids; SCIP_Bool addvar; SCIP_SOL** sols; int nsols; int s; int nitems; SCIP_Longint capacity; SCIP_Real timelimit; SCIP_Real memorylimit; assert(scip != NULL); assert(pricer != NULL); (*result) = SCIP_DIDNOTRUN; /* get the pricer data */ pricerdata = SCIPpricerGetData(pricer); assert(pricerdata != NULL); capacity = pricerdata->capacity; conss = pricerdata->conss; ids = pricerdata->ids; nitems = pricerdata->nitems; /* get the remaining time and memory limit */ SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) ); if( !SCIPisInfinity(scip, timelimit) ) timelimit -= SCIPgetSolvingTime(scip); SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) ); if( !SCIPisInfinity(scip, memorylimit) ) memorylimit -= SCIPgetMemUsed(scip)/1048576.0; /* initialize SCIP */ SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPincludeDefaultPlugins(subscip) ); /* create problem in sub SCIP */ SCIP_CALL( SCIPcreateProbBasic(subscip, "pricing") ); SCIP_CALL( SCIPsetObjsense(subscip, SCIP_OBJSENSE_MAXIMIZE) ); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); /* set time and memory limit */ SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); SCIP_CALL( SCIPallocMemoryArray(subscip, &vars, nitems) ); /* initialization local pricing problem */ SCIP_CALL( initPricing(scip, pricerdata, subscip, vars) ); SCIPdebugMessage("solve pricer problem\n"); /* solve sub SCIP */ SCIP_CALL( SCIPsolve(subscip) ); sols = SCIPgetSols(subscip); nsols = SCIPgetNSols(subscip); addvar = FALSE; /* loop over all solutions and create the corresponding column to master if the reduced cost are negative for master, * that is the objective value i greater than 1.0 */ for( s = 0; s < nsols; ++s ) { SCIP_Bool feasible; SCIP_SOL* sol; /* the soultion should be sorted w.r.t. the objective function value */ assert(s == 0 || SCIPisFeasGE(subscip, SCIPgetSolOrigObj(subscip, sols[s-1]), SCIPgetSolOrigObj(subscip, sols[s]))); sol = sols[s]; assert(sol != NULL); /* check if solution is feasible in original sub SCIP */ SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, FALSE, FALSE ) ); if( !feasible ) { SCIPwarningMessage(scip, "solution in pricing problem (capacity <%d>) is infeasible\n", capacity); continue; } /* check if the solution has a value greater than 1.0 */ if( SCIPisFeasGT(subscip, SCIPgetSolOrigObj(subscip, sol), 1.0) ) { SCIP_VAR* var; SCIP_VARDATA* vardata; int* consids; char strtmp[SCIP_MAXSTRLEN]; char name[SCIP_MAXSTRLEN]; int nconss; int o; int v; SCIPdebug( SCIP_CALL( SCIPprintSol(subscip, sol, NULL, FALSE) ) ); nconss = 0; (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "items"); SCIP_CALL( SCIPallocBufferArray(scip, &consids, nitems) ); /* check which variables are fixed -> which item belongs to this packing */ for( o = 0, v = 0; o < nitems; ++o ) { if( !SCIPconsIsEnabled(conss[o]) ) continue; assert(SCIPgetNFixedonesSetppc(scip, conss[o]) == 0); if( SCIPgetSolVal(subscip, sol, vars[v]) > 0.5 ) { (void) SCIPsnprintf(strtmp, SCIP_MAXSTRLEN, "_%d", ids[o]); strcat(name, strtmp); consids[nconss] = o; nconss++; } else assert( SCIPisFeasEQ(subscip, SCIPgetSolVal(subscip, sol, vars[v]), 0.0) ); v++; } SCIP_CALL( SCIPvardataCreateBinpacking(scip, &vardata, consids, nconss) ); /* create variable for a new column with objective function coefficient 0.0 */ SCIP_CALL( SCIPcreateVarBinpacking(scip, &var, name, 1.0, FALSE, TRUE, vardata) ); /* add the new variable to the pricer store */ SCIP_CALL( SCIPaddPricedVar(scip, var, 1.0) ); addvar = TRUE; /* change the upper bound of the binary variable to lazy since the upper bound is already enforced due to * the objective function the set covering constraint; The reason for doing is that, is to avoid the bound * of x <= 1 in the LP relaxation since this bound constraint would produce a dual variable which might have * a positive reduced cost */ SCIP_CALL( SCIPchgVarUbLazy(scip, var, 1.0) ); /* check which variable are fixed -> which orders belong to this packing */ for( v = 0; v < nconss; ++v ) { assert(SCIPconsIsEnabled(conss[consids[v]])); SCIP_CALL( SCIPaddCoefSetppc(scip, conss[consids[v]], var) ); } SCIPdebug(SCIPprintVar(scip, var, NULL) ); SCIP_CALL( SCIPreleaseVar(scip, &var) ); SCIPfreeBufferArray(scip, &consids); } else break; } /* free pricer MIP */ SCIPfreeMemoryArray(subscip, &vars); if( addvar || SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL ) (*result) = SCIP_SUCCESS; /* free sub SCIP */ SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; }