/** Solves a standard form LP problem in the form of min(c) s.t. A.x = b lb <= x <= ub */ protected int optimizeStandardLP(int nOfSlackVariables) throws Exception { log.info("optimizeStandardLP"); LPOptimizationRequest lpRequest = getLPOptimizationRequest(); if (log.isDebugEnabled() && lpRequest.isDumpProblem()) { log.debug("LP problem: " + lpRequest.toString()); } LPOptimizationResponse lpResponse; if (lpRequest.isPresolvingDisabled()) { // optimization LPPrimalDualMethod opt = new LPPrimalDualMethod(minLBValue, maxUBValue); opt.setLPOptimizationRequest(lpRequest); if (opt.optimizePresolvedStandardLP() == OptimizationResponse.FAILED) { return OptimizationResponse.FAILED; } lpResponse = opt.getLPOptimizationResponse(); setLPOptimizationResponse(lpResponse); } else { // presolving LPPresolver lpPresolver = new LPPresolver(); lpPresolver.setAvoidScaling(lpRequest.isRescalingDisabled()); lpPresolver.setAvoidFillIn(lpRequest.isAvoidPresolvingFillIn()); lpPresolver.setAvoidIncreaseSparsity(lpRequest.isAvoidPresolvingIncreaseSparsity()); testPresolver = lpPresolver; // just for testing lpPresolver.setNOfSlackVariables((short) nOfSlackVariables); lpPresolver.presolve(getC(), getA(), getB(), getLb(), getUb()); int presolvedDim = lpPresolver.getPresolvedN(); if (presolvedDim == 0) { // deterministic problem log.debug("presolvedDim : " + presolvedDim); log.debug("deterministic LP problem"); lpResponse = new LPOptimizationResponse(); lpResponse.setReturnCode(OptimizationResponse.SUCCESS); lpResponse.setSolution(new double[] {}); } else { // solving the presolved problem DoubleMatrix1D presolvedC = lpPresolver.getPresolvedC(); DoubleMatrix2D presolvedA = lpPresolver.getPresolvedA(); DoubleMatrix1D presolvedB = lpPresolver.getPresolvedB(); if (log.isDebugEnabled()) { if (lpPresolver.getPresolvedYlb() != null) { log.debug("Ylb: " + ArrayUtils.toString(lpPresolver.getPresolvedYlb().toArray())); log.debug("Yub: " + ArrayUtils.toString(lpPresolver.getPresolvedYub().toArray())); } if (lpPresolver.getPresolvedZlb() != null) { log.debug("Zlb: " + ArrayUtils.toString(lpPresolver.getPresolvedZlb().toArray())); log.debug("Zub: " + ArrayUtils.toString(lpPresolver.getPresolvedZub().toArray())); } } // new LP problem (the presolved problem) LPOptimizationRequest presolvedLPRequest = lpRequest.cloneMe(); presolvedLPRequest.setC(presolvedC); presolvedLPRequest.setA(presolvedA); presolvedLPRequest.setB(presolvedB); presolvedLPRequest.setLb(lpPresolver.getPresolvedLB()); presolvedLPRequest.setUb(lpPresolver.getPresolvedUB()); presolvedLPRequest.setYlb(lpPresolver.getPresolvedYlb()); presolvedLPRequest.setYub(lpPresolver.getPresolvedYub()); presolvedLPRequest.setZlb(lpPresolver.getPresolvedZlb()); presolvedLPRequest.setZub(lpPresolver.getPresolvedZub()); if (getInitialPoint() != null) { presolvedLPRequest.setInitialPoint(lpPresolver.presolve(getInitialPoint().toArray())); } if (getNotFeasibleInitialPoint() != null) { presolvedLPRequest.setNotFeasibleInitialPoint( lpPresolver.presolve(getNotFeasibleInitialPoint().toArray())); } // optimization // NB: because of rescaling during the presolving phase, minLB and maxUB could have been // rescaled double rescaledMinLBValue = (Double.isNaN(lpPresolver.getMinRescaledLB())) ? this.minLBValue : lpPresolver.getMinRescaledLB(); double rescaledMaxUBValue = (Double.isNaN(lpPresolver.getMaxRescaledUB())) ? this.maxUBValue : lpPresolver.getMaxRescaledUB(); LPPrimalDualMethod opt = new LPPrimalDualMethod(rescaledMinLBValue, rescaledMaxUBValue); opt.setLPOptimizationRequest(presolvedLPRequest); if (opt.optimizePresolvedStandardLP() == OptimizationResponse.FAILED) { return OptimizationResponse.FAILED; } lpResponse = opt.getLPOptimizationResponse(); } // postsolving double[] postsolvedSolution = lpPresolver.postsolve(lpResponse.getSolution()); lpResponse.setSolution(postsolvedSolution); setLPOptimizationResponse(lpResponse); } return lpResponse.getReturnCode(); }
// formulate and generate the solution, if necessary private void solve() { if (solved) return; // min obj.x s.t. a.x=b, lb <= x <= ub // x is energy use per block for size hours, b is slack var per block. // Block is a shift, or portion of shift with constant price. // For multi-hour blocks, energy use is evenly distributed across hours // after solution. Date start = new Date(); int shifts = needs.length; // Create blocks that break on both shift boundaries and tariff price // boundaries. ShiftBlock[] blocks = makeBlocks(shifts); int columns = blocks.length; int blockIndex = -1; double[] obj = new double[columns + shifts]; double[][] a = new double[shifts][columns + shifts]; double[] b = new double[shifts]; double[] lb = new double[columns + shifts]; double[] ub = new double[columns + shifts]; int column = 0; double cumulativeMin = 0.0; // this is the primary constraint // construct the problem for (int i = 0; i < shifts; i++) { // one iteration per shift // double kwh = // needs[i].getEnergyNeeded() + needs[i].getMaxSurplus(); // for (int j = 0; j < needs[i].getDuration(); j++) { while ((blockIndex < blocks.length - 1) && (blocks[blockIndex + 1].getShiftEnergy() == needs[i])) { blockIndex += 1; // one iteration per block within a shift // fill in objective function obj[column] = blocks[blockIndex].getCost(); lb[column] = 0.0; ub[column] = (needs[i].getEnergyNeeded() + needs[i].getMaxSurplus()) * (double) blocks[blockIndex].getDuration() / needs[i].getDuration(); column += 1; // construct cumulative usage constraints // a[i][column] = -1.0; // time = time.plus(TimeService.HOUR); } // fill a row up to column for (int j = 0; j < column; j++) { a[i][j] = -1.0; } // b vector - one entry per constraint double need = needs[i].getEnergyNeeded(); if (needs[i].getMaxSurplus() < 0.0) need += needs[i].getMaxSurplus(); cumulativeMin += need; b[i] = -cumulativeMin; // fill in slack values, one per constraint obj[columns + i] = 0.0; a[i][columns + i] = 1.0; lb[columns + i] = 0.0; // upper bound is max possible energy for shift ub[columns + i] = (needs[i].getEnergyNeeded() + needs[i].getMaxSurplus()); } // run the optimization LPOptimizationRequest or = new LPOptimizationRequest(); log.debug("Obj: " + Arrays.toString(obj)); or.setC(obj); log.debug("a:"); for (int i = 0; i < a.length; i++) log.debug(Arrays.toString(a[i])); or.setA(a); log.debug("b: " + Arrays.toString(b)); or.setB(b); or.setLb(lb); log.debug("ub: " + Arrays.toString(ub)); or.setUb(ub); or.setTolerance(1.0e-2); LPPrimalDualMethod opt = new LPPrimalDualMethod(); opt.setLPOptimizationRequest(or); try { int returnCode = opt.optimize(); if (returnCode != OptimizationResponse.SUCCESS) { log.error(getName() + "bad optimization return code " + returnCode); } double[] sol = opt.getOptimizationResponse().getSolution(); Date end = new Date(); log.info("Solution time: " + (end.getTime() - start.getTime())); log.debug("Solution = " + Arrays.toString(sol)); recordSolution(sol, blocks); } catch (Exception e) { log.error(e.toString()); } // we call it solved whether or not the solution was successful solved = true; }
/** Solves an LP in the form of: min(c) s.t. A.x = b G.x < h lb <= x <= ub */ @Override public int optimize() throws Exception { log.info("optimize"); LPOptimizationRequest lpRequest = getLPOptimizationRequest(); if (log.isDebugEnabled() && lpRequest.isDumpProblem()) { log.debug("LP problem: " + lpRequest.toString()); } // standard form conversion LPStandardConverter lpConverter = new LPStandardConverter(); // the slack variables will have default unboundedUBValue lpConverter.toStandardForm(getC(), getG(), getH(), getA(), getB(), getLb(), getUb()); int nOfSlackVariables = lpConverter.getStandardS(); log.debug("nOfSlackVariables: " + nOfSlackVariables); DoubleMatrix1D standardC = lpConverter.getStandardC(); DoubleMatrix2D standardA = lpConverter.getStandardA(); DoubleMatrix1D standardB = lpConverter.getStandardB(); DoubleMatrix1D standardLb = lpConverter.getStandardLB(); DoubleMatrix1D standardUb = lpConverter.getStandardUB(); // solve the standard form problem LPOptimizationRequest standardLPRequest = lpRequest.cloneMe(); standardLPRequest.setC(standardC); standardLPRequest.setA(standardA); standardLPRequest.setB(standardB); standardLPRequest.setLb( ColtUtils.replaceValues( standardLb, lpConverter.getUnboundedLBValue(), minLBValue)); // substitute not-double numbers standardLPRequest.setUb( ColtUtils.replaceValues( standardUb, lpConverter.getUnboundedUBValue(), maxUBValue)); // substitute not-double numbers if (getInitialPoint() != null) { standardLPRequest.setInitialPoint( lpConverter.getStandardComponents(getInitialPoint().toArray())); } if (getNotFeasibleInitialPoint() != null) { standardLPRequest.setNotFeasibleInitialPoint( lpConverter.getStandardComponents(getNotFeasibleInitialPoint().toArray())); } // optimization LPPrimalDualMethod opt = new LPPrimalDualMethod(minLBValue, maxUBValue); opt.setLPOptimizationRequest(standardLPRequest); if (opt.optimizeStandardLP(nOfSlackVariables) == OptimizationResponse.FAILED) { return OptimizationResponse.FAILED; } // back to original form LPOptimizationResponse lpResponse = opt.getLPOptimizationResponse(); double[] standardSolution = lpResponse.getSolution(); double[] originalSol = lpConverter.postConvert(standardSolution); lpResponse.setSolution(originalSol); setLPOptimizationResponse(lpResponse); return lpResponse.getReturnCode(); }