Nested call to integral fails - matlab

Try this piece of code, which works fine.
a=1;b=2;
% A two-variate function
f2= #(x,y) x+y;
derivedF2=#(x) integral(#(y) f2(x,y), a,b);
% Test the evaluation of the derived function handle
derivedF2(0);
% Test the integration of the derived function handle
% integralVal=integral(derivedF2,a,b);
% integralVal=integral(#(x) derivedF2(x),a,b);
% Test plotting of the derived function handle
figure(11);
ezplot(derivedF2);
But if you uncomment the lines starting with integralVal. The code breaks.
Apparently, the derived function handle does not support integration operation, or have I missed something?

Short answer: you should add the 'ArrayValued' option:
integralVal=integral(derivedF2,a,b, 'ArrayValued', true);
Explanation
You should read your error message:
Output of the function must be the same size as the input. If FUN is an array-valued integrand, set the 'ArrayValued'
option to true.
Because derivedF2 is evaluated in a vectorised way, i.e. it evaluates f at different y coordinates at once by supplying a y vector instead of a single scalar, MATLAB is unable to evaluate the outer integral in a vectorised way too. Therefore you should add the 'ArrayValued' option to the outer integral, i.e.:
integralVal=integral(derivedF2,a,b, 'ArrayValued', true);
Note that ezplot also generate the following related warning:
Warning: Function failed to evaluate on array inputs; vectorizing the function may speed up its evaluation and avoid the
need to loop over array elements.
Note that the problem is purely related to nested calls to integral, also the following code will result in the same error:
integralVal=integral(#(x) integral(#(y) f2(x,y), a,b),a,b);
What is an Array Valued function?
... a function that accepts a scalar input and returns a vector, matrix, or N-D array output.
So, #(y) f2(x, y) is an array valued function if x is an array, i.e. it returns an array for a scalar input of y.
Two possibilities exist to avoid array valued problem:
Avoid that #(y) f2(x, y) is an array valued function, i.e. avoid that x is an array. This can be done by indicating that derivedF2 is an array valued function as elaborated above, although - strictly speaking - it is not an array valued function, i.e. the integral should have the same number of outputs and inputs. However, it uses internally an array valued function, i.e. #(x) f2(x, y) is an array valued function as Matlab evaluates by default the integrand in a vectorised way, i.e. it uses a vector for y.
Tell Matlab that #(y) f2(x, y) is an array valued function:
derivedF2=#(x) integral(#(y) f2(x,y), a,b, 'ArrayValued', true);
This may be a more intuitive approach, but is slower as the internal integral is called much often than the external integral.
An alternative interpretation of Array Valued is that you tell matlab to not use vectorisation, but for this interpretation the name Array Valued is somewhat misleading.

Related

Simulink: Syntax error

I have a syntax error in the following equation:
((Cs+Cf)*u(1)/Cf-Cs*u(2)/Cf)*(1/(1+(Cs+Cf)/(Cf*(10^(u0/20)))))*(1-exp(-(pi*f1*(10^9)/(fs*10^6))*(Cf/(Cs+Cf)+1/(10^(u0/20)))))
Uppercase/lowercase checked, they are ok. What could be the problem?
As mentioned in the documentation of Interpreted MATLAB Function,
The Interpreted MATLAB Function block accepts one real or complex
input of type double ...
Here you're using multiple inputs which are Cs, Cf, u0, u, f1 and fs.
How to solve it?
Solution-1: Using Interpreted MATLAB Function block
One way to deal with this problem would be to concatenate all the input matrices into a single matrix and use its indices to represent each value in the equation.
e.g; if you have:
u=[1 5]; u0=5; Cs=1; Cf=1; f1=1; fs=20;
Concatenate them into a single matrix in your workspace. Something like the following would do:
new=[u, u0, Cs, Cf, f1, fs];
%It could be different depending on the dimensions of these
%variables that you actually have
then use the following equation according to the indices of new in the Interpreted MATLAB Function block:
((new(4)+new(5))*u(1)/new(5)-new(4)*u(2)/new(5))*(1/(1+(new(4)+new(5))/(new(5)*(10^(new(3)/20)))))*(1-exp(-(pi*new(6)*(10^9)/(new(7)*10^6))*(new(5)/(new(4)+new(5))+1/(10^(new(3)/20)))))
Solution-2: Using MATLAB Function block
You can also use the MATLAB Function block in which you can use multiple inputs. For your case, write the following code in it:
function y = foo(u,u0,Cs,Cf,f1,fs)
y = ((Cs+Cf)*u(1)/Cf-Cs*u(2)/Cf)*(1/(1+(Cs+Cf)/(Cf*(10^(u0/20)))))* ...
(1-exp(-(pi*f1*(10^9)/(fs*10^6))*(Cf/(Cs+Cf)+1/(10^(u0/20)))));
and connect Constant blocks with its inputs and give the values of the constants equal to the respective variables that you want to use.

Matlab fit with function returning vector with all the y(x_i) values

I am working on something and I haven't found any solution, maybe I didn't know how to correctly search for it...
I have two arrays of experimental data (x and y). x is a list of certain energies (512 values from 0 to 100 kev) and I want to fit them to a function which returns a vector of values of y for every x in the list (the energies are always the same, 512 certain values). This is because my function model contains several matrix and other functions.
So, I can't evaluate my function as f(x,a,b,c...) (with a,b,c the parameters to fit) and expect a single scalar, but I have to evaluate f(a,b,c...), and it returns a vector of y(x1),y(x2)...
Now, I want to fit my data to my model. But lsqcurvefit needs a function of the form f(x), I suppose that it evaluates every f(x). I could write my function so that every time it is called it evaluates the vector result, and then returns y for the given x, but it would be quite inefficient... And I'm sure there must be another way.
Any idea?
Maybe you can do an fminsearch on the sum of square errors? It is best to put all fitting parameters into one vector. Here I call it p.
f = #(x,p) (p(3)+p(1)*x.^p(2)).^(1/p(4); %example function with four free parameters
sqerr = #(x,y,p) sum((y-f(x,p)).^2); %sum of squared errors
p = [1,1,1,1]; %four starting conditions
p = fminsearch(#(p) sqerr(x,y,p),p); %fit
Then you can find your y(x_i) values by calling the function with the fitted paramters
f(x,p)

Convert function in Matlab into appropriate form

I have written a function feval that takes two arguments and spits out a number.
Now I wanted to use the command integral2 in order to integrate over my function feval(x,y).
The problem seems to be that integral2 thinks that I have a function that can take two arrays as arguments and apply pairwise operations on them. Unfortunately, this is not the case. My function can only works with 2 numbers and not with full arrays. Is there any standard method to make this work?
Actually, this is my code now and MATLAB claims that
q = integral2( #(x,y) arrayfun(func_cross_scat,x,y),0,2*pi,0,pi);
my function(feval, that i renamed func_cross_scat does not get enough input arguments)
Feed integral2 not with feval, but with feval_wrapper defined as
feval_wrapper = #(x,y) arrayfun(feval, x, y)
x and y can now be arrays (of the same size). This works because arrayfun calls feval for each pair of elements of the input arrays x, y and gives an array as the result.
As a side comment, "feval" is probably not a good name for your function, because Matlab has a built-in feval.

Integral of a Recursive Function in MATLAB

I want to compute the following symbolic integral which is recursive :
function [y] = myfunc(i,T)
s = sym('s');
x= sym('x');
h=[....] %matrix n*n (function of x)
d=[....] %matrix n*1 (constants)
for k=1:n
if (T>0)
y= int(exp(-s*x)*h(i,k)*myfunc(k,T-x/d(i)),'x',0,T);
end
end
I expected MATLAB, while computing the integral, calls myfunc(k,T-x/d(i)) for different values of 'x' from 0 to T. However, it returns error since myfunc would be called with symbolic value 'x' and not the real value. Indeed, it cannot determine if (T>0) expression is true or false.
I would be thankful if you can suggest how this recursive integral can be computed ?. Thanks
If you want to ensure that a different real value is used in each step of a recursive function, you can define a variable to account for how deep you are.
Suppose we call it depth, and on the top level it is equal to 1. Each time you go one step deeper you increase depth by 1.
Now, if you want to get a number corresponding to the right depth, you can just call it as y(depth).

How to go from a symbolic expression to a vector in MATLAB

I am working on a function that will generate polynomial interpolants for a given set of ordered pairs. You currently input the indexes of the node points in one vector, and the values of the function to be interpolated in a second vector. I then generate a symbolic expression for the Lagrange polynomial that interpolates that set of points. I would like to be able to go from this symbolic form to a vector form for comparison with test functions and such. That is, I have something that generates some polynomial P(x) in terms of some symbolic variable x. I would like to then sample this polynomial to a vector, and get values for the polynomial over (for example) linspace(-1,1,1000). If this is possible, how do I do it?
I guess I'll include the code that I have so far:
function l_poly = lpoly(x,f)
% Returns the polynomial interpolant as computed by lagrange's formula
syms a
n=size(x,2);
l_poly_vec = 1;
l_poly=0;
for k=1:n,
for l=1:n,
if (k ~= l)
l_poly_vec=l_poly_vec*(a-x(l))/(x(k)-x(l));
end
end
l_poly=l_poly+f(k)*l_poly_vec;
l_poly_vec = 1;
end
I plan on adding a third (or possibly fourth) input depending on how I can solve this issue. I'm guessing I would just need the length of the vector I want to sample to and the endpoints.
If I understand you correctly, you've constructed a Lagrange interpolating polynomial using the symbolic toolbox and now wish to evaluate it over a vector of values. One way to do this is to use the function sym2poly to extract the coefficients of the symbolic polynomial, and then use polyval to evaluate it. Alternatively, you could use matlabFunction to convert your symbolic expression into a regular Matlab function; or use subs to substitute in a numeric value for 'x'.
However, you would probably be better off avoiding the symbolic toolbox altogether and directly constructing the coefficients of the Lagrange interpolating polynomial, or, better yet, use a different interpolation scheme altogether. The function interp1 might be a good place to start.