| @@ -1,42 +0,0 @@ | |||||
| import os, sys | |||||
| import numpy as np | |||||
| import time | |||||
| from matplotlib import pyplot as plt | |||||
| from permanent import permanent | |||||
| import itertools as it | |||||
| def permanent(a): | |||||
| """ Slow way to compute the permanent """ | |||||
| r = range(len(a)) | |||||
| return sum([np.prod(a[r, p]) for p in it.permutations(r)]) | |||||
| if __name__ == '__main__': | |||||
| maxtime=1 | |||||
| dimensions=range(1,11) | |||||
| for (function, label) in zip((permanent, perm_ryser), ("C", "Python")): | |||||
| counts=[] | |||||
| for dimension in dimensions: | |||||
| print dimension | |||||
| real=np.random.uniform(-1, 1, dimension*dimension).reshape((dimension, dimension)) | |||||
| imag=np.random.uniform(-1, 1, dimension*dimension).reshape((dimension, dimension)) | |||||
| submatrix=real+1j*imag | |||||
| t=time.clock() | |||||
| n=0 | |||||
| while time.clock()-t < maxtime: | |||||
| for i in range(5): | |||||
| function(submatrix) | |||||
| n+=5 | |||||
| counts.append(n) | |||||
| plt.plot(dimensions, counts, ".-", label=label) | |||||
| plt.ylabel("Number of permanents per second") | |||||
| plt.xlabel("Dimension") | |||||
| plt.xlim(min(dimensions), max(dimensions)) | |||||
| plt.legend() | |||||
| plt.semilogy() | |||||
| plt.savefig("out.pdf") | |||||
| @@ -1,5 +0,0 @@ | |||||
| #!/bin/bash | |||||
| rm permanent/*.so | |||||
| python ./setup.py build_ext --inplace && | |||||
| python ./run-tests.py | |||||
| @@ -48,6 +48,10 @@ static PyObject *permanent(PyObject *self, PyObject *args) { | |||||
| // Parse the input | // Parse the input | ||||
| PyArrayObject *submatrix; | PyArrayObject *submatrix; | ||||
| if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;} | if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;} | ||||
| if (!PyArray_ISCOMPLEX(submatrix)) { | |||||
| PyErr_SetString(PyExc_TypeError, "Array dtype must be `complex`."); | |||||
| return NULL; | |||||
| } | |||||
| // Compute the permanent | // Compute the permanent | ||||
| npy_complex128 p = ryser(submatrix); | npy_complex128 p = ryser(submatrix); | ||||
| @@ -0,0 +1,27 @@ | |||||
| import numpy as np | |||||
| from permanent import permanent | |||||
| from nose.tools import raises | |||||
| def test_permanent(): | |||||
| """ Dumb tests """ | |||||
| m = np.eye(10, dtype=complex) | |||||
| assert permanent(m) == 1 | |||||
| m = np.zeros((10, 10), dtype=complex) | |||||
| assert permanent(m) == 0 | |||||
| def test_floaty(): | |||||
| """ More tests using a precomputed permanent """ | |||||
| np.random.seed(1234) | |||||
| m = np.random.uniform(0, 1, 16) + 1j*np.random.uniform(0, 1, 16) | |||||
| m = m.reshape(4,4) | |||||
| p = permanent(m) | |||||
| assert np.allclose(p, -8.766131870776363+1.072095650303524j) | |||||
| @raises(TypeError) | |||||
| def test_error(): | |||||
| """ Should raise a TypeError as we are using the wrong dtype """ | |||||
| m = np.eye(10, dtype=float) | |||||
| permanent(m) | |||||