I am trying to automatize a process in MATLAB. I have a symbolic function that has to be converted into an anonymous function.
Basically, I have something like this:
syms x y z t
var = [x y z t];
f = x.^2+y;
gf = gradient(f, var);
gf_fun = matlabFunction(gf, 'vars', {var});
giving as output
gf_fun =
function_handle with value:
#(in1)[in1(:,1).*2.0;1.0;0.0;0.0]
Now, I'd like to evaluate this gf_fun in several points at a time, but, of course, I got strange results, due to how gf_fun is written. For example, if I want to evaluate gf_fun in 6 (different) points simultaneously, what I get is
rng('deafult')
vv = ones(6,4);
gf_fun(vv)
ans =
1.3575
1.5155
1.4863
0.7845
1.3110
0.3424
1.0000
0
0
instead of a matrix with dimensions 4x6, with each colomn being the evaluation of a single point.
I know that a workaround will be the use of a for loop, that is
results = zeros(4,6);
for i = 1:6
results(:,i) = gf_fun(vv(i,:));
end
but I must avoid it due to code performances reasons.
Is there a way to automatize all the process, having a matrix as output of gf_fun while evaluating different point at a time? So, basically, there is a simple way to replace the 0.0 and 1.0 in gf_fun with a more general zeros(size(in1)) and ones(size(in1)) automatically?
Thank you for you help!
Related
I am working on an assignment that requires me to use the trapz function in MATLAB in order to evaluate an integral. I believe I have written the code correctly, but the program returns answers that are wildly incorrect. I am attempting to find the integral of e^(-x^2) from 0 to 1.
x = linspace(0,1,2000);
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = e.^(-(x(iCnt)^2));
end
a = trapz(y);
disp(a);
This code currently returns
1.4929e+03
What am I doing incorrectly?
You need to just specify also the x values:
x = linspace(0,1,2000);
y = exp(-x.^2);
a = trapz(x,y)
a =
0.7468
More details:
First of all, in MATLAB you can use vectors to avoid for-loops for performing operation on arrays (vectors). So the whole four lines of code
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = exp(-(x(iCnt)^2));
end
will be translated to one line:
y = exp(-x.^2)
You defined x = linspace(0,1,2000) it means that you need to calculate the integral of the given function in range [0 1]. So there is a mistake in the way you calculate y which returns it to be in range [1 2000] and that is why you got the big number as the result.
In addition, in MATLAB you should use exp there is not function as e in MATLAB.
Also, if you plot the function in the range, you will see that the result makes sense because the whole page has an area of 1x1.
I'm having trouble with implementing double integral in Matlab.
Unlike other double integrals, I need the result of the first (inside) integral to be an expression of the second variable, before going through the second (outside) integral, as it must be powered by k.
For example:
In the example above, I need the result of the inside integral to be expressed as 2y, so that I can calculate (2y)^k, before doing the second (outside) integral.
Does anyone know how to do this in Matlab?
I don't like doing things symbolically, because 99.9% of all problems don't have a closed form solution at all. For 99.9% of the problems that do have a closed-form solution, that solution is unwieldy and hardly useful at all. That may be because of my specific discipline, but I'm going to assume that your problem falls in one of those 99.9% sets, so I'll present the most obvious numerical way to do this.
And that is, integrate a function which calls integral itself:
function dbl_int()
f = #(x,y) 2.*x.*y + 1;
k = 1;
x_limits = [0 1];
y_limits = [1 2];
val = integral(#(y) integrand(f, y, k, x_limits), ...
y_limits(1), y_limits(2));
end
function val = integrand(f, y, k, x_limits)
val = zeros(size(y));
for ii = 1:numel(y)
val(ii) = integral(#(x) f(x,y(ii)), ...
x_limits(1), x_limits(2));
end
val = val.^k;
end
When defining a function, say TEST = #(t) t.^2. If the input is a vector, say [1,2,3,4], TEST([1,2,3,4]) = [1,4,9,16].
Can we do similar thing if the function defined is in script form? What I mean is that if I have a script, say TEST.m such that ret = TEST(x,y,z) which outputs a value when knowing numerical values of x, y and z. Suppose I want to calculate 100 different values of z ranging from 1 to 100 when x, y are fixed, say at 0, 1 respectively. Is it possible to output TEST(0,1,1:1:100) without writing a for loop or changing any contents of the script TEST.m?
The reason to ask such question comes from the computation time. Usually, the script I have may be a little complicated so that the calculate of a single value may take few minutes to go. Writing for-loop to output it can be very time-consuming. I think of writing parfor loop, but the computation time is still long to me for further uses. I wonder if I can calculate all the 100 values at a time. I am a starter of programmer, and I hope I can get satisfactory answers after this post. Thanks for all your help.
You cab define a new anonymous function to get the fixed values as parameters, and the vector as input. Then use arrayfun to compute it on all values of the array.
Say you have this functions:
function ret = TEST(x,y,z)
ret = f(x)+g(y)+h(z);
end
function r = f(x)
r = x^2;
end
function r = g(y)
r = y^3;
end
function r = h(z)
r = z^4;
end
And you call it from:
x = 2;
y = 3;
z = 1:5;
T = #(z) TEST(x,y,z);
arrayfun(T,z)
So T is a new function that treat x and y as constants, and only have z as input. Then arrayfun takes T and compute it for every element in z, and you get:
ans =
32 47 112 287 656
Now, you can use arrayfun with more vectors, like [a,b,c] = arrayfun(T,z,w,v), if x and y can stay constant.
Hopes it answers your question ;)
folks,
I am wondering if it is possible to write the following function of r as an inline function in matlab. I tried to include the condition as a separate factor such as *(r>a) and I got NaN due to the division of 1/r^3 when r is 0.
I fould a simple way out. It's basically what Shai and Jigg suggested, i.e. using an extra multiplicative factor of (r>a).
To get rid of NaN, we just need to add eps to the denominator of 1/r3, i.e.
1/(r+eps)^3 *(r>a)
First, you haven't stated what should actually happen if r = 0. Mathematically the term gets infinity. I assumed you rather want to set it to zero. And what should happen for r = a? Just another ill-defined case, are you sure your formula is correct?
If you have the Statistics Toolbox you can use nansum. If not, I'd say there is no way around to write your own function similar to nansum, which can't be done inline.
r = -5:1:5;
a = 1;
R = 42; %// rest of your function
%// not working, or removing of nan afterwards required
X = #( r ) (r>=a).*(a./r).^3*R;
%// inline solution with statistics toolbox
Y = #( r ) arrayfun(#(x) nansum( (x>=a)*(a/x)^3*R ), r);
output = [X(r)' Y(r)']
nansum is not vectorized, if you still want to use it for vectors wrap it into arrayfun.
The code of nansum does exactly what was suggested in the comments (output(isnan(output))=0), I'm probably not allowed to copy&paste it here. It filters out all NaN and then sums the input. Use open nansum to have insight.
As pointed out by Jigg, similar functions like nanmean would do the trick as well.
You can try
chi = 1; %// arbitrary value
a = 1; %// arbitrary value
theta = pi/3; %// arbitrary value
nu = #( r ) (r>a).*( (chi/3).*((a.^3)./(r.^3)).*(3*cos(theta).^2 -1);
We have an equation similar to the Fredholm integral equation of second kind.
To solve this equation we have been given an iterative solution that is guaranteed to converge for our specific equation. Now our only problem consists in implementing this iterative prodedure in MATLAB.
For now, the problematic part of our code looks like this:
function delta = delta(x,a,P,H,E,c,c0,w)
delt = #(x)delta_a(x,a,P,H,E,c0,w);
for i=1:500
delt = #(x)delt(x) - 1/E.*integral(#(xi)((c(1)-c(2)*delt(xi))*ms(xi,x,a,P,H,w)),0,a-0.001);
end
delta=delt;
end
delta_a is a function of x, and represent the initial value of the iteration. ms is a function of x and xi.
As you might see we want delt to depend on both x (before the integral) and xi (inside of the integral) in the iteration. Unfortunately this way of writing the code (with the function handle) does not give us a numerical value, as we wish. We can't either write delt as two different functions, one of x and one of xi, since xi is not defined (until integral defines it). So, how can we make sure that delt depends on xi inside of the integral, and still get a numerical value out of the iteration?
Do any of you have any suggestions to how we might solve this?
Using numerical integration
Explanation of the input parameters: x is a vector of numerical values, all the rest are constants. A problem with my code is that the input parameter x is not being used (I guess this means that x is being treated as a symbol).
It looks like you can do a nesting of anonymous functions in MATLAB:
f =
#(x)2*x
>> ff = #(x) f(f(x))
ff =
#(x)f(f(x))
>> ff(2)
ans =
8
>> f = ff;
>> f(2)
ans =
8
Also it is possible to rebind the pointers to the functions.
Thus, you can set up your iteration like
delta_old = #(x) delta_a(x)
for i=1:500
delta_new = #(x) delta_old(x) - integral(#(xi),delta_old(xi))
delta_old = delta_new
end
plus the inclusion of your parameters...
You may want to consider to solve a discretized version of your problem.
Let K be the matrix which discretizes your Fredholm kernel k(t,s), e.g.
K(i,j) = int_a^b K(x_i, s) l_j(s) ds
where l_j(s) is, for instance, the j-th lagrange interpolant associated to the interpolation nodes (x_i) = x_1,x_2,...,x_n.
Then, solving your Picard iterations is as simple as doing
phi_n+1 = f + K*phi_n
i.e.
for i = 1:N
phi = f + K*phi
end
where phi_n and f are the nodal values of phi and f on the (x_i).