Пример #1
0
    def test_lattice_vector(self):
        g = self.X11.genus()
        J = Jacobian(self.X11)
        Omega = self.X11.riemann_matrix()

        # create a random lattice vector
        alpha = numpy.random.randint(-5,5,g)
        beta = numpy.random.randint(-5,5,g)
        z = alpha + numpy.dot(Omega,beta)
        error = numpy.linalg.norm(J(z))
        self.assertLess(error, 1e-14)
Пример #2
0
    def test_already_reduced(self):
        g = self.X11.genus()
        J = Jacobian(self.X11)

        v = 2*numpy.random.rand(g)
        w = 3*numpy.random.rand(g)
        errorv = numpy.linalg.norm(J(v) - J(J(v)))
        errorw = numpy.linalg.norm(J(v) - J(J(v)))

        self.assertLess(errorv, 1e-14)
        self.assertLess(errorw, 1e-14)
Пример #3
0
def RiemannConstantVector(P, epsilon1=1e-6, epsilon2=1e-8, C=None):
    r"""Evaluate the Riemann constant vector at the place `P`.

    Internally, the value of the RCV at the base place :math:`P_0` of the
    Riemann surface containing :math:`P` is computed and stored. This is done
    because the value of the RCV at any other place can be later computed using
    shift with the Abel map.

    Parameters
    ----------
    P : Place
    epsilon1 : double, optional
        Riemann theta tolerance used in the first pass. Default: ``1e-6``.
    epsilon2 : double, optional
        Tolerance used in all subsequent passes. Default: ``1e-8``.
    C : Divisor, optional
        A canonical divisor on the Riemann surface. Computes one using
        :func:`canonical_divisor` if no such divisor is provided.

    Returns
    -------
    K : array
        The Riemann constant vector at `P`.

    """
    if not isinstance(P, Place):
        raise ValueError('P must be a Place of a Rieamnn surface.')

    # check if C is a canonical divisor if one is provided
    if C is not None:
        degree = C.degree
        n = numpy.array(C.multiplicities)
        if (degree != (2 * P.RS.genus() - 2)) or any(n < 0):
            raise ValueError("Cannot compute Riemann constant vector: given "
                             "divisor %s is not canonical." % C)
        if C.RS != P.RS:
            raise ValueError("Cannot compute Riemann constant vector: the "
                             "place %s and the canonical divisor %s do not "
                             "live on the same Riemann surface." % (P, C))
    else:
        C = canonical_divisor(P.RS)

    # return K0 =K(P0) if P is the base place. otherwise, perform appropriate
    # shift by the abel map
    X = P.RS
    J = Jacobian(X)
    g = numpy.complex(X.genus())
    K0 = compute_K0(X, epsilon1, epsilon2, C)
    if P == X.base_place:
        return K0
    return J(K0 + (g - 1) * AbelMap(P))
Пример #4
0
    def test_half_lattice_vectors(self):
        g = self.X11.genus()
        J = Jacobian(self.X11)
        Omega = self.X11.riemann_matrix()

        # iterate over all possible half lattice vectors
        h1 = list(itertools.product((0,0.5),repeat=g))
        h2 = list(itertools.product((0,0.5),repeat=g))
        for hj in h1:
            hj = numpy.array(hj, dtype=numpy.complex)
            for hk in h2:
                hk = numpy.array(hk, dtype=numpy.complex)
                z = hj + numpy.dot(Omega,hk)
                error = numpy.linalg.norm(J(2*z))
                self.assertLess(error, 1e-14)
Пример #5
0
def half_lattice_vector(X, C, epsilon1, epsilon2):
    r"""Returns an appropriate half-lattice vector for the RCV.

    Parameters
    ----------
    X : RiemannSurface
    C : Divisor
        A canonical divisor on the Riemann surface.

    Returns
    -------
    h : array
    """
    # create the list of all half-lattice vectors
    h = initialize_half_lattice_vectors(X)
    J = Jacobian(X)
    g = X.genus()

    # filter pass #1: D = (g-1)*P0
    D = (g - 1) * X.base_place
    h = half_lattice_filter(h, J, C, D, epsilon=epsilon1)
    if len(h) == 1:
        return h[0].T
    if len(h) == 0:
        raise AssertionError('Filtered out all half-lattice vectors.')

    # filter pass #2: D = sum of g-1 distinct regular places
    places = find_regular_places(X, g - 1)
    D = sum(places)
    h = half_lattice_filter(h, J, C, D, epsilon=epsilon2)
    if len(h) == 1:
        return h[0].T
    if len(h) == 0:
        raise AssertionError('Filtered out all half-lattice vectors.')

    # filter pass #3: iterate over every degree g-1 divisor using the places
    # computed above
    for m in sum_partitions(g - 1):
        D = reduce(lambda a, b: a[0] * a[1] + b[0] * b[1], zip(m, places))
        h = half_lattice_filter(h, J, C, D, epsilon=epsilon2)
        if len(h) == 1:
            return h[0].T
    if len(h) == 0:
        raise AssertionError('Filtered out all half-lattice vectors.')

    raise ValueError('Could not find appropriate lattice vector.')
Пример #6
0
def compute_K0(X, epsilon1, epsilon2, C):
    r"""Determine a base value of the Riemann Constant Vector.

    Given a Riemann surface `RS` and a canonical divisor `C` compute the
    Riemann Constant Vector at the base place.

    Parameters
    ----------
    X : RiemannSurface
    epsilon1, epsilon2 : double
        Numerical accuracy thresholds. See :func:`half_lattice_filter`.
    C : Divisor
        A canonical divisor on the Riemann surface.

    Returns
    -------
    K0 : array
        The value of the RCV at the base place of the Riemann surface.

    """
    h = half_lattice_vector(X, C, epsilon1, epsilon2)
    J = Jacobian(X)
    K0 = J(h - 0.5 * AbelMap(C))
    return K0