MatLab input argument error with objective function and fmincon() - matlab

I am working through an example using fmincon().
I define my objective function in objFun.m
function f=objFun(x)
f = 100*(x(2) - (x(1))^2)^2 + (1 - x(1))^2;
end
and I define an initial point x0
x0=[1; -1]
And if I run the objective function with that point as a test I get
>> objFun(x0)
ans =
400
But when I try to use it in fmincon() I get
>> [x, fval] = fmincon(objFun, x0, [1;2],1,[],[],[0; -inf],[inf, 0]);
Not enough input arguments.
Error in objFun (line 2)
f = 100*(x(2) - (x(1))^2)^2 + (1 - x(1))^2;
I suspect I'm missing something very simple here, but what?

you need to pass a handle to the function #objFun not the function itself, and your A and x0 matrix need to be transposed, ie: a row with 2 columns, each row in A is another linear constraint.
x0=[1, -1];
A = [1,2];
b = 1;
[x, fval] = fmincon(#objFun, x0, A,b,[],[],[0; -inf],[inf; 0]);
function f=objFun(x)
f = 100*(x(2) - (x(1))^2)^2 + (1 - x(1))^2;
end

Related

how to create a pulse train using anonymous function - Matlab

I have a pulse shape that is a function of t, call it h(t), that is in the form of:
h = #(t) function of t
I want to create a pulse train that is consisted of N pulses h(t).
I did this by:
for n=0:N-1
comb = comb + h(t - n);
end
However, once I do that I can't change t in the train.
How can I create this train so that it will also be a function of t?
Thanks.
You just need to make comb an anonymous function too. You can initialise it to some trivial function (i.e. it always outputs 0), and then repeatedly modify it. Since variables declared before an anonymous function declaration, including anonymous functions, are kind of "frozen" to the definition at that point this will work.
h = #(t) _______ % some function of 't'
comb = #(t) 0;
for n = 0:N-1
comb = #(t) comb(t) + h(t - n);
end
We can test this with h = #(t) sin(t) and N=3:
>> comb(pi/2)
ans = 1.1242
>> h(pi/2) + h(pi/2-1) + h(pi/2-2)
ans = 1.1242
Note that just displaying comb can be a bit misleading, since information about the recursive definition is somewhat lost
disp(comb)
#(t)comb(t)+h(t-n)

Using Adams-Bashforth method in Matlab to solve Lorenz-System Equation

I am trying to use my second order Adams-Bashforth function here:
function [t,x] = Adams(f,t_max,x0,N)
h = t_max/N;
t = linspace(0,t_max,N+1);
x = zeros(2,N+1);
x(:,1) = x0;
x(:,2) = x0 + h.*(f(t(1),x(:,1)));
for i=2:N
x(:,i+1) = x(:,i) + h.*((3/2.*f(t(i),x(:,i))-(1/2).*f(t(i-1),x(:,i-1))));
end
end
In order to solve the Lorenz System Equation. However, whenever I try to call the function, I get an error.
sigma = 10;
beta = 8/3;
rho = 28;
f = #(t,a) [-sigma*a(1) + sigma*a(2); rho*a(1) - a(2) - a(1)*a(3); -beta*a(3) + a(1)*a(2)];
[t,a] = Adams(f,10,[1 1 1],100);
plot3(a(:,1),a(:,2),a(:,3))
Output:
"Unable to perform assignment because
the size of the left side is 2-by-1 and
the size of the right side is 1-by-3.
Error in Project>Adams (line 55)
x(:,1) = x0;"
Is the issue with my function, or with how I am calling my function? Any help would be appreciated.
in line 5 of your Adams function: x(:,1) = x0;
the input x0 is the initial conditions [1 1 1] a row vector of size [3x1], but x is an array of size zeros(2,N+1), or [2x101].
There are several mistakes here, the first you assign a row vector to a colon vector, not only that, but the size of the container in that first column of array x which is [2x1] , that is a different size than the size of x0. that is what the error tells you.
The function is buggy there , and it wont work unless you debug it according to the original intent of that method you are trying to implement.
note that also in the script f=#(t,... is expected to have an input t, but there is not t in the expression [-sigma*a(1) + sigma*a(2); rho*a(1) - a(2) - a(1)*a(3); -beta*a(3) + a(1)*a(2)];

Not able to use `fzero()` function in Matlab

I am new to Matlab. I am trying to solve a non-linear equation using this inbuilt Matlab function called fzero() but it's not giving me the results.
The main file goes like
A = 5;
B = 6;
C = 10;
eq = equation (A, B, C);
fzero(#(x)eq);
The other function file is:
function eq = equation (A, B, C)
syms x;
eq = A*x.^2 + B*x + C*(asinh(x)) ;
When I run this code, I get the following error:
Error using fzero (line 118)
The input should be either a structure with valid fields or at least two arguments to
FZERO.
Error in main (line 7)
fzero(#(x)eq);
Could someone help me with this?
EDIT:
WHen I specify the check point as 0, it returns me the following error.
Undefined function 'isfinite' for input arguments of type 'sym'.
Error in fzero (line 308)
elseif ~isfinite(fx) || ~isreal(fx)
Error in main (line 7)
fzero(#(x)eq, 0);
There are several mistakes in your code. For a start, fzero is for finding numerical roots of a non-linear equation, it is not for symbolic computations (check the documentation), so get rid of syms x. The correct way to call fzero in your case is a as follows:
A = 5;
B = 6;
C = 10;
eq = #(x) A*x^2 + B*x + C*(asinh(x));
x0 = 0; % or whatever starting point you want to specify
x = fzero(eq,x0)
You need to specify a guess, x0 point
fun = #sin; % function
x0 = 3; % initial point
x = fzero(fun,x0)

Sending a function into a matlab function

I'm trying build a matlab function that will evaluate a function and vector that are sent in as parameters. I'm having a hard time trying to figure out how to send in the function so that it can be evaluated in the matlab function. I figured out how to do it without the function but I'm a little lost trying to evaluate it within a matlab function. Below is my code...
This is what I'm trying to do...
x = [x1 x2]';
f = x(x1)^2 + 2 * (x2)^2
x = [5 10];
f = (5)^2 + 2 * (10)^2 % which I would like to return 225, not a column vector
This is what I have and what I have tried...
x = [5 10]';
% without using a matlab function
% k = 1
% f = x(k)^2 + 2 * x(k + 1)^2; % returns the correct answer of 225
f = x^2 + 2 * x^2 % complains about the scalar 2
f = x.^2 + 2 * x.^2 % returns a column vector [75; 300]
function [value] = evalFunction(f,x)
value = f(x);
I've tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(#f,x) %Error: "f" was previously used as a variable
So I tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(f,x) %value = [97;342]
I'm new to matlab so any help is appreciated. I've been doing some research and found some stuff here on stackoverflow but can't seem to get it to work. I've seen there are other ways to do this, but I will eventually be adding more code to the matlab evalFunction function so I'd like to do it this way. Thanks!
Anonymous functions and function handles plus array indexing. Taking x as a 2-element vector, define and use your function like:
f = #(x) x(1).^2 + 2 * x(2).^2;
value = evalFunction(f,x) % but you can just do f(x) if that is all you need
However, if evalFunction does nothing other than evaluate f at x, then you don't need it at all. Just do f(x).
Alternately,
f = #(x1,x2) x1.^2 + 2*x2.^2;
value = evalFunction(f,x1,x2); % here your function will call it by f(x1,x2)
You are probably coming at this from a C background - in Matlab, x+1 is the entire vector x with 1 added - not the element offset by 1.
The function you need is
f = #(x)x(1).^2 + 2 * (x(2)).^2;
or, to be a little more "matlab-like":
f = #(x) [1 2] * x(1:2)'.^2;
Which performs the element-wise square of the first two elements of x as a column vector, and then does the matrix multiplication with [1 2], resulting in
1 * x(1) .^2 + 2 * x(2) .^2;
Which seems to be what you were asking for.
caveat: did not have opportunity to test this...

how to solve a system of Ordinary Differential Equations (ODE's) in Matlab

I have to solve a system of ordinary differential equations of the form:
dx/ds = 1/x * [y* (g + s/y) - a*x*f(x^2,y^2)]
dy/ds = 1/x * [-y * (b + y) * f()] - y/s - c
where x, and y are the variables I need to find out, and s is the independent variable; the rest are constants. I've tried to solve this with ode45 with no success so far:
y = ode45(#yprime, s, [1 1]);
function dyds = yprime(s,y)
global g a v0 d
dyds_1 = 1./y(1) .*(y(2) .* (g + s ./ y(2)) - a .* y(1) .* sqrt(y(1).^2 + (v0 + y(2)).^2));
dyds_2 = - (y(2) .* (v0 + y(2)) .* sqrt(y(1).^2 + (v0 + y(2)).^2))./y(1) - y(2)./s - d;
dyds = [dyds_1; dyds_2];
return
where #yprime has the system of equations. I get the following error message:
YPRIME returns a vector of length 0, but the length of initial
conditions vector is 2. The vector returned by YPRIME and the initial
conditions vector must have the same number of elements.
Any ideas?
thanks
Certainly, you should have a look at your function yprime. Using some simple model that shares the number of differential state variables with your problem, have a look at this example.
function dyds = yprime(s, y)
dyds = zeros(2, 1);
dyds(1) = y(1) + y(2);
dyds(2) = 0.5 * y(1);
end
yprime must return a column vector that holds the values of the two right hand sides. The input argument s can be ignored because your model is time-independent. The example you show is somewhat difficult in that it is not of the form dy/dt = f(t, y). You will have to rearrange your equations as a first step. It will help to rename x into y(1) and y into y(2).
Also, are you sure that your global g a v0 d are not empty? If any one of those variables remains uninitialized, you will be multiplying state variables with an empty matrix, eventually resulting in an empty vector dyds being returned. This can be tested with
assert(~isempty(v0), 'v0 not initialized');
in yprime, or you could employ a debugging breakpoint.
the syntax for ODE solvers is [s y]=ode45(#yprime, [1 10], [2 2])
and you dont need to do elementwise operation in your case i.e. instead of .* just use *