Python C extension to compute the permanent.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

50 lignes
1.6KB

  1. /* Computes the permanent, given a numpy array */
  2. #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
  3. #include <Python.h>
  4. #include <numpy/arrayobject.h>
  5. #include <math.h>
  6. #include <complex.h>
  7. // Array access macros.
  8. #define SM(x0, x1) (*(npy_complex128*)((PyArray_DATA(submatrix) + \
  9. (x0) * PyArray_STRIDES(submatrix)[0] + \
  10. (x1) * PyArray_STRIDES(submatrix)[1])))
  11. #define SM_shape(x0) (int) PyArray_DIM(submatrix, x0)
  12. #define complex_inc(x0, x1) x0.real+=x1.real; x0.imag+=x1.imag;
  13. // Boilerplate: Forward function declaration, method list, module initialization
  14. static PyObject *permanent(PyObject *self, PyObject *args);
  15. static PyMethodDef methods[] = {
  16. { "permanent", permanent, METH_VARARGS, "Compute the permanent"},
  17. { NULL, NULL, 0, NULL } /* Sentinel */
  18. };
  19. PyMODINIT_FUNC initpermanent(void) {
  20. (void) Py_InitModule("permanent", methods);
  21. import_array();
  22. }
  23. // Ryser's algorithm takes exponential time
  24. // This just calculates the sum
  25. static npy_complex128 perm_ryser(PyArrayObject *submatrix) {
  26. npy_complex128 p = {.real=0, .imag=0};
  27. int size = (int) PyArray_DIM(submatrix, 0);
  28. int i, j;
  29. for (i = 0; i < size; ++i) {
  30. for (j = 0; j < size; ++j) {
  31. complex_inc(p, SM(0,0));
  32. }
  33. }
  34. return p;
  35. }
  36. // This is basically a wrapper which chooses the optimal permanent function
  37. static PyObject *permanent(PyObject *self, PyObject *args) {
  38. // Parse input
  39. PyArrayObject *submatrix;
  40. if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;}
  41. npy_complex128 p = perm_ryser(submatrix);
  42. return PyComplex_FromDoubles(p.real, p.imag);
  43. }