Conflict between generators in different groups with the same name

asked 3 years ago

cgodfrey gravatar image

updated 3 years ago

I wrote a relatively simple implementation of the Seifert van Kampen theorem, and I have a commutative 'cube', so to speak, meaning I want to apply it twice successively. The implementation is

# This function computes the fundamental group of a topological space X using
# the Seifert-van Kampen theorem. We decompose X into the union of two open
# connected subsets, U and V, whose fundamental groups are the free group on
# some generators along with relations alpha and beta, respectively.
# Additionally, we have the fundamental group of U \cap V, which is the free
# group on the generators gamma_i. We then have the inclusion maps
# I: \pi(U\cap V) -> \pi(U) and J: \pi(U\cap V) -> \pi(V) which gives
# us the categorical coproduct of \pi(U) * \pi(V).
def seifert_van_kampen(U, alpha, V, beta, I, J, intersection):
    X = FreeGroup(U.gens() + V.gens())
    relations = []
    for generator in intersection.gens():
        relations.append(X(I(generator))*X(J(generator))^-1)
    relations = relations + alpha + beta
    return X / relations

And it seems to work properly in simple cases. My problem arises when trying to apply it twice successively. My diagram looks like this:

     A --- AB
  /     X    \
S -- B     AG -- X  
  \     X    /
     G --- BG

Where S is the pairwise intersection between any of A, B, and G, and the X in the middle of the diagram represents crossing arrows. Through one application of SVK, I can get the fundamental group for AB, AG, or BG, and the problem occurs with the second step to compute the fundamental group for X.

If I have the fundamental groups for A, B, and G generated by alpha_i, beta_i, and gamma_i respectively, then the fundamental group for AB is generated by the alpha_i and beta_i, and similar for AG and BG. But if I try to use the same logic, say using AB and BG to get X, the generators would be alpha_i, beta_i from AB, and beta_i and gamma_i from BG. But my understanding is that those generators should be considered distinct, and I don't quite see how to make that happen in Sage.

In particular, the additional relations when we compute the coproduct (in the AB/BG case) come from the inclusion map of the generators for B into each of AB and BG respectively, which is exactly those duplicate generators. That part is fine, but if I want to consider those words as elements of the free group on (alpha_i, beta_i, beta_i, gamma_i), I don't know how to make those words use the 'correct' generators.

EDIT: To give the specific way I'm trying to use this, I'm studying 2-knots, and have a particular decomposition into 3 1-knots. The fundamental group of each of the knot complements are A, B, and G above, and I'm trying to recover the fundamental group for the original 2-knot complement. There's a lot of boilerplate stuff to get the knot in a particular representation I can work with, but right now I use the above function like this:

def SVK_cube(braids, b):
    prefixes = ['x', 'y', 'z']
    intersect_maps = []
    groups = []

    intersect_group = FreeGroup(2 * b, 'a')

    # Boilerplate stuff
    graph, _ = make_graph(braids, b)
    graph = is_orientable(graph)
    signs = orientation_signs(graph, b)

    for i in range(3):
        # hom[i] is the element that the ith generator of fundamental group for
        # intersection gets sent to
        hom, group = wirtinger_relations(braids[i], signs, b, prefixes[i])
        print(group)
        print(hom)
        groups.append(group)
        intersect_maps.append(intersect_group.hom(hom))

    a_group, b_group, g_group = groups
    a_rels = [a_group.gen(2*i)*a_group.gen(2*i+1)^-1 for i in range(b)]
    b_rels = [b_group.gen(2*i)*b_group.gen(2*i+1)^-1 for i in range(b)]
    g_rels = [g_group.gen(2*i)*g_group.gen(2*i+1)^-1 for i in range(b)]

    ab = seifert_van_kampen(a_group, a_rels, b_group, b_rels, intersect_maps[0], intersect_maps[1], intersect_group)
    ag = seifert_van_kampen(a_group, a_rels, g_group, g_rels, intersect_maps[0], intersect_maps[2], intersect_group)
    bg = seifert_van_kampen(b_group, b_rels, g_group, g_rels, intersect_maps[1], intersect_maps[2], intersect_group)
    print(ab.simplified())
    print(ag.simplified())
    print(bg.simplified())


braids = [[4,5,6,7,2,3,4,5,6,7],[2,3,4,5,6,7], [2, 3, 4, 5, 6, 7, -7, -7, -7, 1, 1, 1, 3, -5, -4]]
SVK_cube(braids, 4)

And this gives the output:

Free Group on generators {x0, x1, x2, x3, x4, x5, x6, x7}
[x0, x1^-1*x2*x1, x1^-1*x3^-1*x4^-1*x3*x1, x1^-1*x3^-1*x5*x3*x1, x1^-1*x3^-1*x6^-1*x3*x1, x1^-1*x3^-1*x7*x3*x1, x1^-1*x3^-1*x1, x1^-1]
Free Group on generators {y0, y1, y2, y3, y4, y5, y6, y7}
[y0, y1^-1*y2*y1, y1^-1*y3^-1*y1, y1^-1*y4*y1, y1^-1*y5^-1*y1, y1^-1*y6*y1, y1^-1*y7^-1*y1, y1^-1]
Free Group on generators {z0, z1, z2, z3, z4, z5, z6, z7}
[(z0*z1^-1*z2*z1)^2*z0^-1*z1^-1*z2^-1*z1*z0^-1, z0*z1^-1*z2*z1*z0*z1^-1*z2^-1*z1*z0^-1, z1^-1*z3^-1*z4^-1*z3*z1, z1^-1*z6*z1, z1^-1*z6^-1*z3^-1*z6*z1, z1^-1*z6^-1*z5*z6*z1, z7*z1^-1*z7^-1, z7*z1*z7^-1*z1^-1*z7^-1]
Finitely presented group < x0, x2 |  >
Finitely presented group < x4, z0 |  >
Finitely presented group < y0, y2 |  >

I have the simplified group printed out for the sake of space, but the next step would be to take a pair of these groups and compute the coproduct again. I don't think I can use the simplified form because I need to know where the generators for b (for example) are sent to into ab and bg, which is lost in the simplified form.

Preview: (hide)

Comments

Could you add an example that uses your function, with a successful first step and an attempt at the second step? For me it would clarify the types of the objects involved.

rburing gravatar imagerburing ( 3 years ago )

@rburing I added an example, hopefully that helps clear up what I'm trying to do.

cgodfrey gravatar imagecgodfrey ( 3 years ago )