Using c++ complex functions in Cython - c++

I am trying to do a complex exponential in Cython.
I have been able to cobble together the following code for my pyx:
from libc.math cimport sin, cos, acos, exp, sqrt, fabs, M_PI, floor, ceil
cdef extern from "complex.h":
double complex cexp(double complex z)
import numpy as np
cimport numpy as np
import cython
from cython.parallel cimport prange, parallel
def try_cexp():
cdef:
double complex rr1
double complex rr2
rr1 = 1j
rr2 = 2j
print(rr1*rr2)
#print(cexp(rr1))
Note that the print(cexp(rr1)) is commented. When the line is active, I get the following error when running setup.py:
error: command 'C:\\WinPYthon\\Winpython-64bit-3.4.3.6\\python-3.4.3.amd64\\scripts\\gcc.exe' failed with exit status 1
Note that when cexp is commented out, everything runs expected... I can run setup.py, and when I test the function it prints out the product of the two complex numbers.
Here is my setup.py file. Note that it includes code to run openmp in Cython using g++:
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
import os
os.environ["CC"] = "g++-4.7"
os.environ["CXX"] = "g++-4.7"
# These were added based on some examples I had seen of cexp in Cython. No effect.
#import pyximport
#pyximport.install(reload_support=True)
ext_modules = [
Extension('complex_test',
['complex_test.pyx'],
language="c++",
extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp', '-lm']) # Note that '-lm' was
# added due to an example where someone mentioned g++ required
# this. Same results with and without it.
]
setup(
name='complex_test',
cmdclass={'build_ext': build_ext},
ext_modules=ext_modules,
include_dirs=[np.get_include()]
)
Ultimately my goal is to speed up a calcualtion that looks like k*exp(z), where k and z are complex. Currently I am using Numerical expressions, however that has a large memory overhead, and I believe that it's possible to optimize further than it can.
Thank you for your help.

You're using cexp instead of exp as it is in C++. Change your cdef extern to:
cdef extern from "<complex.h>" namespace "std":
double complex exp(double complex z)
float complex exp(float complex z) # overload
and your print call to:
print(exp(rr1))
and it should work as a charm.
I know the compilation messages are lengthy, but in there you can find the error that points to the culprit:
complex_test.cpp: In function ‘PyObject* __pyx_pf_12complex_test_try_cexp(PyObject*)’:
complex_test.cpp:1270:31: error: cannot convert ‘__pyx_t_double_complex {aka std::complex<double>}’ to ‘__complex__ double’ for argument ‘1’ to ‘__complex__ double cexp(__complex__ double)’
__pyx_t_3 = cexp(__pyx_v_rr1);
It's messy, but you can see the cause. *You're supplying a C++ defined type (__pyx_t_double_complex in Cython Jargon) to a C function which expects a different type (__complex__ double).

Related

Getting derivative by "sympy"

I am trying to get the derivative of a equation.
I found a library named "sympy" can do this, however, I kept getting error while using this.
This is my code:
from sympy import *
x = symbols('x')
diff(cos(x), x)
This is the error:
importing sympy.geometry.util with 'from sympy import *' has been
deprecated since SymPy 1.6. Use import sympy.geometry.util instead.
See https://github.com/sympy/sympy/issues/18245 for more info.
self.Warn(
I try to replace 'from sympy import *' with 'import sympy.geometry.util' but still doesn't work.
This is the error after I replace:
importing sympy.geometry.util with 'from sympy import *' has been
deprecated since SymPy 1.6. Use import sympy.geometry.util instead.
See https://github.com/sympy/sympy/issues/18245 for more info.
self.Warn(
How can I solve this?
I tried to run your code on my compiler. It is working fine.
Try reinstalling 'sympy'

How can I specify a non-theano based likelihood?

I saw a post from a few days ago by someone else: pymc3 likelihood math with non-theano function. Even though I think the problem at its core is the same, I thought I would ask with a simpler example:
Inside logp_wrap, I put some made up definition of a likelihood function. It depends on the rv and an observation. In this case I could do this with theano operations, but let's say that I want this function to be more complex and so I cannot use theano.
The problem comes when I try to define the likelihood both in terms of an RV and observations. From what I have seen, this format would work if I was specifying everything in 'logp_wrap' as theano operations.
I have searched around for a solution to this, but haven't found anything where this problem is fully addressed.
The problem in my attempt to do this is actually that the logp_ function is correctly decorated, but the logp_wrap function is only correctly decorated for its input, and not for its output, so I get the error
TypeError: 'TensorVariable' object is not callable.
Would be great if someone had a solution - don't think I am the only one with this problem.
The theano version of this that works (and uses the same function within a function definition) without the #as_op code is here: https://pymc-devs.github.io/pymc3/notebooks/lda-advi-aevb.html?highlight=densitydist (Specifically the sections: "Log-likelihood of documents for LDA" and "LDA model section")
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
"""
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pymc3 as pm
from theano import as_op
import theano.tensor as T
from scipy.stats import norm
#Some data that we observed
g_observed = [0.0, 1.0, 2.0, 3.0]
#Define a function to calculate the logp without using theano
#This as_op is where the problem is - the input is an rv but the output is a
#function.
#as_op(itypes=[T.dscalar],otypes=[T.dscalar])
def logp_wrap(rv):
#We are not using theano so we wrap the function.
#as_op(itypes=[T.dvector],otypes=[T.dscalar])
def logp_(ob):
#Some made up likelihood -
#The key here is that lp depends on the rv input and the observations
lp = np.log(norm.pdf(rv + ob))
return lp
return logp_
hb1_model = pm.Model()
with hb1_model:
I_mean = pm.Normal('I_mean', mu=0.1, sd=0.05)
xs = pm.DensityDist('x', logp_wrap(I_mean),observed = g_observed)
with hb1_model:
step = pm.Metropolis()
trace = pm.sample(1000, step)

Using cython to speed up thousands of set operations

I have been trying to get over my fear of Cython (fear because I literally know NOTHING about c, or c++)
I have a function which takes 2 arguments, a set (we'll call it testSet), and a list of sets (we'll call that targetSets). The function then iterates through targetSets, and computes the length of the intersection with testSet, adding that value to a list, which is then returned.
Now, this isn't by itself that slow, but the problem is I need to do simulations of the testSet (and a large number at that, ~ 10,000), and the targetSet is about 10,000 sets long.
So for a small number of simulations to test, the pure python implementation was taking ~50 secs.
I tried making a cython function, and it worked and it's now running at ~16 secs.
If there is anything else that I could do to the cython function that anyone could think of that would be great (python 2.7 btw)
Here is my Cython implementation in overlapFunc.pyx
def computeOverlap(set testSet, list targetSets):
cdef list obsOverlaps = []
cdef int i, N
cdef set overlap
N = len(targetSets)
for i in range(N):
overlap = testSet & targetSets[i]
if len(overlap) <= 1:
obsOverlaps.append(0)
else:
obsOverlaps.append(len(overlap))
return obsOverlaps
and the setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("overlapFunc",
["overlapFunc.pyx"])]
setup(
name = 'computeOverlap function',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
and some code to build some random sets for testing and to time the function. test.py
import numpy as np
from overlapFunc import computeOverlap
import time
def simRandomSet(n):
for i in range(n):
simSet= set(np.random.randint(low=1, high=100, size=50))
yield simSet
if __name__ == '__main__':
np.random.seed(23032014)
targetSet = [set(np.random.randint(low=1, high=100, size=50)) for i in range(10000)]
simulatedTestSets = simRandomSet(200)
start = time.time()
for i in simulatedTestSets:
obsOverlaps = computeOverlap(i, targetSet)
print time.time()-start
I tried changing the def at the start of the computerOverlap function, as in:
cdef list computeOverlap(set testSet, list targetSets):
but I get the following warning message when I run the setup.py script:
'__pyx_f_11overlapFunc_computeOverlap' defined but not used [-Wunused-function]
and then when I run something that tries to use the function I get an import Error:
from overlapFunc import computeOverlap
ImportError: cannot import name computeOverlap
Thanks in advance for your help,
Cheers,
Davy
In the following line, the extension module name and the filename does not match actual filename.
ext_modules = [Extension("computeOverlapWithGeneList",
["computeOverlapWithGeneList.pyx"])]
Replace it with:
ext_modules = [Extension("overlapFunc",
["overlapFunc.pyx"])]

cython c++ undefined reference to std::ios_base::failure

I just wrote cython code just as simple as that
# distutils: language = c++
from libcpp.map cimport map,pair
from ios import *
cdef map[int,int] * u = new map[int,int]()
cdef add_item(int n, int x):
cdef pair[int,int]p = pair[int,int](n,x)
u.insert(p)
def add(int n, int x):
add_item(n,x)
added build file like
def make_ext(modname, pyxfilename):
from distutils.extension import Extension
return Extension(name=modname,
sources=[pyxfilename],
language='C++')
and run simple script like
import hello
with lines
import pyximport
pyximport.install()
in my sitecustomize.py
At script execution i get ImportError: Building module hello failed: ['ImportError: /home/odomontois/.pyxbld/lib.linux-x86_64-2.7/hello.so: undefined symbol: _ZTINSt8ios_base7failureE\n']
c++filt _ZTINSt8ios_base7failureE prints typeinfo for std::ios_base::failure
Is there any possibility to find out what object file i should include and how to do this in my pyxbld file for example.
Resolved by adding
libraries=["stdc++"]
to pyxbld

Problems while creating a c++ extension with cython

I'm working on osx 10.8.4 64 bit with python 2.7, cython 0.19.1 and numpy 1.6.1.
I'm trying to create an c++ extension to be used with python. The c++ code is given and I wrote a wrapper c++ class to make using the needed functions in python easier.Compiling works but importing the extension file causes the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dlopen(./mserP.so, 2): Symbol not found: __ZN4mser12MSERDetectorC1Ejj
Referenced from: ./mserP.so
Expected in: flat namespace
in ./mserP.so
I tried a smaller example with an easy c++ class with a function that has got a numpy array as its argument. Importing and using of the extension file works great!
Here the wrapper class (maser_wrapper.cpp):
#include "mser_wrapper.h"
#include "mser.h"
#include <iostream>
namespace mser {
CallMser::CallMser(unsigned int imageSizeX,unsigned int imageSizeY)
{
//Create MSERDetector
mser::MSERDetector* detector = new mser::MSERDetector(imageSizeX, imageSizeY);
}
CallMser::~CallMser()
{
delete detector;
}
}
And here the cython file (mserP.pyx):
# distutils: language = c++
# distutils: sources= mser_wrapper.cpp
cdef extern from "mser_wrapper.h" namespace "mser":
cdef cppclass CallMser:
CallMser(unsigned int, unsigned int) except +
cdef class PyCallMser:
cdef CallMser *thisptr
def __cinit__(self, unsigned int imageSizeX, unsigned int imageSizeY):
self.thisptr = new CallMser(imageSizeX, imageSizeY)
def __dealloc__(self):
del self.thisptr
Last but not least the setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(
"mserP.pyx", # our Cython source
sources=["mser_wrapper.cpp"], # additional source file(s)
language="c++", # generate C++ code
))
In namespace "mser" the class "MSERDetector" exists but cannot be found. It's defined in the header file "mser.h" which is included by my wrapper class.
Has anybody an idea what the problem could be? Thanks!
You are missing the object code from mser.cpp. Tell cython to include it by adding it to the sources in setup.py and distutil sources in the cython file.