-
-
Notifications
You must be signed in to change notification settings - Fork 481
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
Fix moebius_transform, midpoint and perpendicular_bisector #29936
Comments
Branch: public/29936 |
Author: Jonathan Kliem |
comment:1
The first thing is to use the flag
This tells me that the preciseness that is claimed with the doctests is far from valid. New commits:
|
Commit: |
comment:2
I know very little about numerics. From what I remember it makes sense to consider the relative error as well:
The situation is far worse with the other two tests, which are essentially the same, if I understand correctly:
|
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:4
I tested 10 times and not a single test failed. I hope that is good enough. |
This comment has been minimized.
This comment has been minimized.
Changed keywords from none to hyperbolic geodesic, hyperbolic point |
This comment has been minimized.
This comment has been minimized.
comment:6
I've added a few people to CC who may know how these tests are supposed to work. Those errors look pretty large to me. For something less substantial: I personally always try to limit my use of |
Dependencies: #29962 |
comment:8
Theoretically, there is not need to base this on top of #29962. But basically #29962 discovers those problems. So the doctest works fine until you test it on top of #29962 with a different random seed than 0. Last 10 new commits:
|
Changed branch from public/29936 to public/29936-reb |
comment:9
Replying to @orlitzky:
I agree. That's why I opened #29939 to fix this.
I agree. I moved that stuff to |
comment:10
Replying to @kliem:
It looks like you are comparing using relative tolerance, which if the values are close to 0, could cause large variations. Since you are taking things to be more random, it is quite possible you could divide by something close to 0. So I am not sure this is a bug as instead it could a problem that you have introduced by changing the doctests.
I disagree. The problem is numerics and working with inexact fields. You cannot get around this. I don't exactly understand what your modified doctests are doing now other than they are comparing something relatively rather than absolutely.
You have two competing issues: large values want relative error, small values want absolute error. You have too much randomness now to deal with. |
comment:11
Replying to @tscrim:
The original tests also fail if you introduce any randomness at all. I'm mainly concerned about the errors that Jonathan noticed right away, e.g.
If you have a method that's supposed to return zero but instead returns two, something other than numerical noise might be to blame. Can that test be re-run with a failing random seed, to see what a failing example looks like? |
comment:12
Replying to @tscrim:
I'm taking the minimum of the absolute and the relative error, because I want to be fair. This makes it much better. This is the original test:
Here are examples that perform bad. I hope you see, why I chose to change the doctest to minimum of absolute and relative norm:
|
comment:13
Given those values, I think the original doctests are unacceptable. We know those exactness claims are wrong. Even if it succeeds with random seed 0, we shouldn't leave it as it is. |
comment:14
So I agree with changing the test in For the issue in the geodesic, the mathematics is correct:
So I think the issue comes from this in the if a * d - b * c < 0:
w = z.conjugate() # Reverses orientation
else:
w = z At least, I only seem to notice it when the determinant of The problem is not the doctests, which are correct and meaningful (testing the three points are indeed mapped to |
comment:37
There is an issue with the midpoints:
|
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:39
This now fixes the issue with |
comment:40
We test a bisector intersects a segment at its midpoint up to rounding error. Testing that in terms of relative hyperbolic distances would be cleaner. Proposed replacement for the - sage: def works_both_ways(a, b):
- ....: UHP = HyperbolicPlane().UHP()
- ....: g = UHP.get_geodesic(a, b)
- ....: h = UHP.get_geodesic(b, a)
- ....: p = g.perpendicular_bisector()
- ....: q = h.perpendicular_bisector()
- ....: c = lambda x: x.coordinates()
- ....: error_ab = norm(c(g.intersection(p)[0]) - c(g.midpoint()))
- ....: error_ba = norm(c(h.intersection(q)[0]) - c(h.midpoint()))
- ....: assert(bool(error_ab < 1e-9) and bool(error_ba < 1e-9)), (error_ab, error_ba)
- sage: works_both_ways(1 + I, 2 + 0.5*I)
- sage: works_both_ways(2 + I, 2 + 0.5*I)
+ sage: def bisector_gets_midpoint(a, b):
+ ....: UHP = HyperbolicPlane().UHP()
+ ....: g = UHP.get_geodesic(a, b)
+ ....: p = g.perpendicular_bisector()
+ ....: x, m = g.intersection(p)[0]), g.midpoint()
+ ....: return bool(x.dist(m) < 1e-9 * a.dist(b))
+ sage: a, b, c = 1 + I, 2 + I, 2 + 0.5*I
+ sage: pairs = [(a, b), (b, a), (a, c), (c, a), (b, c), (c, b)]
+ sage: all(bisector_gets_midpoint(x, y) for x, y in pairs) This also seems more readable to me. Sorry for the slow iterations. |
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:42
I agree that that version is more readable. I tweaked the input points to have floating point numbers as otherwise the code wants to do a really horrible (but exact) symbolic computation. I also made the distance check absolute instead of relative since they should be the same point. |
comment:43
The gap between iterations is no problem. Thank you for taking the time to review this. |
comment:44
Replying to @tscrim:
For short segments (say of length I agree with you about doctesting with floating-point values. - sage: a, b, c = 1.0 + I, 2.0 + I, 2.0 + 0.5*I
- sage: pairs = [(a, b), (b, a), (a, c), (c, a), (b, c), (c, b)]
- sage: all(bisector_gets_midpoint(x, y) for x, y in pairs)
+ sage: c, d, e = CC(1, 1), CC(2, 1), CC(2, 0.5)
+ sage: pairs = [(c, d), (d, c), (c, e), (e, c), (d, e), (e, d)]
+ sage: all(bisector_gets_midpoint(a, b) for a, b in pairs) In |
This comment has been minimized.
This comment has been minimized.
comment:46
I will make that change tomorrow. Ah. right, I forgot to take care of that pyflakes issue... |
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:48
Fixed. |
comment:49
Green patchbot. |
comment:50
Good to see these issues solved. |
comment:51
Thank you for the review. At some point, when I have more free time, I want to implement higher dimensional hyperbolic space. Unfortunately other directly-applicable-to-my-research-code (and paper writing) takes priority... |
Changed branch from public/geometry/fix_hyperbolic_plane-29936 to |
We fix several related issues in hyperbolic geometry:
moebius_transform
wrong in the orientation-reversing(negative determinant) case
midpoint
andperpendicular_bisector
gave different results for (a, b) and (b, a)
Fuzzing
geometry/hyperbolic_space/hyperbolic_geodesic.py
doctests uncovered these issues. See #29935, #29962, #29963.
Depends on #29962
CC: @slel @orlitzky @tscrim @greglaun @sagetrac-jhonrubia6
Component: geometry
Keywords: hyperbolic geodesic
Author: Travis Scrimshaw
Branch/Commit:
234604b
Reviewer: Samuel Lelièvre
Issue created by migration from https://trac.sagemath.org/ticket/29936
The text was updated successfully, but these errors were encountered: