public double solve(Instance ins, Solution sol, int timeout) throws IloException {
    IloCplex solver = new IloCplex();
    BiIndexedIntVarMap y = new BiIndexedIntVarMap(solver, 0, 1, "y"); // (k,v)   (cluster,node)
    IndexedNumVarMap d =
        new IndexedNumVarMap(solver, 0, Double.MAX_VALUE, "dp"); // (k)     (cluster)	
    TriIndexedNumVarMap f =
        new TriIndexedNumVarMap(solver, 0, Double.MAX_VALUE, "f"); // (k,i,j) (cluster,tail,head)
    BiIndexedIntVarMap r = new BiIndexedIntVarMap(solver, 0, 1, "r"); // (k,i)   (cluster,node
    BiIndexedNumVarMap w = new BiIndexedNumVarMap(solver, 0, 1, "w"); // (i,j)   (node1<node2)

    int superRoot = ins.getNumNodes();
    // compute the weights of the objective function
    double w1 = ins.getW1() / ins.getNumNodes();
    double w2 = ins.getW2() / (ins.getLambda() * ins.getMaxClusterNumber());
    double w3 =
        2
            * ins.getW3()
            / (ins.getNumNodes() * (ins.getNumNodes() - 1) * (ins.getDMax() - ins.getDMin()));

    Set<OrderedPair> fp = new TreeSet<OrderedPair>(ins.getP());
    if (isActiveExtension(Extension.PFILTER)) {
      fp = ins.filterP();
      System.out.println("PFILTER: " + (ins.getP().size() - fp.size()) + " pairs filtered");
    }

    // compute the objective function expression
    IloNumExpr expr = solver.numExpr();

    // O1
    IloNumExpr exprO1 = solver.numExpr();
    for (int i = 0; i < ins.getNumNodes(); ++i) {
      expr = solver.numExpr();
      expr = solver.sum(expr, 1);
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) expr = solver.diff(expr, y.get(k, i));
      exprO1 = solver.sum(exprO1, solver.prod(w1, expr));
    }
    // O2
    IloNumExpr exprO2 = solver.numExpr();
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      exprO2 = solver.sum(exprO2, solver.prod(w2, d.get(k)));
    }
    // O3
    IloNumExpr exprO3 = solver.numExpr();
    for (OrderedPair p : fp) {
      double dmax = ins.getDMax();
      double dist = ins.getD(p.i, p.j);
      IloNumVar wvar = w.get(p.i, p.j);
      exprO3 = solver.sum(exprO3, solver.prod(w3 * (dmax - dist), wvar));
    }
    expr = solver.sum(exprO1, solver.sum(exprO2, exprO3));
    solver.add(solver.objective(IloObjectiveSense.Minimize, expr));

    // packing constraints
    for (int i = 0; i < ins.getNumNodes(); ++i) {
      expr = solver.numExpr();
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) expr = solver.sum(expr, y.get(k, i));
      solver.addLe(expr, 1);
    }

    // root uniqueness constraints
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      expr = solver.numExpr();
      for (int i = 0; i < ins.getNumNodes(); ++i) expr = solver.sum(expr, r.get(k, i));
      solver.addLe(expr, 1);
    }

    // f,y linking constraints

    // OUT
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      for (int i = 0; i < ins.getNumNodes(); ++i) {
        expr = solver.numExpr();
        for (Integer j : ins.getOutcut(i)) {
          expr = solver.sum(expr, f.get(k, i, j));
        }
        expr = solver.diff(expr, solver.prod(ins.getMaxClusterSize() - 2, y.get(k, i)));
        solver.addLe(expr, 0);
      }
    }

    // f,r linking constraints
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      for (int i = 0; i < ins.getNumNodes(); ++i) {
        solver.addLe(f.get(k, superRoot, i), solver.prod(ins.getMaxClusterSize(), r.get(k, i)));
      }
    }

    //		//flow generation constraints
    //		for(int k=0;k<ins.getMaxClusterNumber();++k){
    //			expr=solver.numExpr();
    //			for(int i=0;i<ins.getNumNodes();++i){
    //				expr=solver.sum(expr,f.get(k,superRoot,i));
    //				expr=solver.diff(expr, y.get(k, i));
    //			}
    //			solver.addEq(expr, 0);
    //		}

    // flow conservation constraints
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      for (int i = 0; i < ins.getNumNodes(); ++i) {
        expr = solver.numExpr();
        for (Integer j : ins.getOutcut(i)) {
          expr = solver.diff(expr, f.get(k, i, j));
          expr = solver.sum(expr, f.get(k, j, i));
        }
        // i can receive flow also from the super root
        expr = solver.sum(expr, f.get(k, superRoot, i));
        solver.addEq(expr, y.get(k, i));
      }
    }

    // delta definition constraints
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      expr = solver.numExpr();
      for (int i = 0; i < ins.getNumNodes(); ++i) {
        expr = solver.sum(expr, y.get(k, i));
      }
      solver.addLe(solver.diff(expr, ins.getLambda()), d.get(k));
      solver.addGe(solver.diff(expr, ins.getLambda()), solver.prod(-1, d.get(k)));
    }

    // w var definition constraints
    for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
      for (OrderedPair p : fp) {
        expr = solver.numExpr();
        expr = solver.sum(expr, w.get(p.i, p.j));
        expr = solver.diff(expr, y.get(k, p.i));
        expr = solver.diff(expr, y.get(k, p.j));
        expr = solver.sum(expr, 1);
        solver.addGe(expr, 0);
      }
    }

    if (isActiveExtension(Extension.ROOT_MINIMIZATION_CONSTRAINTS)) {
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
        for (OrderedPair p : fp) {
          expr = solver.sum(y.get(k, p.i), r.get(k, p.j));
          solver.addLe(expr, 1);
        }
      }
    }

    if (isActiveExtension(Extension.POLYNOMIAL_ORBITOPE)) {
      // first family
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
        expr = solver.numExpr();
        for (int v = 0; v <= k - 1; ++v) {
          expr = solver.sum(expr, y.get(k, v));
        }
        solver.addEq(expr, 0);
      }
      // second family
      for (int k = 1; k < ins.getMaxClusterNumber(); ++k) {
        for (int v = k; v < ins.getNumNodes(); ++v) {
          expr = solver.numExpr();
          expr = solver.sum(expr, y.get(k, v));
          for (int u = k - 1; u <= v - 1; ++u) {
            expr = solver.diff(expr, y.get(k - 1, u));
          }
          solver.addLe(expr, 0);
        }
      }
    }

    if (isActiveExtension(Extension.EXPONENTIAL_ORBITOPE)) {
      System.err.println("Extension " + Extension.EXPONENTIAL_ORBITOPE + " not implemented yet");
      throw new IllegalArgumentException();
    }

    if (isActiveExtension(Extension.FLOW_LB)) {
      // f,x lower bound
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
        for (int i = 0; i < ins.getNumNodes(); ++i) {
          expr = solver.numExpr();
          for (Integer j : ins.getOutcut(i)) {
            expr = solver.sum(expr, f.get(k, j, i));
          }
          expr = solver.sum(expr, f.get(k, superRoot, i));
          solver.addGe(expr, y.get(k, i));
          solver.addLe(r.get(k, i), f.get(k, superRoot, i));
        }
      }
    }

    solver.setParam(IloCplex.DoubleParam.TiLim, timeout);
    if (isActiveExtension(Extension.ROOT_BRANCHING_PRIORITY)) {
      // Add branching priorities to the root variables
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k)
        for (int i = 0; i < ins.getNumNodes(); ++i) solver.setPriority(r.get(k, i), 100);
    }
    solver.setParam(IloCplex.IntParam.ParallelMode, 1);
    solver.solve();
    System.out.println("STATE=" + solver.getStatus());
    System.out.println("NN=" + solver.getNnodes());
    System.out.println("LB=" + solver.getBestObjValue());

    // If we have a feasible solution we save it
    if (solver.getStatus() == IloCplex.Status.Feasible
        || solver.getStatus() == IloCplex.Status.Optimal) {
      for (int k = 0; k < ins.getMaxClusterNumber(); ++k) {
        for (int v = 0; v < ins.getNumNodes(); ++v) {
          if (FloatUtils.eq(solver.getValue(y.get(k, v)), 1.0)) {
            sol.insert(k, v);
          }
        }
      }
    }

    return solver.getObjValue();
  }
Пример #2
0
  public boolean solve(
      double[] Pmax,
      double[] PregMax,
      double[] Emin,
      double[] Emax,
      int quartersLeftInFirstBid,
      int[] bids,
      int bidSize,
      ArrayList<FlexGraph> flexGraphs) {
    double[] Pmin = new double[Pmax.length];
    // Pre-process data
    if ((Pmin.length - quartersLeftInFirstBid) % 4 != 0) {
      int extraQuarters = 4 - ((Pmin.length - quartersLeftInFirstBid) % 4);
      Pmin = concat(Pmin, new double[extraQuarters]);
      Pmax = concat(Pmax, new double[extraQuarters]);
      PregMax = concat(PregMax, new double[extraQuarters]);
      double[] endE = new double[extraQuarters];
      for (int i = 0; i < endE.length; i++) {
        endE[i] = Emin[Emin.length - 1];
      }
      Emin = concat(Emin, endE);
      Emax = concat(Emax, endE);
    }
    this.quartersLeftInFirstBid = quartersLeftInFirstBid;

    // Solve optimization problem
    try {
      IloCplex cplex = new IloCplex();

      // for all evs
      ArrayList<IloNumVar[]> flexpowers = new ArrayList<IloNumVar[]>();
      ArrayList<IloNumVar[]> flexenergies = new ArrayList<IloNumVar[]>();
      for (int i = 0; i < flexGraphs.size(); i++) {
        FlexGraph flexGraph = flexGraphs.get(i);
        double[] energyMin = convertToDoubles(flexGraph.getEnergyMin());
        double[] energyMax = convertToDoubles(flexGraph.getEnergyMax());
        double[] powerMax = convertToDoubles(flexGraph.getPowerMax());
        // charging power
        IloNumVar[] p = cplex.numVarArray(powerMax.length, new double[powerMax.length], powerMax);
        // path
        IloNumVar[] e = cplex.numVarArray(energyMin.length, energyMin, energyMax);
        for (int j = 0; j < p.length; j++) {
          cplex.addEq(cplex.diff(e[j + 1], e[j]), cplex.prod(1.0 / 4, p[j]));
        }
        flexpowers.add(p);
        flexenergies.add(e);
      }

      // total charging power
      IloNumVar[] p = cplex.numVarArray(Pmin.length, Pmin, Pmax);

      // individual bin constraints
      for (int t = 0; t < p.length; t++) {
        ArrayList<IloNumVar> tempVars = new ArrayList<IloNumVar>();
        for (IloNumVar[] var : flexpowers) {
          if (var.length >= t + 1) {
            tempVars.add(var[t]);
          }
        }
        IloNumVar[] tempVars_array = new IloNumVar[tempVars.size()];
        tempVars.toArray(tempVars_array);
        cplex.addEq(p[t], cplex.sum(tempVars_array));
      }

      // path
      IloNumVar[] e = cplex.numVarArray(Emin.length, Emin, Emax);
      for (int i = 0; i < p.length; i++) {
        cplex.addEq(cplex.diff(e[i + 1], e[i]), cplex.prod(1.0 / 4, p[i]));
      }

      // Emin < path < Emax
      for (int i = 0; i < e.length; i++) {
        cplex.addGe(e[i], Emin[i]);
        cplex.addLe(e[i], Emax[i]);
      }

      // regulation power in each optimziation interval
      IloNumVar[] regPowerQ = cplex.numVarArray(Pmin.length, Pmin, PregMax);

      // calculate regulation power in each optimization interval
      for (int i = 0; i < regPowerQ.length; i++) {
        cplex.addEq(regPowerQ[i], cplex.diff(PregMax[i], p[i]));
      }

      // regulation bids in each hour
      // 1. max nr of bids per houd
      int hours =
          (int) Math.ceil(quartersLeftInFirstBid / 4.0)
              + (int) Math.ceil((regPowerQ.length - quartersLeftInFirstBid) / 4.0);
      int[] maxNrOfBidsPerHour = new int[hours];
      // init with max nr of bids per hour
      for (int i = 0; i < maxNrOfBidsPerHour.length; i++) {
        maxNrOfBidsPerHour[i] = Integer.MAX_VALUE;
      }
      if (quartersLeftInFirstBid > 0) {
        maxNrOfBidsPerHour[0] = bids[0];
        try {
          maxNrOfBidsPerHour[1] = bids[1];
        } catch (IndexOutOfBoundsException ew) {
          System.out.print("Emin = ");
          printArray(Emin);

          System.out.print("Emax = ");
          printArray(Emax);

          System.out.print("Pmax = ");
          printArray(Pmax);

          System.out.println("FirstBidQuarter = " + quartersLeftInFirstBid);

          System.out.print("Bids = ");
          printArray(bids);

          System.out.println("Bidsize = " + bidSize);
        }
      } else {
        maxNrOfBidsPerHour[0] = bids[1];
      }
      // 2. bids per hour
      IloIntVar[] bidsH = cplex.intVarArray(hours, new int[hours], maxNrOfBidsPerHour);
      // limit bids by provided regulation power
      for (int i = 0; i < regPowerQ.length; i++) {
        // convert Q to H
        int h = (int) Math.ceil(((i + 1) - quartersLeftInFirstBid) / 4.0);
        if (quartersLeftInFirstBid == 0) {
          h--;
        }
        // bidsH*bidSize <= regPowerQ[i]
        if (i > 0) {
          // reserve some extra regulation power
          cplex.addLe(cplex.prod(bidsH[h], bidSize), cplex.prod(0.95, regPowerQ[i]));
        } else {
          cplex.addLe(cplex.prod(bidsH[h], bidSize), cplex.prod(1, regPowerQ[i]));
        }
        // System.out.println("h = " + h + ", i=" + i);
      }

      // create model and solve it
      // cplex.addMaximize(cplex.scalProd(p,prices));
      double[] rewards = new double[bidsH.length];
      // init to rewards = 1 for all, but two first hours
      for (int i = 0; i < rewards.length; i++) {
        rewards[i] = 1;
      }
      rewards[0] = 100;
      if (rewards.length > 1) {
        rewards[1] = 100;
      }
      IloLinearNumExpr maximization = cplex.scalProd(bidsH, rewards);
      IloObjective maxObjective = cplex.addMaximize(maximization);

      cplex.setOut(null);
      cplex.solve();
      //			if(cplex.solve()) {
      //				cplex.output().println("Solution status = " + cplex.getStatus());
      //				cplex.output().println("Solution value = " + cplex.getObjValue());
      //
      //				System.out.print("Emin = ");
      //				printArray(Emin);
      //
      //				System.out.print("Emax = ");
      //				printArray(Emax);
      //
      //				System.out.print("Pmax = ");
      //				printArray(Pmax);
      //
      //				powerPath = cplex.getValues(p);
      //				System.out.print("Power = ");
      //				printArray(powerPath);
      //
      //				energyPath = cplex.getValues(e);
      //				System.out.print("Energy = ");
      //				printArray(energyPath);
      //
      //				regPower = cplex.getValues(regPowerQ);
      //				System.out.print("RegPower = ");
      //				printArray(regPower);
      //
      //				bidsN = new int[bidsH.length];
      //				for(int i = 0; i < bidsN.length; i++) {
      //					bidsN[i] = (int) Math.round(cplex.getValue(bidsH[i]));
      //				}
      // shift bids right if no quarter left in current bid slot -- hack-ish
      if (quartersLeftInFirstBid == 0) {
        bidsN = concat(new int[1], bidsN);
      }
      //
      //				System.out.print("Bids = ");
      //				printArray(bidsN);
      //
      //				this.bidSize = bidSize;
      //			}

      // stage two

      // System.out.println((int) );
      //			System.out.println("sum = " + cplex.getValue(cplex.sum(bidsH)));
      //			System.out.println(bidsH[0].getUB());;
      //			System.out.println((int) Math.round(cplex.getValue(bidsH[0])));
      //			bidsH[0].setMin((int) Math.round(cplex.getValue(bidsH[0])));
      //			.setUB(cplex.getValue(bidsH[0]));
      // cplex.addEq(bidsH[1], (int) Math.round(cplex.getValue(bidsH[1])));
      // cplex.addGe(bidsH[1], (int) Math.round(cplex.getValue(bidsH[1])));
      double bid1 = cplex.getValue(bidsH[0]);
      double bid2 = 0;
      if (bidsH.length > 1) {
        bid2 = cplex.getValue(bidsH[1]);
      }
      int totalBids = 0;
      for (int i = 0; i < bidsH.length; i++) {
        totalBids = totalBids + (int) Math.round(cplex.getValue(bidsH[i]));
      }
      cplex.addGe(cplex.sum(bidsH), totalBids);
      cplex.addLe(bid1, bidsH[0]);
      // cplex.getValue(bidsH[1]);
      if (bidsH.length > 1) {
        cplex.addLe(bid2, bidsH[1]);
      }

      cplex.remove(maxObjective);
      IloQuadNumExpr minimization = cplex.quadNumExpr();
      double[] coeff = new double[p.length];
      for (int i = 0; i < p.length; i++) {
        coeff[i] = 1;
      }
      minimization.addTerms(coeff, p, p);
      cplex.addMinimize(minimization);

      cplex.setOut(null);
      if (cplex.solve()) {
        //				cplex.output().println("Solution status = " + cplex.getStatus());
        //				cplex.output().println("Solution value = " + cplex.getObjValue());
        //
        //				System.out.print("Emin = ");
        //				printArray(Emin);
        //
        //				System.out.print("Emax = ");
        //				printArray(Emax);
        //
        //				System.out.print("Pmax = ");
        //				printArray(Pmax);
        //
        powerPath = cplex.getValues(p);
        System.out.print("Power = ");
        printArray(powerPath);

        energyPath = cplex.getValues(e);
        //				System.out.print("Energy = ");
        //				printArray(energyPath);

        regPower = cplex.getValues(regPowerQ);
        System.out.print("RegPower = ");
        printArray(regPower);

        bidsN = new int[bidsH.length];
        for (int i = 0; i < bidsN.length; i++) {
          bidsN[i] = (int) Math.round(cplex.getValue(bidsH[i]));
        }
        // shift bids right if no quarter left in current bid slot -- hack-ish
        if (quartersLeftInFirstBid == 0) {
          bidsN = concat(new int[1], bidsN);
        }

        System.out.print("Bids = ");
        printArray(bidsN);

        this.bidSize = bidSize;
      }

      for (int i = 0; i < flexpowers.size(); i++) {
        flexGraphs.get(i).setSolutionPath(cplex.getValues(flexenergies.get(i)));
      }
      return true;
    } catch (IloException e) {
      System.err.println("Concert exception caught: " + e);
      e.printStackTrace();
      return false;
    }
  }