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
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
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)
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
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)
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