-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
SciPy LowLevelCallable from Lambdify #201
Conversation
A simple example, In [1]: import symengine as se
...: import numpy as np
...: from scipy import integrate
...: args = t, x = se.symbols("t, x")
...:
...: lmb = se.lambdify(args, [se.exp(-x*t)/t**5], as_scipy=True)
...: lmb2 = se.lambdify(args, [se.exp(-x*t)/t**5], as_scipy=False)
...:
In [2]: %timeit integrate.nquad(lmb, [[1, np.inf],[0, np.inf]])
1.39 ms ± 1.87 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [3]: %timeit integrate.nquad(lmb2, [[1, np.inf],[0, np.inf]])
51.5 ms ± 425 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) cc @bjodah |
symengine/lib/symengine_wrapper.pyx
Outdated
@@ -4579,6 +4604,16 @@ cdef class LambdaDouble(_Lambdify): | |||
cpdef unsafe_complex(self, double complex[::1] inp, double complex[::1] out, int inp_offset=0, int out_offset=0): | |||
self.lambda_double_complex[0].call(&out[out_offset], &inp[inp_offset]) | |||
|
|||
cpdef as_scipy_low_level_callable(self): | |||
from scipy import LowLevelCallable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the import of LowLevelCallable needed here?
symengine/lib/symengine_wrapper.pyx
Outdated
@@ -4592,8 +4627,18 @@ IF HAVE_SYMENGINE_LLVM: | |||
cpdef unsafe_real(self, double[::1] inp, double[::1] out, int inp_offset=0, int out_offset=0): | |||
self.lambda_double[0].call(&out[out_offset], &inp[inp_offset]) | |||
|
|||
cpdef as_scipy_low_level_callable(self): | |||
from scipy import LowLevelCallable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
This is really exciting and impressive (as always). I haven't used scipy's LowLevelCallable myself yet (I have been meaning to look into it). Right now I'm quite busy, but I can take a closer look at this PR this weekend. |
|
||
def create_low_level_callable(lambdify, *args): | ||
from scipy import LowLevelCallable | ||
class LambdifyLowLevelCallable(LowLevelCallable): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this class need to be closure? Or could it be defined in a try/except block around from scipy import LowLevelCallable
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to add the initialization time of scipy to symengine. That's why this is done inside a function.
Looks good to me. Too bad the LowLevelCallable isn't used much in scipy at the moment (that might change though). |
Thanks for the review |
Very impressive. Thanks @isuruf ! |
Hi above all, thank you for this awesome tool, it will almost definitly do what i need.
i have
Best wishes Mustafa |
@BlackTeaAndCoffee, you'll have to use the latest version of symengine.py and symengine for this |
cc @BlackTeaAndCoffee
This creates a
LowLevelCallable
that can be used by scipy integrate functions without the overhead of python.