18#include <structmember.h>
26#include "Fields/Interpolation/LeastSquaresSolveFactory.h"
37std::string(
"Return the coefficients of the matrix. Takes no arguments\n\n")+
38std::string(
"Return value is a list of lists, with polynomial coefficients\n")+
39std::string(
"for y_i = sum_j a_{ij}*prod_n(x_n^j_n) forming the i, j term\n")+
40std::string(
"in the matrix.\n");
46 PyErr_SetString(PyExc_TypeError,
47 "Failed to resolve self as PolynomialMap");
50 if (py_map->
map == NULL) {
51 PyErr_SetString(PyExc_TypeError,
52 "PolynomialMap not properly initialised");
56 PyObject* py_coefficients = PyList_New(coefficients.
num_row());
58 for (
size_t i = 0; i < coefficients.
num_row(); ++i) {
59 PyObject* py_row = PyList_New(coefficients.
num_col());
60 for (
size_t j = 0; j < coefficients.
num_col(); ++j) {
61 PyObject* py_value = PyFloat_FromDouble(coefficients(i+1, j+1));
63 PyList_SetItem(py_row, j, py_value);
65 PyList_SetItem(py_coefficients, i, py_row);
68 Py_INCREF(py_coefficients);
69 return py_coefficients;
73std::string(
"Maps from the matrix index to the polynomial term.\n\n")+
74std::string(
" - col: index of the matrix column.\n")+
75std::string(
" - dim: dimension of the problem.\n")+
76std::string(
"Return value is a list of ints of length dim. Terms in the\n")+
77std::string(
"transfer matrix in the column given by col correspond to the\n")+
78std::string(
"coefficient of the x_j1^k1 ... x_jn^kn term where kn are the\n")+
79std::string(
"integers returned by this method.\n")+
80std::string(
"For example, PolynomialMap.index_by_power(5, 2) returns\n")+
81std::string(
"[2, 1] meaning the 7th column in a two-dimensional problem\n")+
82std::string(
"represents the coefficients of x_0^2 x_1^1\n");
85PyObject*
index_by_power(PyObject *py_class, PyObject *args, PyObject *kwds) {
86 PyTypeObject* py_map_type =
reinterpret_cast<PyTypeObject*
>(py_class);
88 if (py_map_type == NULL) {
89 PyErr_SetString(PyExc_TypeError,
90 "Failed to resolve self as PolynomialMapType");
96 static char *kwlist[] = {
97 const_cast<char*
>(
"col"),
98 const_cast<char*
>(
"dim"),
101 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"ii", kwlist, &col, &dim)) {
105 PyErr_SetString(PyExc_ValueError,
"col should be >= 0");
109 PyErr_SetString(PyExc_ValueError,
"dim should be > 0");
112 std::vector<int> powers =
114 PyObject* py_powers = PyList_New(powers.size());
115 Py_INCREF(py_powers);
116 for (
size_t i = 0; i < powers.size(); ++i) {
117 PyObject* py_one_power = PyLong_FromSize_t(powers[i]);
118 Py_INCREF(py_one_power);
119 PyList_SetItem(py_powers, i, py_one_power);
125std::string(
"Apply the mapping to a point.\n\n")+
126std::string(
" - point: list of floats with length equal to the point\n")+
127std::string(
" dimension of the mapping, corresponding to the abscissa.\n")+
128std::string(
"Return value is a list of floats, with length equal to the\n")+
129std::string(
"value dimension of the mapping; corresponding to the ordinates\n");
131PyObject*
evaluate(PyObject *self, PyObject *args, PyObject *kwds) {
134 if (py_map == NULL) {
135 PyErr_SetString(PyExc_TypeError,
136 "Failed to resolve self as PolynomialMap");
139 if (py_map->
map == NULL) {
140 PyErr_SetString(PyExc_TypeError,
141 "PolynomialMap not properly initialised");
145 static char *kwlist[] = {
const_cast<char*
>(
"point"), NULL};
146 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O", kwlist, &py_point)) {
150 if (!PyList_Check(py_point)) {
151 PyErr_SetString(PyExc_TypeError,
"point was not a list");
155 PyErr_SetString(PyExc_TypeError,
"point had wrong size");
159 for (
size_t i = 0; i < point.size(); ++i) {
160 PyObject* point_i = PyList_GetItem(py_point, i);
161 point[i] = PyFloat_AsDouble(point_i);
163 if (PyErr_Occurred())
166 py_map->
map->
F(&point[0], &value[0]);
167 PyObject* py_value = PyList_New(value.size());
168 for (
size_t i = 0; i < value.size(); ++i) {
169 PyObject* value_i = PyFloat_FromDouble(value[i]);
170 PyList_SetItem(py_value, i, value_i);
178std::string(
"Find a mapping by solving for the matrix.\n\n")+
179std::string(
" - points: list, each entry containing a list of floats\n")+
180std::string(
" corresponding to abscissa, each with length PointDimension.\n")+
181std::string(
" The list should be as long as the number of coefficients in\n")+
182std::string(
" the polynomial.\n")+
183std::string(
" - values: list, each entry containing a list of floats\n")+
184std::string(
" corresponding to ordinates, each with length ValueDimension.\n")+
185std::string(
" The list should be as long as points.\n")+
186std::string(
" - polynomial_order: integer, >= 0, corresponding to the\n")+
187std::string(
" order of the fitted polynomial; 0 is constant, 1 is linear...\n")+
188std::string(
"Returns a polynomial map.\n");
190std::vector<std::vector<double> >
get_vectors(PyObject* py_floats) {
193 std::vector< std::vector<double> > data;
194 if (!PyList_Check(py_floats)) {
195 return std::vector<std::vector<double> >();
197 size_t num_rows = PyList_Size(py_floats);
199 return std::vector<std::vector<double> >();
203 for (
size_t i = 0; i < num_rows; ++i) {
204 PyObject* row = PyList_GetItem(py_floats, i);
205 if (!PyList_Check(row)) {
206 return std::vector<std::vector<double> >();
210 num_cols = PyList_Size(row);
212 return std::vector<std::vector<double> >();
214 data = std::vector< std::vector<double> >(num_rows, std::vector<double>(num_cols));
217 if (PyList_Size(row) !=
static_cast<int>(num_cols)) {
218 return std::vector<std::vector<double> >();
220 for (
size_t j = 0; j < num_cols; ++j) {
221 PyObject* py_value = PyList_GetItem(row, j);
222 data.at(i).at(j) = PyFloat_AsDouble(py_value);
223 if (PyErr_Occurred() != NULL)
224 return std::vector<std::vector<double> >();
230PyObject*
exact_solve(PyObject *py_class, PyObject *args, PyObject *kwds) {
231 PyTypeObject* py_map_type =
reinterpret_cast<PyTypeObject*
>(py_class);
233 if (py_map_type == NULL) {
234 PyErr_SetString(PyExc_TypeError,
235 "Failed to resolve self as PolynomialMapType");
239 PyObject* py_points = NULL;
240 PyObject* py_values = NULL;
241 int polynomial_order = 0;
242 PyObject* py_error_matrix = Py_None;
243 static char *kwlist[] = {
244 const_cast<char*
>(
"points"),
245 const_cast<char*
>(
"values"),
246 const_cast<char*
>(
"polynomial_order"),
247 const_cast<char*
>(
"error_matrix"),
250 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OOi|O", kwlist, &py_points,
251 &py_values, &polynomial_order, &py_error_matrix)) {
254 if (polynomial_order < 0) {
255 PyErr_SetString(PyExc_ValueError,
"polynomial_order should be >= 0");
258 std::vector<std::vector<double> > points =
get_vectors(py_points);
259 if (points.size() == 0) {
260 PyErr_SetString(PyExc_ValueError,
"Failed to evaluate points");
263 std::vector<std::vector<double> > values =
get_vectors(py_values);
264 if (values.size() == 0) {
265 PyErr_SetString(PyExc_ValueError,
"Failed to evaluate values");
268 if (points.size() != values.size()) {
269 PyErr_SetString(PyExc_ValueError,
"points misaligned with values");
274 std::vector<std::vector<double> > no_derivs;
275 std::vector<std::vector<int> > no_indices;
276 size_t dim = points[0].size();
278 dim, dim, points, no_derivs, no_indices);
279 test_map =
solve.PolynomialSolve(values, no_derivs);
281 PyErr_SetString(PyExc_ValueError, exc.
what().c_str());
284 PyObject* py_map_obj =
_alloc(py_map_type, 0);
286 py_map->
map = test_map;
291std::string(
"Find a mapping by solving for the matrix.\n\n")+
292std::string(
" - points: list, each entry containing a list of floats\n")+
293std::string(
" corresponding to abscissa, each with length PointDimension.\n")+
294std::string(
" The list should be at least as long as the number of \n")+
295std::string(
" coefficients in the polynomial.\n")+
296std::string(
" - values: list, each entry containing a list of floats\n")+
297std::string(
" corresponding to ordinates, each with length ValueDimension.\n")+
298std::string(
" The list should be as long as points.\n")+
299std::string(
" - polynomial_order: integer, >= 0, corresponding to the\n")+
300std::string(
" order of the fitted polynomial; 0 is constant, 1 is linear...\n")+
301std::string(
" - coefficients: list of PolynomialCoefficients. Fix these\n")+
302std::string(
" coefficients to some \n")+
303std::string(
" - weights: list, of length = 0, corresponding to\n")+
304std::string(
"Returns a polynomial map.\n");
307PyObject*
least_squares(PyObject *py_class, PyObject *args, PyObject *kwds) {
308 PyTypeObject* py_map_type =
reinterpret_cast<PyTypeObject*
>(py_class);
310 if (py_map_type == NULL) {
311 PyErr_SetString(PyExc_TypeError,
312 "Failed to resolve self as PolynomialMapType");
316 PyObject* py_points = NULL;
317 PyObject* py_values = NULL;
318 int polynomial_order = 0;
319 PyObject* py_coefficients = NULL;
320 PyObject* py_weights = NULL;
321 static char *kwlist[] = {
322 const_cast<char*
>(
"points"),
323 const_cast<char*
>(
"values"),
324 const_cast<char*
>(
"polynomial_order"),
325 const_cast<char*
>(
"polynomial_coefficients"),
326 const_cast<char*
>(
"weights"),
329 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OOi|OO", kwlist, &py_points,
330 &py_values, &polynomial_order, &py_coefficients, &py_weights)) {
333 if (polynomial_order < 0) {
334 PyErr_SetString(PyExc_ValueError,
"polynomial_order should be >= 0");
337 std::vector<std::vector<double> > points =
get_vectors(py_points);
338 std::vector<std::vector<double> > values =
get_vectors(py_values);
339 std::vector<interpolation::PolynomialCoefficient> coeff;
340 std::vector<double> weights;
342 if (py_weights != NULL) {
343 if (!PyList_Check(py_weights)) {
344 PyErr_SetString(PyExc_TypeError,
345 "Failed to resolve weights as a list");
348 size_t list_size = PyList_Size(py_weights);
349 weights = std::vector<double>(list_size);
350 for (
size_t i = 0; i < list_size; ++i) {
351 PyObject* py_value = PyList_GetItem(py_weights, i);
352 weights[i] = int(PyFloat_AsDouble(py_value));
353 if (PyErr_Occurred() != NULL) {
359 if (py_coefficients != NULL) {
360 if (!PyList_Check(py_coefficients)) {
361 PyErr_SetString(PyExc_TypeError,
362 "Failed to resolve coefficients as a list");
365 size_t list_size = PyList_Size(py_coefficients);
366 for (
size_t i = 0; i < list_size; ++i) {
367 PyObject* py_value = PyList_GetItem(py_coefficients, i);
369 if (py_coeff == NULL) {
370 PyErr_SetString(PyExc_TypeError,
371 "Failed to resolve list item as a PolynomialCoefficient.");
374 coeff.push_back(*(py_coeff->
coeff));
380 interpolation::LeastSquaresSolveFactory solver(polynomial_order, points);
381 solver.setWeights(weights);
382 solver.setCoefficients(coeff);
385 PyErr_SetString(PyExc_ValueError, exc.
what().c_str());
388 PyObject* py_map_obj =
_alloc(py_map_type, 0);
390 py_map->
map = test_map;
396int _init(PyObject* self, PyObject *args, PyObject *kwds) {
399 if (py_map == NULL) {
400 PyErr_SetString(PyExc_TypeError,
401 "Failed to resolve self as PolynomialMap in __init__");
406 if (py_map->
map != NULL) {
412 PyObject* py_coefficients;
413 static char *kwlist[] = {
const_cast<char*
>(
"point_dimension"),
414 const_cast<char*
>(
"coefficients"), NULL};
415 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"iO", kwlist,
416 &point_dim, &py_coefficients)) {
422 if (!PyList_Check(py_coefficients)) {
423 PyErr_SetString(PyExc_TypeError,
424 "Failed to resolve coefficients as a list");
427 size_t num_rows = PyList_Size(py_coefficients);
429 PyErr_SetString(PyExc_ValueError,
"coefficients was empty");
435 for (
size_t i = 0; i < num_rows; ++i) {
436 PyObject* row = PyList_GetItem(py_coefficients, i);
437 if (!PyList_Check(py_coefficients)) {
438 PyErr_SetString(PyExc_TypeError,
439 "Failed to resolve coefficients row as a list");
444 num_cols = PyList_Size(row);
446 PyErr_SetString(PyExc_ValueError,
"coefficients row was empty");
452 if (PyList_Size(row) !=
static_cast<int>(num_cols)) {
453 PyErr_SetString(PyExc_ValueError,
454 "coefficients row had wrong number of elements");
456 for (
size_t j = 0; j < num_cols; ++j) {
457 PyObject* py_value = PyList_GetItem(row, j);
458 coefficients(i+1, j+1) = PyFloat_AsDouble(py_value);
459 if (PyErr_Occurred() != NULL)
467 }
catch (std::exception& exc) {
468 PyErr_SetString(PyExc_RuntimeError, (&exc)->what());
480 return reinterpret_cast<PyObject*
>(map);
483PyObject *
_new(PyTypeObject *
type, Py_ssize_t nitems) {
493 if (self->
map != NULL)
499static PyMemberDef _members[] = {
503static PyMethodDef _methods[] = {
518std::string(
"PolynomialMap provides routines to calculate multivariate \n")+
519std::string(
"polynomials.\n\n")+
520std::string(
"__init__()\n")+
521std::string(
" Takes two arguments.\n")+
522std::string(
" - point_dim: integer which defines the dimension of the\n")+
523std::string(
" points (abscissa)\n")+
524std::string(
" - coefficients: list of lists of floats which define the\n")+
525std::string(
" polynomial\n")+
526std::string(
"The value dimension of the PolynomialMap is the number of rows\n")+
527std::string(
"coefficients matrix\n");
529static PyTypeObject PyPolynomialMapType = {
530 PyObject_HEAD_INIT(NULL)
531 "polynomial_map.PolynomialMap",
549 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
574 "polynomial_map module contains the PolynomialMap class";
576static struct PyModuleDef polynomial_map_def = {
577 PyModuleDef_HEAD_INIT,
590 PySquarePolynomialMap::PyPolynomialMapType.tp_new = PyType_GenericNew;
591 if (PyType_Ready(&PySquarePolynomialMap::PyPolynomialMapType) < 0)
594 PyObject* module = PyModule_Create(&polynomial_map_def);
598 PyTypeObject* polynomial_map_type = &PySquarePolynomialMap::PyPolynomialMapType;
599 Py_INCREF(polynomial_map_type);
600 PyModule_AddObject(module,
"PolynomialMap",
601 reinterpret_cast<PyObject*
>(polynomial_map_type));
std::string get_coefficients_as_matrix_docstring
PyObject * least_squares(PyObject *py_class, PyObject *args, PyObject *kwds)
PyObject * index_by_power(PyObject *py_class, PyObject *args, PyObject *kwds)
PyObject * exact_solve(PyObject *py_class, PyObject *args, PyObject *kwds)
std::vector< std::vector< double > > get_vectors(PyObject *py_floats)
std::string least_squares_docstring
PyObject * _alloc(PyTypeObject *type, Py_ssize_t nitems)
std::string evaluate_docstring
std::string exact_solve_docstring
void _dealloc(PyPolynomialMap *self)
void _free(PyPolynomialMap *self)
std::string class_docstring
int _init(PyObject *self, PyObject *args, PyObject *kwds)
PyObject * _new(PyTypeObject *type, Py_ssize_t nitems)
std::string index_by_power_docstring
PyObject * get_coefficients_as_matrix(PyObject *self, PyObject *args, PyObject *kwds)
PyObject * evaluate(PyObject *self, PyObject *args, PyObject *kwds)
void solve(double *Matrix, double *Solution, double *rightHandSide, const int &M, const int &N)
boost::function< boost::tuple< double, bool >(arguments_t)> type
interpolation::PolynomialCoefficient * coeff
interpolation::SquarePolynomialVector * map
size_t num_col() const
returns number of columns in the matrix
size_t num_row() const
returns number of rows in the matrix
SolveFactory is a factory class for solving a set of linear equations to generate a polynomial based ...
SquarePolynomialVector describes a vector of multivariate polynomials.
unsigned int PointDimension() const
static std::vector< int > IndexByPower(int index, int nInputVariables)
unsigned int ValueDimension() const
MMatrix< double > GetCoefficientsAsMatrix() const
void F(const double *point, double *value) const
virtual const std::string & what() const
Return the message string for the exception.
PyMODINIT_FUNC PyInit_polynomial_map(void)
const char * module_docstring