MATLAB: Using FZERO on a function which has a vector output - matlab

I am working on my thesis and running in some programming problems in Matlab. I am trying to implement the ''golden Bisection Method'' to speed up my code. To this end, I've consulted the build in function FZERO.
So I am determining the difference between two vectors which are both (1x20).
Difference = Clmax_dist-cl_vec;
Clmax_dist comes from a semi-empirical method and cl_vec comes from the excecution of an external AVL.exe file.
Essentially, this difference depends only on one single variable AOA because the Clmax_dist vector is a constant. Hence, I am constantly feeding a new AOA value to the AVL.exe to obtain a new cl_vec and compare this again to the constant Clmax_dist.
I am iterating this until one of the element in the vector becomes either zero or negative. My loop stops and reveals the final AOA. This is a time consuming method and I wanted to use FZERO to speed this up.
However, the FZERO documentation reveals that it only works on function which has a scalar as input. Hence, my question is: How can I use FZERO with a function which has a vector as an output. Or do i need to do something totally different?
I've tried the following:
[Difference] = obj.DATCOMSPANLOADING(AOA);
fun=#obj.DATCOMSPANLOADING;
AOA_init = [1 20];
AOA_root = fzero(fun,AOA_init,'iter');
this gave me the following error:
Operands to the || and && operators must be convertible to logical scalar values.
Error in fzero (line 423)
while fb ~= 0 && a ~= b
Error in CleanCLmax/run (line 11)
AOA_root = fzero(fun,AOA_init,'iter');
Error in InitiatorController/moduleRunner (line 11)
ModuleHandle.run;
Error in InitiatorController/runModule (line 95)
obj.moduleRunner(ModuleHandle);
Error in RunSteps (line 7)
C.runModule('CleanCLmax');
The DATCOMSPANDLOADING function contains the following:
function [Difference] = DATCOMSPANLOADING(obj,AOA)
[Input]= obj.CLmaxInput; % Creates Input structure and airfoil list
obj.writeAirfoils(Input); % Creates airfoil coordinate files in AVL directory
[Clmax_dist,YClmax,Cla_mainsections] = obj.Clmax_spanwise(Input); % Creates spanwise section CLmax with ESDU method
[CLa] = obj.WingLiftCurveSlope(Input,Cla_mainsections); % Wing lift curve slope
[Yle_wing,cl_vec] = obj.AVLspanloading(Input,CLa,AOA); % Creates spanloading with AVL
Difference = Clmax_dist-cl_vec;
end
If I need to elaborate further, feel free to ask. And of course, Thank you very much.

fzero indeed only works on scalars. However, you can turn your criterion into a scalar: You are interested in AOA where any of the elements in the vector becomes zero, in which case you rewrite your objective function to return two output arguments: minDifference, which is min(Difference), and Difference. The first output, minDifference is the minimum of the difference, i.e. what fzero should try to optimize (from your question, I'm assuming all values start positive). The second output you'd use to inspect your difference vector in the end.

Related

Receiving unknown errors when trying to use fsolve to find the solutions of a function

I have to plot the solution for masses between 4 and 8kg, which I wrote using the code below:
weight=linspace(4,8,100)
Then I use a for loop to find the solutions for the weights within this vector, while also declaring the variable a, and a guess of the time required:
for z=1:length(weight)
a=(weight./(1360*pi)).^(1/3)
tguess=14400
timeinseconds=fsolve(#(t)cookingtimes(t,a),tguess)
timeinhours=timeinseconds/(60*60)
end
The function that I mentioned previously is below:
function F=cookingtimes(t,a)
k=1:22;
alpha=0.7*10^(-7);
F(1)=(2./(pi*0.464))*sum(((-1).^(k-1))./k).*sin(k*pi*0.464).*exp(((-(k.^2)).*(pi.^2).*((alpha.*t))./(a.^2)))-57/80
end
Where F(1) represents the following equation 1, which will be equal to 57/80. Rather than adding until infinity, I chose the value of 22 as the equation converges to this value. r/a is equal to 0.464, which is why this is present within my function.
When running this code, I am given errors that I cant manage to solve.
Arrays have incompatible sizes for this operation.
Error in Homework1>cookingtimes (line 58)
F(1)=(2./(pi*0.464))*sum(((-1).^(k-1))./k).*sin(k*pi*0.464).*exp(((-(k.^2)).*(pi.^2).*.((alpha.*t))./(a.^2)))-57/80
Error in Homework1 (line 28)
timeinseconds=fsolve(#(t)cookingtimes(t,a),tguess)
Error in fsolve (line 264)
fuser = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.
The arrays that I have produced are all of the same length, which is why I am very stuck on this issue.
You are trying to perform an operation on two arrays that have different sizes. In your case, the issue may be caused by the fact that you are defining the variable a as a vector inside the for loop, but using it in the function cookingtimes as a scalar. To fix this, you can modify your function to accept a vector of a values and return a corresponding vector of function values.
I modified the cookingtimes function to accept a vector of a values, and return a corresponding vector of function values.
function F=cookingtimes(t,a)
k=1:22;
alpha=0.7*10^(-7);
F=(2./(pi*0.464))*sum(((-1).^(k-1))./k).*sin(k*pi*0.464).*exp(((-(k.^2)).* (pi.^2).*((alpha.*t))./(a.^2)))-57/80;
end
In the for loop, You need to compute a for each weight value, and use a vector of a values in the call to fsolve. Also store the solutions in a vector timeinseconds instead of a scalar, as there are multiple solutions to be found.
for z=1:length(weight)
a=(weight(z)./(1360*pi)).^(1/3); % compute a for each weight value
tguess=14400;
timeinseconds(z)=fsolve(#(t)cookingtimes(t,a),tguess);
timeinhours=timeinseconds/(60*60);
end

Numerically solve a gamma parameter estimation

I am trying to numerically solve an equation using fzero in Matlab. It is part of a bigger exercise. I haven't posted much here so not sure how much background information you need about this exercise so will try to keep it short.
This is my code:
fun = #(a)log(a/xBar) + (1/n) * log(dataProd) + diff(gamma(a))/gamma(a);
x0 = 0.8014;
x = fzero(fun,x0)
These are the values:
n = 209
xBar is 0.6078
dataProd = 3.1554e-77
I get the following error message in Matlab:
Operands to the || and && operators must be convertible to logical
scalar values.
Error in fzero (line 306)
elseif ~isfinite(fx) || ~isreal(fx)
Any idea why I get this error message?
I would guess that, during the search for a solution, fzero tries to evaluate your function at a=0, leading to an infinity. To check if this is the case, either look and see if you can set the optimization parameter 'display' to 'iter', or something similar in your version of Matlab. Otherwise, you can simply move your function to a separate m-file and call disp(a) on the first line. That way you will be able to see what fzero is doing and which value of a is causing the problem.

While loop error with Netwon-Raphson Method

I am trying to find use to Newton-Raphson method to find the roots. It does this by making a guess and then improving the guess after each iteration until you get one of the zeros.
Because the Newton-Raphson method quickly finds the zeros, it gives me a small error immediately and after two or three iterations max it should fail to meet the conditions of the while loop. However, the problem is that when I remove the semi-colon after "error" in my loop, I start getting fractions that should break the while loop, but its like Matlab doesn't know that 123/8328423 is less than 1. It continues to run until I manually force the program to stop running.
How do I fix this? I tried format long, format longe, and using double both in the command window, in the scrip file, and somewhere in the loop.
Thank you in advance for any tips, suggestions, or advice that may help!!
A = [1,2,-4;2,-2,-2;-4,-2,1;];
format longe
% syms x y z
% P = x^4 + 3*x^2*y^2-z^3+y+1;
% feval(symengine,'degree',P,x)
syms x
B = mateigenvalue(A);
f(x) = simplify(matdet(B));
x0 = 1;
error = 10;
while(error > .01)
x1 = x0 - f(x0)/(27*(x0)-3*(x0)^2);
error = abs(((f(x0)-f(x1))/f(x0))*100)
x0 = x1;
end
x0 = double(x0)
I reckon the main problem is with error.
It starts as double but inside the while-loop it turns into a symbolic variable and you can't easily compare symbolic variables with scalar values (the .01 in the while-loop condition).
Check in your workspace if error is symbolic (or type class(error) and check if sym is returned). I guess it is symbolic because a fraction is returned (123/8328423), as instead Matlab treats double values with decimals, not fractions.
If so, try doing (inside the while-loop) a conversion for error that is, under the line
error = abs(((f(x0)-f(x1))/f(x0))*100);
try putting
error=double(error);
So error will be temporarily converted in double and you can easily compare its value with .01 to check the while-loop condition.
Also, it is bad practice to call a variable error since error() is a built-in function in Matlab. By naming a variable error you cannot use the error() function. Same story goes for other built-in functions.

Matlab Running a parameterized fminsearch in a for loop?

Essentially I want to have fminsearch run over a variety or parameters.
So I have the following snipet of code running:
%Setting up the changeable WIRX parameters:
L = 0.15; %Length along the electrodes in meters
I = 3000; %Current in amps
%Running the fminsearch:
TeNe = fminsearch(#(params) TeNe(params,L,I),[5,1.5e21],optimset('MaxFunEvals', 100000,'MaxIter', 100000));
What I want to do is be able to run this in a for loop with an array of values for L and I. However what i noticed is that I cannot even run this piece of code twice in a row with out getting the error:
Subscript indices must either be real positive integers or logicals.
Any insight would be much appreciated!
I assume that TeNe is a function which you call with the following inputs: (params,L,I).
However, the output of fminsearch is also assigned to TeNe.
That is why, after the first loop iteration you get the error you see. L has been set to 0.15, however, this makes no sense as an index to an array called TeNe - which you end up with after running fminsearch.
Consider changing the name of the output variable.

What is a good substitute for matlabFunction?

I wrote a small program in MATLAB to compute the Shapley value
using the multi-linear extension of a TU game. However, I run
into trouble with the Symbolic Math Toolbox of MATLAB. In
the program I have to integrate a set of functions to get the
Shapley value. However, inside a MATLAB program I cannot use
the int() command
Error using sym/subsindex (line 663) Ivalid indexing or function definition. When defining a function, ensure that the body of the function is a SYM object. When indexing, the input must be numeric, logical or ':'.
Error in ShapleyValueML (line 65)shv(jj)=int(dfy,0,1)
as a consequence I have to use integral() instead. In this case, I
need to transcribe the set of expressions into MATLAB function handle
with matlabFunction(). However, on all Linux machines (MATLAB R2014a) on
which I have access this command does not work (see the discussion below).
As a workaround, the MATLAB program returns the set of functions
into the current workspace, there the Shapley value can be computed
using the int() command.
To make the discussion more concrete, let us consider this small
MATLAB program first.
function [shv,F,dfm]=ShapleyValueML(v)
N=length(v);
[~, n]=log2(N);
S=1:N;
int=0:-1:1-n;
mat=(rem(floor(S(:)*pow2(int)),2)==1);
cmat=(rem(floor(S(:)*pow2(int)),2)==0);
x=sym('x',[1 n]);
mx=1-x;
y = sym('y');
vy=ones(1,n)*y;
F=0;
shv=zeros(1,n);
dfm=cell(1,n);
for ss=1:N
pd1=x(mat(ss,:));
pd2=mx(cmat(ss,:));
pd=prod(pd1)*prod(pd2)*v(ss);
F=pd+F;
end
F=expand(F);
for jj=1:n
dF=diff(F,x(jj));
dfy=subs(dF,x,vy);
%% Does not work!! MATLAB bug???
% mf=matlabFunction(dfy);
% shv(jj)=integral(mf,0,1);
%%
%% The best would be to use:
%%
% shv(jj)=int(dfy,0,1)
%% but it cannot be used inside a program.
dfm{jj}=dfy;
end
end
The commented parts are the parts that do not work inside
the program, but are needed to compute the Shapley value
with that program, which is its purpose. I tested this program
up to 12 players, and I was able to successfully calculate the
Shapley value by a two step procedure. Hence, the above program
specifies correctly the considered problem. To get a better
understanding of this two step procedure and of the functionality
of the above program, let us focus on a three person game.
The values of the coalitions are given by the following data array
>> v = [0,0,90,0,100,120,220];
Notice that coalitions are ordered in accordance with their unique
integer representations. The game is defined, we can now evaluate
the multi-linear extension and the set of partial derivatives with
the above program, but not the Shapley value.
>> [shv,F,dfm]=ShapleyValueML(v);
Integration of the set of partial derivatives runs over the diagonal
of the unit-cube, but then we can set the variables from [x1,x2,x3]
to [y,y,y], and integration runs from 0 to 1.
>> for k=1:3, shv(k)=int(dfm{k},0,1);end;
The solution of the integration is the Shapley value given by:
>> shv
shv =
65 75 80
Checking that this is indeed the Shapley value can be accomplished
with a potential function approach implemented in
>> sh_v=ShapleyValue(v)
sh_v =
65 75 80
that ships with my MATLAB Game Theory Toolbox MatTuGames from
http://www.mathworks.com/matlabcentral/fileexchange/35933-mattugames
Instead of integrating with int() one can also use integral(),
but then the contents like
>> dfm{1}
ans =
- 90*y^2 + 190*y
must be rewritten with matlabFunction() into a function handle. As I
have mentioned above this does not work under Linux
(MATLAB R2013a,R2013b,R2014a). To see this let us try to reproduce
the example
>> syms x y
>> r = sqrt(x^2 + y^2);
from the documentation at the URL:
http://www.mathworks.de/de/help/symbolic/generate-matlab-functions.html?searchHighlight=matlabFunction
This should give
ht =
#(x,y)tanh(sqrt(x.^2+y.^2))
but I get
>> ht = matlabFunction(tanh(r))
Cell contents reference from a non-cell array object.
Error in vectorize (line 15)
c = cells{i};
Error in sym/matlabFunction>mup2mat (line 319)
res = vectorize(res(2:end-1)); % remove quotes
Error in sym/matlabFunction>mup2matcell (line 304)
r = mup2mat(c{1});
Error in sym/matlabFunction (line 123)
body = mup2matcell(funs);
Here comes now my question: Exists there an alternative procedure to
get from
>> dfm{1}
ans =
- 90*y^2 + 190*y
a function handle
>> df=#(y) (- 90.*y.^2 + 190.*y)
df =
#(y)(-90.*y.^2+190.*y)
to integrate it by
>> integral(df,0,1)
ans =
65
Or to put it differently. Is there an alternative method available to
change multiplication * to element-wise multiplication .*, and the
power operation ^ to element-wise power.^?
Of course, any suggestions of improvement for the above MATLAB program
are highly appreciated.
I think I know what the problem is; Towards the beginning of ShapleyValueML function, you have a variable named int which shadows the builtin integration function:
...
int=0:-1:1-n; %# <-- problem!
...
shv(jj)=int(dfy,0,1)
...
That explains the error coming from sym/subsindex, you were using a symbolic object as an index into the numeric array int.
Change the variable name to something else, and the commented code runs fine (the symbolic integration)! Simple as that :)