New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sparse BlockOperator #1808
base: main
Are you sure you want to change the base?
Sparse BlockOperator #1808
Conversation
Thanks for working on this @TiKeil. Could also a COO format (e.g., a triple of row indices, column indices, and |
1e9dbb1
to
8397c4d
Compare
Thanks for the suggestion. This would mean to force the user to use it in sparse form or would you do it optional? I have been thinking about this as well but I thought that it might be easier to basically hide the sparse functionality entirely in the |
I meant doing it similarly to
I guess it depends on whether there are applications (which I don't know about) with very large sparse block operators where forming zero blocks is too costly. |
Ah ok, I see. That would mean that it would be no longer possible to use the "old" way where no sparsity is used and instead the
You mean zero blocks in the sense of I will work on it, thanks ! |
I would say that it would be good to keep the old input style (list of lists of |
I agree that the input style should be the same, but if we handle it like in the But: Potentially a user-code assumes that every |
This worked out quite nicely. The only bad technical thing is that the |
I obviously failed to get the CI running with the |
The developer documentation talks a little bit about how to get new dependencies into the CI. I think it would be great if you look into that, tell me what's unclear, so I can update that now. |
|
5cf4dcd
to
dcfb64e
Compare
I automated most of the process in #1845 |
dcfb64e
to
27aa2d0
Compare
18e66f2
to
e80291b
Compare
96bd2ad
to
2479320
Compare
This pull request modifies make ci_requirements and commit the changed files to ensure that CI runs with the updated dependencies. |
@TiKeil, good and bad news: the good news is that sparse can now apparently be installed again via conda-forge. However, current sparse now hard-depends on numba. So adding sparse as a hard dependency would make pyMOR depend on numba and, thus, llvm. I don't think that this would be a wise decision for pyMOR. Thus, overall I think we should see if it is feasible to run our own sparse data structure. @TiKeil, do you want to look into this in the near future? Otherwise, I'd remove the release milestone. |
Sad to hear. Would it instead be possible to have it as an optional requirement and leave sparse 'BlockOperators' as an optional thing as I intended to do it in the first place ? For instance have a 'make_sparse' method that can only be used if the user has the optional package. As a default we could stay with our current dense implementation. Or is the hard numba dependency also an issue for optional requirements ? Regarding providing our own sparse implementation: that seems possible but is probably nothing I will do in the next days. |
Thanks @pmli for looking into this. I lately tried with CSC and did not think about trying other formats. I propose, I revert my latest changes and use COO from scipy sparse instead. |
Very annoying observation: >>> import numpy as np
>>> import scipy.sparse as sps
>>> A = np.array([['', 'a'], ['b', '']], dtype=object)
>>> B = sps.coo_array(A)
>>> print(repr(B))
<2x2 sparse array of type '<class 'numpy.object_'>'
with 2 stored elements in COOrdinate format>
>>> B = sps.coo_matrix((B.data, (B.row, B.col)))
Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.10/code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "/Users/admin/Projects/pymor-dev/venv/lib/python3.10/site-packages/scipy/sparse/_coo.py", line 160, in __init__
self.data = getdata(obj, copy=copy, dtype=dtype)
File "/Users/admin/Projects/pymor-dev/venv/lib/python3.10/site-packages/scipy/sparse/_sputils.py", line 141, in getdata
getdtype(data.dtype)
File "/Users/admin/Projects/pymor-dev/venv/lib/python3.10/site-packages/scipy/sparse/_sputils.py", line 126, in getdtype
raise ValueError(
ValueError: object dtype is not supported by sparse matrices |
cd5e08e
to
285ea37
Compare
pre-commit.ci autofix |
This worked half-way-well. Current problems are:
I appreciate comments in that direction but I still think that we have a chance to merge this soon, even with these workarounds. |
for more information, see https://pre-commit.ci
46770a9
to
6abc805
Compare
For me: check if |
@TiKeil, @pmli, there is no constructor for sparse arrays that allows constructing those from sparse data, then I'd assume that a lot of other stuff does not work / is broken as well. In that case I'd go with the roll-your-own-sparse-format approach. (@TiKeil, otherwise, you should take a look at the CI failures.) |
The CI failures are all due to the fact that the |
I agree, it seems that there is a bug in |
This PR revisits ideas from #889.
In #889, @pmli proposed to use pydata/sparse for implementing a sparse BlockOperator. One advantage of this is that we do not need a specialized class and can just incorporate it into
BlockOperatorBase
.In this PR, I implemented a first idea on how to do this. Actually, worked out pretty well and there is less code duplication than I thought.
Basically, if specified by the
make_sparse
argument in the__init__
, theBlockOperator
does not createZeroOperator
for everyNone
entry. Instead it creates aCOO
matrix fromsparse
. Then, the respectivecoords
with non-zero entries are stored. The same is now done for the dense case to be able to follow the samefor
loops for sparse and dense.If the dense version is needed, the
to_dense()
method can be used.Apart from the tests that I pushed, the code needs further testing.
Another debate would be the default value for
make_sparse
. For now, it is probably better to stick withFalse
. However, I do not see a reason whyTrue
should not be the default in the future. Also because if the dense version is strictly required, one can use theto_dense()
mechanism.The
BlockDiagonalOperator
already uses the sparse structure since theapply
,apply_adjoint
, andassemble
overwrites for this class can then immediately be dropped.
Another thing would be to think about whether some methods from pydata/sparse can be used to simplify things even further.
Anything that looks strange to you?