Exemple #1
0
        def laplace(cls, self, parameters, variable, x='x', s='t'):
            r"""
            Returns the Laplace transform of self with respect to the variable
            var.

            INPUT:

            -  ``x`` - variable of self

            -  ``s`` - variable of Laplace transform.

            We assume that a piecewise function is 0 outside of its domain and
            that the left-most endpoint of the domain is 0.

            EXAMPLES::

                sage: x, s, w = var('x, s, w')
                sage: f = piecewise([[(0,1),1],[[1,2], 1-x]])
                sage: f.laplace(x, s)
                -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2
                sage: f.laplace(x, w)
                -e^(-w)/w + (w + 1)*e^(-2*w)/w^2 + 1/w - e^(-w)/w^2

            ::

                sage: y, t = var('y, t')
                sage: f = piecewise([[[1,2], 1-y]])
                sage: f.laplace(y, t)
                (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2

            ::

                sage: s = var('s')
                sage: t = var('t')
                sage: f1(t) = -t
                sage: f2(t) = 2
                sage: f = piecewise([[[0,1],f1],[(1,infinity),f2]])
                sage: f.laplace(t,s)
                (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2
            """
            from sage.all import assume, exp, forget
            x = SR.var(x)
            s = SR.var(s)
            assume(s > 0)
            result = 0
            for domain, f in parameters:
                for interval in domain:
                    a = interval.lower()
                    b = interval.upper()
                    result += (SR(f) * exp(-s * x)).integral(x, a, b)
            forget(s > 0)
            return result
Exemple #2
0
        def laplace(cls, self, parameters, variable, x='x', s='t'):
            r"""
            Returns the Laplace transform of self with respect to the variable
            var.

            INPUT:

            -  ``x`` - variable of self

            -  ``s`` - variable of Laplace transform.

            We assume that a piecewise function is 0 outside of its domain and
            that the left-most endpoint of the domain is 0.

            EXAMPLES::

                sage: x, s, w = var('x, s, w')
                sage: f = piecewise([[(0,1),1],[[1,2], 1-x]])
                sage: f.laplace(x, s)
                -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2
                sage: f.laplace(x, w)
                -e^(-w)/w + (w + 1)*e^(-2*w)/w^2 + 1/w - e^(-w)/w^2

            ::

                sage: y, t = var('y, t')
                sage: f = piecewise([[[1,2], 1-y]])
                sage: f.laplace(y, t)
                (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2

            ::

                sage: s = var('s')
                sage: t = var('t')
                sage: f1(t) = -t
                sage: f2(t) = 2
                sage: f = piecewise([[[0,1],f1],[(1,infinity),f2]])
                sage: f.laplace(t,s)
                (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2
            """
            from sage.all import assume, exp, forget
            x = SR.var(x)
            s = SR.var(s)
            assume(s>0)
            result = 0
            for domain, f in parameters:
                for interval in domain:
                    a = interval.lower()
                    b = interval.upper()
                    result += (SR(f)*exp(-s*x)).integral(x,a,b)
            forget(s>0)
            return result
Exemple #3
0
        def integral(cls, self, parameters, variable, x=None, a=None, b=None, definite=False):
            r"""
            By default, return the indefinite integral of the function.
            If definite=True is given, returns the definite integral.

            AUTHOR:

            - Paul Butler

            EXAMPLES::

                sage: f1(x) = 1-x
                sage: f = piecewise([((0,1),1), ((1,2),f1)])
                sage: f.integral(definite=True)
                1/2

            ::

                sage: f1(x) = -1
                sage: f2(x) = 2
                sage: f = piecewise([((0,pi/2),f1), ((pi/2,pi),f2)])
                sage: f.integral(definite=True)
                1/2*pi

                sage: f1(x) = 2
                sage: f2(x) = 3 - x
                sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]])
                sage: f.integral()
                piecewise(x|-->2*x + 4 on (-2, 0), x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x)

                sage: f1(y) = -1
                sage: f2(y) = y + 3
                sage: f3(y) = -y - 1
                sage: f4(y) = y^2 - 1
                sage: f5(y) = 3
                sage: f = piecewise([[[-4,-3],f1],[(-3,-2),f2],[[-2,0],f3],[(0,2),f4],[[2,3],f5]])
                sage: F = f.integral(y)
                sage: F
                piecewise(y|-->-y - 4 on [-4, -3], y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), y|-->-1/2*y^2 - y - 1/2 on [-2, 0], y|-->1/3*y^3 - y - 1/2 on (0, 2), y|-->3*y - 35/6 on [2, 3]; y)

            Ensure results are consistent with FTC::

                sage: F(-3) - F(-4)
                -1
                sage: F(-1) - F(-3)
                1
                sage: F(2) - F(0)
                2/3
                sage: f.integral(y, 0, 2)
                2/3
                sage: F(3) - F(-4)
                19/6
                sage: f.integral(y, -4, 3)
                19/6
                sage: f.integral(definite=True)
                19/6

            ::

                sage: f1(y) = (y+3)^2
                sage: f2(y) = y+3
                sage: f3(y) = 3
                sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2], [(0, infinity), f3]])
                sage: f.integral()
                piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), y|-->3*y + 9/2 on (0, +oo); y)

            ::

                sage: f1(x) = e^(-abs(x))
                sage: f = piecewise([[(-infinity, infinity), f1]])
                sage: f.integral(definite=True)
                2
                sage: f.integral()
                piecewise(x|-->-1/2*((sgn(x) - 1)*e^(2*x) - 2*e^x*sgn(x) + sgn(x) + 1)*e^(-x) - 1 on (-oo, +oo); x)

            ::

                sage: f = piecewise([((0, 5), cos(x))])
                sage: f.integral()
                piecewise(x|-->sin(x) on (0, 5); x)


            TESTS:

            Verify that piecewise integrals of zero work (trac #10841)::

                sage: f0(x) = 0
                sage: f = piecewise([[[0,1],f0]])
                sage: f.integral(x,0,1)
                0
                sage: f = piecewise([[[0,1], 0]])
                sage: f.integral(x,0,1)
                0
                sage: f = piecewise([[[0,1], SR(0)]])
                sage: f.integral(x,0,1)
                0

            """
            if a != None and b != None:
                F = self.integral(x)
                return F(b) - F(a)

            if a != None or b != None:
                raise TypeError('only one endpoint given')

            area = 0
            new_pieces = []

            if x == None:
                x = self.default_variable()

            # The integral is computed by iterating over the pieces in order.
            # The definite integral for each piece is calculated and accumulated in `area`.
            # The indefinite integral of each piece is also calculated,
            # and the `area` before each piece is added to the piece.
            #
            # If a definite integral is requested, `area` is returned.
            # Otherwise, a piecewise function is constructed from the indefinite integrals
            # and returned.
            #
            # An exception is made if integral is called on a piecewise function
            # that starts at -infinity. In this case, we do not try to calculate the
            # definite integral of the first piece, and the value of `area` remains 0
            # after the first piece.

            from sage.symbolic.assumptions import assume, forget
            for domain, fun in parameters:
                for interval in domain:
                    start = interval.lower()
                    end = interval.upper()
                    if start == -infinity and not definite:
                        fun_integrated = fun.integral(x, end, x)
                    else:
                        try:
                            assume(start < x)
                        except ValueError: # Assumption is redundant
                            pass
                        fun_integrated = fun.integral(x, start, x) + area
                        forget(start < x)
                        if definite or end != infinity:
                            area += fun.integral(x, start, end)
                    new_pieces.append([interval, SR(fun_integrated).function(x)])

            if definite:
                return SR(area)
            else:
                return piecewise(new_pieces)
Exemple #4
0
def curve(nb_equipes, max_points=100, K=1, R=2, base=2, verbose=False):
    r"""
    INPUT:

    - ``nb_equipes`` -- integer
    - ``max_points`` -- integer
    - ``K`` -- the value at ``p = nb_equipes``
    - ``R`` -- real (default: ``2``), curve parameter
    - ``base`` -- 2
    - ``verbose`` - bool 

    EXEMPLES::

        sage: from slabbe.ranking_scale import curve
        sage: curve(20, 100)
        -99*(p*(log(40) + 1) - p*log(p) - 20*log(40) + 20*log(20) -
        20)/(19*log(40) - 20*log(20) + 19) + 1
        sage: curve(64, 100)
        99*(p*(7*log(2) + 1) - p*log(p) + 64*log(64) - 448*log(2) -
        64)/(64*log(64) - 441*log(2) - 63) + 1

    ::

        sage: curve(64, 100)(p=64)
        1
        sage: curve(64, 100)(p=1)
        100
        sage: curve(64, 100)(p=2)
        198*(32*log(64) - 218*log(2) - 31)/(64*log(64) - 441*log(2) - 63) + 1
        sage: n(curve(64, 100)(p=2))     # abs tol 1e-10
        95.6871477097753

    ::

        sage: curve(64, 100, verbose=True)
        fn = -(p*(7*log(2) + 1) - p*log(p) + 64*log(64) - 448*log(2) - 64)/log(2)
        aire = 147.889787576005
        fn normalise = 99*(p*(7*log(2) + 1) - p*log(p) + 64*log(64) - 448*log(2) - 64)/(64*log(64) - 441*log(2) - 63) + 1
        99*(p*(7*log(2) + 1) - p*log(p) + 64*log(64) - 448*log(2) - 64)/(64*log(64) - 441*log(2) - 63) + 1

    The base argument seems to be useless (why?)::

        sage: curve(100,100,base=3)
        -99*(p*(log(200) + 1) - p*log(p) - 100*log(200) + 100*log(100) -
        100)/(99*log(200) - 100*log(100) + 99) + 1
        sage: curve(100,100,base=2)
        -99*(p*(log(200) + 1) - p*log(p) - 100*log(200) + 100*log(100) -
        100)/(99*log(200) - 100*log(100) + 99) + 1
        
    """
    from sage.symbolic.assumptions import forget, assume
    from sage.misc.functional import integrate, n
    from sage.functions.log import log
    from sage.calculus.var import var
    x, p = var('x,p')
    forget()
    assume(p - 1 > 0)
    assume(p - nb_equipes < 0)
    fn = integrate(
        log(R * nb_equipes, base=base) - log(x, base=base), x, p, nb_equipes)
    if verbose: print "fn = %s" % fn
    aire = fn(p=1)
    if verbose: print "aire = %s" % n(aire)
    fn_normalise = fn / aire * (max_points - K) + K
    if verbose: print "fn normalise = %s" % fn_normalise
    return fn_normalise
Exemple #5
0
        def integral(cls,
                     self,
                     parameters,
                     variable,
                     x=None,
                     a=None,
                     b=None,
                     definite=False):
            r"""
            By default, return the indefinite integral of the function.
            If definite=True is given, returns the definite integral.

            AUTHOR:

            - Paul Butler

            EXAMPLES::

                sage: f1(x) = 1-x
                sage: f = piecewise([((0,1),1), ((1,2),f1)])
                sage: f.integral(definite=True)
                1/2

            ::

                sage: f1(x) = -1
                sage: f2(x) = 2
                sage: f = piecewise([((0,pi/2),f1), ((pi/2,pi),f2)])
                sage: f.integral(definite=True)
                1/2*pi

                sage: f1(x) = 2
                sage: f2(x) = 3 - x
                sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]])
                sage: f.integral()
                piecewise(x|-->2*x + 4 on (-2, 0), x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x)

                sage: f1(y) = -1
                sage: f2(y) = y + 3
                sage: f3(y) = -y - 1
                sage: f4(y) = y^2 - 1
                sage: f5(y) = 3
                sage: f = piecewise([[[-4,-3],f1],[(-3,-2),f2],[[-2,0],f3],[(0,2),f4],[[2,3],f5]])
                sage: F = f.integral(y)
                sage: F
                piecewise(y|-->-y - 4 on [-4, -3], y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), y|-->-1/2*y^2 - y - 1/2 on [-2, 0], y|-->1/3*y^3 - y - 1/2 on (0, 2), y|-->3*y - 35/6 on [2, 3]; y)

            Ensure results are consistent with FTC::

                sage: F(-3) - F(-4)
                -1
                sage: F(-1) - F(-3)
                1
                sage: F(2) - F(0)
                2/3
                sage: f.integral(y, 0, 2)
                2/3
                sage: F(3) - F(-4)
                19/6
                sage: f.integral(y, -4, 3)
                19/6
                sage: f.integral(definite=True)
                19/6

            ::

                sage: f1(y) = (y+3)^2
                sage: f2(y) = y+3
                sage: f3(y) = 3
                sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2], [(0, infinity), f3]])
                sage: f.integral()
                piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), y|-->3*y + 9/2 on (0, +oo); y)

            ::

                sage: f1(x) = e^(-abs(x))
                sage: f = piecewise([[(-infinity, infinity), f1]])
                sage: f.integral(definite=True)
                2
                sage: f.integral()
                piecewise(x|-->-1/2*((sgn(x) - 1)*e^(2*x) - 2*e^x*sgn(x) + sgn(x) + 1)*e^(-x) - 1 on (-oo, +oo); x)

            ::

                sage: f = piecewise([((0, 5), cos(x))])
                sage: f.integral()
                piecewise(x|-->sin(x) on (0, 5); x)


            TESTS:

            Verify that piecewise integrals of zero work (trac #10841)::

                sage: f0(x) = 0
                sage: f = piecewise([[[0,1],f0]])
                sage: f.integral(x,0,1)
                0
                sage: f = piecewise([[[0,1], 0]])
                sage: f.integral(x,0,1)
                0
                sage: f = piecewise([[[0,1], SR(0)]])
                sage: f.integral(x,0,1)
                0

            """
            if a != None and b != None:
                F = self.integral(x)
                return F(b) - F(a)

            if a != None or b != None:
                raise TypeError('only one endpoint given')

            area = 0
            new_pieces = []

            if x == None:
                x = self.default_variable()

            # The integral is computed by iterating over the pieces in order.
            # The definite integral for each piece is calculated and accumulated in `area`.
            # The indefinite integral of each piece is also calculated,
            # and the `area` before each piece is added to the piece.
            #
            # If a definite integral is requested, `area` is returned.
            # Otherwise, a piecewise function is constructed from the indefinite integrals
            # and returned.
            #
            # An exception is made if integral is called on a piecewise function
            # that starts at -infinity. In this case, we do not try to calculate the
            # definite integral of the first piece, and the value of `area` remains 0
            # after the first piece.

            from sage.symbolic.assumptions import assume, forget
            for domain, fun in parameters:
                for interval in domain:
                    start = interval.lower()
                    end = interval.upper()
                    if start == -infinity and not definite:
                        fun_integrated = fun.integral(x, end, x)
                    else:
                        try:
                            assume(start < x)
                        except ValueError:  # Assumption is redundant
                            pass
                        fun_integrated = fun.integral(x, start, x) + area
                        forget(start < x)
                        if definite or end != infinity:
                            area += fun.integral(x, start, end)
                    new_pieces.append(
                        [interval, SR(fun_integrated).function(x)])

            if definite:
                return SR(area)
            else:
                return piecewise(new_pieces)
Exemple #6
0
    def adapted_chart(self, index="", latex_index=""):
        r"""
        Create charts and changes of charts in the ambient manifold adapted
        to the foliation.

        A manifold `M` of dimension `m` can be foliated by submanifolds `N` of
        dimension `n`. The corresponding embedding needs `m-n` free parameters
        to describe the whole manifold.

        A set of coordinates adapted to a foliation is a set of coordinates
        `(x_1,...,x_n,t_1,...t_{m-n})` such that `(x_1,...x_n)` are coordinates
        of `N` and `(t_1,...t_{m-n})` are the `m-n` free parameters of the
        foliation.

        Provided that an embedding with free variables is already defined, this
        function constructs such charts and coordinates changes whenever
        it is possible.

        If there are restrictions of the coordinates on the starting chart,
        these restrictions are also propagated.

        INPUT:

        - ``index`` -- (default: ``""``) string defining the name of the
          coordinates in the new chart. This string will be added at the end of
          the names of the old coordinates. By default, it is replaced by
          ``"_"+self._ambient._name``
        - ``latex_index`` -- (default: ``""``) string defining the latex name
          of the coordinates in the new chart. This string will be added at the
          end of the latex names of the old coordinates. By default, it is
          replaced by ``"_"+self._ambient._latex_()``

        OUTPUT:

        - list of charts created from the charts of ``self``

        EXAMPLES::

            sage: M = Manifold(3, 'M', structure="topological")
            sage: N = Manifold(2, 'N', ambient=M, structure="topological")
            sage: N
            2-dimensional submanifold N embedded in 3-dimensional manifold M
            sage: CM.<x,y,z> = M.chart()
            sage: CN.<u,v> = N.chart()
            sage: t = var('t')
            sage: phi = N.continuous_map(M,{(CN,CM):[u,v,t+u**2+v**2]})
            sage: phi_inv = M.continuous_map(N,{(CM,CN):[x,y]})
            sage: phi_inv_t = M.scalar_field({CM:z-x**2-y**2})
            sage: N.set_immersion(phi, inverse=phi_inv, var=t,
            ....:                 t_inverse={t:phi_inv_t})
            sage: N.declare_embedding()
            sage: N.adapted_chart()
            [Chart (M, (u_M, v_M, t_M))]
        """
        if not self._embedded:
            raise ValueError("an embedding is required")

        if self._dim_foliation + self._dim != self._ambient._dim:
            raise ValueError("a foliation of dimension Dim(M)-Dim(N) is "
                             "needed to find an adapted chart")
        if not isinstance(index, str):
            raise TypeError("index must be a string")

        res = []
        self._subs = []

        # All possible expressions for the immersion
        domains = self._immersion._coord_expression.keys()
        postscript = index
        if index == "":
            postscript = "_" + self._ambient._name

        latex_postscript = latex_index
        if latex_postscript == "":
            latex_postscript = "_" + self._ambient._latex_()

        for domain in list(domains):
            name = " ".join([domain[0][i]._repr_()+postscript+":{"
                             + domain[0][i]._latex_()+"}"+latex_postscript
                             for i in self.irange()]) + " "\
                   + " ".join(v._repr_()+postscript for v in self._var)
            chart = domain[1]._domain.chart(name)
            if chart not in res:

                # Construct restrictions on coordinates:
                subs = {domain[0][i]: chart[:][i] for i in range(self._dim)}
                for i in range(len(self._var)):
                    subs[self._var[i]] = chart[:][self._dim + i]
                for rest in domain[0]._restrictions:
                    chart.add_restrictions(rest.subs(subs))
                for _a in assumptions(*(domain[0][:] + tuple(self._var))):
                    if isinstance(_a, Expression):
                        assume(_a.subs(subs))

                self._subs.append(subs)
                res.append(chart)
                self._immersion.add_expr(domain[0], chart,
                                         list(domain[0][:]) + self._var)
                self._immersion_inv.add_expr(chart, domain[0],
                                             chart[:][0:self._dim])
                for i in range(len(self._var)):
                    self._t_inverse[self._var[i]].add_expr(
                        chart[:][self._dim:][i], chart=chart)

        for (chartNV, chartMV) in self._immersion._coord_expression:
            for (chartNU, chartMU) in self._immersion._coord_expression:
                if chartMU is not chartMV and\
                        (chartMU, chartMV) not in self._ambient._coord_changes:
                    if (chartNU, chartNV) in self._coord_changes or \
                            chartNU is chartNV:
                        _f = self._immersion.coord_functions(chartNV, chartMV)
                        _g = self._coord_changes[(chartNU, chartNV)]._transf \
                            if chartNU is not chartNV else lambda *x: x
                        _h = self._immersion_inv.coord_functions(
                            chartMU, chartNU)
                        expr = list(_f(*_g(*_h(*chartMU[:]))))
                        substitutions = {
                            v: self._t_inverse[v].expr(chartMU)
                            for v in self._var
                        }
                        for i in range(len(expr)):
                            expr[i] = expr[i].subs(substitutions)

                        chartMU.transition_map(chartMV, expr)
        self._adapted_charts = res
        return res
    def adapted_chart(self, postscript=None, latex_postscript=None):
        r"""
        Create charts and changes of charts in the ambient manifold adapted
        to the foliation.

        A manifold `M` of dimension `m` can be foliated by submanifolds `N` of
        dimension `n`. The corresponding embedding needs `m-n` free parameters
        to describe the whole manifold.

        A chart adapted to the foliation is a set of coordinates
        `(x_1,\ldots,x_n,t_1,\ldots,t_{m-n})` on `M` such that
        `(x_1,\ldots,x_n)` are coordinates on `N` and `(t_1,\ldots,t_{m-n})`
        are the `m-n` free parameters of the foliation.

        Provided that an embedding with free variables is already defined, this
        function constructs such charts and coordinates changes whenever
        it is possible.

        If there are restrictions of the coordinates on the starting chart,
        these restrictions are also propagated.

        INPUT:

        - ``postscript`` -- (default: ``None``) string defining the name of the
          coordinates of the adapted chart. This string will be appended to
          the names of the coordinates `(x_1,\ldots,x_n)` and of the parameters
          `(t_1,\ldots,t_{m-n})`. If ``None``, ``"_" + self.ambient()._name``
          is used
        - ``latex_postscript`` -- (default: ``None``) string defining the LaTeX
          name of the coordinates of the adapted chart. This string will be
          appended to the LaTeX names of the coordinates `(x_1,\ldots,x_n)` and
          of the parameters `(t_1,\ldots,t_{m-n})`, If ``None``,
          ``"_" + self.ambient()._latex_()`` is used

        OUTPUT:

        - list of adapted charts on `M` created from the charts of ``self``

        EXAMPLES::

            sage: M = Manifold(3, 'M', structure="topological",
            ....:              latex_name=r"\mathcal{M}")
            sage: N = Manifold(2, 'N', ambient=M, structure="topological")
            sage: N
            2-dimensional topological submanifold N immersed in the
             3-dimensional topological manifold M
            sage: CM.<x,y,z> = M.chart()
            sage: CN.<u,v> = N.chart()
            sage: t = var('t')
            sage: phi = N.continuous_map(M, {(CN,CM): [u,v,t+u^2+v^2]})
            sage: phi_inv = M.continuous_map(N, {(CM,CN): [x,y]})
            sage: phi_inv_t = M.scalar_field({CM: z-x^2-y^2})
            sage: N.set_embedding(phi, inverse=phi_inv, var=t,
            ....:                 t_inverse={t:phi_inv_t})
            sage: N.adapted_chart()
            [Chart (M, (u_M, v_M, t_M))]
            sage: latex(_)
            \left[\left(\mathcal{M},({{u}_{\mathcal{M}}}, {{v}_{\mathcal{M}}},
             {{t}_{\mathcal{M}}})\right)\right]

        The adapted chart has been added to the atlas of ``M``::

            sage: M.atlas()
            [Chart (M, (x, y, z)), Chart (M, (u_M, v_M, t_M))]
            sage: N.atlas()
            [Chart (N, (u, v))]

        The names of the adapted coordinates can be customized::

            sage: N.adapted_chart(postscript='1', latex_postscript='_1')
            [Chart (M, (u1, v1, t1))]
            sage: latex(_)
            \left[\left(\mathcal{M},({{u}_1}, {{v}_1}, {{t}_1})\right)\right]

        """
        if not self._embedded:
            raise ValueError("an embedding is required")

        if self._dim_foliation + self._dim != self._ambient._dim:
            raise ValueError("a foliation of dimension dim(M) - dim(N) is "
                             "needed to find an adapted chart")
        res = []
        self._subs = []

        if postscript is None:
            postscript = "_" + self._ambient._name.replace("^", "")
            # NB: "^" is deleted from the name of ambient to get valid
            # Python identifiers for the symbolic variables representing the
            # coordinates
        if latex_postscript is None:
            latex_postscript = "_{" + self._ambient._latex_() + "}"

        # All possible expressions for the immersion
        chart_pairs = list(self._immersion._coord_expression.keys())
        for (chart1, chart2) in chart_pairs:
            name = " ".join(chart1[i]._repr_() + postscript + ":{"
                             + chart1[i]._latex_() + "}" + latex_postscript
                             for i in self.irange()) + " " \
                   + " ".join(v._repr_() + postscript + ":{" + v._latex_()
                              + "}" + latex_postscript for v in self._var)
            chart = chart2.domain().chart(name)
            if chart not in res:

                # Construct restrictions on coordinates:
                subs = {chart1[:][i]: chart[:][i] for i in range(self._dim)}
                # NB: chart1[:][i] is used instead of chart1[i] to allow for
                #     start_index != 0
                for i in range(len(self._var)):
                    subs[self._var[i]] = chart[:][self._dim + i]
                for rest in chart1._restrictions:
                    chart.add_restrictions(rest.subs(subs))
                for _a in assumptions(*(chart1[:] + tuple(self._var))):
                    if isinstance(_a, Expression):
                        assume(_a.subs(subs))

                self._subs.append(subs)
                res.append(chart)
                self._immersion.add_expr(chart1, chart,
                                         list(chart1[:]) + self._var)
                self._immersion_inv.add_expr(chart, chart1,
                                             chart[:][0:self._dim])
                for i in range(len(self._var)):
                    self._t_inverse[self._var[i]].add_expr(
                        chart[:][self._dim:][i], chart=chart)

        for (chartNV, chartMV) in self._immersion._coord_expression:
            for (chartNU, chartMU) in self._immersion._coord_expression:
                if chartMU is not chartMV and\
                        (chartMU, chartMV) not in self._ambient._coord_changes:
                    if (chartNU, chartNV) in self._coord_changes or \
                            chartNU is chartNV:
                        _f = self._immersion.coord_functions(chartNV, chartMV)
                        _g = self._coord_changes[(chartNU, chartNV)]._transf \
                            if chartNU is not chartNV else lambda *x: x
                        _h = self._immersion_inv.coord_functions(
                            chartMU, chartNU)
                        expr = list(_f(*_g(*_h(*chartMU[:]))))
                        substitutions = {
                            v: self._t_inverse[v].expr(chartMU)
                            for v in self._var
                        }
                        for i in range(len(expr)):
                            expr[i] = expr[i].subs(substitutions)

                        chartMU.transition_map(chartMV, expr)
        self._adapted_charts = res
        return res
Exemple #8
0
def curve(nb_equipes, max_points=100, K=1, R=2, base=2, verbose=False):
    r"""
    INPUT:

    - ``nb_equipes`` -- integer
    - ``max_points`` -- integer
    - ``K`` -- the value at ``p = nb_equipes``
    - ``R`` -- real (default: ``2``), curve parameter
    - ``base`` -- 2
    - ``verbose`` - bool 

    EXEMPLES::

        sage: from slabbe.ranking_scale import curve
        sage: curve(20, 100)
        -99*(p*(log(40) + 1) - p*log(p) - 20*log(40) + 20*log(20) -
        20)/(19*log(40) - 20*log(20) + 19) + 1
        sage: curve(64, 100)
        -33*(p*(7*log(2) + 1) - p*log(p) - 64*log(2) - 64)/(19*log(2) + 21) + 1

    ::

        sage: curve(64, 100)(p=64)
        1
        sage: curve(64, 100)(p=1)
        100
        sage: curve(64, 100)(p=2)
        66*(26*log(2) + 31)/(19*log(2) + 21) + 1
        sage: n(curve(64, 100)(p=2))     # abs tol 1e-10
        95.6871477097753

    ::

        sage: curve(64, 100, verbose=True)
        fn = -(p*(7*log(2) + 1) - p*log(p) - 64*log(2) - 64)/log(2)
        aire = 147.889787576005
        fn normalise = -33*(p*(7*log(2) + 1) - p*log(p) - 64*log(2) - 64)/(19*log(2) + 21) + 1
        -33*(p*(7*log(2) + 1) - p*log(p) - 64*log(2) - 64)/(19*log(2) + 21) + 1

    The base argument seems to be useless (why?)::

        sage: curve(100,100,base=3)
        -99*(p*(log(200) + 1) - p*log(p) - 100*log(200) + 200*log(10) - 
        100)/(99*log(200) - 200*log(10) + 99) + 1
        sage: curve(100,100,base=2)
        -99*(p*(log(200) + 1) - p*log(p) - 100*log(200) + 200*log(10) -
        100)/(99*log(200) - 200*log(10) + 99) + 1
        
    """
    from sage.symbolic.assumptions import forget, assume
    from sage.misc.functional import integrate, n
    from sage.functions.log import log
    from sage.calculus.var import var
    x,p = var('x,p')
    forget()
    assume(p - 1 > 0)
    assume(p-nb_equipes < 0)
    fn = integrate(log(R*nb_equipes, base=base) - log(x, base=base), x, p, nb_equipes)
    if verbose: print("fn = %s" % fn)
    aire = fn(p=1)
    if verbose: print("aire = %s" % n(aire))
    fn_normalise = fn / aire * (max_points - K) + K
    if verbose: print("fn normalise = %s" % fn_normalise)
    return fn_normalise