Numerically integrate a function f(x) over x using MATLAB where f(x) has another argument y which is a vector - matlab

I would like to numerically integrate a vector which represents a function f(x) over the range of x specified by bounds x0 and x1 in Matlab. I would like to check that the output of the integration is correct and that it converges.
There are the quad and quadl functions that serve well in identifying the required error tolerance, but they need the input argument to be a function and not the resulting vector of the function. There is also the trapz function where we can enter the two vectors x and f(x), but then it computes the integral of f(x) with respect to x depending on the spacing used by vector x. However, there is no given way using trapz to adjust the tolerance as in quad and quadl and make sure the answer is converging.
The main problem why I can't use quad and quadl functions is that f(x) is the following equation:
f(x) = sum(exp(-1/2 *(x-y))), the summation is over y, where y is a vector of length n and x is an element that is given each time to the function f(x). Therefore, all elements in vector y are subtracted from element x and then the summation over y is calculated to give us the value f(x). This is done for m values of x, where m is not equal to n.
When I use quadl as explained in the Matlab manual, where f(x) is defined in a separate function .m file and then in the main calling file, I use Q = quadl(#f,x0,x1,tolerance,X,Y); here X is a vector of length m and Y is a vector of length L. Matlab gives an error: "??? Error using ==> minus
Matrix dimensions must agree." at the line where I define the function f(x) in the .m function file. f(x) = sum(exp(-1/2 *(x-y)))
I assume the problem is that Matlab treats x and y as vectors that should be of the same length when they are subtracted from each other, whereas what's needed is to subtract the vector Y each time from a single element from the vector X.
Would you please recommend a way to solve this problem and successfully numerically integrate f(x) versus x with a method to control the tolerance?

From the documentationon quad it says:
The function y = fun(x) should accept a vector argument x and return a vector result y, the integrand evaluated at each element of x.
So every time we call the function, we need to evaluate the integrand at each given x.
Also, to parameterize the function call with the constant vector Y, I recommend an anonymous function call. There's a reasonable demo here. Here's how I implemented your problem in Matlab:
function Q = test_num_int(x0,x1,Y)
Q = quad(#(x) myFun(x,Y),x0,x1);
end
function fx = myFun(x,Y)
fy = zeros(size(Y));
fx = zeros(size(x));
for jj=1:length(fx)
for ii=1:length(Y)
fy(ii) = exp(-1/2 *(x(jj)-Y(ii)));
end
fx(jj) = sum(fy);
end
end
Then I called the function and got the following output:
Y = 0:0.1:1;
x0 = 0;
x1 = 1;
Q = test_num_int(x0,x1,Y)
Q =
11.2544
The inputs for the lower and upper bound and the constant array are obviously just dummy values, but the integral converges very quickly, almost immediately. Hope this helps!

I believe the following would also work:
y = randn(10,1);
func = #(x) sum(exp(-1/2 *(x-y)));
integral(func,0,1,'ArrayValued',true)

Related

Symbolic differentiation

Well, I know, for a normal case, if I define
syms x,y
K = f(x,y)
as an explicit expression on x and y, we can do diff(K, x) or diff(K, y) to obtain what we want.
But right now, if I have another function
J = g(K)
And I want to do
diff(J, K)
then error occurs as:
'The second argument must be a variable or a non negative integer specifying the number of differentiations.'
So, in a nutshell, how to solve this kind of 'chained expression differentiation'? (Sorry for this ambiguous description.)
According to the diff function in Matlab,
The first argument should be the function you want to differentiate
and the remaining arguments must be either the symbolic variables or a
non-negative number which represents the number of differentiation.
So, the error.
The second argument must be a variable or a non negative integer specifying the number of differentiations.
In the code diff(J, K) is saying that K is a symbolic variable to the Matlab but in actual case, K is an expression in the terms of x and y. So, this is the reason why Matlab is throwing that error.
So if you want to differentiate a chained function with variables x, y then you need to mention each symbolic variables explicitly within the diff() function whenever you want to differentiate that expression. The code to do so is below.
% define the symbolic functions
% as f(x,y) and g(K)
syms f(x,y) g(K)
% create the functions
K = f(x,y)
J = g(K)
% differentiate the functions with
% respect to x and y respectively.
% ------------------------
% differentiate w.r.t x
diff_K_x = diff(K, x)
% differentiate w.r.t y
diff_K_y = diff(K, y)
% -----------------------
% differentiate the function J with respect to x and y both
diff_K_xy = diff(J,x,y)

How to plot function of 3 variables with Octave?

I am new to Octave (and matlab for that matter). I have a function that looks like this
I would like to plot g(x,0.5,5) say.
Here it is what I tried in Octave
I defined an anonymous function
f=#(n,x,t) 1./n.*log(n.*pi.*t).*sin(n.*pi.*x);
then another anonymous function
g=#(m,x,t)x.^2+sum(f([1:m],x,t));
Finally defined
x=-1:0.1:1;
plot(x,g(5,x,0.5))
but I get an error. Is this the right way of plotting this function? I must be doing a simple beginner error?
When you call f(n,x,t), you are passing a 1-by-5 vector for n and a 1-by-21 vector for x. These have different numbers of elements, and therefore can't be multiplied element-by-element. However, you can rewrite f to accommodate vectors for each and perform the sum from g by using matrix multiplication:
f = #(n, x, t) (1./n.*log(n.*pi.*t))*sin(pi.*n(:)*x);
g = #(m, x, t) x.^2 + f(1:m, x, t);
And now your plot will work:
x = -1:0.1:1;
plot(x, g(5, x, 0.5));

Integral of a 2D function with parameters in Matlab

I have a function in Matlab which takes four arguments:
function result = my_function(par1, x, y, par2)
// some code
end
I want to integrate it in 2D (along the x and y dimentions), for a chosen values of par1 and par2. Here is how I do it:
par1 = 1;par2 =2;
result = integral2(#(x,y)my_function(par1, x, y, par2), xmin, xmax, ymin, ymax);
However, when I ran this code and display the size of variables x and y inside my function, it is big. The integral2 function executes my function on arrays of arguments at once.
How can I force matlab to execute the function my_function for one value of x and y at a time?
Of course, I can check the size of x and y inside my function and then manually create an array of results:
function result = my_function(par1, x, y, par2)
result = zeros(size(x));
for i=1:size(result(:))
% do the work here
end
reshape(result, size(x))
end
But this isn't a very elegant solution.
Update: I agree that the integer is a scalar and I like it that way. The problem is that my function work only when the arguments (x and y) are scalars.
Matlab needs an array of values of my function to calculate the integral, so it evaluates my function once when x and y are arrays. And I want it to evaluate my function many times for x and y which are scalars.

Why does lsqnonlin reshape its input argument?

The optimization function lsqnonlin appears to change the shape of x, the argument to the function being minimized, if x is a multidimensional matrix. Why does it do this and can I stop it?
The documentation says "When x0 is a matrix, solvers pass x as a matrix of the same size as x0 to ... the objective function." However, in the following example the size of x changes on subsequent iteration of lsqnonlin.
Function to minimize:
function y = myfun(X)
size(X)
y = [];
for k = 1:numel(X)
y(k) = 2 * X(k) + 5;
end
end
Call to lsqnonlin:
x0 = rand(2,2,3);
x = lsqnonlin(#myfun,x0);
Displays:
ans =
2 2 3
ans =
2 6
etc.
Why is the shape of X changing?
Edit:
This bug have been fixed in MATLAB R2015b.
By looking at the stack trace it appears that the dimension of the optimization variable X becomes wrong when the objective function is called by finDiffEvalAndChkErr, that in turn is called by finitedifferences. These are encrypted functions so there is not much to say. The only thing to do is to notice this to Mathworks.
The function finitedifferences behaves in this way because when it is called by sfdnls it receives: X in column array shape, and its true size as number of rows and number of colums, the latter being the product of the last dimensions of X.
I guess that the dimensions of X can be restored by a reshape inside myfun. Another possibility is to give to lsqnonlin the gradient of the objective function, so that the clearly buggy internal functions are no longer used.

How to plot this function in MATLAB?

I have a simple function below (I omitted the allocations, etc. for brevity) that I have been tryig to plot against it's x value for specific values of N and T but I keep getting a dimensions error. I think that when I try to plot this I am defining an array for x and then plotting Psum(N', x, T') for certain N' and T' against these x, however MATLAB doesn't seem to like this. Can someone give me some direction please.
function U = Psum(N, X, T)
for m = 1:N
A(1,m) = (1/(m*pi))*sin(m*pi*X)*T*exp(-(m^2)*(pi^2)*T);
% array terms of partial sum
end
M = -sum(A); % evaluate Nth partial sum
U = T*(1-X) + M; % output U(X,T) = T(1-X) + V(X,T)
end
I'm getting a similar error when I try to plot the following, I think there must be something wrong with my general approach
syms x;
f = #(x)((x/(100*pi))*(exp(-(100^2)*(pi^2)*x)));
x = 0:0.1:10000;
plot(x,f(x),'r')
title('PartialSum convergence');
xlabel('T');
ylabel('a_n');
the error I get here reads:
Error using *
Inner matrix dimensions must agree.
Here's the analysis of why you're getting a dimension mismatch error. From this line:
A(1,m) = (1/(m*pi))*sin(m*pi*X)*T*exp(-(m^2)*(pi^2)*T)
The element A(1, m) is supposed to be a scalar value in a two-dimensional matrix. Now let's see what are the dimensions of each of the multiplicands:
(1/(m*pi)) is a scalar (that is, a 1×1 matrix).
sin(m*pi*X) has the same dimensions as X. Let's assume its dimensions are q×n.
exp(-(m^2)*(pi^2)*T) has the same dimensions as T, and is multiplied by T.
Therefore T must be a square matrix, so let's assume its dimensions are p×p.
What we get is a q×n matrix multiplied by a square p×p matrix, and the result must be a scalar (that is, 1×1 matrix). This forces q=1 and n=p.
Now let's look at this line:
U = T*(1-X) + M
We are forced to conclude that p=1, otherwise T cannot be multiplied by X from the right.
This means that your code forces T and X to be scalar! No wonder you're getting a error :)
The remedy is simple: revise the computation in Psum so that it can produce correct results for both a scalar X and a vector X. A possible fix would be adding another loop to iterate over all values of X:
function U = Psum(N, X, T)
U = zeros(size(X));
for k = 1:numel(X) %// Iterate over all values of X
for m = 1:N
A(1,m) = (1/(m*pi))*sin(m*pi*X(k))*T*exp(-(m^2)*(pi^2)*T);
%// array terms of partial sum
end
M = -sum(A); % evaluate Nth partial sum
U(k) = T*(1-X(k)) + M; % output U(X,T) = T(1-X) + V(X,T)
end
end
The output of this function has the same dimensions as X.
By the way, did you verify that Psum produces that correct result for scalar inputs?
I don't fully understand what you are trying to accomplish, but just an observation for you: if your input X is a vector, line 3 can not be computed correctly
A(1,m) = (1/(m*pi))*sin(m*pi*X)*T*exp(-(m^2)*(pi^2)*T);
because the right hand side of the equation give you a vector, but the right hand side A(1,m) is one element, not vector. so you have dimension mismatch.
Hope this helps!