예제 #1
0
def taut_polynomial_via_tree_and_smith(tri, angle, cycles = [], alpha = True, mode = "taut"):
    # set up
    assert tri.homology().rank() == 1 # need the polynomial ring to be a PID
    ZH = group_ring(tri, angle, cycles, alpha = alpha, ring = QQ) # ditto
    P = ZH.polynomial_ring()

    ET = edges_to_triangles_matrix(tri, angle, cycles, ZH, P, mode = mode)
    _, non_tree_faces, _ = spanning_dual_tree(tri)

    ET = ET.transpose()
    ET = Matrix([row for i, row in enumerate(ET) if i in non_tree_faces]).transpose()

    # compute via smith normal form
    ETs = ET.smith_form()[0]
    a = tri.countEdges()
    ETs_reduced = Matrix([row[:a] for row in ETs])
    return normalise_poly(ETs_reduced.determinant(), ZH, P)
예제 #2
0
def faces_in_smith(triangulation, angle_structure, cycles):
    N = edge_equation_matrix_taut_reduced(triangulation, angle_structure,
                                          cycles)
    N = Matrix(N)
    N = N.transpose()
    return N.smith_form()
예제 #3
0
def order_of_euler_class(delta, E):
    """
    Given the coboundary operator delta and an Euler two-cocycle E,
    returns k if [E] is k--torsion.  By convention, returns zero if
    [E] is non-torsion.  Note that the trivial element is 1--torsion.
    """

    delta = Matrix(delta)
    E = vector(E)

    # Note that E is a coboundary if there is a one-cocycle C solving
    #
    # E = C*delta
    #
    # We can find C (if it exists at all) using Smith normal form.

    D, U, V = delta.smith_form()
    assert D == U*delta*V

    # So we are trying to solve
    #
    # C*delta = C*U.inverse()*D*V.inverse() = E
    #
    # for a one-cochain C.  Multiply by V to get
    #
    # C*delta*V = C*U.inverse()*D = E*V
    #
    # Now set
    #
    # B = C*U.inverse(), and so B*U = C
    #
    # and rewrite to get
    #
    # B*U*delta*V = B*D = E*V
    #
    # So define E' by:

    Ep = E*V

    # Finally we attempt to solve B * D = Ep.  Note that D is
    # diagonal: so if we can solve all of the equations

    # B[i] * D[i][i] == Ep[i]

    # with B[i] integers, then [E] = 0 in cohomology.

    diag = diagonal(D)

    if any( (diag[i] == 0 and Ep[i] != 0) for i in range(len(Ep)) ):
        return 0

    # All zeros are at the end in Smith normal form.  Since we've
    # passed the above we can now remove them.

    first_zero = diag.index(0)
    diag = diag[:first_zero]
    Ep = Ep[:first_zero]

    # Since diag[i] is (now) never zero we can divide to get the
    # fractions Ep[i]/diag[i] and then find the scaling that makes
    # them simultaneously integral.

    denoms = [ diag[i] / gcd(Ep[i], diag[i]) for i in range(len(Ep)) ]
    return lcm(denoms)