Closed sophiatev closed 1 year ago
Many thanks for this very detailed report and proposed solution, definitely something isn't right here! I will try to look into it in detail in the next few days.
Thank you! FYI, I noticed a bug in my initial proposed solution. The updated post has my new proposed solution which works with what I've tested thus far.
I incorporated your fix in 0e30e0e99fd0f0d. I checked that the link constructed under permuting the PD labels.
Thanks for both pointing this out and solving the underlying problem!
Maybe this issue can be closed then ?
Closed by 0e30e0e99fd0f0dd1547a8e0.
It seems to me there's a bug in how Spherogram builds a link from its PD code for two-strand components. If I pass in a PD code for a Hopf link with two positive crossings,
[(1, 2, 0, 3), (2, 1, 3, 0)]
(pictured on left), and then call thePD_code()
method on the constructed link, the PD code I get back is[(1, 2, 0, 3), (3, 0, 2, 1)]
, which corresponds to a Hopf link with two negative crossings (pictured on right). I also double checked that each crossing of the constructed link has acrossing.sign
of -1, confirming that the wrong link is constructed.However, if I instead pass in the PD code
[(1, 3, 0, 2), (3, 1, 2, 0)]
, which corresponds to the same Hopf link with two positive crossings, simply with relabeled strands (see below), I get back the correct PD code. In this case, thecrossing.sign
of each crossing is correct: +1.I believe this is due to the logic of this else statement in the method
_component_starts
oflinks_base.py
. As I understand it, this logic seems to assume that in the case a component is made up of just two strands, the lowest-labeled strand of the component must be the incoming overstrand of a crossing. It extracts the two crossings that the strand "glues" together, and checks for which of those two the lowest-labeled strand (calledm
) is an overstrand. It then orients the component to point along the strand two indices away fromm
in that crossing's PD tuple. This only works if that strand is an outgoing strand, which is true only ifmin
is an incoming strand.This is the case for the second image that Spherogram processes correctly. For the left component, we see that the lowest-labeled strand is
m = 0
, and in this case it is indeed the incoming overstrand of crossingc2
. Similarly, the lowest-labeled strand for the right component ism = 2
, and this once more is the incoming overstrand of crossingc1
. So the top crossing is oriented with strand 1 as the outgoing strand, and the bottom crossing is oriented with strand 3 as the outgoing strand, which is correct. In the first image I posted, the logic remains the same for the left component (0 is still the incoming overstrand of the top crossing), so the orientation is set correctly for that component. However, for the right component, 2 is no longer the incoming overstrand but rather the incoming understrand of crossingc2
. As such, theelse
statement decides that we should orient the component to point along strand 3 moving from the bottom crossing,c1
. It does this under the assumption that since 2 wasn't the incoming overstrand forc2
, it must be forc1
, and hence strand 3 must be the outgoing strand. We wrongly reverse the orientation of the second component and end up with an inequivalent link with two negative crossings, pictured in the first image on the right.The comment in the
else
statement seems to imply that we are using the fact that the first element of a crossing's PD code is the incoming understrand. But this doesn't imply that the lowest labeled-strand of a two-strand component will be the incoming overstrand of some crossing. I think the correct logic would rather look likeThis is of course assuming that component with just two strands should appear as the understrand in one crossing and as the overstrand in another. Otherwise it's just an unknot lying on top of or below the link diagram, in which case the orientation doesn't matter anyway.