I want to optimize an unconstrained multivariable problem using fminunc function in MATLAB. Here is an example:
Minimize the function f(w)=x'Ax
Create a file myfun.m:
function f = myfun(x)
f = x'*A*x + b'x
Then call fminunc to find a minimum of myfun near x0:
[x,fval] = fminunc(#myfun,x0).
My problem is that in my algorithm, the matrix A and vector b in myfun.m are not fixed, but can be changed over loops, so I cannot type them by hand. How can I pass values to A and b?
There are a few options for passing additional arguments to an objective function. For a simple one like yours, you could just make an anonymous function, which will save the values of A and b when it was created:
A = myMatA();
b = myVecb();
myfun = #(x) x.'*A*x + b.'*x;
[x,fval] = fminunc(myfun,x0); % use no # with an anonymous function
The other two options are global variables (yuck!) and nested functions. A nested function version looks like this:
function [x,fval] = myopt(A,B,x0)
[x,fval] = fminunc(#myfunnested,x0);
function y = myfunnested(x)
y = x.'*A*x + b.'*x;
end
end
But I think you would not use fminunc to solve minimization of x'Ax + b'x...
Related
It seems that, to create a function f(x,y)=x+y, I can have two approaches.
syms x y; f(x,y) = x+y
f = #(x,y) x+y
They seem very similar, and I do not know whether there are some subtle differences.
Typically, if I need to evaluate the function for inputs or many samples I would opt-in to using the second method (function handles/anonymous functions).
Method 1: Symbolic Functions
This method allows the function to be evaluated at a specific point/value by using the subs(), substitution function. Both plots can be plotted using fsurf().
clear;
syms x y
f(x,y) = x+y;
fsurf(f);
subs(f,[x y],[5 5])
Variants and offsetting of symbolic functions can be done similarly to anonymous functions/function handles with the one caveat of not needing to include the input parameters in the #().
g = f(x,y) + f(x-5,y-5)
fsurf(g);
Method 2: Anonymous Functions/Function Handles
This method allows you to directly input values into the function f(x,y). I prefer anonymous functions because they seem more flexible.
clear;
f = #(x,y) x+y;
fsurf(f);
f(5,5)
Some cool things you can do is offset and easily add variants of anonymous functions. Inputs can also be in the form of arrays.
x = 10; y = 2;
f(x-5,y-5) + f(x,y)
g = #(x,y) f(x,y) + f(x-5,y-20);
fsurf(g);
Ran using MATLAB R2019b
I would like to solve the following polynomial numerically for r:
I am trying to use fzero() as follows:
r = (5/(r^2*9))- ((2)/(9*(6-r)^2))
x0 = 10; % some initial point
x = fzero(r,x0)
How can this be done with fzero()?
Input variable and function name should be different
Just change the function name to pol
To use fzero the function pol have to be a function handle
defined via #
pol =#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2))
x0 = 10; % some initial point
x = fzero(pol,x0)
solution
x = 3.6754
It should be noted that, the first argument in fzero() should be "a function handle, inline function, or string containing the name of the function to evaluate", but yours is just an expression, which is not valid.
Besides the approach by #Adam (using function handle), another way is to use anonymous function, i.e.,
x = fzero(#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2)) ,x0)
where
#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2))
is the anonymous function with respect to argument r.
You will get the same result that x = 3.6754.
I'm implementing a ML receiver for a communication channel.
For this I need to find the minimum value of the function below with respect to x in the range x = 0 to 15 (16QAM)
f = abs( rx(n) - (h'*h)*x )^2 ;
I have to iterate this in a loop (n=1:100). I found that I can do this by matlab function x = fminbnd(fun,x1,x2) where I can put the function in a separate .m-file as:
function f = myfun(x)
f = abs( rx(n) - (h'*h)*x )^2
and find the minimum for x from
x = fminbnd(#myfun,x1,x2);
My question is since constants to the function rx(n) is changing thorough the loop, how to sent it to the function myfun(x) within the loop.
You can do it by using an anonymous function to call your function in a separate file:
function mainfcnmin
h = [1;1];
rx = 1:3;
for n = 1:length(rx)
x = fminbnd(#(x)myfun(x,rx(n),h),0,15)
end
end
function f = myfun(x,rx,h)
f = abs(rx-(h'*h)*x)^2 ;
end
Or alternatively in one file by defining the function directly in the anonymous function like this:
h = [1;1];
rx = 1:3;
for n = 1:length(rx)
x = fminbnd(#(x)(abs(rx(n)-(h'*h)*x)^2),0,15)
end
You will need to make a function with rx(n) as a second parameter and then turn it into a single parameter anonymous function inside the loop.
Here is an example from the MATLAB documentation (for 'fminsearch' function):
If fun is parameterized, you can use anonymous functions to capture
the problem-dependent parameters. For example, suppose you want to
minimize the objective function myfun defined by the following
function file:
function f = myfun(x,a)
f = x(1)^2 + a*x(2)^2;`
Note that myfun has an extra parameter a, so you cannot pass it directly to > fminsearch. To optimize for a specific value of a, such as a = 1.5.
Assign the value to a
a = 1.5; % define parameter first
Call
fminsearch with a one-argument anonymous function that captures that
value of a and calls myfun with two arguments:
x = fminsearch(#(x) myfun(x,a),[0,1])
Hope that helped (sorry for bad text formatting).
I have some code here which illustrates the nested nature of some integrals that I want to perform in matlab. When I run the following code I get the error
Error using .*
Matrix dimensions must agree.
Error in fun1/integrand (line 7)
f = x.^2.*t;
it seems that the way I have set it up now does not allow for vectorized output of the integral function. What can I do to make my code run? I have commented below what I want the functions to do.
My code is as follows:
%Main script:
z = linspace(0,10,10);
I = zeros(10,1);
for i = 1:10
I(i) = fun2(z(i));
end
%Function 1 in separate file:
function I = fun1(x)
I = integral(#integrand,-1,1);
function f = integrand(t)
f = x.^2.*t;
end
end
%Function 2 in separate file:
function I = fun2(z)
I = integral2(#integrand,-1,1,-1,1);
function f = integrand(x,y)
f = z.*fun1(x).*y; // here fun1 should return the value for all x that is swept through by integral2 during its call.
end
end
The problem with your code is you are using integral2 and integral1 in a combination. This way integral2 generates a grid for x and y and integral1 generates the t values. This way the t and x values don't match in size, and even if they would they are part of a different grid.
As already discussed, using ingetral3 is the right choice. Alternatively you could simply "fix" this introducing a loop, but this results in much slower code:
function I = fun1(x)
I=nan(size(x));
for ix=1:numel(x)
I(ix) = integral(#(t)integrand(x(ix),t),-1,1);
end
function f = integrand(x,t)
f = x.^2.*t;
end
end
I want to solve two nonlinear equations in MATLAB so i did the following:
part of my script
c=[A\u;A\v];
% parts of code are omitted.
x0=[1;1];
sol= fsolve(#myfunc,x0);
the myfunc function is as follows
function F = myfunc(x)
F=[ x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj];
end
i have two unknowns x(1) and x(2)
my question is How to pass a values(c,ii,jj) to myfunc in every time i call it?
or how to overcome this error Undefined function or method 'c' for input arguments of type 'double'.
thanks
Edit: The previous answer was bogus and not contributing at all. Hence has been deleted. Here is the right way.
In your main code create a vector of the coefficients c,ii,jj and a dummy function handle f_d
coeffs = [c,ii,jj];
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
sol = fsolve(f_d,x0);
Make your function myfunc capable of taking in 2 variables, x0 and coeffs
function F = myfunc(x, coeffs)
c = coeffs(1:end-2);
ii = coeffs(end-1);
jj = coeffs(end);
F(1) = x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
F(2) = x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj;
I think that should solve for x0(1) and x0(2).
Edit: Thank you Eitan_T. Changes have been made above.
There is an alternative option, that I prefer, if a function handle is not what you are looking for.
Say I have this function:
function y = i_have_a_root( x, a )
y = a*x^2;
end
You can pass in your initial guess for x and a value for a by just calling fsolve like so:
a = 5;
x0 = 0;
root = fsolve('i_have_a_root',x0,[],a);
Note: The [] is reserved for fsolve options, which you probably want to use. See the second call to fsolve in the documentation here for information on the options argument.