/** 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;
}
Beispiel #2
0
/** 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;
}