1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
26
27
28 public class ADMMQPModifiedRuizEquilibrium {
29
30
31 private static final double MIN_SCALING = 1.0e-6;
32
33
34 private static final double MAX_SCALING = 1.0e+6;
35
36
37 private final RealMatrix H;
38
39
40 private final RealVector q;
41
42
43 private final RealMatrix A;
44
45
46 private RealMatrix D;
47
48
49 private RealMatrix E;
50
51
52 private double c;
53
54
55 private RealMatrix Dinv;
56
57
58 private RealMatrix Einv;
59
60
61 private double cinv;
62
63
64
65
66
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
75
76
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
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
157
158
159 public RealMatrix getScaledH() {
160 return D.multiply(H).multiply(D).scalarMultiply(c);
161 }
162
163
164
165
166 public RealMatrix getScaledA() {
167 return E.multiply(A).multiply(D);
168 }
169
170
171
172
173 public RealVector getScaledQ() {
174 return D.operate(q.mapMultiply(c));
175 }
176
177
178
179
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
194
195
196
197 public RealVector unscaleX(RealVector x) {
198 return D.operate(x);
199 }
200
201
202
203
204
205 public RealVector unscaleY(RealVector y) {
206 return E.operate(y).mapMultiply(cinv);
207 }
208
209
210
211
212
213 public RealVector unscaleZ(RealVector z) {
214 return Einv.operate(z);
215 }
216
217
218
219
220
221 RealVector scaleX(RealVector x) {
222 return Dinv.operate(x);
223 }
224
225
226
227
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 }