Skip to content
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

Singular intersections of saddle connections #249

Open
Julien-Boulanger opened this issue Sep 12, 2023 · 10 comments
Open

Singular intersections of saddle connections #249

Julien-Boulanger opened this issue Sep 12, 2023 · 10 comments

Comments

@Julien-Boulanger
Copy link

It would be nice to implement a function which computes the algebraic intersection of two saddle connections (or closed curves which are unions of saddle connections if there are more than one singularity). For this, one would need to be able to compute the intersection of two saddle connections at a singular point.

@videlec
Copy link
Collaborator

videlec commented Sep 13, 2023

The fastest is to compute the homology class of saddle connections (and their sum) and compute the algebraic intersection their. In other words, decompose any path as a formal sum of edges of the original polygons that define your surface.

Note that there are "two" algebraic intersections

  • $H_1(S; \mathbb{Z}) \times H_1(S; \mathbb{Z}) \to \mathbb{Z})$
  • $H_1(S, \Sigma; \mathbb{Z}) \times H_1(S \setminus \Sigma; \mathbb{Z}) \to \mathbb{Z})$

@videlec
Copy link
Collaborator

videlec commented Sep 13, 2023

There is a partial implementation that Julian started in #213. We should discuss how to make the map $\text{saddle connection} \mapsto \text{homology}$.

@saraedum
Copy link
Member

saraedum commented Oct 27, 2023

@Julien-Boulanger implemented the basic algorithm here.
I'll try to merge this into #213.

def algebraic_intersection(dict_a,dict_b):
    r'''
    Returns the algebraic intersection of the closed curves 
    represented in homology as dictionaries of edges with multiplicities
    
     ``dict_a`` is the dictionnary corresponding to the closed curve a,
     It .
     ``dict_b`` is the dictionnary corresponding to the closed curve b.
     
    We assume that we have an underlying translation surface denoted S, 
    and we implicitely assume that the edges of the polygons are labeled counterclockwise
    (which is the case for surfaces already defined in Flatsurf)
    
    The local variable counter_b is not used to compute the intersection,
    it only makes sure that the curve b is closed.

    EXAMPLES:
    sage: from flatsurf import translation_surfaces
    sage: S = translation_surfaces.regular_octagon()
    sage: dict0 = {(0, 0):1, (0, 1):0, (0, 2):0, (0, 3):0, (0, 4):0, (0, 5):0, (0, 6):0, (0, 7):0}
    sage: dict1 = {(0, 0):0, (0, 1):1, (0, 2):0, (0, 3):0, (0, 4):0, (0, 5):0, (0, 6):0, (0, 7):0}
    sage: algebraic_intersection(dict_0,dict_1)
    1

    sage: from flatsurf import translation_surfaces
    sage: S = translation_surfaces.regular_octagon()
    sage: dict0 = {(0, 0):0, (0, 1):1, (0, 2):0, (0, 3):0, (0, 4):0, (0, 5):0, (0, 6):0, (0, 7):0}
    sage: dict1 = {(0, 0):3, (0, 1):1, (0, 2):5, (0, 3):0, (0, 4):-2, (0, 5):0, (0, 6):0, (0, 7):0}
    sage: algebraic_intersection(dict_0,dict_1)
    0

    sage: from flatsurf import translation_surfaces
    sage: S = translation_surfaces.regular_octagon()
    sage: dict0 = {(0, 0):2, (0, 1):1, (0, 2):3, (0, 3):1, (0, 4):1, (0, 5):1, (0, 6):0, (0, 7):1}
    sage: dict1 = {(0, 0):1, (0, 1):2, (0, 2):1, (0, 3):1, (0, 4):2, (0, 5):3, (0, 6):4, (0, 7):3}
    sage: algebraic_intersection(dict_0,dict_1)
    1

    sage: from flatsurf import translation_surfaces
    sage: S = translation_surfaces.cathedral(1,4)
    sage: dict0 = {(3, 4):0, (0, 3):1, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):0, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
    sage: dict1 = {(3, 4):0, (0, 3):0, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):1, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
    sage: algebraic_intersection(dict0,dict1)
    0

    sage: from flatsurf import translation_surfaces
    sage: S = translation_surfaces.cathedral(1,4)
    sage: dict0 = {(3, 4):0, (0, 3):1, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):0, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
    sage: dict3 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):0, (2, 1):7, (2, 2):-2, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
    sage: algebraic_intersection(dict0,dict3)
    2
    '''
    Angles = S.angles(return_adjacent_edges=True)
    Intersection = 0
    for x in Angles:
        counter_a = 0
        counter_b = 0
        for edge in x[1]:
            counter_a = counter_a + dict_a[edge]
            Intersection = Intersection +counter_a*dict_b[edge]
            Intersection = Intersection -counter_a*dict_b[S.opposite_edge(edge[0],edge[1])]
            counter_a = counter_a - dict_a[S.opposite_edge(edge[0],edge[1])]
            counter_b = counter_b + dict_b[edge]
            counter_b = counter_b - dict_b[S.opposite_edge(edge[0],edge[1])]
            #print(edge,counter_a,Intersection)
        assert counter_a==0, "The first curve is not closed"
        assert counter_b==0, "The second curve is not closed"
    return Intersection
r'''
Examples of dictionaries of closed curves on the cathedral surface (1,4) : translation_surfaces.cathedral(1,4)
dict_9 is an example where two opposite edges have both non-zero multiplicities. It should not be an issue.
'''
dict_0 = {(3, 4):0, (0, 3):1, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):0, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_1 = {(3, 4):0, (0, 3):0, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):1, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_2 = {(3, 4):0, (0, 3):3, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):7, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_3 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):0, (2, 1):7, (2, 2):-2, (3, 7):0, (1, 2):0,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_4 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):5, (2, 1):4, (2, 2):-2, (3, 7):0, (1, 2):-5,
          (3, 1):0, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_5 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):5, (2, 1):4, (2, 2):-2, (3, 7):0, (1, 2):-5,
          (3, 1):6, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_6 = {(3, 4):0, (0, 3):0, (0, 0):0, (3, 3):0, (1, 7):0, (3, 0):0, (2, 1):0, (2, 2):0, (3, 7):0, (1, 2):0,
          (3, 1):6, (1, 6):0, (1, 8):0, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):0, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_7 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):5, (2, 1):4, (2, 2):-2, (3, 7):0, (1, 2):-5,
          (3, 1):6, (1, 6):0, (1, 8):7, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):-7, (3, 6):0,
          (0, 2):0, (1, 9):0, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):0, (1, 0):0, (0, 1):0}
dict_8 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):0, (1, 7):-1, (3, 0):5, (2, 1):4, (2, 2):-2, (3, 7):0, (1, 2):-5,
          (3, 1):6, (1, 6):0, (1, 8):7, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):-7, (3, 6):0,
          (0, 2):0, (1, 9):8, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):10, (1, 0):0, (0, 1):0}
dict_9 = {(3, 4):1, (0, 3):3, (0, 0):2, (3, 3):2, (1, 7):-1, (3, 0):5, (2, 1):4, (2, 2):-2, (3, 7):0, (1, 2):-5,
          (3, 1):6, (1, 6):0, (1, 8):7, (3, 2):0, (3, 5):0, (1, 1):0, (1, 3):-7, (3, 6):0,
          (0, 2):0, (1, 9):8, (1, 5):0, (2, 3):0, (2, 0):0, (1, 4):10, (1, 0):0, (0, 1):0}
from flatsurf import translation_surfaces
S = translation_surfaces.cathedral(1,4)
algebraic_intersection(dict_0,dict_3)
r'''
Check the algebraic intersection of two random dictionaries corresponding to closed curves on the regular octagon.
(Since it has only one singularity, all dictionaries represent closed curves)
'''
import random
[a,b,c,d,a1,b1,c1,d1] = [random.randrange(1,101,1) for _ in range(8)]
[e,f,g,h,e1,f1,g1,h1] = [random.randrange(1,101,1) for _ in range(8)]
dict0 = {(0, 0):a, (0, 1):b, (0, 2):c, (0, 3):d, (0, 4):a1, (0, 5):b1, (0, 6):c1, (0, 7):d1}
dict1 = {(0, 0):e, (0, 1):f, (0, 2):g, (0, 3):h, (0, 4):e1, (0, 5):f1, (0, 6):g1, (0, 7):h1}
from flatsurf import translation_surfaces
S = translation_surfaces.regular_octagon()
X = algebraic_intersection(dict0,dict1)
Y = (a-a1)*(f-g+h-f1+g1-h1)+(b-b1)*(-e+g-h+e1-g1+h1)+(c-c1)*(e-f+h-e1+f1-h1)+(d-d1)*(-e+f-g+e1-f1+g1)
assert X==Y
Z = algebraic_intersection(dict_0,dict_0)
assert Z==0
r'''
Check the algebraic intersection of two random dictionaries corresponding to closed curves on the regular double pentagon.
(Since it has only one singularity, all dictionaries represent closed curves)
'''
import random
[a,b,c,d,e,a1,b1,c1,d1,e1] = [random.randrange(1,101,1) for _ in range(10)]
[f,g,h,i,j,f1,g1,h1,i1,j1] = [random.randrange(1,101,1) for _ in range(10)]
dict0 = {(0, 0):a, (0, 1):b, (0, 2):c, (0, 3):d, (0, 4):e,
         (1, 0):a1,(1, 1):b1,(1, 2):c1,(1,3):d1, (1,4):e1}
dict1 = {(0, 0):f, (0, 1):g, (0, 2):h, (0, 3):i, (0, 4):j,
         (1, 0):f1,(1, 1):g1,(1, 2):h1,(1,3):i1, (1,4):j1}
from flatsurf import translation_surfaces
S = translation_surfaces.veech_double_n_gon(5)
Z = algebraic_intersection(dict0,dict0)
assert Z==0
X = algebraic_intersection(dict0,dict1)
Y = (a-a1)*(g-h+i-j-g1+h1-i1+j1)+(b-b1)*(-f+h-i+j+f1-h1+i1-j1)+(c-c1)*(f-g+i-j-f1+g1-i1+j1)+(d-d1)*(-f+g-h+j+f1-g1+h1-j1)+(e-e1)*(f-g+h-i-f1+g1-h1+i1)
assert X==Y
r'''
Check the algebraic intersection of two random dictionaries corresponding to closed curves on the 3-squared L.
(Since it has only one singularity, all dictionaries represent closed curves)
'''
import random
[a,b,c,d,e,f,a1,b1,c1,d1,e1,f1] = [random.randrange(1,101,1) for _ in range(12)]
[g,h,i,j,k,l,g1,h1,i1,j1,k1,l1] = [random.randrange(1,101,1) for _ in range(12)]
dict0 = {(0, 0):a, (0, 1):b, (0, 2):c, (0, 3):d,
         (1, 0):c1,(1, 1):e,(1, 2):a1,(1,3):e1,
         (2, 0):f,(2, 1):d1,(2, 2):f1,(2,3):b1}
dict1 = {(0, 0):g, (0, 1):h, (0, 2):i, (0, 3):j,
         (1, 0):i1,(1, 1):k,(1, 2):g1,(1,3):k1,
         (2, 0):l,(2, 1):j1,(2, 2):l1,(2,3):h1}
from flatsurf import translation_surfaces
S = translation_surfaces.mcmullen_L(1,1,1,1)
Z = algebraic_intersection(dict0,dict0)
assert Z==0
X = algebraic_intersection(dict0,dict1)
Y = (a-a1-c+c1)*(k-k1)+(-b+b1+d-d1)*(l-l1)+(e-e1)*(-g+g1+i-i1+l-l1)+(f-f1)*(h-h1-j+j1-k+k1)
assert X==Y
r'''
Check the algebraic intersection of two random dictionaries corresponding to closed curves on the 3-squared surface with a single horizontal cylinder.
(Since it has only one singularity, all dictionaries represent closed curves)
'''
import random
[a,b,c,d,e,f,a1,b1,c1,d1,e1,f1] = [random.randrange(1,101,1) for _ in range(12)]
[g,h,i,j,k,l,g1,h1,i1,j1,k1,l1] = [random.randrange(1,101,1) for _ in range(12)]
dict0 = {(1, 0):a, (1, 1):b, (1, 2):c, (1, 3):d,
         (2, 0):e,(2, 1):f,(2, 2):e1,(2,3):b1,
         (3, 0):c1,(3, 1):d1,(3, 2):a1,(3,3):f1}
dict1 = {(1, 0):g, (1, 1):h, (1, 2):i, (1, 3):j,
         (2, 0):k,(2, 1):l,(2, 2):k1,(2,3):h1,
         (3, 0):i1,(3, 1):j1,(3, 2):g1,(3,3):l1}
from flatsurf import translation_surfaces
G = SymmetricGroup(3)
r = G('(1,2,3)')
u = G('(1,3)')
S = translation_surfaces.origami(r,u)
Z = algebraic_intersection(dict0,dict0)
assert Z==0
X = algebraic_intersection(dict0,dict1)
Y = (a-a1)*(i-j+k-i1+j1-k1)+(b-b1)*(-k+k1)+(c-c1)*(-g+j+k+g1-j1-k1)+(d-d1)*(g-i-k-g1+i1+k1)
Y = Y+ (e-e1)*(-g+h-i+j+l+g1-h1+i1-j1-l1)+(f-f1)*(-k+k1)
assert X==Y
r'''
Examples of dictionaries corresponding to closed curves on the 4-squared surface,
and test of their intersections.
'''
dict1 = {(1, 0):0, (1, 1):1, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict2 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):1,
         (2, 0):0,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict3 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):1,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict4 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):1,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
#for i = 1,2,3,4, the curves are pairwise non-intersecting
dict5 = {(1, 0):1, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):-1,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict6 = {(1, 0):1, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):1,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict7 = {(1, 0):1, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):-1, (4, 1):0, (4, 2):0, (4, 3):0}
dict8 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):1,(2, 1):0,(2, 2):1,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):0, (4, 1):0, (4, 2):0, (4, 3):0}
dict9 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):1,(2, 1):0,(2, 2):0,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):1, (4, 1):0, (4, 2):0, (4, 3):0}
dict10 = {(1, 0):0, (1, 1):0, (1, 2):0, (1, 3):0,
         (2, 0):0,(2, 1):0,(2, 2):-1,(2,3):0,
         (3, 0):0,(3, 1):0,(3, 2):0,(3,3):0,
         (4, 0):1, (4, 1):0, (4, 2):0, (4, 3):0}
from flatsurf import translation_surfaces
G = SymmetricGroup(4)
r = G('(1,2)(3,4)')
u = G('(2,3)')
S = translation_surfaces.origami(r,u)
assert algebraic_intersection(dict1,dict1)==0
assert algebraic_intersection(dict1,dict2)==0
assert algebraic_intersection(dict1,dict3)==0
assert algebraic_intersection(dict1,dict4)==0
assert algebraic_intersection(dict1,dict5)==-1
assert algebraic_intersection(dict1,dict6)==-1
assert algebraic_intersection(dict1,dict7)==-1
assert algebraic_intersection(dict1,dict8)==0
assert algebraic_intersection(dict1,dict9)==0
assert algebraic_intersection(dict1,dict10)==0

assert algebraic_intersection(dict2,dict1)==0
assert algebraic_intersection(dict2,dict2)==0
assert algebraic_intersection(dict2,dict3)==0
assert algebraic_intersection(dict2,dict4)==0
assert algebraic_intersection(dict2,dict5)==1
assert algebraic_intersection(dict2,dict6)==1
assert algebraic_intersection(dict2,dict7)==1
assert algebraic_intersection(dict2,dict8)==0
assert algebraic_intersection(dict2,dict9)==0
assert algebraic_intersection(dict2,dict10)==0

assert algebraic_intersection(dict3,dict1)==0
assert algebraic_intersection(dict3,dict2)==0
assert algebraic_intersection(dict3,dict3)==0
assert algebraic_intersection(dict3,dict4)==0
assert algebraic_intersection(dict3,dict5)==0
assert algebraic_intersection(dict3,dict6)==0
assert algebraic_intersection(dict3,dict7)==1
assert algebraic_intersection(dict3,dict8)==0
assert algebraic_intersection(dict3,dict9)==-1
assert algebraic_intersection(dict3,dict10)==-1

assert algebraic_intersection(dict4,dict1)==0
assert algebraic_intersection(dict4,dict2)==0
assert algebraic_intersection(dict4,dict3)==0
assert algebraic_intersection(dict4,dict4)==0
assert algebraic_intersection(dict4,dict5)==0
assert algebraic_intersection(dict4,dict6)==0
assert algebraic_intersection(dict4,dict7)==-1
assert algebraic_intersection(dict4,dict8)==0
assert algebraic_intersection(dict4,dict9)==1
assert algebraic_intersection(dict4,dict10)==1

assert algebraic_intersection(dict5,dict1)==1
assert algebraic_intersection(dict5,dict2)==-1
assert algebraic_intersection(dict5,dict3)==0
assert algebraic_intersection(dict5,dict4)==0
assert algebraic_intersection(dict5,dict5)==0
assert algebraic_intersection(dict5,dict6)==0
assert algebraic_intersection(dict5,dict7)==0
assert algebraic_intersection(dict5,dict8)==0
assert algebraic_intersection(dict5,dict9)==0
assert algebraic_intersection(dict5,dict10)==0

assert algebraic_intersection(dict6,dict1)==1
assert algebraic_intersection(dict6,dict2)==-1
assert algebraic_intersection(dict6,dict3)==0
assert algebraic_intersection(dict6,dict4)==0
assert algebraic_intersection(dict6,dict5)==0
assert algebraic_intersection(dict6,dict6)==0
assert algebraic_intersection(dict6,dict7)==0
assert algebraic_intersection(dict6,dict8)==0
assert algebraic_intersection(dict6,dict9)==0
assert algebraic_intersection(dict6,dict10)==0

assert algebraic_intersection(dict7,dict1)==1
assert algebraic_intersection(dict7,dict2)==-1
assert algebraic_intersection(dict7,dict3)==-1
assert algebraic_intersection(dict7,dict4)==1
assert algebraic_intersection(dict7,dict5)==0
assert algebraic_intersection(dict7,dict6)==0
assert algebraic_intersection(dict7,dict7)==0
assert algebraic_intersection(dict7,dict8)==0
assert algebraic_intersection(dict7,dict9)==0
assert algebraic_intersection(dict7,dict10)==0

assert algebraic_intersection(dict8,dict1)==0
assert algebraic_intersection(dict8,dict2)==0
assert algebraic_intersection(dict8,dict3)==0
assert algebraic_intersection(dict8,dict4)==0
assert algebraic_intersection(dict8,dict5)==0
assert algebraic_intersection(dict8,dict6)==0
assert algebraic_intersection(dict8,dict7)==0
assert algebraic_intersection(dict8,dict8)==0
assert algebraic_intersection(dict8,dict9)==0
assert algebraic_intersection(dict8,dict10)==0

assert algebraic_intersection(dict9,dict1)==0
assert algebraic_intersection(dict9,dict2)==0
assert algebraic_intersection(dict9,dict3)==1
assert algebraic_intersection(dict9,dict4)==-1
assert algebraic_intersection(dict9,dict5)==0
assert algebraic_intersection(dict9,dict6)==0
assert algebraic_intersection(dict9,dict7)==0
assert algebraic_intersection(dict9,dict8)==0
assert algebraic_intersection(dict9,dict9)==0
assert algebraic_intersection(dict9,dict10)==0

assert algebraic_intersection(dict10,dict1)==0
assert algebraic_intersection(dict10,dict2)==0
assert algebraic_intersection(dict10,dict3)==1
assert algebraic_intersection(dict10,dict4)==-1
assert algebraic_intersection(dict10,dict5)==0
assert algebraic_intersection(dict10,dict6)==0
assert algebraic_intersection(dict10,dict7)==0
assert algebraic_intersection(dict10,dict8)==0
assert algebraic_intersection(dict10,dict9)==0
assert algebraic_intersection(dict10,dict10)==0

saraedum added a commit to saraedum/sage-flatsurf that referenced this issue Nov 13, 2023
@saraedum
Copy link
Member

saraedum commented Nov 13, 2023

@Julien-Boulanger I adapted your code for the branch in #211. It can now be tested there (let me know if you need help with this.)

def algebraic_intersection(self, other):
r"""
Return the algebraic intersection of this class of a closed curve with
``other``.
EXAMPLES::
sage: from flatsurf import translation_surfaces, SimplicialHomology
sage: S = translation_surfaces.regular_octagon()
sage: H = SimplicialHomology(S)
sage: H((0, 0)).algebraic_intersection(H((0, 1)))
1
sage: a = H((0, 1))
sage: b = 3 * H((0, 0)) + 5 * H((0, 2)) - 2 * H((0, 4))
sage: a.algebraic_intersection(b)
0
sage: a = 2 * H((0, 0)) + H((0, 1)) + 3 * H((0, 2)) + H((0, 3)) + H((0, 4)) + H((0, 5)) + H((0, 7))
sage: b = H((0, 0)) + 2 * H((0, 1)) + H((0, 2)) + H((0, 3)) + 2 * H((0, 4)) + 3 * H((0, 5)) + 4 * H((0, 6)) + 3 * H((0, 7))
sage: a.algebraic_intersection(b)
1
sage: S = translation_surfaces.cathedral(1, 4)
sage: H = SimplicialHomology(S)
sage: a = H((0, 3))
sage: b = H((2, 1))
sage: a.algebraic_intersection(b)
0
sage: a = H((0, 3))
sage: b = H((3, 4)) + 3 * H((0, 3)) + 2 * H((0, 0)) - H((1, 7)) + 7 * H((2, 1)) - 2 * H((2, 2))
sage: a.algebraic_intersection(b)
2
"""
intersection = 0
multiplicities = dict(self._chain)
other_multiplicities = dict(other._chain)
for _, adjacent_edges in self.parent().surface().angles(return_adjacent_edges=True):
counter = 0
other_counter = 0
for edge in adjacent_edges:
opposite_edge = self.parent().surface().opposite_edge(*edge)
counter += multiplicities.get(edge, 0)
intersection += counter * other_multiplicities.get(edge, 0)
intersection -= counter * other_multiplicities.get(opposite_edge, 0)
counter -= multiplicities.get(opposite_edge, 0)
other_counter += other_multiplicities.get(edge, 0)
other_counter -= other_multiplicities.get(opposite_edge, 0)
if counter:
raise TypeError("homology class does not correspond to a closed curve")
if other_counter:
raise ValueError("homology class does not correspond to a closed curve")
return intersection

It seems to work fine. However, one of the examples produces a different output for me. Your example was:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.regular_octagon()
sage: dict0 = {(0, 0):2, (0, 1):1, (0, 2):3, (0, 3):1, (0, 4):1, (0, 5):1, (0, 6):0, (0, 7):1}
sage: dict1 = {(0, 0):1, (0, 1):2, (0, 2):1, (0, 3):1, (0, 4):2, (0, 5):3, (0, 6):4, (0, 7):3}
sage: algebraic_intersection(dict_0,dict_1)
1

However, when I run the following, I get -6 instead of 1.

sage: from flatsurf import translation_surfaces, SimplicialHomology
sage: S = translation_surfaces.regular_octagon()
sage: H = SimplicialHomology(S)

sage: a = 2 * H((0, 0)) + H((0, 1)) + 3 * H((0, 2)) + H((0, 3)) + H((0, 4)) + H((0, 5)) + H((0, 7))
sage: b = H((0, 0)) + 2 * H((0, 1)) + H((0, 2)) + H((0, 3)) + 2 * H((0, 4)) + 3 * H((0, 5)) + 4 * H((0, 6)) + 3 * H((0, 7))
sage: a.algebraic_intersection(b)
-6

Maybe I made some silly transcription error. Can you check what's the correct result here?

@Julien-Boulanger
Copy link
Author

That's my fault I checked again and it should indeed be a -6 !

@saraedum
Copy link
Member

This was included in #291.

@saraedum saraedum reopened this Nov 12, 2024
@saraedum
Copy link
Member

But the interface for saddle connections is still missing I think.

@videlec
Copy link
Collaborator

videlec commented Nov 15, 2024

But the interface for saddle connections is still missing I think.

What do you think it should be : surface.homology()(saddle_connection)? saddle_connection.homology()? both? something else?

@saraedum
Copy link
Member

But the interface for saddle connections is still missing I think.

What do you think it should be : surface.homology()(saddle_connection)? saddle_connection.homology()? both? something else?

I think it should be homology(saddle_connection). I don't like saddle_connection.homology() because the homology is not unique.

@videlec
Copy link
Collaborator

videlec commented Nov 16, 2024

See #308

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants