ADMMQPModifiedRuizEquilibrium.java

  1. /*
  2.  * Licensed to the Hipparchus project under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.hipparchus.optim.nonlinear.vector.constrained;

  18. import org.hipparchus.linear.ArrayRealVector;
  19. import org.hipparchus.linear.MatrixUtils;
  20. import org.hipparchus.linear.RealMatrix;
  21. import org.hipparchus.linear.RealVector;
  22. import org.hipparchus.util.FastMath;

  23. /** TBD.
  24.  * @since 3.1
  25.  */
  26. public class ADMMQPModifiedRuizEquilibrium {

  27.     /** Minimum scaling value. */
  28.     private static final double MIN_SCALING = 1.0e-6;

  29.     /** Maximum scaling value. */
  30.     private static final double MAX_SCALING = 1.0e+6;

  31.     /** Square matrix of weights for quadratic terms. */
  32.     private final RealMatrix H;

  33.     /** Vector of weights for linear terms. */
  34.     private final RealVector q;

  35.     /** Constraints coefficients matrix. */
  36.     private final RealMatrix A;

  37.     /** TBC. */
  38.     private RealMatrix D;

  39.     /** TBC. */
  40.     private RealMatrix E;

  41.     /** TBC. */
  42.     private double c;

  43.     /** Inverse of D. */
  44.     private RealMatrix Dinv;

  45.     /** Inverse of E. */
  46.     private RealMatrix Einv;

  47.     /** Inverse of c. */
  48.     private double cinv;

  49.     /** Simple constructor
  50.      * @param H square matrix of weights for quadratic terms
  51.      * @param A constraints coefficients matrix
  52.      * @param q vector of weights for linear terms
  53.      */
  54.     public ADMMQPModifiedRuizEquilibrium(RealMatrix H, RealMatrix A, RealVector q) {
  55.         this.H  = H;
  56.         this.A  = A;
  57.         this.q  = q;
  58.     }

  59.     /** Normalize matrices.
  60.      * @param epsilon TBD
  61.      * @param maxIteration TBD
  62.      */
  63.     public void normalize(double epsilon, int maxIteration) {

  64.         int iteration = 0;
  65.         this.c = 1.0;
  66.         RealVector gammaD = new ArrayRealVector(H.getRowDimension());
  67.         RealVector gammaE = new ArrayRealVector(A.getRowDimension());

  68.         double lambda;
  69.         RealVector q1 = q.copy();
  70.         RealMatrix H1 = H.copy();
  71.         RealMatrix A1 = A.copy();
  72.         RealMatrix diagD;
  73.         RealMatrix diagE;
  74.         RealMatrix SD = MatrixUtils.createRealIdentityMatrix(H.getRowDimension());
  75.         RealMatrix SE = MatrixUtils.createRealIdentityMatrix(A.getRowDimension());
  76.         RealVector H1norm = new ArrayRealVector(H1.getColumnDimension());
  77.         while (iteration < maxIteration) {
  78.        // while (1.0 - gamma.getLInfNorm() > epsilon && iteration < maxIteration) {

  79.             for (int i = 0; i < H1.getColumnDimension(); i++) {
  80.                 double norma = (new ArrayRealVector(H1.getColumn(i), A1.getColumn(i))).getLInfNorm();
  81.                 gammaD.setEntry(i, norma);
  82.             }

  83.             for (int i = 0; i < A1.getRowDimension(); i++) {
  84.                 double norma = A1.getRowVector(i).getLInfNorm();
  85.                 gammaE.setEntry(i, norma);
  86.             }

  87.             gammaD = limitScaling(gammaD);
  88.             gammaE = limitScaling(gammaE);

  89.             for (int i = 0; i < gammaD.getDimension(); i++) {
  90.                 gammaD.setEntry(i, 1.0 / FastMath.sqrt(gammaD.getEntry(i)));
  91.             }

  92.             for (int i = 0; i < gammaE.getDimension(); i++) {
  93.                 gammaE.setEntry(i, 1.0 / FastMath.sqrt(gammaE.getEntry(i)));
  94.             }

  95.             diagD = MatrixUtils.createRealDiagonalMatrix(gammaD.toArray());
  96.             diagE = MatrixUtils.createRealDiagonalMatrix(gammaE.toArray());

  97.             H1 = diagD.multiply(H1.copy()).multiply(diagD.copy());
  98.             q1 = diagD.operate(q1.copy());
  99.             A1 = diagE.multiply(A1.copy()).multiply(diagD.copy());

  100.             for (int i = 0; i < H1.getRowDimension(); i++) {
  101.                 double norma = (new ArrayRealVector(H1.getRow(i))).getLInfNorm();
  102.                 H1norm.setEntry(i, norma);
  103.             }
  104.             double qnorm = q1.getLInfNorm();
  105.             if (qnorm == 0) {
  106.                 qnorm = 1.0;
  107.             }
  108.             qnorm = limitScaling(new ArrayRealVector(1, qnorm)).getEntry(0);
  109.             double mean = 0;
  110.             for (int i = 0; i < H1norm.getDimension(); i++) {
  111.                 mean+=H1norm.getEntry(i) / H1norm.getDimension();
  112.             }

  113.             lambda = 1.0 / limitScaling(new ArrayRealVector(1, FastMath.max(mean, qnorm))).getEntry(0);

  114.             H1 = H1.copy().scalarMultiply(lambda);
  115.             q1 = q1.copy().mapMultiply(lambda);
  116.             c *= lambda;
  117.             SD = diagD.multiply(SD.copy());
  118.             SE = diagE.multiply(SE.copy());
  119.             iteration += 1;
  120.         }
  121.         this.E    = SE.copy();
  122.         this.D    = SD.copy();
  123.         this.Einv = MatrixUtils.inverse(SE);
  124.         this.Dinv = MatrixUtils.inverse(SD);
  125.         this.cinv = 1.0 / c;

  126.     }

  127.     /** Get scaled square matrix of weights for quadratic terms.
  128.      * @return scaled square matrix of weights for quadratic terms
  129.      */
  130.     public RealMatrix getScaledH() {
  131.         return D.multiply(H).multiply(D).scalarMultiply(c);
  132.     }

  133.     /** Get scaled constraints coefficients matrix.
  134.      * @return scaled constraints coefficients matrix
  135.      */
  136.     public RealMatrix getScaledA() {
  137.         return E.multiply(A).multiply(D);
  138.     }

  139.     /** Get scaled vector of weights for linear terms.
  140.      * @return scaled vector of weights for linear terms
  141.      */
  142.     public RealVector getScaledQ() {
  143.         return D.operate(q.mapMultiply(c));
  144.     }

  145.     /** Get scaled upper bound
  146.      * @param lb1 unscaled lower bound
  147.      * @return scaled lower bound
  148.      */
  149.     public RealVector getScaledLUb(RealVector lb1) {
  150.         RealVector scaledLUb = new ArrayRealVector(lb1.getDimension());
  151.         for (int i = 0; i < lb1.getDimension(); i++) {
  152.             if (lb1.getEntry(i) != Double.POSITIVE_INFINITY) {
  153.                 scaledLUb.setEntry(i, E.getEntry(i, i) * lb1.getEntry(i));
  154.             } else {
  155.                 scaledLUb.setEntry(i, Double.POSITIVE_INFINITY);
  156.             }
  157.         }
  158.         return scaledLUb;
  159.     }

  160.     /** Unscale solution vector.
  161.      * @param x scaled solution vector
  162.      * @return unscaled solution vector
  163.      */
  164.     public RealVector unscaleX(RealVector x) {
  165.         return D.operate(x);
  166.     }

  167.     /** Unscale Y vector.
  168.      * @param y scaled Y vector
  169.      * @return unscaled Y vector
  170.      */
  171.     public RealVector unscaleY(RealVector y) {
  172.         return E.operate(y).mapMultiply(cinv);
  173.     }

  174.     /** Unscale Z vector.
  175.      * @param z scaled Z vector
  176.      * @return unscaled Z vector
  177.      */
  178.     public RealVector unscaleZ(RealVector z) {
  179.         return Einv.operate(z);
  180.     }

  181.     /** Scale solution vector.
  182.      * @param x unscaled solution vector
  183.      * @return scaled solution vector
  184.      */
  185.     RealVector scaleX(RealVector x) {
  186.         return Dinv.operate(x);
  187.     }

  188.     /** Limit scaling.
  189.      * @param v vector to limit
  190.      * @return rescaled vector, taking scaling limits into account
  191.      */
  192.     private RealVector limitScaling(RealVector v) {

  193.         RealVector result = new ArrayRealVector(v.getDimension());
  194.         for (int i = 0; i < v.getDimension(); i++) {
  195.             result.setEntry(i,  v.getEntry(i) < MIN_SCALING ? 1.0 : v.getEntry(i));
  196.             result.setEntry(i,  v.getEntry(i) > MAX_SCALING ? MAX_SCALING : v.getEntry(i));
  197.         }

  198.         return result;

  199.     }

  200. }