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
ENH: linalg: add the function 'solve_circulant' for solving a circulant system #3157
Conversation
""" | ||
c = np.atleast_1d(c) | ||
if c.ndim > 1: | ||
raise ValueError("`c` must be one-dimensional.") |
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.
It may require thinking about the UI a little harder, but I don't think you need to enforce 1-dimensionality. Instead, you could accept c
s of shape (..., M)
and b
s of shape (..., M)
or (..., M, N)
. If you can identify where in c
and b
is the dimension of shape M
, you would simply have to take the fft along that axis, and let broadcasting do its magic. That way you could solve not only for N
different RHS, but also for P
different LHS
by passing c
of shape (P, M)
and b
of (M, N)
... Sort of what happens in np.linalg.solve
in 1.8.
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.
Definitely something like that is possible. I thought about it while adding that strict dimension check, but decided to keep it simple to start. I've only spent a little time with the generalized API of solve
, and it feels a bit awkward. Wouldn't it have made more sense to generalize the shape of b
to (M, ...), which then includes (M,) and (M, N)? (Just roll M to the end for the purposes of broadcasting.) Anyway, I'll look at this some more, and see what makes sense for solve_circ
.
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.
Generalized ufuncs roll from axes from the end, and moreover it's more efficient for C-order arrays.
Anyway, scipy.linalg should in any case follow the convention in numpy.linalg.
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.
Well, what would make sense from a gufunc broadcasting point of view is to have a single function that solved things like c = (.., M)
and b = (..., M)
, and if you wanted to solve for multiple RHS pass in something like c = (M)
and b = (N, M)
, if you wanted multiple LHS pass in c = (P, M)
and b = (M)
, and if you wanted both then go with c = (P, 1, M)
and b = (N, M)
, which would give you a return x = (P, N, M)
where item x[p, n]
would be the solution with the p
-th LHS and the n
-th RHS. But GESV follows the opposite convention for the RHS, and so the efficient handling of multiple RHS requires that b = (M, N)
, and that's what solve
has been doing for ages, and sticking to the convention basically ruins having a nice consistent interface. If you look at the Python source code of np.linalg.solve
, there are two different gufuncs called from solve
, one for single RHS (solve1
), other for multiple(solve
), and the logic to select one or the other is not entirely satisfactory.
Looks good to me. Maybe add tests with negative/imaginary/random c. Also it wouldn't bother me too much to type out |
@argriffing: Some more test cases is a good idea--I'll add some. I could live with the longer name if most folks prefer it. |
I think the longer name is justified, since then we'd have |
I've update the PR with more tests, and To help with the discussion of the API, I also added the function In the new API, there is no change to the basic case, where This idea is quite general, and could be used elsewhere. It generalizes the API of the gufuncs in numpy. Note that the special case where |
Bump. |
The _b version API is in principle fine from broadcasting POV, but I'm a |
I haven't read all of the API discussion on this PR but I'd expect |
64f0daf
to
e96ba7a
Compare
I updated the pull request. The proposed signature of
When Note that |
This looks ready. Besides a rebase, is there anything left to do here? |
e96ba7a
to
2535400
Compare
Rebased. I don't have any more changes in mind. |
@pv @argriffing maybe time for a final review and then green button it? |
Yes, it has tests asserting that |
ENH: linalg: add the function 'solve_circulant' for solving a circulant system
Thanks @WarrenWeckesser sorry it took a year to merge :/ |
No description provided.