How to use fminunc with summation in matlab? - matlab

I am trying to solve the following function with fminunc:
Σ((x(i)-1).^2) for i = 1 to 20
My code is below:
fun4 = #(x) sum((x(i)-1).^2, i, 1, 20)
[x,fval,exitflag,output]= fminunc(fun4,[1,1])
And, it gives the following error:
??? Error using ==> sym.sym>notimplemented at 2514
Function 'subsindex' is not implemented for MuPAD symbolic objects.
Could you help me, please?

You should check out the sum documentation for details about how to use it to sum over a vector.
In your case, if you have a vector x of at least 20 elements, you can get the subvector of "x(i) for i in the range 1 to 20" by x(1:20).
You can subtract scalars from a vector just by using the standard subtract sign, but to then square all of the elements individually you should use an "element-wise" operator (having a dot before the operator, like .^). As it happens, you were already doing this anyway.
The 2nd, 3rd and 4th arguments you were passing to sum are causing an error, because sum doesn't expect the arguments you are passing to it. For further details on the inputs it does expect see the linked docs.
All of this means your function can be simplified:
fun4 = #(x) sum((x(1:20)-1).^2);

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

min of row on Matlab GPU with arrayfun

I would like to find the index of the smallest value resulting from some computation, like the nearest value, using Matlab gpuArrays.
However, in the arrayfun scenario the min function doesn't seem to offer the functionality.
With the following code:
function grid_gpu_test
gridSize = 8;
grid = gpuArray(rand(gridSize));
all_c=1:gridSize; % because : is not supported
function X = min_diff(row)
X = min(abs(grid(row,all_c)-grid(row,1)))
end
rows = gpuArray.colon(2, gridSize)';
arrayfun(#min_diff, rows)
end
I get the following error:
Too few input arguments supplied to: 'min'. Error in 'grid_gpu_test' (line: 9)
Is there a way to achieve this? I know that using min(gpuArray) works normally when it's not in arrayfun, but I want to achieve this with an operation that doesn't simplify into matrix operations.
I'm a little confused by your question, because your code errors out when you try to run it on the CPU. By making rows go 2:(gridSize+1), then it exceeds the size of grid.
In any case, I think here rather than arrayfun, you want to use bsxfun (or implicit expansion if you have R2016b or later). Here's the bsxfun version.
grid = gpuArray.rand(8);
% I think what you're trying to compute is the difference
% between each column of "grid" compared to the first column
difference = bsxfun(#minus, grid(:,1), grid);
% To find the minimum difference, and its column, use
% the following form of MIN
[val, col] = min(difference, [], 2)
Here I'm using the "reduction" form of min, and I want to reduce across columns, so I need to pass in the 2 as the third argument. The second argument is [] to tell MATLAB that you want the "reduction" form of min, rather than the element-wise form of min. (Note that gpuArray/arrayfun supports only the element-wise form of min, which explains the error you're seeing).
Based on the extra information in the comments, perhaps xcorr2 is what you're after (this works on the GPU).

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

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.

Matlab: nest fzero in fminsearch

I am trying to minimize with respect to a variable "y" a function that contains a parameter which must be calculated as a solution of an equality that contains "y" as well (say, y=-3; in my complete problem it is an equation with no analytic closed form solution, so I really need fzero).
Because of this, I include the fzero function in the argument of fminsearch:
fminsearch( #(y) 10*fzero(#(y) y+3, 0)) ;
I get the error:
Error using fminsearch (line 85)
The input to FMINSEARCH should be either a structure with
valid fields or consist of at least two arguments.
I obviously get the same error with:
f = fzero(#(y) y+3, 0);
fminsearch(#(y) 10*f);
Apparently the problem is that I cannot "nest" a fzero inside fminsearch.
Any idea about how to turn around this problem?
If you read the error message you got and look at the documentation of fminsearch you'll see that you need to call it with two input arguments. You call it with only one.
fminsearch( #(y) 10*fzero(#(x) x+3, 0), 0 )

How can I solve this MATLAB "Matrix dimensions must agree" error?

I am typing some code for a class but every time I run the function I get the same error:
??? Error using ==> plus
Matrix dimensions must agree.
Error in ==> Test at 6
f32=3.*exp((-x2.^2-y1.^2)./3);
I know that the problem is a simple index error, but I can't seem to find it anywhere. Can somebody help me?
Also I'm having the same problem with the following line of code:
f34=(exp(-0.3./x2))./(log(y2).*sqrt(x2));
EDIT #1:
x2 is defined as 0:0.1:5 and y1 is defined as -5:0.1:5, but that is what I have been assigned to define them as. And I know exp is not a function because I have used it elsewhere in my file.
EDIT #2:
OK. So if I can't use my current x and y is there anyway I can define them to keep them on those bounds while still making them the same size?
UPDATE:
OK, now that you have confirmed that your variables x2 and y1 contain different numbers of elements, you have a couple of solutions to choose from:
For each variable, you can create a set number of values over the respective ranges using the function LINSPACE. For example:
x2 = linspace(0,5,101); %# 101 values spanning the range 0 to 5
y1 = linspace(-5,5,101); %# 101 values spanning the range -5 to 5
However, when you compute the result f32 (which will also be a 101-element array), it will only be evaluated at the respective pairs of values in x2 and y1 (e.g. x2(1) and y1(1), x2(50) and y1(50), etc.).
If you would rather evaluate f32 at every unique pair of points over the ranges of x2 and y1, you should instead use the function MESHGRID to generate your values. This will also allow you to have a different numbers of points over the ranges for x2 and y1:
[x2,y1] = meshgrid(0:0.1:5,-5:0.1:5);
The above will create x2 and y1 as 101-by-51 arrays such that f32 will also be a 101-by-51 array evaluated at all the points over the given ranges of values.
Previous answer:
The first thing to test is if all the variables you are putting into the equation are the same size or scalar values, which they would have to be since you are using element-wise operators like .^ and .*. For the first equation, see what output you get when you do this:
size(x2)
size(y1)
If they give the same result, or either is [1 1], then that's not your problem.
The next thing to check is whether or not you have shadowed the EXP function by creating a variable by the name exp. If you're running the code as a script in the command window, type whos and see if a variable named exp shows up. If it does, you need to delete or rename it so that you can use the function EXP.
How do you expect -x2.^2-y1.^2 to work when x2 and y1 is of different size? x2=0:0.1:5 has fifty or so entires while y1=-5:0.1:5 has a hundred or so entries.