Indexing arrays in matlab from 0 - matlab

For the math class I'm taking, I have to write a program to compute the FFT of a function. We have been given the code in class. I'm having problems entering the code in matlab because the index starts at 0. This is the code given in class:
Input: q,N,f(k)
Output: d(k)
sigma(0) = 0
for r = 0 to q-1
for k = 0 to (2^r)-1
sigma((2^r)+k) = sigma(k) + 2^(q-1-k)
end
end
for k = 0 to N-1
d(k) = f(sigma(k))/N
end
for r = 0 to q-1
M = 2^r
Theta = e^(-i*pi()/M)
for k = 0 to M-1
for j = 0 to 2^(q-1-r)-1
x = theta^(k)*d(2*j*M+k)-x
d(2*j*m+k) = d(2*j*M+k)+x
end
end
end
Normally this would not be hard to implement but, the indicies are throwing me off. How do I write this code starting the loops at index 1 instead of 0(the program has to be written in Matlab)? Normally I would just manually calculate the first term(0 term) and put it outside the loop and then, shift the loop by one index. This problem however is not that simple. Thanks.

Just add one whenever you're indexing into an array. For example:
sigma((2^r)+k+1) = sigma(k+1) + 2^(q-1-k)
Also, use 1i when you mean sqrt(-1) since it's clearer, safer, since you can overwrite the meaning of i or j accidentally, and faster.

i would do every array index as "i array index" and then immediately change array index to be i array index - 1. you can then use array index for the mathematical portion and i*array index* to index specified arrays.
example:
instead of
for i = 0:n
sum = sum + i*array(i);
end
i would do
for ii = 1:n+1
i = ii-1;
sum = sum + i*array(ii);
end
EDIT: incredibly stupid typo: ii should go from 1:n+1 - that was the entire point of my change!

Related

Not sure what to do about error message "Conversion to double from cell is not possible."

I'm writing a program that finds the indices of a matrix G where there is only a single 1 for either a column index or a row index and removes any found index if it has a 1 for both the column and row index. Then I want to take these indices and use them as indices in an array U, which is where the trouble comes. The indices do not seem to be stored as integers and I'm not sure what they are being stored as or why. I'm quite new to Matlab (but thats probably obvious) and so I don't really understand how types work for Matlab or how they're assigned. So I'm not sure why I',m getting the error message mentioned in the title and I'm not sure what to do about it. Any assistance you can provide would be greatly appreciated.
I forgot to mention this before but G is a matrix that only contains 1s or 0s and U is an array of strings (i think what would be called a cell?)
function A = ISClinks(U, G)
B = [];
[rownum,colnum] = size(G);
j = 1;
for i=1:colnum
s = sum(G(:,i));
if s == 1
B(j,:) = i;
j = j + 1;
end
end
for i=1:rownum
s = sum(G(i,:));
if s == 1
if ismember(i, B)
B(B == i) = [];
else
B(j,:) = i;
j = j+1;
end
end
end
A = [];
for i=1:size(B,1)
s = B(i,:);
A(i,:) = U(s,:);
end
end
This is the problem code, but I'm not sure what's wrong with it.
A = [];
for i=1:size(B,1)
s = B(i,:);
A(i,:) = U(s,:);
end
Your program seems to be structured as though it had been written in a language like C. In MATLAB, you can usually substitute specialized functions (e.g. any() ) for low-level loops in many cases. Your function could be written more efficiently as:
function A = ISClinks(U, G)
% Find columns and rows that are set in the input
active_columns=any(G,1);
active_rows=any(G,2).';
% (Optional) Prevent columns and rows with same index from being simultaneously set
%exclusive_active_columns = active_columns & ~active_rows; %not needed; this line is only for illustrative purposes
%exclusive_active_rows = active_rows & ~active_columns; %same as above
% Merge column state vector and row state vector by XORing them
active_indices=xor(active_columns,active_rows);
% Select appropriate rows of matrix U
A=U(active_indices,:);
end
This function does not cause errors with the example input matrices I tested. If U is a cell array (e.g. U={'Lorem','ipsum'; 'dolor','sit'; 'amet','consectetur'}), then return value A will also be a cell array.

Storing data from obtained from loop

Suppose a MATLAB program is written as:
c=5;
a=4.5;
m=14;
for i=1:14
a=c*a;
end
How do I store the values of a? I wish to use the values of a later.
You need to store previous values of a in an array. You can pre-allocate the array outside of your loop and then fill it each time through your loop.
a = zeros(1, 15);
a(1) = 4.5;
for k = 1:14
a(k + 1) = c * a(k);
end
last_a = a(end);
A short form of #Suever's answer, can be written like that:
c=5;
a=4.5*c.^(0:14);
The results are:
a=
4.50000000000000 22.5000000000000 112.500000000000 562.500000000000 2812.50000000000 14062.5000000000 70312.5000000000 .......

MATLAB list manipulation

Consider I have a code segment as follows:
Case 1
n = 20;
for i = 2 : n
mat = rand([2,i]);
mat = [mat, mat(:,1)]; %add the first column to the last
%feed the variable 'mat' to a function
end
Case 2
n = 10;
list = [];
for i = 1 : n
a = rand([2,1]);
b = rand([2,2])
list = [list, [a,b]];
end
In this way, MATLAB gives the below suggestion:
The variable 'mat' appears to change size on every loop. Consider preallocating for speed up.
The variable 'list' appears to change size on every loop. Consider preallocating for speed up.
I am a MATLAB newconer, So I would like to know how to deal with this issue. How to do this in native MATLAB style? Thanks in advance.
I'll focus on the second case, as it's the only one that makes sense:
n = 10;
list = [];
for i = 1 : n
a = rand([2,1]);
b = rand([2,2])
list = [list, [a,b]];
end
That you are doing here, for each loop, is to create two vectors with random numbers, a and b. a has dimension 2x1, and b has dimension 2x2. Then, you concatenate these two, with the matrix list.
Note that each call to rand are independent, so rand(2,3) will behave the same way [rand(2,2), rand(2,1)] does.
Now, since you loop 10 times, and you add rand(2,3) every time, you're essentially doing [rand(2,2), rand(2,1), rand(2,2), rand(2,1) ...]. This is equivalent to rand(2,30), which is a lot faster. Therefore, "Consider preallocating for speed up."
Now, if your concatenations doesn't contain random matrices, but are really the output from some function that can't output the entire matrix you want, then preallocate and insert it to the matrix using indices:
Let's define a few functions:
function x = loopfun(n)
x = n*[1; 2];
end
function list = myfun1(n)
list = zeros(2, n);
for ii = 1:n
list(:,ii) = loopfun(ii);
end
end
function list = myfun2(n)
list = [];
for ii = 1:n
list = [list, loopfun(ii)];
end
end
f1 = #() myfun1(100000); f2 = #() myfun2(100000);
fprintf('Preallocated: %f\nNot preallocated: %f\n', timeit(f1), timeit(f2))
Preallocated: 0.141617
Not preallocated: 0.318272
As you can see, the function with preallocation is twice as fast as the function with an increasing sized matrix. The difference is smaller if there are few iterations, but the general idea is the same.
f1 = #() myfun1(5); f2 = #() myfun2(5);
fprintf('Preallocated: %f\nNot preallocated: %f\n', timeit(f1), timeit(f2))
Preallocated: 0.000010
Not preallocated: 0.000018

MATLAB: Using a for loop within another function

I am trying to concatenate several structs. What I take from each struct depends on a function that requires a for loop. Here is my simplified array:
t = 1;
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
Here I am doing concatenation manually:
A = [a(1:2).data a(1:3).data a(1:4).data a(1:5).data] %concatenation function
As you can see, the range (1:2), (1:3), (1:4), and (1:5) can be looped, which I attempt to do like this:
t = 2;
A = [for t = 2:5
a(1:t).data
end]
This results in an error "Illegal use of reserved keyword "for"."
How can I do a for loop within the concatenate function? Can I do loops within other functions in Matlab? Is there another way to do it, other than copy/pasting the line and changing 1 number manually?
You were close to getting it right! This will do what you want.
A = []; %% note: no need to initialize t, the for-loop takes care of that
for t = 2:5
A = [A a(1:t).data]
end
This seems strange though...you are concatenating the same elements over and over...in this example, you get the result:
A =
1 4 1 4 9 1 4 9 16 1 4 9 16 25
If what you really need is just the .data elements concatenated into a single array, then that is very simple:
A = [a.data]
A couple of notes about this: why are the brackets necessary? Because the expressions
a.data, a(1:t).data
don't return all the numbers in a single array, like many functions do. They return a separate answer for each element of the structure array. You can test this like so:
>> [b,c,d,e,f] = a.data
b =
1
c =
4
d =
9
e =
16
f =
25
Five different answers there. But MATLAB gives you a cheat -- the square brackets! Put an expression like a.data inside square brackets, and all of a sudden those separate answers are compressed into a single array. It's magic!
Another note: for very large arrays, the for-loop version here will be very slow. It would be better to allocate the memory for A ahead of time. In the for-loop here, MATLAB is dynamically resizing the array each time through, and that can be very slow if your for-loop has 1 million iterations. If it's less than 1000 or so, you won't notice it at all.
Finally, the reason that HBHB could not run your struct creating code at the top is that it doesn't work unless a is already defined in your workspace. If you initialize a like this:
%% t = 1; %% by the way, you don't need this, the t value is overwritten by the loop below
a = []; %% always initialize!
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
then it runs for anyone the first time.
As an appendix to gariepy's answer:
The matrix concatenation
A = [A k];
as a way of appending to it is actually pretty slow. You end up reassigning N elements every time you concatenate to an N size vector. If all you're doing is adding elements to the end of it, it is better to use the following syntax
A(end+1) = k;
In MATLAB this is optimized such that on average you only need to reassign about 80% of the elements in a matrix. This might not seam much, but for 10k elements this adds up to ~ an order of magnitude of difference in time (at least for me).
Bare in mind that this works only in MATLAB 2012b and higher as described in this thead: Octave/Matlab: Adding new elements to a vector
This is the code I used. tic/toc syntax is not the most accurate method for profiling in MATLAB, but it illustrates the point.
close all; clear all; clc;
t_cnc = []; t_app = [];
N = 1000;
for n = 1:N;
% Concatenate
tic;
A = [];
for k = 1:n;
A = [A k];
end
t_cnc(end+1) = toc;
% Append
tic;
A = [];
for k = 1:n;
A(end+1) = k;
end
t_app(end+1) = toc;
end
t_cnc = t_cnc*1000; t_app = t_app*1000; % Convert to ms
% Fit a straight line on a log scale
P1 = polyfit(log(1:N),log(t_cnc),1); P_cnc = #(x) exp(P1(2)).*x.^P1(1);
P2 = polyfit(log(1:N),log(t_app),1); P_app = #(x) exp(P2(2)).*x.^P2(1);
% Plot and save
loglog(1:N,t_cnc,'.',1:N,P_cnc(1:N),'k--',...
1:N,t_app,'.',1:N,P_app(1:N),'k--');
grid on;
xlabel('log(N)');
ylabel('log(Elapsed time / ms)');
title('Concatenate vs. Append in MATLAB 2014b');
legend('A = [A k]',['O(N^{',num2str(P1(1)),'})'],...
'A(end+1) = k',['O(N^{',num2str(P2(1)),'})'],...
'Location','northwest');
saveas(gcf,'Cnc_vs_App_test.png');

Get the iteration number inside a MATLAB for loop

Say I have a for loop in MATLAB:
scales = 5:5:95;
for scale = scales
do stuff
end
How can I get the iteration number inside a MATLAB for loop as concisely as possible?
In Python for example I would use:
for idx, item in enumerate(scales):
where idx is the iteration number.
I know that in MATLAB (like in any other language) I could create a count variable:
scales = 5:5:95;
scale_count = 0;
for scale = scales
scale_count = scale_count + 1;
do stuff
end
I could otherwise use find:
scales = 5:5:95;
for scale = scales
scale_count = find(scales == scale);
do stuff
end
But I'm curious to know whether there exists a more concise way to do it, e.g. like in the Python example.
Maybe you can use the following:
scales = 5:5:95;
for iter = 1:length(scales)
scale=scales(iter); % "iter" is the iteration number.
do stuff
end
Since for iterates over the columns of whatever you give it, another way of approximating multiple loop variables would be to use an appropriately constructed matrix:
for scale=[5:5:95; 1:19]
% do stuff with scale(1) or scale(2) as appropriate
end
(my personal preference is to loop over the indices as per Parag's answer and just refer to data(index) directly within the loop, without an intermediate. Matlab's syntax isn't very concise at the best of times - you just get used to it)
The MATLAB way is probably doing it with vectors.
For example suppose you want to find in a vector if there is a value that is equal to its position. You would generally do this:
a = [10 20 1 3 5];
found = 0;
for index = 1:length(a)
if a(index) == index
found = 1;
break;
end
end
Instead you can do:
found = any(a == 1:length(a));
In general
for i=1:length(a)
dostuff(a(i), i);
end
can be replaced with:
dostuff(a(i), 1:length(a))
it dostuff can be vectorized or
arrayfun(#dostuff, a, 1:length(a))
otherwise.