Summary
bottleneck and wasserstein drop bars with non-finite death times and return a finite distance where the true distance is inf. The accompanying warning does not distinguish the case where the result is still correct from the case where it is not — and the warning count is inverted with respect to correctness.
Reproduced on persim 0.3.8.
Reproduction
import numpy as np, persim
A = np.array([[0.0, np.inf], [0.1, 0.5]]) # has an essential class
B = np.array([[0.0, 1.0], [0.1, 0.5]]) # does not
persim.bottleneck(A, B) # -> 0.5
persim.wasserstein(A, B) # -> 0.7071067811865476
There is no finite-cost matching between A and B: the essential bar cannot be matched to the diagonal, and B has no essential bar to match it to. The distance is inf. The returned 0.5 is the distance between the finite remainders.
The warning does not track correctness
| Inputs |
bottleneck |
Correct? |
Warnings |
A vs A |
0.0 |
yes |
2 |
A vs B |
0.5 |
no — should be inf |
1 |
The warning is emitted once per argument containing a non-finite death, so the correct call raises two and the incorrect call raises one. Neither its presence nor its absence certifies a result. The first row is correct only incidentally — dropping matching essential bars from both sides happens to preserve a distance of zero.
The text itself,
UserWarning: dgm1 has points with non-finite death times;ignoring those points
states the mechanism accurately but not the consequence, so it reads as a routine preprocessing note rather than "this return value is not the bottleneck distance". It is also removed entirely by the warnings.filterwarnings("ignore") that sits near the top of a great many analysis scripts.
wasserstein behaves the same way.
Suggested fix
Partition both diagrams by finiteness, per homological degree:
- if the essential-bar counts differ, return
inf without calling the matching;
- if they agree, the distance is
max(bottleneck(finite parts), max |bᵢ − b′ᵢ|) over the sorted essential births, since essential bars can only be matched to one another and matching (b, ∞) to (b′, ∞) costs |b − b′|.
Happy to open a PR if that shape looks right to you.
Found while building a backend-agnostic persistence-diagram interchange layer (akritihq/akriti); we depend on persim for distances. Fuller write-up in our RFC-0001 §9.1 and Appendix A.4.
Summary
bottleneckandwassersteindrop bars with non-finite death times and return a finite distance where the true distance isinf. The accompanying warning does not distinguish the case where the result is still correct from the case where it is not — and the warning count is inverted with respect to correctness.Reproduced on persim 0.3.8.
Reproduction
There is no finite-cost matching between
AandB: the essential bar cannot be matched to the diagonal, andBhas no essential bar to match it to. The distance isinf. The returned0.5is the distance between the finite remainders.The warning does not track correctness
bottleneckAvsAAvsBinfThe warning is emitted once per argument containing a non-finite death, so the correct call raises two and the incorrect call raises one. Neither its presence nor its absence certifies a result. The first row is correct only incidentally — dropping matching essential bars from both sides happens to preserve a distance of zero.
The text itself,
states the mechanism accurately but not the consequence, so it reads as a routine preprocessing note rather than "this return value is not the bottleneck distance". It is also removed entirely by the
warnings.filterwarnings("ignore")that sits near the top of a great many analysis scripts.wassersteinbehaves the same way.Suggested fix
Partition both diagrams by finiteness, per homological degree:
infwithout calling the matching;max(bottleneck(finite parts), max |bᵢ − b′ᵢ|)over the sorted essential births, since essential bars can only be matched to one another and matching(b, ∞)to(b′, ∞)costs|b − b′|.Happy to open a PR if that shape looks right to you.
Found while building a backend-agnostic persistence-diagram interchange layer (akritihq/akriti); we depend on persim for distances. Fuller write-up in our RFC-0001 §9.1 and Appendix A.4.