Matlab error : Subscript indices must either be real positive integers or logicals - matlab

I have the following error in MATLAB:
??? Subscript indices must either be real positive integers or
logicals.
Error in ==> Lloyd_Max at 74 D(w_count) = mean((x -
centers(xq)).^2);
This is my code :
function [ xq,centers,D ] = Lloyd_Max( x,N,min_value,max_value )
%LLOYD_MAX Summary of this function goes here
% Detailed explanation goes here
x = x';
temp = (max_value - min_value)/2^N;
count=1;
for j=0:temp:((max_value - min_value)-temp),
centers(count) = (j + j + temp )/2;
count = count + 1;
end
for i=1:length(centers),
k(i) = centers(i);
end
w_count = 0;
while((w_count < 2) || (D(w_count) - D(w_count - 1) > 1e-6))
w_count = w_count + 1;
count1 = 2;
for i=2:(count-1),
T(i) = (k(i-1) + k(i))/2;
count1 = count1 +1 ;
end
T(1) = min_value;
T(count1) = max_value;
index = 1;
for j=2:count1,
tempc = 0;
tempk = 0;
for k=1:10000,
if(x(k) >= T(j-1) && x(k) < T(j))
tempk = tempk + x(k);
tempc = tempc + 1;
end
end
k(index) = tempk;
k_count(index) = tempc;
index = index + 1;
end
for i=1:length(k),
k(i) = k(i)/k_count(i);
end
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
for i=1:10000,
cnt = 1;
for l=2:count1,
if(xq(i) > T(l-1) && xq(i) <= T(l))
xq(i) = cnt;
end
cnt = cnt +1 ;
end
end
D(w_count) = mean((x - centers(xq)).^2);
end
end
and i call it and have these inputs :
M = 10000
t=(randn(M,1)+sqrt(-1)*randn(M,1))./sqrt(2);
A= abs(t).^2;
[xq,centers,D] = Lloyd_Max( A,2,0,4 );
I tried to comment the while and the D, Results :
I got the xq and the centers all normal, xq in the 1-4 range, centers 1-4 indexes and 0.5-3.5 range.
I dont know whats going wrong here...Please help me.
Thank in advance!
MYSTERY SOVLED!
Thank you all guys for your help!
I just putted out of the while the for loop :
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
and it worked like charm.... this loop was initilizing the array again. Sorry for that. Thank you again!

There is an assignment xq(i) = x(i) somewhere in the middle of your function, but you pass A as x from outside where you calculate A from t which is sampled by randn, so you can't promise xq is an integer.

I'm not sure exactly what you are aiming to do, but your vector xq does not contain integers, it contains doubles. If you want to use a vector of indices as you do with centers(xq), all elements of the vector need to be integers.
Upon a little inspection, it looks like xq are x values, you should find some way to map them to the integer of the closest cell to which they belong (i'm guessing 'centers' represents centers of cells?)

Related

Matlab Nested Radicals

Working on an assignment in MATLAB and I can't seem to figure this problem out due to the arithmetic, I've been trying it for about 6 hours now
I need to create a loop that accepts user input > 1 (done) and loops through the following (m is input)
t1 = sqrt(m);
t2 = sqrt(m-sqrt(m));
t3 = sqrt(m-sqrt(m+sqrt(m)))
t4 = sqrt(m-sqrt(m+sqrt(m-sqrt(m))))
t5 = sqrt(m-sqrt(m+sqrt(m-sqrt(m+sqrt(m)))))
and so on until the new t value minus the old t value is < 1e-12
My current code is as follows
%Nested Radicals
clear all;
clc;
%User input for m
m = input('Please enter a value for m: ');
%Error message if m is less than 1
if m <= 1
fprintf('ERROR: m must be greater than 1\n')
m = input('Please enter a value for m: ');
end
%Error message if m is not an integer
if mod(m,1) ~= 0
fprintf('m must be an integer\n')
m = input('Please enter a value for m: \n');
end
%Nested things
t_old = m;
t_new = sqrt(m);
varsign = -1;
index = 1;
loop = true;
endResult = 1e-12;
sqrts = [sqrt(m), sqrt(m-sqrt(m)), sqrt(m-sqrt(m+sqrt(m))), sqrt(m-sqrt(m+sqrt(m-sqrt(m)))), sqrt(m-sqrt(m+sqrt(m-sqrt(m+sqrt(m)))))];
fprintf('m = %d\n',m)
fprintf('t1 = %14.13f\n', t_new')
while loop
if index ~= 1
curResult = abs(sqrts(1,index) - sqrts(1, index-1));
else
curResult = abs(sqrts(1, index));
end
if curResult > endResult
if index < 5
t_new = sqrts(1, index+1);
else
t_new = sqrts(1, index);
loop=false;
end
if index
fprintf('t%d = %14.13f\n', index, t_new)
end
else
fprintf('t%d = %14.13f\n', index, t_new);
break;
end
index = index + 1;
if index > 50
fprintf('t%d = %14.13f\n', index, t_new);
break;
end
end
Unless I'm very much mistaken, you can write the expression for t(n) as follows:
t(n) = sqrt(m-sqrt(m+t(n-2));
which makes it a lot easier to loop:
%Nested Radicals
clear all;
clc;
%User input for m
m = input('Please enter a value for m: ');
%Error message if m is less than 1
if m <= 1
fprintf('ERROR: m must be greater than 1\n')
m = input('Please enter a value for m:');
end
%Error message if m is not an integer
if mod(m,1) ~= 0
fprintf('m must be an integer\n')
m = input('Please enter a value for m:');
end
%Nested things
t_old = sqrt(m);
t_new = sqrt(m-sqrt(m));
threshold = 1e-12;
k = 3;
while abs(t_new - t_old) >= threshold
temp = sqrt(m-sqrt(m+t_old));
t_old = t_new;
t_new = temp;
k = k+1;
end
fprintf('t%d = %14.13f\n', k-2, t_old);
fprintf('t%d = %14.13f\n', k-1, t_new);
fprintf('t%d - t%d = %14.13f\n', k-2, k-1, t_old - t_new);
which gives for m=9 for example:
Please enter a value for m: 9
t17 = 2.3722813232696
t18 = 2.3722813232691
t17 - t18 = 0.0000000000005
I'm not sure what you're trying to do with the sqrts variable, you should be calculating each step on the fly in your loop, since you can't possibly know how deep you need to go
m = 5; % Get m however you want to
n = 0; % Iteration counter
tol = 1e-12 % Tolerance at which to stop
dt = 1; % initialise to some value greater than 'tol' so we can start the loop
% Loop until tn is less than tolerance. Would be sensible to add a condition on n,
% like "while tn > tol && n < 1000", so the loop doesn't go on for years if the
% condition takes a trillion loops to be satisfied
while dt > tol
% Set the value of the deepest nested expression
tn = sqrt(m);
% We know how many times take sqrt, so for loop our way out of the nested function
% Initially we want the sign to be -1, then +1, -1, ...
% This is achieved using ((-1)^ii)
for ii = 1:n
tn = sqrt(m + ((-1)^ii)*tn); % Calculate next nested function out
end
% Increment iteration number
n = n + 1;
dt = abs( t_old - tn );
t_old = tn;
end
I've not done any analysis on your function, so have no idea if it's guaranteed to converge to some value <1e-12. If it isn't then you definitely need to add some maximum iteration condition as I suggest in the comments above.

Counting Inversions in MATLAB Using MergeSort

I'm trying to implement an inversion counter in MATLAB using MergeSort, but for some reason, some of the answers are way off. For example, the number of inversions in [3, 4, 8, 1] is 3, but I'm getting 2. However, the array is being sorted correctly, so I think that the way that I'm counting the split inversions is the problem.
Here's my code:
function [count, sorted] = mergesort(A)
% count is the number of inversions; sorted is the sorted array.
n = length(A);
if n == 1
count = 0;
sorted = A;
else
m = ceil(n/2);
[count1, sorted1] = mergesort(A(1:m));
[count2, sorted2] = mergesort(A(m+1:n));
[crosscount, sorted] = merge(sorted1, sorted2);
count = count1 + count2 + crosscount;
end
end
function [crosscount, z] = merge(x, y)
n = length(x); m = length(y); z = zeros(1, n+m);
ix = 1;
iy = 1;
crosscount = 0;
for iz = 1:(n+m);
if ix > n
z(iz) = y(iy);
iy = iy + 1;
elseif iy > m
z(iz) = x(ix);
ix = ix + 1;
crosscount = crosscount + (n + 1 - ix); %this might be wrong
elseif x(ix) <= y(iy)
z(iz) = x(ix);
ix = ix + 1;
elseif x(ix) > y(iy)
z(iz) = y(iy);
iy = iy + 1;
crosscount = crosscount + 1; %im pretty sure this is right
end
end
end
Alright, so a friend helped me figure it out. My intuition was correct, but I needed help from an actual programmer to understand where I went wrong:
elseif iy > m
z(iz) = x(ix);
ix = ix + 1;
crosscount = crosscount + (n + 1 - ix); **%this might be wrong - this is actually wrong, since you don't want to count if you're traversing beyond the edge of the right array, and since the actual counting is happening in the last if case**
elseif x(ix) <= y(iy)
z(iz) = x(ix);
ix = ix + 1;
elseif x(ix) > y(iy)
z(iz) = y(iy);
iy = iy + 1;
crosscount = crosscount + **(n + 1 - ix)** **this is right because you're counting the remaining numbers in your left array that are also greater than y(iy) and just adding that to your count**
end

I need to implement a WSN simulator for group leader selection, using matlab

I am trying to implement a wireless sensor network simulator on matlab and I need your help.
This is exactly what I want to do:
Deploy nodes randomly in a 2D plane.
Model a group leader election algorithm using two conditions:
a) Energy: generate random energy values associated with each of the sensors, the sensor node with the maximum energy has higher probability of being selected as leader.
b) Proximity: the sensor node that is mostly surrounded by neighboring nodes has higher probability of being selected.
So, for a random node that has maximum energy and more neighbors can be selected as leader and plotted with the rest of the nodes in a different color.
I have been working on this, trying to develop my code all to no avail. I am not really good with matlab coding, I am still learning.
Please guys, I need any help I can get on this, my deadline is imminent.
Thanks,
Ike
First of all building a wireless networks simulator using matlab is by far not the best choice to do. its better to use specialized simulators such as NS2 or Omnet++. however, I have developed once a simple m-file code to randomly deploy points in a square are and try to link between these points according to the distance between these points. the points are assumed to be sensor nodes.
try to modify on it to get what you need. please vote up if this answer was useful to you:
W=0;X=0;Y=0;Z=0;
nodedistance = zeros();
maxx = 400; maxy=400; maxn = 50;
q = zeros(maxn);
e = rand(maxn,1)*100;
nodeloc = rand(maxn, 2)* maxx;
node(maxn) = struct('NodeNum',zeros(maxn),'nEnergy',zeros(maxn),'Loc',[zeros(maxn,1), zeros(maxn,2)]);
rss(maxn,maxn) = struct('NodeNumber',zeros(maxn),'NodeDistance',zeros(maxn));
for a = 1:100,
m = 2;
node = struct();
rss = struct();
nodedistance = zeros();
maxx = 400; maxy=400; maxn = 50;
q = zeros(maxn);
e = rand(maxn,1)*100;
nodeloc = rand(maxn, 2)* maxx;
for i = 1: maxn,
node(i)=struct('NodeNum',i,'nEnergy',e(i),'Loc',[nodeloc(i, 1), nodeloc(i, 2)]);
end
for i = 1:maxn,
for j = 1:maxn,
rss(i,j) = struct('NodeNumber',i,'NodeDistance',sqrt((node(i).Loc(1)- node(j).Loc(1))^2+(node(i).Loc(2)-node(j).Loc(2))^2));
end
end
for i = 1:maxn,
for j = 1:maxn,
nodedistance(i,j)=rss(i,j).NodeDistance;
end
end
for i = 1:maxn,
for j = 1:maxn,
if (node(i).nEnergy > 0) && (node (j).nEnergy > 0) && (0 < nodedistance(i,j) && nodedistance(i,j) <= 30)
if (node(i).nEnergy < node (j).nEnergy) %|| ( (node(i).nEnergy == node (j).nEnergy )&& (0 < nodedistance(i,j) && nodedistance(i,j)) < 30) %|| (0 < nodedistance(i,j) && nodedistance(i,j) <= 30)
q(i,j) = 1;
elseif node(i).nEnergy == node (j).nEnergy && 0 < nodedistance(i,j) && nodedistance(i,j) < 30
q(i,j) = 1;
else if 0 < nodedistance(i,j) && nodedistance(i,j) <= 30
q(i,j) = 1;
else
q(i,j) = 0;
end
end
end
end
end
end
for i = 1:maxn,
for j = 1:maxn,
if q(i,j) == 1
q(j,i) = 1;
end
end
end
colordef white,
figure(1);
axis equal
for i = 1:maxn,
hold on
box on;
plot(nodeloc(i, 1), nodeloc(i, 2), 'k.', 'MarkerSize', 5);
lscatter(nodeloc(i, 1),nodeloc(i, 2),i);
grid on;
end
gplot(q,nodeloc,'r-');
c = q;
b = 0; zeros(maxn);
check = 1;
while (check)
for m = 2:30
p = size(b)
b = zeros(maxn,maxn);
for i = 1:maxn,
for j = 1:maxn,
if i ~= j
if c(i,j) == 0
for k = 1:maxn,
if c(i,k) >0 && q(k,j) >0
b(i,j) = m;
break
else b(i,j) = 0;
end
end
end
end
end
end
f = size(b)
c = c + b;
if b ==0
check = 0;
else b = 0;% while loop here the condition.
m = m + 1;
end
end
k = 0;
for i = 1:maxn,
for j = 1:maxn,
k = k + c(i,j);
end
end
average_hop = k/(maxn*(maxn-1));
o = 0;
for i = 1:maxn,
for j = 1:maxn,
if c(i,j) ~= 0
o = o + 1;
end
end
end
c(~c) = nan;
r=max(max(c));
t=min(min(c));
clear
end
formatSpec1 = 'The number of hops from node %d to node %d is %d \n';
formatSpec2 = 'The average number of hops is %.4f, the maximum hop-count is %d, the minimum hop-count is %d \n';
formatSpec3 = 'The number of created paths is %d \n';
fileID = fopen('Paths11.txt','w');
fprintf(fileID,formatSpec1,i,j,c(i,j));
fprintf(fileID,formatSpec2,average_hop,r,t);
fprintf(fileID,formatSpec3,o);
clear;
X = X+average_hop;
Y = Y+r;
z = Z+t;
W = W+o;
end;
formatSpec1 = 'The number of hops from node %d to node %d is %d \n';
formatSpec2 = 'The average number of hops is %.4f, the average maximum hop-count is %.2f, the minimum hop-count is %d \n';
formatSpec3 = 'The average number of created paths is %.2f \n';
fileID = fopen('Energy-50-AODV.txt','w');
fprintf(fileID,formatSpec1,i,j,c(i,j));
fprintf(fileID,formatSpec2,X/a,Y/a,t);
fprintf(fileID,formatSpec3,W/a);
clear;
This is not a get-your-homework-done-for-free site; you'll have to do most of the work yourself. Here are my tips:
Don't leave your assignments to the last minute.
Study the MATLAB code of other people working in your field, and refer to the MATLAB help files (hit F1) when you get stuck. Here's a fruitful search query to point you in the right direction: wsn OR "sensor network" clustering matlab code site:edu

Filter points using hist in matlab

I have a vector. I want to remove outliers. I got bin and no of values in that bin. I want to remove all points based on the number of elements in each bin.
Data:
d1 =[
360.471912914169
505.084636471948
514.39429429184
505.285068055647
536.321181755858
503.025854206322
534.304229816684
393.387035881967
396.497969729985
520.592172434431
421.284713703215
420.401106087984
537.05330275495
396.715779872694
514.39429429184
404.442344469518
476.846474245118
599.020867750031
429.163139144079
514.941744277933
445.426761656729
531.013596812737
374.977332648255
364.660115724218
538.306752697753
519.042387479096
1412.54699036882
405.571202133485
516.606049132218
2289.49623498271
378.228766753667
504.730621222846
358.715764917016
462.339366699398
512.429858614816
394.778786157514
366
498.760463549388
366.552861126468
355.37022947906
358.308526273099
376.745272034036
366.934599077274
536.0901883079
483.01740134285
508.975480745389
365.629593988233
536.368800360349
557.024236456548
366.776498701866
501.007025898839
330.686029339009
508.395475983019
429.563732174866
2224.68806802212
534.655786464525
518.711297351426
534.304229816684
514.941744277933
420.32368479542
367.129404978681
525.626188464768
388.329756778952
1251.30895065927
525.626188464768
412.313764019587
513.697381733643
506.675438520558
1517.71183364959
550.276294237722
543.359917550053
500.639590923451
395.129864728041];
Histogram computation:
[nelements,centers] = hist(d1);
nelements=55 13 0 0 1 1 1 0 0 2
I want to remove all points apearing less than 5 (in nelements). It means only first 2 elements in nelements( 55, 13 ) remains.
Is there any function in matlab.
You can do it along these lines:
threshold = 5;
bin_halfwidth = (centers(2)-centers(1))/2;
keep = ~any(abs(bsxfun(#minus, d1, centers(nelements<threshold))) < bin_halfwidth , 2);
d1_keep = d1(keep);
Does this do what you want?
binwidth = centers(2)-centers(1);
centersOfRemainingBins = centers(nelements>5);
remainingvals = false(length(d1),1);
for ii = 1:length(centersOfRemainingBins )
remainingvals = remainingvals | (d1>centersOfRemainingBins (ii)-binwidth/2 & d1<centersOfRemainingBins (ii)+binwidth/2);
end
d_out = d1(remainingvals);
I don't know Matlab function for this problem, but I think, that function with follow code is what are you looking for:
sizeData = size(data);
function filter_hist = filter_hist(data, binCountRemove)
if or(max(sizeData) == 0, binCountRemove < 1)
disp('Error input!');
filter_hist = [];
return;
end
[n, c] = hist(data);
sizeN = size(n);
intervalSize = c(2) - c(1);
if sizeData(1) > sizeData(2)
temp = transpose(data);
else
temp = data;
end
for i = 1:1:max(sizeN)
if n(i) < binCountRemove
a = c(i) - intervalSize / 2;
b = c(i) + intervalSize / 2;
sizeTemp = size(temp);
removeInds = [];
k = 0;
for j = 1:1:max(sizeTemp)
if and(temp(j) > a, less_equal(temp(j), b) == 1)
k = k + 1;
removeInds(k) = j;
end
end
temp(removeInds) = [];
end
end
filter_hist = transpose(temp);
%Determines when 'a' less or equal to 'b' by accuracy
function less_equal = less_equal(a, b)
delta = 10^-6; %Accuracy
if a < b
less_equal = 1;
return;
end
if abs(b - a) < delta
less_equal = 1;
return;
end
less_equal = 0;
You can do something like this
nelements=nelements((nelements >5))

Subscript indices must either be real positive integers or logicals

i have the following error in my matlab function code:
??? Subscript indices must either be real positive integers or logicals.
Error in ==> AFA at 15
M(k,j) = mean(T(i:sze,j));
here is the part of the code where the problem is :
sz =size(T);
lim = sz(2) - ordre;
M = zeros(sz(1),sz(2));
r= 0;
for j=1:sze,
k = 1;
for i=1:lim,
M(k,j) = mean(T(i:i+ordre,j));
k = k + 1;
end
for i=lim+1:sz(2),
M(k,j) = mean(T(i:sz(2),j));
k = k + 1;
end
end
The following works for me without error
T = magic(25);ordre = 5; %# I make up some values here
sz =size(T);
lim = sz(2) - ordre;
%# I've added a check here
if lim < 1, error('ordre has to be at most sz(2)-1 (is %i)',ordre);end
M = zeros(sz(1),sz(2));
r= 0;
for j=1:sz(2), %# I needed to change this line (sz(1) works as well)
k = 1;
for i=1:lim,
M(k,j) = mean(T(i:i+ordre,j));
k = k + 1;
end
for i=lim+1:sz(2),
M(k,j) = mean(T(i:sz(2),j));
k = k + 1;
end
end