index out of bounds error because numel - matlab

It loops through until the last time and then I get an error "Attempted to access EQ_NUM(8); index out of bounds because
numel(EQ_NUM)=7."
N_NODE=8
N_PRE_DISP=2
DISP_NODE= [2 7]
EQ_NUM = 0;
for i = 1:N_PRE_DISP
NODE=DISP_NODE(i);
EQ_NUM(NODE) = -i;
end
ROW = 0;
for i = 1:N_NODE
if (EQ_NUM(i)==0)
ROW = ROW+1;
EQ_NUM(i)=ROW;
end
end

In this loop
EQ_NUM = 0;
for i = 1:N_PRE_DISP
NODE=DISP_NODE(i);
EQ_NUM(NODE) = -i;
end
you create EQ_NUM with 7 elements; the highest value that NODE takes is the highest value in DISP_NODE(1:2) which is 7.
In this loop
ROW = 0;
for i = 1:N_NODE
if (EQ_NUM(i)==0)
ROW = ROW+1;
EQ_NUM(i)=ROW;
end
end
you loop over i=1:8 and eventually try to execute EQ_NUM(8)==0.
You need to fix something, but I don't know what. Possibly you think that Matlab arrays are indexed from 0, they're not, the first index into a Matlab array is 1.

Related

Implement huffmandict() function in matlab using arrays

I would like to implement the huffmandict() function in Matlab. I have already written a code in which I create an array with all the probabilities. Each time I add the 2 last probabilities , I update my array by adding the new sum probability at the next row in the right place. I also have an array with the sums only. The problem is I don't know how to continue to assign '0' and '1'. Any idea?
This is my code:
function code_words = my_huffmandict_func(init_symbols,probs)
my_symbol_array = [];
my_symbol_array = init_symbols;
my_probs = [];
my_probs = probs;
if length(my_symbol_array)~=length(my_probs)
error('Number of symbols and number of probabilities are not the same.');
end
for i=1:length(my_probs) %sorting the probabilities in descending order and
change the sequence of the symbols
for j=1:length(my_probs)
if (my_probs(i)> my_probs(j))
temp1=my_probs(i);
temp2=my_symbol_array(i);
my_probs(i)= my_probs(j);
my_symbol_array(i)= my_symbol_array(j);
my_probs(j)= temp1;
my_symbol_array(j)= temp2;
end
end
end
my_sum_array = [];
k=1;
init_lengthpr = length(my_probs);
all_occured_probs = [];
all_occured_probs(1,:) = my_probs;
while length(my_probs)>2 %we need this while loop as long as there are more
than 2 symbols left
my_temp_sum = my_probs(length(my_probs)) + my_probs(length(my_probs-1)); %we add the the possibilities of the two less possible outputs
my_sum_array = [my_sum_array,my_temp_sum]; %in this array we keep all the sums that occured
my_probs = [my_probs(1:length(my_probs)-2), my_temp_sum];%we update the possibilities' array
my_probs = sort(my_probs,'descend'); %we sort the array again
k=k+1;
all_occured_probs(k,:) = [my_probs,zeros(1,init_lengthpr-length(my_probs))];
end
end

Avoid for loop for setting the matrix element in Matlab

In a matrix, how does one set an adjacent and diagonal element to 1 if the values in these locations are the same avoiding a for loop?
An attempt made with for loop is given
[r,c] = size(mat1);
Sval = zeros(size(mat1));
for i = 1:r
for j = 1:c-1
if(mat1(i,j) == mat1(i,j+1))
Sval(i,j) = 1;
Sval(i,j+1) = 1;
else
Sval(i,j) = 0;
Sval(i,j+1) = 0;
end;
end;
end;
To receive the exact same output without the loops the code is the following. However it is not quite clear what you want to achieve with this code. Please elaborate further if this doesn't answer your question.
Sval = mat1(:,1:c-1) == mat1(:,2:c);
Sval(:,c) = Sval(:,c-1);
If I interpret your sentence right what you actually want is to shift/copy the equal values to the right as well. This could be achived by:
Sval = mat1(:,1:c-1) == mat1(:,2:c);
Sval(:,c) = zeros(r,1);
Sval(:,2:c) = Sval(:,1:c-1) | Sval(:,2:c);

Get final variable for a code with loops on Matlab

I have a code with two for loops. The code is working properly. The problem is that at the end I would like to get a variable megafinal with the results for all the years. The original varaible A has 3M rows, so it gives me an error because the size of the megafinal changes with each loop iteration and matlab stops running the code. I guess it’s a problem of inefficiency. Does anyone know a way to get this final variable despite of the size?
y = 1997:2013;
for i=1:length(y)
A=b(cell2mat(b(:,1))==y(i),:);
%Obtain the absolute value of the difference
c= cellfun(#minus,A(:,3),A(:,4));
c=abs(c);
c= num2cell(c);
A(:,end+1) = c;
%Delete rows based on a condition
d = (abs(cell2mat(A(:,8)) - cell2mat(A(:,7))));
[~, ind1] = sort(d);
e= A(ind1(end:-1:1),:);
[~, ind2,~] = unique(strcat(e(:,2),e(:, 6)));
X= e(ind2,:);
(…)
for j = 2:length(X)
if strcmp(X(j,2),X(j-1,2)) == 0
lin2 = j-1;
%Sort
X(lin1:lin2,:) = sortrows(X(lin1:lin2,:),13);
%Rank
[~,~,f]=unique([X{lin1:lin2,13}].');
g=accumarray(f,(1:numel(f))',[],#mean);
X(lin1:lin2,14)=num2cell(g(f));
%Score
out1 = 100 - ((cell2mat(X(lin1:lin2,14))-1) ./ size(X(lin1:lin2,:),1))*100;
X(lin1:lin2,15) = num2cell(out1);
lin1 = j;
end
end
%megafinal(i)=X
end
Make megafinal a cell array. This will account for the varying sizes of X at each iteration. As such, simply do this:
megafinal{i} = X;
To access a cell element, you just have to do megafinal{num}, where num is any index you want.

Removing repeated elements in a list of words and counting the number of repetitions

This is my code, I am trying to sort an array of words, and calling the sorted array 'a'.
I am trying to use a while loop to compare adjacent elements of a, and as it is sorted any repetitions should already be next to each other. If there is a repetition I remove the word and and it to the count. I am unsure how to get my output to show each sorted word and its associated count together. Thank you for any help.
(myAsort is a function I have already made that puts words into alphabetical order)
For example if I input myACsort({'cat','dog','cat'), I want the output to be:
answer =
'cat' 'dog'
count:2 count:1
function [ answer ]= myACsort( input )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
a = myAsort(input);
n = length(a);
i = 1;
count = 1;
while (i<=n)
if isequal(a{i},a{i+1})
a(i+1) = [];
count = count+1;
else
count = 1;
i=i+1;
end
end
end
The usual combination of unique and accumarray would be my suggestion:
>> strs = {'cat','dog','cat'};
>> [uStr,ia,ic] = unique(strs);
>> countCell = [uStr(:).'; num2cell(accumarray(ic,1)).']
countCell =
'cat' 'dog'
[ 2] [ 1]
FYI, you can later extract the counts via counts = [countCell{2,:}];.
If you wan to do it without the help of these functions, you can fix up your myACsort function as follows:
function answer = myACsort(input)
a = sort(input); % sort operates on cell arrays of strings
i = 1; count = 1;
uwords = a(1);
while (i<numel(a))
if i<numel(a) && isequal(a{i},a{i+1})
a(i+1) = [];
count(i) = count(i)+1;
else
i=i+1;
count(i) = 1;
uwords(i) = a(i);
end
end
answer = [uwords(:).'; num2cell(count(:)).'];
Although array growing is not very efficient.
Another approach: sort the strings (variable sortedStrs), detect the end of each run of equal strings in the sorted sequence (variable ind), and the result is easily obtained from that.
strs = {'cat','dog','cat'}; %// data
n = numel(strs);
sortedStrs = sort(strs);
dif = arrayfun(#(n) ~strcmp(sortedStrs{n},sortedStrs{n-1}), 2:n);
ind = [ find(dif) n ];
result(1,:) = sortedStrs(ind);
result(2,:) = mat2cell([ind(1) diff(ind)],1,ones(1,numel(ind)));

Avoiding for-loops in matrix operations with cell elements

The dimensions of this problem are: model.nlf = 4. Each {r} of Kuu or KuuGamma are 500x500 matrices of data.
How to suppress the for-loop? my intuition goes toward using cellfun with a function for logdet.
logDetKuu = 0;
for r=1:model.nlf,
if isfield(model, 'gamma') && ~isempty(model.gamma)
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(model.KuuGamma{r});
model.logDetKuu{r} = logdet(model.KuuGamma{r}, model.sqrtKuu{r});
else
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(model.Kuu{r});
model.logDetKuu{r} = logdet(model.Kuu{r}, model.sqrtKuu{r});
end
logDetKuu = logDetKuu + model.logDetKuu{r};
end
Grateful for pointers. Thanks
Follow up question: Can the following type of for-loops on cell elements be vectorized?
nlf = 4; nout = 16; each KuuinvKuy{1,1} are 150x650
for k =1: model.nout,
for r =1: model.nlf,
model.KuuinvKuy{r,k} = model.Kuuinv{r}*model.Kyu{k,r}';
end
end
If all your matrices are so large, and you execute your for-loop only 4 times, then there is no reason to remove the for-loops, since it will not lead to any speedup. My only observation is that the condition of the if seems to be independent of the loop, so it is cleaner to move that if before the loop. Something like this:
if isfield(model, 'gamma') && ~isempty(model.gamma)
myKuu = model.KuuGamma;
else
myKuu = model.Kuu;
end
logDetKuu = 0;
for r=1:model.nlf,
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(myKuu{r});
model.logDetKuu{r} = logdet(myKuu{r}, model.sqrtKuu{r});
logDetKuu = logDetKuu + model.logDetKuu{r};
end