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
Related
I'm trying to avoid the function tf() from Matlab since it requires specific toolboxes to run.
The transfer function that I'm using is quite simple. Is the model for a heatsink temperature.
H(s) = (Rth/Tau)/(s + 1/Tau)
In order to avoid the tf() function, I've tried to substitute the transfer function with a state space model coded in Matlab.
I've used the function ss() to get te values of A,B,C and D. And I've tried to compare the results from tf() and my function.
Here's the code that I've used:
Rth = 8.3220e-04; % ºC/W
Tau = 0.0025; % s
P = rand(1,10)*1000; % Losses = input
t = 0:1:length(P)-1; % Time array
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Transfer function %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
H = tf([0 Rth/Tau],[1 1/Tau]);
Transfer_func = lsim(H,P,t);
figure, plot(Transfer_func),grid on,grid minor, title('Transfer func')
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% My función ss %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
% Preallocate for speed
x(1:length(P)) = 0;
y(1:length(P)) = 0;
u = P;
sys = ss(H);
A = sys.A;
B = sys.B;
C = sys.C;
D = sys.D;
for k = 1:length(u)
x(k+1) = A*x(k) + B*u(k);
y(k) = C*x(k) + D*u(k);
end
figure, plot(y), grid on,grid minor, title('With my función')
I know that the values from A,B,C and D are ok, since I've checked them using
H = tf([0 Rth/Tau],[1 1/Tau]);
sys = ss(H);
state_space_sys = ss(sys.A,sys.B,sys.C,sys.D);
state_space = lsim(state_space_sys,P,t);
figure, plot(state_space),grid on,grid minor, title('State space')
As you can see, the results obtained from my funtion and the function tf() are very different.
Is there any mistakes on the approach?
If it's not possible to avoid the tf() function in this way, is there any other way?
At the end, I found another solution. I'm posting this here, so if someone has the same problem, can use this approach.
If you take the transfer function, and develop it, we reach to the following expresion
H(s) = deltaT(s)/P(s) = (Rth/Tau)/(s + 1/Tau)
deltaT(s) * (s + 1/Tau) = (Rth/Tau) * P(s)
deltaT(s) * s = (Rth/Tau) * P(s) - deltaT(s)/Tau
Now, we know that 1/s is equal to integrate. So in the end, we have to integrate the right side of the equation. The code would be like this.
Cth = Tau/Rth;
deltaT = zeros(size(P));
for i = 2:length(P)
deltaT(i) = (1/Cth * (P(i)-deltaT(i-1)/Rth))*(time(i)-time(i-1)) + deltaT(i-1);
end
This integral has the same output as the function tf().
I am trying to learn Matlab as someone with an R background. I have the following program written for an iteration that I would like to repeat until the specified condition is met. I believe that I have all of code written for Matlab, except for the command that the iteration should repeat infinitely times until the condition is met (denoted below).
Would someone be able to tell me how to translate this to Matlab syntax? I think that I should be using a while-loop, but I'm not sure since the iterations should continue until a condition is met rather than continuing while some condition is met. Is there an until equivalent? Thank you!
function xn = newton_v2(f,fd,x0,tol)
% newton iteration
xn = x0;
repeat{ %%% 'This is how I would begin the repeat command in R'
% evaluate function and derivative
fxn = feval(f,xn);
fdxn = feval(fd,xn);
% newton iteration step
xnp1 = xn - fxn/fdxn;
if(abs(xnp1 - xn)/abs(xnp1) < tol)
xn<-xnp1
end
% update
xn = xnp1;
} %%% 'This is how I would end the repeat command in R'
end
Also, please let me know if you see anything else wrong in my Matlab code.
I'm not great with R syntax, but you would have two options 1.pass in an array of values to a matlab for loop and iterate through them. Then graph it to find the best solution and try to get more precise from there 2. Set a condition on a while loop. I think you are looking more for a while loop, so you'll put your condition in there. It may be more computationally heavy, but depending on the funct. may be fine.
I do the Newton method with a while loop though the recursive version in the answer by hamaney is interesting. I do this by passing a function handle, initial guess and tolerance to a function.
function x1 = NewtonMethod(f,x,tol)
% dtol is calculated from eps based on the function handle...not shown
xi = f(x); % initial guess
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
while (abs(x1 - x) < tol)
x = x1;
xi = f(x);
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
end
end
There is a problem with this approach. If the initial guess is poorly conditioned or the function unbounded it is possible for this to be an infinite loop. Because of this I include a loop counter and normally break when that counter reaches a maxSteps value.
Adding the inifinite loop protection looks something like this.
xi = f(x); % initial guess
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
loopCounter = 0;
while (abs(x1 - x) < tol)
x = x1;
xi = f(x);
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
loopCounter = loopCounter + 1;
if loopCounter > maxSteps
% include warning message
break
end
end
Do you mean the syntax for the for loop?
If you are trying to create Newton's method, see my own implementation script
y is the function
x0 - first initial value
n - # of xns to approximate
function Xn = newtonsMethod (y,x0,n,startDomain,endDomain)
%the tangent line at any point on the curve
y1 = matlabFunction(diff(sym(y)));
Xn = x0;
x= linspace(startDomain,endDomain,1000);
%recursive call for the newton formula
for i = 1 : n
%find the tangent line
L =#(x)(y1(Xn).*(x-Xn)+y(Xn));
%find the root
Xn = Xn - (y(Xn)./y1(Xn));
end
end
This might be not the best way to do it. but it could help!
I have a function provided by the instructor, which is not available for us to see the inner workings.
This function basically integrates whatever you input it.
Here is our loop:
for i = 1:length(time)-1
intdefValues(i) = intdef(t, r, time(i), time(i+1));
end
We are trying to do this:
intdefValues = intdef(t, r, time(1:end-1), time(2:end));
Are we wrong? Is there anyway that the function doesn't support vectors?
Syntax for the function in case you are curious;
intdef(t, x, a, b)
Where t = time vector, x = function, and a,b are the start / end parameters.
tic(); % ------------
% TEST ALSO
% PERFORMANCE:
% prepare another "vectorOfTimeENDs",
% aligned with your loop-ing strategy
% for a fully vectorised call
startsVector = time(1:end-1); % just a syntax-sugar, may omit for speed == time(1:end-1)
endsVector = time(2:end); % this one is important
intdefValues = intdef( tVector, rFunction, startsVector, endsVector );
toc()
% ---------------------------------------------------------------------------
tic(); % COMPARE WITH THE ORIGINAL FOR/LOOP:
for i = 1:length(time)-1
intdefValues(i) = intdef( tVector, rFunction, time(i), time(i+1) );
end
toc()
I have tried to implement Laplace equation in my matlab code sequence as shown below. I created this LaplaceExplicit.m and thus used another function numgrid in the same. However, it shows error as "Input variable n is undefined". What should be done? The code is as below-
function [x,y,T]= LaplaceExplicit(n,m,Dx,Dy)
echo off;
numgrid(n,m);
R = 5.0;
T = R*ones(n+1,m+1); % All T(i,j) = 1 includes all boundary conditions
x = [0:Dx:n*Dx];y=[0:Dy:m*Dy]; % x and y vectors
for i = 1:n % Boundary conditions at j = m+1 and j = 1
6
T(i,m+1) = T(i,m+1)+ R*x(i)*(1-x(i));
T(i,1) = T(i,1) + R*x(i)*(x(i)-1);
end;
TN = T; % TN = new iteration for solution
err = TN-T;
% Parameters in the solution
beta = Dx/Dy;
denom = 2*(1+beta^2);
% Iterative procedure
epsilon = 1e-5; % tolerance for convergence
imax = 1000; % maximum number of iterations allowed
k = 1; % initial index value for iteration
% Calculation loop
while k<= imax
for i = 2:n
for j = 2:m
TN(i,j)=(T(i-1,j)+T(i+1,j)+beta^2*(T(i,j-1)+T(i,j+1)))/denom;
err(i,j) = abs(TN(i,j)-T(i,j));
end;
end;
T = TN; k = k + 1;
errmax = max(max(err));
if errmax < epsilon
[X,Y] = meshgrid(x,y);
figure(2);contour(X,Y,T',20);xlabel('x');ylabel('y');
title('Laplace equation solution - Dirichlet boundary conditions Explicit');
figure(3);surfc(X,Y,T');xlabel('x');ylabel('y');zlabel('T(x,y)');
title('Laplace equation solution - Dirichlet boundary conditions Explicit');
fprintf('Convergence achieved after %i iterations.\n',k);
fprintf('See the following figures:\n');
fprintf('==========================\n');
fprintf('Figure 1 - sketch of computational grid \n');
fprintf('Figure 2 - contour plot of temperature \n');
fprintf('Figure 3 - surface plot of temperature \n');
return
end;
end;
fprintf('\n No convergence after %i iterations.',k);
MATLAB will go through a standard look-up procedure to work out what it represents. First, is it a local variable? If not, is a function or script (command)? This also requires looking in a prescribed set of places. The simple version is: first look in the current directory, then look in the directories specified by the MATLAB path (in order).
Hence, if you write square_table.m and save it in C:\work\Moe\MATLAB then that directory needs to be either the current working directory on on the MATLAB path. Otherwise you will get an error ("undefined function or variable").
Sorry people, got my questions answered.. it was just some problem with initialisation and calling a function defined in another .m file. Resolved it and now the code's working fine.. :)
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