-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
BUG: "sp.linalg.solve_discrete_are" fails for random data #6572
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
Conversation
This fixes #2251 and its tests per the discussion on the issue page. The doc string is updated.
This is Py2 issue I guess
Hopefully this will make Travis happy.
For some unknown reason, the test works locally but trips up on the master branch. Here testing whether this is due to the matrix object.
BTW you can check all the pep8 failures locally by installing pep8 ( |
This reverts commit f9162f8.
Bah, I guess I'm not cut for this. I've checked the files thrice with pep8 and it still fails. |
I've slept over it checked with some more examples and I think this PR is ready for review. Thanks . |
U.S. Energy Research and Development Agency under contract | ||
ERDA-E(49-18)-2087. | ||
http://dspace.mit.edu/bitstream/handle/1721.1/1301/R-0859-05666488.pdf | ||
P. van Dooren , "A Generalized Eigenvalue Approach For Solving Riccati |
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 know it was like this in the original, but it would be better to put this in a references section and just cite it here. See:
Though the previous method doesn't always work, it still might be nice to see how the two compare speed-wise. (Especially on more sizable problems.) Benchmarks would go here: https://github.com/scipy/scipy/blob/master/benchmarks/benchmarks/linalg.py You can run them with https://asv.readthedocs.io/en/latest/writing_benchmarks.html |
Unfortunately, on a windows machine I can't do any of the build related stuff including the |
Maybe I'm just being silly though. Edit: yes, I think I'm being silly. |
Also it's possible to run benchmarks without |
It would be nice to include more DAREX examples in the tests. |
Indeed but then I have to include balancing algorithms which is basically copying everything from my other implementation which doesn't seem that easy to convert to SciPy way without breaking some back-compatibility. |
I like this one. I'm still in favor of putting in DAREX examples, however. Not all of them will fail (the only three I tried work fine), and they provide extra coverage that wasn't possible before (e.g. singular |
@person142 Oh that I can tell. In the CAREX examples, there are two examples fail** even after my balancing implementations (ex.6 and 12 in the matlab version). In DAREX I have to finish the conversion from matlab to Python but so far so good but I'm sure it will fail on a few suspicious looking ones. One major pain is the PEP8 and those matrices don't go well together, is there a way to ignore PEP8 temporarily of things or what is the preferred way of entering them? Tall Submatrices ? ** By fail I mean the accuracy is not good enough absolutely though satisfactory in the relative sense (max error is less than a certain percent of the 1-norm the matrix). |
If the matrices are big, I would put them as data files (e.g. text files), under |
removed previous two test cases as they are already in darex, fails are commented out
|
Ok, for the benefit of anyone looking at this: with the new set of tests the old function has 4 exceptions due to ill-conditioning in https://github.com/person142/scipy/tree/old-discrete-are |
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.
Ok, I left some comments. They're mostly pretty small things; I think this is pretty close to being done.
ERDA-E(49-18)-2087. | ||
http://dspace.mit.edu/bitstream/handle/1721.1/1301/R-0859-05666488.pdf | ||
The equation is solved by forming the extended symplectic matrix pencil, | ||
as described in [1]_, .. math:`H - \lambda J` given by the block matrices |
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.
For inline math do :math:H - \lambda J
.
You can see the result of building the docs here:
|
||
[ A 0 B ] [ I 0 B ] | ||
[ -Q I 0 ] - \lambda * [ 0 A^T 0 ] | ||
[ 0 0 R ] [ 0 -B^T 0 ] |
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.
This isn't rendering right.
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.
Needs ::
(two colons) at the end of the preceding text, ie. ... given by the block matrices::
if np.iscomplexobj(x): | ||
r_or_c = complex | ||
|
||
if not np.equal(*x.shape): |
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.
This fails for a 1 x 1 array.
|
||
if m != a.shape[0]: | ||
raise ValueError("Matrix a and b should have the same number of rows.") | ||
|
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 thing about spacing.
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 get your point on spacing
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's not a show-stopper, but I'd like related groups of if statements to not have any spaces between them (and maybe be converted to if/elif's) so that they cluster together visually. But this might just be a personal preference so I won't press the point.
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 thought you wanted a spacing between the ifs inside the for loop so I extrapolated from that, but I have no preference.
|
||
if m != q.shape[0]: | ||
raise ValueError("Matrix a and q should have the same shape.") | ||
|
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.
Ditto on spacing.
up, ul, uu = lu(u00) | ||
|
||
if 1/cond(uu) < np.spacing(1.): | ||
return np.array([[]]) |
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.
Sorry, forgot to clarify this before: failure conditions should raise an exception (in this case a LinAlgError
).
sym_threshold = np.max(np.spacing([1000., norm(u_sym, 1)])) | ||
|
||
if np.max(np.abs(u_sym)) > sym_threshold: | ||
return np.array([[]]) |
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.
Exception here too.
[3.7730, -30.2800, 14.6900]]) * 0.001, | ||
np.diag([50, 0, 0, 0, 50, 0, 0, 0, 0]), | ||
np.eye(3)), | ||
## darex #12 |
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 have some suggested changes for this test:
It turns the failing tests into known failures so that they're more visible.
np.array([[1, 2], [1, 3]]), | ||
np.array([[1, 1+1j], [1-1j, 2]]), | ||
np.array([[2, -2j], [2j, 3]])), | ||
# User-reported |
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.
For got to mention this: reference the original github issue here so it's easy to find later.
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.
Ah, forgot to include this...
np.eye(3), | ||
1e6 * np.eye(3), | ||
1e6 * np.eye(3), | ||
"Fails"), |
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.
Ok so I got a little lazy putting in the causes for failure here; should probably at least be something like "unsatisfactory absolute error" if that's the cause.
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.
No actually it is a complete failure to find a valid solution. The other two I marked it as bad accuracy
This hopefully concludes the requested changes. Please let me know if there are additional items |
I'm happy (the CircleCI passed, not sure why it's still yellow), but I'll wait to get a second opinion from another developer. |
|
||
# Check the deviation from symmetry for success | ||
u_sym = u00.conj().T.dot(u10) | ||
u_sym -= u_sym.conj().T |
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.
This will bomb if u_sym
is real, because in-place operations on overlapping memory regions is undefined behavior.
For extra fun, you don't see it for small matrices due to buffering.
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.
Iow, should be u_sym = u_sym - u_sym.conj().T
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.
Wow. That's really good to know. I'll fix it in a moment. Is there any place where I can read more about it?
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's the issue about Numpy arrays and views to numpy arrays, eg b = a[::2]; b[0] = 1
modifies also a
. I think it's mentioned in most numpy tutorials. With in-place operations etc., you want to make sure the output operand is not a view of any kind of the input.
However, I think this particular caveat here will go away in near future numpy/numpy#8043. There are also long threads about this in the numpy issue tracker, but I'd recommend those only for entertainment purposes now that there's a consensus on how the issue will be addressed.
Looks OK to me apart from that one cmment. |
Also would be good to squash things. |
blank line reduction, removal of redundant indexing
@person142: there's an option to squash and merge in the github merge button |
I don't know what "squash" refers to actually. |
Thanks, merged! |
Great! Thanks for sticking with us @ilayn, and I look forward to your future improvements! |
Pleasure is mine. |
This fixes #2251 and its tests per the discussion on the issue page. The doc string is updated.