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.RealMatrix;
20 import org.hipparchus.linear.RealVector;
21 import org.hipparchus.optim.ConvergenceChecker;
22 import org.hipparchus.optim.OptimizationData;
23 import org.hipparchus.util.FastMath;
24
25 /** Convergence Checker for ADMM QP Optimizer.
26 * @since 3.1
27 */
28 public class ADMMQPConvergenceChecker implements ConvergenceChecker<LagrangeSolution>, OptimizationData {
29
30 /** Quadratic term matrix. */
31 private final RealMatrix h;
32
33 /** Constraint coefficients matrix. */
34 private final RealMatrix a;
35
36 /** Linear term matrix. */
37 private final RealVector q;
38
39 /** Absolute tolerance for convergence. */
40 private final double epsAbs;
41
42 /** Relative tolerance for convergence. */
43 private final double epsRel;
44
45 /** Convergence indicator. */
46 private boolean converged;
47
48 /** Simple constructor.
49 * @param h quadratic term matrix
50 * @param a constraint coefficients matrix
51 * @param q linear term matrix
52 * @param epsAbs
53 * @param epsRel
54 */
55 ADMMQPConvergenceChecker(final RealMatrix h, final RealMatrix a, final RealVector q,
56 final double epsAbs, final double epsRel) {
57 this.h = h;
58 this.a = a;
59 this.q = q;
60 this.epsAbs = epsAbs;
61 this.epsRel = epsRel;
62 this.converged = false;
63 }
64
65 /** {@inheritDoc} */
66 @Override
67 public boolean converged(final int i, final LagrangeSolution previous, final LagrangeSolution current) {
68 return converged;
69 }
70
71 /** Evaluate convergence.
72 * @param rp primal residual
73 * @param rd dual residual
74 * @param maxPrimal primal vectors max
75 * @param maxDual dual vectors max
76 * @return true of convergence has been reached
77 */
78 public boolean converged(final double rp, final double rd, final double maxPrimal, final double maxDual) {
79 boolean result = false;
80
81 if (rp <= epsPrimalDual(maxPrimal) && rd <= epsPrimalDual(maxDual)) {
82 result = true;
83 converged = true;
84 }
85 return result;
86 }
87
88 /** Compute primal residual.
89 * @param x primal problem solution
90 * @param z auxiliary variable
91 * @return primal residual
92 */
93 public double residualPrime(final RealVector x, final RealVector z) {
94 return a.operate(x).subtract(z).getLInfNorm();
95 }
96
97 /** Compute dual residual.
98 * @param x primal problem solution
99 * @param y dual problem solution
100 * @return dual residual
101 */
102 public double residualDual(final RealVector x, final RealVector y) {
103 return q.add(a.transpose().operate(y)).add(h.operate(x)).getLInfNorm();
104 }
105
106 /** Compute primal vectors max.
107 * @param x primal problem solution
108 * @param z auxiliary variable
109 * @return primal vectors max
110 */
111 public double maxPrimal(final RealVector x, final RealVector z) {
112 return FastMath.max(a.operate(x).getLInfNorm(), z.getLInfNorm());
113 }
114
115 /** Compute dual vectors max.
116 * @param x primal problem solution
117 * @param y dual problem solution
118 * @return dual vectors max
119 */
120 public double maxDual(final RealVector x, final RealVector y) {
121 return FastMath.max(FastMath.max(h.operate(x).getLInfNorm(),
122 a.transpose().operate(y).getLInfNorm()),
123 q.getLInfNorm());
124 }
125
126 /** Combine absolute and relative tolerances.
127 * @param maxPrimalDual either {@link #maxPrimal(RealVector, RealVector)}
128 * or {@link #maxDual(RealVector, RealVector)}
129 * @return global tolerance
130 */
131 private double epsPrimalDual(final double maxPrimalDual) {
132 return epsAbs + epsRel * maxPrimalDual;
133 }
134
135 }