def test_issue1566(): # Allow only upper or lower limit evaluation e = Integral(x**2, (x, None, 1)) f = Integral(x**2, (x, 1, None)) assert e.doit() == Rational(1, 3) assert f.doit() == Rational(-1, 3) assert Integral(x*y, (x, None, y)).subs(y, t) == Integral(x*t, (x, None, t)) assert Integral(x*y, (x, y, None)).subs(y, t) == Integral(x*t, (x, t, None))
def test_doit(): e = Integral(Integral(2*x), (x, 0, 1)) assert e.doit() == Rational(1, 3) assert e.doit(deep=False) == Rational(1, 3) f = Function('f') # doesn't matter if the integral can't be performed assert Integral(f(x), (x, 1, 1)).doit() == 0 # doesn't matter if the limits can't be evaluated assert Integral(0, (x, 1, Integral(f(x), x))).doit() == 0
def test_doit(): a = Integral(x**2, x) assert isinstance(a.doit(), Integral) == False assert isinstance(a.doit(integrals=True), Integral) == False assert isinstance(a.doit(integrals=False), Integral) == True assert (2*Integral(x, x)).doit() == x**2
def test_issue1566(): # Allow only upper or lower limit evaluation e = Integral(x**2, (x, None, 1)) f = Integral(x**2, (x, 1, None)) assert e.doit() == Rational(1, 3) assert f.doit() == Rational(-1, 3) assert Integral(x*y, (x, None, y)).subs(y, t) == Integral(x*t, (x, None, t)) assert Integral(x*y, (x, y, None)).subs(y, t) == Integral(x*t, (x, t, None)) #FIXME-py3k: This fails somewhere down the line with: #FIXME-py3k: TypeError: type Float doesn't define __round__ method assert integrate(x**2, (x, None, 1)) == Rational(1, 3) assert integrate(x**2, (x, 1, None)) == Rational(-1, 3) assert integrate("x**2", ("x", "1", None)) == Rational(-1, 3)
def test_doit_integrals(): e = Integral(Integral(2*x), (x, 0, 1)) assert e.doit() == Rational(1, 3) assert e.doit(deep=False) == Rational(1, 3) f = Function('f') # doesn't matter if the integral can't be performed assert Integral(f(x), (x, 1, 1)).doit() == 0 # doesn't matter if the limits can't be evaluated assert Integral(0, (x, 1, Integral(f(x), x))).doit() == 0 assert Integral(x, (a, 0)).doit() == 0 limits = ((a, 1, exp(x)), (x, 0)) assert Integral(a, *limits).doit() == S(1)/4 assert Integral(a, *list(reversed(limits))).doit() == 0
def test_conjugate_transpose(): A, B = symbols("A B", commutative=False) x = Symbol("x", complex=True) p = Integral(A*B, (x,)) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose() x = Symbol("x", real=True) p = Integral(A*B, (x,)) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose()
def test_conjugate_transpose(): A, B = symbols("A B", commutative=False) x = Symbol("x", complex=True) p = Integral(A * B, (x, )) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose() x = Symbol("x", real=True) p = Integral(A * B, (x, )) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose()
def main(): print "Hydrogen radial wavefunctions:" var("r a") print "R_{21}:" pprint(R_nl(2, 1, a, r)) print "R_{60}:" pprint(R_nl(6, 0, a, r)) print "Normalization:" i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) print pretty(i), " = ", i.doit() i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) print pretty(i), " = ", i.doit() i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) print pretty(i), " = ", i.doit()
def main(): print("Hydrogen radial wavefunctions:") a, r = symbols("a r") print("R_{21}:") pprint(R_nl(2, 1, a, r)) print("R_{60}:") pprint(R_nl(6, 0, a, r)) print("Normalization:") i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit()))
def main(): print "Hydrogen radial wavefunctions:" a, r = symbols("a r") print "R_{21}:" pprint(R_nl(2, 1, a, r)) print "R_{60}:" pprint(R_nl(6, 0, a, r)) print "Normalization:" i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit()))
def test_transform(): a = Integral(x**2 + 1, (x, -1, 2)) fx = x fy = 3*y + 1 assert a.doit() == a.transform(fx, fy).doit() assert a.transform(fx, fy).transform(fy, fx) == a fx = 3*x + 1 fy = y assert a.transform(fx, fy).transform(fy, fx) == a a = Integral(sin(1/x), (x, 0, 1)) assert a.transform(x, 1/y) == Integral(sin(y)/y**2, (y, 1, oo)) assert a.transform(x, 1/y).transform(y, 1/x) == a a = Integral(exp(-x**2), (x, -oo, oo)) assert a.transform(x, 2*y) == Integral(2*exp(-4*y**2), (y, -oo, oo)) # < 3 arg limit handled properly assert Integral(x, x).transform(x, a*y).doit() == \ Integral(y*a**2, y).doit() _3 = S(3) assert Integral(x, (x, 0, -_3)).transform(x, 1/y).doit() == \ Integral(-1/x**3, (x, -oo, -1/_3)).doit() assert Integral(x, (x, 0, _3)).transform(x, 1/y) == \ Integral(y**(-3), (y, 1/_3, oo)) # issue 8400 i = Integral(x + y, (x, 1, 2), (y, 1, 2)) assert i.transform(x, (x + 2*y, x)).doit() == \ i.transform(x, (x + 2*z, x)).doit() == 3
def test_transform(): a = Integral(x**2 + 1, (x, -1, 2)) fx = x fy = 3 * y + 1 assert a.doit() == a.transform(fx, fy).doit() assert a.transform(fx, fy).transform(fy, fx) == a fx = 3 * x + 1 fy = y assert a.transform(fx, fy).transform(fy, fx) == a a = Integral(sin(1 / x), (x, 0, 1)) assert a.transform(x, 1 / y) == Integral(sin(y) / y**2, (y, 1, oo)) assert a.transform(x, 1 / y).transform(y, 1 / x) == a a = Integral(exp(-x**2), (x, -oo, oo)) assert a.transform(x, 2 * y) == Integral(2 * exp(-4 * y**2), (y, -oo, oo)) # < 3 arg limit handled properly assert Integral(x, x).transform(x, a*y).doit() == \ Integral(y*a**2, y).doit() _3 = S(3) assert Integral(x, (x, 0, -_3)).transform(x, 1/y).doit() == \ Integral(-1/x**3, (x, -oo, -1/_3)).doit() assert Integral(x, (x, 0, _3)).transform(x, 1/y) == \ Integral(y**(-3), (y, 1/_3, oo)) # issue 8400 i = Integral(x + y, (x, 1, 2), (y, 1, 2)) assert i.transform(x, (x + 2*y, x)).doit() == \ i.transform(x, (x + 2*z, x)).doit() == 3
def fr2fd(expression): """ Integruje \a expression vyjadřující četnost chyb λ(t). Z výsledku sestaví rovnici pro funkci spolehlivosti R(t), hustotu pravděpodobnosti poruchy f(t) a funkci poruchovosti F(t). """ from sympy import symbols, Add, Mul, Lambda, exp, Integral, sympify, lambdify, Pow, Integer a, b = symbols('a b') x = symbols('x', negative=False, real=True) t = symbols("t", negative=False, real=True) locals = { "add": Add, "mul": Mul, "sub": Lambda((a, b), a - b), "div": Lambda((a, b), a / b), "inv": Lambda((a), Pow(a, Integer(-1))), "X0": x } fr = sympify(expression, locals=locals, evaluate=False) # h(x) nebo-li λ(x) nebo-li "Failure Rate" fr = sympy.nsimplify(fr, rational_conversion='exact', rational=True, tolerance=1e-7) printDbg("h(x) =", fr) int_fr = Integral(fr, (x, 0, t)) expr_int_fr = int_fr.doit() fr = fr.subs(x, t) # h(t) nebo-li λ(t) nebo-li "Failure Rate" printDbg("h(t) =", fr) rf = exp( -expr_int_fr ) # R(t) = exp(-integrate(h(x),x,0,t)) nebo-li "Reliability Function" printDbg("R(t) =", rf) fd = fr * rf # f(t) = h(t)*R(t) = h(t)*exp(-integrate(h(x),x,0,t)) nebo-li "Failure Density" printDbg("f(t) =", fd) uf = 1 - rf # F(t) = 1-R(t) = 1-exp(-integrate(h(x),x,0,t)) nebo-li "Unreliability Function" printDbg("F(t) =", uf) #printDbg(fd == uf.diff(t)) #printDbg(fr == fd / rf) # Vytvoření rychle vyhodnotitelných funkcí modules = ["math"] fr_lambda = lambdify(t, fr, modules) # "Failure Rate" fd_lambda = lambdify(t, fd, modules) # "Failure Density" uf_lambda = lambdify(t, uf, modules) # "Unreliability Function" rf_lambda = lambdify(t, rf, modules) # "Reliability Function" return { "h": fr, "f": fd, "F": uf, "R": rf, "h(t)": fr_lambda, "f(t)": fd_lambda, "F(t)": uf_lambda, "R(t)": rf_lambda }
def compute_as_and_bs(prob_fun, n, alpha=0): '''Compute the a's and b's for the symmetric silent duel.''' P = prob_fun t = Symbol('t0', positive=True) a_n, h_n = compute_a_n(prob_fun, alpha=alpha) normalizing_constants = deque([h_n]) transitions = deque([a_n]) f_star_products = deque([1, 1 - P(a_n)]) for step in range(n): # prepending new a's and h's to the front of the list last_a = transitions[0] last_h = normalizing_constants[0] next_a = Symbol('a', positive=True) next_a_integral = Integral((1 - P(t)) * f_star(P, t, transitions), (t, next_a, last_a)) next_a_integrated = next_a_integral.doit() # print("%s" % next_a_integrated) P_next_a_solutions = solve(next_a_integrated - 1 / last_h, P(next_a)) print("P(a_{n-%d}) is one of %s" % (step + 1, P_next_a_solutions)) P_next_a = Max(*P_next_a_solutions) next_a_solutions = solve(P(next_a) - P_next_a, next_a) next_a_solutions_in_range = [ soln for soln in next_a_solutions if 0 < soln <= 1 ] assert len(next_a_solutions_in_range) == 1 next_a_soln = next_a_solutions_in_range[0] print("a_{n-%d} = %s" % (step + 1, next_a_soln)) next_h_integral = Integral(f_star(P, t, transitions), (t, next_a_soln, last_a)) next_h = 1 / next_h_integral.doit() print("h_{n-%d} = %s" % (step + 1, next_h)) print("dF_{n-%d} coeff = %s" % (step + 1, next_h * f_star_products[-1])) f_star_products.append(f_star_products[-1] * (1 - P_next_a)) transitions.appendleft(next_a_soln) normalizing_constants.appendleft(next_h) return transitions
def test_doit(): e = Integral(Integral(2*x), (x, 0, 1)) assert e.doit() == Rational(1, 3) f = Function('f') # doesn't matter if the integral can't be performed assert Integral(f(x), (x, 1, 1)).doit() == 0 # doesn't matter if the limits can't be evaluated assert Integral(0, (x, 1, Integral(f(x), x))).doit() == 0
def main(): print "Hydrogen radial wavefunctions:" var("r a") print "R_{21}:" pprint(R_nl(2, 1, a, r)) print "R_{60}:" pprint(R_nl(6, 0, a, r)) print "Normalization:" i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit()))
def _variable_force_(fx, lower_bound, upper_bound, variable_of_integration) -> object: """Work Done by Variable Force: we need to recall the mass-density formula of a one-dimensional object, as well as how to calculate the work done on an object by a variable force. Linear density of the string is equal to the mass divided by the length of the string: - p = m/L, where m is mass and L is length of the object. As the string is wound up, the portion of the cable that is hanging down decreases. The mass of the cable alone can therefore be expressed as the linear density multiplied by x, the length of the hanging portion of the cable. Since we also know that F=ma and the acceleration is equal to g, the force from the cable alone is equal to: - F(x) = ρxg The force from the weight of the crate is equal to its mass multiplied by g. The total force is therefore: - F(x) = pxg + pL The mass m of a one-dimensional object oriented along the x-axis over the interval [a,b] is given by: - m = ∫ [a, b] ρ(x) dx, where ρ(x) is the linear density of the object at a point x in the interval. When linear density is constant, this simplifies to: - m = ∫ [a, b] ρ dx. If a variable force F(x) moves an object in a positive direction along the x-axis from point a to point b, then the work done on the object is: - W = ∫ [a, b] F(x) dx. :param fx: :param lower_bound: :param upper_bound: :param variable_of_integration: :return: """ _l_ = lower_bound _u_ = upper_bound _var_ = variable_of_integration _work_ = Integral(fx, (_var_, _l_, _u_)) _work_sol_ = _work_.doit() print("\nWork Integral: \n") pretty_print(_work_) print("\nWork = \n") pretty_print(_work_sol_) return _work_sol_
def test_is_zero(): from sympy.abc import x, m, n assert Integral(0, (x, 1, x)).is_zero assert Integral(1, (x, 1, 1)).is_zero assert Integral(1, (x, 1, 2)).is_zero is False assert Integral(sin(m*x)*cos(n*x), (x, 0, 2*pi)).is_zero is None assert Integral(x, (m, 0)).is_zero assert Integral(x + 1/m, (m, 0)).is_zero is None i = Integral(m, (m, 1, exp(x)), (x, 0)) assert i.is_zero is None and i.doit() == S(1)/4 assert Integral(m, (x, 0), (m, 1, exp(x))).is_zero is True
def test_transform(): a = Integral(x**2+1, (x, -1, 2)) assert a.doit() == a.transform(x, 3*x+1).doit() assert a.transform(x, 3*x+1).transform(x, 3*x+1, inverse=True) == a assert a.transform(x, 3*x+1, inverse=True).transform(x, 3*x+1) == a a = Integral(sin(1/x), (x, 0, 1)) assert a.transform(x, 1/x) == Integral(sin(x)/x**2, (x, 1, oo)) assert a.transform(x, 1/x).transform(x, 1/x) == a a = Integral(exp(-x**2), (x, -oo, oo)) assert a.transform(x, 2*x) == Integral(2*exp(-4*x**2), (x, -oo, oo)) raises(ValueError, "a.transform(x, 1/x)") raises(ValueError, "a.transform(x, 1/x)")
class _TimeIntegrationRisch(object): params = [1, 10, 100] def setup(self, n): x = symbols('x') self.integral = Integral(self.make_expr(n), x) self.values = {} def teardown(self, n): x = symbols('x') for key, val in self.values.items(): ref = self.make_expr(n) if (ref - val.diff(x)).simplify() != 0: raise ValueError("Incorrect result, invalid timing:" " %s != %s" % (ref, val)) def time_doit(self, n): self.values['time_doit'] = self.integral.doit() def time_doit_risch(self, n): self.values['time_doit_risch'] = self.integral.doit(risch=True)
def _mean_value_(fx, lower_bound, upper_bound, variable_of_integration, average_rate_change=None) -> object: """The Mean Value Theorem: Let f be a function such that: 1. It is continuous on the closed interval [a, b]. 2. It is differentiable on the open interval (a, b). Then there is (at least) a number c in (a, b) such that - f'(c) = [ f(b) - f(a) ] / [ b - a ] Comment: Notice that the left side is the instantaneous rate of change / slope of the tangent line at c, while the right side is the average rate of change / slope of the secant line from a to b. Thus the theorem guarantees that there is at least one place in (a, b) where the tangent line there is parallel to the secant line connecting the points (a, f (a)) and (b, f (b)) on the curve y = f (x). :param fx: :param lower_bound: :param upper_bound: :param variable_of_integration: :param average_rate_change: :return: """ a = lower_bound b = upper_bound _var_ = variable_of_integration _area_ = Integral(fx, (_var_, a, b)) avg_roc = average_rate_change if avg_roc is not None: _mean_avg_roc_ = Fraction(1 / (b - a)).limit_denominator() * avg_roc elif avg_roc is None: _mean_avg_roc_ = "None" _given_c = "None" _mean_value_theorem_of_integral_ = Fraction(1 / (b - a)).limit_denominator() * _area_.doit() if _mean_value_theorem_of_integral_ > 0: c = solve(fx - _mean_value_theorem_of_integral_) elif _mean_value_theorem_of_integral_ < 0: c = solve(fx + _mean_value_theorem_of_integral_) print("\nf({}) = \n".format(_var_)) pretty_print(fx) print("\nIntegral: \n") pretty_print(_area_) print("\nMean value theorem for integral: \n") pretty_print(_mean_value_theorem_of_integral_) print("\nMean value given a rate of change: \n") pretty_print(_mean_avg_roc_) print("\nc from Mean value theorem for integral: \n") pretty_print(c)
def compute_a_n(prob_fun, alpha=0): P = prob_fun t = Symbol('t0', positive=True) a_n = Symbol('a_n', positive=True) a_n_integral = Integral( ((1 + alpha) - (1 - alpha) * P(t)) * f_star(P, t, []), (t, a_n, 1)) a_n_integrated = a_n_integral.doit() P_a_n_solutions = solve(a_n_integrated - 2 * (1 - alpha), P(a_n)) P_a_n = Max(*P_a_n_solutions) print("P(a_n) = %s" % P_a_n) a_n_solutions = solve(P(a_n) - P_a_n, a_n) a_n_solutions_in_range = [soln for soln in a_n_solutions if 0 < soln <= 1] assert len(a_n_solutions_in_range) == 1 a_n = a_n_solutions_in_range[0] print("a_n = %s" % a_n) h_n_integral = Integral(f_star(P, t, []), (t, a_n, 1)) h_n_integrated = h_n_integral.doit() h_n = (1 - alpha) / h_n_integrated print("h_n = %s" % h_n) return (a_n, h_n)
def ritz(a,b,n,f,fi,fi0): u = Symbol("u") const = [Symbol("C"+str(i)) for i in range(1,n+1)] u_ = get_u(fi,n,const) u_+=fi0 f = f.subs({u:u_}) J = Integral(f,(x,a,b)) F = J.doit() #Partial derrivatives derr = [diff(F,c) for c in const] #Get С sol = solve(derr,const) #Put С into u u = u_.subs(sol) return u
def test_transform(): a = Integral(x ** 2 + 1, (x, -1, 2)) assert a.doit() == a.transform(x, 3 * x + 1).doit() assert a.transform(x, 3 * x + 1).transform(x, 3 * x + 1, inverse=True) == a assert a.transform(x, 3 * x + 1, inverse=True).transform(x, 3 * x + 1) == a a = Integral(sin(1 / x), (x, 0, 1)) assert a.transform(x, 1 / x) == Integral(sin(x) / x ** 2, (x, 1, oo)) assert a.transform(x, 1 / x).transform(x, 1 / x) == a a = Integral(exp(-x ** 2), (x, -oo, oo)) assert a.transform(x, 2 * x) == Integral(2 * exp(-4 * x ** 2), (x, -oo, oo)) # < 3 arg limit handled properly assert Integral(x, x).transform(x, a * x) == Integral(x * a ** 2, x) raises(ValueError, "a.transform(x, 1/x)") raises(ValueError, "a.transform(x, 1/x)") _3 = S(3) assert Integral(x, (x, 0, -_3)).transform(x, 1 / x) == Integral(-1 / x ** 3, (x, -oo, -1 / _3)) assert Integral(x, (x, 0, _3)).transform(x, 1 / x) == Integral(x ** (-3), (x, 1 / _3, oo))
def evaluate_problem_input(self, expression: Expression, problem_type): logger.info("Starting problem input validation") if problem_type != 'derivative' and problem_type != 'integral': raise SuspiciousOperation('Invalid input type') try: if problem_type == 'derivative': derivative = Derivative(expression.sympy_expr, 'x') return Expression(derivative.doit()).solve_derivatives( ).to_latex_with_derivatives() integral = Integral(expression.sympy_expr, x) return latex(integral.doit()) except: logger.info("Invalid expression") raise SuspiciousOperation('Invalid expression')
def test_transform(): a = Integral(x**2+1, (x, -1, 2)) assert a.doit() == a.transform(x, 3*x+1).doit() assert a.transform(x, 3*x+1).transform(x, 3*x+1, inverse=True) == a assert a.transform(x, 3*x+1, inverse=True).transform(x, 3*x+1) == a a = Integral(sin(1/x), (x, 0, 1)) assert a.transform(x, 1/x) == Integral(sin(x)/x**2, (x, 1, oo)) assert a.transform(x, 1/x).transform(x, 1/x) == a a = Integral(exp(-x**2), (x, -oo, oo)) assert a.transform(x, 2*x) == Integral(2*exp(-4*x**2), (x, -oo, oo)) # < 3 arg limit handled properly assert Integral(x, x).transform(x, a*x) == Integral(x*a**2, x) raises(ValueError, "a.transform(x, 1/x)") raises(ValueError, "a.transform(x, 1/x)") _3 = S(3) assert Integral(x, (x, 0, -_3)).transform(x, 1/x) == \ Integral(-1/x**3, (x, -oo, -1/_3)) assert Integral(x, (x, 0, _3)).transform(x, 1/x) == \ Integral(x**(-3), (x, 1/_3, oo))
def _linear_density_(px, lower_bound, upper_bound, variable_of_integration) -> object: """ Let R denote a region bounded above by the graph of a continuous function f(x), below by the x-axis, and on the left and right by the lines x = a and x = b, respectively. Let ρ denote the density of the associated lamina. Then we can make the following statements: - i. The mass of the lamina is: - m = ρ ∫ [a, b] f(x)dx - ii. The moments M_x and M_y of the lamina with respect to the x-axis and y-axes, respectively, are - M_x = ρ ∫ [a, b] [f(x)]^2/2 dx and - M_y = ρ ∫ [a, b] x f(x) dx - iii. The coordinates of the center of mass ( X̅, y̅ ) are: - X̅ = M_y/m and y̅ = M_x/m :param px: :param lower_bound: :param upper_bound: :param variable_of_integration: :return: """ _l_ = lower_bound _u_ = upper_bound _var_ = variable_of_integration _mass_ = Integral(px, (_var_, _l_, _u_)) _mass_sol_ = _mass_.doit() print("\nIntegral mass: \n") pretty_print(_mass_) print("\nMass of the object: \n") pretty_print(_mass_sol_) return [_mass_, _mass_sol_]
from sympy import init_printing, symbols, Integral, oo, exp, Eq, solve, Rational, latex from IPython.display import display init_printing(use_latex=True, latex_mode='equation*', forecolor='White') #remove "White" if your background is white x = symbols('x') gamma, sigma = symbols ('gamma sigma', positive=True) def lorentz(x, gamma): return 1/(gamma**2 + x**2) # normnormalizing Lorentzian L_int = Integral(lorentz(x,gamma), (x, -oo, oo)) L_norm = L_int.doit() display(Eq(L_int, L_norm )) # calculating the half width at half maximum (HWHM) of a Lorenzian L_max = lorentz(0,gamma) L_HWHM = Eq(lorentz(x,gamma),(Rational(1,2)*L_max)) display(L_HWHM) display(solve(L_HWHM, x)) def gauss(x,sigma): return exp(-x**2/2/sigma**2) # normnormalizing Gaussian G_int = Integral(gauss(x,sigma), (x, -oo, oo)) G_norm = G_int.doit()
#!/usr/bin/env python """ This example shows how to work with the Hydrogen radial wavefunctions. """ from sympy import var, pprint, Integral, oo, Eq from sympy.physics.hydrogen import R_nl print "Hydrogen radial wavefunctions:" var("r a") print "R_{21}:" pprint(R_nl(2, 1, a, r)) print "R_{60}:" pprint(R_nl(6, 0, a, r)) print "Normalization:" i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit()))
def expectation(self, expr, var, evaluate=True, **kwargs): """ Expectation of expression over distribution """ integral = Integral(expr * self.pdf(var), (var, self.set), **kwargs) return integral.doit() if evaluate else integral
def _cylindrical_shell_(fx, gx, lower_bound, upper_bound, line_of_rotation, variable_of_integration) -> object: """Volumes by Cylindrical Shells: the Shell Method. V = 2πrh Δr Another method of find the volumes of solids of revolution is the shell method. It can usually find volumes that are otherwise difficult to evaluate using the Disc / Washer method. - General formula: V = ∫ 2π (shell radius)(shell height) dx The Shell Method (about the y-axis)The volume of the solid generated by revolving about the y-axis the region between the x-axis and the graph of a continuous function y = f (x), a ≤ x ≤ b is: - V = ∫ [a,b] 2π [radius] * [shell height] dx = ∫ [a,b] 2π * x * f(x) dx Similarly, The Shell Method (about the x-axis) The volume of the solid generated by revolving about the x-axis the region between the y-axis and the graph of a continuous function x = f (y), c ≤ y ≤ d is: - V = ∫ [c,d] 2π [radius] * [shell height] dy = ∫ [c,d] 2π * y * f(y) dy ***Note: An easy way to remember which method to use to find the volume of a solid of revolution is to note that the Disc / Washer method is used if the independent variable of the function(s) and the axis of rotation is the same (e.g., the area under y = f (x), revolved about the x-axis); while the Shell method should be used if the independent variable is different from the axis of rotation (e.g., the area under x = f (y), revolved about the x-axis). :param fx: :param gx: :param lower_bound: :param upper_bound: :param line_of_rotation: :param variable_of_integration: :return: """ # noinspection DuplicatedCode _l_ = lower_bound _u_ = upper_bound _var_ = variable_of_integration _f_ = fx if fx is not None else gx _g_ = gx k = line_of_rotation if line_of_rotation is not None else None _radius_ = _var_ if k is None else (_var_ - k) _k_ = _radius_ if _radius_ is not None else _var_ if _f_ is not None and _g_ is None: if _u_ is None: sol = solve(_f_) for aa in sol: if aa > 0: _u_ = aa pretty_print(_u_) _v_ = Integral((2 * pi * _k_ * _f_), (_var_, _l_, _u_)) _demo_ = Integral((2 * pi * _k_ * _f_), _var_) _demo_sol = _demo_.doit() print("\nIntegral: \n") pretty_print(_v_) print("\nSolution: \n") sol_v = _v_.doit() pretty_print(sol_v) return [_demo_, _demo_sol, _v_, sol_v] elif _f_ is not None and _g_ is not None: if _u_ is None: sol = solve(_g_ - _f_) for aa in sol: if aa > 0: _u_ = aa pretty_print(_u_) _v_ = Integral((2 * pi * _radius_ * (_f_ - _g_)), (_var_, _l_, _u_)) _demo_ = Integral((2 * pi * _radius_ * (_f_ - _g_)), _var_) _demo_sol = _demo_.doit() print("\nIntegral: \n") pretty_print(_v_) print("\nSolution: \n") sol_v = _v_.doit() pretty_print(sol_v) pretty_print(simplify(sol_v)) return [_demo_, _demo_sol, _v_, sol_v]
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() Product.is_convergent() """ from sympy import Interval, Integral, Limit, log, symbols, Ge, Gt, simplify p, q = symbols('p q', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError( "convergence checking for more than one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func_cond in sequence_term.args: if func_cond[1].func is Ge or func_cond[ 1].func is Gt or func_cond[1] == True: return Sum( func_cond[0], (sym, lower_limit, upper_limit)).is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit(sequence_term, sym, upper_limit) if lim_val.is_number and lim_val is not S.Zero: return S.false except NotImplementedError: pass try: lim_val_abs = limit(abs(sequence_term), sym, upper_limit) if lim_val_abs.is_number and lim_val_abs is not S.Zero: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] > -1: return S.false p2_series_test = order.expr.match((1 / sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] < 1: return S.false ### ----------- root test ---------------- ### lim = Limit(abs(sequence_term)**(1 / sym), sym, S.Infinity) lim_evaluated = lim.doit() if lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p) * q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- comparison test ------------- ### # (1/log(n)**p) comparison log_test = order.expr.match(1 / (log(sym)**p)) if log_test is not None: return S.false # (1/(n*log(n)**p)) comparison log_n_test = order.expr.match(1 / (sym * (log(sym))**p)) if log_n_test is not None: if log_n_test[p] > 1: return S.true return S.false # (1/(n*log(n)*log(log(n))*p)) comparison log_log_n_test = order.expr.match(1 / (sym * (log(sym) * log(log(sym))**p))) if log_log_n_test is not None: if log_log_n_test[p] > 1: return S.true return S.false # (1/(n**p*log(n))) comparison n_log_test = order.expr.match(1 / (sym**p * log(sym))) if n_log_test is not None: if n_log_test[p] > 1: return S.true return S.false ### ------------- integral test -------------- ### if is_decreasing(sequence_term, interval): integral_val = Integral(sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### -------------- Dirichlet tests -------------- ### if order.expr.is_Mul: a_n, b_n = order.expr.args[0], order.expr.args[1] m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit( Sum(g_n, (sym, interval.inf, m)).doit(), m, S.Infinity) if ing_val.is_finite: return S.true except NotImplementedError: pass if is_decreasing(a_n, interval): dirich1 = _dirichlet_test(b_n) if dirich1 is not None: return dirich1 if is_decreasing(b_n, interval): dirich2 = _dirichlet_test(a_n) if dirich2 is not None: return dirich2 raise NotImplementedError( "The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def test_doit2(): e = Integral(Integral(2*x), (x, 0, 1)) # risch currently chokes on the contained integral. assert e.doit(deep = False) == e
cos, sin, diff, integrate, Derivative, Integral, ) init_printing(use_unicode=True) assert 10**10 < oo x, y = symbols('x, y') f = Integral(x**2, x) print(f) assert f.doit() == x**3 / 3 assert limit(x**2, x, 2) == 4 print(sin(1) / cos(1)) print(exp(x)) assert integrate(x, (x, 0, 2)) == 2 z = Integral(x**2, (x, 0, 2)) print(z) assert z.doit() == 8 / 3 assert diff(x**2, x) == 2 * x assert diff(x**3, x, 2) == 6 * x assert diff(x * y, x) == y
def test_nested_doit(): e = Integral(Integral(x, x), x) f = Integral(x, x, x) assert e.doit() == f.doit()
#!/usr/bin/env python # coding: utf-8 # In[1]: from sympy import init_printing, symbols, Integral, Derivative, sin, exp, Eq from IPython.display import display init_printing(use_latex=True, latex_mode='equation*') x = symbols('x') # In[2]: int_x = Integral(sin(x)*exp(x), x) display(Eq(int_x, int_x.doit())) derv_x = Derivative(sin(x)*exp(x), x) display(Eq(derv_x, derv_x.doit()))
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() Product.is_convergent() """ from sympy import Interval, Integral, Limit, log, symbols, Ge, Gt, simplify p, q = symbols('p q', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError("convergence checking for more than one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity sym_ = Dummy(sym.name, integer=True, positive=True) sequence_term = sequence_term.xreplace({sym: sym_}) sym = sym_ interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func, cond in sequence_term.args: # see if it represents something going to oo if cond == True or cond.as_set().sup is S.Infinity: s = Sum(func, (sym, lower_limit, upper_limit)) return s.is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit(sequence_term, sym, upper_limit) if lim_val.is_number and lim_val is not S.Zero: return S.false except NotImplementedError: pass try: lim_val_abs = limit(abs(sequence_term), sym, upper_limit) if lim_val_abs.is_number and lim_val_abs is not S.Zero: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### ----------- ratio test ---------------- ### next_sequence_term = sequence_term.xreplace({sym: sym + 1}) ratio = combsimp(powsimp(next_sequence_term/sequence_term)) lim_ratio = limit(ratio, sym, upper_limit) if lim_ratio.is_number: if abs(lim_ratio) > 1: return S.false if abs(lim_ratio) < 1: return S.true ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] >= -1: return S.false p2_series_test = order.expr.match((1/sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] <= 1: return S.false ### ------------- Limit comparison test -----------### # (1/n) comparison try: lim_comp = limit(sym*sequence_term, sym, S.Infinity) if lim_comp.is_number and lim_comp > 0: return S.false except NotImplementedError: pass ### ----------- root test ---------------- ### lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity) lim_evaluated = lim.doit() if lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p)*q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- comparison test ------------- ### # (1/log(n)**p) comparison log_test = order.expr.match(1/(log(sym)**p)) if log_test is not None: return S.false # (1/(n*log(n)**p)) comparison log_n_test = order.expr.match(1/(sym*(log(sym))**p)) if log_n_test is not None: if log_n_test[p] > 1: return S.true return S.false # (1/(n*log(n)*log(log(n))*p)) comparison log_log_n_test = order.expr.match(1/(sym*(log(sym)*log(log(sym))**p))) if log_log_n_test is not None: if log_log_n_test[p] > 1: return S.true return S.false # (1/(n**p*log(n))) comparison n_log_test = order.expr.match(1/(sym**p*log(sym))) if n_log_test is not None: if n_log_test[p] > 1: return S.true return S.false ### ------------- integral test -------------- ### maxima = solveset(sequence_term.diff(sym), sym, interval) if not maxima: check_interval = interval elif isinstance(maxima, FiniteSet) and maxima.sup.is_number: check_interval = Interval(maxima.sup, interval.sup) if ( is_decreasing(sequence_term, check_interval) or is_decreasing(-sequence_term, check_interval)): integral_val = Integral( sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### -------------- Dirichlet tests -------------- ### if order.expr.is_Mul: a_n, b_n = order.expr.args[0], order.expr.args[1] m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit(Sum(g_n, (sym, interval.inf, m)).doit(), m, S.Infinity) if ing_val.is_finite: return S.true except NotImplementedError: pass if is_decreasing(a_n, interval): dirich1 = _dirichlet_test(b_n) if dirich1 is not None: return dirich1 if is_decreasing(b_n, interval): dirich2 = _dirichlet_test(a_n) if dirich2 is not None: return dirich2 _sym = self.limits[0][0] sequence_term = sequence_term.xreplace({sym: _sym}) raise NotImplementedError("The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def is_convergent(self): """ Convergence tests are used for checking the convergence of a series. There are various tests employed to check the convergence, returns true if convergent and false if divergent and NotImplementedError if can not be checked. Like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import Interval, factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolute_convergent() """ from sympy import Interval, Integral, Limit, log, symbols, Ge, Gt, simplify p, q = symbols('p q', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError("convergence checking for more that one symbol \ containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func_cond in sequence_term.args: if func_cond[1].func is Ge or func_cond[1].func is Gt or func_cond[1] == True: return Sum(func_cond[0], (sym, lower_limit, upper_limit)).is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit(abs(sequence_term), sym, upper_limit) if lim_val.is_number and lim_val != S.Zero: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] > -1: return S.false p2_series_test = order.expr.match((1/sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] < 1: return S.false ### ----------- root test ---------------- ### lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity) lim_evaluated = lim.doit() if lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false ### ------------- alternating series test ----------- ### d = symbols('d', cls=Dummy) dict_val = sequence_term.match((-1)**(sym + p)*q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- comparison test ------------- ### # (1/log(n)**p) comparison log_test = order.expr.match(1/(log(sym)**p)) if log_test is not None: return S.false # (1/(n*log(n)**p)) comparison log_n_test = order.expr.match(1/(sym*(log(sym))**p)) if log_n_test is not None: if log_n_test[p] > 1: return S.true return S.false # (1/(n*log(n)*log(log(n))*p)) comparison log_log_n_test = order.expr.match(1/(sym*(log(sym)*log(log(sym))**p))) if log_log_n_test is not None: if log_log_n_test[p] > 1: return S.true return S.false # (1/(n**p*log(n))) comparison n_log_test = order.expr.match(1/(sym**p*log(sym))) if n_log_test is not None: if n_log_test[p] > 1: return S.true return S.false ### ------------- integral test -------------- ### if is_decreasing(sequence_term, interval): integral_val = Integral(sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### -------------- Dirichlet tests -------------- ### if order.expr.is_Mul: a_n, b_n = order.expr.args[0], order.expr.args[1] m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit(Sum(g_n, (sym, interval.inf, m)).doit(), m, S.Infinity) if ing_val.is_finite: return S.true except NotImplementedError: pass if is_decreasing(a_n, interval): dirich1 = _dirichlet_test(b_n) if dirich1 is not None: return dirich1 if is_decreasing(b_n, interval): dirich2 = _dirichlet_test(a_n) if dirich2 is not None: return dirich2 raise NotImplementedError("The algorithm to find the convergence of %s " "is not yet implemented" % (sequence_term))
""" This example shows how to work with the Hydrogen radial wavefunctions. """ from sympy import var, pprint, Integral, oo, Eq from sympy.physics.hydrogen import R_nl print "Hydrogen radial wavefunctions:" var("r a") print "R_{21}:" pprint(R_nl(2, 1, a, r)) print "R_{60}:" pprint(R_nl(6, 0, a, r)) print "Normalization:" i = Integral(R_nl(1, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 0, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit())) i = Integral(R_nl(2, 1, 1, r)**2 * r**2, (r, 0, oo)) pprint(Eq(i, i.doit()))
def _volume_washer_(fx, gx, lower_bound, upper_bound, variable_of_integration) -> object: """ The washer method: If a region in the plane is revolved about a line in the same plane, the resulting object is known as a solid of revolution. For example, a solid right circular cylinder can be generated by revolving a rectangle. Similarly, a solid spherical ball can be generated by revolving a semi-disk. The line about which we rotate the shape is called the axis of revolution. We can extend the disk method to find the volume of a hollow solid of revolution. Assuming that the functions f(x) and g(x) are continuous and non-negative on the interval [a,b] and g(x) ≤ f(x), consider a region that is bounded by two curves y = f(x) and y = g(x), between x = a and x = b. The volume of the solid formed by revolving the region about the x−axis is: - V = π ∫ [a,b] ( [f(x)]^2 − [g(x)]^2 ) dx At a point x on the x−axis, a perpendicular cross section of the solid is washer-shape with the inner radius r = g(x) and the outer radius R = f(x). The volume of the solid generated by revolving about the y−axis a region between the curves x = f(y) and x = g(y), where g(y) ≤ f(y) and c ≤ y ≤ d is given by the formula: - V = π ∫ [c,d] ( [f(y)]^2 − [g(y)]^2 ) dy :param fx: f(x) is the top curve :param gx: g(x) is the bottom curve :param lower_bound: :param upper_bound: :param variable_of_integration: :return: """ a, b = symbols('a, b') _a_ = lower_bound _b_ = upper_bound _v_ = variable_of_integration if str(_v_) == "x": _l_ = "a" _u_ = "b" elif str(_v_) == "y": _l_ = "c" _u_ = "d" fx_area = ar.circle_(fx) gx_area = ar.circle_(gx) demo = Integral((fx_area - gx_area), (_v_, _l_, _u_)) vol = Integral((fx_area - gx_area), (_v_, _a_, _b_)) int_vol = vol.doit() print('\nf(x) = \n{0}'.format(pretty(fx))) print('\ng(x) = \n{0}'.format(pretty(gx))) print('\nArea of f(x) = \n') pretty_print(fx_area) print('\nArea of g(x) = \n') pretty_print(gx_area) print( '\nIntegrate the Area of [ A(f({0})) - A(g({0})) ], over the bounds of ' '{1} = {2} & {3} = {4}: \n'.format(_v_, _l_, _a_, _u_, _b_)) pretty_print(demo) print( '\nIntegrate the Area of [ A(f({0})) - A(g({0})) ], over the bounds of ' '{1} = {2} & {3} = {4}: \n'.format(_v_, _l_, _a_, _u_, _b_)) pretty_print(vol) print('\nFind the antiderivative of integration: \n') pretty_print(demo.doit()) print('\nSolve for the volume over the bounded region R: \n') pretty_print(int_vol)
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() Product.is_convergent() """ from sympy import Interval, Integral, log, symbols, simplify p, q, r = symbols('p q r', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError("convergence checking for more than one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity sym_ = Dummy(sym.name, integer=True, positive=True) sequence_term = sequence_term.xreplace({sym: sym_}) sym = sym_ interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func, cond in sequence_term.args: # see if it represents something going to oo if cond == True or cond.as_set().sup is S.Infinity: s = Sum(func, (sym, lower_limit, upper_limit)) return s.is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit_seq(sequence_term, sym) if lim_val is not None and lim_val.is_zero is False: return S.false except NotImplementedError: pass try: lim_val_abs = limit_seq(abs(sequence_term), sym) if lim_val_abs is not None and lim_val_abs.is_zero is False: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] >= -1: return S.false p2_series_test = order.expr.match((1/sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] <= 1: return S.false ### ------------- comparison test ------------- ### # 1/(n**p*log(n)**q*log(log(n))**r) comparison n_log_test = order.expr.match(1/(sym**p*log(sym)**q*log(log(sym))**r)) if n_log_test is not None: if (n_log_test[p] > 1 or (n_log_test[p] == 1 and n_log_test[q] > 1) or (n_log_test[p] == n_log_test[q] == 1 and n_log_test[r] > 1)): return S.true return S.false ### ------------- Limit comparison test -----------### # (1/n) comparison try: lim_comp = limit_seq(sym*sequence_term, sym) if lim_comp is not None and lim_comp.is_number and lim_comp > 0: return S.false except NotImplementedError: pass ### ----------- ratio test ---------------- ### next_sequence_term = sequence_term.xreplace({sym: sym + 1}) ratio = combsimp(powsimp(next_sequence_term/sequence_term)) try: lim_ratio = limit_seq(ratio, sym) if lim_ratio is not None and lim_ratio.is_number: if abs(lim_ratio) > 1: return S.false if abs(lim_ratio) < 1: return S.true except NotImplementedError: pass ### ----------- root test ---------------- ### # lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity) try: lim_evaluated = limit_seq(abs(sequence_term)**(1/sym), sym) if lim_evaluated is not None and lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false except NotImplementedError: pass ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p)*q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- integral test -------------- ### check_interval = None maxima = solveset(sequence_term.diff(sym), sym, interval) if not maxima: check_interval = interval elif isinstance(maxima, FiniteSet) and maxima.sup.is_number: check_interval = Interval(maxima.sup, interval.sup) if (check_interval is not None and (is_decreasing(sequence_term, check_interval) or is_decreasing(-sequence_term, check_interval))): integral_val = Integral( sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### ----- Dirichlet and bounded times convergent tests ----- ### # TODO # # Dirichlet_test # https://en.wikipedia.org/wiki/Dirichlet%27s_test # # Bounded times convergent test # It is based on comparison theorems for series. # In particular, if the general term of a series can # be written as a product of two terms a_n and b_n # and if a_n is bounded and if Sum(b_n) is absolutely # convergent, then the original series Sum(a_n * b_n) # is absolutely convergent and so convergent. # # The following code can grows like 2**n where n is the # number of args in order.expr # Possibly combined with the potentially slow checks # inside the loop, could make this test extremely slow # for larger summation expressions. if order.expr.is_Mul: args = order.expr.args argset = set(args) ### -------------- Dirichlet tests -------------- ### m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit_seq(Sum(g_n, (sym, interval.inf, m)).doit(), m) if ing_val is not None and ing_val.is_finite: return S.true except NotImplementedError: pass ### -------- bounded times convergent test ---------### def _bounded_convergent_test(g1_n, g2_n): try: lim_val = limit_seq(g1_n, sym) if lim_val is not None and (lim_val.is_finite or ( isinstance(lim_val, AccumulationBounds) and (lim_val.max - lim_val.min).is_finite)): if Sum(g2_n, (sym, lower_limit, upper_limit)).is_absolutely_convergent(): return S.true except NotImplementedError: pass for n in range(1, len(argset)): for a_tuple in itertools.combinations(args, n): b_set = argset - set(a_tuple) a_n = Mul(*a_tuple) b_n = Mul(*b_set) if is_decreasing(a_n, interval): dirich = _dirichlet_test(b_n) if dirich is not None: return dirich bc_test = _bounded_convergent_test(a_n, b_n) if bc_test is not None: return bc_test _sym = self.limits[0][0] sequence_term = sequence_term.xreplace({sym: _sym}) raise NotImplementedError("The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def euler_maclaurin(self, m=0, n=0, eps=0, eval_integral=True): """ Return an Euler-Maclaurin approximation of self, where m is the number of leading terms to sum directly and n is the number of terms in the tail. With m = n = 0, this is simply the corresponding integral plus a first-order endpoint correction. Returns (s, e) where s is the Euler-Maclaurin approximation and e is the estimated error (taken to be the magnitude of the first omitted term in the tail): >>> from sympy.abc import k, a, b >>> from sympy import Sum >>> Sum(1/k, (k, 2, 5)).doit().evalf() 1.28333333333333 >>> s, e = Sum(1/k, (k, 2, 5)).euler_maclaurin() >>> s -log(2) + 7/20 + log(5) >>> from sympy import sstr >>> print(sstr((s.evalf(), e.evalf()), full_prec=True)) (1.26629073187415, 0.0175000000000000) The endpoints may be symbolic: >>> s, e = Sum(1/k, (k, a, b)).euler_maclaurin() >>> s -log(a) + log(b) + 1/(2*b) + 1/(2*a) >>> e Abs(1/(12*b**2) - 1/(12*a**2)) If the function is a polynomial of degree at most 2n+1, the Euler-Maclaurin formula becomes exact (and e = 0 is returned): >>> Sum(k, (k, 2, b)).euler_maclaurin() (b**2/2 + b/2 - 1, 0) >>> Sum(k, (k, 2, b)).doit() b**2/2 + b/2 - 1 With a nonzero eps specified, the summation is ended as soon as the remainder term is less than the epsilon. """ from sympy.functions import bernoulli, factorial from sympy.integrals import Integral m = int(m) n = int(n) f = self.function if len(self.limits) != 1: raise ValueError("More than 1 limit") i, a, b = self.limits[0] if (a > b) == True: if a - b == 1: return S.Zero, S.Zero a, b = b + 1, a - 1 f = -f s = S.Zero if m: if b.is_Integer and a.is_Integer: m = min(m, b - a + 1) if not eps or f.is_polynomial(i): for k in range(m): s += f.subs(i, a + k) else: term = f.subs(i, a) if term: test = abs(term.evalf(3)) < eps if test == True: return s, abs(term) elif not (test == False): # a symbolic Relational class, can't go further return term, S.Zero s += term for k in range(1, m): term = f.subs(i, a + k) if abs(term.evalf(3)) < eps and term != 0: return s, abs(term) s += term if b - a + 1 == m: return s, S.Zero a += m x = Dummy('x') I = Integral(f.subs(i, x), (x, a, b)) if eval_integral: I = I.doit() s += I def fpoint(expr): if b is S.Infinity: return expr.subs(i, a), 0 return expr.subs(i, a), expr.subs(i, b) fa, fb = fpoint(f) iterm = (fa + fb)/2 g = f.diff(i) for k in range(1, n + 2): ga, gb = fpoint(g) term = bernoulli(2*k)/factorial(2*k)*(gb - ga) if (eps and term and abs(term.evalf(3)) < eps) or (k > n): break s += term g = g.diff(i, 2, simplify=False) return s + iterm, abs(term)
def _surface_area_of_revolution_(fx, gx, lower_bound, upper_bound, line_of_rotation, variable_of_integration) -> object: """Area of a Surface of Revolution: A surface of revolution is obtained when a curve is rotated about an axis. We consider two cases – revolving about the x−axis and revolving about the y−axis. Revolving about the x−axis: Suppose that y(x), y(t), and y(θ) are smooth non-negative functions on the given interval. A1. If the curve y = f(x), a ≤ x ≤ b is rotated about the x−axis, then the surface area is given by: - A = 2π ∫ [a, b] f(x) √(1 + [f′(x)]^2) dx. A2. If the curve is described by the function x = g(y), c ≤ y ≤ d, and rotated about the x−axis, then the area of the surface of revolution is given by: - A = 2π ∫ [c, d] y √(1 + [g′(y)]^2) dy. A3. If the curve defined by the parametric equations x = x(t), y = y(t), with t ranging over some interval [α, β], is rotated about the x−axis, then the surface area is given by the following integral (provided that y(t) is never negative): - A = 2π ∫ [α, β] y(t) √([x′(t)]^2 + [y′(t)]^2) dt. A4. If the curve defined by polar equation r = r(θ), with θ ranging over some interval [α, β], is rotated about the polar axis, then the area of the resulting surface is given by the following formula (provided that y = r sin θ is never negative): - A = 2π ∫ [α, β] r(θ) sin(θ) √([r(θ)]^2 + [r′(θ)]^2) dθ. Revolving about the y−axis: Suppose that g(y), x(t), and x(θ) are smooth non-negative functions on the given interval. B1. If the curve y = f(x), a ≤ x ≤ b is rotated about the y−axis, then the surface area is given by: - A = 2π ∫ [a, b] x √(1 + [f′(x)]^2) dx. B2. If the curve is described by the function x = g(y), c ≤ y ≤ d, and rotated about the y−axis, then the area of the surface of revolution is given by: - A = 2π ∫ [c, d] g(y) √(1 + [g′(y)]^2) dy. B3. If the curve defined by the parametric equations x = x(t), y = y(t), with t ranging over some interval [α, β], is rotated about the y−axis, then the surface area is given by the following integral (provided that x(t) is never negative): - A = 2π ∫ [α, β] x(t) √([x′(t)]^2 + [y′(t)]^2) dt. B4. If the curve defined by polar equation r = r(θ), with θ ranging over some interval [α, β], is rotated about y-axis, then the area of the resulting surface is given by the following formula (provided that x = r sin θ is never negative): - A = 2π ∫ [α, β] r(θ) cos(θ) √([r(θ)]^2 + [r′(θ)]^2) dθ. :param fx: :param gx: :param lower_bound: :param upper_bound: :param line_of_rotation: :param variable_of_integration: :return: """ _l_ = lower_bound _u_ = upper_bound _var_ = variable_of_integration _f_ = fx if fx is not None else gx _g_ = gx k = line_of_rotation if line_of_rotation is not None else None _radius_ = _var_ if k is None else (_var_ - k) _k_ = _radius_ if _radius_ is not None else _var_ if _f_ is not None and _g_ is None: _f_der = _f_.diff(_var_) _f_arc = simplify(2 * pi * _f_ * sqrt(1 + _f_der**2)) _f_int = Integral(_f_arc, (_var_, _l_, _u_)) sol_f_int = simplify(_f_int.doit()) _demo_ = Integral(_f_arc, _var_) _demo_sol = _demo_.doit() print("\nf({}) = \n".format(_var_)) pretty_print(_f_) print("\nf'({}) = \n".format(_var_)) pretty_print(_f_der) print("\nArc Length Function: \n") pretty_print(_demo_) print("\nUnbounded Antiderivative Solution of Arc Length: \n") pretty_print(_demo_sol) # print("\nArc Length") # pretty_print(_f_arc) print("\nBounded Arc Length: \n") pretty_print(_f_int) print("\nBounded Arc Length Solution: \n") pretty_print(simplify(sol_f_int)) print(sol_f_int) print("\nExpanded Solution: \n") pretty_print(expand(sol_f_int)) return [fx, _f_der, _demo_, _demo_sol, _f_int, sol_f_int]
def test_doit(): e = Integral(Integral(2*x), (x, 0, 1)) assert e.doit() == Rational(1, 3)