View Javadoc
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  
19  import org.hipparchus.linear.ArrayRealVector;
20  import org.hipparchus.linear.MatrixUtils;
21  import org.hipparchus.linear.RealMatrix;
22  import org.hipparchus.linear.RealVector;
23  import org.hipparchus.util.FastMath;
24  
25  /** TBD.
26   * @since 3.1
27   */
28  public class ADMMQPModifiedRuizEquilibrium {
29  
30      /** Minimum scaling value. */
31      private static final double MIN_SCALING = 1.0e-6;
32  
33      /** Maximum scaling value. */
34      private static final double MAX_SCALING = 1.0e+6;
35  
36      /** Square matrix of weights for quadratic terms. */
37      private final RealMatrix H;
38  
39      /** Vector of weights for linear terms. */
40      private final RealVector q;
41  
42      /** Constraints coefficients matrix. */
43      private final RealMatrix A;
44  
45      /** TBC. */
46      private RealMatrix D;
47  
48      /** TBC. */
49      private RealMatrix E;
50  
51      /** TBC. */
52      private double c;
53  
54      /** Inverse of D. */
55      private RealMatrix Dinv;
56  
57      /** Inverse of E. */
58      private RealMatrix Einv;
59  
60      /** Inverse of c. */
61      private double cinv;
62  
63      /** Simple constructor
64       * @param H square matrix of weights for quadratic terms
65       * @param A constraints coefficients matrix
66       * @param q vector of weights for linear terms
67       */
68      public ADMMQPModifiedRuizEquilibrium(RealMatrix H, RealMatrix A, RealVector q) {
69          this.H  = H;
70          this.A  = A;
71          this.q  = q;
72      }
73  
74      /** Normalize matrices.
75       * @param epsilon TBD
76       * @param maxIteration TBD
77       */
78      public void normalize(double epsilon, int maxIteration) {
79  
80          int iteration = 0;
81          this.c = 1.0;
82          RealVector gammaD = new ArrayRealVector(H.getRowDimension());
83          RealVector gammaE = new ArrayRealVector(A.getRowDimension());
84  
85          double lambda;
86          RealVector q1 = q.copy();
87          RealMatrix H1 = H.copy();
88          RealMatrix A1 = A.copy();
89          RealMatrix diagD;
90          RealMatrix diagE;
91          RealMatrix SD = MatrixUtils.createRealIdentityMatrix(H.getRowDimension());
92          RealMatrix SE = MatrixUtils.createRealIdentityMatrix(A.getRowDimension());
93          RealVector H1norm = new ArrayRealVector(H1.getColumnDimension());
94          while (iteration < maxIteration) {
95         // while (1.0 - gamma.getLInfNorm() > epsilon && iteration < maxIteration) {
96  
97              for (int i = 0; i < H1.getColumnDimension(); i++) {
98                  double norma = (new ArrayRealVector(H1.getColumn(i), A1.getColumn(i))).getLInfNorm();
99                  gammaD.setEntry(i, norma);
100             }
101 
102             for (int i = 0; i < A1.getRowDimension(); i++) {
103                 double norma = A1.getRowVector(i).getLInfNorm();
104                 gammaE.setEntry(i, norma);
105             }
106 
107             gammaD = limitScaling(gammaD);
108             gammaE = limitScaling(gammaE);
109 
110             for (int i = 0; i < gammaD.getDimension(); i++) {
111                 gammaD.setEntry(i, 1.0 / FastMath.sqrt(gammaD.getEntry(i)));
112             }
113 
114             for (int i = 0; i < gammaE.getDimension(); i++) {
115                 gammaE.setEntry(i, 1.0 / FastMath.sqrt(gammaE.getEntry(i)));
116             }
117 
118             diagD = MatrixUtils.createRealDiagonalMatrix(gammaD.toArray());
119             diagE = MatrixUtils.createRealDiagonalMatrix(gammaE.toArray());
120 
121             H1 = diagD.multiply(H1.copy()).multiply(diagD.copy());
122             q1 = diagD.operate(q1.copy());
123             A1 = diagE.multiply(A1.copy()).multiply(diagD.copy());
124 
125             for (int i = 0; i < H1.getRowDimension(); i++) {
126                 double norma = (new ArrayRealVector(H1.getRow(i))).getLInfNorm();
127                 H1norm.setEntry(i, norma);
128             }
129             double qnorm = q1.getLInfNorm();
130             if (qnorm == 0) {
131                 qnorm = 1.0;
132             }
133             qnorm = limitScaling(new ArrayRealVector(1, qnorm)).getEntry(0);
134             double mean = 0;
135             for (int i = 0; i < H1norm.getDimension(); i++) {
136                 mean+=H1norm.getEntry(i) / H1norm.getDimension();
137             }
138 
139             lambda = 1.0 / limitScaling(new ArrayRealVector(1, FastMath.max(mean, qnorm))).getEntry(0);
140 
141             H1 = H1.copy().scalarMultiply(lambda);
142             q1 = q1.copy().mapMultiply(lambda);
143             c *= lambda;
144             SD = diagD.multiply(SD.copy());
145             SE = diagE.multiply(SE.copy());
146             iteration += 1;
147         }
148         this.E    = SE.copy();
149         this.D    = SD.copy();
150         this.Einv = MatrixUtils.inverse(SE);
151         this.Dinv = MatrixUtils.inverse(SD);
152         this.cinv = 1.0 / c;
153 
154     }
155 
156     /** Get scaled square matrix of weights for quadratic terms.
157      * @return scaled square matrix of weights for quadratic terms
158      */
159     public RealMatrix getScaledH() {
160         return D.multiply(H).multiply(D).scalarMultiply(c);
161     }
162 
163     /** Get scaled constraints coefficients matrix.
164      * @return scaled constraints coefficients matrix
165      */
166     public RealMatrix getScaledA() {
167         return E.multiply(A).multiply(D);
168     }
169 
170     /** Get scaled vector of weights for linear terms.
171      * @return scaled vector of weights for linear terms
172      */
173     public RealVector getScaledQ() {
174         return D.operate(q.mapMultiply(c));
175     }
176 
177     /** Get scaled upper bound
178      * @param lb1 unscaled lower bound
179      * @return scaled lower bound
180      */
181     public RealVector getScaledLUb(RealVector lb1) {
182         RealVector scaledLUb = new ArrayRealVector(lb1.getDimension());
183         for (int i = 0; i < lb1.getDimension(); i++) {
184             if (lb1.getEntry(i) != Double.POSITIVE_INFINITY) {
185                 scaledLUb.setEntry(i, E.getEntry(i, i) * lb1.getEntry(i));
186             } else {
187                 scaledLUb.setEntry(i, Double.POSITIVE_INFINITY);
188             }
189         }
190         return scaledLUb;
191     }
192 
193     /** Unscale solution vector.
194      * @param x scaled solution vector
195      * @return unscaled solution vector
196      */
197     public RealVector unscaleX(RealVector x) {
198         return D.operate(x);
199     }
200 
201     /** Unscale Y vector.
202      * @param y scaled Y vector
203      * @return unscaled Y vector
204      */
205     public RealVector unscaleY(RealVector y) {
206         return E.operate(y).mapMultiply(cinv);
207     }
208 
209     /** Unscale Z vector.
210      * @param z scaled Z vector
211      * @return unscaled Z vector
212      */
213     public RealVector unscaleZ(RealVector z) {
214         return Einv.operate(z);
215     }
216 
217     /** Scale solution vector.
218      * @param x unscaled solution vector
219      * @return scaled solution vector
220      */
221     RealVector scaleX(RealVector x) {
222         return Dinv.operate(x);
223     }
224 
225     /** Limit scaling.
226      * @param v vector to limit
227      * @return rescaled vector, taking scaling limits into account
228      */
229     private RealVector limitScaling(RealVector v) {
230 
231         RealVector result = new ArrayRealVector(v.getDimension());
232         for (int i = 0; i < v.getDimension(); i++) {
233             result.setEntry(i,  v.getEntry(i) < MIN_SCALING ? 1.0 : v.getEntry(i));
234             result.setEntry(i,  v.getEntry(i) > MAX_SCALING ? MAX_SCALING : v.getEntry(i));
235         }
236 
237         return result;
238 
239     }
240 
241 }