Gauss-Laguerre Quadrature Evaluation Points and Weights
This example shows how to solve polynomial equations and systems of equations, and work with the results using Symbolic Math Toolbox™.
Gaussian quadrature rules approximate an integral by sums . Here, the and are parameters of the method, depending on but not on . They follow from the choice of the weight function , as follows. Associated to the weight function is a family of orthogonal polynomials. The polynomials' roots are the evaluation points . Finally, the weights are determined by the condition that the method be correct for polynomials of small degree. Consider the weight function on the interval . This case is known as the Gauss-Laguerre quadrature.
syms t
n = 4;
w(t) = exp(-t);Assume you know the first members of the family of orthogonal polynomials. In case of the quadrature rule considered here, they turn out to be the Laguerre polynomials.
F = laguerreL(0:n-1, t)
F =
Let L be the st polynomial, the coefficients of which are still to be determined.
X = sym('X', [1, n+1])X =
L = poly2sym(X, t)
L =
Represent the orthogonality relations between the Laguerre polynomials F and L in a system of equations sys.
sys = [int(F.*L.*w(t), t, 0, inf) == 0]
sys =
Add the condition that the polynomial have norm 1.
sys = [sys, int(L^2.*w(t), 0, inf) == 1]
sys =
Solve for the coefficients of L.
S = solve(sys, X)
S = struct with fields:
X1: [2×1 sym]
X2: [2×1 sym]
X3: [2×1 sym]
X4: [2×1 sym]
X5: [2×1 sym]
solve returns the two solutions in a structure array. Display the solutions.
structfun(@display, S)
ans =
ans =
ans =
ans =
ans =
Make the solution unique by imposing an extra condition that the first coefficient be positive:
sys = [sys, X(1)>0]; S = solve(sys, X)
S = struct with fields:
X1: 1/24
X2: -2/3
X3: 3
X4: -4
X5: 1
Substitute the solution into L.
L = subs(L, S)
L =
As expected, this polynomial is the |n|th Laguerre polynomial:
laguerreL(n, t)
ans =
The evaluation points are the roots of the polynomial L. Solve L for the evaluation points. The roots are expressed in terms of the root function.
x = solve(L)
x =
The form of the solutions might suggest that nothing has been achieved, but various operations are available on them. Compute floating-point approximations using vpa:
vpa(x)
ans =
Some spurious imaginary parts might occur. Prove symbolically that the roots are real numbers:
isAlways(in(x, 'real'))ans = 4×1 logical array
1
1
1
1
For polynomials of degree less than or equal to 4, you can use MaxDegree to obtain the solutions in terms of nested radicals instead in terms of root. However, subsequent operations on results of this form would be slow.
xradical = solve(L, 'MaxDegree', 4)xradical =
The weights are given by the condition that for polynomials of degree less than , the quadrature rule must produce exact results. It is sufficient if this holds for a basis of the vector space of these polynomials. This condition results in a system of four equations in four variables.
y = sym('y', [n, 1]); sys = sym(zeros(n)); for k=0:n-1 sys(k+1) = sum(y.*(x.^k)) == int(t^k * w(t), t, 0, inf); end sys
sys =
Solve the system both numerically and symbolically. The solution is the desired vector of weights .
[a1, a2, a3, a4] = vpasolve(sys, y)
a1 =
a2 =
a3 =
a4 =
[alpha1, alpha2, alpha3, alpha4] = solve(sys, y)
alpha1 =
alpha2 =
alpha3 =
alpha4 =
Alternatively, you can also obtain the solution as a structure by giving only one output argument.
S = solve(sys, y)
S = struct with fields:
y1: -(root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3)*root(z^4…
y2: (root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3)*root(z^4 …
y3: (root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4 …
y4: -(root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4…
structfun(@double, S)
ans = 4×1
0.6032
0.3574
0.0389
0.0005
Convert the structure S to a symbolic array:
Scell = struct2cell(S);
alpha = transpose([Scell{:}])alpha =
The symbolic solution looks complicated. Simplify it, and convert it into a floating point vector:
alpha = simplify(alpha)
alpha =
vpa(alpha)
ans =
Increase the readability by replacing the occurrences of the roots x in alpha by abbreviations:
subs(alpha, x, sym('R', [4, 1]))ans =
Sum the weights to show that their sum equals 1:
simplify(sum(alpha))
ans =
A different method to obtain the weights of a quadrature rule is to compute them using the formula . Do this for . It leads to the same result as the other method:
int(w(t) * prod((t - x(2:4)) ./ (x(1) - x(2:4))), t, 0, inf)
ans =
The quadrature rule produces exact results even for all polynomials of degree less than or equal to , but not for .
simplify(sum(alpha.*(x.^(2*n-1))) -int(t^(2*n-1)*w(t), t, 0, inf))
ans =
simplify(sum(alpha.*(x.^(2*n))) -int(t^(2*n)*w(t), t, 0, inf))
ans =
Apply the quadrature rule to the cosine, and compare with the exact result:
vpa(sum(alpha.*(cos(x))))
ans =
int(cos(t)*w(t), t, 0, inf)
ans =
For powers of the cosine, the error oscillates between odd and even powers:
errors = zeros(1, 20); for k=1:20 errors(k) = double(sum(alpha.*(cos(x).^k)) -int(cos(t)^k*w(t), t, 0, inf)); end plot(real(errors))
