Replies: 3 comments
-
Thanks for starting a discussion on this. Here are some thoughts:
which works just fine because any PyLops operator is also setup to implement pylops/pylops/LinearOperator.py Line 75 in 3529da6 and this can be explicitely called here pylops/pylops/LinearOperator.py Line 183 in 3529da6 @ and * operator overloads here: pylops/pylops/LinearOperator.py Line 258 in 3529da6 Now, we can of course make changes to |
Beta Was this translation helpful? Give feedback.
-
Currently, we check that the vector is "flat" before we call matvec: pylops/pylops/LinearOperator.py Lines 256 to 261 in 3529da6 Instead, we could substitute this by: if np.prod(x.shape) == self.shape[1]:
return self.matvec(x)
elif x.ndim == 2: # Optionally, we can add "and x.shape[0] == self.shape[1]"
return self.matmat(x)
else:
raise ValueError("expected 1-d or 2-d array or matrix, got %r" % x) Using your example Fop * np.ones((nx * nt, 20)) # This will call matmat
Fop * np.ones((nx * nt * 20)) # This will error
Fop * np.ones((nx, nt, 20)) # This will error (but maybe we want it to call matmat...?)
Fop * np.ones((nx, nt)) # This will call matvec
Fop * np.ones((nx, nt, 1)) # This will call matvec
Fop * np.ones((nx * nt,)) # This will call matvec How about I submit a draft PR and we can play around with this? |
Beta Was this translation helpful? Give feedback.
-
Sounds good. I just wanted to make sure you were aware of the presence of Let me finalise the describe PR, I should be done by the end of today and then you can make a draft PR and we take it from there |
Beta Was this translation helpful? Give feedback.
-
Description
Many linear operators act along a specific dimension(s), not on a flattened array. For example a 2D array
x
shaped(nx, nt)
can be differentiated along the x-direction by appyingFirstDerivative((nx, nt), axis=0) * x.ravel()
. The.ravel()
call is necessary to flatten (without copy). LikeFirstDerivative
, these operators takedims
and sometimesaxis
(ordir
before #310) as keyword arguments. Since #331 all operators which receivedims
have class attributesdims
(model shape) anddimsd
(data shape).This pattern is very common throughout the PyLops and indeed for many operators in the wild. I hope to promote in this discussion the best practices—and possibly new features—for operators which follow this pattern.
Decorators for developers
Flattening by decorator
One suggestion is the use of decorators to simplify the implementation of several operators which follow the reshape/flatten pattern. As an example the
Flip
operator defines_matvec
as follows:One possibility for simplifying this pattern is defining a decorator along the lines of:
By providing this decorator, as long as users implement
dims
anddimsd
, they can implement their functions normally without worrying about reshaping and flattening.Flexible operators
Arguably doing reshape/flatten does not require a large boilerplate. So the above code might not be super useful. However, they become useful if we allow operators to receive not only flattened arrays, but reshaped ones as well. Currently, running
FirstDerivative((nx, nt), axis=0) * x
will produce aValueError
unlessx
is shaped(nx * nt,)
or(nx * nt, 1)
. However, it makes sense that it should work on an array shaped(nx, nt)
. Implementing this requires some changes toLinearOperator
, and the following decorator could be used to automatically flatten/reshape an array depending on the input size.Closing remarks
The purpose of this discussion is twofold. First, I would like to know if accepting non-flattened array is something that makes sense and would be interesting to users. Second, I would like to hear any thoughts, comments and criticisms on the above approaches.
Beta Was this translation helpful? Give feedback.
All reactions