コード例 #1
0
    def _hyperbolic_arc(self, z0, z3, first=False):
        """
        Function to construct Bezier path as an approximation to
        the hyperbolic arc between the complex numbers z0 and z3 in the
        hyperbolic plane.
        """
        z0, z3 = (CC(z0), CC(z3))
        p = (abs(z0)*abs(z0)-abs(z3)*abs(z3))/(z0-z3).real()/2
        r = abs(z0-p)

        if abs(z3-z0)/r < 0.1:
            self.path.append([(z0.real(),z0.imag()), (z3.real(),z3.imag())])
            return

        if z0.imag() == 0 and z3.imag() == 0:
            p = (z0.real()+z3.real())/2
            zm = CC(p, r)
            self._hyperbolic_arc(z0, zm, first)
            self._hyperbolic_arc(zm, z3)
            return
        else:
            zm = ((z0+z3)/2-p)/abs((z0+z3)/2-p)*r+p
            t = (8*zm-4*(z0+z3)).imag()/3/(z3-z0).real()
            z1 = z0 + t*CC(z0.imag(), (p-z0.real()))
            z2 = z3 - t*CC(z3.imag(), (p-z3.real()))
        if first:
            self.path.append([(z0.real(), z0.imag()),
                              (z1.real(), z1.imag()),
                              (z2.real(), z2.imag()),
                              (z3.real(), z3.imag())])
            first = False
        else:
            self.path.append([(z1.real(), z1.imag()),
                              (z2.real(), z2.imag()),
                              (z3.real(), z3.imag())])
コード例 #2
0
 def __init__(self, A, B, options):
     A, B = (CC(A), CC(B))
     if A.imag()<0:
         raise ValueError("%s is not a valid point in the UHP model"%(A))
     if B.imag()<0:
         raise ValueError("%s is not a valid point in the UHP model"%(B))
     self.path = []
     self._hyperbolic_arc(A, B, True)
     BezierPath.__init__(self, self.path, options)
     self.A, self.B = (A, B)
コード例 #3
0
    def boundary_point_in_model(self, p):
        r"""
        Check whether a complex number is a real number or ``\infty``.
        In the ``UHP.model_name_name``, this is the ideal boundary of
        hyperbolic space.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: UHP.boundary_point_in_model(1 + I)
            False
            sage: UHP.boundary_point_in_model(infinity)
            True
            sage: UHP.boundary_point_in_model(CC(infinity))
            True
            sage: UHP.boundary_point_in_model(RR(infinity))
            True
            sage: UHP.boundary_point_in_model(1)
            True
            sage: UHP.boundary_point_in_model(12)
            True
            sage: UHP.boundary_point_in_model(1 - I)
            False
            sage: UHP.boundary_point_in_model(-2*I)
            False
            sage: UHP.boundary_point_in_model(0)
            True
            sage: UHP.boundary_point_in_model(I)
            False
        """
        if isinstance(p, HyperbolicPoint):
            return p.is_boundary()
        im = abs(imag(CC(p)).n())
        return (im < EPSILON) or bool(p == infinity)
コード例 #4
0
    def point_in_model(self, p):
        r"""
        Check whether a complex number lies in the open upper half plane.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: UHP.point_in_model(1 + I)
            True
            sage: UHP.point_in_model(infinity)
            False
            sage: UHP.point_in_model(CC(infinity))
            False
            sage: UHP.point_in_model(RR(infinity))
            False
            sage: UHP.point_in_model(1)
            False
            sage: UHP.point_in_model(12)
            False
            sage: UHP.point_in_model(1 - I)
            False
            sage: UHP.point_in_model(-2*I)
            False
            sage: UHP.point_in_model(I)
            True
            sage: UHP.point_in_model(0) # Not interior point
            False
        """
        if isinstance(p, HyperbolicPoint):
            return p.is_boundary()
        return bool(imag(CC(p)) > 0)
コード例 #5
0
ファイル: dft.py プロジェクト: sagemath/sagetrac-mirror
    def fft(self):
        """
        Wraps the gsl ``FastFourierTransform.forward()`` in
        :mod:`~sage.calculus.transforms.fft`.

        If the length is a power of 2 then this automatically uses the
        radix2 method. If the number of sample points in the input is
        a power of 2 then the wrapper for the GSL function
        ``gsl_fft_complex_radix2_forward()`` is automatically called.
        Otherwise, ``gsl_fft_complex_forward()`` is used.

        EXAMPLES::

            sage: J = list(range(5))
            sage: A = [RR(1) for i in J]
            sage: s = IndexedSequence(A,J)
            sage: t = s.fft(); t
            Indexed sequence: [5.00000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000]
                indexed by [0, 1, 2, 3, 4]
        """
        from sage.rings.cc import CC
        I = CC.gen()

        # elements must be coercible into RR
        J = self.index_object()  ## must be = range(N)
        N = len(J)
        S = self.list()
        a = FastFourierTransform(N)
        for i in range(N):
            a[i] = S[i]
        a.forward_transform()
        return IndexedSequence([a[j][0] + I * a[j][1] for j in J], J)
コード例 #6
0
ファイル: phc.py プロジェクト: sagemath/sagetrac-mirror
def get_classified_solution_dicts(output_file_contents,
                                  input_ring,
                                  get_failures=True):
    """
    Return a dictionary of lists of dictionaries of variable:value (key:value)
    pairs.  Only used internally; see the classified_solution_dict function in
    the PHC_Object class definition for details.

    INPUT:

    - output_file_contents -- phc solution output as a string
    - input_ring -- a PolynomialRing that variable names can be coerced into

    OUTPUT:

    - a dictionary of lists if dictionaries of solutions, classifies by type

    EXAMPLES::

        sage: from sage.interfaces.phc import *
        sage: R2.<x1,x2> = PolynomialRing(QQ,2)
        sage: test_sys = [(x1-2)^5-x2, (x2-1)^5-1]
        sage: sol = phc.blackbox(test_sys, R2)          # optional -- phc
        sage: sol_classes = get_classified_solution_dicts(sol.output_file_contents,R2)  # optional -- phc
        sage: len(sol_classes['real'])            # optional -- phc
        1
    """
    output_list = output_file_contents.splitlines()
    solution_dicts = {}
    solution_types = ['complex', 'real', 'failure']
    for sol_type in solution_types:
        solution_dicts[sol_type] = []
    for solution_line in range(len(output_list) - 1, -1, -1):
        if output_list[solution_line].find('THE SOLUTIONS') == 0:
            break
    var_number = int(output_list[solution_line + 2].split(' ')[1])
    # sol_number = int(output_list[solution_line+2].split(' ')[0])
    for i in range(solution_line + 1, len(output_list)):
        if output_list[i].count('the solution for t') == 1:
            phc_type = output_list[i + var_number + 1].split(' = ')[-1]
            if phc_type.find('complex') != -1:
                phc_type = 'complex'
            elif phc_type.find('real') != -1:
                phc_type = 'real'
            else:
                phc_type = 'failure'
            temp_dict = {}
            for j in range(1, var_number + 1):
                rawsplit = output_list[i + j].split(': ')[1].split(' ')
                for extras in range(rawsplit.count('')):
                    rawsplit.remove('')
                temp_var = output_list[i + j].split(': ')[0].replace(' ', '')
                if phc_type == 'real':
                    temp_dict[input_ring(temp_var)] = RR(rawsplit[0])
                else:
                    temp_dict[input_ring(temp_var)] = CC(
                        rawsplit[0], rawsplit[1])
            solution_dicts[phc_type].append(temp_dict)
    return solution_dicts
コード例 #7
0
ファイル: airy.py プロジェクト: sagemath/sagetrac-mirror
    def _evalf_(self, x, **kwargs):
        """
        EXAMPLES::

            sage: from sage.functions.airy import airy_ai_simple
            sage: airy_ai_simple(0.0)
            0.355028053887817
            sage: airy_ai_simple(1.0 * I)
            0.331493305432141 - 0.317449858968444*I

        We can use several methods for numerical evaluation::

            sage: airy_ai_simple(3).n(algorithm='mpmath')
            0.00659113935746072
            sage: airy_ai_simple(3).n(algorithm='mpmath', prec=100)
            0.0065911393574607191442574484080
            sage: airy_ai_simple(3).n(algorithm='scipy')  # rel tol 1e-10
            0.006591139357460719
            sage: airy_ai_simple(I).n(algorithm='scipy')  # rel tol 1e-10
            0.33149330543214117 - 0.3174498589684438*I

        TESTS::

            sage: parent(airy_ai_simple(3).n(algorithm='scipy'))
            Real Field with 53 bits of precision
            sage: airy_ai_simple(3).n(algorithm='scipy', prec=200)
            Traceback (most recent call last):
            ...
            NotImplementedError: airy_ai not implemented for precision > 53
        """
        algorithm = kwargs.get('algorithm', 'mpmath') or 'mpmath'
        parent = kwargs.get('parent')
        if algorithm == 'scipy':
            if hasattr(parent, 'prec') and parent.prec() > 53:
                raise NotImplementedError("%s not implemented for precision > 53" % self.name())
            from sage.rings.real_mpfr import RR
            from sage.rings.cc import CC
            from sage.functions.other import real, imag
            from scipy.special import airy as airy
            if x in RR:
                y = airy(real(x))[0]
                if parent is None:
                    return RR(y)
            else:
                y = airy(complex(real(x), imag(x)))[0]
                if parent is None:
                    return CC(y)
            return parent(y)
        elif algorithm == 'mpmath':
            import mpmath
            from sage.libs.mpmath import utils as mpmath_utils
            return mpmath_utils.call(mpmath.airyai, x, parent=parent)
        else:
            raise ValueError("unknown algorithm '%s'" % algorithm)
コード例 #8
0
ファイル: airy.py プロジェクト: sagemath/sagetrac-mirror
    def _evalf_(self, x, **kwargs):
        """
        EXAMPLES::

            sage: from sage.functions.airy import airy_bi_simple
            sage: airy_bi_simple(0.0)
            0.614926627446001
            sage: airy_bi_simple(1.0 * I)
            0.648858208330395 + 0.344958634768048*I

        We can use several methods for numerical evaluation::

            sage: airy_bi_simple(3).n(algorithm='mpmath')
            14.0373289637302
            sage: airy_bi_simple(3).n(algorithm='mpmath', prec=100)
            14.037328963730232031740267314
            sage: airy_bi_simple(3).n(algorithm='scipy')  # rel tol 1e-10
            14.037328963730136
            sage: airy_bi_simple(I).n(algorithm='scipy')  # rel tol 1e-10
            0.648858208330395 + 0.34495863476804844*I

        TESTS::

            sage: parent(airy_bi_simple(3).n(algorithm='scipy'))
            Real Field with 53 bits of precision
            sage: airy_bi_simple(3).n(algorithm='scipy', prec=200)
            Traceback (most recent call last):
            ...
            NotImplementedError: airy_bi not implemented for precision > 53
        """
        algorithm = kwargs.get('algorithm', 'mpmath') or 'mpmath'
        parent = kwargs.get('parent', None)
        if algorithm == 'scipy':
            if hasattr(parent, 'prec') and parent.prec() > 53:
                raise NotImplementedError("%s not implemented for precision > 53" % self.name())
            from sage.rings.real_mpfr import RR
            from sage.rings.cc import CC
            from sage.functions.other import real, imag
            from scipy.special import airy as airy
            if x in RR:
                y = airy(real(x))[2]
                if parent is None:
                    return RR(y)
            else:
                y = airy(complex(real(x), imag(x)))[2]
                if parent is None:
                    return CC(y)
            return parent(y)
        elif algorithm == 'mpmath':
            import mpmath
            from sage.libs.mpmath import utils as mpmath_utils
            return mpmath_utils.call(mpmath.airybi, x, parent=parent)
        else:
            raise ValueError("unknown algorithm '%s'" % algorithm)
コード例 #9
0
ファイル: airy.py プロジェクト: sagemath/sagetrac-mirror
    def _evalf_(self, x, **kwargs):
        """
        EXAMPLES::

            sage: airy_bi_prime(0.0)
            0.448288357353826

        We can use several methods for numerical evaluation::

            sage: airy_bi_prime(4).n(algorithm='mpmath')
            161.926683504613
            sage: airy_bi_prime(4).n(algorithm='mpmath', prec=100)
            161.92668350461340184309492429
            sage: airy_bi_prime(4).n(algorithm='scipy')  # rel tol 1e-10
            161.92668350461398
            sage: airy_bi_prime(I).n(algorithm='scipy')  # rel tol 1e-10
            0.135026646710819 - 0.1288373867812549*I

        TESTS::

            sage: parent(airy_bi_prime(3).n(algorithm='scipy'))
            Real Field with 53 bits of precision
            sage: airy_bi_prime(3).n(algorithm='scipy', prec=200)
            Traceback (most recent call last):
            ...
            NotImplementedError: airy_bi_prime not implemented
             for precision > 53
        """
        algorithm = kwargs.get('algorithm', 'mpmath') or 'mpmath'
        parent = kwargs.get('parent', None)
        if algorithm == 'scipy':
            if hasattr(parent, 'prec') and parent.prec() > 53:
                raise NotImplementedError("%s not implemented for precision > 53" % self.name())
            from sage.rings.real_mpfr import RR
            from sage.rings.cc import CC
            from sage.functions.other import real, imag
            from scipy.special import airy as airy
            if x in RR:
                y = airy(real(x))[3]
                if parent is None:
                    return RR(y)
            else:
                y = airy(complex(real(x), imag(x)))[3]
                if parent is None:
                    return CC(y)
            return parent(y)
        elif algorithm == 'mpmath':
            import mpmath
            from sage.libs.mpmath import utils as mpmath_utils
            return mpmath_utils.call(mpmath.airybi, x, derivative=1,
                                     parent=parent)
        else:
            raise ValueError("unknown algorithm '%s'" % algorithm)
コード例 #10
0
ファイル: airy.py プロジェクト: sagemath/sagetrac-mirror
    def _evalf_(self, x, **kwargs):
        """
        EXAMPLES::

            sage: airy_ai_prime(0.0)
            -0.258819403792807

        We can use several methods for numerical evaluation::

            sage: airy_ai_prime(4).n(algorithm='mpmath')
            -0.00195864095020418
            sage: airy_ai_prime(4).n(algorithm='mpmath', prec=100)
            -0.0019586409502041789001381409184
            sage: airy_ai_prime(4).n(algorithm='scipy')    # rel tol 1e-10
            -0.00195864095020418
            sage: airy_ai_prime(I).n(algorithm='scipy')    # rel tol 1e-10
            -0.43249265984180707 + 0.09804785622924324*I

        TESTS::

            sage: parent(airy_ai_prime(3).n(algorithm='scipy'))
            Real Field with 53 bits of precision
            sage: airy_ai_prime(3).n(algorithm='scipy', prec=200)
            Traceback (most recent call last):
            ...
            NotImplementedError: airy_ai_prime not implemented
             for precision > 53
        """
        algorithm = kwargs.get('algorithm', 'mpmath') or 'mpmath'
        parent = kwargs.get('parent', None)
        if algorithm == 'scipy':
            if hasattr(parent, 'prec') and parent.prec() > 53:
                raise NotImplementedError("%s not implemented for precision > 53" % self.name())
            from sage.rings.real_mpfr import RR
            from sage.rings.cc import CC
            from sage.functions.other import real, imag
            from scipy.special import airy as airy
            if x in RR:
                y = airy(real(x))[1]
                if parent is None:
                    return RR(y)
            else:
                y = airy(complex(real(x), imag(x)))[1]
                if parent is None:
                    return CC(y)
            return parent(y)
        elif algorithm == 'mpmath':
            import mpmath
            from sage.libs.mpmath import utils as mpmath_utils
            return mpmath_utils.call(mpmath.airyai, x, derivative=1,
                                     parent=parent)
        else:
            raise ValueError("unknown algorithm '%s'" % algorithm)
コード例 #11
0
ファイル: phc.py プロジェクト: sagemath/sagetrac-mirror
def get_solution_dicts(output_file_contents, input_ring, get_failures=True):
    """
    Return a list of dictionaries of variable:value (key:value)
    pairs.  Only used internally; see the solution_dict function in
    the PHC_Object class definition for details.

    INPUT:

    - output_file_contents -- phc solution output as a string
    - input_ring -- a PolynomialRing that variable names can be coerced into

    OUTPUT:

    a list of dictionaries of solutions

    EXAMPLES::

        sage: from sage.interfaces.phc import *
        sage: R2.<x1,x2> = PolynomialRing(QQ,2)
        sage: test_sys = [(x1-1)^5-x2, (x2-1)^5-1]
        sage: sol = phc.blackbox(test_sys, R2)             # optional -- phc
        sage: test = get_solution_dicts(sol.output_file_contents,R2)  # optional -- phc
        sage: str(sum([q[x1].real() for q in test]))[0:4]  # optional -- phc
        '25.0'
    """
    output_list = output_file_contents.splitlines()
    solution_dicts = []
    for solution_line in range(len(output_list) - 1, -1, -1):
        if output_list[solution_line].find('THE SOLUTIONS') == 0:
            break
    try:
        var_number = int(output_list[solution_line + 2].split(' ')[1])
        # sol_number = int(output_list[solution_line+2].split(' ')[0])
    except IndexError:
        var_number = int(output_list[solution_line + 1].split(' ')[1])
        # sol_number = int(output_list[solution_line+1].split(' ')[0])
    for i in range(solution_line + 1, len(output_list)):
        if output_list[i].count('the solution for t') == 1:
            if output_list[i - 3].count('success') > 0 or get_failures:
                temp_dict = {}
                for j in range(1, var_number + 1):
                    rawsplit = output_list[i + j].split(': ')[1].split(' ')
                    for extras in range(rawsplit.count('')):
                        rawsplit.remove('')
                    temp_var = output_list[i + j].split(': ')[0].replace(
                        ' ', '')
                    temp_dict[input_ring(temp_var)] = CC(
                        rawsplit[0], rawsplit[1])
                solution_dicts.append(temp_dict)
    return solution_dicts
コード例 #12
0
    def boundary_point_in_model(self, p):
        r"""
        Check whether a complex number lies in the open unit disk.

        EXAMPLES::

            sage: PD = HyperbolicPlane().PD()
            sage: PD.boundary_point_in_model(1.00)
            True
            sage: PD.boundary_point_in_model(1/2 + I/2)
            False
            sage: PD.boundary_point_in_model(1 + .2*I)
            False
        """
        if isinstance(p, HyperbolicPoint):
            return p.is_boundary()
        return bool(abs(abs(CC(p)) - 1) < EPSILON)
コード例 #13
0
    def __init__(self, pts, options):
        """
        Initialize HyperbolicPolygon.

        EXAMPLES::

            sage: from sage.plot.hyperbolic_polygon import HyperbolicPolygon
            sage: print(HyperbolicPolygon([0, 1/2, I], {}))
            Hyperbolic polygon (0.000000000000000, 0.500000000000000, 1.00000000000000*I)
        """
        pts = [CC(_) for _ in pts]
        self.path = []
        self._hyperbolic_arc(pts[0], pts[1], True)
        for i in range(1, len(pts) - 1):
            self._hyperbolic_arc(pts[i], pts[i + 1])
        self._hyperbolic_arc(pts[-1], pts[0])
        BezierPath.__init__(self, self.path, options)
        self._pts = pts
コード例 #14
0
    def show(self, boundary=True, **options):
        r"""
        Plot ``self``.

        EXAMPLES::

            sage: HyperbolicPlane().PD().get_point(0).show()
            Graphics object consisting of 2 graphics primitives
            sage: HyperbolicPlane().KM().get_point((0,0)).show()
            Graphics object consisting of 2 graphics primitives
            sage: HyperbolicPlane().HM().get_point((0,0,1)).show()
            Graphics3d Object
        """
        p = self.coordinates()
        if p == infinity:
            raise NotImplementedError("can't draw the point infinity")

        opts = {'axes': False, 'aspect_ratio': 1}
        opts.update(self.graphics_options())
        opts.update(options)

        from sage.plot.point import point
        from sage.misc.functional import numerical_approx

        if self._bdry:  # It is a boundary point
            p = numerical_approx(p)
            pic = point((p, 0), **opts)
            if boundary:
                bd_pic = self._model.get_background_graphic(bd_min=p - 1,
                                                            bd_max=p + 1)
                pic = bd_pic + pic
        else:  # It is an interior point
            if p in RR:
                p = CC(p)
            elif hasattr(p, 'items') or hasattr(p, '__iter__'):
                p = [numerical_approx(k) for k in p]
            else:
                p = numerical_approx(p)
            pic = point(p, **opts)
            if boundary:
                bd_pic = self.parent().get_background_graphic()
                pic = bd_pic + pic
        return pic
コード例 #15
0
    def __init__(self, sides, i_angle, center, options):
        """
        Initialize HyperbolicRegularPolygon.

        EXAMPLES::

            sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
            sage: print(HyperbolicRegularPolygon(5,pi/2,I, {}))
            Hyperbolic regular polygon (sides=5, i_angle=1/2*pi, center=1.00000000000000*I)
        """
        self.center = CC(center)
        if self.center.imag() <= 0:
            raise ValueError(
                "center: %s is not a valid point in the upper half plane model of the hyperbolic plane"
                % (self.center))
        if sides < 3:
            raise ValueError(
                "degenerated polygons (sides<=2) are not supported")
        if i_angle <= 0 or i_angle >= pi:
            raise ValueError("interior angle %s must be in (0, pi) interval" %
                             (i_angle))
        if pi * (sides - 2) - sides * i_angle <= 0:
            raise ValueError(
                "there exists no hyperbolic regular compact polygon, for sides=%s the interior angle must be less than %s"
                % (sides, pi * (sides - 2) / sides))
        self.sides = sides
        self.i_angle = i_angle
        beta = 2 * pi / self.sides  # compute the rotation angle to be used ahead
        alpha = self.i_angle / Integer(2)
        I = CC(0, 1)
        # compute using cosine theorem the radius of the circumscribed circle
        # using the triangle formed by the radius and the three known angles
        r = arccosh(cot(alpha) * (1 + cos(beta)) / sin(beta))

        # The first point will be always on the imaginary axis limited
        # to 8 digits for efficiency in the subsequent calculations.
        z_0 = [I * (e**r).n(digits=8)]

        # Compute the dilation isometry used to move the center
        # from I to the imaginary part of the given center.
        scale = self.center.imag()

        # Compute the parabolic isometry to move the center to the
        # real part of the given center.
        h_disp = self.center.real()

        d_z_k = [z_0[0] * scale + h_disp
                 ]  #d_k has the points for the polygon in the given center
        z_k = z_0  #z_k has the Re(z)>0 vertices for the I centered polygon
        r_z_k = []  #r_z_k has the Re(z)<0 vertices
        if is_odd(self.sides):
            vert = (self.sides - 1) // 2
        else:
            vert = self.sides // 2 - 1
        for k in range(vert):
            # Compute with 8 digits to accelerate calculations
            new_z_k = self._i_rotation(z_k[-1], beta).n(digits=8)
            z_k = z_k + [new_z_k]
            d_z_k = d_z_k + [new_z_k * scale + h_disp]
            r_z_k = [-(new_z_k).conjugate() * scale + h_disp] + r_z_k
        if is_odd(self.sides):
            HyperbolicPolygon.__init__(self, d_z_k + r_z_k, options)
        else:
            z_opo = [I * (e**(-r)).n(digits=8) * scale + h_disp]
            HyperbolicPolygon.__init__(self, d_z_k + z_opo + r_z_k, options)
コード例 #16
0
from sage.rings.integer_ring import ZZ
from sage.rings.real_mpfr import RR
from sage.rings.real_double import RDF
from sage.rings.complex_mpfr import ComplexField, is_ComplexNumber
from sage.rings.cc import CC
from sage.rings.real_mpfr import (RealField, is_RealNumber)

from sage.symbolic.function import GinacFunction, BuiltinFunction

import sage.libs.mpmath.utils as mpmath_utils
from sage.combinat.combinat import bernoulli_polynomial

from .gamma import psi
from .other import factorial

I = CC.gen(0)


class Function_zeta(GinacFunction):
    def __init__(self):
        r"""
        Riemann zeta function at s with s a real or complex number.

        INPUT:

        -  ``s`` - real or complex number

        If s is a real number the computation is done using the MPFR
        library. When the input is not real, the computation is done using
        the PARI C library.
コード例 #17
0
def smallest_dynamical(f, dynatomic=True, start_n=1, prec=53, emb=None, algorithm='HS', check_minimal=True):
    r"""
    Determine the poly with smallest coefficients in `SL(2,\ZZ)` orbit of ``F``

    Smallest is in the sense of global height.
    The method is the algorithm in Hutz-Stoll [HS2018]_.
    A binary form defining the periodic points is associated to ``f``.
    From this polynomial a bound on the search space can be determined.

    ``f`` should already be a minimal model or finding the orbit
    representatives may give wrong results.

    INPUT:

    - ``f`` -- a dynamical system on `P^1`

    - ``dynatomic`` -- boolean. whether ``F`` is the periodic points or the
      formal periodic points of period ``m`` for ``f``

    - ``start_n`` - positive integer. the period used to start trying to
      create associate binary form ``F``

    - ``prec``-- positive integer. precision to use in CC

    - ``emb`` -- embedding into CC

    - ``algorithm`` -- (optional) string; either ``'BM'`` for the Bruin-Molnar
      algorithm or ``'HS'`` for the Hutz-Stoll algorithm. If not specified,
      properties of the map are utilized to choose how to compute minimal
      orbit representatives

    - ``check_minimal`` -- (default: True), boolean, whether to check
      if this map is a minimal model

    OUTPUT: pair [dynamical system, matrix]

    EXAMPLES::

        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import smallest_dynamical
        sage: P.<x,y> = ProjectiveSpace(QQ,1)
        sage: f = DynamicalSystem([50*x^2 + 795*x*y + 2120*y^2, 265*x^2 + 106*y^2])
        sage: smallest_dynamical(f)  #long time
        [
        Dynamical System of Projective Space of dimension 1 over Rational Field
          Defn: Defined on coordinates by sending (x : y) to
                (-480*x^2 - 1125*x*y + 1578*y^2 : 265*x^2 + 1060*x*y + 1166*y^2),
        <BLANKLINE>
        [1 2]
        [0 1]
        ]
    """
    def insert_item(pts, item, index):
        # binary insertion to maintain list of points left to consider
        N = len(pts)
        if N == 0:
          return [item]
        elif N == 1:
            if item[index] > pts[0][index]:
                pts.insert(0,item)
            else:
                pts.append(item)
            return pts
        else: # binary insertion
            left = 1
            right = N
            mid = (left + right) // 2  # these are ints so this is .floor()
            if item[index] > pts[mid][index]: # item goes into first half
                return insert_item(pts[:mid], item, index) + pts[mid:N]
            else: # item goes into second half
                return pts[:mid] + insert_item(pts[mid:N], item, index)

    def coshdelta(z):
        # The cosh of the hyperbolic distance from z = t+uj to j
        return (z.norm() + 1)/(2*z.imag())

    # can't be smaller if height 0
    f.normalize_coordinates()
    if f.global_height(prec=prec) == 0:
        return [f, matrix(ZZ,2,2,[1,0,0,1])]
    all_min = f.all_minimal_models(return_transformation=True, algorithm=algorithm, check_minimal=check_minimal)

    current_min = None
    current_size = None
    # search for minimum over all orbits
    for g,M in all_min:
        PS = g.domain()
        CR = PS.coordinate_ring()
        x,y = CR.gens()
        n = start_n # sometimes you get a problem later with 0,infty as roots
        if dynatomic:
            pts_poly = g.dynatomic_polynomial(n)
        else:
            gn = g.nth_iterate_map(n)
            pts_poly = y*gn[0] - x*gn[1]
        d = ZZ(pts_poly.degree())
        max_mult = max([ex for p,ex in pts_poly.factor()])
        while ((d < 3) or (max_mult >= d/2) and (n < 5)):
            n = n+1
            if dynatomic:
                pts_poly = g.dynatomic_polynomial(n)
            else:
                gn = g.nth_iterate_map(n)
                pts_poly = y*gn[0] - x*gn[1]
            d = ZZ(pts_poly.degree())
            max_mult = max([ex for p,ex in pts_poly.factor()])
        assert(n<=4), "n > 4, failed to find usable poly"

        R = get_bound_dynamical(pts_poly, g, m=n, dynatomic=dynatomic, prec=prec, emb=emb)
        # search starts in fundamental domain
        G,MG = pts_poly.reduced_form(prec=prec, emb=emb, smallest_coeffs=False)
        red_g = f.conjugate(M*MG)
        if G != pts_poly:
            R2 = get_bound_dynamical(G, red_g, m=n, dynatomic=dynatomic, prec=prec, emb=emb)
            if R2 < R:
                # use the better bound
                R = R2
        red_g.normalize_coordinates()
        if red_g.global_height(prec=prec) == 0:
            return [red_g, M*MG]

        # height
        if current_size is None:
            current_size = e**red_g.global_height(prec=prec)
        v0, th = covariant_z0(G, prec=prec, emb=emb)
        rep = 2*CC.gen(0)
        from math import isnan
        if isnan(v0.abs()):
            raise ValueError("invalid covariant: %s"%v0)

        # get orbit
        S = matrix(ZZ,2,2,[0,-1,1,0])
        T = matrix(ZZ,2,2,[1,1,0,1])
        TI = matrix(ZZ,2,2,[1,-1,0,1])

        count = 0
        pts = [[G, red_g, v0, rep, M*MG, coshdelta(v0), 0]]  # label - 0:None, 1:S, 2:T, 3:T^(-1)
        if current_min is None:
            current_min = [G, red_g, v0, rep, M*MG, coshdelta(v0)]
        while pts != []:
            G, g, v, rep, M, D, label = pts.pop()
            # apply ST and keep z, Sz
            if D > R:
                break #all remaining pts are too far away
            # check if it is smaller. If so, we can improve the bound
            count += 1
            new_size = e**g.global_height(prec=prec)
            if new_size < current_size:
                current_min = [G ,g, v, rep, M, coshdelta(v)]
                current_size = new_size
                if new_size == 1: # early exit
                    return [current_min[1], current_min[4]]
                new_R = get_bound_dynamical(G, g, m=n, dynatomic=dynatomic, prec=prec, emb=emb)
                if new_R < R:
                    R = new_R

            # add new points to check
            if label != 1 and min((rep+1).norm(), (rep-1).norm()) >= 1: # don't undo S
                # the 2nd condition is equivalent to |\Re(-1/rep)| <= 1/2
                # this means that rep can have resulted from an inversion step in
                # the shift-and-invert procedure, so don't invert

                # do inversion
                z = -1/v
                new_pt = [G.subs({x:-y, y:x}), g.conjugate(S), z, -1/rep, M*S, coshdelta(z), 1]
                pts = insert_item(pts, new_pt, 5)
            if label != 3:  # don't undo T on g
                # do right shift
                z = v-1
                new_pt = [G.subs({x:x+y}), g.conjugate(TI), z, rep-1, M*TI, coshdelta(z), 2]
                pts = insert_item(pts, new_pt, 5)
            if label != 2:  # don't undo TI on g
                # do left shift
                z = v+1
                new_pt = [G.subs({x:x-y}), g.conjugate(T), z, rep+1, M*T, coshdelta(z), 3]
                pts = insert_item(pts, new_pt, 5)

    return [current_min[1], current_min[4]]
コード例 #18
0
ファイル: lseries.py プロジェクト: sagemath/sagetrac-mirror
    def __call__(self, s, prec=53):
        """
        Evaluate this complex `L`-series at `s`.

        INPUT:

        - ``s`` -- complex number

        - ``prec`` -- integer (default: 53) the number of bits of precision
          used in computing the lseries of the newforms.

        OUTPUT:

        a complex number L(A, s).

        EXAMPLES::

            sage: L = J0(23).lseries()
            sage: L(1)
            0.248431866590600
            sage: L(1, prec=100)
            0.24843186659059968120725033931

            sage: L = J0(389)[0].lseries()
            sage: L(1) # long time (2s) abstol 1e-10
            -1.33139759782370e-19
            sage: L(1, prec=100) # long time (2s) abstol 1e-20
            6.0129758648142797032650287762e-39
            sage: L.rational_part()
            0

            sage: L = J1(23)[0].lseries()
            sage: L(1)
            0.248431866590600

            sage: J = J0(11) * J1(11)
            sage: J.lseries()(1)
            0.0644356903227915

            sage: L = JH(17,[2]).lseries()
            sage: L(1)
            0.386769938387780

        """
        abelian_variety = self.abelian_variety()
        # Check for easy dimension zero case
        if abelian_variety.dimension() == 0:
            return CC(1)
        try:
            factors = self.__factors[prec]
            return prod(L(s) for L in factors)
        except AttributeError:
            self.__factors = {}
        except KeyError:
            pass
        abelian_variety = self.abelian_variety()
        newforms = abelian_variety.newform_decomposition('a')

        factors = [
            newform.lseries(embedding=i, prec=prec) for newform in newforms
            for i in range(newform.base_ring().degree())
        ]
        self.__factors[prec] = factors

        return prod(L(s) for L in factors)
コード例 #19
0
ファイル: phc.py プロジェクト: sagemath/sagetrac-mirror
    def _parse_path_file(self, input_filename, verbose=False):
        """
        Takes a phpack output file containing path tracking information
        and parses it into a list of lists of dictionaries - i.e. a
        list of solutions paths, where each solution path is a list of
        dictionaries of variable and homotopy parameter values.

        INPUT:

        - input_filename -- file must have path-tracking information

        OUTPUT:

        - a list of lists of dictionaries, described above

        EXAMPLES::

            sage: from sage.interfaces.phc import *
            sage: R2.<x,y> = PolynomialRing(QQ,2)
            sage: start_sys = [x^5-y^2,y^5-1]
            sage: sol = phc.blackbox(start_sys, R2)    # optional -- phc
            sage: start_save = sol.save_as_start()     # optional -- phc
            sage: end_sys = [x^5-2,y^5-x^2]            # optional -- phc
            sage: path_track_filename = phc._path_track_file(start_save, end_sys, R2, c_skew = .001)  # optional -- phc
            sage: sol_paths = phc._parse_path_file(path_track_filename)   # optional -- phc
            sage: len(sol_paths)  # optional -- phc
            25
        """

        if not os.path.exists(input_filename):
            raise RuntimeError("The file containing output from phc (" +
                               input_filename + ") cannot be found")

        fh = open(input_filename)
        line_idx = 0
        begin = 0
        count = 0
        solutions_dicts = []
        steps_dicts = []

        # regular expressions for matching certain output types
        var_cnt_regex = re.compile('^ +([0-9]+)')
        output_regex = re.compile('^OUTPUT INFORMATION DURING')
        t_regex = re.compile(
            r'(^t +: +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+) +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+)$)',
            re.IGNORECASE)
        sols_regex = re.compile(
            r'(^ *(([a-z]|[0-9])+) +: +(-?[0-9]+\.[0-9]+E[-+][0-9]+) +(-?[0-9]+\.[0-9]+E[-+][0-9]+)$)',
            re.IGNORECASE)
        complete_regex = re.compile('^TIMING INFORMATION')

        breakfast = False
        a_line = fh.readline()
        end_test = ''
        while a_line:
            # processing....
            a_line = a_line.replace("\n", '')
            if line_idx == 0:
                m = var_cnt_regex.match(a_line)
                if m:
                    count = Integer(m.group(1))
            if count > 0:
                m = output_regex.match(a_line)
                if m:
                    begin = 1
                if begin:
                    m = t_regex.match(a_line)
                    if m:
                        # put the t-values into a dict
                        # m.group(2) contains the real val
                        # m.group(3) contains the imaginary val
                        # fh_w.write( "T=> G1(" + m.group(2) + '),G2(' + m.group(3) + ")\n")
                        # read off two lines - this should be 'm' and 'the solution for t :'
                        a_line = fh.readline()
                        end_test = a_line  # store this to check for end of solution
                        a_line = fh.readline()
                        t_val = CC(m.group(2), m.group(3))
                        temp_dict = {}
                        temp_dict["t"] = t_val
                        for i in range(0, count):
                            a_line = fh.readline()
                            m = sols_regex.match(a_line)
                            if m:
                                # m.group(2) contains our var name
                                # m.group(4) contains our real val
                                # m.group(5) contains our imaginary val
                                temp_dict[m.group(2)] = CC(
                                    m.group(4), m.group(5))
                        steps_dicts.append(temp_dict)
                    # check if its the end of a solution
                    if end_test.find('Length of path') != -1:
                        if verbose:
                            print("recording sol")
                        if steps_dicts != []:
                            solutions_dicts.append(steps_dicts)
                        steps_dicts = []
                    m = complete_regex.match(a_line)
                    if m:
                        breakfast = True
            if breakfast:
                break
            line_idx += 1
            a_line = fh.readline()
        fh.close()
        return solutions_dicts
コード例 #20
0
def julia_plot(f=None, **kwds):
    r"""
    Plots the Julia set of a given polynomial ``f``. Users can specify whether
    they would like to display the Mandelbrot side by side with the Julia set
    with the ``mandelbrot`` argument. If ``f`` is not specified, this method
    defaults to `f(z) = z^2-1`.

    The Julia set of a polynomial ``f`` is the set of complex numbers `z` for
    which the function `f(z)` is bounded under iteration. The Julia set can
    be visualized by plotting each point in the set in the complex plane.
    Julia sets are examples of fractals when plotted in the complex plane.

    ALGORITHM:

    Let `R_c = \bigl(1 + \sqrt{1 + 4|c|}\bigr)/2` if the polynomial is of the
    form `f(z) = z^2 + c`; otherwise, let `R_c = 2`.
    For every `p \in \mathbb{C}`, if `|f^{k}(p)| > R_c` for some `k \geq 0`,
    then `f^{n}(p) \to \infty`.  Let `N` be the maximum number of iterations.
    Compute the first `N` points on the orbit of `p` under `f`. If for
    any `k < N`, `|f^{k}(p)| > R_c`, we stop the iteration and assign a color
    to the point `p` based on how quickly `p` escaped to infinity under
    iteration of `f`. If `|f^{i}(p)| \leq R_c` for all `i \leq N`, we assume
    `p` is in the Julia set and assign the point `p` the color black.

    INPUT:

    - ``f`` -- input polynomial (optional - default: ``z^2 - 1``).

    - ``period`` -- list (optional - default: ``None``), returns the Julia set
      for a random `c` value with the given (formal) cycle structure.

    - ``mandelbrot`` -- boolean (optional - default: ``True``), when set to
      ``True``, an image of the Mandelbrot set is appended to the right of the
      Julia set.

    - ``point_color`` -- RGB color (optional - default: ``'tomato'``),
      color of the point `c` in the Mandelbrot set (any valid input for Color).

    - ``x_center`` -- double (optional - default: ``-1.0``), Real part
      of center point.

    - ``y_center`` -- double (optional - default: ``0.0``), Imaginary part
      of center point.

    - ``image_width`` -- double (optional - default: ``4.0``), width of image
      in the complex plane.

    - ``max_iteration`` -- long (optional - default: ``500``), maximum number
      of iterations the map `f(z)`.

    - ``pixel_count`` -- long (optional - default: ``500``), side length of
      image in number of pixels.

    - ``base_color`` -- hex color (optional - default: ``'steelblue'``), color
      used to determine the coloring of set (any valid input for Color).

    - ``level_sep`` -- long (optional - default: 1), number of iterations
      between each color level.

    - ``number_of_colors`` -- long (optional - default: 30), number of colors
      used to plot image.

    - ``interact`` -- boolean (optional - default: ``False``), controls whether
      plot will have interactive functionality.

    OUTPUT:

    24-bit RGB image of the Julia set in the complex plane.

    .. TODO::

        Implement the side-by-side Mandelbrot-Julia plots for general one-parameter families
        of polynomials.

    EXAMPLES:

    The default ``f`` is `z^2 - 1`::

        sage: julia_plot()
        1001x500px 24-bit RGB image

    To display only the Julia set, set ``mandelbrot`` to ``False``::

        sage: julia_plot(mandelbrot=False)
        500x500px 24-bit RGB image

    ::

        sage: R.<z> = CC[]
        sage: f = z^3 - z + 1
        sage: julia_plot(f)
        500x500px 24-bit RGB image

    To display an interactive plot of the Julia set in the Notebook,
    set ``interact`` to ``True``. (This is only implemented for polynomials of
    the form ``f = z^2 + c``)::

        sage: julia_plot(interact=True)
        interactive(children=(FloatSlider(value=-1.0, description='Real c'...

        ::

        sage: R.<z> = CC[]
        sage: f = z^2 + 1/2
        sage: julia_plot(f,interact=True)
        interactive(children=(FloatSlider(value=0.5, description='Real c'...

    To return the Julia set of a random `c` value with (formal) cycle structure
    `(2,3)`, set ``period = [2,3]``::

        sage: julia_plot(period=[2,3])
        1001x500px 24-bit RGB image

    To return all of the Julia sets of `c` values with (formal) cycle structure
    `(2,3)`::

        sage: period = [2,3] # not tested
        ....: R.<c> = QQ[]
        ....: P.<x,y> = ProjectiveSpace(R,1)
        ....: f = DynamicalSystem([x^2+c*y^2, y^2])
        ....: L = f.dynatomic_polynomial(period).subs({x:0,y:1}).roots(ring=CC)
        ....: c_values = [k[0] for k in L]
        ....: for c in c_values:
        ....:     julia_plot(c)

    Polynomial maps can be defined over a polynomial ring or a fraction field,
    so long as ``f`` is polynomial::

        sage: R.<z> = CC[]
        sage: f = z^2 - 1
        sage: julia_plot(f)
        1001x500px 24-bit RGB image

    ::

        sage: R.<z> = CC[]
        sage: K = R.fraction_field(); z = K.gen()
        sage: f = z^2-1
        sage: julia_plot(f)
        1001x500px 24-bit RGB image

    Interact functionality is not implemented if the polynomial is not of the
    form `f = z^2 + c`::

        sage: R.<z> = CC[]
        sage: f = z^3 + 1
        sage: julia_plot(f, interact=True)
        Traceback (most recent call last):
        ...
        NotImplementedError: The interactive plot is only implemented for ...
    """

    # extract keyword arguments
    period = kwds.pop("period", None)
    mandelbrot = kwds.pop("mandelbrot", True)
    point_color = kwds.pop("point_color", 'tomato')
    x_center = kwds.pop("x_center", 0.0)
    y_center = kwds.pop("y_center", 0.0)
    image_width = kwds.pop("image_width", 4.0)
    max_iteration = kwds.pop("max_iteration", 500)
    pixel_count = kwds.pop("pixel_count", 500)
    base_color = kwds.pop("base_color", 'steelblue')
    level_sep = kwds.pop("level_sep", 1)
    number_of_colors = kwds.pop("number_of_colors", 30)
    interacts = kwds.pop("interact", False)

    f_is_default_after_all = None

    if period: # pick a random c with the specified period
        R = PolynomialRing(CC, 'c')
        c = R.gen()
        x, y = ProjectiveSpace(R, 1, 'x,y').gens()
        F = DynamicalSystem([x**2 + c * y**2, y**2])
        L = F.dynatomic_polynomial(period).subs({x: 0, y: 1}).roots(ring=CC)
        c = L[randint(0, len(L) - 1)][0]

    base_color = Color(base_color)
    point_color = Color(point_color)

    EPS = 0.00001

    if f is not None and period is None: # f user-specified and no period given

        # try to coerce f to live in a polynomial ring
        S = PolynomialRing(CC, names='z')
        z = S.gen()
        try:
            f_poly = S(f)
        except TypeError:
            R = f.parent()
            if not (R.is_integral_domain() and
                   (CC.is_subring(R) or CDF.is_subring(R))):
                raise ValueError('Given `f` must be a complex polynomial.')
            else:
                raise NotImplementedError(
                        'Julia sets not implemented for rational functions.'
                        )

        if (f_poly - z*z) in CC: # f is specified and of the form z^2 + c.
            f_is_default_after_all = True
            c = f_poly - z*z
        else: # f is specified and not of the form z^2 + c
            if interacts:
                raise NotImplementedError(
                        "The interactive plot is only implemented for "
                        "polynomials of the form f = z^2 + c."
                            )
            else:
                return general_julia(f_poly, x_center, y_center,
                                    image_width, max_iteration,
                                    pixel_count, level_sep,
                                    number_of_colors, base_color)

    # otherwise we can use fast_julia_plot for z^2 + c
    if f_is_default_after_all or f is None or period is not None:

        # specify default c = -1 value if f and period were not specified
        if not f_is_default_after_all and period is None:
            c = -1

        c = CC(c)
        c_real = c.real()
        c_imag = c.imag()

        if interacts: # set widgets
            from ipywidgets.widgets import FloatSlider, IntSlider, \
                                           ColorPicker, interact
            widgets = dict(
                c_real = FloatSlider(min=-2.0, max=2.0, step=EPS,
                                  value=c_real, description="Real c"),
                c_imag = FloatSlider(min=-2.0, max=2.0, step=EPS,
                                  value=c_imag, description="Imag c"),
                x_center = FloatSlider(min=-1.0, max=1.0, step=EPS,
                                  value=x_center, description="Real center"),
                y_center = FloatSlider(min=-1.0, max=1.0, step=EPS,
                                  value=y_center, description="Imag center"),
                image_width = FloatSlider(min=EPS, max=4.0, step=EPS,
                                  value=image_width, description="Width"),
                max_iteration = IntSlider(min=0, max=1000,
                                  value=max_iteration, description="Iterations"),
                pixel_count = IntSlider(min=10, max=1000,
                                  value=pixel_count, description="Pixels"),
                level_sep = IntSlider(min=1, max=20,
                                  value=level_sep, description="Color sep"),
                color_num = IntSlider(min=1, max=100,
                                  value=number_of_colors, description="# Colors"),
                base_color = ColorPicker(value=base_color.html_color(),
                                         description="Base color"),
            )
            if mandelbrot:
                widgets["point_color"] = ColorPicker(value=point_color.html_color(),
                                                     description="Point color")
                return interact(**widgets).widget(julia_helper)
            else:
                return interact(**widgets).widget(fast_julia_plot)
        elif mandelbrot: # non-interactive with mandelbrot
            return julia_helper(c_real, c_imag, x_center, y_center,
                                image_width, max_iteration, pixel_count,
                                level_sep, number_of_colors, base_color,
                                point_color)
        else: # non-interactive without mandelbrot
            return fast_julia_plot(c_real, c_imag, x_center, y_center,
                                   image_width, max_iteration, pixel_count,
                                   level_sep, number_of_colors, base_color)
コード例 #21
0
def hyperbolic_regular_polygon(sides, i_angle, center=CC(0, 1), **options):
    r"""
    Return a hyperbolic regular polygon in the upper half model of
    Hyperbolic plane given the number of sides, interior angle and
    possibly a center.

    Type ``?hyperbolic_regular_polygon`` to see all options.

    INPUT:

    - ``sides`` -- number of sides of the polygon

    - ``i_angle`` -- interior angle of the polygon

    - ``center``  -- (default: `i`) hyperbolic center point
      (complex number) of the polygon

    OPTIONS:

    - ``alpha`` -- default: 1

    - ``fill`` -- default: ``False``

    - ``thickness`` -- default: 1

    - ``rgbcolor`` -- default: ``'blue'``

    - ``linestyle`` -- (default: ``'solid'``) the style of the line,
      which can be one of the following:

      * ``'dashed'`` or ``'--'``
      * ``'dotted'`` or ``':'``
      * ``'solid'`` or ``'-'``
      * ``'dashdot'`` or ``'-.'``

    EXAMPLES:

    Show a hyperbolic regular polygon with 6 sides and square angles::

        sage: g = hyperbolic_regular_polygon(6, pi/2)
        sage: g.plot()
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

         g = hyperbolic_regular_polygon(6, pi/2)
         sphinx_plot(g.plot())

    With more options::

        sage: g = hyperbolic_regular_polygon(6, pi/2, center=3+2*I, fill=True, color='red')
        sage: g.plot()
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

         g = hyperbolic_regular_polygon(6, pi/2, center=3+2*I, fill=True, color='red')
         sphinx_plot(g.plot())

    The code verifies is there exists a hyperbolic regular polygon
    with the given data, checking

    .. MATH::

        A(\mathcal{P}) = \pi(s-2) - s \cdot \alpha > 0,

    where `s` is ``sides`` and `\alpha` is ``i_angle`. This raises an error if
    the ``i_angle`` is less than the minimum to generate a compact polygon::

        sage: hyperbolic_regular_polygon(4, pi/2)
        Traceback (most recent call last):
        ...
        ValueError: there exists no hyperbolic regular compact polygon,
         for sides=4 the interior angle must be less than 1/2*pi

    It is an error to give a center outside the upper half plane in
    this model::

        sage: from sage.plot.hyperbolic_regular_polygon import hyperbolic_regular_polygon
        sage: hyperbolic_regular_polygon(4, pi/4, 1-I)
        Traceback (most recent call last):
        ...
        ValueError: center: 1.00000000000000 - 1.00000000000000*I is not
         a valid point in the upper half plane model of the hyperbolic plane
    """
    g = Graphics()
    g._set_extra_kwds(g._extract_kwds_for_show(options))
    g.add_primitive(HyperbolicRegularPolygon(sides, i_angle, center, options))
    g.set_aspect_ratio(1)
    return g
コード例 #22
0
class HyperbolicRegularPolygon(HyperbolicPolygon):
    r"""
    Primitive class for regular hyperbolic polygon type.

    See ``hyperbolic_regular_polygon?`` for information about plotting
    a hyperbolic regular polygon in the upper complex halfplane.

    INPUT:

    - ``sides`` -- number of sides of the polygon

    - ``i_angle`` -- interior angle of the polygon

    - ``center``-- center point as a complex number of the polygon

    EXAMPLES:

    Note that constructions should use :func:`hyperbolic_regular_polygon`::

         sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
         sage: print(HyperbolicRegularPolygon(5,pi/2,I, {}))
         Hyperbolic regular polygon (sides=5, i_angle=1/2*pi, center=1.00000000000000*I)

    The code verifies is there exists a compact hyperbolic regular polygon
    with the given data, checking

    .. MATH::

        A(\mathcal{P}) = \pi(s-2) - s \cdot \alpha > 0,

    where `s` is ``sides`` and `\alpha` is ``i_angle`. This raises an error if
    the ``i_angle`` is less than the minimum to generate a compact polygon::

        sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
        sage: P = HyperbolicRegularPolygon(4, pi/2, I, {})
        Traceback (most recent call last):
        ...
        ValueError: there exists no hyperbolic regular compact polygon,
         for sides=4 the interior angle must be less than 1/2*pi

    It is an error to give a center outside the upper half plane in this model ::

         sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
         sage: P = HyperbolicRegularPolygon(4, pi/4, 1-I, {})
         Traceback (most recent call last):
         ...
         ValueError: center: 1.00000000000000 - 1.00000000000000*I is not
          a valid point in the upper half plane model of the hyperbolic plane

    TESTS::

         sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
         sage: P = HyperbolicRegularPolygon(4, -pi/4, I, {})
         Traceback (most recent call last):
         ...
         ValueError: interior angle -1/4*pi must be in (0, pi) interval

         sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
         sage: P=HyperbolicRegularPolygon(16, 3*pi/2, I, {})
         Traceback (most recent call last):
         ...
         ValueError: interior angle 3/2*pi must be in (0, pi) interval

         sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
         sage: P = HyperbolicRegularPolygon(2, pi/10, I, {})
         Traceback (most recent call last):
         ...
         ValueError: degenerated polygons (sides<=2) are not supported
    """
    def __init__(self, sides, i_angle, center, options):
        """
        Initialize HyperbolicRegularPolygon.

        EXAMPLES::

            sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
            sage: print(HyperbolicRegularPolygon(5,pi/2,I, {}))
            Hyperbolic regular polygon (sides=5, i_angle=1/2*pi, center=1.00000000000000*I)
        """
        self.center = CC(center)
        if self.center.imag() <= 0:
            raise ValueError(
                "center: %s is not a valid point in the upper half plane model of the hyperbolic plane"
                % (self.center))
        if sides < 3:
            raise ValueError(
                "degenerated polygons (sides<=2) are not supported")
        if i_angle <= 0 or i_angle >= pi:
            raise ValueError("interior angle %s must be in (0, pi) interval" %
                             (i_angle))
        if pi * (sides - 2) - sides * i_angle <= 0:
            raise ValueError(
                "there exists no hyperbolic regular compact polygon, for sides=%s the interior angle must be less than %s"
                % (sides, pi * (sides - 2) / sides))
        self.sides = sides
        self.i_angle = i_angle
        beta = 2 * pi / self.sides  # compute the rotation angle to be used ahead
        alpha = self.i_angle / Integer(2)
        I = CC(0, 1)
        # compute using cosine theorem the radius of the circumscribed circle
        # using the triangle formed by the radius and the three known angles
        r = arccosh(cot(alpha) * (1 + cos(beta)) / sin(beta))

        # The first point will be always on the imaginary axis limited
        # to 8 digits for efficiency in the subsequent calculations.
        z_0 = [I * (e**r).n(digits=8)]

        # Compute the dilation isometry used to move the center
        # from I to the imaginary part of the given center.
        scale = self.center.imag()

        # Compute the parabolic isometry to move the center to the
        # real part of the given center.
        h_disp = self.center.real()

        d_z_k = [z_0[0] * scale + h_disp
                 ]  #d_k has the points for the polygon in the given center
        z_k = z_0  #z_k has the Re(z)>0 vertices for the I centered polygon
        r_z_k = []  #r_z_k has the Re(z)<0 vertices
        if is_odd(self.sides):
            vert = (self.sides - 1) // 2
        else:
            vert = self.sides // 2 - 1
        for k in range(vert):
            # Compute with 8 digits to accelerate calculations
            new_z_k = self._i_rotation(z_k[-1], beta).n(digits=8)
            z_k = z_k + [new_z_k]
            d_z_k = d_z_k + [new_z_k * scale + h_disp]
            r_z_k = [-(new_z_k).conjugate() * scale + h_disp] + r_z_k
        if is_odd(self.sides):
            HyperbolicPolygon.__init__(self, d_z_k + r_z_k, options)
        else:
            z_opo = [I * (e**(-r)).n(digits=8) * scale + h_disp]
            HyperbolicPolygon.__init__(self, d_z_k + z_opo + r_z_k, options)

    def _repr_(self):
        """
        String representation of HyperbolicRegularPolygon.

        TESTS::

            sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
            sage: HyperbolicRegularPolygon(5,pi/2,I, {})._repr_()
            'Hyperbolic regular polygon (sides=5, i_angle=1/2*pi, center=1.00000000000000*I)'
        """
        return (
            "Hyperbolic regular polygon (sides=%s, i_angle=%s, center=%s)" %
            (self.sides, self.i_angle, self.center))

    def _i_rotation(self, z, alpha):
        r"""
        Return the resulting point after applying a hyperbolic
        rotation centered at `0 + i` and angle ``alpha`` to ``z``.

        INPUT:

        - ``z``-- point in the upper complex halfplane to which
          apply the isometry

        - ``alpha``-- angle of rotation (radians,counterwise)

        OUTPUT:

        - rotated point in the upper complex halfplane

        TESTS::

            sage: from sage.plot.hyperbolic_regular_polygon import HyperbolicRegularPolygon
            sage: P = HyperbolicRegularPolygon(4, pi/4, 1+I, {})
            sage: P._i_rotation(2+I, pi/2)
            I - 2
        """
        _a = alpha / 2
        _c = cos(_a)
        _s = sin(_a)
        G = matrix([[_c, _s], [-_s, _c]])
        return (G[0][0] * z + G[0][1]) / (G[1][0] * z + G[1][1])
コード例 #23
0
def smallest_poly(F, prec=53, norm_type='norm', emb=None):
    r"""
    Determine the poly with smallest coefficients in `SL(2,\Z)` orbit of ``F``

    Smallest can be in the sense of `L_2` norm or height.
    The method is the algorithm in Hutz-Stoll [HS2018]_.

    ``F`` needs to be a binary form with no multiple roots of degree
    at least 3. It should already be reduced in the sense of
    Cremona-Stoll [CS2003]_.

    INPUT:

    - ``F`` -- binary form of degree at least 3 with no multiple roots

    - ``norm_type`` -- string - ``norm`` or ``height`` controlling what ``smallest``
      means for the coefficients.

    OUTPUT: pair [poly, matrix]

    EXAMPLES::

        sage: from sage.rings.polynomial.binary_form_reduce import smallest_poly
        sage: R.<x,y> = QQ[]
        sage: F = -x^8 + 6*x^7*y - 7*x^6*y^2 - 12*x^5*y^3 + 27*x^4*y^4\
        ....: - 4*x^3*y^5 - 19*x^2*y^6 + 10*x*y^7 - 5*y^8
        sage: smallest_poly(F, prec=100) #long time
        [
        -x^8 - 2*x^7*y + 7*x^6*y^2 + 16*x^5*y^3 + 2*x^4*y^4 - 2*x^3*y^5 + 4*x^2*y^6 - 5*y^8,
        <BLANKLINE>
        [1 1]
        [0 1]
        ]

    ::

        sage: from sage.rings.polynomial.binary_form_reduce import smallest_poly, get_bound_poly
        sage: R.<x,y> = QQ[]
        sage: F = -2*x^3 + 2*x^2*y + 3*x*y^2 + 127*y^3
        sage: smallest_poly(F)
        [
                                               [1 4]
        -2*x^3 - 22*x^2*y - 77*x*y^2 + 43*y^3, [0 1]
        ]
        sage: F0, M = smallest_poly(F, norm_type='height')
        sage: F0, M  # random
        (
                                                [5 4]
        -58*x^3 - 47*x^2*y + 52*x*y^2 + 43*y^3, [1 1]
        )
        sage: M in SL2Z, F0 == R.hom(M * vector([x, y]))(F)
        (True, True)
        sage: get_bound_poly(F0, norm_type='height')  # tol 1e-12
        23.3402702199809

    An example with a multiple root::

        sage: R.<x,y> = QQ[]
        sage: F = -16*x^7 - 114*x^6*y - 345*x^5*y^2 - 599*x^4*y^3 - 666*x^3*y^4\
        ....: - 481*x^2*y^5 - 207*x*y^6 - 40*y^7
        sage: F.reduced_form()
        (
                                                              [-1 -1]
        -x^5*y^2 - 24*x^3*y^4 - 3*x^2*y^5 - 2*x*y^6 + 16*y^7, [ 1  0]
        )
    """
    def insert_item(pts, item, index):
        # binary insertion to maintain list of points left to consider
        N = len(pts)
        if N == 0:
            return [item]
        elif N == 1:
            if item[index] > pts[0][index]:
                pts.insert(0, item)
            else:
                pts.append(item)
            return pts
        else:  # binary insertion
            left = 1
            right = N
            mid = (left + right) // 2  # these are ints so this is .floor()
            if item[index] > pts[mid][index]:  # item goes into first half
                return insert_item(pts[:mid], item, index) + pts[mid:N]
            else:  # item goes into second half
                return pts[:mid] + insert_item(pts[mid:N], item, index)

    def coshdelta(z):
        # The cosh of the hyperbolic distance from z = t+uj to j
        return (z.norm() + 1) / (2 * z.imag()
                                 )  # reduce in the sense of Cremona-Stoll

    G = F
    MG = matrix(ZZ, 2, 2, [1, 0, 0, 1])
    x, y = G.parent().gens()
    if norm_type == 'norm':
        current_size = sum([abs(i)**2 for i in G.coefficients()
                            ])  # euclidean norm squared
    elif norm_type == 'height':  # height
        current_size = exp(
            max([c.global_height(prec=prec) for c in G.coefficients()]))
    else:
        raise ValueError('type must be norm or height')
    v0, th = covariant_z0(G, prec=prec, emb=emb)
    rep = 2 * CC.gen(0)  # representative point in fundamental domain
    from math import isnan
    if isnan(v0.abs()):
        raise ValueError("invalid covariant: %s" % v0)
    R = get_bound_poly(G, prec=prec, norm_type=norm_type)

    # check orbit
    S = matrix(ZZ, 2, 2, [0, -1, 1, 0])
    T = matrix(ZZ, 2, 2, [1, 1, 0, 1])
    TI = matrix(ZZ, 2, 2, [1, -1, 0, 1])

    count = 0
    pts = [[G, v0, rep, MG, coshdelta(v0),
            0]]  # label - 0:None, 1:S, 2:T, 3:T^(-1)
    current_min = [G, v0, rep, MG, coshdelta(v0)]
    while pts:
        G, v, rep, M, D, label = pts.pop()
        # apply ST and keep z, Sz
        if D > R:
            break  # all remaining pts are too far away
        # check if it is smaller. If so, we can improve the bound
        count += 1
        if norm_type == 'norm':
            new_size = sum([abs(i)**2 for i in G.coefficients()
                            ])  # euclidean norm squared
        else:  # height
            new_size = exp(
                max([c.global_height(prec=prec) for c in G.coefficients()]))
        if new_size < current_size:
            current_min = [G, v, rep, M, coshdelta(v)]
            current_size = new_size
            R = get_bound_poly(G, norm_type=norm_type, prec=prec, emb=emb)

        # add new points to check
        if label != 1 and min((rep + 1).norm(),
                              (rep - 1).norm()) >= 1:  # don't undo S
            # the 2nd condition is equivalent to |\Re(-1/rep)| <= 1/2
            # this means that rep can have resulted from an inversion step in
            # the shift-and-invert procedure, so don't invert

            # do inversion
            z = -1 / v
            new_pt = [
                G.subs({
                    x: -y,
                    y: x
                }), z, -1 / rep, M * S,
                coshdelta(z), 1
            ]
            pts = insert_item(pts, new_pt, 4)
        if label != 3:  # don't undo TI
            # do right shift
            z = v - 1
            new_pt = [G.subs({x: x + y}), z, rep - 1, M * T, coshdelta(z), 2]
            pts = insert_item(pts, new_pt, 4)
        if label != 2:  # don't undo T
            # do left shift
            z = v + 1
            new_pt = [G.subs({x: x - y}), z, rep + 1, M * TI, coshdelta(z), 3]
            pts = insert_item(pts, new_pt, 4)

    return [current_min[0], current_min[3]]
コード例 #24
0
    def contradicts(self, soln):
        """
        Return ``True`` if this assumption is violated by the given
        variable assignment(s).

        INPUT:

        - ``soln`` -- Either a dictionary with variables as keys or a symbolic
          relation with a variable on the left hand side.

        EXAMPLES::

            sage: from sage.symbolic.assumptions import GenericDeclaration
            sage: GenericDeclaration(x, 'integer').contradicts(x==4)
            False
            sage: GenericDeclaration(x, 'integer').contradicts(x==4.0)
            False
            sage: GenericDeclaration(x, 'integer').contradicts(x==4.5)
            True
            sage: GenericDeclaration(x, 'integer').contradicts(x==sqrt(17))
            True
            sage: GenericDeclaration(x, 'noninteger').contradicts(x==sqrt(17))
            False
            sage: GenericDeclaration(x, 'noninteger').contradicts(x==17)
            True
            sage: GenericDeclaration(x, 'even').contradicts(x==3)
            True
            sage: GenericDeclaration(x, 'complex').contradicts(x==3)
            False
            sage: GenericDeclaration(x, 'imaginary').contradicts(x==3)
            True
            sage: GenericDeclaration(x, 'imaginary').contradicts(x==I)
            False

            sage: var('y,z')
            (y, z)
            sage: GenericDeclaration(x, 'imaginary').contradicts(x==y+z)
            False

            sage: GenericDeclaration(x, 'rational').contradicts(y==pi)
            False
            sage: GenericDeclaration(x, 'rational').contradicts(x==pi)
            True
            sage: GenericDeclaration(x, 'irrational').contradicts(x!=pi)
            False
            sage: GenericDeclaration(x, 'rational').contradicts({x: pi, y: pi})
            True
            sage: GenericDeclaration(x, 'rational').contradicts({z: pi, y: pi})
            False
       """
        if isinstance(soln, dict):
            value = soln.get(self._var)
            if value is None:
                return False
        elif soln.lhs() == self._var:
            value = soln.rhs()
        else:
            return False
        try:
            CC(value)
        except TypeError:
            return False
        if self._assumption == 'integer':
            return value not in ZZ
        elif self._assumption == 'noninteger':
            return value in ZZ
        elif self._assumption == 'even':
            return value not in ZZ or bool(ZZ(value) % 2)
        elif self._assumption == 'odd':
            return value not in ZZ or not (ZZ(value) % 2)
        elif self._assumption == 'rational':
            return value not in QQ
        elif self._assumption == 'irrational':
            return value in QQ
        elif self._assumption == 'real':
            return value not in RR
        elif self._assumption == 'imaginary':
            return value not in CC or CC(value).real() != 0
        elif self._assumption == 'complex':
            return value not in CC