I'm a bit of a beginner at matlab so I'm having a some trouble understanding differentiating a dot operator and a for loop.
Given a Column vector (it's a pretty long column vector). We are given the following equation...
f(x)=0.2*x^3 + (1/3)*(x^2-1) + 2*cos(x)+3*cos(10x)
I need to use the method of dot operator and a for loop to create 2 plots and also the time (using tic, toc)
However, with dot operator does it mean using
.^ or .*
in the equation? and if this is the case, wouldn't I still need to use that in order to make a for loop?
Any clarification or assistance would be greatly appreciated! I don't really understand how I would write these...
The operators prefixed with a dot are called element-wise operators. It performs the operation on each element of the arrays (after checking that all involved arrays have the same number of elements). So you don't need a for-loop with using this operator, this is implied. This is called vectorization.
For example:
C = A.*B;
is equivalent to:
C = zeros(size(C));
for i=1:numel(A)
C(i) = A(i)*B(i);
end
but the first one is heavily optimized. So it's strongly advised to use vectorized operators as much as possible.
your x is an vector of defined length and step size, for example it can be:
x = 1:1:100 %generates 1,2,3....100
x = 1:0.1:10 %generates 0.1,0.2,0.3....10
so if you want to write a function of x (which is a vector), for speed purposes, you might want to use the dot-product denoted by .* in matlab. In your case you can do:
f(x)=0.2.*x.^3 + (1/3).*(x.^2-1) + 2.*cos(x) +3.*cos(10x)
The more costly way to compute is to use a for loop:
for x = 1:100
f(x)=0.2*x^3 + (1/3)*(x^2-1) + 2*cos(x) +3*cos(10x)
end
figure
plot(f)
The problem in your for loop is that you overwrite on the value of fx2, in each iteration you give it a new value but it always remain of size 1x1. For minimal change in your code you could do something like:
fx2=[];
for x = A(:,4)
fx2 = [fx2 0.2*x^3+(1/3)*(x^2-1)+2*cos(x)+3*cos(10*x)];
end
plot(x,fx2)
that way, you add a new value in the vector fx2 at each iteration instead of overwriting, (fx2 would be 1x1 then 1x2...). However be aware that this is not optimized at all because well there is a for loop that can be avoided but also because fx2's size changes at each iteration. Another better solution would be to predefine fx2 with the right size and then in the loop, change its ith value at the ith iteration.
Related
I am trying to compute this
in MATLAB but the code requires about 8 hours to compile. In particular e, Ft=[h(t);q(t)] and Omega are 2x1 matrices (e' is 1x2), Gamma is a 2x2 matrix and n=30. Can someone help me to optimize this code?
I tried in this way:
aux=[0;0];
for k=0:29
for j=1:k-1
aux=[aux Gamma^j*Omega];
end
E(t,k+1)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
end
Vix=1/30*sum(E,2);
EDIT
now I changed into this and it is faster, but I am not sure that I am applying correctly the formula in the picture...
for t=2:T
% 1. compute today's volatility
csi(t) = log(SP500(t)/SP500(t-1))-r(t)+0.5*h(t);
q(t+1) = omega+rho*q(t)+phi*((csi(t)-lambda*sqrt(h(t)))^2-h(t));
h(t+1) = q(t)+alpha*((csi(t)-lambda*sqrt(h(t)))^2-q(t))+beta*(h(t)-q(t));
for k=1:30
aux=zeros(2,k);
for j=0:k-1
aux(:,j+1)=Gamma^j*Omega;
end
E(t,k)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
end
end
Vix(2:end)=1/30*sum(E(2:end,:),2);
(I don't need Vix(1))
Here are some reasons I can think of:
REPEATED COPYING(No preallocation) The main reason for the long run time is the line aux=[aux Gamma^j*Omega] line, in which an array is concatenated at every loop iteration. MATLAB's debugger should have flagged this for you in its editor and should have cited that "memory preallocation" using zeros should be implemented.
Essentially, when one concatenates arrays this way, MATLAB is internally making copies of the array at every loop iteration, thus, in addition to the math operations copying is taking place. As the array grows, the copying operations become ever more expensive. This is avoided by preallocation, which consists of predefining the size of the storage array (in this case the variable aux) so that MATLAB doesn't have to keep on allocating space on the go. Try:
aux = zeros(2, 406); %Creates a 2 by 406 array. I explain how I get 406 below:
p = 0; %A variable that indexes the columns of aux
for k=0:29
for j=1:k-1
p = p+1; %Update column counter
aux(:,p) = Gamma^j*Omega; % A 2x2 matrix multiplied by a 2x1 matrix yields a 2x1.
end
E(t,k+1)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
end
Vix=1/30*sum(E,2);
Now, MATLAB simply overwrites the individual elements of aux instead of copying aux, and concatenating it with Gamma^j*Omega, and then overwriting aux. Essentially, the above makes MATLAB allocate space for aux ONCE instead of 406 times. I figured out that aux ends up being a 2 by 406 array for the n=30 case in the end by running this code:
p = 0;
for k = 0:29
for j = 1:k-1
p = p + 1;
end
end
To know the final size of aux for other values of n you should see if a formula for it is available (or derive your own).
LOOPING TRANSPOSITION OF A CONSTANT?
Next, e'. As you may know, ' is the transpose operation. From your sample code, the variable e is not edited inside the for loops, yet you have the ' operator inside the outer for loop. If you perform the transpose operation once outside the outer for loop you save yourself the expense of transposing it at every loop iteration.
RUNNING TOTAL
As a final note, I would suggest replacing sum(aux,2) with a variable that keeps a running total. This is because currently, this makes MATLAB sum over the entirety of aux at every loop iteration.
Hope this helps mate.
I'm trying to vectorize one function in Matlab, but I have a problem with assigning values.
function [val] = clenshaw(coeffs,x)
b=zeros(1,length(coeffs)+2);
for k=length(coeffs):-1:2
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
end
val=coeffs(1)-b(3)+b(2).*x;
The purpose of this function is to use Clenshaw's algorithm to compute a value of one polynomial with coefficients "coeffs" at point x.
It work fine when x is a single value, but I'd like it to work with vector of arguments too.
When I try to pass a vector I get an error:
Unable to perform assignment because the left
and right sides have a different number of
elements.
Error in clenshaw (line 7)
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
I understand that there is a problem, because I'm trying to assign vector to a scalar variable b(k).
I tried making b a matrix instead of a vector, however I still cannot get the return output I'd like to have which would be a vector of values of this function at points from vector x.
Thank you for helping and sorry if something isn't entirely clear, because English is not my native language.
The vectorized version of your function looks like this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(x),length(coeffs)+2);
for k=length(coeffs):-1:2
b(:,k)=coeffs(k)-b(:,k+2)+2*b(:,k+1).*transpose(x);
end
val=coeffs(1)-b(:,3)+b(:,2).*transpose(x);
end
b needs to be a matrix. In your loop, you have to perform every operation per row of b. So you need to write b(:,k) instead of b(k). Since b(:,k) is a vector and not a scalar, you also have to be careful with the dimensions when using the .* operator. To get the correct results, you need to transpose x. The same goes for the calculation of val. If you don't like the transposition, just swap the rows and cols of b and you get this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(coeffs)+2, length(x));
for k=length(coeffs):-1:2
b(k,:)=coeffs(k)-b(k+2,:)+2*b(k+1,:).*x;
end
val=coeffs(1)-b(3,:)+b(2,:).*x;
end
However, the first version returns a column vector and the second a row vector. So you might need to transpose the result if the vector type is important.
Good evening everyone,
I want to create a function
f(x) = [f1(x), f2(x), ... , fn(x)]
in MatLab, with an arbitrary form and number for the fi. In my current case they are meant to be basis elements for a finite-dimensional function space, so for example a number of multi variable polynomials. I want to able to be able to set form (e.g. hermite/lagrange polynomials, ...) and number via arguments in some sort of "function creating" function, so I would like to solve this for arbitrary functions fi.
Assume for now that the fi are fi:R^d -> R, so vector input to scalar output. This means the result from f should be a n-dim vector containing the output of all n functions. The number of functions n could be fairly large, as there is permutation involved. I also need to evaluate the resulting function very often, so I hope to do it as efficiently as possible.
Currently I see two ways to do this:
Create a cell with each fi using a loop, using something like
funcell{i}=matlabFunction(createpoly(degree, x),'vars',{x})
and one of the functions from the symbolic toolbox and a symbolic x (vector). It is then possible to create the desired function with cellfun, e.g.
f=#(x) cellfun(#(v) v(x), funcell)
This is relatively short, easy and what can be found when doing searches. It even allows extension to vector output using 'UniformOutput',false and cell2mat. On the downside it is very inefficient, first during creation because of matlabFunction and then during evaluation because of cellfun.
The other idea I had is to create a string and use eval. One way to do this would be
stringcell{i}=[char(createpoly(degree, x)),';']
and then use strjoin. In theory this should yield an efficient function. There are two problems however. The first is the use of eval (mostly on principle), the second is inserting the correct arguments. The symbolic toolbox does not allow symbols of the form x(i), so the resulting string will not contain them either. The only remedy I have so far is some sort of string replacement on the xi that are allowed, but this is also far from elegant.
So I do have ways to do what I need right now, but I would appreciate any ideas for a better solution.
From my understanding of the problem, you could do the straightforward:
Initialization step:
my_fns = cell(n, 1); %where n is number of functions
my_fns{1} = #f1; % Assuming f1 is defined in f1.m etc...
my_fns{2} = #f2;
Evaluation at x:
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
For example if you put it in my_evaluate.m:
function z = my_evaluate(my_fns, x)
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
How might this possibly be sped up?
Depends on if you have special structure than can be exploited.
Are there calculations common to some subset of f1 through fn that need not be repeated with each function call? Eg. if the common calculation step is costly, you could do y = f_helper(x) and z(i) = fi(x, y).
Can the functions f1...fn be vector / matrix friendly, allowing evaluation of multiple points with each function call?
The big issue is how fast your function calls f1 through fn are, not how you collect the results from those calls in a vector.
I have recently been tasked with using a first derivative filter on an image of myself. The instructor said that I should first fix the value of y and preform f(x+1) - f(x) on the rows and then fix the new "X" values and preform f(y+1)-f(y) on the columns.
Note: I have been asked to do this task manually, not using filter2() or any other programmed function, so please do not suggest that I use filter2() or similar. Thanks!
I tried calling up all the pixels and subtracting each successive one by doing
fid = fopen('image.raw')
myimage = fread(fid,[512 683], '*int8')
fclose(fid)
imsz = size(myimage)
x = imsz(1)
for I = 1:512
for J = 1:683
X(I) - X(I-1) = XX
But it doesnt seem to work, and I dont quite understand why. If you could help me, or point me in the right direction, I would be very appreciative.
First of all, your code is syntatically incorrect:
There is no end statement to any of your loops, and besides, you don't even need loops here.
You seem to read your image into the variable myimage, but you're using an undefined variable X when attempting to calculate the derivative.
The order of your assignment statements is reversed. The variable you wish to assign to should be written in the left hand part of the assignement.
I strongly suggest that you read online tutorials and get yourself familiar with MATLAB basics before taking on more complicated tasks.
As to your specific problem:
MATLAB encourages vectorized operations, i.e operations on entire arrays (vectors or matrices) at once. To subtract adjacent values in an array, what you're basically doing is subtracting two arrays, shifted by one element with respect to each other. For one dimensional arrays, that would translate in MATLAB to:
a(2:end) - a(1:end-1)
where a is your array. The end keyword specifies the last index in the array.
To compute the derivative of an image (a 2-D matrix), you need to decide along which axis you want to perform that operation. To approximate the derivate along the y-axis, do this:
X(2:end, :) - X(1:end-1, :)
You can verify that this gives you the same result as diff(X, 1) (or simply diff(X)). To compute the approximate derivative along the x-axis, which is equivalent to diff(X, 2), do this:
X(:, 2:end) - X(:, 1:end-1)
The colon (:) is the same as writing 1:end as the array subscript for the corresponding dimension.
If your filtered image is div then
for Y = 1:682
for X = 1:511
div(X, Y) = myimage(X + 1, Y + 1) - myimage(X,Y);
end
end
Remember the last row and the last column are not filtered!
I want to apply a function to all columns in a matrix with MATLAB. For example, I'd like to be able to call smooth on every column of a matrix, instead of having smooth treat the matrix as a vector (which is the default behaviour if you call smooth(matrix)).
I'm sure there must be a more idiomatic way to do this, but I can't find it, so I've defined a map_column function:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
which I can call with:
smoothed = map_column(input, #(c) (smooth(c, 9)));
Is there anything wrong with this code? How could I improve it?
The MATLAB "for" statement actually loops over the columns of whatever's supplied - normally, this just results in a sequence of scalars since the vector passed into for (as in your example above) is a row vector. This means that you can rewrite the above code like this:
function result = map_column(m, func)
result = [];
for m_col = m
result = horzcat(result, func(m_col));
end
If func does not return a column vector, then you can add something like
f = func(m_col);
result = horzcat(result, f(:));
to force it into a column.
Your solution is fine.
Note that horizcat exacts a substantial performance penalty for large matrices. It makes the code be O(N^2) instead of O(N). For a 100x10,000 matrix, your implementation takes 2.6s on my machine, the horizcat one takes 64.5s. For a 100x5000 matrix, the horizcat implementation takes 15.7s.
If you wanted, you could generalize your function a little and make it be able to iterate over the final dimension or even over arbitrary dimensions (not just columns).
Maybe you could always transform the matrix with the ' operator and then transform the result back.
smoothed = smooth(input', 9)';
That at least works with the fft function.
A way to cause an implicit loop across the columns of a matrix is to use cellfun. That is, you must first convert the matrix to a cell array, each cell will hold one column. Then call cellfun. For example:
A = randn(10,5);
See that here I've computed the standard deviation for each column.
cellfun(#std,mat2cell(A,size(A,1),ones(1,size(A,2))))
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Of course, many functions in MATLAB are already set up to work on rows or columns of an array as the user indicates. This is true of std of course, but this is a convenient way to test that cellfun worked successfully.
std(A,[],1)
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Don't forget to preallocate the result matrix if you are dealing with large matrices. Otherwise your CPU will spend lots of cycles repeatedly re-allocating the matrix every time it adds a new row/column.
If this is a common use-case for your function, it would perhaps be a good idea to make the function iterate through the columns automatically if the input is not a vector.
This doesn't exactly solve your problem but it would simplify the functions' usage. In that case, the output should be a matrix, too.
You can also transform the matrix to one long column by using m(:,:) = m(:). However, it depends on your function if this would make sense.