Пример #1
0
    def _eval_(self, n, x):
        """
        EXAMPLES::

            sage: y=var('y')
            sage: bessel_I(y,x)
            bessel_I(y, x)
            sage: bessel_I(0.0, 1.0)
            1.26606587775201
            sage: bessel_I(1/2, 1)
            sqrt(2)*sinh(1)/sqrt(pi)
            sage: bessel_I(-1/2, pi)
            sqrt(2)*cosh(pi)/pi
        """
        if (not isinstance(n, Expression) and not isinstance(x, Expression) and
                (is_inexact(n) or is_inexact(x))):
            coercion_model = get_coercion_model()
            n, x = coercion_model.canonical_coercion(n, x)
            return self._evalf_(n, x, parent(n))

        # special identities
        if n == Integer(1) / Integer(2):
            return sqrt(2 / (pi * x)) * sinh(x)
        elif n == -Integer(1) / Integer(2):
            return sqrt(2 / (pi * x)) * cosh(x)

        return None  # leaves the expression unevaluated
Пример #2
0
    def _eval_(self, a, z):
        """
        EXAMPLES::

            sage: struve_H(0,0)
            0
            sage: struve_H(pi,0)
            0
            sage: struve_H(-1/2,x)
            sqrt(2)*sqrt(1/(pi*x))*sin(x)
            sage: struve_H(1/2,-1)
            -sqrt(2)*sqrt(-1/pi)*(cos(1) - 1)
            sage: struve_H(1/2,pi)
            2*sqrt(2)/pi
            sage: struve_H(2,x)
            struve_H(2, x)
            sage: struve_H(-3/2,x)
            -bessel_J(3/2, x)
        """
        from sage.symbolic.ring import SR
        if z.is_zero() \
                and (SR(a).is_numeric() or SR(a).is_constant()) \
                and a.real() >= -1:
                return ZZ(0)
        if a == -Integer(1)/2:
            from sage.functions.trig import sin
            return sqrt(2/(pi*z)) * sin(z)
        if a == Integer(1)/2:
            from sage.functions.trig import cos
            return sqrt(2/(pi*z)) * (1-cos(z))
        if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer():
            from sage.rings.rational_field import QQ
            n = (a*(-2) - 1)/2
            return Integer(-1)**n * bessel_J(n+QQ(1)/2, z)
Пример #3
0
def platonic_dodecahedron():
    r"""Produce a triple consisting of a polyhedral version of the platonic dodecahedron,
    the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface
    to the polyhedron.

    EXAMPLES::

    sage: from flatsurf.geometry.polyhedra import platonic_dodecahedron
    sage: polyhedron,surface,surface_to_polyhedron = platonic_dodecahedron()
    sage: TestSuite(surface).run()
    r"""
    vertices=[]
    phi=AA(1+sqrt(5))/2
    F=NumberField(phi.minpoly(),"phi",embedding=phi)
    phi=F.gen()
    for x in xrange(-1,3,2):
        for y in xrange(-1,3,2):
            for z in xrange(-1,3,2):
                vertices.append(vector(F,(x,y,z)))
    for x in xrange(-1,3,2):
        for y in xrange(-1,3,2):
            vertices.append(vector(F,(0,x*phi,y/phi)))
            vertices.append(vector(F,(y/phi,0,x*phi)))
            vertices.append(vector(F,(x*phi,y/phi,0)))
    scale=AA(2/sqrt(1+(phi-1)**2+(1/phi-1)**2))
    p=Polyhedron(vertices=vertices)
    s,m = polyhedron_to_cone_surface(p,scaling_factor=scale)
    return p,s,m
Пример #4
0
    def _eval_(self, a, z):
        """
        EXAMPLES::

            sage: struve_L(-2,0)
            struve_L(-2, 0)
            sage: struve_L(-1,0)
            0
            sage: struve_L(pi,0)
            0
            sage: struve_L(-1/2,x)
            sqrt(2)*sqrt(1/(pi*x))*sinh(x)
            sage: struve_L(1/2,1)
            sqrt(2)*(cosh(1) - 1)/sqrt(pi)
            sage: struve_L(2,x)
            struve_L(2, x)
            sage: struve_L(-3/2,x)
            -bessel_I(3/2, x)
        """
        from sage.symbolic.ring import SR
        if z.is_zero() \
                and (SR(a).is_numeric() or SR(a).is_constant()) \
                and a.real() >= -1:
                return ZZ(0)
        if a == -Integer(1)/2:
            from sage.functions.hyperbolic import sinh
            return sqrt(2/(pi*z)) * sinh(z)
        if a == Integer(1)/2:
            from sage.functions.hyperbolic import cosh
            return sqrt(2/(pi*z)) * (cosh(z)-1)
        if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer():
            from sage.rings.rational_field import QQ
            n = (a*(-2) - 1)/2
            return Integer(-1)**n * bessel_I(n+QQ(1)/2, z)
Пример #5
0
 def get_s(self):
     """Returns a single value of s as required for the Elligator map while there may even be two of them, in which case the returned values is the smaller of the two
     """ 
     try:
         return self._s
     except AttributeError:
         pass
     s = []
     d = self.__E.get_d()
     if is_square(-d):
         c = ( 2*(d-1) + 4*sqrt(-d) ) / ( 2*(d+1) )
         s_2 = 2/c
         if is_square(s_2):
             s.append(sqrt(s_2))
         
         c = ( 2*(d-1) - 4*sqrt(-d) ) / ( 2*(d+1) )
         s_2 = 2/c
         if is_square(s_2):
             s.append(sqrt(s_2))
     if len(s) == 0:
         return None
     elif len(s) == 1:
         return s[0]
     else:
         if s[0] < s[1]:
             return s[0]
         else: 
             return s[1]    
Пример #6
0
    def __eq__(self, other):
        r"""
        Return ``True`` if the isometries are the same and ``False`` otherwise.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: A = UHP.get_isometry(identity_matrix(2))
            sage: B = UHP.get_isometry(-identity_matrix(2))
            sage: A == B
            True

            sage: HM = HyperbolicPlane().HM()
            sage: A = HM.random_isometry()
            sage: A == A
            True
        """
        if not isinstance(other, HyperbolicIsometry):
            return False
        test_matrix = bool((self.matrix() - other.matrix()).norm() < EPSILON)
        if self.domain().is_isometry_group_projective():
            A,B = self.matrix(), other.matrix() # Rename for simplicity
            m = self.matrix().ncols()
            A = A / sqrt(A.det(), m) # Normalized to have determinant 1
            B = B / sqrt(B.det(), m)
            test_matrix = ((A - B).norm() < EPSILON
                           or (A + B).norm() < EPSILON)
        return self.domain() is other.domain() and test_matrix
Пример #7
0
 def _0f1(b, z):
     F12 = cosh(2 * sqrt(z))
     F32 = sinh(2 * sqrt(z)) / (2 * sqrt(z))
     if 2 * b == 1:
         return F12
     if 2 * b == 3:
         return F32
     if 2 * b > 3:
         return ((b - 2) * (b - 1) / z * (_0f1(b - 2, z) -
                 _0f1(b - 1, z)))
     if 2 * b < 1:
         return (_0f1(b + 1, z) + z / (b * (b + 1)) *
                 _0f1(b + 2, z))
     raise ValueError
Пример #8
0
def SO21_to_SL2R(M):
    r"""
    A homomorphism from `SO(2, 1)` to `SL(2, \RR)`.

    Note that this is not the only homomorphism, but it is the only one
    that works in the context of the implemented 2D hyperbolic geometry
    models.

    EXAMPLES::

        sage: from sage.geometry.hyperbolic_space.hyperbolic_coercion import SO21_to_SL2R
        sage: (SO21_to_SL2R(identity_matrix(3)) - identity_matrix(2)).norm() < 10**-4
        True
    """
    ####################################################################
    # SL(2,R) is the double cover of SO (2,1)^+, so we need to choose  #
    # a lift.  I have formulas for the absolute values of each entry   #
    # a,b ,c,d of the lift matrix(2,[a,b,c,d]), but we need to choose  #
    # one entry to be positive.  I choose d for no particular reason,  #
    # unless d = 0, then we choose c > 0.  The basic strategy for this #
    # function is to find the linear map induced by the SO(2,1)        #
    # element on the Lie algebra sl(2, R).  This corresponds to the    #
    # Adjoint action by a matrix A or -A in SL(2,R).  To find which    #
    # matrix let X,Y,Z be a basis for sl(2,R) and look at the images   #
    # of X,Y,Z as well as the second and third standard basis vectors  #
    # for 2x2 matrices (these are traceless, so are in the Lie         #
    # algebra).  These corresponds to AXA^-1 etc and give formulas     #
    # for the entries of A.                                            #
    ####################################################################
    (m_1,m_2,m_3,m_4,m_5,m_6,m_7,m_8,m_9) = M.list()
    d = sqrt(Integer(1)/Integer(2)*m_5 - Integer(1)/Integer(2)*m_6 -
             Integer(1)/Integer(2)*m_8 + Integer(1)/Integer(2)*m_9)
    if M.det() > 0:  # EPSILON?
        det_sign = 1
    elif M.det() < 0:  # EPSILON?
        det_sign = -1
    if d > 0:  # EPSILON?
        c = (-Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/d
        b = (-Integer(1)/Integer(2)*m_2 + Integer(1)/Integer(2)*m_3)/d
        ad = det_sign*1 + b*c  # ad - bc = pm 1
        a = ad/d
    else:  # d is 0, so we make c > 0
        c = sqrt(-Integer(1)/Integer(2)*m_5 - Integer(1)/Integer(2)*m_6 +
                 Integer(1)/Integer(2)*m_8 + Integer(1)/Integer(2)*m_9)
        d = (-Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/c
            # d = 0, so ad - bc = -bc = pm 1.
        b = - (det_sign*1)/c
        a = (Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/b
    A = matrix(2, [a, b, c, d])
    return A
Пример #9
0
def RankingScale_USAU_2013():
    r"""
    EXAMPLES::

        sage: from slabbe.ranking_scale import RankingScale_USAU_2013
        sage: R = RankingScale_USAU_2013()
        sage: R.table()
          Position   Serie 1500   Serie 1000   Serie 500   Serie 250
          1          1500         1000         500         250
          2          1366         911          455         228
          3          1252         835          417         209
          4          1152         768          384         192
          5          1061         708          354         177
          6          979          653          326         163
          7          903          602          301         151
          8          832          555          278         139
          9          767          511          256         128
          10         706          471          236         118
          11         648          432          217         109
          12         595          397          199         100
          13         544          363          182         91
          14         497          332          166         83
          15         452          302          151         76
          16         410          274          137         69
          17         371          248          124         62
          18         334          223          112         56
          19         299          199          100         50
          20         266          177          89          45
          21         235          157          79          40
          22         206          137          69          35
          23         178          119          60          30
          24         152          102          51          26
          25         128          86           43          22
          26         106          71           36          18
          27         85           57           29          15
          28         66           44           22          12
          29         47           32           16          9
          30         31           21           11          6
          31         15           10           6           3
          32         1            1            1           1
    """
    L1500 = [0] + discrete_curve(32, 1500, K=1, R=sqrt(2), base=e)
    L1000 = [0] + discrete_curve(32, 1000, K=1, R=sqrt(2), base=e)
    L500 = [0] + discrete_curve(32, 500, K=1, R=sqrt(2), base=e)
    L250 = [0] + discrete_curve(32, 250, K=1, R=sqrt(2), base=e)

    scales = L1500, L1000, L500, L250
    names = ['Serie 1500', 'Serie 1000', 'Serie 500', 'Serie 250']
    return RankingScale(names, scales)
Пример #10
0
    def show(self, show_hyperboloid=True, **graphics_options):
        r"""
        Plot ``self``.

        EXAMPLES::

            sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic import *
            sage: g = HyperbolicPlane().HM().random_geodesic()
            sage: g.show()
            Graphics3d Object
        """
        x = SR.var('x')
        opts = self.graphics_options()
        opts.update(graphics_options)
        v1, u2 = [vector(k.coordinates()) for k in self.endpoints()]
        # Lorentzian Gram Shmidt.  The original vectors will be
        # u1, u2 and the orthogonal ones will be v1, v2.  Except
        # v1 = u1, and I don't want to declare another variable,
        # hence the odd naming convention above.
        # We need the Lorentz dot product of v1 and u2.
        v1_ldot_u2 = u2[0]*v1[0] + u2[1]*v1[1] - u2[2]*v1[2]
        v2 = u2 + v1_ldot_u2 * v1
        v2_norm = sqrt(v2[0]**2 + v2[1]**2 - v2[2]**2)
        v2 = v2 / v2_norm
        v2_ldot_u2 = u2[0]*v2[0] + u2[1]*v2[1] - u2[2]*v2[2]
        # Now v1 and v2 are Lorentz orthogonal, and |v1| = -1, |v2|=1
        # That is, v1 is unit timelike and v2 is unit spacelike.
        # This means that cosh(x)*v1 + sinh(x)*v2 is unit timelike.
        hyperbola = cosh(x)*v1 + sinh(x)*v2
        endtime = arcsinh(v2_ldot_u2)
        from sage.plot.plot3d.all import parametric_plot3d
        pic = parametric_plot3d(hyperbola, (x, 0, endtime), **graphics_options)
        if show_hyperboloid:
            pic += self._model.get_background_graphic()
        return pic
Пример #11
0
    def cmp_ir(self,z):
        """ 
        returns -1 for left, 0 for in, and 1 for right from initial region
        cut line is on the north ray from pfp.

        Works only for real x0.
        """
        pfp = self.pfp
        x0 = self.x0
        if x0 > 0.5:
            print z,abs(z)
            if real(z) >= real(pfp) and abs(z) < abs(pfp):
                return 0
            if real(z) < real(pfp):
                return -1
            if real(z) > real(pfp):
                return 1
        else:
            if imag(z) > imag(pfp):
                if real(z) > real(pfp):
                    return 1
                if real(z) < real(pfp):
                    return -1
            if real(z) < real(pfp) and real(z) > log(real(pfp)) + log(sqrt(1+tan(imag(z))**2)):
                return 0
            if real(z) > real(pfp):
                return 1
            if real(z) < real(pfp):
                return -1
Пример #12
0
    def perpendicular_bisector(self): #UHP
        r"""
        Return the perpendicular bisector of the hyperbolic geodesic ``self``
        if that geodesic has finite length.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: g = UHP.random_geodesic()
            sage: h = g.perpendicular_bisector()
            sage: c = lambda x: x.coordinates()
            sage: bool(c(g.intersection(h)[0]) - c(g.midpoint()) < 10**-9)
            True

        Infinite geodesics cannot be bisected::

            sage: UHP.get_geodesic(0, 1).perpendicular_bisector()
            Traceback (most recent call last):
            ...
            ValueError: the length must be finite
        """
        if self.length() == infinity:
            raise ValueError("the length must be finite")
        start = self._start.coordinates()
        d = self._model._dist_points(start, self._end.coordinates()) / 2
        S = self.complete()._to_std_geod(start)
        T1 = matrix([[exp(d/2), 0], [0, exp(-d/2)]])
        s2 = sqrt(2) * 0.5
        T2 = matrix([[s2, -s2], [s2, s2]])
        isom_mtrx = S.inverse() * (T1 * T2) * S # We need to clean this matrix up.
        if (isom_mtrx - isom_mtrx.conjugate()).norm() < 5*EPSILON: # Imaginary part is small.
            isom_mtrx = (isom_mtrx + isom_mtrx.conjugate()) / 2 # Set it to its real part.
        H = self._model.get_isometry(isom_mtrx)
        return self._model.get_geodesic(H(self._start), H(self._end))
Пример #13
0
def solve_degree2_to_integer_range(a,b,c):
    r"""
    Returns the greatest integer range `[i_1, i_2]` such that
    `i_1 > x_1` and `i_2 < x_2` where `x_1, x_2` are the two zeroes of the equation in `x`:
    `ax^2+bx+c=0`.

    If there is no real solution to the equation, it returns an empty range with negative coefficients.

    INPUT:

    - ``a``, ``b`` and ``c`` -- coefficients of a second degree equation, ``a`` being the coefficient of
      the higher degree term.

    EXAMPLES::

        sage: from sage.coding.guruswami_sudan.utils import solve_degree2_to_integer_range
        sage: solve_degree2_to_integer_range(1, -5, 1)
        (1, 4)

    If there is no real solution::

        sage: solve_degree2_to_integer_range(50, 5, 42)
        (-2, -1)
    """
    D = b**2 - 4*a*c
    if D < 0:
        return (-2,-1)
    sD = float(sqrt(D))
    minx, maxx = (-b-sD)/2.0/a , (-b+sD)/2.0/a
    mini, maxi = (ligt(minx), gilt(maxx))
    if mini > maxi:
        return (-2,-1)
    else:
        return (mini,maxi)
Пример #14
0
def platonic_icosahedron():
    r"""Produce a triple consisting of a polyhedral version of the platonic icosahedron,
    the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface
    to the polyhedron.

    EXAMPLES::

    sage: from flatsurf.geometry.polyhedra import platonic_icosahedron
    sage: polyhedron,surface,surface_to_polyhedron = platonic_icosahedron()
    sage: TestSuite(surface).run()
    r"""
    vertices=[]
    phi=AA(1+sqrt(5))/2
    F=NumberField(phi.minpoly(),"phi",embedding=phi)
    phi=F.gen()
    for i in xrange(3):
        for s1 in xrange(-1,3,2):
            for s2 in xrange(-1,3,2):
                p=3*[None]
                p[i]=s1*phi
                p[(i+1)%3]=s2
                p[(i+2)%3]=0
                vertices.append(vector(F,p))
    p=Polyhedron(vertices=vertices)
    
    s,m = polyhedron_to_cone_surface(p)
    return p,s,m
Пример #15
0
    def _test_representation(self, **options):
        """
        Check (on some elements) that ``self`` is a representation of the
        given semigroup.

        EXAMPLES::

            sage: G = groups.permutation.Dihedral(4)
            sage: R = G.regular_representation()
            sage: R._test_representation()

            sage: G = CoxeterGroup(['A',4,1], base_ring=ZZ)
            sage: M = CombinatorialFreeModule(QQ, ['v'])
            sage: from sage.modules.with_basis.representation import Representation
            sage: on_basis = lambda g,m: M.term(m, (-1)**g.length())
            sage: R = Representation(G, M, on_basis, side="right")
            sage: R._test_representation(max_runs=500)
        """
        from sage.functions.other import sqrt
        tester = self._tester(**options)
        S = tester.some_elements()
        L = []
        max_len = int(sqrt(tester._max_runs)) + 1
        for i,x in enumerate(self._semigroup):
            L.append(x)
            if i >= max_len:
                break
        for x in L:
            for y in L:
                for elt in S:
                    if self._left_repr:
                        tester.assertEqual(x*(y*elt), (x*y)*elt)
                    else:
                        tester.assertEqual((elt*y)*x, elt*(y*x))
Пример #16
0
 def random_point(self):
     while(1):
         x = self.base_ring().random_element()
         test = (x**2 - 1)/(self._d*(x**2) - 1)
         if is_square(test):
             y = sqrt(test)
             return self([x,y,1])    
    def iter_positive_forms_with_content(self) :
        if self.__disc is infinity :
            raise ValueError, "infinity is not a true filter index"
        
        
        if self.__reduced :        
            for a in xrange(1,isqrt(self.__disc // 3) + 1) :
                for b in xrange(a+1) :
                    g = gcd(a, b)
                    for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                        yield (a,b,c), gcd(g,c)
        else :
            maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
            for a in xrange(1, maxtrace + 1) :
                for c in xrange(1, maxtrace - a + 1) :
                    g = gcd(a,c)
                    
                    Bu = isqrt(4*a*c - 1)

                    di = 4*a*c - self.__disc
                    if di >= 0 :
                        Bl = isqrt(di) + 1 
                    else :
                        Bl = 0
                    
                    for b in xrange(-Bu, -Bl + 1) :
                        yield (a,b,c), gcd(g,b)
                    for b in xrange(Bl, Bu + 1) :
                        yield (a,b,c), gcd(g,b)
        #! if self.__reduced

        raise StopIteration
Пример #18
0
 def cmp_ir(self,z):
     """ 
     returns -1 for left, 0 for in, and 1 for right from initial region
     cut line is on the north ray from L.
     """
     L = self.L
     x0 = self.x0
     if x0 > 0.5:
         if real(z) > real(L) and abs(z) < abs(L):
             return 0
         if real(z) < real(L):
             return -1
         if real(z) > real(L):
             return 1
     else:
         if imag(z) > imag(L):
             if real(z) > real(L):
                 return 1
             if real(z) < real(L):
                 return -1
         if real(z) < real(L) and real(z) > log(real(L)) + log(sqrt(1+tan(imag(z))**2)):
             return 0
         if real(z) > real(L):
             return 1
         if real(z) < real(L):
             return -1
Пример #19
0
def RankingScale_CQU4_2011():
    r"""
    EXEMPLES::
        
        sage: from slabbe.ranking_scale import RankingScale_CQU4_2011
        sage: R = RankingScale_CQU4_2011()
        sage: R.table()
          Position   Grand Chelem   Mars Attaque   La Flotte   Petit Chelem
          1          1000           1000           800         400
          2          938            938            728         355
          3          884            884            668         317
          4          835            835            614         285
          5          791            791            566         256
          6          750            750            522         230
          7          711            711            482         206
          8          675            675            444         184
          9          641            641            409         164
          10         609            609            377         146
        ...
          95         0              11             0           0
          96         0              10             0           0
          97         0              9              0           0
          98         0              8              0           0
          99         0              7              0           0
          100        0              6              0           0
          101        0              4              0           0
          102        0              3              0           0
          103        0              2              0           0
          104        0              1              0           0
    """
    from sage.rings.integer_ring import ZZ
    serieA = [0] + discrete_curve(50, 1000, K=1, R=sqrt(2), base=e) #Movember, Bye Bye, Cdf, MA
    la_flotte = [0] + discrete_curve(32, 800, K=1, R=sqrt(2), base=e)  # la flotte
    serieB = [0] + discrete_curve(24, 400, K=1, R=sqrt(2), base=e) # october fest, funenuf, la viree

    nb_ma = 104
    pivot_x = 40
    pivot_y = serieA[pivot_x]
    slope = (1-pivot_y) / (nb_ma-pivot_x)
    L = [pivot_y + slope * (p-pivot_x) for p in range(pivot_x, nb_ma+1)]
    L = [ZZ(round(_)) for _ in L]
    mars_attaque = serieA[:pivot_x] + L

    scales = serieA, mars_attaque, la_flotte, serieB
    names = ["Grand Chelem", "Mars Attaque", "La Flotte", "Petit Chelem"]
    return RankingScale(names, scales)
Пример #20
0
            def _2f1(a, b, c, z):
                """
                Evaluation of 2F1(a, b; c; z), assuming a, b, c positive
                integers or half-integers
                """
                if b == c:
                    return (1 - z) ** (-a)
                if a == c:
                    return (1 - z) ** (-b)
                if a == 0 or b == 0:
                    return Integer(1)
                if a > b:
                    a, b = b, a
                if b >= 2:
                    F1 = _2f1(a, b - 1, c, z)
                    F2 = _2f1(a, b - 2, c, z)
                    q = (b - 1) * (z - 1)
                    return (((c - 2 * b + 2 + (b - a - 1) * z) * F1 +
                            (b - c - 1) * F2) / q)
                if c > 2:
                    # how to handle this case?
                    if a - c + 1 == 0 or b - c + 1 == 0:
                        raise NotImplementedError
                    F1 = _2f1(a, b, c - 1, z)
                    F2 = _2f1(a, b, c - 2, z)
                    r1 = (c - 1) * (2 - c - (a + b - 2 * c + 3) * z)
                    r2 = (c - 1) * (c - 2) * (1 - z)
                    q = (a - c + 1) * (b - c + 1) * z
                    return (r1 * F1 + r2 * F2) / q

                if (a, b, c) == (R12, 1, 2):
                    return (2 - 2 * sqrt(1 - z)) / z
                if (a, b, c) == (1, 1, 2):
                    return -log(1 - z) / z
                if (a, b, c) == (1, R32, R12):
                    return (1 + z) / (1 - z) ** 2
                if (a, b, c) == (1, R32, 2):
                    return 2 * (1 / sqrt(1 - z) - 1) / z
                if (a, b, c) == (R32, 2, R12):
                    return (1 + 3 * z) / (1 - z) ** 3
                if (a, b, c) == (R32, 2, 1):
                    return (2 + z) / (2 * (sqrt(1 - z) * (1 - z) ** 2))
                if (a, b, c) == (2, 2, 1):
                    return (1 + z) / (1 - z) ** 3
                raise NotImplementedError
Пример #21
0
    def _eval_(self, n, x):
        """
        EXAMPLES::

            sage: y=var('y')
            sage: bessel_I(y,x)
            bessel_I(y, x)
            sage: bessel_I(0.0, 1.0)
            1.26606587775201
            sage: bessel_I(1/2, 1)
            sqrt(2)*sinh(1)/sqrt(pi)
            sage: bessel_I(-1/2, pi)
            sqrt(2)*cosh(pi)/pi
        """
        # special identities
        if n == Integer(1) / Integer(2):
            return sqrt(2 / (pi * x)) * sinh(x)
        elif n == -Integer(1) / Integer(2):
            return sqrt(2 / (pi * x)) * cosh(x)
Пример #22
0
 def n_random_points(self,n):
     v = []
     while(len(v) < n):
         x = self.base_ring().random_element()
         test = (x**2 - 1)/(self._d*(x**2) - 1)
         if is_square(test):
             y = sqrt(test)
             v.append(self([x,y,1]))
     v.sort()
     return v        
Пример #23
0
    def __init__(self, n, instance='key', m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        all other parameters are chosen as in [CGW2013]_.

        INPUT:

        - ``n`` - security parameter (integer >= 89)
        - ``instance`` - one of

          - "key" - the LWE-instance that hides the secret key is generated
          - "encrypt" - the LWE-instance that hides the message is generated
            (default: ``key``)

        - ``m`` - number of allowed samples or ``None`` in which case ``m`` is
          chosen as in [CGW2013]_.  (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import UniformNoiseLWE
            sage: UniformNoiseLWE(89)
            LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131)

            sage: UniformNoiseLWE(89, instance='encrypt')
            LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181)
        """

        if n<89:
            raise TypeError("Parameter too small")

        n2 = n
        C  = 4/sqrt(2*pi)
        kk = floor((n2-2*log(n2, 2)**2)/5)
        n1 = floor((3*n2-5*kk)/2)
        ke = floor((n1-2*log(n1, 2)**2)/5)
        l  = floor((3*n1-5*ke)/2)-n2
        sk = ceil((C*(n1+n2))**(3/2))
        se = ceil((C*(n1+n2+l))**(3/2))
        q = next_prime(max(ceil((4*sk)**((n1+n2)/n1)), ceil((4*se)**((n1+n2+l)/(n2+l))), ceil(4*(n1+n2)*se*sk+4*se+1)))

        if kk<=0:
            raise TypeError("Parameter too small")

        if instance == 'key':
            D  = UniformSampler(0, sk-1)
            if m is None:
                m = n1
            LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m)
        elif instance == 'encrypt':
            D   = UniformSampler(0, se-1)
            if m is None:
                m = n2+l
            LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m)
        else:
            raise TypeError("Parameter instance=%s not understood."%(instance))
Пример #24
0
    def image_coordinates(self, x):
        """
        Return the image of the coordinates of the hyperbolic point ``x``
        under ``self``.

        EXAMPLES::

            sage: KM = HyperbolicPlane().KM()
            sage: UHP = HyperbolicPlane().UHP()
            sage: phi = UHP.coerce_map_from(KM)
            sage: phi.image_coordinates((0, 0))
            I
            sage: phi.image_coordinates((0, 1))
            +Infinity
        """
        if tuple(x) == (0, 1):
            return infinity
        return (-x[0]/(x[1] - 1)
                + I*(-(sqrt(-x[0]**2 - x[1]**2 + 1) - x[0]**2 - x[1]**2 + 1)
                     / ((x[1] - 1)*sqrt(-x[0]**2 - x[1]**2 + 1) + x[1] - 1)))
Пример #25
0
    def __init__(self, n, delta=0.01, m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP2011]_.

        INPUT:

        - ``n`` - security parameter (integer > 0)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``m=2*n +
          128`` as in [LP2011]_ (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import LindnerPeikert
            sage: LindnerPeikert(n=20)
            LWE(20, 2053, Discrete Gaussian sampler over the Integers with sigma = 3.600954 and c = 0, 'noise', 168)
        """
        if m is None:
            m = 2*n + 128
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #         (c*exp((1-c**2)/2))**(2*n) == 2**-40
        #    log((c*exp((1-c**2)/2))**(2*n)) == -40*log(2)
        #       (2*n)*log(c*exp((1-c**2)/2)) == -40*log(2)
        #  2*n*(log(c)+log(exp((1-c**2)/2))) == -40*log(2)
        #            2*n*(log(c)+(1-c**2)/2) == -40*log(2)
        #              2*n*log(c)+n*(1-c**2) == -40*log(2)
        #  2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP2011]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP2011]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D   = DiscreteGaussianDistributionIntegerSampler(stddev)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist='noise', m=m)
Пример #26
0
    def _derivative_(self, a, z, diff_param=None):
        """
        EXAMPLES::

            sage: diff(struve_H(3/2,x),x)
            -1/2*sqrt(2)*sqrt(1/(pi*x))*(cos(x) - 1) + 1/16*sqrt(2)*x^(3/2)/sqrt(pi) - 1/2*struve_H(5/2, x)
        """
        if diff_param == 0:
            raise ValueError("cannot differentiate struve_H in the first parameter")

        from sage.functions.other import sqrt, gamma
        return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_H(a+1,z)+struve_H(a-1,z))/2
Пример #27
0
    def compute_kappa_lambda_Q_from_mu_nu(self):
        """ Computes some kappa, lambda and Q from mu, nu, which might not be optimal for computational purposes
        """
        try:
	    from sage.functions.other import sqrt 
            from sage.rings.all import Integer
            from math import pi
            self.Q_fe = float(sqrt(Integer(self.level))/2.**len(self.nu_fe)/pi**(len(self.mu_fe)/2.+len(self.nu_fe)))
            self.kappa_fe = [.5 for m in self.mu_fe] + [1. for n in self.nu_fe] 
            self.lambda_fe = [m/2. for m in self.mu_fe] + [n for n in self.nu_fe]
        except Exception as e:
            raise Exception("Expecting a mu and a nu to be defined"+str(e))
 def __init__(self,dic,repr=None):
     self._reduction_dic = dic
     for key in dic.keys():
         self[key] = copy(dic[key])
     self._dim = int(sqrt(len(self.keys())))
     self._repr = repr
     if self._repr is None:
         self._repr = "This is a matrix reduction object: description missing"
     elif type(self._repr)!=str:
         raise ValueError, "Fifth input must be descriptive string or empty argument."
     else:
         self._repr = "This is a matrix reduction object: " + str(self._repr)
Пример #29
0
    def _derivative_(self, a, z, diff_param=None):
        """
        EXAMPLES::

            sage: diff(struve_L(1,x),x)
            1/3*x/pi - 1/2*struve_L(2, x) + 1/2*struve_L(0, x)
        """
        if diff_param == 0:
            raise ValueError("cannot differentiate struve_L in the first parameter")

        from sage.functions.other import sqrt, gamma
        return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_L(a+1,z)+struve_L(a-1,z))/2
Пример #30
0
def is_squareSum(x):
    """
    Determine whether an integer is a sum of two squares.
    """
    if x.is_prime():
        return x == 2 or x % 4 == 1
    i, j, y = -1, 0, x
    while j <= y:
        if sqrt(y).is_integer():
            return True
        i += 2
        j += i
        y -= i
    return False
Пример #31
0
    def _eval_(self, n, x):
        """
        EXAMPLES::

            sage: bessel_K(1,0)
            bessel_K(1, 0)
            sage: bessel_K(1.0, 0.0)
            +infinity
            sage: bessel_K(-1, 1).n(128)
            0.60190723019723457473754000153561733926
        """
        # special identity
        if n == Integer(1) / Integer(2) and x > 0:
            return sqrt(pi / 2) * exp(-x) * x**(-Integer(1) / Integer(2))
Пример #32
0
    def _eval_(self, n, x):
        """
        EXAMPLES::

            sage: bessel_K(1,0)
            bessel_K(1, 0)
            sage: bessel_K(1.0, 0.0)
            +infinity
            sage: bessel_K(-1, 1).n(128)
            0.60190723019723457473754000153561733926
        """
        # special identity
        if n == Integer(1) / Integer(2) and x > 0:
            return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2))
Пример #33
0
def gghlite_attacks(params, rerand=False):
    """
    Given parameters for a GGHLite-like problem instance estimate how
    long two lattice attacks would take.
    The two attacks are:
    - finding a short multiple of ‘g‘.
    - finding short ‘b_0/b_1‘ from ‘x_0/x_1‘
    :param params: parameters for a GGHLite-like graded encoding scheme
    :returns: cost estimate for lattice attacks
    """
    n = params["n"]
    q = params["q"]
    sigma = params[u"σ"]
    sigma_p = params[u"σ’"]
    # NTRU attack
    nt = OrderedDict()
    nt["n"] = n
    nt[u"τ"] = RR(_sage_const_0p3)
    base = (sqrt(q) / (sqrt(_sage_const_2) * sqrt(n) * sigma_p * nt[u"τ"]))
    if rerand:
        base = base / sigma
    nt[u"δ_0"] = RR(base**(_sage_const_1 / (_sage_const_2 * n)))
    nt = complete_lattice_attack(nt)
    return nt
Пример #34
0
    def translation_length(self): #UHP
        r"""
        For hyperbolic elements, return the translation length;
        otherwise, raise a ``ValueError``.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: UHP.get_isometry(matrix(2,[2,0,0,1/2])).translation_length()
            2*arccosh(5/4)

        ::

            sage: H = UHP.isometry_from_fixed_points(-1,1)
            sage: p = UHP.get_point(exp(i*7*pi/8))
            sage: Hp = H(p)
            sage: bool((UHP.dist(p, Hp) - H.translation_length()) < 10**-9)
            True
        """
        d = sqrt(self._matrix.det()**2)
        tau = sqrt((self._matrix / sqrt(d)).trace()**2)
        if self.classification() in ['hyperbolic', 'oriention-reversing hyperbolic']:
            return 2 * arccosh(tau/2)
        raise TypeError("translation length is only defined for hyperbolic transformations")
Пример #35
0
    def __init__(self, N, delta=0.01, m=None):
        """
        Construct a Ring-LWE oracle in dimension ``n=phi(N)`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP11]_.

        INPUT:

        - ``N`` - index of cyclotomic polynomial (integer > 0, must be power of 2)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``3*n`` is
          used (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import RingLindnerPeikert
            sage: RingLindnerPeikert(N=16)
            RingLWE(16, 1031, Discrete Gaussian sampler for polynomials of degree < 8 with σ=2.803372 in each component, x^8 + 1, 'noise', 24)
        """
        n = euler_phi(N)
        if m is None:
            m = 3*n
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #  i.e c>=1 such that 2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP11]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP11]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], n, stddev)
        RingLWE.__init__(self, N=N, q=q, D=D, poly=None, secret_dist='noise', m=m)
Пример #36
0
 def compute_kappa_lambda_Q_from_mu_nu(self):
     """ Computes some kappa, lambda and Q from mu, nu, which might not be optimal for computational purposes
     """
     try:
         from sage.functions.other import sqrt
         from sage.rings.all import Integer
         from math import pi
         self.Q_fe = float(
             sqrt(Integer(self.level)) / 2.**len(self.nu_fe) /
             pi**(len(self.mu_fe) / 2. + len(self.nu_fe)))
         self.kappa_fe = [.5 for m in self.mu_fe] + [1. for n in self.nu_fe]
         self.lambda_fe = [m / 2.
                           for m in self.mu_fe] + [n for n in self.nu_fe]
     except Exception as e:
         raise Exception("Expecting a mu and a nu to be defined" + str(e))
Пример #37
0
    def is_quasigeometric(self):
        """
        Decide whether the binary recurrence sequence is degenerate and similar to a geometric sequence,
        i.e. the union of multiple geometric sequences, or geometric after term ``u0``.

        If `\\alpha/\\beta` is a `k` th root of unity, where `k>1`, then necessarily `k = 2, 3, 4, 6`.
        Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is scaler
        matrix.  Thus for all values of `j` mod `k`, the `j` mod `k` terms of `u_n` form a geometric
        series.

        If `\\alpha` or `\\beta` is zero, this implies that `c=0`.  This is the case when `F` is
        singular.  In this case, `u_1, u_2, u_3, ...` is geometric.

        EXAMPLES::

            sage: S = BinaryRecurrenceSequence(0,1)
            sage: [S(i) for i in range(10)]
            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
            sage: S.is_quasigeometric()
            True

            sage: R = BinaryRecurrenceSequence(3,0)
            sage: [R(i) for i in range(10)]
            [0, 1, 3, 9, 27, 81, 243, 729, 2187, 6561]
            sage: R.is_quasigeometric()
            True
        """

        #First test if F is singular... i.e. beta = 0
        if self.c == 0:
            return True

        #Otherwise test if alpha/beta is a root of unity that is not 1
        else:
            if (self.b**2 + 4 * self.c) != 0:  #thus alpha/beta != 1

                if (self.b**2 + 4 * self.c).is_square():
                    A = sqrt((self.b**2 + 4 * self.c))

                else:
                    K = QuadraticField((self.b**2 + 4 * self.c), 'x')
                    A = K.gen()

                if ((self.b + A) / (self.b - A))**(6) == 1:
                    return True

        return False
Пример #38
0
def weight_class(length, weight):
    r"""
    Return the weight class corresponding to a given length and weight.

    The length is the length of the truth table of a Boolean function.
    The weight is the Hamming weight of the Boolean function.

    INPUT:

    - ``length`` -- positive integer:
    - ``weight`` -- positive integer: the given Hamming weight.

    OUTPUT:

    An integer representing the weight class corresponding to ``length`` and
    ``weight``.

    EXAMPLES:

    ::

        sage: from boolean_cayley_graphs.weight_class import weight_class
        sage: weight_class(4,1)
        0
        sage: weight_class(16,10)
        1
        sage: weight_class(16,6)
        0
        sage: weight_class(64,36)
        1
        sage: weight_class(63,37)
        1
        sage: weight_class(65,35)
        0

    .. NOTE::

        The weight class really only makes sense for bent functions, for which
        the weight class is either 0 or 1 [Leo2017]_.

    REFERENCES:

    Leopardi [Leo2017]_ Section 2.2.

    """
    sqrtlength = sqrt(length)
    return int(((weight*2)/sqrtlength - sqrtlength + 1) / 2)
Пример #39
0
def johnson_radius(n, d):
    r"""
    Returns the Johnson-radius for the code length `n` and the minimum distance `d`.

    The Johnson radius is defined as `n - \sqrt(n(n-d))`.

    INPUT:

    - ``n`` -- an integer, the length of the code
    - ``d`` -- an integer, the minimum distance of the code

    EXAMPLES::

        sage: sage.coding.guruswami_sudan.utils.johnson_radius(250, 181)
        -5*sqrt(690) + 250
    """
    return n - sqrt(n * (n - d))
Пример #40
0
    def lift(self, x):
        """
        INPUT:
         - ``x`` -- an element of ``self``

        Lifts ``x`` to the ambient space for ``self``, as per
        :meth:`Sets.Subquotients.ParentMethods.lift()
        <sage.categories.sets_cat.Sets.Subquotients.ParentMethods.lift>`.

        EXAMPLES::

            sage: C = FiniteEnumeratedSets().IsomorphicObjects().example(); C
            The image by some isomorphism of An example of a finite enumerated set: {1,2,3}
            sage: C.lift(9)
            3
        """
        return sqrt(x)
Пример #41
0
def platonic_tetrahedron():
    r"""Produce a triple consisting of a polyhedral version of the platonic tetrahedron,
    the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface
    to the polyhedron.

    EXAMPLES::

    sage: from flatsurf.geometry.polyhedra import platonic_tetrahedron
    sage: polyhedron,surface,surface_to_polyhedron = platonic_tetrahedron()
    sage: TestSuite(surface).run()
    r"""
    vertices = []
    for x in range(-1, 3, 2):
        for y in range(-1, 3, 2):
            vertices.append(vector(QQ, (x, y, x * y)))
    p = Polyhedron(vertices=vertices)
    s, m = polyhedron_to_cone_surface(p, scaling_factor=AA(1 / sqrt(2)))
    return p, s, m
Пример #42
0
 def normalize_cusps(self, areas=None):
     """
     Scale cusp so that they have the given target area.
     Without argument, each cusp is scaled to have area 1.
     If the argument is a number, scale each cusp to have that area.
     If the argument is an array, scale each cusp by the respective
     entry in the array.
     """
     current_areas = self.cusp_areas()
     if not areas:
         areas = [1 for area in current_areas]
     elif not isinstance(areas, list):
         areas = [areas for area in current_areas]
     scales = [
         sqrt(area / current_area)
         for area, current_area in zip(areas, current_areas)
     ]
     self.scale_cusps(scales)
    def evaluate_mu(self, affine_parameter, solution_key=None):
        r"""
        Compute the mass parameter `\mu` at a given value of the affine
        parameter `\lambda`.

        INPUT:

        - ``affine_parameter`` -- value of the affine parameter `\lambda`
        - ``solution_key`` -- (default: ``None``) string denoting the numerical
          solution to use for the evaluation; if ``None``, the latest solution
          computed by :meth:`integrate` is used.

        OUTPUT:

        - value of `\mu`

        """
        return sqrt(
            self.evaluate_mu2(affine_parameter, solution_key=solution_key))
Пример #44
0
    def _an_element_3d(self, x=0, y=0):
        r"""
        Returns an element in self.

        EXAMPLES::

            sage: from slabbe import DiscreteHyperplane
            sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=10)
            sage: p._an_element_3d()
            (0, 0, 0)
        """
        a, b, c = self._v
        x_sqrt3 = ceil(x / sqrt(3))
        left = ((a + b) * y + (a - b) * x_sqrt3 - self._mu) / (a + b + c)
        right = ((a + b) * y +
                 (a - b) * x_sqrt3 - self._mu + self._omega) / (a + b + c)
        #print "left, right = ", left, right
        #print "left, right = ", ceil(left), ceil(right)-1
        # left <= z <= right
        znew = ceil(left)
        xnew = znew - y - x_sqrt3
        ynew = znew - y + x_sqrt3
        znew = ceil(right) - 1
        #print xnew, ynew, znew
        #print vector((xnew, ynew, znew)) in self
        #print vector((x,y,ceil(right)-1)) in self
        v = vector((xnew, ynew, znew))
        if v in self:
            v.set_immutable()
            return v
        else:
            print "%s not in the plane" % v
            print "trying similar points"
            v = vector((xnew, ynew, znew - 1))
            if v in self:
                v.set_immutable()
                return v
            v = vector((xnew, ynew, znew + 1))
            if v in self:
                v.set_immutable()
                return v
        raise ValueError("%s not in the plane" % v)
Пример #45
0
    def get_background_graphic(self, **bdry_options):
        r"""
        Return a graphic object that makes the model easier to visualize.
        For the hyperboloid model, the background object is the hyperboloid
        itself.

        EXAMPLES::

            sage: H = HyperbolicPlane().HM().get_background_graphic()
        """
        from sage.plot.plot3d.all import plot3d
        from sage.all import SR
        hyperboloid_opacity = bdry_options.get('hyperboloid_opacity', .1)
        z_height = bdry_options.get('z_height', 7.0)
        x_max = sqrt((z_height ** 2 - 1) / 2.0)
        x = SR.var('x')
        y = SR.var('y')
        return plot3d((1 + x ** 2 + y ** 2).sqrt(),
                      (x, -x_max, x_max), (y,-x_max, x_max),
                      opacity=hyperboloid_opacity, **bdry_options)
Пример #46
0
def platonic_octahedron():
    r"""Produce a triple consisting of a polyhedral version of the platonic octahedron,
    the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface
    to the polyhedron.

    EXAMPLES::

    sage: from flatsurf.geometry.polyhedra import platonic_octahedron
    sage: polyhedron,surface,surface_to_polyhedron = platonic_octahedron()
    sage: TestSuite(surface).run()
    r"""
    vertices = []
    for i in range(3):
        temp = vector(QQ, [1 if k == i else 0 for k in range(3)])
        for j in range(-1, 3, 2):
            vertices.append(j * temp)
    octahedron = Polyhedron(vertices=vertices)
    surface,surface_to_octahedron = \
        polyhedron_to_cone_surface(octahedron,scaling_factor=AA(sqrt(2)))
    return octahedron, surface, surface_to_octahedron
Пример #47
0
    def change_iso_curve(self, a):
        """
        INPUT:
        * a the montgomery a coefficient of the target curve
        OUTPUT:
        * the point P seen in the new curve
        """
        a1 = self.curve.Fp2(self.curve.a)
        if (a**2 - 4) * (a1**2 - 3)**3 != (a1**2 - 4) * (a**2 - 3)**3:
            # i.e if  256*(a1**2 - 3)**3/(a1**2 - 4) != 256*(a**2 - 3)**3/(a**2 - 4)
            raise RuntimeError('the curves are not isomorphic.')
        E_a1 = EllipticCurve(self.curve.Fp2, [0, a1, 0, 1, 0])
        E_a = EllipticCurve(self.curve.Fp2, [0, a, 0, 1, 0])
        xP = self.x / self.z
        yP = sqrt(xP**3 + a1 * xP**2 + xP)

        P_ws = E_a1(xP, yP)
        iso = E_a1.isomorphism_to(E_a)
        curve_target = copy(self.curve)
        curve_target.a = a
        return Point(iso(P_ws)[0], 1, curve_target)
Пример #48
0
    def _eval_(self, n, x):
        """
        EXAMPLES::

            sage: bessel_K(1,0)
            bessel_K(1, 0)
            sage: bessel_K(1.0, 0.0)
            +infinity
            sage: bessel_K(-1, 1).n(128)
            0.60190723019723457473754000153561733926
        """
        if (not isinstance(n, Expression) and not isinstance(x, Expression)
                and (is_inexact(n) or is_inexact(x))):
            coercion_model = get_coercion_model()
            n, x = coercion_model.canonical_coercion(n, x)
            return self._evalf_(n, x, parent(n))

        # special identity
        if n == Integer(1) / Integer(2) and x > 0:
            return sqrt(pi / 2) * exp(-x) * x**(-Integer(1) / Integer(2))

        return None  # leaves the expression unevaluated
Пример #49
0
    def inner_horizon_radius(self):
        r"""
        Return the value of the Boyer-Lindquist coordinate `r` at the inner
        horizon (Cauchy horizon).

        EXAMPLES::

            sage: from kerrgeodesic_gw import KerrBH
            sage: a, m = var('a m')
            sage: BH = KerrBH(a, m)
            sage: BH.inner_horizon_radius()
            m - sqrt(-a^2 + m^2)

        An alias is ``cauchy_horizon_radius()``::

            sage: BH.cauchy_horizon_radius()
            m - sqrt(-a^2 + m^2)

        """
        m = self._m
        a = self._a
        return m - sqrt(m**2 - a**2)
Пример #50
0
    def __iter__(self):
        if self.__disc is infinity:
            raise ValueError("infinity is not a true filter index")

        if self.__reduced:
            for c in range(0, self._indefinite_content_bound()):
                yield (0, 0, c)

            for a in range(1, isqrt(self.__disc // 3) + 1):
                for b in range(a + 1):
                    for c in range(a,
                                   (b**2 + (self.__disc - 1)) // (4 * a) + 1):
                        yield (a, b, c)
        else:
            ##FIXME: These are not all matrices
            for a in range(0, self._indefinite_content_bound()):
                yield (a, 0, 0)
            for c in range(1, self._indefinite_content_bound()):
                yield (0, 0, c)

            maxtrace = floor(5 * self.__disc / 15 + sqrt(self.__disc) / 2)
            for a in range(1, maxtrace + 1):
                for c in range(1, maxtrace - a + 1):
                    Bu = isqrt(4 * a * c - 1)

                    di = 4 * a * c - self.__disc
                    if di >= 0:
                        Bl = isqrt(di) + 1
                    else:
                        Bl = 0

                    for b in range(-Bu, -Bl + 1):
                        yield (a, b, c)
                    for b in range(Bl, Bu + 1):
                        yield (a, b, c)
        #! if self.__reduced

        raise StopIteration
Пример #51
0
    def ideal_endpoints(self):
        r"""
        Determine the ideal (boundary) endpoints of the complete
        hyperbolic geodesic corresponding to ``self``.

        OUTPUT:

        - a list of 2 boundary points

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: UHP.get_geodesic(I, 2*I).ideal_endpoints()
            [Boundary point in UHP 0,
             Boundary point in UHP +Infinity]
            sage: UHP.get_geodesic(1 + I, 2 + 4*I).ideal_endpoints()
            [Boundary point in UHP -sqrt(65) + 9,
             Boundary point in UHP sqrt(65) + 9]
        """
        start = self._start.coordinates()
        end = self._end.coordinates()
        [x1, x2] = [real(k) for k in [start, end]]
        [y1, y2] = [imag(k) for k in [start, end]]
        M = self._model
        # infinity is the first endpoint, so the other ideal endpoint
        # is just the real part of the second coordinate
        if start == infinity:
            return [M.get_point(start), M.get_point(x2)]
        # Same idea as above
        if end == infinity:
            return [M.get_point(x1), M.get_point(end)]
        # We could also have a vertical line with two interior points
        if x1 == x2:
            return [M.get_point(x1), M.get_point(infinity)]
        # Otherwise, we have a semicircular arc in the UHP
        c = ((x1 + x2) * (x2 - x1) + (y1 + y2) * (y2 - y1)) / (2 * (x2 - x1))
        r = sqrt((c - x1)**2 + y1**2)
        return [M.get_point(c - r), M.get_point(c + r)]
Пример #52
0
    def evaluate_mu(self, affine_parameter, solution_key=None):
        r"""
        Compute the mass parameter `\mu` at a given value of the affine
        parameter `\lambda`.

        INPUT:

        - ``affine_parameter`` -- value of the affine parameter `\lambda`
        - ``solution_key`` -- (default: ``None``) string denoting the numerical
          solution to use for the evaluation; if ``None``, the latest solution
          computed by :meth:`integrate` is used.

        OUTPUT:

        - value of `\mu`

        """
        p = self.evaluate_tangent_vector(affine_parameter,
                                         solution_key=solution_key)
        point = p.parent().base_point()
        g = self._spacetime.metric().at(point)
        mu = sqrt(-g(p, p))
        return mu.substitute(self._numerical_substitutions())
Пример #53
0
    def __init__(self, n, secret_dist='uniform', m=None):
        """
        Construct LWE instance parameterised by security paramter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise are chosen as in
        [Reg09]_.

        INPUT:

        - ``n`` - security paramter (integer > 0)
        - ``secret_dist`` - distribution of the secret. See documentation of :class:`LWE`
          for details (default='uniform')
        - ``m`` - number of allowed samples or ``None`` if no such limit exists
          (default: ``None``)

        EXAMPLES::

            sage: Regev(n=20)
            LWE(20, 401, DiscreteGaussianSamplerRejection(1.915069, 401, 4), 'uniform', None)
        """
        q = ZZ(next_prime(n**2))
        s = RR(1 / (RR(n).sqrt() * log(n, 2)**2) * q)
        D = DiscreteGaussianSampler(s / sqrt(2 * pi.n()), q)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist=secret_dist, m=m)
Пример #54
0
    def mu(self, epsilon=1e-12):
        """
        Returns rescaling factor associated to the couple with precision epsilon
        in the search of the root of the contact function.
        """

        eta = var('eta')

        Y = (eta * self.ellipsoid2.red_belonging_matrix().inverse() +
             (1 - eta) * self.ellipsoid1.red_belonging_matrix().inverse())

        p = (eta * (1 - eta) *
             ((self.ellipsoid2.pos - self.ellipsoid1.pos).transpose()) *
             (Y.adjugate()) * (self.ellipsoid2.pos - self.ellipsoid1.pos))
        q = Y.determinant()

        h = expand(p.derivative(eta) * q - p * q.derivative(eta))[0, 0]
        F = expand(p / q)[0, 0]

        root, iter = halleyMethod(
            h, eta, self.ellipsoid1.R[0] /
            (self.ellipsoid1.R[0] + self.ellipsoid2.R[0]), epsilon)
        return sqrt(F(eta=root))
Пример #55
0
    def perpendicular_bisector(self):  # UHP
        r"""
        Return the perpendicular bisector of the hyperbolic geodesic ``self``
        if that geodesic has finite length.

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: g = UHP.random_geodesic()
            sage: h = g.perpendicular_bisector()
            sage: c = lambda x: x.coordinates()
            sage: bool(c(g.intersection(h)[0]) - c(g.midpoint()) < 10**-9)
            True

        Infinite geodesics cannot be bisected::

            sage: UHP.get_geodesic(0, 1).perpendicular_bisector()
            Traceback (most recent call last):
            ...
            ValueError: the length must be finite
        """
        if self.length() == infinity:
            raise ValueError("the length must be finite")
        start = self._start.coordinates()
        d = self._model._dist_points(start, self._end.coordinates()) / 2
        S = self.complete()._to_std_geod(start)
        T1 = matrix([[exp(d / 2), 0], [0, exp(-d / 2)]])
        s2 = sqrt(2) * 0.5
        T2 = matrix([[s2, -s2], [s2, s2]])
        isom_mtrx = S.inverse() * (T1 * T2) * S
        # We need to clean this matrix up.
        if (isom_mtrx - isom_mtrx.conjugate()).norm() < 5 * EPSILON:
            # Imaginary part is small.
            isom_mtrx = (isom_mtrx + isom_mtrx.conjugate()) / 2
            # Set it to its real part.
        H = self._model.get_isometry(isom_mtrx)
        return self._model.get_geodesic(H(self._start), H(self._end))
Пример #56
0
    def icosahedron(self, base_ring=QQ):
        """
        Return an icosahedron with edge length 1.

        INPUT:

        - ``base_ring`` -- Either ``QQ`` or ``RDF``.

        OUTPUT:

        A Polyhedron object of a floating point or rational
        approximation to the regular 3d icosahedron.

        If ``base_ring=QQ``, a rational approximation is used and the
        points are not exactly the vertices of the icosahedron. The
        icosahedron's coordinates contain the golden ratio, so there
        is no exact representation possible.

        EXAMPLES::

            sage: ico = polytopes.icosahedron()
            sage: sum(sum( ico.vertex_adjacency_matrix() ))/2
            30
        """
        if base_ring == QQ:
            g = QQ(1618033) / 1000000  # Golden ratio approximation
            r12 = QQ(1) / 2
        elif base_ring == RDF:
            g = RDF((1 + sqrt(5)) / 2)
            r12 = RDF(QQ(1) / 2)
        else:
            raise ValueError("field must be QQ or RDF.")
        verts = [i([0, r12, g / 2]) for i in AlternatingGroup(3)]
        verts = verts + [i([0, r12, -g / 2]) for i in AlternatingGroup(3)]
        verts = verts + [i([0, -r12, g / 2]) for i in AlternatingGroup(3)]
        verts = verts + [i([0, -r12, -g / 2]) for i in AlternatingGroup(3)]
        return Polyhedron(vertices=verts, base_ring=base_ring)
Пример #57
0
    def isco_radius(self, retrograde=False):
        r"""
        Return the Boyer-Lindquist radial coordinate of the innermost stable
        circular orbit (ISCO) in the equatorial plane.

        INPUT:

        - ``retrograde`` -- (default: ``False``) boolean determining whether
          retrograde or prograde (direct) orbits are considered

        OUTPUT:

        - Boyer-Lindquist radial coordinate `r` of the innermost stable
          circular orbit in the equatorial plane

        EXAMPLES::

            sage: from kerrgeodesic_gw import KerrBH
            sage: a, m = var('a m')
            sage: BH = KerrBH(a, m)
            sage: BH.isco_radius()
            m*(sqrt((((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) + 1)^2
             + 3*a^2/m^2) - sqrt(-(((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3)
             + 2*sqrt((((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) + 1)^2
             + 3*a^2/m^2) + 4)*(((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) - 2)) + 3)
            sage: BH.isco_radius(retrograde=True)
            m*(sqrt((((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) + 1)^2
             + 3*a^2/m^2) + sqrt(-(((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3)
             + 2*sqrt((((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) + 1)^2
             + 3*a^2/m^2) + 4)*(((a/m + 1)^(1/3) + (-a/m + 1)^(1/3))*(-a^2/m^2 + 1)^(1/3) - 2)) + 3)
            sage: KerrBH(0.5).isco_radius()  # tol 1.0e-13
            4.23300252953083
            sage: KerrBH(0.9).isco_radius()  # tol 1.0e-13
            2.32088304176189
            sage: KerrBH(0.98).isco_radius()  # tol 1.0e-13
            1.61402966763547

        ISCO in Schwarzschild spacetime::

            sage: KerrBH(0, m).isco_radius()
            6*m

        ISCO in extreme Kerr spacetime (`a=m`)::

            sage: KerrBH(m, m).isco_radius()
            m
            sage: KerrBH(m, m).isco_radius(retrograde=True)
            9*m

        """
        m = self._m
        a = self._a
        eps = -1 if not retrograde else 1
        # Eq. (2.21) in Bardeen, Press & Teukolsky, ApJ 178, 347 (1972)
        asm = a / m
        asm2 = asm**2
        one_third = QQ(1) / QQ(3)
        z1 = 1 + (1 - asm2)**one_third * ((1 + asm)**one_third +
                                          (1 - asm)**one_third)
        z2 = sqrt(3 * asm2 + z1**2)
        return m * (3 + z2 + eps * sqrt((3 - z1) * (3 + z1 + 2 * z2)))
Пример #58
0
def revolution_plot3d(curve,
                      trange,
                      phirange=None,
                      parallel_axis='z',
                      axis=(0, 0),
                      print_vector=False,
                      show_curve=False,
                      **kwds):
    """
    Return a plot of a revolved curve.

    There are three ways to call this function:

    - ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.

    - ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.

    - ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.

    INPUT:

    - ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.

    - ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.

    - ``phirange`` - A 2-tuple of the form `(\phi_{\min},\phi_{\max})`, (default `(0,\pi)`) that specifies the angle in which the curve is to be revolved.

    - ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.

    - ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:

        - 'z' - then axis is the point in which the revolution axis intersects the  `x y` plane.

        - 'x' - then axis is the point in which the revolution axis intersects the  `y z` plane.

        - 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.

    - ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.

    - ``show_curve`` - If True, the curve will be displayed.


    EXAMPLES:

    Let's revolve a simple function around different axes::

        sage: u = var('u')
        sage: f=u^2
        sage: revolution_plot3d(f,(u,0,2),show_curve=True,opacity=0.7).show(aspect_ratio=(1,1,1))

    If we move slightly the axis, we get a goblet-like surface::

        sage: revolution_plot3d(f,(u,0,2),axis=(1,0.2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    A common problem in calculus books, find the volume within the following revolution solid::

        sage: line=u
        sage: parabola=u^2
        sage: sur1=revolution_plot3d(line,(u,0,1),opacity=0.5,rgbcolor=(1,0.5,0),show_curve=True,parallel_axis='x')
        sage: sur2=revolution_plot3d(parabola,(u,0,1),opacity=0.5,rgbcolor=(0,1,0),show_curve=True,parallel_axis='x')
        sage: (sur1+sur2).show()


    Now let's revolve a parametrically defined circle. We can play with the topology of the surface by changing the axis, an axis in `(0,0)` (as the previous one) will produce a sphere-like surface::

        sage: u = var('u')
        sage: circle=(cos(u),sin(u))
        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    An axis on `(0,y)` will produce a cylinder-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    And any other axis will produce a torus-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(2,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    Now, we can get another goblet-like surface by revolving a curve in 3d::

        sage: u = var('u')
        sage: curve=(u,cos(4*u),u^2)
        sage: revolution_plot3d(curve,(u,0,2),show_curve=True,parallel_axis='z',axis=(1,.2),opacity=0.5).show(aspect_ratio=(1,1,1))

    A curvy curve with only a quarter turn::

        sage: u = var('u')
        sage: curve=(sin(3*u),.8*cos(4*u),cos(u))
        sage: revolution_plot3d(curve,(u,0,pi),(0,pi/2),show_curve=True,parallel_axis='z',opacity=0.5).show(aspect_ratio=(1,1,1),frame=False)
    """
    from sage.symbolic.ring import SR
    from sage.symbolic.constants import pi
    from sage.functions.other import sqrt
    from sage.functions.trig import sin
    from sage.functions.trig import cos
    from sage.functions.trig import atan2

    if parallel_axis not in ['x', 'y', 'z']:
        raise ValueError("parallel_axis must be either 'x', 'y', or 'z'.")

    vart = trange[0]

    if str(vart) == 'phi':
        phi = SR.var('fi')
    else:
        phi = SR.var('phi')

    if phirange is None:  #this if-else provides a phirange
        phirange = (phi, 0, 2 * pi)
    elif len(phirange) == 3:
        phi = phirange[0]
        pass
    else:
        phirange = (phi, phirange[0], phirange[1])

    if isinstance(curve, tuple) or isinstance(curve, list):
        #this if-else provides a vector v to be plotted
        #if curve is a tuple or a list of length 2, it is interpreted as a parametric curve
        #in the x-z plane.
        #if it is of length 3 it is interpreted as a parametric curve in 3d space

        if len(curve) == 2:
            x = curve[0]
            y = 0
            z = curve[1]
        elif len(curve) == 3:
            x = curve[0]
            y = curve[1]
            z = curve[2]
    else:
        x = vart
        y = 0
        z = curve

    if parallel_axis == 'z':
        x0 = axis[0]
        y0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if x0 != 0 or y0 != 0:
            phase = atan2((y - y0), (x - x0))
        R = sqrt((x - x0)**2 + (y - y0)**2)
        v = (R * cos(phi + phase) + x0, R * sin(phi + phase) + y0, z)
    elif parallel_axis == 'x':
        y0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if z0 != 0 or y0 != 0:
            phase = atan2((z - z0), (y - y0))
        R = sqrt((y - y0)**2 + (z - z0)**2)
        v = (x, R * cos(phi + phase) + y0, R * sin(phi + phase) + z0)
    elif parallel_axis == 'y':
        x0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if z0 != 0 or x0 != 0:
            phase = atan2((z - z0), (x - x0))
        R = sqrt((x - x0)**2 + (z - z0)**2)
        v = (R * cos(phi + phase) + x0, y, R * sin(phi + phase) + z0)

    if print_vector:
        print(v)
    if show_curve:
        curveplot = parametric_plot3d((x, y, z),
                                      trange,
                                      thickness=2,
                                      rgbcolor=(1, 0, 0))
        return parametric_plot3d(v, trange, phirange, **kwds) + curveplot
    return parametric_plot3d(v, trange, phirange, **kwds)
Пример #59
0
    def is_degenerate(self):
        """
        Decide whether the binary recurrence sequence is degenerate.

        Let `\\alpha` and `\\beta` denote the roots of the characteristic polynomial
        `p(x) = x^2-bx -c`.  Let `a = u_1-u_0\\beta/(\\beta - \\alpha)` and
        `b = u_1-u_0\\alpha/(\\beta - \\alpha)`.  The sequence is, thus, given by
        `u_n = a \\alpha^n - b\\beta^n`.  Then we say that the sequence is nondegenerate
        if and only if `a*b*\\alpha*\\beta \\neq 0` and `\\alpha/\\beta` is not a
        root of unity.

        More concretely, there are 4 classes of degeneracy, that can all be formulated
        in terms of the matrix `F = [[0,1], [c, b]]`.

        - `F` is singular --  this corresponds to ``c`` = 0, and thus `\\alpha*\\beta = 0`. This sequence is geometric after term ``u0`` and so we call it ``quasigeometric``.

        - `v = [[u_0], [u_1]]` is an eigenvector of `F` -- this corresponds to a ``geometric`` sequence with `a*b = 0`.

        - `F` is nondiagonalizable -- this corresponds to `\\alpha = \\beta`.  This sequence will be the point-wise product of an arithmetic and geometric sequence.

        - `F^k` is scaler, for some `k>1` -- this corresponds to `\\alpha/\\beta` a `k` th root of unity. This sequence is a union of several geometric sequences, and so we again call it ``quasigeometric``.

        EXAMPLES::

            sage: S = BinaryRecurrenceSequence(0,1)
            sage: S.is_degenerate()
            True
            sage: S.is_geometric()
            False
            sage: S.is_quasigeometric()
            True

            sage: R = BinaryRecurrenceSequence(3,-2)
            sage: R.is_degenerate()
            False

            sage: T = BinaryRecurrenceSequence(2,-1)
            sage: T.is_degenerate()
            True
            sage: T.is_arithmetic()
            True

        """

        if (self.b**2 + 4 * self.c) != 0:

            if (self.b**2 + 4 * self.c).is_square():
                A = sqrt((self.b**2 + 4 * self.c))

            else:
                K = QuadraticField((self.b**2 + 4 * self.c), 'x')
                A = K.gen()

            aa = (self.u1 - self.u0 *
                  (self.b + A) / 2) / (A)  #called `a` in Docstring
            bb = (self.u1 - self.u0 *
                  (self.b - A) / 2) / (A)  #called `b` in Docstring

            #(b+A)/2 is called alpha in Docstring, (b-A)/2 is called beta in Docstring

            if (self.b - A) != 0:
                if ((self.b + A) / (self.b - A))**(6) == 1:
                    return True
            else:
                return True

            if aa * bb * (self.b + A) * (self.b - A) == 0:
                return True
            return False
        return True
        def cartan_invariants_matrix(self):
            r"""
            Return the Cartan invariants matrix of the algebra.

            OUTPUT: a matrix of non negative integers

            Let `A` be this finite dimensional algebra and
            `(S_i)_{i\in I}` be representatives of the right simple
            modules of `A`. Note that their adjoints `S_i^*` are
            representatives of the left simple modules.

            Let `(P^L_i)_{i\in I}` and `(P^R_i)_{i\in I}` be
            respectively representatives of the corresponding
            indecomposable projective left and right modules of `A`.
            In particular, we assume that the indexing is consistent
            so that `S_i^*=\operatorname{top} P^L_i` and
            `S_i=\operatorname{top} P^R_i`.

            The *Cartan invariant matrix* `(C_{i,j})_{i,j\in I}` is a
            matrix of non negative integers that encodes much of the
            representation theory of `A`; namely:

            - `C_{i,j}` counts how many times `S_i^*\otimes S_j`
              appears as composition factor of `A` seen as a bimodule
              over itself;

            - `C_{i,j}=\dim Hom_A(P^R_j, P^R_i)`;

            - `C_{i,j}` counts how many times `S_j` appears as
              composition factor of `P^R_i`;

            - `C_{i,j}=\dim Hom_A(P^L_i, P^L_j)`;

            - `C_{i,j}` counts how many times `S_i^*` appears as
              composition factor of `P^L_j`.

            In the commutative case, the Cartan invariant matrix is
            diagonal. In the context of solving systems of
            multivariate polynomial equations of dimension zero, `A`
            is the quotient of the polynomial ring by the ideal
            generated by the equations, the simple modules correspond
            to the roots, and the numbers `C_{i,i}` give the
            multiplicities of those roots.

            .. NOTE::

                For simplicity, the current implementation, assumes
                that the index set `I` is of the form
                `\{0,\dots,n-1\}`. Better indexations will be possible
                in the future.

            ALGORITHM:

            The Cartan invariant matrix of `A` is computed from the
            dimension of the summands of its peirce decomposition.

            .. SEEALSO::

                - :meth:`peirce_decomposition`
                - :meth:`isotypic_projective_modules`

            EXAMPLES:

            For a semisimple algebra, in particular for group algebras
            in chararacteristic zero, the Cartan invariants matrix is
            the identity::

                sage: A3 = SymmetricGroup(3).algebra(QQ)
                sage: A3.cartan_invariants_matrix()
                [1 0 0]
                [0 1 0]
                [0 0 1]

            For the path algebra of a quiver, the Cartan invariants
            matrix counts the number of paths between two vertices::

                sage: A = Algebras(QQ).FiniteDimensional().WithBasis().example()
                sage: A.cartan_invariants_matrix()
                [1 2]
                [0 1]

            In the commutative case, the Cartan invariant matrix is diagonal::

                sage: Z12 = Monoids().Finite().example(); Z12
                An example of a finite multiplicative monoid: the integers modulo 12
                sage: A = Z12.algebra(QQ)
                sage: A.cartan_invariants_matrix()
                [1 0 0 0 0 0 0 0 0]
                [0 1 0 0 0 0 0 0 0]
                [0 0 2 0 0 0 0 0 0]
                [0 0 0 1 0 0 0 0 0]
                [0 0 0 0 2 0 0 0 0]
                [0 0 0 0 0 1 0 0 0]
                [0 0 0 0 0 0 1 0 0]
                [0 0 0 0 0 0 0 2 0]
                [0 0 0 0 0 0 0 0 1]

            With the algebra of the `0`-Hecke monoid::

                sage: from sage.monoids.hecke_monoid import HeckeMonoid
                sage: A = HeckeMonoid(SymmetricGroup(4)).algebra(QQ)
                sage: A.cartan_invariants_matrix()
                [1 0 0 0 0 0 0 0]
                [0 2 1 0 1 1 0 0]
                [0 1 1 0 1 0 0 0]
                [0 0 0 1 0 1 1 0]
                [0 1 1 0 1 0 0 0]
                [0 1 0 1 0 2 1 0]
                [0 0 0 1 0 1 1 0]
                [0 0 0 0 0 0 0 1]
            """
            from sage.rings.integer_ring import ZZ
            A_quo = self.semisimple_quotient()
            idempotents_quo = A_quo.central_orthogonal_idempotents()
            # Dimension of simple modules
            dim_simples = [
                sqrt(A_quo.principal_ideal(e).dimension())
                for e in idempotents_quo
            ]
            # Orthogonal idempotents
            idempotents = self.orthogonal_idempotents_central_mod_radical()

            def C(i, j):
                summand = self.peirce_summand(idempotents[i], idempotents[j])
                return summand.dimension() / (dim_simples[i] * dim_simples[j])

            return Matrix(ZZ, len(idempotents), C)