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