GteApprPolynomial2.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteArray2.h>
11 #include <Mathematics/GteGMatrix.h>
13 #include <array>
14 
15 // The samples are (x[i],w[i]) for 0 <= i < S. Think of w as a function of
16 // x, say w = f(x). The function fits the samples with a polynomial of
17 // degree d, say w = sum_{i=0}^d c[i]*x^i. The method is a least-squares
18 // fitting algorithm. The mParameters stores the coefficients c[i] for
19 // 0 <= i <= d. The observation type is std::array<Real,2>, which represents
20 // a pair (x,w).
21 //
22 // WARNING. The fitting algorithm for polynomial terms
23 // (1,x,x^2,...,x^d)
24 // is known to be nonrobust for large degrees and for large magnitude data.
25 // One alternative is to use orthogonal polynomials
26 // (f[0](x),...,f[d](x))
27 // and apply the least-squares algorithm to these. Another alternative is to
28 // transform
29 // (x',w') = ((x-xcen)/rng, w/rng)
30 // where xmin = min(x[i]), xmax = max(x[i]), xcen = (xmin+xmax)/2, and
31 // rng = xmax-xmin. Fit the (x',w') points,
32 // w' = sum_{i=0}^d c'[i]*(x')^i.
33 // The original polynomial is evaluated as
34 // w = rng*sum_{i=0}^d c'[i]*((x-xcen)/rng)^i
35 
36 namespace gte
37 {
38 
39 template <typename Real>
41  :
42  public ApprQuery<Real, ApprPolynomial2<Real>, std::array<Real, 2>>
43 {
44 public:
45  // Initialize the model parameters to zero.
46  ApprPolynomial2(int degree);
47 
48  // The minimum number of observations required to fit the model.
49  int GetMinimumRequired() const;
50 
51  // Estimate the model parameters for all observations specified by the
52  // indices. This function is called by the base-class Fit(...) functions.
53  bool Fit(std::vector<std::array<Real, 2>> const& observations,
54  std::vector<int> const& indices);
55 
56  // Compute the model error for the specified observation for the current
57  // model parameters. The returned value for observation (x0,w0) is
58  // |w(x0) - w0|, where w(x) is the fitted polynomial.
59  Real Error(std::array<Real, 2> const& observation) const;
60 
61  // Get the parameters of the model.
62  std::vector<Real> const& GetParameters() const;
63 
64  // Evaluate the polynomial. The domain interval is provided so you can
65  // interpolate (x in domain) or extrapolate (x not in domain).
66  std::array<Real, 2> const& GetXDomain() const;
67  Real Evaluate(Real x) const;
68 
69 private:
70  int mDegree, mSize;
71  std::array<Real, 2> mXDomain;
72  std::vector<Real> mParameters;
73 };
74 
75 
76 template <typename Real>
78  :
79  mDegree(degree),
80  mSize(degree + 1),
82 {
83  mXDomain[0] = std::numeric_limits<Real>::max();
84  mXDomain[1] = -mXDomain[0];
85  std::fill(mParameters.begin(), mParameters.end(), (Real)0);
86 }
87 
88 template <typename Real>
90 {
91  return mSize;
92 }
93 
94 template <typename Real>
96  std::vector<std::array<Real, 2>> const& observations,
97  std::vector<int> const& indices)
98 {
99  if (indices.size() > 0)
100  {
101  int s, i0, i1;
102 
103  // Compute the powers of x.
104  int numSamples = static_cast<int>(indices.size());
105  int twoDegree = 2 * mDegree;
106  Array2<Real> xPower(twoDegree + 1, numSamples);
107  for (s = 0; s < numSamples; ++s)
108  {
109  Real x = observations[indices[s]][0];
110  mXDomain[0] = std::min(x, mXDomain[0]);
111  mXDomain[1] = std::max(x, mXDomain[1]);
112 
113  xPower[s][0] = (Real)1;
114  for (i0 = 1; i0 <= twoDegree; ++i0)
115  {
116  xPower[s][i0] = x * xPower[s][i0 - 1];
117  }
118  }
119 
120  // Matrix A is the Vandermonde matrix and vector B is the right-hand
121  // side of the linear system A*X = B.
123  GVector<Real> B(mSize);
124  for (i0 = 0; i0 <= mDegree; ++i0)
125  {
126  Real sum = (Real)0;
127  for (s = 0; s < numSamples; ++s)
128  {
129  Real w = observations[indices[s]][1];
130  sum += w * xPower[s][i0];
131  }
132 
133  B[i0] = sum;
134 
135  for (i1 = 0; i1 <= mDegree; ++i1)
136  {
137  sum = (Real)0;
138  for (s = 0; s < numSamples; ++s)
139  {
140  sum += xPower[s][i0 + i1];
141  }
142 
143  A(i0, i1) = sum;
144  }
145  }
146 
147  // Solve for the polynomial coefficients.
148  GVector<Real> coefficients = Inverse(A) * B;
149  bool hasNonzero = false;
150  for (int i = 0; i < mSize; ++i)
151  {
152  mParameters[i] = coefficients[i];
153  if (coefficients[i] != (Real)0)
154  {
155  hasNonzero = true;
156  }
157  }
158  return hasNonzero;
159 
160  }
161 
162  std::fill(mParameters.begin(), mParameters.end(), (Real)0);
163  return false;
164 }
165 
166 template <typename Real>
167 Real ApprPolynomial2<Real>::Error(std::array<Real, 2> const& observation)
168 const
169 {
170  Real w = Evaluate(observation[0]);
171  Real error = std::abs(w - observation[1]);
172  return error;
173 }
174 
175 template <typename Real>
176 std::vector<Real> const& ApprPolynomial2<Real>::GetParameters() const
177 {
178  return mParameters;
179 }
180 
181 template <typename Real>
182 std::array<Real, 2> const& ApprPolynomial2<Real>::GetXDomain() const
183 {
184  return mXDomain;
185 }
186 
187 template <typename Real>
189 {
190  int i = mDegree;
191  Real w = mParameters[i];
192  while (--i >= 0)
193  {
194  w = mParameters[i] + w * x;
195  }
196  return w;
197 }
198 
199 
200 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
std::array< Real, 2 > const & GetXDomain() const
Real Evaluate(Real x) const
std::vector< Real > const & GetParameters() const
std::vector< Real > mParameters
GLint GLenum GLint x
Definition: glcorearb.h:404
bool Fit(std::vector< std::array< Real, 2 >> const &observations, std::vector< int > const &indices)
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:852
GLsizei GLenum const void * indices
Definition: glcorearb.h:401
GLdouble s
Definition: glext.h:231
int GetMinimumRequired() const
std::array< Real, 2 > mXDomain
Quaternion< Real > Inverse(Quaternion< Real > const &d)
Real Error(std::array< Real, 2 > const &observation) const


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59