In order to refactor my MATLAB code, I thought I'd pass around functions as arguments (what MATLAB calls anonymous functions), inspired by functional programming.
However, it seems performance is hit quite severely. In the examples below, I compare different approaches. (The code snippet is wrapped in a function in order to be able to use subfunctions)
The result I get is 0 seconds for direct, almost 0 seconds using a subfunction, and 5 seconds using anonymous functions. I'm running MATLAB 7.7 (R2007b) on OS X 10.6, on a C2D 1.8 GHz.
Can anyone run the code and see what they get? I'm especially interested in performance on Windows.
function [] = speedtest()
clear all; close all;
function y = foo(x)
y = zeros(1,length(x));
for j=1:N
y(j) = x(j)^2;
end
end
x = linspace(-100,100,100000);
N = length(x);
%% direct
t = cputime;
y = zeros(1,N);
for i=1:N
y(i) = x(i)^2;
end
r1 = cputime - t;
%% using subfunction
t = cputime;
y = foo(x);
r2 = cputime - t;
%% using anon function
fn = #(x) x^2;
t = cputime;
y = zeros(1,N);
for i=1:N
y(i) = fn(x(i));
end
r3 = cputime-t;
[r1 r2 r3]
end
You're cheating with the nested function. :) The anonymous function is being called inside a loop, so you're measuring the cost of calling it 100,000 times. The nested function only gets called once, so its function call overhead is negligible. To compare the cost of calling anonymous vs named functions, you should have the nested function do the same work as the anonymous function and then call it from inside a loop, too.
I did that and still got similar results. The anonymous function is about 20 times slower.
However, you can still use function handles with non-anonymous functions, and that doesn't have the same performance hit as anonymous functions. This works with either nested functions (as with the foo in your original test) or non-nested subfunctions (which don't act as closures and may have less overhead).
function [] = speedtest()
function y = foo(x)
y = x^2;
end
r = struct;
...
%% using nested function through function handle
fn = #foo;
y = zeros(1,N);
t = cputime;
for i=1:N
y(i) = fn(x(i));
end
r.nested_handle = cputime - t;
...
%% using subfunction through function handle
fn = #subfunction_foo;
y = zeros(1,N);
t = cputime;
for i=1:N
y(i) = fn(x(i));
end
r.subfunction_handle = cputime - t;
...
end % end function speedtest
function y = subfunction_foo(x)
y = x^2;
end
I get this on R2009b in Windows.
>> speedtest
direct: 0
nested: 0.0469
nested_handle: 0.0781
subfunction: 0.0313
subfunction_handle: 0.0313
anonymous: 1.2344
Another way to look at it is to structure your code so it's "vectorized" and operates on arrays, reducing the number of function calls and the cost of the function call doesn't matter so much. That would be more idiomatic Matlab: typical performance advice is to ignore the cost of function calls and loops because you ought to be doing fewer calls on larger arguments anyway.
I can confirm your findings Grav. The speedtest function returns the following on my computer.
>> speedtest()
ans =
0 0.0313 1.3906
As a sidenote, the function cputime is not the best method for measuring computation time. Use the tic and toc functions instead. see link
These functions provides a much higher time resolution, and using them I obtain the following.
>> speedtest()
ans =
0.0062 0.0162 1.3495
Results from a Windows machine, Matlab 2009a
>> test
ans =
0 0.0156 1.1094
I faced the same issue as Gary, just thought it would be good to check Andrew's answer on a more recent version of Matlab (2014a) (Mac). The results first:
direct: 0.0722
anonymous: 0.3916
subfunction: 0.2277
And the code I used:
function []=SpeedTest()
fanon = #(x,y) x*x+y*y;
iter=1000000;
x=1:iter;
y=1:iter;
var1=nan(size(x));
var2=nan(size(x));
var3=nan(size(x));
timefor=struct('direct',nan,'anonymous',nan','subfunction',nan);
tic;
for i=1:iter
var1(i)=x(i)*x(i)+y(i)*y(i);
end
timefor.direct=toc;
tic;
for i=1:iter
var2(i)=fanon(x(i),y(i));
end
timefor.anonymous=toc;
tic;
for i=1:iter
var3(i)=fsub(x(i),y(i));
end
timefor.subfunction=toc;
display(timefor);
end
function [z]=fsub(x,y)
z=x*x+y*y;
end
Related
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)
I'm trying to write a function that uses Newton's Method to solve a system of nonlinear equations
Function:
[roots, count, resids, history] = Newtons(func,x0,tol)
with the following inputs and outputs.
I'm struggling with creating the function handle (the first input) and using it in the main function as well as understanding and generating the resids and history outputs. I would really appreciate some help with this function.
What I've done/tried so far: (I'm relatively new to Matlab and believe it is totally wrong and not worth looking at)
% function handle for the first input (func)
function [f, J] = jacobian(f, x)
n=length(x);
fx=f(x);
step=1e-10;
for i=1:n
xstep = x;
xstep(i)=x(i)+step;
J(:,i)=(f(xstep)-fx)/step;
end
end
function [roots, count, resids, history] = Newtons(func,x0,tol)
func = #jacobian;
if nargin == 2
tol = 10e-10;
end
MAXIT = 50;
xx = x0;
N = 0;
while N < 50
JJ = func(2);
end
I am currently involved in a group project where we have to conduct portfolio selection and optimisation. The paper being referenced is given here: (specifically page 5 and 6, equations 7-10)
http://faculty.london.edu/avmiguel/DeMiguel-Nogales-OR.pdf
We are having trouble creating the optimisation problem using M-Portfolios, given below
min (wrt w,m) (1/T) * sum_(rho)*(w'*r_t - m) (Sorry I couldn't get the formatting to work)
s.t. w'e = 1 (just a condition saying that all weights add to 1)
So far, this is what we have attempted:
function optPortfolio = portfoliofminconM(returns,theta)
% Compute the inputs of the mean-variance model
mu = mean(returns)';
sigma = cov(returns);
% Inputs for the fmincon function
T = 120;
n = length(mu);
w = theta(1:n);
m = theta((n+1):(2*n));
c = 0.01*ones(1,n);
Aeq = ones(1,(2*n));
beq = 1;
lb = zeros(2,n);
ub = ones(2,n);
x0 = ones(n,2) / n; % Start with the equally-weighted portfolio
options = optimset('Algorithm', 'interior-point', ...
'MaxIter', 1E10, 'MaxFunEvals', 1E10);
% Nested function which is used as the objective function
function objValue = objfunction(w,m)
cRp = (w'*(returns - (ones(T,1)*m'))';
objValue = 0;
for i = 1:T
if abs(cRp(i)) <= c;
objValue = objValue + (((cRp(i))^2)/2);
else
objValue = objValue + (c*(abs(cRp(i))-(c/2)));
end
end
The problem starts at our definitions for theta being used as a vector of w and m. We don't know how to use fmincon with 2 variables in the objective function properly. In addition, the value of the objective function is conditional on another value (as shown in the paper) and this needs to be done over a rolling time window of 120 months for a total period of 264 months.(hence the for-loop and if-else)
If any more information is required, I will gladly provide it!
If you can additionally provide an example that deals with a similar problem, can you please link us to it.
Thank you in advance.
The way you minimize a function of two scalars with fmincon is to write your objective function as a function of a single, two-dimensional vector. For example, you would write f(x,y) = x.^2 + 2*x*y + y.^2 as f(x) = x(1)^2 + 2*x(1)*x(2) + x(2)^2.
More generally, you would write a function of two vectors as a function of a single, large vector. In your case, you could rewrite your objfunction or do a quick hack like:
objfunction_for_fmincon = #(x) objfunction(x(1:n), x(n+1:2*n));
I have a simple function as below:
function dz = statespace(t,z)
dz = A*z + B*k*z
end
My main script is :
clear all;close all;format short;clc;
% step 1 -- input system parameters
% structure data
M1 = 1; M2= 1; M3= 1; %Lumped Mass(Tons)
M= diag([M1,M2,M3]);
k(1)= 980; k(2)= 980; k(3)= 980; %Stiffness Coefficient(KN/M)
K = zeros(3,3);
for i=1:2
K(i,i)=k(i)+k(i+1);
end
K(3,3)=k(3);
for i=1:2
K(i,i+1)=-k(i+1);
end
for i=2:3
K(i,i-1)=-k(i);
end %Stiffness Matrix(KN/M)
c(1)= 1.407; c(2)= 1.407; c(3)= 1.407; %Damping Coefficient(KN.sec/M)
C = zeros(3,3);
for i=1:2
C(i,i)=c(i)+c(i+1);
end
C(3,3)=c(3);
for i=1:2
C(i,i+1)=-c(i+1);
end
for i=2:3
C(i,i-1)=-c(i);
end %Damping Matrix(KN.sec/M)
A = [zeros(3) eye(3);-inv(M)*K -inv(M)*C]
H = [1;0;0]
B = [0;0;0;inv(M)*H]
k = [-1 -1 -1 -1 -1 -1]
t = 0:0.004:10;
[t,z] = ode45(statespace,t);
When I run my main script it comes with following error:
Undefined function or variable 'A'.
Error in statespace (line 2)
dz = A*z + B*k*z
As you can see I defined A in main script. Why this problem happening?
There multiple things wrong with your code. First, you need to supply the values of A and B to your function but as you are invoking it (incorrectly without the # and additional parameter y0 as I commented below) in the toolbox ode45, you have to keep just two parameters so you cannot supply A and B as additional parameters. If you define A and B within your function or share them via global variables you will get further. However, as noted below the definitions don't seem to be correct as A * z and B * k * z don't have the same dimensions. z is a scalar so B * k needs to be same size and shape as A which currently it is not.
Edit from:
As Jubobs suggested change your function's parameters to include A, B and k. Also you don't need t as it is never used in the function. So:
function dz = statespace(A, B, k, z)
dz = A*z + B*k*z
end
As others have pointed out, A, B and k are not defined in the function workspace, so you either need to define them again (ugly, not recommended), declare them as global variables (slightly better, but still not good practice), or pass them as arguments to your function (the better solution). However, because you then want to use the function with ode45, you need to be a bit careful with how you do it:
function dz = statespace(t,z,A,B,k)
dz = A*z + B*k*z
end
and then the call to ode45 would like this:
[t,z] = ode45(#(t,z)statespace(t,z,A,B,k),[0 Tf],z0); % where Tf is your final time and z0 your initial conditions
See Error using ode45 and deval for a similar problem.
I have this MATLAB code as part of my project, as per the information I got from the professor's report, most of the time is spent in the while loop. Any suggestions regarding how can
I improve the efficiency? Generally, how can I make the for loops more efficient?
% p is 2D matrix of big size
s=size(p);
pp=p;
p=zeros(s(1),s(2));
while(norm(p-pp)>0.05 )
p=pp;
for n=1:N
z=0;
for miu=1:C
z = z + p(n,miu) * funQ(n,miu,p,R,N,C); % call function funQ
end
for lambda=1:C
pp(n,lambda) = (p(n,lambda) * funQ(n,lambda,p,R,N,C))/z; % call function funQ
end
end
end
I don't know what funQ does but if it is amenable to vectorization then, you can try the following:
Replace
for miu=1:C
z = z + p(n,miu) * funQ(n,miu,p,R,N,C); % call function funQ
end
With
miu=1:C
z = sum(p(n,miu) * funQ(n,miu,p,R,N,C)); % call function funQ
Similarly,
Replace
for lambda=1:C
pp(n,lambda) = (p(n,lambda) * funQ(n,lambda,p,R,N,C))/z; % call function funQ
end
With
pp(n,:) = (p(n,lambda) * funQ(n,lambda,p,R,N,C))/z; % call function funQ