示例#1
0
    def regular_polygon(self, n, exact=True, base_ring=None):
        """
        Return a regular polygon with `n` vertices.

        INPUT:

        - ``n`` -- a positive integer, the number of vertices.

        - ``exact`` -- (boolean, default ``True``) if ``False`` floating point
          numbers are used for coordinates.

        - ``base_ring`` -- a ring in which the coordinates will lie. It is
          ``None`` by default. If it is not provided and ``exact`` is ``True``
          then it will be the field of real algebraic number, if ``exact`` is
          ``False`` it will be the real double field.

        EXAMPLES::

            sage: octagon = polytopes.regular_polygon(8)
            sage: octagon
            A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices
            sage: octagon.n_vertices()
            8
            sage: v = octagon.volume()
            sage: v
            2.828427124746190?
            sage: v == 2*QQbar(2).sqrt()
            True

        Its non exact version::

            sage: polytopes.regular_polygon(3, exact=False).vertices()
            (A vertex at (0.0, 1.0),
             A vertex at (0.8660254038, -0.5),
             A vertex at (-0.8660254038, -0.5))
            sage: polytopes.regular_polygon(25, exact=False).n_vertices()
            25
        """
        n = ZZ(n)
        if n <= 2:
            raise ValueError(
                "n (={}) must be an integer greater than 2".format(n))

        if base_ring is None:
            if exact:
                base_ring = AA
            else:
                base_ring = RDF

        try:
            omega = 2 * base_ring.pi() / n
            verts = [((i * omega).sin(), (i * omega).cos()) for i in range(n)]
        except AttributeError:
            z = QQbar.zeta(n)
            verts = [(base_ring((z**k).imag()), base_ring((z**k).real()))
                     for k in range(n)]

        return Polyhedron(vertices=verts, base_ring=base_ring)
示例#2
0
def _formal_monodromy_from_critical_monomials(critical_monomials, ring):
    r"""
    Compute the formal monodromy matrix of the canonical system of fundamental
    solutions at the origin.

    INPUT:

    - ``critical_monomials``: list of ``FundamentalSolution`` objects ``sol``
      such that, if ``sol = z^(λ+n)·(1 + Õ(z)`` where ``λ`` is the leftmost
      valuation of a group of solutions and ``s`` is another shift of ``λ``
      appearing in the basis, then ``sol.value[s]`` contains the list of
      coefficients of ``z^(λ+s)·log(z)^k/k!``, ``k = 0, 1, ...`` in ``sol``

    - ``ring``

    OUTPUT:

    - the formal monodromy matrix, with coefficients in ``ring``

    - a boolean flag indicating whether the local monodromy is scalar (useful
      when ``ring`` is an inexact ring!)
    """

    mat = matrix.matrix(ring, len(critical_monomials))
    twopii = 2 * pi * QQbar(QQi.gen())
    expo0 = critical_monomials[0].leftmost
    scalar = True

    for j, jsol in enumerate(critical_monomials):

        for i, isol in enumerate(critical_monomials):
            if isol.leftmost != jsol.leftmost:
                continue
            for k, c in enumerate(jsol.value[isol.shift]):
                delta = k - isol.log_power
                if c.is_zero():
                    continue
                if delta >= 0:
                    # explicit conversion sometimes necessary (Sage bug #31551)
                    mat[i, j] += ring(c) * twopii**delta / delta.factorial()
                if delta >= 1:
                    scalar = False

        expo = jsol.leftmost
        if expo != expo0:
            scalar = False
        if expo.parent() is QQ:
            eigv = ring(QQbar.zeta(expo.denominator())**expo.numerator())
        else:
            # conversion via QQbar seems necessary with some number fields
            eigv = twopii.mul(QQbar(expo), hold=True).exp(hold=True)
        eigv = ring(eigv)
        if ring is SR:
            _rescale_col_hold_nontrivial(mat, j, eigv)
        else:
            mat.rescale_col(j, eigv)

    return mat, scalar
示例#3
0
文件: library.py 项目: Findstat/sage
    def regular_polygon(self, n, exact=True, base_ring=None):
        """
        Return a regular polygon with `n` vertices.

        INPUT:

        - ``n`` -- a positive integer, the number of vertices.

        - ``exact`` -- (boolean, default ``True``) if ``False`` floating point
          numbers are used for coordinates.

        - ``base_ring`` -- a ring in which the coordinates will lie. It is
          ``None`` by default. If it is not provided and ``exact`` is ``True``
          then it will be the field of real algebraic number, if ``exact`` is
          ``False`` it will be the real double field.

        EXAMPLES::

            sage: octagon = polytopes.regular_polygon(8)
            sage: octagon
            A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices
            sage: octagon.n_vertices()
            8
            sage: v = octagon.volume()
            sage: v
            2.828427124746190?
            sage: v == 2*QQbar(2).sqrt()
            True

        Its non exact version::

            sage: polytopes.regular_polygon(3, exact=False).vertices()
            (A vertex at (0.0, 1.0),
             A vertex at (0.8660254038, -0.5),
             A vertex at (-0.8660254038, -0.5))
            sage: polytopes.regular_polygon(25, exact=False).n_vertices()
            25
        """
        n = ZZ(n)
        if n <= 2:
            raise ValueError("n (={}) must be an integer greater than 2".format(n))

        if base_ring is None:
            if exact:
                base_ring = AA
            else:
                base_ring = RDF

        try:
            omega = 2*base_ring.pi() / n
            verts = [((i*omega).sin(), (i*omega).cos()) for i in range(n)]
        except AttributeError:
            z = QQbar.zeta(n)
            verts = [(base_ring((z**k).imag()), base_ring((z**k).real())) for k in range(n)]

        return Polyhedron(vertices=verts, base_ring=base_ring)
示例#4
0
def rotation_matrix_angle(r, check=False):
    r"""
    Return the angle of the rotation matrix ``r`` divided by ``2 pi``.

    EXAMPLES::

        sage: from flatsurf.geometry.matrix_2x2 import rotation_matrix_angle

        sage: def rot_matrix(p, q):
        ....:     z = QQbar.zeta(q) ** p
        ....:     c = z.real()
        ....:     s = z.imag()
        ....:     return matrix(AA, 2, [c,-s,s,c])
        sage: [rotation_matrix_angle(rot_matrix(i, 5)) for i in range(1,5)]
        [1/5, 2/5, 3/5, 4/5]
        sage: [rotation_matrix_angle(rot_matrix(i, 5)) for i in range(1,5)]
        [1/5, 2/5, 3/5, 4/5]
        sage: [rotation_matrix_angle(rot_matrix(i,7)) for i in range(1,7)]
        [1/7, 2/7, 3/7, 4/7, 5/7, 6/7]

    Some random tests::

        sage: for _ in range(100):
        ....:     r = QQ.random_element(x=0,y=500)
        ....:     r -= r.floor()
        ....:     m = rot_matrix(r.numerator(), r.denominator())
        ....:     assert rotation_matrix_angle(m) == r

    .. NOTE::

        This is using floating point arithmetic and might be wrong.
    """
    e0, e1 = r.change_ring(CDF).eigenvalues()
    m0 = (e0.log() / 2 / CDF.pi()).imag()
    m1 = (e1.log() / 2 / CDF.pi()).imag()
    r0 = RR(m0).nearby_rational(max_denominator=10000)
    r1 = RR(m1).nearby_rational(max_denominator=10000)
    if r0 != -r1:
        raise RuntimeError
    r0 = r0.abs()
    if r[0][1] > 0:
        return QQ.one() - r0
    else:
        return r0

    if check:
        e = r.change_ring(AA).eigenvalues()[0]
        if e.minpoly() != ZZ['x'].cyclotomic_polynomial()(r.denominator()):
            raise RuntimeError
        z = QQbar.zeta(r.denominator())
        if z**r.numerator() != e:
            raise RuntimeError

    return r
示例#5
0
def rotation_matrix_angle(r, check=False):
    r"""
    Return the angle of the rotation matrix ``r`` divided by ``2 pi``.

    EXAMPLES::

        sage: from flatsurf.geometry.matrix_2x2 import rotation_matrix_angle

        sage: def rot_matrix(p, q):
        ....:     z = QQbar.zeta(q) ** p
        ....:     c = z.real()
        ....:     s = z.imag()
        ....:     return matrix(AA, 2, [c,-s,s,c])
        sage: [rotation_matrix_angle(rot_matrix(i, 5)) for i in range(1,5)]
        [1/5, 2/5, 3/5, 4/5]
        sage: [rotation_matrix_angle(rot_matrix(i,7)) for i in range(1,7)]
        [1/7, 2/7, 3/7, 4/7, 5/7, 6/7]

    Some random tests::

        sage: for _ in range(100):
        ....:     r = QQ.random_element(x=0,y=500)
        ....:     r -= r.floor()
        ....:     m = rot_matrix(r.numerator(), r.denominator())
        ....:     assert rotation_matrix_angle(m) == r

    .. NOTE::

        This is using floating point arithmetic and might be wrong.
    """
    e0,e1 = r.change_ring(CDF).eigenvalues()
    m0 = (e0.log() / 2 / CDF.pi()).imag()
    m1 = (e1.log() / 2 / CDF.pi()).imag()
    r0 = RR(m0).nearby_rational(max_denominator=10000)
    r1 = RR(m1).nearby_rational(max_denominator=10000)
    if r0 != -r1:
        raise RuntimeError
    r0 = r0.abs()
    if r[0][1] > 0:
        return QQ.one() - r0
    else:
        return r0

    if check:
        e = r.change_ring(AA).eigenvalues()[0]
        if e.minpoly() != ZZ['x'].cyclotomic_polynomial()(r.denominator()):
            raise RuntimeError
        z = QQbar.zeta(r.denominator())
        if z**r.numerator() != e:
            raise RuntimeError

    return r