OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
PySquarePolynomialMap.cpp
Go to the documentation of this file.
1 //
2 // Python API for PolynomialCoefficient (part of the multidimensional polynomial fitting routines)
3 //
4 // Copyright (c) 2008-2023, Chris Rogers, STFC Rutherford Appleton Laboratory, Didcot, UK
5 //
6 // This file is part of OPAL.
7 //
8 // OPAL is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
15 //
16 
17 #include <Python.h>
18 #include <structmember.h>
19 
20 #include <vector>
21 #include <string>
22 
26 #include "Fields/Interpolation/LeastSquaresSolveFactory.h"
27 
28 #include "PyOpal/Globals.h"
29 #include "PyOpal/PySquarePolynomialMap.h"
30 #include "PyOpal/PyPolynomialCoefficient.h"
31 
32 namespace PySquarePolynomialMap {
33 
35 
37 std::string("Return the coefficients of the matrix. Takes no arguments\n\n")+
38 std::string("Return value is a list of lists, with polynomial coefficients\n")+
39 std::string("for y_i = sum_j a_{ij}*prod_n(x_n^j_n) forming the i, j term\n")+
40 std::string("in the matrix.\n");
41 
42 PyObject* get_coefficients_as_matrix(PyObject *self, PyObject *args, PyObject *kwds) {
43  PyPolynomialMap* py_map = reinterpret_cast<PyPolynomialMap*>(self);
44  // failed to cast or self was not initialised - something horrible happened
45  if (py_map == nullptr) {
46  PyErr_SetString(PyExc_TypeError,
47  "Failed to resolve self as PolynomialMap");
48  return nullptr;
49  }
50  if (py_map->map == nullptr) {
51  PyErr_SetString(PyExc_TypeError,
52  "PolynomialMap not properly initialised");
53  return nullptr;
54  }
56  PyObject* py_coefficients = PyList_New(coefficients.num_row());
57  // not safe from out of memory errors (etc)
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));
62  Py_INCREF(py_value);
63  PyList_SetItem(py_row, j, py_value);
64  }
65  PyList_SetItem(py_coefficients, i, py_row);
66  Py_INCREF(py_row);
67  }
68  Py_INCREF(py_coefficients);
69  return py_coefficients;
70 }
71 
73 std::string("Maps from the matrix index to the polynomial term.\n\n")+
74 std::string(" - col: index of the matrix column.\n")+
75 std::string(" - dim: dimension of the problem.\n")+
76 std::string("Return value is a list of ints of length dim. Terms in the\n")+
77 std::string("transfer matrix in the column given by col correspond to the\n")+
78 std::string("coefficient of the x_j1^k1 ... x_jn^kn term where kn are the\n")+
79 std::string("integers returned by this method.\n")+
80 std::string("For example, PolynomialMap.index_by_power(5, 2) returns\n")+
81 std::string("[2, 1] meaning the 7th column in a two-dimensional problem\n")+
82 std::string("represents the coefficients of x_0^2 x_1^1\n");
83 
84 
85 PyObject* index_by_power(PyObject *py_class, PyObject *args, PyObject *kwds) {
86  PyTypeObject* py_map_type = reinterpret_cast<PyTypeObject*>(py_class);
87  // failed to cast or self was not initialised - something horrible happened
88  if (py_map_type == nullptr) {
89  PyErr_SetString(PyExc_TypeError,
90  "Failed to resolve self as PolynomialMapType");
91  return nullptr;
92  }
93 
94  int col = 0;
95  int dim = 0;
96  static char *kwlist[] = {
97  const_cast<char*>("col"),
98  const_cast<char*>("dim"),
99  nullptr
100  };
101  if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &col, &dim)) {
102  return nullptr;
103  }
104  if (col < 0) {
105  PyErr_SetString(PyExc_ValueError, "col should be >= 0");
106  return nullptr;
107  }
108  if (dim <= 0) {
109  PyErr_SetString(PyExc_ValueError, "dim should be > 0");
110  return nullptr;
111  }
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);
120  }
121  return py_powers;
122 }
123 
124 std::string evaluate_docstring =
125 std::string("Apply the mapping to a point.\n\n")+
126 std::string(" - point: list of floats with length equal to the point\n")+
127 std::string(" dimension of the mapping, corresponding to the abscissa.\n")+
128 std::string("Return value is a list of floats, with length equal to the\n")+
129 std::string("value dimension of the mapping; corresponding to the ordinates\n");
130 
131 PyObject* evaluate(PyObject *self, PyObject *args, PyObject *kwds) {
132  PyPolynomialMap* py_map = reinterpret_cast<PyPolynomialMap*>(self);
133  // failed to cast or self was not initialised - something horrible happened
134  if (py_map == nullptr) {
135  PyErr_SetString(PyExc_TypeError,
136  "Failed to resolve self as PolynomialMap");
137  return nullptr;
138  }
139  if (py_map->map == nullptr) {
140  PyErr_SetString(PyExc_TypeError,
141  "PolynomialMap not properly initialised");
142  return nullptr;
143  }
144  PyObject* py_point;
145  static char *kwlist[] = {const_cast<char*>("point"), nullptr};
146  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &py_point)) {
147  return nullptr;
148  }
149 
150  if (!PyList_Check(py_point)) {
151  PyErr_SetString(PyExc_TypeError, "point was not a list");
152  return nullptr;
153  }
154  if (PyList_Size(py_point) != py_map->map->PointDimension()) {
155  PyErr_SetString(PyExc_TypeError, "point had wrong size");
156  return nullptr;
157  }
158  std::vector<double> point(py_map->map->PointDimension());
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);
162  }
163  if (PyErr_Occurred()) // probably not a double in the list
164  return nullptr;
165  std::vector<double> value(py_map->map->ValueDimension());
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);
171  Py_INCREF(value_i);
172  }
173  Py_INCREF(py_value);
174  return py_value;
175 }
176 
178 std::string("Find a mapping by solving for the matrix.\n\n")+
179 std::string(" - points: list, each entry containing a list of floats\n")+
180 std::string(" corresponding to abscissa, each with length PointDimension.\n")+
181 std::string(" The list should be as long as the number of coefficients in\n")+
182 std::string(" the polynomial.\n")+
183 std::string(" - values: list, each entry containing a list of floats\n")+
184 std::string(" corresponding to ordinates, each with length ValueDimension.\n")+
185 std::string(" The list should be as long as points.\n")+
186 std::string(" - polynomial_order: integer, >= 0, corresponding to the\n")+
187 std::string(" order of the fitted polynomial; 0 is constant, 1 is linear...\n")+
188 std::string("Returns a polynomial map.\n");
189 
190 std::vector<std::vector<double> > get_vectors(PyObject* py_floats) {
191  // convert from list of list of floats to std::vector< std::vector<double> >
192  // first check validity of coefficients
193  std::vector< std::vector<double> > data;
194  if (!PyList_Check(py_floats)) {
195  return std::vector<std::vector<double> >();
196  }
197  size_t num_rows = PyList_Size(py_floats);
198  if (num_rows == 0) {
199  return std::vector<std::vector<double> >();
200  }
201  size_t num_cols = 0;
202  // now loop over the rows
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> >();
207  }
208  // do some initialisation in the first row
209  if (i == 0) {
210  num_cols = PyList_Size(row);
211  if (num_cols == 0) {
212  return std::vector<std::vector<double> >();
213  }
214  data = std::vector< std::vector<double> >(num_rows, std::vector<double>(num_cols));
215  }
216  // now loop over columns
217  if (PyList_Size(row) != static_cast<int>(num_cols)) {
218  return std::vector<std::vector<double> >();
219  }
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() != nullptr) // not a float
224  return std::vector<std::vector<double> >();
225  }
226  }
227  return data;
228 }
229 
230 PyObject* exact_solve(PyObject *py_class, PyObject *args, PyObject *kwds) {
231  PyTypeObject* py_map_type = reinterpret_cast<PyTypeObject*>(py_class);
232  // failed to cast or self was not initialised - something horrible happened
233  if (py_map_type == nullptr) {
234  PyErr_SetString(PyExc_TypeError,
235  "Failed to resolve self as PolynomialMapType");
236  return nullptr;
237  }
238 
239  PyObject* py_points = nullptr;
240  PyObject* py_values = nullptr;
241  int polynomial_order = 0;
242  PyObject* py_error_matrix = Py_None; // borrowed reference
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"),
248  nullptr
249  };
250  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOi|O", kwlist, &py_points,
251  &py_values, &polynomial_order, &py_error_matrix)) {
252  return nullptr;
253  }
254  if (polynomial_order < 0) {
255  PyErr_SetString(PyExc_ValueError, "polynomial_order should be >= 0");
256  return nullptr;
257  }
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");
261  return nullptr;
262  }
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");
266  return nullptr;
267  }
268  if (points.size() != values.size()) {
269  PyErr_SetString(PyExc_ValueError, "points misaligned with values");
270  return nullptr;
271  }
272  interpolation::SquarePolynomialVector* test_map = nullptr;
273  try {
274  std::vector<std::vector<double> > no_derivs;
275  std::vector<std::vector<int> > no_indices;
276  size_t dim = points[0].size();
277  interpolation::SolveFactory solve(polynomial_order, polynomial_order,
278  dim, dim, points, no_derivs, no_indices);
279  test_map = solve.PolynomialSolve(values, no_derivs);
280  } catch (GeneralClassicException& exc) {
281  PyErr_SetString(PyExc_ValueError, exc.what().c_str());
282  return nullptr;
283  }
284  PyObject* py_map_obj = _alloc(py_map_type, 0);
285  PyPolynomialMap* py_map = reinterpret_cast<PyPolynomialMap*>(py_map_obj);
286  py_map->map = test_map;
287  return py_map_obj;
288 }
289 
291 std::string("Find a mapping by solving for the matrix.\n\n")+
292 std::string(" - points: list, each entry containing a list of floats\n")+
293 std::string(" corresponding to abscissa, each with length PointDimension.\n")+
294 std::string(" The list should be at least as long as the number of \n")+
295 std::string(" coefficients in the polynomial.\n")+
296 std::string(" - values: list, each entry containing a list of floats\n")+
297 std::string(" corresponding to ordinates, each with length ValueDimension.\n")+
298 std::string(" The list should be as long as points.\n")+
299 std::string(" - polynomial_order: integer, >= 0, corresponding to the\n")+
300 std::string(" order of the fitted polynomial; 0 is constant, 1 is linear...\n")+
301 std::string(" - coefficients: list of PolynomialCoefficients. Fix these\n")+
302 std::string(" coefficients to some \n")+
303 std::string(" - weights: list, of length = 0, corresponding to\n")+
304 std::string("Returns a polynomial map.\n");
305 
306 
307 PyObject* least_squares(PyObject *py_class, PyObject *args, PyObject *kwds) {
308  PyTypeObject* py_map_type = reinterpret_cast<PyTypeObject*>(py_class);
309  // failed to cast or self was not initialised - something horrible happened
310  if (py_map_type == nullptr) {
311  PyErr_SetString(PyExc_TypeError,
312  "Failed to resolve self as PolynomialMapType");
313  return nullptr;
314  }
315 
316  PyObject* py_points = nullptr;
317  PyObject* py_values = nullptr;
318  int polynomial_order = 0;
319  PyObject* py_coefficients = nullptr;
320  PyObject* py_weights = nullptr;
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"),
327  nullptr
328  };
329  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &py_points,
330  &py_values, &polynomial_order, &py_coefficients, &py_weights)) {
331  return nullptr;
332  }
333  if (polynomial_order < 0) {
334  PyErr_SetString(PyExc_ValueError, "polynomial_order should be >= 0");
335  return nullptr;
336  }
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;
341  // weights
342  if (py_weights != nullptr) {
343  if (!PyList_Check(py_weights)) {
344  PyErr_SetString(PyExc_TypeError,
345  "Failed to resolve weights as a list");
346  return nullptr;
347  }
348  size_t list_size = PyList_Size(py_weights); // nb: size 0 is legal
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() != nullptr) { // not an int
354  return nullptr;
355  }
356  }
357  }
358  // coefficients
359  if (py_coefficients != nullptr) {
360  if (!PyList_Check(py_coefficients)) {
361  PyErr_SetString(PyExc_TypeError,
362  "Failed to resolve coefficients as a list");
363  return nullptr;
364  }
365  size_t list_size = PyList_Size(py_coefficients); // nb: size 0 is legal
366  for (size_t i = 0; i < list_size; ++i) {
367  PyObject* py_value = PyList_GetItem(py_coefficients, i);
368  PyCoefficient* py_coeff = reinterpret_cast<PyCoefficient*>(py_value);
369  if (py_coeff == nullptr) {
370  PyErr_SetString(PyExc_TypeError,
371  "Failed to resolve list item as a PolynomialCoefficient.");
372  return nullptr;
373  }
374  coeff.push_back(*(py_coeff->coeff));
375  }
376 
377  }
378  interpolation::SquarePolynomialVector* test_map = nullptr;
379  try {
380  interpolation::LeastSquaresSolveFactory solver(polynomial_order, points);
381  solver.setWeights(weights);
382  solver.setCoefficients(coeff);
383  test_map = new interpolation::SquarePolynomialVector(solver.solve(values));
384  } catch (GeneralClassicException& exc) {
385  PyErr_SetString(PyExc_ValueError, exc.what().c_str());
386  return nullptr;
387  }
388  PyObject* py_map_obj = _alloc(py_map_type, 0);
389  PyPolynomialMap* py_map = reinterpret_cast<PyPolynomialMap*>(py_map_obj);
390  py_map->map = test_map;
391  return py_map_obj;
392 }
393 
394 
395 
396 int _init(PyObject* self, PyObject *args, PyObject *kwds) {
397  PyPolynomialMap* py_map = reinterpret_cast<PyPolynomialMap*>(self);
398  // failed to cast or self was not initialised - something horrible happened
399  if (py_map == nullptr) {
400  PyErr_SetString(PyExc_TypeError,
401  "Failed to resolve self as PolynomialMap in __init__");
402  return -1;
403  }
404  // legal python to call initialised_object.__init__() to reinitialise, so
405  // handle this case
406  if (py_map->map != nullptr) {
407  delete py_map->map;
408  py_map->map = nullptr;
409  }
410  // read in arguments
411  int point_dim;
412  PyObject* py_coefficients;
413  static char *kwlist[] = {const_cast<char*>("point_dimension"),
414  const_cast<char*>("coefficients"), nullptr};
415  if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwlist,
416  &point_dim, &py_coefficients)) {
417  return -1;
418  }
419 
420  // convert from list of list of floats to Matrix<double>
421  // first check validity of coefficients
422  if (!PyList_Check(py_coefficients)) {
423  PyErr_SetString(PyExc_TypeError,
424  "Failed to resolve coefficients as a list");
425  return -1;
426  }
427  size_t num_rows = PyList_Size(py_coefficients);
428  if (num_rows == 0) {
429  PyErr_SetString(PyExc_ValueError, "coefficients was empty");
430  return -1;
431  }
432  size_t num_cols = 0;
433  interpolation::MMatrix<double> coefficients;
434  // now loop over the rows
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");
440  return -1;
441  }
442  // do some initialisation in the first row
443  if (i == 0) {
444  num_cols = PyList_Size(row);
445  if (num_cols == 0) {
446  PyErr_SetString(PyExc_ValueError, "coefficients row was empty");
447  return -1;
448  }
449  coefficients = interpolation::MMatrix<double>(num_rows, num_cols);
450  }
451  // now loop over columns
452  if (PyList_Size(row) != static_cast<int>(num_cols)) {
453  PyErr_SetString(PyExc_ValueError,
454  "coefficients row had wrong number of elements");
455  }
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() != nullptr) // not a float
460  return -1;
461  }
462  }
463 
464  // now initialise the internal map
465  try {
466  py_map->map = new interpolation::SquarePolynomialVector(point_dim, coefficients);
467  } catch (std::exception& exc) {
468  PyErr_SetString(PyExc_RuntimeError, (&exc)->what());
469  return -1;
470  }
471  return 0;
472 }
473 
474 PyObject *_alloc(PyTypeObject *type, Py_ssize_t nitems) {
475  void* void_map = malloc(sizeof(PyPolynomialMap));
476  PyPolynomialMap* map = reinterpret_cast<PyPolynomialMap*>(void_map);
477  map->map = nullptr;
478  Py_REFCNT(map) = 1;
479  Py_TYPE(map) = type;
480  return reinterpret_cast<PyObject*>(map);
481 }
482 
483 PyObject *_new(PyTypeObject *type, Py_ssize_t nitems) {
484  return _alloc(type, nitems);
485 }
486 
487 void _dealloc(PyPolynomialMap * self) {
488  _free(self);
489 }
490 
491 void _free(PyPolynomialMap * self) {
492  if (self != nullptr) {
493  if (self->map != nullptr)
494  delete self->map;
495  free(self);
496  }
497 }
498 
499 static PyMemberDef _members[] = {
500 {nullptr}
501 };
502 
503 static PyMethodDef _methods[] = {
504 {"get_coefficients_as_matrix", (PyCFunction)get_coefficients_as_matrix,
505  METH_VARARGS|METH_KEYWORDS, get_coefficients_as_matrix_docstring.c_str()},
506 {"evaluate", (PyCFunction)evaluate,
507  METH_VARARGS|METH_KEYWORDS, evaluate_docstring.c_str()},
508 {"exact_solve", (PyCFunction)exact_solve,
509  METH_CLASS|METH_VARARGS|METH_KEYWORDS, exact_solve_docstring.c_str()},
510 {"least_squares", (PyCFunction)least_squares,
511  METH_CLASS|METH_VARARGS|METH_KEYWORDS, least_squares_docstring.c_str()},
512 {"index_by_power", (PyCFunction)index_by_power,
513  METH_CLASS|METH_VARARGS|METH_KEYWORDS, index_by_power_docstring.c_str()},
514 {nullptr}
515 };
516 
517 std::string class_docstring =
518 std::string("PolynomialMap provides routines to calculate multivariate \n")+
519 std::string("polynomials.\n\n")+
520 std::string("__init__()\n")+
521 std::string(" Takes two arguments.\n")+
522 std::string(" - point_dim: integer which defines the dimension of the\n")+
523 std::string(" points (abscissa)\n")+
524 std::string(" - coefficients: list of lists of floats which define the\n")+
525 std::string(" polynomial\n")+
526 std::string("The value dimension of the PolynomialMap is the number of rows\n")+
527 std::string("coefficients matrix\n");
528 
529 static PyTypeObject PyPolynomialMapType = {
530  PyObject_HEAD_INIT(nullptr)
531  "polynomial_map.PolynomialMap", /*tp_name*/
532  sizeof(PyPolynomialMap), /*tp_basicsize*/
533  0, /*tp_itemsize*/
534  (destructor)_dealloc, /*tp_dealloc*/
535  0, /*tp_print*/
536  0, /*tp_getattr*/
537  0, /*tp_setattr*/
538  0, /*tp_compare*/
539  0, /*tp_repr*/
540  0, /*tp_as_number*/
541  0, /*tp_as_sequence*/
542  0, /*tp_as_mapping*/
543  0, /*tp_hash */
544  0, /*tp_call*/
545  0, /*tp_str*/
546  0, /*tp_getattro*/
547  0, /*tp_setattro*/
548  0, /*tp_as_buffer*/
549  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
550  class_docstring.c_str(), /* tp_doc */
551  0, /* tp_traverse */
552  0, /* tp_clear */
553  0, /* tp_richcompare */
554  0, /* tp_weaklistoffset */
555  0, /* tp_iter */
556  0, /* tp_iternext */
557  _methods, /* tp_methods */
558  _members, /* tp_members */
559  0, /* tp_getset */
560  0, /* tp_base */
561  0, /* tp_dict */
562  0, /* tp_descr_get */
563  0, /* tp_descr_set */
564  0, /* tp_dictoffset */
565  (initproc)_init, /* tp_init */
566  (allocfunc)_alloc, /* tp_alloc, called by new */
567  0, // (newfunc)_new, /* tp_new */
568  (freefunc)_free, /* tp_free, called by dealloc */
569 };
570 
571 } // namespace PyPolynomialMap
572 
573 const char* module_docstring =
574  "polynomial_map module contains the PolynomialMap class";
575 
576 static struct PyModuleDef polynomial_map_def = {
577  PyModuleDef_HEAD_INIT,
578  "polynomial_map", /* m_name */
579  module_docstring, /* m_doc */
580  -1, /* m_size */
581  nullptr, /* m_methods */
582  nullptr, /* m_reload */
583  nullptr, /* m_traverse */
584  nullptr, /* m_clear */
585  nullptr, /* m_free */
586 };
587 
588 PyMODINIT_FUNC PyInit_polynomial_map(void) {
590  PySquarePolynomialMap::PyPolynomialMapType.tp_new = PyType_GenericNew;
591  if (PyType_Ready(&PySquarePolynomialMap::PyPolynomialMapType) < 0)
592  return nullptr;
593 
594  PyObject* module = PyModule_Create(&polynomial_map_def);
595  if (module == nullptr)
596  return nullptr;
597 
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));
602 
603  return module;
604 }
605 
606 
PyObject * index_by_power(PyObject *py_class, PyObject *args, PyObject *kwds)
void solve(double *Matrix, double *Solution, double *rightHandSide, const int &M, const int &N)
void Initialise()
Definition: Globals.cpp:50
interpolation::SquarePolynomialVector * map
MMatrix< double > GetCoefficientsAsMatrix() const
virtual const std::string & what() const
Return the message string for the exception.
PyObject * exact_solve(PyObject *py_class, PyObject *args, PyObject *kwds)
void _dealloc(PyPolynomialMap *self)
int _init(PyObject *self, PyObject *args, PyObject *kwds)
PyObject * _alloc(PyTypeObject *type, Py_ssize_t nitems)
SolveFactory is a factory class for solving a set of linear equations to generate a polynomial based ...
Definition: SolveFactory.h:44
PyObject * get_coefficients_as_matrix(PyObject *self, PyObject *args, PyObject *kwds)
PyObject * _new(PyTypeObject *type, Py_ssize_t nitems)
PyMODINIT_FUNC PyInit_polynomial_map(void)
interpolation::PolynomialCoefficient * coeff
std::vector< std::vector< double > > get_vectors(PyObject *py_floats)
SquarePolynomialVector describes a vector of multivariate polynomials.
PyObject * evaluate(PyObject *self, PyObject *args, PyObject *kwds)
std::string get_coefficients_as_matrix_docstring
size_t num_row() const
returns number of rows in the matrix
void F(const double *point, double *value) const
size_t num_col() const
returns number of columns in the matrix
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special exception
Definition: LICENSE:157
static std::vector< int > IndexByPower(int index, int nInputVariables)
void _free(PyPolynomialMap *self)
SquarePolynomialVector * PolynomialSolve(const std::vector< std::vector< double > > &values, const std::vector< std::vector< double > > &deriv_values)
SDDS1 &description type
Definition: test.stat:4
PyObject * least_squares(PyObject *py_class, PyObject *args, PyObject *kwds)