1 /*
2  * Licensed to the Apache Software Foundation (ASF) 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 ASF 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  *      http://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 
18 package org.apache.commons.math3.optim.nonlinear.vector.jacobian;
19 
20 import java.util.ArrayList;
21 
22 import org.apache.commons.math3.analysis.MultivariateVectorFunction;
23 import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
24 import org.apache.commons.math3.analysis.UnivariateFunction;
25 import org.apache.commons.math3.stat.regression.SimpleRegression;
26 import org.apache.commons.math3.optim.nonlinear.vector.ModelFunction;
27 import org.apache.commons.math3.optim.nonlinear.vector.ModelFunctionJacobian;
28 
29 /**
30  * Class that models a straight line defined as {@code y = a x + b}.
31  * The parameters of problem are:
32  * <ul>
33  *  <li>{@code a}</li>
34  *  <li>{@code b}</li>
35  * </ul>
36  * The model functions are:
37  * <ul>
38  *  <li>for each pair (a, b), the y-coordinate of the line.</li>
39  * </ul>
40  */
41 @Deprecated
42 class StraightLineProblem {
43     /** Cloud of points assumed to be fitted by a straight line. */
44     private final ArrayList<double[]> points;
45     /** Error (on the y-coordinate of the points). */
46     private final double sigma;
47 
48     /**
49      * @param error Assumed error for the y-coordinate.
50      */
StraightLineProblem(double error)51     public StraightLineProblem(double error) {
52         points = new ArrayList<double[]>();
53         sigma = error;
54     }
55 
addPoint(double px, double py)56     public void addPoint(double px, double py) {
57         points.add(new double[] { px, py });
58     }
59 
60     /**
61      * @return the list of x-coordinates.
62      */
x()63     public double[] x() {
64         final double[] v = new double[points.size()];
65         for (int i = 0; i < points.size(); i++) {
66             final double[] p = points.get(i);
67             v[i] = p[0]; // x-coordinate.
68         }
69 
70         return v;
71     }
72 
73     /**
74      * @return the list of y-coordinates.
75      */
y()76     public double[] y() {
77         final double[] v = new double[points.size()];
78         for (int i = 0; i < points.size(); i++) {
79             final double[] p = points.get(i);
80             v[i] = p[1]; // y-coordinate.
81         }
82 
83         return v;
84     }
85 
target()86     public double[] target() {
87         return y();
88     }
89 
weight()90     public double[] weight() {
91         final double weight = 1 / (sigma * sigma);
92         final double[] w = new double[points.size()];
93         for (int i = 0; i < points.size(); i++) {
94             w[i] = weight;
95         }
96 
97         return w;
98     }
99 
getModelFunction()100     public ModelFunction getModelFunction() {
101         return new ModelFunction(new MultivariateVectorFunction() {
102                 public double[] value(double[] params) {
103                     final Model line = new Model(params[0], params[1]);
104 
105                     final double[] model = new double[points.size()];
106                     for (int i = 0; i < points.size(); i++) {
107                         final double[] p = points.get(i);
108                         model[i] = line.value(p[0]);
109                     }
110 
111                     return model;
112                 }
113             });
114     }
115 
116     public ModelFunctionJacobian getModelFunctionJacobian() {
117         return new ModelFunctionJacobian(new MultivariateMatrixFunction() {
118                 public double[][] value(double[] point) {
119                     return jacobian(point);
120                 }
121             });
122     }
123 
124     /**
125      * Directly solve the linear problem, using the {@link SimpleRegression}
126      * class.
127      */
128     public double[] solve() {
129         final SimpleRegression regress = new SimpleRegression(true);
130         for (double[] d : points) {
131             regress.addData(d[0], d[1]);
132         }
133 
134         final double[] result = { regress.getSlope(), regress.getIntercept() };
135         return result;
136     }
137 
138     private double[][] jacobian(double[] params) {
139         final double[][] jacobian = new double[points.size()][2];
140 
141         for (int i = 0; i < points.size(); i++) {
142             final double[] p = points.get(i);
143             // Partial derivative wrt "a".
144             jacobian[i][0] = p[0];
145             // Partial derivative wrt "b".
146             jacobian[i][1] = 1;
147         }
148 
149         return jacobian;
150     }
151 
152     /**
153      * Linear function.
154      */
155     public static class Model implements UnivariateFunction {
156         final double a;
157         final double b;
158 
159         public Model(double a,
160                      double b) {
161             this.a = a;
162             this.b = b;
163         }
164 
165         public double value(double x) {
166             return a * x + b;
167         }
168     }
169 }
170