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.exception.MathIllegalArgumentException;
20  import org.hipparchus.optim.InitialGuess;
21  import org.hipparchus.optim.nonlinear.scalar.ObjectiveFunction;
22  import org.junit.jupiter.api.Test;
23  
24  import static org.junit.jupiter.api.Assertions.assertEquals;
25  import static org.junit.jupiter.api.Assertions.assertNotNull;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  import static org.junit.jupiter.api.Assertions.fail;
28  
29  class ADMMQPOptimizerTest extends AbstractConstrainedOptimizerTest {
30  
31      protected ConstraintOptimizer buildOptimizer() {
32          return new ADMMQPOptimizer();
33      }
34  
35      @Test
36      void test1() {
37          QuadraticFunction q = new QuadraticFunction(new double[][] { { 4.0, -2.0 }, { -2.0, 4.0 } },
38                                                      new double[] { 6.0, 0.0 },
39                                                      0.0);
40  
41          // y = 1
42          LinearEqualityConstraint eqc = new LinearEqualityConstraint(new double[][] { { 0.0, 1.0 } },
43                                                                      new double[] { 1.0 });
44  
45  
46          // x > 0, y > 0, x + y > 2
47          LinearInequalityConstraint ineqc = new LinearInequalityConstraint(new double[][] { { 1.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 1.0 } },
48                                                                            new double[] { 0.0, 0.0, 2.0 });
49  
50  
51          doTestProblem(new double[] {  1, 1 },       2.5e-5,
52                        new double[] { -6, 0, 0, 8 }, 2.6e-4,
53                        8, 2.0e-4,
54                        new ObjectiveFunction(q),
55                        null,
56                        eqc, ineqc);
57  
58      }
59  
60      @Test
61      void test2() {
62          QuadraticFunction q = new QuadraticFunction(new double[][] { { 6.0, 2.0 }, { 2.0, 8.0 } },
63                                                      new double[] { 5.0, 1.0 },
64                                                      0.0);
65  
66          // constraint x + 2y = 1
67          LinearEqualityConstraint eqc = new LinearEqualityConstraint(new double[][] { { 1.0, 2.0 } },
68                                                                      new double[] { 1.0 });
69  
70          // x > 0, y > 0
71          LinearInequalityConstraint ineqc = new LinearInequalityConstraint(new double[][] { { 1.0, 0.0 }, { 0.0, 1.0 } },
72                                                                            new double[] { 0.0, 0.0 });
73  
74  
75          doTestProblem(new double[] {  0, 0.5 },     1.1e-5,
76                        new double[] { 2.5, 3.5, 0 }, 8.5e-6,
77                        1.5, 6.3e-5,
78                        new ObjectiveFunction(q),
79                        null,
80                        eqc, ineqc);
81  
82      }
83  
84      @Test
85      void testBounded() {
86          QuadraticFunction q = new QuadraticFunction(new double[][] { { 1.0, 0.0 }, { 0, 1.0 } },
87                                                      new double[] { -3.0, -1.0 },
88                                                      5.0);
89  
90          // 0 < x < 2, 0 < y < 2
91          LinearBoundedConstraint ineqc = new LinearBoundedConstraint(new double[][] { { 1.0, 0.0 },{ 0.0, 1.0 }},
92                                                                       new double[] { 0.0,0.0 }, new double[] { 2.0,2.0 });
93  
94  
95          doTestProblem(new double[] { 2, 1 }, 4.6e-6,
96                        new double[] { 1, 0 }, 3.1e-5,
97                        0.5, 4.6e-6,
98                        new ObjectiveFunction(q),
99                        null,
100                       ineqc);
101 
102     }
103 
104     @Test
105     void testOptimizeWithGuess() {
106         // GIVEN
107         final ADMMQPOptimizer optimizer = createOptimizerOnSimpleProblem(false, false);
108         optimizer.parseOptimizationData(new InitialGuess(new double[2]));
109 
110         // WHEN
111         final LagrangeSolution solution  = optimizer.optimize();
112 
113         // THEN
114         assertNotNull(optimizer.getConvergenceChecker());
115         assertTrue(optimizer.isConverged());
116         assertEquals(0., solution.getValue(), 0);
117     }
118 
119     @Test
120     void testOptimizeWithoutScaling() {
121         // GIVEN
122         final ADMMQPOptimizer optimizer = createOptimizerOnSimpleProblem(false, false);
123 
124         // WHEN
125         final LagrangeSolution solution  = optimizer.optimize();
126 
127         // THEN
128         assertNotNull(optimizer.getConvergenceChecker());
129         assertTrue(optimizer.isConverged());
130         assertEquals(0., solution.getValue(), 0);
131     }
132 
133     @Test
134     void testOptimizeWithPolishWithScaling() {
135         // GIVEN
136         final ADMMQPOptimizer optimizer = createOptimizerOnSimpleProblem(true, true);
137 
138         // WHEN
139         final LagrangeSolution solution  = optimizer.optimize();
140 
141         // THEN
142         assertNotNull(optimizer.getConvergenceChecker());
143         assertTrue(optimizer.isConverged());
144         assertEquals(0., solution.getValue(), 0);
145     }
146 
147     @Test
148     void testOptimizeWithPolishWithoutScaling() {
149         // GIVEN
150         final ADMMQPOptimizer optimizer = createOptimizerOnSimpleProblem(true, false);
151 
152         // WHEN
153         final LagrangeSolution solution  = optimizer.optimize();
154 
155         // THEN
156         assertNotNull(optimizer.getConvergenceChecker());
157         assertTrue(optimizer.isConverged());
158         assertEquals(0., solution.getValue(), 0);
159     }
160 
161     private ADMMQPOptimizer createOptimizerOnSimpleProblem(final boolean polishing, final boolean scaling) {
162         final QuadraticFunction q = new QuadraticFunction(new double[][] { { 1.0, 0.0 }, { 0.0, 1.0 } },
163                 new double[] { 0.0, 0.0 }, 0.0);
164         final LinearEqualityConstraint eqc = new LinearEqualityConstraint(new double[][] { { 1.0, 1.0 } },
165                 new double[] { 0.0 });
166 
167         final ADMMQPOption option = new ADMMQPOption();
168         option.setPolishing(polishing);
169         option.setScaling(scaling);
170 
171         final ADMMQPOptimizer optimizer = new ADMMQPOptimizer();
172         optimizer.parseOptimizationData(new ObjectiveFunction(q), eqc, option);
173         return optimizer;
174     }
175 
176     @Test
177     void testParseOptimizationDataException() {
178         // GIVEN
179         final ADMMQPOptimizer testSQPOptimizer = new ADMMQPOptimizer();
180         final EqualityConstraint equalityConstraint = new LinearEqualityConstraint(new double[1][1], new double[1]);
181         final QuadraticFunction multivariateFunction = new QuadraticFunction(new double[1][1], new double[1], 0);
182         final ObjectiveFunction objectiveFunction = new ObjectiveFunction(multivariateFunction);
183         // WHEN
184         try {
185             testSQPOptimizer.parseOptimizationData(objectiveFunction, equalityConstraint);
186             fail();
187         } catch (final MathIllegalArgumentException exception) {
188             assertEquals("rank of constraints must be lesser than domain dimension, but 1 >= 1",
189                     exception.getMessage());
190         }
191     }
192 
193 }