Can someone find why I get the error: Index in position 2 exceeds array bounds. Index must not exceed 1.

3 views (last 30 days)
the code I have is:
X= [46,52,55,71,32,5,6,11,14;47,56,47,58,59,66,70,72,71]; %data set
x_five=X(:,1:5); %only 5 first columns of X
x_new=x_five;
% while length(x_new)>1 %stop after getting one cluster
%2 for loops going all the data points pairs i and j:
for i=1:length(x_new)
for j=1:length(x_new)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
end
end
while length(x_new)>1 %stop with 1 clusters
for d=1:length(x_new)
MIN = min(dist(dist~=0)); %find the min distance (which isn't zero)
[i,j] = find(dist==MIN); %find the indices of min distance
Centroid=[(x_five(1,i(1))+x_five(1,j(1)))./2,(x_five(2,i(1))+x_five(2,j(1)))./2]; %centroid position is the avg of the merged points
disp(['step #', num2str(length(x_five)-length(x_new)+1),': merging the closest points ', num2str(i(1)),'&',num2str(j(1)),' to a new centroid(cluster)',num2str(Centroid)]);
%Addition of the new centroid to the end column
x_new(:,end+1)=Centroid;
%removal of the previous closest data points and caculation the new
%distances
% if i>1 & j>1
x_new(:,j(1))=[];
x_new(:,i(1))=[];
dist(:,[i,j])=0; %removal of the distance so the next min distance will be cacl
dist([i,j],:)=0;
for i=1:length(x_new)
for j=1:length(x_new)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
dist(i,j)
end
end
end
end
step #1: merging the closest points 3&1 to a new centroid(cluster)50.5 47
ans = 0
ans = 9.4868
ans = 20.2237
ans = 9.1241
ans = 9.4868
ans = 0
ans = 25.9422
ans = 4.5000
ans = 20.2237
ans = 25.9422
ans = 0
ans = 22.0511
ans = 9.1241
ans = 4.5000
ans = 22.0511
ans = 0
step #2: merging the closest points 4&2 to a new centroid(cluster)61.5 57
ans = 0
ans = 20.2237
ans = 9.1241
ans = 20.2237
ans = 0
ans = 22.0511
ans = 9.1241
ans = 22.0511
ans = 0
step #3: merging the closest points 3&1 to a new centroid(cluster)50.5 47
ans = 0
ans = 22.0511
ans = 22.0511
ans = 0
step #4: merging the closest points 2&1 to a new centroid(cluster)49 51.5
ans = 0
Index in position 2 exceeds array bounds. Index must not exceed 1.
I get the error for the line 49:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
Thx in advance
  4 Comments
Mathieu NOE
Mathieu NOE on 13 Jan 2023
seems to me you while loop is looping one iteration too much
this test will come already too late when the error is thrown
while length(x_new)>1 %stop with 1 clusters

Sign in to comment.

Answers (2)

Voss
Voss on 13 Jan 2023
Edited: Voss on 13 Jan 2023
1. Consider the following. Start with x_new as you have it initially:
X= [46,52,55,71,32,5,6,11,14;47,56,47,58,59,66,70,72,71];
x_five=X(:,1:5); %only 5 first columns of X
x_new=x_five;
disp(x_new);
46 52 55 71 32 47 56 47 58 59
Now, say i=3 and j=1, so you want to remove the first and third columns of x_new, which is essentially what happens the first time your code removes some columns from x_new:
i = 3;
j = 1;
x_new(:,j(1))=[];
x_new(:,i(1))=[];
disp(x_new);
52 55 32 56 47 59
Were the first and third columns deleted? No, the third column (55,47) is still there. Instead, the first and fourth columns were deleted. Why?
Because you are deleting the columns in two separate steps. First, you delete the first column with x_new(:,j(1))=[];, so that what was originally the third column (which was to be deleted) is now the second column. So then when you delete the third column with x_new(:,i(1))=[]; you are actually deleting what was originally the fourth column of x_new.
Instead of two separate deletion operations, delete both columns at once like this:
x_new(:,[j(1) i(1)])=[];
Here's proof that it works as intended:
x_new=x_five; % restore original x_new value
disp(x_new);
46 52 55 71 32 47 56 47 58 59
x_new(:,[j(1) i(1)])=[]; % delete columns 1 and 3
disp(x_new); % columns 2, 4, and 5 remain
52 71 32 56 58 59
2. After two columns of x_new are deleted (and the new centroid column is appended to the end), you set the corresponding rows and columns in dist to zero, but dist remains a 5-by-5 matrix. That means that dist no longer corresponds to x_new; it has extra row(s) and column(s) compared to x_new (x_new has one fewer column than it did on the previous iteration). Therefore, any subsequent removal of columns of x_new based on the location of the minimum non-zero element in dist may be incorrect because row and column indexes in dist don't correspond to column indexes of x_new anymore. To fix that problem, just remove the rows and columns from dist corresponding to the columns removed from x_new. Then the sizes of x_new and dist remain coherent and the algorithm performs as intended, as best I can tell. (Also, note that you only have to update the last row and column of dist each time, corresponding to the new centroid point, instead of the whole matrix - but I didn't change that.)
3. You're calculating the new Centroid point from x_five, which is the initial value of x_new, but shouldn't you use the current value of x_new? dist is calculated from the current value of x_new, and dist is what's used to determine which two points to take the centroid of, so using x_new (not x_five) to calculate Centroid makes sense to me.
4. The for d=1:size(x_new,2) loop inside the while loop, I don't know why it's there, and I think the intention of the code is sufficiently fulfilled just using the while loop.
%HW 5
clc;
close all;
clear all;
%Q1
%Q1a
% s1=str2num('asdfqert');
% s2=str2num('aerfqebt');
% pdist2(s1)
% seqdist()
%Q1b(i)
X= [46,52,55,71,32,5,6,11,14;47,56,47,58,59,66,70,72,71];
x_five=X(:,1:5); %only 5 first columns of X
x_new=x_five;
size(x_new,2)
ans = 5
% while length(x_new)>1 %stop after getting one cluster
%2 for loops going all the data points pairs i and j:
for i=1:size(x_new,2)
for j=1:size(x_new,2)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
end
end
while size(x_new,2)>1 %stop with 1 clusters
% for d=1:size(x_new,2)
x_new
dist
MIN = min(dist(dist~=0)); %find the min distance (which isn't zero)
[i,j] = find(dist==MIN); %find the indices of min distance
% Centroid=[(x_five(1,i(1))+x_five(1,j(1)))./2,(x_five(2,i(1))+x_five(2,j(1)))./2]; %centroid position is the avg of the merged points
Centroid=[(x_new(1,i(1))+x_new(1,j(1)))./2,(x_new(2,i(1))+x_new(2,j(1)))./2]; %centroid position is the avg of the merged points
disp(['step #', num2str(length(x_five)-length(x_new)+1),': merging the closest points ', num2str(i(1)),'&',num2str(j(1)),' to a new centroid(cluster)',num2str(Centroid)]);
%Addition of the new centroid to the end column
x_new(:,end+1)=Centroid;
%removal of the previous closest data points and caculation the new
%distances
% if i>1 & j>1
% x_new(:,j(1))=[];
% x_new(:,i(1))=[];
x_new(:,[j(1) i(1)])=[];
% dist(:,[i,j])=0; %removal of the distance so the next min distance will be cacl
% dist([i,j],:)=0;
dist(:,[i,j])=[]; %removal of the distance so the next min distance will be cacl
dist([i,j],:)=[];
for i=1:size(x_new,2)
for j=1:size(x_new,2)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
end
end
% end
end
x_new = 2×5
46 52 55 71 32 47 56 47 58 59
dist = 5×5
0 10.8167 9.0000 27.3130 18.4391 10.8167 0 9.4868 19.1050 20.2237 9.0000 9.4868 0 19.4165 25.9422 27.3130 19.1050 19.4165 0 39.0128 18.4391 20.2237 25.9422 39.0128 0
step #1: merging the closest points 3&1 to a new centroid(cluster)50.5 47
x_new = 2×4
52.0000 71.0000 32.0000 50.5000 56.0000 58.0000 59.0000 47.0000
dist = 4×4
0 19.1050 20.2237 9.1241 19.1050 0 39.0128 23.2648 20.2237 39.0128 0 22.0511 9.1241 23.2648 22.0511 0
step #2: merging the closest points 4&1 to a new centroid(cluster)51.25 51.5
x_new = 2×3
71.0000 32.0000 51.2500 58.0000 59.0000 51.5000
dist = 3×3
0 39.0128 20.7921 39.0128 0 20.6594 20.7921 20.6594 0
step #3: merging the closest points 3&2 to a new centroid(cluster)41.625 55.25
x_new = 2×2
71.0000 41.6250 58.0000 55.2500
dist = 2×2
0 29.5034 29.5034 0
step #4: merging the closest points 2&1 to a new centroid(cluster)56.3125 56.625

Walter Roberson
Walter Roberson on 13 Jan 2023
x_new is 2x5.
length(x_new) is 0 if any(size(x_new) == 0) and is max(size(x_new)) otherwise, so length(x_new) is max([2 5]) which is 5.
You use that 5 as a row index but there are only two rows.
Do not use length() with something that is not a vector.
  3 Comments
Walter Roberson
Walter Roberson on 13 Jan 2023
What you should do is not use length() calls. Use size() calls and specify which dimension you wish to take the size of.
Hadar
Hadar on 13 Jan 2023
Edited: Walter Roberson on 13 Jan 2023
Ok, I fix that and now I have another problem:(
How can I break the loop so I won't get MIN size to be [0 1] and an error from the lime
I actually think the while has to puse one step before it does?
----
my fixed code:
%HW 5
clc;
close all;
clear all;
%Q1
%Q1a
% s1=str2num('asdfqert');
% s2=str2num('aerfqebt');
% pdist2(s1)
% seqdist()
%Q1b(i)
X= [46,52,55,71,32,5,6,11,14;47,56,47,58,59,66,70,72,71];
x_five=X(:,1:5); %only 5 first columns of X
x_new=x_five;
size(x_new,2)
% while length(x_new)>1 %stop after getting one cluster
%2 for loops going all the data points pairs i and j:
for i=1:size(x_new,2)
for j=1:size(x_new,2)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
end
end
while size(x_new,2)>1 %stop with 1 clusters
for d=1:size(x_new,2)
MIN = min(dist(dist~=0)); %find the min distance (which isn't zero)
size(dist)
size(MIN)
[i,j] = find(dist==MIN); %find the indices of min distance
Centroid=[(x_five(1,i(1))+x_five(1,j(1)))./2,(x_five(2,i(1))+x_five(2,j(1)))./2]; %centroid position is the avg of the merged points
disp(['step #', num2str(length(x_five)-length(x_new)+1),': merging the closest points ', num2str(i(1)),'&',num2str(j(1)),' to a new centroid(cluster)',num2str(Centroid)]);
%Addition of the new centroid to the end column
x_new(:,end+1)=Centroid;
%removal of the previous closest data points and caculation the new
%distances
% if i>1 & j>1
x_new(:,j(1))=[];
x_new(:,i(1))=[];
dist(:,[i,j])=0; %removal of the distance so the next min distance will be cacl
dist([i,j],:)=0;
for i=1:size(x_new,2)
for j=1:size(x_new,2)
%generation of the distance matrix first 5 elements:
dist(i,j)=sqrt(((x_new(1,i)-x_new(1,j)).^2) + ((x_new(2,i)-x_new(2,j)).^2));
end
end
end
end
-----
the error I get:Error using ==
Arrays have incompatible sizes for this operation.
----
and this is (I think) beacause in the last iteration the size of MIN is changed to [0 1] , I don't know why
Thx again

Sign in to comment.

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!