Browse Source

Graphs

master
Pete Shadbolt 10 years ago
parent
commit
a864e8ab6d
6 changed files with 31 additions and 45 deletions
  1. +1
    -1
      makefile
  2. +24
    -16
      run-tests.py
  3. +1
    -1
      src/bithacks.h
  4. +3
    -3
      src/npy_util.h
  5. +2
    -2
      src/permanent.c
  6. +0
    -22
      src/permanents.h

+ 1
- 1
makefile View File

@@ -7,7 +7,7 @@ setup = setup.py
default : $(target) test default : $(target) test


# Compile # Compile
$(target): $(srcdir)/permanent.c
$(target): $(srcdir)/*
python $(setup) build_ext --inplace python $(setup) build_ext --inplace


test : test :


+ 24
- 16
run-tests.py View File

@@ -4,6 +4,7 @@ import multiprocessing as mp
import numpy as np import numpy as np
import lib import lib
import time import time
from matplotlib import pyplot as plt


def perm_ryser(a): def perm_ryser(a):
''' the permanent calculated using the ryser formula. much faster than the naive approach ''' ''' the permanent calculated using the ryser formula. much faster than the naive approach '''
@@ -16,23 +17,30 @@ def perm_ryser(a):
terms=map(get_term, indeces) terms=map(get_term, indeces)
return np.sum(terms)*((-1)**n) return np.sum(terms)*((-1)**n)


dimension=9
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
maxtime=1
dimensions=range(1,11)


#print lib.permanent(submatrix), perm_ryser(submatrix)
for (function, label) in zip((lib.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


#sys.exit(0)
#t=time.clock()
#for i in range(1000):
#perm_ryser(submatrix)
#t1=time.clock()-t
t=time.clock()
n=0
while time.clock()-t < maxtime:
for i in range(5):
function(submatrix)
n+=5
counts.append(n)


t=time.clock()
for i in range(1000):
lib.permanent(submatrix)
t2=time.clock()-t
print t2
plt.plot(dimensions, counts, '.-', label=label)


#print t1/t2
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
- 1
src/bithacks.h View File

@@ -8,7 +8,7 @@ int countbits(unsigned int n)
q = (q & 0x0F0F0F0F0F0F0F0F) + ((q & 0xF0F0F0F0F0F0F0F0) >> 4); q = (q & 0x0F0F0F0F0F0F0F0F) + ((q & 0xF0F0F0F0F0F0F0F0) >> 4);
q = (q & 0x00FF00FF00FF00FF) + ((q & 0xFF00FF00FF00FF00) >> 8); q = (q & 0x00FF00FF00FF00FF) + ((q & 0xFF00FF00FF00FF00) >> 8);
q = (q & 0x0000FFFF0000FFFF) + ((q & 0xFFFF0000FFFF0000) >> 16); q = (q & 0x0000FFFF0000FFFF) + ((q & 0xFFFF0000FFFF0000) >> 16);
q = (q & 0x00000000FFFFFFFF) + ((q & 0xFFFFFFFF00000000) >> 32); // This last & isq't strictly qecessary.
q = (q & 0x00000000FFFFFFFF) + ((q & 0xFFFFFFFF00000000) >> 32); // This last & isn't strictly qecessary.
return q; return q;
} }




+ 3
- 3
src/npy_util.h View File

@@ -40,8 +40,8 @@ void complex_inc(npy_complex128 *a, npy_complex128 b) {


// Multipy a number by another one // Multipy a number by another one
void complex_multiply(npy_complex128 *a, npy_complex128 b) { void complex_multiply(npy_complex128 *a, npy_complex128 b) {
npy_complex128 c = {.real=a->real, .imag=a->imag};
a->real = c.real*b.real-c.imag*b.imag;
a->imag = c.real*b.imag+c.imag*b.real;
double c = a->real;
a->real = a->real*b.real-a->imag*b.imag;
a->imag = c*b.imag+a->imag*b.real;
} }



+ 2
- 2
src/permanent.c View File

@@ -4,7 +4,7 @@
#include <numpy/arrayobject.h> #include <numpy/arrayobject.h>
#include "npy_util.h" #include "npy_util.h"
#include "bithacks.h" #include "bithacks.h"
#include "permanents.h"
#include "ryser.h"


// Forward function declaration // Forward function declaration
static PyObject *permanent(PyObject *self, PyObject *args); static PyObject *permanent(PyObject *self, PyObject *args);
@@ -28,6 +28,6 @@ static PyObject *permanent(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;} if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &submatrix)) {return NULL;}


// Compute the permanent // Compute the permanent
npy_complex128 p = perm_ryser(submatrix);
npy_complex128 p = ryser(submatrix);
return PyComplex_FromDoubles(p.real, p.imag); return PyComplex_FromDoubles(p.real, p.imag);
} }

+ 0
- 22
src/permanents.h View File

@@ -1,22 +0,0 @@
// Ryser's algorithm
static npy_complex128 perm_ryser(PyArrayObject *submatrix) {
int n = (int) PyArray_DIM(submatrix, 0);
npy_complex128 rowsum, rowsumprod;
npy_complex128 perm = complex_zero;
int exp = 1 << n;
int i, y, z;
for (i=0; i<exp; ++i) {
rowsumprod = complex_one;
for (y=0; y<n; ++y) {
rowsum = complex_zero;
for (z=0; z<n; ++z) {
if ((i & (1 << z)) != 0) { complex_inc(&rowsum, SM(z, y)); }
}
complex_multiply(&rowsumprod, rowsum);
}
complex_inc(&perm, complex_float_prod(rowsumprod, bitparity(i)));
}
if (n%2 == 1) {perm=complex_float_prod(perm, -1);}
return perm;
}


Loading…
Cancel
Save