Passing argument to inner function Matlab - matlab

So I'm trying to write a function for a triple integral which depends ultimately on variable q which is a final limit of integration, and also a variable b which helps parameterize the function. However, this code isn't working and I'm not entirely sure what to do. I think it probably involves doing something to pass down the value of b to the nested functions, but I'm pretty new at matlab, any help is appreciated.
function [r] = test1(q,u)
b = u;
r = quad(#(k)Inner(k),-0.5.*(1-b)-b-1,q);
function [w] = Inner(k)
w = zeros(1);
for i = 1 : length(k);
w(i) = quad(#(n)InnerIntegral(n,b).*unifpdf(k(i)-n,-1,1),0,k(i)-1,k(i)+1);
end;
function [y] = InnerIntegral(n)
y = zeros(1);
for i = 1 : length(n);
y(i) = quad(#(m)unifpdf(n(i)-m, -b, b).*unifpdf(m,-0.5.*b,0.5.*b), n(i)-b,n(i)+b);
end;
end
end
end

Look at the little orange tick marks on the right side of the editor. In my copy, hovering over one says "Outer loop index 'i' is set inside a child function."
I don't know what the inputs or expected outputs of this function should be, but you should try to avoid confusing MATLAB. It has weird scoping rules. Use a different variable in the second nested function, perhaps j instead of i.

Related

How to create a function that takes a matrix as an input?

I am new to MatLab.
Write a function that takes as input a matrix D ∈ R^(N×2), D_i = (x_i,y_i), and the period ω and returns a plot showing a fit of the data without noise.
I need help with creating the function that takes the input as a matrix and period ω. Here is what I have so far. Am I on the right track?
function F = fftfuntion(D, omega)
check = 0;
x = D(:,1);
y = D(;,2);
You are on track but there are 3 problems:
First: you are using p variable inside your function which is not defined there. If it is defined in your main code you have to insert it to this function by adding an input to your function as p and when the function is called you have to put p there. Your other solution is to set p as a global variable which is not recommended.
function F = fftfuntion(D, omega,p)
Second: you have said that you need omega as an input and you are changing it with omega = 2*pi which is not right.
Finally I don't see any output which I think that's because you are not still done with the function.
Good luck

Summation of N function handles in MATLAB

I have N functions in MATLAB and I can define them using strcat, num2str and eval in a for loop. So without defining by hand I am able to define N functions. Let N=4 and let them be given as follows:
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
Now I add these four functions and I can do this by hand as follows:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x));
Here I can do it by hand because I know that N=4. However, in general I never know how many functions I will have. For all cases I cannot write a new function.
Is there any way to do this automatically? I mean if I give N=6 I am expecting to see MATLAB giving me this:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x)+f5(x)+f6(x));
Whenever I give N=2 then I must have the function f, defined as follows:
f=#(x)(f1(x)+f2(x));
How can we do this?
First of all, you should read this answer that gives a series of reasons to avoid the use of eval. There are very few occasions where eval is necessary, in all other cases it just complicates things. In this case, you use to dynamically generate variable names, which is considered a very bad practice. As detailed in the linked answer and in further writings linked in that answer, dynamic variable names make the code harder to read, harder to maintain, and slower to execute in MATLAB.
So, instead of defining functions f1, f2, f3, ... fN, what you do is define functions f{1}, f{2}, f{3}, ... f{N}. That is, f is a cell array where each element is an anonymous function (or any other function handle).
For example, instead of
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
you do
N = 4;
a = [4.5, 3.4, 7.1, 2.1];
f = cell(N,1);
for ii=1:N
f{ii} = #(x) a(ii) * x + 1;
end
With these changes, we can easily answer the question. We can now write a function that outputs the sum of the functions in f:
function y = sum_of_functions(f,x)
y = 0;
for ii=1:numel(f)
y = y + f{ii}(x);
end
end
You can put this in a file called sum_of_functions.m, or you can put it at the end of your function file or script file, it doesn't matter. Now, in your code, when you want to evaluate y = f1(x) + f2(x) + f3(x)..., what you write is y = sum_of_functions(f,x).

MATLAB: Slow Read-in of constant variables in Script Function

In the latest MATLAB release, I am using the feature of local functions in the script to simplify and shorten the code.
Right now I have a simple script that does mathematical calculations, up to millions of iterations in a for loop. From the loop, I extracted the mathematical part as it is used in multiple independent loops. However, I have the problem with speed and constant variables that need to be in the function. If I write the code without the local function, it is fast, but in the case of using the function, it is 10x slower.
I think it is due to the repetitive read-in of variables in the function. If the read-in happens from a file, it takes forever. The best I have achieved is by using evalin function to call in variables from the base workspace. It works, but as I mentioned, it is 10x slower than without a separate local function.
How to overcome this?
The structure looks like this:
load('Data.mat'); r=1; %Reads variables L,n
for Lx = L1:Ld:L2
for x = x1:d:x2
Yx(r) = myF(x); r=r+1
end
end
%A few more different loops...
function y = myF(x)
L = evalin('base','L');
n = evalin('base','n');
...
a = (x-L)^2; b = sin(a)-n/2; ... y=b*a/L;
end
You will want to explicitly pass the variables as additional input arguments to myF so that you don't have to load them every time. This way you don't have to worry about calling evalin or loading them from the file every iteration through the loop.
load('Data.mat'); r=1; %Reads variables L,n
for Lx = L1:Ld:L2
for x = x1:d:x2
Yx(r) = myF(x, L, n); r=r+1
end
end
function y = myF(x, L, n)
a = (x-L)^2; b = sin(a)-n/2;
y=b*a/L;
end
If for some reason you can't modify myF, just turn the entire thing into a function and make myF a subfunction and it will therefore automatically have access to any variable within the parent function. In this case you'll also want to assign the output of load to a variable to prevent strange behavior and not have issues with adding a variable to a static workspace
function myfunction()
data = load('Data.mat');
L = data.L;
n = data.n;
for Lx = L1:Ld:L2
for x = x1:d:x2
Yx(r) = myF(x);
r=r+1
end
end
function y = myF(x)
a = (x-L)^2; b = sin(a)-n/2;
y=b*a/L;
end
end
A third alternative is to take a hard look at myF and consider whether you can vectorize the contents so that you don't actually have to continuously call it millions of times.
You could vectorize it by doing something like
[Lx, x] = ndgrid(L1:Ld:L2, x1:d:x2);
a = (x - L).^2;
b = sin(a) - (n / 2);
Yx = (b .* a) ./ L;

Passing in an function to solve integral equation with fsolve

I am trying to solve an integral equation of the form
Integrate[f(x)*g(x,w),dx]
Solve for w: ------------------------ = 0.5
Integrate[f(x),dx]
of which there are definite limits (numerical integration).
Searching around on this and mathworks website I found some code that does it using functions in functions. I have run into a few problems though:
The code currently is (simplified equations for testing):
function [bfound]=testingSolveIntegral
options = optimset('MaxFunEvals',50);
bfound = fsolve(#func2minimize,[1 2 3],options); %testing start points at 1,2,3
function output = func2minimize(w)
t0 = -1;
t1 = 1;
L = 0.5;
output = (L - (integral(#myFunc,t0,t1,'ArrayValued',true,'RelTol',1e-30,'AbsTol',1e-30)./integral(#myFunc2,t0,t1,'ArrayValued',true,'RelTol',1e-30,'AbsTol',1e-30)));
function f = myFunc(muu)
f = B.*muu.^2*(w.*muu.^2);
end
function f2 = myFunc2(muu)
f2 = B.*muu^2;
end
end
end
This works wonderfully, but what I would like to do is then solve these equations in a loop for different values of B, eg, B = 1:1:100. I have tried a few things inside this code but only get errors.
Do I need to call this function from an outside script which dictates the B loop?
I would also like to define my functions in this outside script eg something like:
func = #(muu) B.*muu.^2*(w.*muu.^2);
func2 = #(muu) B.*muu^2;
for B = 1:1:100
testingSolveIntegral(func,func2,B)
I have tried a few things but am getting lost in the torrent of functions flying around the place. Assistance on how to set up such a script would be greatly appreciated.
Thanks
The integral doc page tells you how to perfom this task (section "Integrate Parametrized Function").
First define functions f and g with as many arguments as you have parameters/variables. For example, define:
g = #(muu,w) muu.^2*(w.*muu.^2);
f = #(muu) muu.^2;
Then call integral with an anonymous function which fix the values of the parameters:
for w=1:100
q(w) = integral(#(x) g(x,w).*f(x),bmin, bmax)./integral(f,bmin, bmax);
end

MATLAB's legendre function returns an array

I am working with an equation from a book and it works when I used Mathematica to solve it. It essentially contains the integral of certain orders of Legendre polynomials. E.g. P_1(x), P_2(x), P_3(x).
When I use Mathematica for a particular case e.g.
LegendreP[3, 0.5]
I get
-0.4375
which allows me to continue with my evaluation. But in MATLAB I get:
>> legendre(3,0.5)
ans =
-0.4375
-0.3248
5.6250
-9.7428
The first returned value is always correct but then it spits out... I think the other coefficients? So what I would like to do is tell MATLAB just to return the first value. Is there a way to do this without assigning it to its own variable afterwards? Eg. something like
legendre(3,0.5)(1)
Obviously wont work because it doesn't exist in memory yet. Am I even going about this the right way?
Thanks
If it bothers you, just put legendre into a new function legendre1, so you're using the library function, but with your desired functionality.
function [ P ] = legendre1( n,X )
P = legendre(n,X);
P = P(1);
end
or implement a custom range:
function [ P ] = legendre1( n,X,range )
P = legendre(n,X);
P = P(range);
end
so legendre1( 3,0.5,1 ) will return:
P =
-0.4375
and legendre1( 3,0.5,1:2 )
P =
-0.4375
-0.3248