/** gets the dual solution of the linear constraint in the current LP */ jdouble JNISCIPCONSLINEAR(getDualsolLinear)( JNIEnv* env, /**< JNI environment variable */ jobject jobj, /**< JNI class pointer */ jlong jscip, /**< SCIP data structure */ jlong jcons /**< constraint data */ ) { SCIP* scip; SCIP_CONS* cons; SCIP_Real num; /* convert JNI pointer into C pointer */ scip = (SCIP*) (size_t) jscip; assert(scip != NULL); /* convert JNI pointer into C pointer */ cons = (SCIP_CONS*) (size_t) jcons; assert( cons != NULL); num = SCIPgetDualsolLinear(scip, cons); return (jdouble) num; }
/** 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* values; SCIP_Longint* weights; SCIP_Longint* capacities; int nbins; int b; SCIP_Real timelimit; SCIP_Real memorylimit; SCIP_Real dualHallBound; assert(scip != NULL); assert(pricer != NULL); (*result) = SCIP_DIDNOTRUN; /* get the pricer data */ pricerdata = SCIPpricerGetData(pricer); assert(pricerdata != NULL); capacities = pricerdata->capacities; conss = pricerdata->conss; ids = pricerdata->ids; values = pricerdata->values; weights = pricerdata->weights; nitems = pricerdata->nitems; nbins = pricerdata->nbins; dualHallBound = 0.0; // run pricing problem for each bin for (b = 0; b < nbins; ++b) { // assert(SCIPgetDualsolLinear(scip, conss[nitems+b])<= 0); // TODO edit if correct objsense dualHallBound -= SCIPgetDualsolLinear(scip, conss[nitems+b]); if (b < nbins-1 && capacities[b+1] == capacities[b]) continue; /* 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)); /* free sub SCIP */ SCIP_CALL(SCIPcreateProb(subscip, "pricing", NULL, NULL, NULL, NULL, NULL, NULL, NULL)); 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, b)); 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("solution in pricing problem (capacity <%d>) is infeasible\n", capacities[b]); continue; } /* check if the solution has a value greater than 1.0 */ // First subscip? if (SCIPisFeasGT(scip, SCIPgetSolOrigObj(subscip, sol), dualHallBound)) { SCIP_VAR* var; SCIP_VARDATA* vardata; int* consids; char strtmp[SCIP_MAXSTRLEN]; char name[SCIP_MAXSTRLEN]; int nconss; int o; int v; SCIP_Longint totalvalue; SCIP_Longint totalweight; SCIPdebug(SCIP_CALL(SCIPprintSol(subscip, sol, NULL, FALSE))); nconss = 0; totalvalue = 0.0; totalweight = 0.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; totalvalue+= values[o]; totalweight += weights[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, -totalvalue, 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)); } /* add variable to hall constraints */ for (v = 0; v <= b; v++) { SCIP_CALL(SCIPaddCoefLinear(scip, conss[nitems+v], var, 1.0)); if (totalweight <= capacities[v] && v < b && capacities[b] != capacities[b+1]) break; } 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; }