How to memoize a recursive function in Matlab - matlab

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.)

Related

Matlab: How to get the Nth element in fibonacci sequence recursively without loops or inbuilt functions

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

How to return a series of number from a recursive function in Matlab

I use dynamic programming for finding the shortest path between two matrices. I printed all the step of the shortest path, but I would also like to save all of them so I can print them as a 2D figure. I wrote the code like below but it doesn't work. I searched on the internet and it seems like it need to be pass by an object as the argument? Does anyone know how to get the path matrix from the returning value? Thanks in advance!
ttt=find_path(7,7)
function pathMat = find_path(a,b)
pathMat=[];
if (a==0 || b==0)
return;
end
filename = sprintf('/Users/name/Desktop/song1.wav');
[x, Fs]=audioread(filename);
s=x;
filename = sprintf('/Users/name/Desktop/song2.wav');
[x, Fs]=audioread(filename);
t=x;
% dynamic time warping
w=-Inf;
ns=size(s,2);
nt=size(t,2);
%% initialization
D=zeros(ns+2,nt+2)-Inf; % cache matrix
D(1,1)=0;
D(2,2)=0;
% similarity matrix (cosing similarity)
oost = zeros(ns+1,nt+1)-Inf;
for i=1:ns
for j=1:nt
oost(i+1,j+1) =
(dot(s(:,i),t(:,j))/(norm(s(:,i),2)*norm(t(:,j),2))); % = cos(theta)
end
end
%% begin dynamic programming
%find the maximal similarity between two matrix
for i=1:ns
for j=1:nt
D(i+2,j+2)=oost(i+1,j+1)+max([D(i,j+1)+oost(i,j+1), D(i+1,j)+oost(i+1,j), D(i+1,j+1)]);
end
end
d=max(D(:,nt+2));
d_len=nt+2;
while(max(D(:,d_len))==-Inf)
d_len=d_len-1;
d=max(D(:,d_len));
end
fprintf('(%d, %d)', a, b);
pathMat = [pathMat];
if (max([D(a,b+1)+oost(a,b+1), D(a+1,b)+oost(a+1,b), D(a+1,b+1)])==D(a,b+1)+oost(a,b+1))
fprintf('(%d, %d)', a-1, b);
pathMat=[pathMat;find_path(a-1,b)];
find_path(a-2,b-1);
elseif (max([D(a,b+1)+oost(a,b+1), D(a+1,b)+oost(a+1,b), D(a+1,b+1)])==D(a+1,b)+oost(a+1,b))
fprintf('(%d, %d)', a, b-1);
pathMat=[pathMat;find_path(a,b-1)];
find_path(a-1,b-2);
elseif (max([D(a,b+1)+oost(a,b+1), D(a+1,b)+oost(a+1,b), D(a+1,b+1)])==D(a+1,b+1))
find_path(a-1,b-1);
end
end
There are two approaches you can use, to retain values between function calls or store all results in a "global" variable.
Due to the clutter and length of your code (not everything is relevant to the question), I will take the example of a factorial program to describe the approach.
Let there be a function that not only computes the factorial of the given number recursively, but also all the intermediate results of numbers lesser than itself. I believe this is a close model of what you require. An example of what the function should do:
>> [fact, list] = factorial(5)
>> fact = 120
>> list = [1, 2, 6, 24, 120]
Approach 1: Use persistent variables
Persistent variables are the equivalent of static function variables (like in C) in MATLAB.
Persistent variables by default are assigned to [] on first use. Also, the value is retained across function calls as expected. A sample code using this approach to define our factorial program:
function [fact, list] = factorial(n)
if n <= 1
fact = 1;
else
fact = n * factorial(n-1);
end
persistent res;
res = [res, fact];
list = res;
end
This can be used as follows:
>> [f, list] = factorial(4)
f =
24
list =
1 2 6 24
>> clear factorial
>> [f, list] = factorial(3)
f =
6
list =
1 2 6
Approach 2: Sharing variables in nested functions
MATLAB supports nested function definitions, where the inner functions can share variables from the outer one, and modify them without explicitly being passing as arguments. A sample code using this approach:
function [fact, list] = factorial(n)
list = [];
fact = factorial_core(n);
function fact = factorial_core(n)
if n <= 1
fact = 1;
else
fact = n * factorial_core(n-1);
end
list = [list, fact];
end
end
This is used the same way as before, except that clear factorial (that clears the persistent variables) between function calls is not required.
I would recommend you to try out whichever suits your case best. Also, it appears that you are loading the wav files each time of the recursion, which is unnecessary and inefficient. These two approaches can be used to avoid that, apart from solve your problem.

MATLAB function handles and parameters

When I type help gmres in MATLAB I get the following example:
n = 21; A = gallery('wilk',n); b = sum(A,2);
tol = 1e-12; maxit = 15;
x1 = gmres(#(x)afun(x,n),b,10,tol,maxit,#(x)mfun(x,n));
where the two functions are:
function y = afun(x,n)
y = [0; x(1:n-1)] + [((n-1)/2:-1:0)'; (1:(n-1)/2)'].*x+[x(2:n); 0];
end
and
function y = mfun(r,n)
y = r ./ [((n-1)/2:-1:1)'; 1; (1:(n-1)/2)'];
end
I tested it and it works great. My question is in both those functions what is the value for x since we never give it one?
Also shouldn't the call to gmres be written like this: (y in the #handle)
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
Function handles are one way to parametrize functions in MATLAB. From the documentation page, we find the following example:
b = 2;
c = 3.5;
cubicpoly = #(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
which results in:
x =
-1.0945
So what's happening here? fzero is a so-called function function, that takes function handles as inputs, and performs operations on them -- in this case, finds the root of the given function. Practically, this means that fzero decides which values for the input argument x to cubicpoly to try in order to find the root. This means the user just provides a function - no need to give the inputs - and fzero will query the function with different values for x to eventually find the root.
The function you ask about, gmres, operates in a similar manner. What this means is that you merely need to provide a function that takes an appropriate number of input arguments, and gmres will take care of calling it with appropriate inputs to produce its output.
Finally, let's consider your suggestion of calling gmres as follows:
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
This might work, or then again it might not -- it depends whether you have a variable called x in the workspace of the function eventually calling either afun or mfun. Notice that now the function handles take one input, y, but its value is nowhere used in the expression of the function defined. This means it will not have any effect on the output.
Consider the following example to illustrate what happens:
f = #(y)2*x+1; % define a function handle
f(1) % error! Undefined function or variable 'x'!
% the following this works, and g will now use x from the workspace
x = 42;
g = #(y)2*x+1; % define a function handle that knows about x
g(1)
g(2)
g(3) % ...but the result will be independent of y as it's not used.

How does one pass a function with some fixed argument as an argument in MATLAB

I want to pass a function that has arguments to another function that takes the function handler (pointer) as an argument, but some of the arguments to the function handler need to be fixed. How does one do this in MATLAB?
Concretely I want to minimize a function h(eta) using fminsearch(fun,x0). One obvious issue is that if I pass all the arguments in x0 it will minimize it with respect to all the arguments but that isn't what I want to do. What I really want to do is instead:
I have tried the following and it seems to work as far as I tested it:
function [ h ] = function_returner( x )
%
t = -10000;
h = #(eta)-10*x + t + eta^2;
end
and the script to test it:
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
returns the correct minimum and the correct value of x at which the minimum is obtained. The thing that I wanted to make sure is that the variables that are fixed of h indeed remain fixed after I returned the function handler. i.e. if h is passed around, how does one make sure that the variables don't change value just because they go into an environment that has the same variables names as in the function handler?
I also wrote:
x = inf;
t = inf;
eta = inf;
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
and it seems to go unaffected (i.e. it works as I want it to work). But just to be on the safe side, I was hoping there was not a some weird edge condition that this doesn't work.
You are worrying unnecessarily. :-) The thing is, when you create an anonymous function, all the outer variables that are used for its definition are frozen, so you don't need to worry that the function will change behavior behind your back via modified parameters. To test this, try this script:
a = 1;
b = 2;
f = #(u,v) u*a + v*b;
x = f(1,1); %// x is 3 = 1*1 + 1*2
a = 2;
b = 3;
g = #(w) f(w,a)
y = g(1); %// y is 5 = f(1,2) = 1*1 + 2*2

Error using fmincon matlab

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.