Matlab integral function & function handles in a loop - matlab

'Outliers.m' is called from a higher level .m file. The variables are all defined in the higher level file, and set as globals for access by Outliers.m. The purpose of the code is to identify outliers using Chauvenets Criterion, and for this, I have to calculate the integral of the guassian distribution, using the Integral function and function handles. The code works and gives sensible values when I enter specific variables as a test, but I cannot get it to work in a loop. My data set is comprised of 7 individual samples, each 1x30, all of which need to be analyzed. I have had various errors, read through the guidance on Integral and function handles, but cannot seem to find the solution...Any help or guidance would be very much appreciated.... Here is my code:
n = 7
for x = 1:n
for y = 1:30
z(x,y) = abs((cc(x,y) - mastercc(1,y))/masterccstd(1,y));
xmax(x,y) = mastercc(1,y)+z(x,y)*masterccstd(1,y);
xmin(x,y) = mastercc(1,y)-z(x,y)*masterccstd(1,y);
p(x,y) = 1/(masterccstd(1,y)*(sqrt(2*pi)));
fun(x,y)= #(x,y,z) (exp(-1/2)*z(x,y).^2);
q(x,y) = integral(fun(x,y),xmin(x,y),xmax(x,y),'ArrayValued',true);
pq(x,y) = p(x,y)*q(x,y); % probability
value(x,y) = n*(1/pq(x,y));
count(x,y) = logical(value(x,y) <0.5);
badbins(x)=sum(count(x,:));
end
end

It seems like your error is caused by an invald function definition.
If you try it like this it should work:
fun = #(x,y,z) (exp(-1/2)*z(x,y).^2)
Now it can be called like this for example:
fun(1,2,magic(4))

Solution to the loop problem, courtesy Andrei Bobrov via Matlab Central, link below:
http://www.mathworks.com/matlabcentral/answers/103958#comment_177000
NB: Please note the code is not complete for the purpose I explained in the problem description, but it does solve the Loop error.

Related

Assign many values of "solve" structure to matrix: MATLAB

I am trying to solve a large system of linear equations in matlab (about 3600 equations!) Since the number of variables is too many, I have to define them in a matrix. So I use this code to define the variables:
A = sym('A',[60,60]);
It has to be a 60x60 matrix because the variables correspond to a finite difference problem (i.e. a mesh grid).
After writing the corresponding equations in a for loop, I use the solve function in this way:
mysol = solve(eq,A);
Where eq is the equations matrix.
My problem is that, when I try to solve this system as shown in MATLAB help, i.e. writing something like this:
C(1,1) = mysol.A(1,1)
I get an error that says: "Reference to non-existent field 'A'". But if I write something like:
C(1,1) = mysol.A1_1
then it works.
Does anyone know how I can fix this? I don't want to do this for every variable!
You could try accessing the fields in the structure dynamically like so:
for ii = 1:60
for jj = 1:60
field = sprintf('A%d_%d', ii, jj);
C(ii, jj) = mysol.(field);
end
end

Is it possible to use use `parfor` for parallel computing in Matlab in these codes?

I am using parfor for parallel computing in Matlab. I am not familiar with this command. If that is possible, please look at my code below and tell me if I can write it with parfor.
These errors and warnings are appear in Matlab Editor:
The parfor loop cannot be run due to the way variable Dat is used. (when I comment line Dat.normXpj = normXpj(pj,:); This error is solved and other errors similar to the following error is appeared.
The entire array or structure Bound is broadcast variable. This
might result in unnecessary communication overhead.
parfor pj = 1:size(normXpj,1)
Dat.normXpj = normXpj(pj,:);
if size(Dat.InitialGuess)==0
X = (Bound(:,1)+(Bound(:,2)-Bound(:,1)).*rand(Nvar,1))';
else
X = Dat.InitialGuess;
end
[Xsqp, ~, FLAG,Options] = mopOPT(X,Dat);
FEVALS = Options.funcCount;
FES = FES+FEVALS;
PSet(pj,:) = Xsqp;
PFront(pj,:) = mop(Xsqp,Dat,0);
if FLAG==-2
disp('.......... Algo paso...');
else
F = PFront(pj,:);
if Nobj==2
plot(F(1,1),F(1,2),'*r'); grid on; hold on;
elseif Nobj==3
end
end
end
The problem here is that it we can see that you're not using Dat in a way that is order-dependent, but the static analysis machinery of parfor cannot deduce that because of the way you're assigning into it. I think you can work around this by instead creating a whole new Dat for each iteration of the loop, like so:
Dat = struct('normXpj', rand(10,1), 'InitialGuess', 3);
normXpj = rand(10);
parfor idx = 1:10
tmpDat = struct('normXpj', normXpj(:,idx), 'InitialGuess', Dat.InitialGuess);
% use 'tmpDat'
disp(tmpDat);
end
The answer is no, unfortunately. At line:
Dat.normXpj = normXpj(pj,:);
you assign a value to Dat.normXpj, but you have to know that in a parfor loop there can be multiple iterations executing at the same time. So what value should be used for Dat.normXpj ? Matlab cannot decide, hence your error.
More generally, your code looks quite messy. I suppose you want to use parfor to increase execution speed. Probably a more efficient option would be to use the profiler (see profile) to detect the bottlenecks in your code, and apply a correction if that's possible.
Best,

MATLAB Using fzero - returns error

I'm trying to use the MATLAB function fzero properly but my program keeps returning an error message. This is my code (made up of two m-files):
friction_zero.m
function fric_zero = friction_zero(reynolds)
fric_zero = 0.25*power(log10(5.74/(power(reynolds,0.9))),-2);
flow.m
function f = flow(fric)
f = 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(power(10,4));
z = fzero(#flow,f_initial)
The goal is to return z as the root for the equation specified by f when flow.m is run.
I believe I have the correct syntax as I have spent a couple of hours online looking at examples. What happens is that it returns the following error message:
"Undefined function or variable 'fric'."
(Of course it's undefined, it's the variable I'm trying to solve!)
Can someone point out to me what I've done wrong? Thanks
EDIT
Thanks to all who helped! You have assisted me to eventually figure out my problem.
I had to add another file. Here is a full summary of the completed code with output.
friction_zero.m
function fric_zero = friction_zero(re)
fric_zero = 0.25*power(log10(5.74/(power(re,0.9))),-2); %starting value for fric
flow.m
function z = flow(fric)
re = power(10,4);
z = 1/(sqrt(fric))-1.873*log10(re*sqrt(fric))-233/((re*sqrt(fric))^0.9)-0.2361;
flow2.m
f_initial = friction_zero(re); %arbitrary starting value (Reynolds)
x = #flow;
fric_root = fzero(x,f_initial)
This returns an output of:
fric_root = 0.0235
Which seems to be the correct answer (phew!)
I realised that (1) I didn't define reynolds (which is now just re) in the right place, and (2) I was trying to do too much and thus skipped out on the line x = #flow;, for some reason when I added the extra line in, MATLAB stopped complaining. Not sure why it wouldn't have just taken #flow straight into fzero().
Once again, thanks :)
You need to make sure that f is a function in your code. This is simply an expression with reynolds being a constant when it isn't defined. As such, wrap this as an anonymous function with fric as the input variable. Also, you need to make sure the output variable from your function is z, not f. Since you're solving for fric, you don't need to specify this as the input variable into flow. Also, you need to specify f as the input into fzero, not flow. flow is the name of your main function. In addition, reynolds in flow is not defined, so I'm going to assume that it's the same as what you specified to friction_zero. With these edits, try doing this:
function z = flow()
reynolds = power(10,4);
f = #(fric) 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(reynolds);
z = fzero(#f, f_initial); %// You're solving for `f`, not flow. flow is your function name
The reason that you have a problem is because flow is called without argument I think. You should read a little more about matlab functions. By the way, reynolds is not defined either.
I am afraid I cannot help you completely since I have not been doing fluid mechanics. However, I can tell you about functions.
A matlab function definition looks something like this:
function x0 = f(xGuess)
a = 2;
fcn =#(t) a*t.^3+t; % t must not be an input to f.
disp(fcn);
a = 3;
disp(fcn);
x0 = fsolve(fcn1,xGuess); % x0 is calculated here
The function can then ne called as myX0 = f(myGuess). When you define a matlab function with arguments and return values, you must tell matlab what to do with them. Matlab cannot guess that. In this function you tell matlab to use xGuess as an initial guess to fsolve, when solving the anonymous function fcn. Notice also that matlab does not assume that an undefined variable is an independent variable. You need to tell matlab that now I want to create an anonymous function fcn which have an independent variable t.
Observation 1: I use .^. This is since the function will take an argument an evaluate it and this argument can also be a vector. In this particulat case I want pointwise evaluation. This is not really necessary when using fsolve but it is good practice if f is not a matrix equation, since "vectorization" is often used in matlab.
Observation 2: notice that even if a changes its value the function does not change. This is since matlab passes the value of a variable when defining a function and not the variable itself. A c programmer would say that a variable is passed by its value and not by a pointer. This means that fcn is really defined as fcn = #(x) 2*t.^3+t;. Using the variable a is just a conveniance (constants can may also be complicated to find, but when found they are just a value).
Armed with this knowledge, you should be able to tackle the problem in front of you. Also, the recursive call to flow in your function will eventuallt cause a crash. When you write a function that calls itself like this you must have a stopping criterium, something to tell the program when to stop. As it is now, flow will call ifself in the last row, like z = fzero(#flow,f_initial) for 500 times and then crash. Alos it is possible as well to define functions with zero inputs:
function plancksConstant = h()
plancksConstant = 6.62606957e−34;
Where the call h or h() will return Plancks constant.
Good luck!

Function to find entries with same maximum value in a vector

In my project I need a function which returns the index of the largest element of a given vector. Just like max. For more than one entry with the same maximum value (which occurs frequently) the function should choose one randomly. Unlike max.
The function is a subfunction in a MATLAB Function Block in Simulink. And the whole Simulink model is compiled.
My basic idea was:
function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end
But I got problems with the comparison in find and with randi.
I found out about safe comparison here: Problem using the find function in MATLAB. Also I found a way to replace randi([1,imax],1): Implement 'randi' using 'rand' in MATLAB.
My Code now looks like this:
function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end
Still doesn't work. I understand that the length of index_max is unclear and causes problems. But I can not think of any way to know it before. Any ideas how to solve this?
Also, I'm shocked that ceil doesn't work when the code gets executed?? In debug mode there is no change to the input visible.
I thought about creating an array like: index_max = abs(vector - max(vector)) < tolerance; But not sure how that could help. Also, it doesn't solve my problem with the random selection.
Hopefully somebody has more ideas or at least could give me some hints!
I am using MATLAB R2012b (32bit) on a Windows7-64bit PC, with the Lcc-win32 C 2.4.1 compiler.
Edit:
Vector usually is of size 5x1 and contains values between -2000 and zero which are of type double, e.g. vector = [-1000 -1200 -1000 -1100 -1550]'. But I think such a simple function should work with any kind of input vector.
The call of length(index_max) causes an system error in MATLAB and forces me to shut it down. I guess this is due to the strange return I get from find. For a vector with all the same values the return from find is something like [1.000 2.000 1.000 2.000 0.000]' which doesn't make any sense to me at all.
function v= findOpt(v)
if isempty(v)
return;
end
v = find((max(v) - v) < 0.00001);
v = v(ceil(rand(1)*end));
end
I was indeed overloading, just like user664303 suggested! Since I can not use objects in my project, I wanted an function that behaves similar, so I wrote:
function varargout = table(mode, varargin)
persistent table;
if isempty(table) && ~strcmp(mode,'writeTable')
error(...)
end
switch mode
case 'getValue'
...
case 'writeTable'
table = ...
...
end
end
Wanted to avoid passing the dimensions for the table in every call and thought it would be enough if the first call initializes the Table with mode='writeTable'. Looks like this caused my problem.
No problems after changing to:
if isempty(table)
table = zeros(dim1,dim2,...)
end

How do I properly setup numerical integration in MATLAB?

I'm looking to integrate this expression:
However I seem to be having problems setting up the function. As outlined in this MATLAB explanation, I've defined a separate function named 'NDfx.m' which looks like this:
function [ y ] = NDfx(x)
y = (1/sqrt(2*pi))*exp(-.5*x^2); % Error occurs here
end
However when I call it within my main function I get an error at the commented line above. My main function looks like this:
function[P] = NormalDistro(u,o2,x)
delta = x-u;
dev = abs((delta)/o2); % Normalizes the parameters entered into function
P_inner = quad(#NDfx,-dev,dev); % Integrates function NDfx from -dev to dev (error here)
P_outer = 1 - P_inner; % Calculation of outer bounds of the integral
if delta > 0
P = P_inner + (P_outer/2);
elseif delta < 0
P = P_outer/2;
elseif dev == 0
P = .5;
end
end
The specific error that I get is:
Error in ==> mpower
Inputs must be a scalar and a square matrix
You've setup everything correctly for integration. The error is in the definition of the function itself. When using variables for function that will be integrated, a "." (period) must precede operators like ^ and * when they are applied to the variable:
function [y] = NDfx(x)
y = (1/sqrt(2*pi))*exp(-.5*(x.^2));
end
Krono and user57368 are correct. They have already correctly answered your actual question. My answer is merely to answer the question you did not ask. That is, why are you using quad here at all? The point is that many people want to integrate a function of that form, and it has been done already! Use existing tools to solve your problems, as those tools will often have been written by someone who knows how to solve the problem accurately and efficiently.
In this case, the existing tool is comprised of the functions erf and erfc. They provide an accurate, efficient, vectorized solution to your problem. The only thing you will need to do is figure out how to transform those integrals to your current problem, done by a simple scaling of the input to erf and the output.