symengine.py icon indicating copy to clipboard operation
symengine.py copied to clipboard

.evalf() for matrices

Open michaelwcl opened this issue 1 year ago • 9 comments

This may sound a bit baseless since I am very new to symengine and have recently been trying to convert my sympy based code to symengine for speed reasons.

Currently, I work with 4x4 symbolic matrices and have a need to .sub() and evaluate in order to use the data.

However, to my knowledge, symengine matrices don't have a evalf function, as I see this error:

AttributeError: 'symengine.lib.symengine_wrapper.MutableDenseMatrix' object has no attribute 'evalf'

I'm not sure how else I can go about this, and I feel that my implmentation would cost me speed. I was hoping that there could be a .evalf() for matrices in symengine.

michaelwcl avatar Sep 23 '24 20:09 michaelwcl

With evalf, do you need arbitrary precision? if not, you should be able to use lambdify to get floating point values.

Otherwise you can use applyfunc:

>>> m = se.DenseMatrix([[se.pi, se.Catalan], [se.sqrt(2), se.sqrt(3)]])
>>> m
[pi, Catalan]
[sqrt(2), sqrt(3)]
>>> m.applyfunc(lambda arg: arg.evalf(100))
[3.1415926535897932384626433833, 0.91596559417721901505460351493]
[1.4142135623730950488016887242, 1.7320508075688772935274463415]

bjodah avatar Sep 24 '24 13:09 bjodah

I'll give that a try, thanks! I don't need arbitrary precision so it should work.

michaelwcl avatar Sep 24 '24 18:09 michaelwcl

Also, this is partly related. When I try to use symengine for multiprocessing purposes, I get the error:

TypeError: no default __reduce__ due to non-trivial __cinit__

I know this is to do with pickling, and I'm not sure how to go about it. I saw in the previous issues of symengine that pickling was added, but perhaps I'm doing it wrong. I am coding in python and I guess also using the python wrapper. Is there an existent method for pickling that I'm not aware of? Thanks

michaelwcl avatar Oct 02 '24 14:10 michaelwcl

My hunch is that the matrix class is missing a __reduce__ method: https://github.com/symengine/symengine.py/blob/bf8f69a68d168ca3b764879387951c618f5d371e/symengine/lib/symengine_wrapper.in.pyx#L3304

With a bit of luck, all that is needed is to add one like the one thats present on Basic. (or perhaps more akin to the one for the Lambdify classes).

bjodah avatar Oct 02 '24 15:10 bjodah

I believe that's it. I'm using matrices within the python wrapper, and I'm trying to reduce a matrix to pass to another process (as in input argument)

How would I go about requesting the __reduce__ method to be added? I am not sure whether to open another issue and potentially cause clutter.

michaelwcl avatar Oct 02 '24 15:10 michaelwcl

@michaelwcl requests as such might not quite have the effect you're looking for (unless your need stems from a commercial project, and your employer is willing to pay for consultancy work). It's not that people don't want to help (they do! me included), but time constraints might mean that it can take quite a while before someone gets around adding this.

You can also try to add this yourself (there's a bit of a learning curve getting started), but open source projects (genereally) are always looking for contributors. And for the maintainers, finding the time to provide help/feedback on a pull request is easier, than say fulfilling feature requests.

bjodah avatar Oct 03 '24 06:10 bjodah

No that fully makes sense, and thank you. I think I'm going to attempt my own implementation, or at least try. You said there's a 'reduce' present in 'Basic' right? I think I'll start from there.

michaelwcl avatar Oct 03 '24 14:10 michaelwcl

@michaelwcl the best request in this case is to send a PR with the implementation. :)

Thanks for using SymEngine. If you find other issues, please report them, and if you have time to fix some, we would highly appreciate it.

certik avatar Oct 03 '24 14:10 certik

Yes, the __reduce__ method is something the Python docs describe here: https://python.readthedocs.io/en/latest/library/pickle.html#object.reduce

It's implemented for Basic here: https://github.com/symengine/symengine.py/blob/bf8f69a68d168ca3b764879387951c618f5d371e/symengine/lib/symengine_wrapper.in.pyx#L847

and for LLVMDouble it's here: https://github.com/symengine/symengine.py/blob/bf8f69a68d168ca3b764879387951c618f5d371e/symengine/lib/symengine_wrapper.in.pyx#L5249

The references to .thisptr (in Basic) and .lambda_visitor (in LLVMDouble) might be mysterious at a glance, but those fields are defined here: https://github.com/symengine/symengine.py/blob/bf8f69a68d168ca3b764879387951c618f5d371e/symengine/lib/symengine_wrapper.in.pxd#L11 https://github.com/symengine/symengine.py/blob/bf8f69a68d168ca3b764879387951c618f5d371e/symengine/lib/symengine_wrapper.in.pxd#L48

the fields that need serializing in DenseMatrix are found here: https://github.com/symengine/symengine/blob/0ccc20fea491ba0939768a2d74e590df2c1c2a74/symengine/matrix.h#L331

and for the (sparse) CSRMatrix you find the fields here: https://github.com/symengine/symengine/blob/0ccc20fea491ba0939768a2d74e590df2c1c2a74/symengine/matrix.h#L474

hope it's of some help!

bjodah avatar Oct 03 '24 14:10 bjodah