Python C extension to compute the permanent.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

permanent.c 1.9KB

10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /* Functions to compute 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 "npy_util.h"
  6. #include "bithacks.h"
  7. // Forward function declaration
  8. static PyObject *permanent(PyObject *self, PyObject *args);
  9. // Method list
  10. static PyMethodDef methods[] = {
  11. { "permanent", permanent, METH_VARARGS, "Computes the permanent of a numpy using the most appropriate method available"},
  12. { NULL, NULL, 0, NULL } // Sentinel
  13. };
  14. // Module initialization
  15. PyMODINIT_FUNC initpermanent(void) {
  16. (void) Py_InitModule("permanent", methods);
  17. import_array();
  18. }
  19. // Ryser's algorithm
  20. static npy_complex128 ryser(PyArrayObject *submatrix) {
  21. int n = (int) PyArray_DIM(submatrix, 0);
  22. npy_complex128 rowsum, rowsumprod;
  23. npy_complex128 perm = complex_zero;
  24. int exp = 1 << n;
  25. int i, y, z;
  26. for (i=0; i<exp; ++i) {
  27. rowsumprod = complex_one;
  28. for (y=0; y<n; ++y) {
  29. rowsum = complex_zero;
  30. for (z=0; z<n; ++z) {
  31. if ((i & (1 << z)) != 0) { complex_inc(&rowsum, SM(z, y)); }
  32. }
  33. complex_multiply(&rowsumprod, rowsum);
  34. }
  35. complex_inc(&perm, complex_float_prod(rowsumprod, bitparity(i)));
  36. }
  37. if (n%2 == 1) { perm=complex_float_prod(perm, -1); }
  38. return perm;
  39. }
  40. // This is a wrapper which chooses the optimal permanent function
  41. static PyObject *permanent(PyObject *self, PyObject *args) {
  42. // Parse the input
  43. PyArrayObject *submatrix;
  44. if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;}
  45. if (!PyArray_ISCOMPLEX(submatrix)) {
  46. PyErr_SetString(PyExc_TypeError, "Array dtype must be `complex`.");
  47. return NULL;
  48. }
  49. // Compute the permanent
  50. npy_complex128 p = ryser(submatrix);
  51. return PyComplex_FromDoubles(p.real, p.imag);
  52. }