OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
SquarePolynomialVector.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, Chris Rogers
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <algorithm>
29#include <cmath>
30#include <iomanip>
31#include <sstream>
32
33#include "Utilities/GSLCompat.h"
34
36
40
41namespace interpolation {
42
44 std::vector<std::vector<std::vector<int> > > SquarePolynomialVector::_polyKeyByPower;
45 std::vector<std::vector<std::vector<int> > > SquarePolynomialVector::_polyKeyByVector;
46
47 SquarePolynomialVector::SquarePolynomialVector() : _pointDim(0), _polyCoeffs() {}
48
50 : _pointDim(pv._pointDim),
51 _polyCoeffs(pv._polyCoeffs.num_row(), pv._polyCoeffs.num_col(), 0.) {
53 }
54
56 int numberOfInputVariables, MMatrix<double> polynomialCoefficients)
57 : _pointDim(numberOfInputVariables), _polyCoeffs(polynomialCoefficients) {
58 SetCoefficients(numberOfInputVariables, polynomialCoefficients);
59 }
60
61 SquarePolynomialVector::SquarePolynomialVector(std::vector<PolynomialCoefficient> coefficients)
62 : _pointDim(0), _polyCoeffs() {
63 SetCoefficients(coefficients);
64 }
65
67 _pointDim = pointDim;
68 _polyCoeffs = coeff;
69
70 if (int(_polyKeyByVector.size()) < pointDim
71 || _polyKeyByVector[pointDim - 1].size() < coeff.num_col())
72 IndexByVector(coeff.num_col(), pointDim); // sets _polyKeyByVector and _polyKeyByPower
73 }
74
75 void SquarePolynomialVector::SetCoefficients(std::vector<PolynomialCoefficient> coeff) {
76 _pointDim = 0;
77 int maxPolyOrder = 0;
78 int valueDim = 0;
79 for (unsigned int i = 0; i < coeff.size(); i++) {
80 int polyOrder = coeff[i].InVariables().size();
81 for (unsigned int j = 0; j < coeff[i].InVariables().size(); j++)
82 if (coeff[i].InVariables()[j] > _pointDim) _pointDim = coeff[i].InVariables()[j];
83 if (coeff[i].OutVariable() > valueDim) valueDim = coeff[i].OutVariable();
84 if (polyOrder > maxPolyOrder) maxPolyOrder = polyOrder;
85 }
86 _pointDim++; // PointDim indexes from 0
88 valueDim + 1, NumberOfPolynomialCoefficients(_pointDim, maxPolyOrder + 1), 0.);
89 if (int(_polyKeyByVector.size()) < _pointDim
92 _polyCoeffs.num_col(), _pointDim); // sets _polyKeyByVector and _polyKeyByPower
93
94 for (size_t i = 0; i < _polyCoeffs.num_col(); i++) {
95 for (unsigned int j = 0; j < coeff.size(); j++)
96 if (coeff[j].InVariables() == _polyKeyByVector[_pointDim - 1].back()) {
97 int dim = coeff[j].OutVariable();
98 _polyCoeffs(dim + 1, i + 1) = coeff[j].Coefficient();
99 }
100 }
101 }
102
104 for (size_t i = 0; i < coeff.num_row() && i < _polyCoeffs.num_row(); i++)
105 for (size_t j = 0; j < coeff.num_col() && j < _polyCoeffs.num_col(); j++)
106 _polyCoeffs(i + 1, j + 1) = coeff(i + 1, j + 1);
107 }
108
109 void SquarePolynomialVector::F(const double* point, double* value) const {
110 MVector<double> pointV(PointDimension(), 1), valueV(ValueDimension(), 1);
111 for (unsigned int i = 0; i < PointDimension(); i++)
112 pointV(i + 1) = point[i];
113 F(pointV, valueV);
114 for (unsigned int i = 0; i < ValueDimension(); i++)
115 value[i] = valueV(i + 1);
116 }
117
119 MVector<double> polyVector(_polyCoeffs.num_col(), 1);
120 MakePolyVector(point, polyVector);
121 MVector<double> answer = _polyCoeffs * polyVector;
122 for (unsigned int i = 0; i < ValueDimension(); i++)
123 value(i + 1) = answer(i + 1);
124 }
125
127 const MVector<double>& point, MVector<double>& polyVector) const {
128 for (unsigned int i = 0; i < _polyCoeffs.num_col(); i++) {
129 polyVector(i + 1) = 1.;
130 for (unsigned int j = 0; j < _polyKeyByVector[_pointDim - 1][i].size(); j++)
131 polyVector(i + 1) *= point(_polyKeyByVector[_pointDim - 1][i][j] + 1);
132 }
133 return polyVector;
134 }
135
136 double* SquarePolynomialVector::MakePolyVector(const double* point, double* polyVector) const {
137 for (unsigned int i = 0; i < _polyCoeffs.num_col(); i++) {
138 polyVector[i] = 1.;
139 for (unsigned int j = 0; j < _polyKeyByVector[i].size(); j++)
140 polyVector[i] *= point[_polyKeyByVector[_pointDim - 1][i][j]];
141 }
142 return polyVector;
143 }
144
146 std::vector<int> check, size_t check_index, size_t poly_power,
147 std::vector<std::vector<int> >& nearby_points) {
148 check[check_index] = poly_power;
149 nearby_points.push_back(check);
150 if (check_index + 1 == check.size()) return;
151 for (int i = 1; i < int(poly_power); ++i)
152 IndexByPowerRecursive(check, check_index + 1, i, nearby_points);
153 for (int i = 0; i <= int(poly_power); ++i) {
154 check[check_index] = i;
155 IndexByPowerRecursive(check, check_index + 1, poly_power, nearby_points);
156 }
157 }
158
159 std::vector<int> SquarePolynomialVector::IndexByPower(int index, int point_dim) {
160 if (point_dim < 1)
162 "SquarePolynomialVector::IndexByPower", "Point dimension must be > 0"));
163 while (int(_polyKeyByPower.size()) < point_dim)
164 _polyKeyByPower.push_back(std::vector<std::vector<int> >());
165 if (index < int(_polyKeyByPower[point_dim - 1].size()))
166 return _polyKeyByPower[point_dim - 1][index];
167 // poly_order 0 means constant term
168 std::vector<std::vector<int> > nearby_points(1, std::vector<int>(point_dim, 0));
169 // poly_order > 0 means corresponding poly terms (1 is linear, 2 is quadratic...)
170 int this_poly_order = 0;
171 while (int(nearby_points.size()) < index + 1) {
172 IndexByPowerRecursive(nearby_points[0], 0, this_poly_order + 1, nearby_points);
173 this_poly_order += 1;
174 }
175 _polyKeyByPower[point_dim - 1] = nearby_points;
176 return _polyKeyByPower[point_dim - 1][index];
177 }
178
179 // Turn int index into an index for element of polynomial
180 // e.g. x_1^4 x_2^3 = {1,1,1,1,2,2,2}
181 std::vector<int> SquarePolynomialVector::IndexByVector(int index, int point_dim) {
182 while (int(_polyKeyByVector.size()) < point_dim)
183 _polyKeyByVector.push_back(std::vector<std::vector<int> >());
184 // if _polyKeyByVector is big enough, just return the value
185 if (index < int(_polyKeyByVector[point_dim - 1].size()))
186 return _polyKeyByVector[point_dim - 1][index];
187 // make sure _polyKeyByPower is big enough
188 IndexByPower(index, point_dim);
189 // update _polyKeyByVector with values from _polyKeyByPower
190 for (size_t i = _polyKeyByVector[point_dim - 1].size();
191 i < _polyKeyByPower[point_dim - 1].size(); ++i) {
192 _polyKeyByVector[point_dim - 1].push_back(std::vector<int>());
193 for (size_t j = 0; j < _polyKeyByPower[point_dim - 1][i].size(); ++j)
194 for (int k = 0; k < _polyKeyByPower[point_dim - 1][i][j]; ++k)
195 _polyKeyByVector[point_dim - 1][i].push_back(j);
196 }
197 return _polyKeyByVector[point_dim - 1][index];
198 }
199
201 int pointDimension, int order) {
202 int number = 1;
203 for (int i = 0; i < pointDimension; ++i)
204 number *= order + 1;
205 return number;
206 }
207
208 std::ostream& operator<<(std::ostream& out, const SquarePolynomialVector& spv) {
209 if (SquarePolynomialVector::_printHeaders) spv.PrintHeader(out, '.', ' ', 14, true);
210 out << '\n' << spv.GetCoefficientsAsMatrix();
211 return out;
212 }
213
215 std::ostream& out, char int_separator, char str_separator, int length,
216 bool pad_at_start) const {
217 if (!_polyKeyByPower[_pointDim - 1].empty())
218 PrintContainer<std::vector<int> >(
219 out, _polyKeyByPower[_pointDim - 1][0], int_separator, str_separator,
220 length - 1, pad_at_start);
221 for (unsigned int i = 1; i < _polyCoeffs.num_col(); ++i)
222 PrintContainer<std::vector<int> >(
223 out, _polyKeyByPower[_pointDim - 1][i], int_separator, str_separator, length,
224 pad_at_start);
225 }
226
227 template <class Container>
229 std::ostream& out, const Container& container, char T_separator, char str_separator,
230 int length, bool pad_at_start) {
231 // class Container::iterator it;
232 std::stringstream strstr1("");
233 std::stringstream strstr2("");
234 typename Container::const_iterator it1 = container.begin();
235 typename Container::const_iterator it2 = it1;
236 while (it1 != container.end()) {
237 it2++;
238 if (it1 != container.end() && it2 != container.end())
239 strstr1 << (*it1) << T_separator;
240 else
241 strstr1 << (*it1);
242 it1++;
243 }
244
245 if (int(strstr1.str().size()) > length && length > 0)
246 strstr2 << strstr1.str().substr(1, length);
247 else
248 strstr2 << strstr1.str();
249
250 if (!pad_at_start) out << strstr2.str();
251 for (int i = 0; i < length - int(strstr2.str().size()); i++)
252 out << str_separator;
253 if (pad_at_start) out << strstr2.str();
254 }
255
257 std::vector<int> index = IndexByPower(_polyCoeffs.num_col(), _pointDim);
258 size_t maxPower = *std::max_element(index.begin(), index.end());
259 return maxPower;
260 }
261
263 if (derivPower == nullptr) {
265 "SquarePolynomialVector::Deriv", "Derivative points to nullptr"));
266 }
267 MMatrix<double> newPolyCoeffs(_polyCoeffs.num_row(), _polyCoeffs.num_col(), 0.);
268 std::vector<std::vector<int> > powerKey = _polyKeyByPower[_pointDim - 1];
269 for (size_t j = 0; j < _polyCoeffs.num_col(); ++j) {
270 std::vector<int> thisPower = powerKey[j];
271 std::vector<int> newPower(_pointDim);
272 // f(x) = Product(x_i^t_i)
273 // d^n f(x) / Product(d x_j^d_j) =
274 // t_i >= d_j ... Product(x_i^(t_i - d_j) * t_i!/(t_i-d_j)!
275 // t_i < d_j ... 0
276 double newCoeff = 1.;
277 // calculate the coefficient
278 for (size_t k = 0; k < thisPower.size(); ++k) {
279 newPower[k] = thisPower[k] - derivPower[k];
280 if (newPower[k] < 0) {
281 newCoeff = 0.;
282 break;
283 }
284 newCoeff *= gsl_sf_fact(thisPower[k]) / gsl_sf_fact(newPower[k]);
285 }
286 // put it in the matrix of coefficients
287 for (size_t k = 0; k < powerKey.size(); ++k) {
288 bool match = true;
289 for (size_t l = 0; l < powerKey[k].size(); ++l) {
290 if (powerKey[k][l] != newPower[l]) {
291 match = false;
292 break;
293 }
294 }
295 if (match) {
296 for (size_t i = 0; i < _polyCoeffs.num_row(); ++i) {
297 newPolyCoeffs(i + 1, k + 1) = newCoeff * _polyCoeffs(i + 1, j + 1);
298 }
299 }
300 }
301 }
302 SquarePolynomialVector vec(_pointDim, newPolyCoeffs);
303 return vec;
304 }
305
306} // namespace interpolation
double gsl_sf_fact(unsigned int n)
Factorial (computed via for large ).
Definition GSLCompat.h:69
size_t num_col() const
returns number of columns in the matrix
size_t num_row() const
returns number of rows in the matrix
SquarePolynomialVector describes a vector of multivariate polynomials.
static std::vector< std::vector< std::vector< int > > > _polyKeyByVector
static unsigned int NumberOfPolynomialCoefficients(int pointDimension, int order)
void SetCoefficients(int pointDim, MMatrix< double > coeff)
MVector< double > & MakePolyVector(const MVector< double > &point, MVector< double > &polyVector) const
static std::vector< std::vector< std::vector< int > > > _polyKeyByPower
static std::vector< int > IndexByPower(int index, int nInputVariables)
static void PrintContainer(std::ostream &out, const Container &container, char T_separator, char str_separator, int length, bool pad_at_start)
MMatrix< double > GetCoefficientsAsMatrix() const
SquarePolynomialVector Deriv(const int *derivPower) const
void PrintHeader(std::ostream &out, char int_separator='.', char str_separator=' ', int length=14, bool pad_at_start=true) const
void F(const double *point, double *value) const
static std::vector< int > IndexByVector(int index, int nInputVariables)
friend std::ostream & operator<<(std::ostream &, const SquarePolynomialVector &)
static void IndexByPowerRecursive(std::vector< int > check, size_t check_index, size_t poly_power, std::vector< std::vector< int > > &nearby_points)