I want to solve a simple problem with fmincon but It returns an error message.
I have 2 functions f_2 and f_1 and I want to minimize each of them individually. I want to write f_1 and f_2 in a one matlab function i.e., my fun.m. Then I want to call each of them using an index from the main code. Here is the code you can see:
main code:
AA=[1 2 -1 -0.5 1];bb=-2;
xo=[1 1 1 1 1];
VLB=[-1 -1 -1 -1 -1];
VUB=[100 100 100 100 100];
for F_index = 1:2
[x,fval]=fmincon(#myfun,xo,AA,bb,[],[],VLB,VUB)
end
%% here is the function
function f = myfun(x, F_index)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
if F_index == 2
f = 100*(x(3) - x(5)) + (3*x(1)+2*x(2) - x(3)/3)^2 + 0.01*(x(4) - x(5))
end
Undefined function or variable 'F_index'.
Error in myfun (line 2) if F_index == 1
Error in fmincon (line 564)
initVals.f =
feval(funfcn{3},X,varargin{:});
Error in main (line 6)
[x,fval]=fmincon(#myfun,xo,AA,bb,[],[],VLB,VUB)
Caused by:
Failure in initial user-supplied objective
function evaluation. FMINCON cannot continue.
The error message clearly states the problem: The variable F_index is undefined within the function myfun. Variables in Matlab have a scope restricted to the function (or rather "workspace") within which they are defined. They can be made "global", but that's not something you normally want to do.
A workaround is to use nested functions, where variables of the enclosing function become available in the nested function:
function main_function
AA=[1 2 -1 -0.5 1];bb=-2;
xo=[1 1 1 1 1];
VLB=[-1 -1 -1 -1 -1];
VUB=[100 100 100 100 100];
F_index = 1;
for F_index = 1:2
[x,fval]=fmincon(#myfun,xo,AA,bb,[],[],VLB,VUB)
end
function f = myfun(x)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
if F_index == 2
f = 100*(x(3) - x(5)) + (3*x(1)+2*x(2) - x(3)/3)^2 + 0.01*(x(4) - x(5))
end
end
end
Now myfun is nested in main_function and has access to its variables.
You can bind extra arguments using anonymous functions:
fmincon(#(x) myfun(x, F_index), ...)
Here, the value of F_index is evaluated and becomes part of the anonymous function.
However, these look like completely independent functions. Why not separate them all the way, and use a cell array of handles for the iteration?
fcns = {#fun1, #fun2};
for F_index = 1:2
[x,fval]=fmincon(fcns{F_index},xo,AA,bb,[],[],VLB,VUB)
end
You need to learn about variables in/out functions.
Practically in any programming language, when you enter a function, that function can only access the variables that are created inside, or that are passed as an argument as x, y, z and potato in the next example: myfun(x,y,z, potato).
This means that in:
function f = myfun(x)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
end
myfun does not have any idea what F_index is.
One of the ways of solving it is declaring F_index as global, but I would recommend you rather change the function somehow, so it doesn't access out of function variables.
Related
I am attempting to write a recursive code that takes an input n and outputs the nth term of the Fibonacci sequence, without using any loops or any of MATLABS inbuilt functions.
for exemple:
fibo(6)
ans = 8
I am having trouble with writing the code recursively, and would really appreciate some help.
with a loop I wrote:
function f = fib1(n)
if n <= 1
f = 1;
else
f = fib1(n-1) + fib1(n-2);
end
end
If you want to get 8 for fib1(6), that means you need to start your fibonacci sequence from n=1. However, you code indicates that you start from n=0. In this case, you should use n <=2 in your if-else statement, i.e.,
function f = fib1(n)
if n <= 2
f = 1;
else
f = fib1(n-1) + fib1(n-2);
end
end
such that
>> fib1(6)
ans = 8
If you don't want to use any recursion, you can try the code below
function f = fib2(n)
f = (((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n)/sqrt(5);
end
which gives
>> fib2(6)
ans = 8
I'm using Matlab R2018a. This has a "memoize" function, which works at top level, but I don't see how to use it for recursive functions.
For example, I tried this:
function z = recfib(n)
if n == 1
z = 1;
else
z = memfib(n-1)+memfib(n-2);
end
fprintf('computed f(%d)=%d',n,z);
end
and then
memfib = memoize(#recfib);
But this doesn't work, as calls to memfib or recfib produce an error:
Undefined function or variable 'memfib'.
You need to stick that memfib somewhere that the calls inside the function can see it. If you just do memfib = memoize(#recfib) at the command line or in calling code, you end up with a memfib variable in the base/caller workspace, not a globally-visible memfib function.
I think you can do this with a persistent variable inside the recfib function. This works for me in R2019b.
function z = recfib(n)
persistent memfib
if isempty(memfib)
memfib = memoize(#recfib);
end
if n <= 1
z = 1;
else
z = memfib(n-1)+memfib(n-2);
end
fprintf('computed f(%d)=%d\n',n,z);
end
Running it twice shows the memoization happening:
>> recfib(8)
computed f(1)=1
computed f(0)=1
computed f(2)=2
computed f(3)=3
computed f(4)=5
computed f(5)=8
computed f(6)=13
computed f(7)=21
computed f(8)=34
ans =
34
>> recfib(8)
computed f(8)=34
ans =
34
>>
(Also, you've got a bug in the base case test; it needs to be n <= 1, not n == 1, to catch the 0 and -1 cases, because that memfib(n-2) line ends up calling memfib(0) when n = 2.)
I have a problem about matlab code. I have a specific one variable function, and i want to assign a vector or array in this function as a x value. But i didn't reach success.
A part of my code is at below:
a=-5; b=10; n=20; %[a,b] interval range and n is number of interval
sz = (b-a)/n; %interval size
t=1; %iteration number
for i=1:n
I(i,:,t) = [a+(i-1)*sz a+i*sz]; %interval
x(i,:,t) = a+(i-0.5)*sz; %midpoint of interval
end
f= x.^2-3.*x+5; %my sample function
for i=1:n
if i==1
j=i+1;
neigbor(i,:,t) = I(j,:,t); %neigbor of interval I1's
h_f(i,:,t) =abs(f(x(i,:,t))-f(x(j,:,t))); %heuristic value
prob(i,:,t)=(ph(j,:,t).*h_f(i,:,t))./(ph(j,:,t).*h_f(i,:,t)); %probability
...
Other if conditions are following this code, but i check this below portion with sample i and j value, it gives error like this : "Subscript indices must either be real positive integers or logicals."
h_f(i,:,t) =abs(f(x(i,:,t))-f(x(j,:,t)));
What don't i know? What is my mistake? Can you suggest anything? If you need complete code, i can post.
Edit : Actually this function f returns value by using itself. But it doesn't return value in comment h_f(i,:,t)= abs((f(x(i,:,t)-x(j,:,t))
Solution Edit: After creating separate function m file, and calling in main function. Don't need to write x array in f.
In Matlab, you need to declare functions in a separate .m file. I created a separate file "f.m" and inserted the following code:
function return_val = f(x)
return_val = x.^2-3.*x+5; %my sample function
end
Then, in your main file, you can call this function as follows:
a=-5; b=10; n=20; %[a,b] interval range and n is number of interval
sz = (b-a)/n; %interval size
t=1; %iteration number
for i=1:n
I(i,:,t) = [a+(i-1)*sz a+i*sz]; %interval
x(i,:,t) = a+(i-0.5)*sz; %midpoint of interval
end
f = f(x)
Hope this helps.
As was posted you can create f as a function in a file but you can also inline the function with a handle. This is done as follows:
f = #(x) x.^2 - 3.*x + 5;
The f is the function handle with x as an input, see more information here: http://www.mathworks.com/help/matlab/matlab_prog/creating-a-function-handle.html.
This new f is then used as you would expect.
>> f(2)
ans =
3
>> f(5)
ans =
15
>> f(1:3)
ans =
3 3 5
>> f(4:10)
ans =
9 15 23 33 45 59 75
I want to build a series of different function with matlab and integrate and differentiate the results. but the mathwork says the output of the str2func can't access the variable or could bot be used by other function.
Is any one help me with this problem?
I want to create these function:
f1= #(x,l) x.*(l-x);
f2= #(x,l) x.^2.*(l-x).^2.*(l/2-x).^2;
f3= #(x,l) x.^3.*(l-x).^3;
f4= #(x,l) x.^4.*(l-x).^6.*(l/2-x).^4;
f5= #(x,l) x.^5.*(l-x).^5;
f6= #(x,l) x.^6.*(l-x).^6.*(l/2-x).^6;
f7= #(x,l) x.^7.*(l-x).^7;
f8= #(x,l) x.^8.*(l-x).^8.*(l/2-x).^8;
f9= #(x,l) x.^9.*(l-x).^9;
f10= #(x,l) x.^10.*(l-x).^10.*(l/2-x).^10;
I write this function:
syms x l
f=cell(10,1);
fun=cell(10,1);
for i=1:10
if mod(i,2) ~= 0
f{i}=['x','.^',num2str(i),'.*','(l-x)','.^',num2str(i)];
else
f{i}=['x','.^',num2str(i),'.*','(l-x)','.^',num2str(i),'.*','(l/2-x)','.^',num2str(i)];
end
end
for i=1:10
for j=1:10
if mod(i,2) ~= 0 & mod(j,2) ~= 0
Fs = ['(x)','x','.^',num2str(i),'.*','(l-x)','.^',num2str(i),'*','x','.^',num2str(j),'.*','(l-x)','.^',num2str(j)];
FS = str2func (Fs)
fjnew = str2func(['(x)','x','.^',num2str(j),'.*','(l-x)','.^',num2str(j)])
fj_diff = diff(fjnew,x)
when I run that the error is :
Undefined function '(x)x.^1.*(l-x).^1' for input arguments of type 'sym'.
Error in sym>funchandle2ref (line 1172)
S = x(S{:});
Error in sym>tomupad (line 989)
x = funchandle2ref(x);
Error in sym (line 142)
S.s = tomupad(x,'');
Error in sym/privResolveArgs (line 810)
argout{k} = sym(arg);
Error in sym/diff (line 21)
args = privResolveArgs(S,varargin{:});
Your Sincerely
Saeed Nasiri
I found all your problems.
The character "l" is not the character "1". One of them is L and the other is a number. You just wrote "l" \ell\ instead of "1" \one\ in (l-x). EDIT I just realised you actually want l not 1.
Function handles are not (x)x.^2 (random example), they are #(x)x.^2! You forgot to add the "#" in all the calls, thus =['(x)' should be =['#(x)'
3.Your functions are actually (as yourself described in the post), variable respect x and l. Thus, you need the function handle to say that. Change =['#(x)' for =['#(x,l)'.
Iam not sure if you are aware of this, but you dont use practically any of the parts of your code. Your code can be reduced to 4 lines and it will do exactly the same. Fs,FS adn f are never use.:
The result of your code is the same as:
for i=1:10
for j=1:10
if mod(i,2) ~= 0 & mod(j,2) ~= 0
fjnew = str2func(['#(x,l)','x','.^',num2str(j),'.*','(l-x)','.^',num2str(j)])
fj_diff = diff(fjnew,x)
end
end
end
So unless you are doing more stuff with it later, there is no need to compute stuff unnecessarily.
I have my code working using the integral function but I'm looking to implement it using the trapz function instead.
fc = 5*10^6;
fb = 0.2*10^6;
F = [0:10000:10^7];
Tb = 1/fb;
Sequence = [0 1 0 1 1 0 1 1 1 0 0 0 1 0 1 ];
A = sqrt(9/Tb);
w = 2*pi*fc;
I = zeros(1,length(F));
for counter1 = 1:length(Sequence)
if Sequence ( 1, counter1) == 1
s_of_t = #(t) A*cos(w*t)*exp(-1i*2*pi*t*F);
else
s_of_t = #(t) -A*cos(w*t)*exp(-1i*2*pi*t*F);
end
S_of_f = integral(s_of_t,((counter1-1)*Tb),(counter1*Tb),'ArrayValued', true);
for counter2 = 1:length(S_of_f)
I( 1, counter2) = I(1,counter2)+S_of_f(1,counter2);
end
clear S_of_f s_of_t;
end
figure(1)
plot(F,abs(I));
What I want to do is use the trapz function instead of the integral function like this:
for n = 1 : length(F)
S_of_f(n) = trapz(F,s_of_t);
end
instead of:
S_of_f = integral(s_of_t,((counter1-1)*Tb),(counter1*Tb),'ArrayValued', true);
I am having trouble implementing my code using this function so if you have any advice I'd appreciate it.
Errors include:
Undefined function 'max' for input arguments of type 'function_handle'.
Error in trapz (line 43)
perm = [dim:max(ndims(y),dim) 1:dim-1];
I'm not sure which function handles I'm missing.
(Yes I'm taking the Fourier Transform however my attempts to utilize the FFT function took up way too much memory).
trapz expects a vector of function evaluations, not a function handle, which is what integral expects.
if Sequence ( 1, counter1) == 1
s_of_t = #(t,F) A*cos(w*t).*exp(-1i*2*pi*t*F);
else
s_of_t = #(t,F) -A*cos(w*t).*exp(-1i*2*pi*t*F);
end
for i=1:length(F)
r=linspace(((counter1-1)*Tb),(counter1*Tb),100);
S_of_f(i) = trapz(r,s_of_t(r,F(i)));
end
...
I arbitrarily chose 100 evaluation points for the integral using trapz; you will want to modify this to an appropriate value depending on how you are using this code.