def test_jacobi_poly(): raises(ValueError, lambda: jacobi_poly(-1, a, b, x)) assert jacobi_poly(1, a, b, x, polys=True) == Poly((a/2 + b/2 + 1)*x + a/2 - b/2, x, domain='ZZ(a,b)') assert jacobi_poly(0, a, b, x) == 1 assert jacobi_poly(1, a, b, x) == a/2 - b/2 + x*(a/2 + b/2 + 1) assert jacobi_poly(2, a, b, x) == (a**2/8 - a*b/4 - a/8 + b**2/8 - b/8 + x**2*(a**2/8 + a*b/4 + 7*a/8 + b**2/8 + 7*b/8 + S(3)/2) + x*(a**2/4 + 3*a/4 - b**2/4 - 3*b/4) - S(1)/2) assert jacobi_poly(1, a, b, polys=True) == Poly((a/2 + b/2 + 1)*x + a/2 - b/2, x, domain='ZZ(a,b)')
def eval(cls, n, a, b, x): # Simplify to other polynomials # P^{a, a}_n(x) if a == b: if a == -S.Half: return C.RisingFactorial(S.Half, n) / C.factorial(n) * chebyshevt(n, x) elif a == S.Zero: return legendre(n, x) elif a == S.Half: return C.RisingFactorial(3 * S.Half, n) / C.factorial(n + 1) * chebyshevu(n, x) else: return C.RisingFactorial(a + 1, n) / C.RisingFactorial(2 * a + 1, n) * gegenbauer(n, a + S.Half, x) elif b == -a: # P^{a, -a}_n(x) return ( C.gamma(n + a + 1) / C.gamma(n + 1) * (1 + x) ** (a / 2) / (1 - x) ** (a / 2) * assoc_legendre(n, -a, x) ) elif a == -b: # P^{-b, b}_n(x) return ( C.gamma(n - b + 1) / C.gamma(n + 1) * (1 - x) ** (b / 2) / (1 + x) ** (b / 2) * assoc_legendre(n, b, x) ) if not n.is_Number: # Symbolic result P^{a,b}_n(x) # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) if x.could_extract_minus_sign(): return S.NegativeOne ** n * jacobi(n, b, a, -x) # We can evaluate for some special values of x if x == S.Zero: return ( 2 ** (-n) * C.gamma(a + n + 1) / (C.gamma(a + 1) * C.factorial(n)) * C.hyper([-b - n, -n], [a + 1], -1) ) if x == S.One: return C.RisingFactorial(a + 1, n) / C.factorial(n) elif x == S.Infinity: if n.is_positive: # TODO: Make sure a+b+2*n \notin Z return C.RisingFactorial(a + b + n + 1, n) * S.Infinity else: # n is a given fixed integer, evaluate into polynomial return jacobi_poly(n, a, b, x)
def eval(cls, n, a, b, x): # Simplify to other polynomials # P^{a, a}_n(x) if a == b: if a == Rational(-1, 2): return RisingFactorial(S.Half, n) / factorial(n) * chebyshevt( n, x) elif a.is_zero: return legendre(n, x) elif a == S.Half: return RisingFactorial( 3 * S.Half, n) / factorial(n + 1) * chebyshevu(n, x) else: return RisingFactorial(a + 1, n) / RisingFactorial( 2 * a + 1, n) * gegenbauer(n, a + S.Half, x) elif b == -a: # P^{a, -a}_n(x) return gamma(n + a + 1) / gamma(n + 1) * (1 + x)**(a / 2) / ( 1 - x)**(a / 2) * assoc_legendre(n, -a, x) if not n.is_Number: # Symbolic result P^{a,b}_n(x) # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) if x.could_extract_minus_sign(): return S.NegativeOne**n * jacobi(n, b, a, -x) # We can evaluate for some special values of x if x.is_zero: return (2**(-n) * gamma(a + n + 1) / (gamma(a + 1) * factorial(n)) * hyper([-b - n, -n], [a + 1], -1)) if x == S.One: return RisingFactorial(a + 1, n) / factorial(n) elif x is S.Infinity: if n.is_positive: # Make sure a+b+2*n \notin Z if (a + b + 2 * n).is_integer: raise ValueError( "Error. a + b + 2*n should not be an integer.") return RisingFactorial(a + b + n + 1, n) * S.Infinity else: # n is a given fixed integer, evaluate into polynomial return jacobi_poly(n, a, b, x)
def test_jacobi_poly(): raises(ValueError, lambda: jacobi_poly(-1, a, b, x)) assert jacobi_poly(1, a, b, x, polys=True) == Poly( (a / 2 + b / 2 + 1) * x + a / 2 - b / 2, x, domain='ZZ(a,b)') assert jacobi_poly(0, a, b, x) == 1 assert jacobi_poly(1, a, b, x) == a / 2 - b / 2 + x * (a / 2 + b / 2 + 1) assert jacobi_poly(2, a, b, x) == ( a**2 / 8 - a * b / 4 - a / 8 + b**2 / 8 - b / 8 + x**2 * (a**2 / 8 + a * b / 4 + a * Q(7, 8) + b**2 / 8 + b * Q(7, 8) + Q(3, 2)) + x * (a**2 / 4 + a * Q(3, 4) - b**2 / 4 - b * Q(3, 4)) - S.Half) assert jacobi_poly(1, a, b, polys=True) == Poly( (a / 2 + b / 2 + 1) * x + a / 2 - b / 2, x, domain='ZZ(a,b)')
def test_jacobi_poly(): raises(ValueError, lambda: jacobi_poly(-1, a, b, x)) assert jacobi_poly(1, a, b, x, polys=True) == Poly( (a / 2 + b / 2 + 1) * x + a / 2 - b / 2, x, domain='ZZ(a,b)') assert jacobi_poly(0, a, b, x) == 1 assert jacobi_poly(1, a, b, x) == a / 2 - b / 2 + x * (a / 2 + b / 2 + 1) assert jacobi_poly(2, a, b, x) == ( a**2 / 8 - a * b / 4 - a / 8 + b**2 / 8 - b / 8 + x**2 * (a**2 / 8 + a * b / 4 + 7 * a / 8 + b**2 / 8 + 7 * b / 8 + S(3) / 2) + x * (a**2 / 4 + 3 * a / 4 - b**2 / 4 - 3 * b / 4) - S(1) / 2) assert jacobi_poly(1, a, b, polys=True) == Poly( (a / 2 + b / 2 + 1) * x + a / 2 - b / 2, x, domain='ZZ(a,b)')
def eval(cls, n, a, b, x): # Simplify to other polynomials # P^{a, a}_n(x) if a == b: if a == -S.Half: return C.RisingFactorial(S.Half, n) / C.factorial(n) * chebyshevt(n, x) elif a == S.Zero: return legendre(n, x) elif a == S.Half: return C.RisingFactorial(3*S.Half, n) / C.factorial(n + 1) * chebyshevu(n, x) else: return C.RisingFactorial(a + 1, n) / C.RisingFactorial(2*a + 1, n) * gegenbauer(n, a + S.Half, x) elif b == -a: # P^{a, -a}_n(x) return C.gamma(n + a + 1) / C.gamma(n + 1) * (1 + x)**(a/2) / (1 - x)**(a/2) * assoc_legendre(n, -a, x) elif a == -b: # P^{-b, b}_n(x) return C.gamma(n - b + 1) / C.gamma(n + 1) * (1 - x)**(b/2) / (1 + x)**(b/2) * assoc_legendre(n, b, x) if not n.is_Number: # Symbolic result P^{a,b}_n(x) # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) if x.could_extract_minus_sign(): return S.NegativeOne**n * jacobi(n, b, a, -x) # We can evaluate for some special values of x if x == S.Zero: return (2**(-n) * C.gamma(a + n + 1) / (C.gamma(a + 1) * C.factorial(n)) * C.hyper([-b - n, -n], [a + 1], -1)) if x == S.One: return C.RisingFactorial(a + 1, n) / C.factorial(n) elif x == S.Infinity: if n.is_positive: # TODO: Make sure a+b+2*n \notin Z return C.RisingFactorial(a + b + n + 1, n) * S.Infinity else: # n is a given fixed integer, evaluate into polynomial return jacobi_poly(n, a, b, x)
def gauss_jacobi(n, alpha, beta, n_digits): r""" Computes the Gauss-Jacobi quadrature [1]_ points and weights. The Gauss-Jacobi quadrature of the first kind approximates the integral: .. math:: \int_{-1}^1 (1-x)^\alpha (1+x)^\beta f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i) The nodes `x_i` of an order `n` quadrature rule are the roots of `P^{(\alpha,\beta)}_n` and the weights `w_i` are given by: .. math:: w_i = -\frac{2n+\alpha+\beta+2}{n+\alpha+\beta+1} \frac{\Gamma(n+\alpha+1)\Gamma(n+\beta+1)} {\Gamma(n+\alpha+\beta+1)(n+1)!} \frac{2^{\alpha+\beta}}{P'_n(x_i) P^{(\alpha,\beta)}_{n+1}(x_i)} Parameters ========== n : the order of quadrature alpha : the first parameter of the Jacobi Polynomial, `\alpha > -1` beta : the second parameter of the Jacobi Polynomial, `\beta > -1` n_digits : number of significant digits of the points and weights to return Returns ======= (x, w) : the ``x`` and ``w`` are lists of points and weights as Floats. The points `x_i` and weights `w_i` are returned as ``(x, w)`` tuple of lists. Examples ======== >>> from sympy import S >>> from sympy.integrals.quadrature import gauss_jacobi >>> x, w = gauss_jacobi(3, S.Half, -S.Half, 5) >>> x [-0.90097, -0.22252, 0.62349] >>> w [1.7063, 1.0973, 0.33795] >>> x, w = gauss_jacobi(6, 1, 1, 5) >>> x [-0.87174, -0.5917, -0.2093, 0.2093, 0.5917, 0.87174] >>> w [0.050584, 0.22169, 0.39439, 0.39439, 0.22169, 0.050584] See Also ======== gauss_legendre, gauss_laguerre, gauss_hermite, gauss_gen_laguerre, gauss_chebyshev_t, gauss_chebyshev_u, gauss_lobatto References ========== .. [1] https://en.wikipedia.org/wiki/Gauss%E2%80%93Jacobi_quadrature .. [2] http://people.sc.fsu.edu/~jburkardt/cpp_src/jacobi_rule/jacobi_rule.html .. [3] http://people.sc.fsu.edu/~jburkardt/cpp_src/gegenbauer_rule/gegenbauer_rule.html """ x = Dummy("x") p = jacobi_poly(n, alpha, beta, x, polys=True) pd = p.diff(x) pn = jacobi_poly(n + 1, alpha, beta, x, polys=True) xi = [] w = [] for r in p.real_roots(): if isinstance(r, RootOf): r = r.eval_rational(S(1) / 10**(n_digits + 2)) xi.append(r.n(n_digits)) w.append( (-(2 * n + alpha + beta + 2) / (n + alpha + beta + S.One) * (gamma(n + alpha + 1) * gamma(n + beta + 1)) / (gamma(n + alpha + beta + S.One) * gamma(n + 2)) * 2**(alpha + beta) / (pd.subs(x, r) * pn.subs(x, r))).n(n_digits)) return xi, w
def gauss_jacobi(n, alpha, beta, n_digits): r""" Computes the Gauss-Jacobi quadrature [1]_ points and weights. The Gauss-Jacobi quadrature of the first kind approximates the integral: .. math:: \int_{-1}^1 (1-x)^\alpha (1+x)^\beta f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i) The nodes `x_i` of an order `n` quadrature rule are the roots of `P^{(\alpha,\beta)}_n` and the weights `w_i` are given by: .. math:: w_i = -\frac{2n+\alpha+\beta+2}{n+\alpha+\beta+1}\frac{\Gamma(n+\alpha+1)\Gamma(n+\beta+1)} {\Gamma(n+\alpha+\beta+1)(n+1)!} \frac{2^{\alpha+\beta}}{P'_n(x_i) P^{(\alpha,\beta)}_{n+1}(x_i)} Parameters ========== n : the order of quadrature alpha : the first parameter of the Jacobi Polynomial, `\alpha > -1` beta : the second parameter of the Jacobi Polynomial, `\beta > -1` n_digits : number of significant digits of the points and weights to return Returns ======= (x, w) : the ``x`` and ``w`` are lists of points and weights as Floats. The points `x_i` and weights `w_i` are returned as ``(x, w)`` tuple of lists. Examples ======== >>> from sympy import S >>> from sympy.integrals.quadrature import gauss_jacobi >>> x, w = gauss_jacobi(3, S.Half, -S.Half, 5) >>> x [-0.90097, -0.22252, 0.62349] >>> w [1.7063, 1.0973, 0.33795] >>> x, w = gauss_jacobi(6, 1, 1, 5) >>> x [-0.87174, -0.5917, -0.2093, 0.2093, 0.5917, 0.87174] >>> w [0.050584, 0.22169, 0.39439, 0.39439, 0.22169, 0.050584] See Also ======== gauss_legendre, gauss_laguerre, gauss_hermite, gauss_gen_laguerre, gauss_chebyshev_t, gauss_chebyshev_u References ========== .. [1] http://en.wikipedia.org/wiki/Gauss%E2%80%93Jacobi_quadrature .. [2] http://people.sc.fsu.edu/~jburkardt/cpp_src/jacobi_rule/jacobi_rule.html .. [3] http://people.sc.fsu.edu/~jburkardt/cpp_src/gegenbauer_rule/gegenbauer_rule.html """ x = Dummy("x") p = jacobi_poly(n, alpha, beta, x, polys=True) pd = p.diff(x) pn = jacobi_poly(n+1, alpha, beta, x, polys=True) xi = [] w = [] for r in p.real_roots(): if isinstance(r, RootOf): r = r.eval_rational(S(1)/10**(n_digits+2)) xi.append(r.n(n_digits)) w.append(( - (2*n+alpha+beta+2) / (n+alpha+beta+S.One) * (gamma(n+alpha+1)*gamma(n+beta+1)) / (gamma(n+alpha+beta+S.One)*gamma(n+2)) * 2**(alpha+beta) / (pd.subs(x, r) * pn.subs(x, r)) ).n(n_digits)) return xi, w
LegendreF = Rat(1) / (Rat(2) ** n) * (binomial(n, k)) ** 2 * (x - Rat(1)) ** k * (x + Rat(1)) ** (n - k) LegendreP = Sum(LegendreF, (k, 0, n)) for nvar in range(4): legendre_poly(nvar, x) == LegendreP.subs(n, nvar).doit().expand() # True (LegendreF.subs(n, n + 1) / LegendreF).simplify() # (n + 1)**2*(x + 1)/(2*(k - n - 1)**2) (LegendreF.subs(k, k + 1) / LegendreF).simplify() # (k - n)**2*(x - 1)/((k + 1)**2*(x + 1)) JacobiF = ( Rat(1) / (Rat(2) ** n) * binomial(n + alpha, n - k) * binomial(n + beta, k) * (x - Rat(1)) ** k * (x + Rat(1)) ** (n - k) ) JacobiP = Sum(JacobiF, (k, 0, n)) for alphvar in range(5): for betvar in range(5): for nvar in range(5): jacobi_poly(nvar, alphvar, betvar, x) == JacobiP.subs(n, nvar).subs(alpha, alphvar).subs( beta, betvar ).doit().expand() # True ( JacobiF.subs(n, n + 1) / JacobiF ).simplify() # (x + 1)*(alpha + n + 1)*(beta + n + 1)/(2*(k - n - 1)*(-beta + k - n - 1)) (JacobiF.subs(k, k + 1) / JacobiF).simplify() # (k - n)*(x - 1)*(-beta + k - n)/((k + 1)*(x + 1)*(alpha + k + 1))