I am dealing with a problem of finding accurate numerical values of integrals. Specifically, the integral is introduced by using the best approximation scheme (Legendre Polynomials) to approximate a vector valued function whose indefinite integral is not easy to be explicitly written down. The code is provided as follows:
r1 = 0.7; r2 = 1; r3 = r2 - r1; d = 8;
syms y real
le = [];
for i = 0:d
l = [coeffs(legendreP(i,(2/r1)*y+1)) zeros(1,d-i)];
le = [le; l];
end
leg = [];
for i = 0:d
l = [coeffs(legendreP(i,(2*y + r1 + r2)/r3)) zeros(1,d-i)];
leg = [leg; l];
end
syms x
t = [];
for i = 0 : d
t = [t ; x^i];
end
xp = t;
lp = le*xp; la = leg*xp;
fi1 = [exp(sin(x)); exp(cos(x))]; fi2 = [sin(x^2); cos(x^2)];
ny1 = size(fi1,1); ny2 = size(fi2,1); ny = ny1 + ny2;
ga1 = fi1*lp'; ga2 = fi2*la';
Ga1 = double(int(ga1,x,-r1,0)*diag(2.*(0:d)+1)*(1/r1));
Ga2 = double(int(ga2,x,-r2,-r1)*diag(2.*(0:d)+1)*(1/r3));
ep1 = fi1 - Ga1*lp; ep2 = fi2 - Ga2*la;
E1 = double(int(ep1*ep1',x,-r1,0)); E2 = double(int(ep2*ep2',x,-r2,-r1));
The code works fine until d = 8 when an error is returned to state that DOUBLE cannot convert the input expression into a double array. If the input expression contains a symbolic variable, use VPA.
I have tried vpa function but the same problem happens still.
One may suggest to use integral numerical integration instead of int. However, the numerical integration seems produce inaccurate result compared to the symbolic representation. Note that the error matrix E1 and E2 become extremely small when the approximation degree d becomes large.
To summarize, the problem here is how to extract, or accurately calculate if anyone has suggestions, the numerical values of E1 and E2.
Thanks a lot!

2 commentaires

You say that we can try it ourselves, but since there are undefined variables, we cannot do so.
Undefined function or variable 'n'.
So trying it ourselves stops at line 1.
Qian Feng
Qian Feng le 17 Nov 2016
Sorry, now the code should be correct

Connectez-vous pour commenter.

 Réponse acceptée

Walter Roberson
Walter Roberson le 7 Nov 2016

1 vote

If you change your first line to
syms n
r1 = 0.7; r2 = 1; r3 = r2 - r1; d = 8; di = n*(d+1);
then you can complete down through E1. After that, unfortunately MATLAB does not know how to do the integral, even though there is a closed-form solution for it. You will need to switch to numeric:
FF = ep2*ep2';
FF1 = matlabFunction(simplify(FF(1));
FF2 = matlabFunciton(simplify(FF(2));
E2(1) = integral(FF1, -r2, -r1);
E2(2) = integral(FF2, -r2, -r1);

26 commentaires

Qian Feng
Qian Feng le 7 Nov 2016
Modifié(e) : Qian Feng le 7 Nov 2016
but when d<8, why the value of E2 can be obtained in fact? This is one of the reason I posed this question since it seems weird that the code only fails to produce result when d become relatively higher. Try d = 1...7 then you can see what I am talking about.
Sorry, di and n are redundant in my code and they should not be there in the first place.
Walter Roberson
Walter Roberson le 7 Nov 2016
Modifié(e) : Walter Roberson le 7 Nov 2016
I believe the appropriate answer is "I don't know." It is not obvious to me why there might be problems with the numeric integral.
The other half of the answer is: considering you are converting to double() immediately after, is there a reason not to duck the issue by doing numeric integration over the function handle?
Qian Feng
Qian Feng le 17 Nov 2016
Modifié(e) : Qian Feng le 17 Nov 2016
Thank you very much for the answer. Now first I have a question. What is the mechanism which Matlab applies when I use the syntax double(Ga1) ? Does it automatically perform a numerical integration or use other scheme to get the numerical values of Ga1.
Walter Roberson
Walter Roberson le 17 Nov 2016
Modifié(e) : Walter Roberson le 18 Oct 2017
If you have an symbolic int() that it cannot find a closed form solutions for then when you double() it sends the problem to the mupad routine numeric::int for numeric integration. I do not recall at the moment what the default integration method is.
Qian Feng
Qian Feng le 17 Nov 2016
Modifié(e) : Qian Feng le 1 Déc 2016
The reason asked this question is because as I had said in the main question that It occurred that using symbolic produces more accurate results than applying numerical integrations.
Walter Roberson
Walter Roberson le 17 Nov 2016
In cases where a closed-form solution can be found, double(int()) involves finding the closed form solution and evaluating it at the given locations. That might involve calculations with large or small magnitudes or have taken into account odd shapes that are difficult to calculate accurately numerically in a finite amount of time.
In the case where no closed form solution can be found, the double() triggers using numeric::int which uses quadrature . This still has advantages compared to numeric integration at the MATLAB level because of the extended range and extended digits that symbolics permits.
Qian Feng
Qian Feng le 21 Nov 2016
OK. Based on the information you provided, then there must be some problems occurred to the scenario of numeric::int when d>=8. Do you have some idea about that ? Could the error happened simply because the numerical values become too small to be handled ?
Use "vpaintegral" introduced in 16b: https://www.mathworks.com/help/symbolic/vpaintegral.html.
F2 = vpaintegral(ep2*ep2',x,-r2,-r1)
F2 =
[ 1.53919e-23, 2.0475e-23]
[ 2.0475e-23, 2.73446e-23]
Workaround without using the new vpaintegral:
RRR = ep2*ep2';
E2 = zeros(size(RRR));
for K = 1 : numel(RRR)
E2(K) = double( sum(int(children(expand(RRR(K))),x,-r2,-r1)) );
end
Karan Gill
Karan Gill le 22 Nov 2016
Walter, that's very fancy ;)
Qian Feng
Qian Feng le 30 Nov 2016
Thanks Walter and Karan, could you guys put your answer into a new thread so I can accept it ? There are many comments in this one.
Walter Roberson
Walter Roberson le 30 Nov 2016
You can Accept this one if I answered your question. If you ended up using vpaintegral() then Yes, Karan should create an Answer so that can be accepted.
Walter Roberson
Walter Roberson le 30 Nov 2016
(I just created a bug report about the integral failing.)
Karan Gill
Karan Gill le 30 Nov 2016
FWIW I plonked down a separate answer.
Qian Feng
Qian Feng le 1 Déc 2016
OK, I want to accept both answers of you guys but it seems there is only one answer I can accept.
Walter Roberson
Walter Roberson le 1 Déc 2016
Correct, only one Answer can be accepted at present. But you can Vote for the other.
Qian Feng
Qian Feng le 6 Déc 2016
OK, So the integral failing can be considered as a bug ? Thanks a lot for highlighting it.
Walter Roberson
Walter Roberson le 6 Déc 2016
Mathworks tells me that double() fails for this because it uses fewer digits and apparently there might be some convergence problem in that case. double(vpa()) is another way of approaching it.
Qian Feng
Qian Feng le 20 Déc 2016
double(vpa()) still generated error when d = 8
Walter Roberson
Walter Roberson le 20 Déc 2016
Use a higher digits for vpa() and allow double() to reduce it.
Qian Feng
Qian Feng le 21 Déc 2016
Could you explain the meaning 'allow double() to reduce it' ? Is there an option for double() to do this ?
SomeLargeNumberOfDigits = 32;
double( vpa(YourExpression, SomeLargeNumberOfDigits) )
Karan Gill
Karan Gill le 23 Déc 2016
Qian Feng
Qian Feng le 30 Déc 2016
Ok, is this about reducing the Number of significant digits of vpa function ?
Walter Roberson
Walter Roberson le 30 Déc 2016
Modifié(e) : Walter Roberson le 24 Sep 2017
No, you need the number of digits of vpa to remain high so that vpa is able to converge. But then you can transform those higher number of symbolic digits into a numeric floating point value with double().
... or just use vpaintegral() directly if you have a new enough MATLAB.
Qian Feng
Qian Feng le 4 Jan 2017
Right, so I need larger valued of digits for vpa function.

Connectez-vous pour commenter.

Plus de réponses (1)

Karan Gill
Karan Gill le 30 Nov 2016
Modifié(e) : Karan Gill le 17 Oct 2017

2 votes

Use "vpaintegral" introduced in 16b: https://www.mathworks.com/help/symbolic/vpaintegral.html.
F2 = vpaintegral(ep2*ep2',x,-r2,-r1)
F2 =
[ 1.53919e-23, 2.0475e-23]
[ 2.0475e-23, 2.73446e-23]

4 commentaires

clear all
tic
my = 2;
d = 15; de = 15;
r1 = 2; r2 = 4.05; r3 = r2 - r1;
dai1 = d+1; dai2 = de+1;
ro = (dai1 + dai2)*my;
syms y real
le = [];
for i = 0:d
l = [coeffs(legendreP(i,(2/sym(r1))*y+1)) zeros(1,d-i)];
le = [le; l];
end
leg = [];
for i = 0:d
l = [coeffs(legendreP(i,(2*y + sym(r1 + r2))/ sym(r3) )) zeros(1,d-i)];
leg = [leg; l];
end
syms x real
xp = (x.^(0:d))';
l1 = le*xp; l2 = leg*xp;
a = 18;
fi1 = [sin(a*x); cos(a*x); exp(sin(a*x)); exp(cos(a*x))]; fi2 = fi1;
ga1 = fi1*l1'; ga2 = fi2*l2';
Dd = diag(2.*(0:d)+1); Dde = diag(2.*(0:de)+1);
Ga1 = vpaintegral(ga1,x,-r1,0, 'AbsTol',1e-20, 'RelTol',1e-20, 'MaxFunctionCalls', Inf)*Dd*(r1^(-1));
ep1 = simplify((fi1 - Ga1*l1)*(fi1 - Ga1*l1)', 'Steps', 100);
E1 = vpaintegral(ep1,x, -r1, 0, 'AbsTol',1e-20, 'RelTol',1e-20);
Ga2 = vpaintegral(ga2,x,-r2,-r1, 'MaxFunctionCalls', Inf)*Dde*(r3^(-1));
ep2 = simplify((fi2 - Ga2*l2)*(fi2 - Ga2*l2)', 'Steps', 100);
E2 = vpaintegral(ep2,x, -r2,-r1, 'MaxFunctionCalls', Inf);
toc
eta1 = 1; eta2 = 1;
Karan, see the attached code here. There are difficulties to get the value of Ga2. If we put the breakpoint at Ga2, you can see that Ga1 and E1 can be calculated within a reasonable period. The functions inside of the integrations contain no singularities I believe, so I am puzzled here since the type of functions inside of the integrations among Ga1, Ga2, are the same.
Walter Roberson
Walter Roberson le 22 Sep 2017
In your Ga2 computation, you left out the AbsTol and RelTol options. The ga2(end-1) is quite sensitive to the number of digits of computation near -4.05
Qian Feng
Qian Feng le 24 Sep 2017
Thanks Walter, so what number do you suggest that I should choose for the AbsTol and RelTol in this case?
Walter Roberson
Walter Roberson le 24 Sep 2017
My tests with a different package suggested that 20 or so digits of precision was needed to get a decent result, so 1e-20 like you used for Ga1 might be enough.

Connectez-vous pour commenter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by