Saving to separate variables within a for loop - matlab

Below is my code, I want to calculate the hamming distance between my "inp" and each row in the a matrix and save these hamming distances in different variables.:
a=[1 1 1 1;1 0 1 1;1 1 0 0; 1 0 0 1]
inp=[0 1 0 1]
for i = 1:4
D=a(i,:);
('dist%d',i)=pdist2(inp,D,'hamming')
fprintf('\n')
i=i+1;
end
This code is not working and I know that the ('dist%d',i) is the part that is wrong. However, I can't solve it. What i want to do is get the results as follows: dist1= , dist2= , dist3= , dist4= .And this is why I tied it with the "i" because it is my loop. Any ideas how can this be solved.

It appears you confused printing with assignment of variables. In general: evaluate, assign to a variable, then print.
Although Matlab does not require this, it's a good practice to initialize the place where you will store the distances. I do it with dist = zeros(4,1) below.
Store each distance in dist(i), the ith element of the array.
After that, print a formatted string with i and dist(i).
You don't need i=i+1, the for loop does incrementing for you.
a=[1 1 1 1;1 0 1 1;1 1 0 0; 1 0 0 1];
inp=[0 1 0 1];
dist = zeros(4,1);
for i = 1:4
D=a(i,:);
dist(i)=pdist2(inp,D,'hamming');
fprintf('dist%d = %f \n', i, dist(i))
end
Note that if the printout was the only goal, storing the results in dist would be unnecessary. You could just do
fprintf('dist%d = %f \n', i, pdist2(inp,D,'hamming'))
then, without introducing the array dist.

Related

MATLAB - Create repeated sequences of ones and zeros with loops

I am trying to create a single column vector (out), which is comprised of a sequence of ones and zeros. These should occur in sets of length B and C respectively, which are repeated A number of times. For example:
out=[1
0
0
1
0
0
1
0
0]
It is currently set up as:
out=[0]; %not ideal, but used to initially define 'out'
A=3;
B=1;
C=2;
for i = 1:length(A)
for ii = 1:length(B)
out(end+1,1) = ones(ii,1);
end
for iii = 1:length(C)
out(end+1,1) = zeros(iii,1);
end
end
This is not working - current output:
out=[0
1
0]
How can I correct these loops to get the desired output? Also, is there a better way of achieving this with the given the inputs?
Many thanks.
1) You do not need to use length as this returns the length of an array type, so A,B,C will all be length of 1.
2) Just directly use the values as shown below. Also you can initialize an empty array with empty brackets []
3) If you're using the zeros and ones commands, these generate whole arrays/matrices and do not need to be in a loop. If you want to keep your loop version, just use =1 or =0
out=[]; %--> you can use this instead
A=3;
B=1;
C=2;
for i = 1:A
out(end+1:end+B,1) = ones(B,1);
out(end+1:end+C,1) = zeros(C,1);
end
... or of course to be more "Matlaby" just do what David said in the comments repmat([ones(B,1);zeros(C,1)],A,1), but the above is there to help you on your way.
How about some modulo arithmetic?
result = double(mod(0:(B+C)*A-1, B+C)<B).';
Example:
>> B = 2; %// number of ones in each period
>> C = 4; %// number of zeros in each period
>> A = 3; %// number of periods
>> result = double(mod(0:(B+C)*A-1, B+C)<B).'
result =
1
1
0
0
0
0
1
1
0
0
0
0
1
1
0
0
0
0
I can suggest 2 ways:
a)Using for loop-
A=3;
B=2;
C=3;
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=[]; % to save data
for(i=1:A)
Warehouse=cat(2,Warehouse,combinedVector);
end
b)using repmat:
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=repmat(combinedVector, [A,1]);
I hope, this will solve your problem.

Why code is not giving proper results Matlab?

I know this type of questions may have been answered before but i am a beginner in matlab so please bear my kiddy questions.
I wan to generate a 11*12 matrix from a set of values. i have five different vectors named X,Y Z,u,v.
my code is:
A=zeros(12,11);
for i=1:6
A=[X(i) Y(i) Z(i) 1 0 0 0 0 (-u(i)*X(i)) (-u(i)*Y(i)) (-u(i)*Z(i)),0 0 0 0 X(i) Y(i) Z(i) 1 (-v(i)*X(i)) (-v(i)*Y(i)) (-v(i)*Z(i))];
end
Here for each iteration i want to fill two rows. So it becomes 12 rows in total. But the problem is that
1. it is giving me 22*1 matrix
2. It is giving wrong values
That means it is appending columns in each iteration that i do not want.
Kindly help me to find a 11*12 matrix. Thanks
You are assigning a completely new matrix to A on every iteration, so this will result in what you get.
What you want is to replace the rows each iteration. You can index the matrix to do this:
A(1,:) = [1 2 3 4];
This, for example, will replace the first row with the given values. So you can use
A(i*2-1,:)=[X(i) Y(i) Z(i) 1 0 0 0 0 (-u(i)*X(i)) (-u(i)*Y(i)) (-u(i)*Z(i))];
A(i*2,:)=[0 0 0 0 X(i) Y(i) Z(i) 1 (-v(i)*X(i)) (-v(i)*Y(i)) (-v(i)*Z(i))];
Unfortunately I don't have Matlab here now to see if you could combine those into one line by indexing A(i*2-1:i*2,:) or not.

How to make a general case of inserting ones in any type of matrix, in the non-principal diagonal

The title might be confusing, here's a particular example to explain myself. Also, I'm not sure how do you call the diagonal that starts in (1,2) and goes onward: (2,3) ; (3,4) and so on. Non-principal, non-main diagonal, not sure at all.
3x3 case
-1 1 0
-1 0 1
0 -1 1
4x4 case
-1 1 0 0
-1 0 1 0
-1 0 0 1
0 -1 1 0
0 -1 0 1
0 0 -1 1
So if the original matrix was a 4x4 (or any other size), I am able to make a matrix the size of the second example. I now have to insert the -1 and 1's in this fashion. This means n-1 number of -1's inserted if j=1, and then, a n-1 number of ones in the non-principal diagonal. When this is done, it's the same but for j=2 and the next non-principal diagonal, and so on.
Thing is, I'm thinking all the time about loops, and too many cases arise, because what I want is to be able to do this for any possible dimension, not for a particular case.
But then I saw this post Obtaining opposite diagonal of a matrix in Matlab
With this answer: A(s:s-1:end-1)
And it seems like a much cleaner way of doing it, since my own way (not finished since I'm not able to figure all the cases) has too many conditions. With a sentence like that, I could choose the diagonal, insert ones, and do it as many times as required, depending of the n dimension.
This leaves the problem of inserting the -1's, but I guess I could manage something.
It seems to mee that you want to obtain the following matrix B of size n × (n-1)*n/2
n = 4;
idx = fliplr(fullfact([n n]));
idx(diff(idx')<=0,:) = [];
m = size(idx,1);
B = zeros(m,n);
B(sub2ind(size(B),1:m,idx(:,1)')) = -1;
B(sub2ind(size(B),1:m,idx(:,2)')) = 1;
Approach #1
Here's a vectorized approach that has more memory requirements than a non-vectorized or for-loop based one. So, it could be tried out for small to medium sized datasizes.
The basic idea is this. For n=4 as an example, we take
-1 1 0 0
-1 0 1 0
-1 0 0 1
as the basic building block, replicate it n-1 i.e. 3 times and then remove the rows that aren't supposed to be part of the final output as per the requirements of the problem. Because of this very nature, this solution has more memory requirements, as we need to remove rows 6,8,9 for n = 4 case. But this gives us the opportunity to work with everything in one go.
N = n-1; %// minus 1 of the datasize, n
blksz = N*(N+1); %// number of elements in a (n-1)*n blocksize that is replicated
b1 = [-1*ones(N,1) eye(N)] %// Create that special starting (n-1)*n block
idx1 = find(b1~=0) %// find non zero elements for the starting block
idx2 = bsxfun(#plus,idx1,[0:N-1]*(blksz+N)) %// non zero elements for all blocks
b1nzr = repmat(b1(b1~=0),[1 N]) %// elements for all blocks
vald_ind = bsxfun(#le,idx2,[1:N]*blksz) %// positions of valid elements all blocks
mat1 = zeros(N,blksz) %// create an array for all blocks
mat1(idx2(vald_ind)) = b1nzr(vald_ind) %// put right elements into right places
%// reshape into a 3D array, join/concatenate along dim3
out = reshape(permute(reshape(mat1,N,N+1,[]),[1 3 2]),N*N,[])
%// remove rows that are not entertained according to the requirements of problem
out = out(any(out==1,2),:)
Approach #2
Here's a loop based code that could be easier to get a hold on if you have to explain it to yourself or just people and most importantly scales up pretty well on performance criteria across varying datasizes.
start_block = [-1*ones(n-1,1) eye(n-1)] %// Create that special starting (n-1)*n block
%// Find starting and ending row indices for each shifted block to be repeated
ends = cumsum([n-1:-1:1])
starts = [1 ends(1:end-1)+1]
out = zeros(sum(1:n-1),n) %// setup all zeros array to store output
for k1 = 1:n-1
%// Put elements from shifted portion of start_block for creating the output
out(starts(k1):ends(k1),k1:end) = start_block(1:n-k1,1:n-k1+1)
end
With n=4, the output -
out =
-1 1 0 0
-1 0 1 0
-1 0 0 1
0 -1 1 0
0 -1 0 1
0 0 -1 1
I don't know if I understood properly, but is this what you are looking for:
M=rand(5);
k=1; % this is to select the k-th diagonal
D=diag(ones(1,size(M,2)-abs(k)), k);
M(D==1)=-1;
M =
0.9834 -1.0000 0.8402 0.6310 0.0128
0.8963 0.1271 -1.0000 0.3164 0.6054
0.8657 0.6546 0.3788 -1.0000 0.5765
0.8010 0.8640 0.2682 0.4987 -1.0000
0.5550 0.2746 0.1529 0.7386 0.6550

Two FOR statements coupled into one

Is is possible to put two for statements into one statement. Something like
A = [ 0 0 0 5
0 2 0 0
1 3 0 0
0 0 4 0];
a=size(A);
b=size(A);
ind=0;
c=0;
for ({i=1:a},{j=1:b})
end
Your question is very broad, but one thing to consider is that in MATLAB you can often take advantage of linear indexing (instead of subscripting), without actually having to reshape the array. For example,
>> A = [ 0 0 0 5
0 2 0 0
1 3 0 0
0 0 4 0];
>> A(3,2)
ans =
3
>> A(7) % A(3+(2-1)*size(A,1))
ans =
3
You can often use this to your advantage in a for loop over all the elements:
for ii=1:numel(A),
A(ii) = A(ii) + 1; % or something more useful
end
Is the same as:
for ii=1:size(A,2),
for jj=1:size(A,1),
A(jj,ii) = A(jj,ii) + 1;
end
end
But to address your specific goal in this problem, as you stated in the comments ("I am storing the non zero elements in another matrix; with elements like the index number, value, row number and column number."), of making sparse matrix representation, it comes to this:
>> [i,j,s] = find(A);
>> [m,n] = size(A);
>> S = sparse(i,j,s,m,n)
S =
(3,1) 1
(2,2) 2
(3,2) 3
(4,3) 4
(1,4) 5
But that's not really relevant to the broader question.
Actually you can combine multiple loops into one for, however it would require you to loop over a vector containing all elements rather than the individual elements.
Here is a way to do it:
iRange = 1:2;
jRange = 1:3;
[iL jL] = ndgrid(iRange,jRange);
ijRange = [iL(:) jL(:)]';
for ij = ijRange
i = ij(1); j = ij(2);
end
Note that looping over the variables may be simpler, but perhaps this method has some advantages as well.
No
read this http://www.mathworks.com/help/matlab/matlab_prog/loop-control-statements.html
i also don't see any added value even if it was possible
No I don't think you can put two for loops in one line.
Depends on your operation, you may be able to reshape it and use one for loop. If you are doing something as simple as just printing out all elements,
B = reshape(A,a*b,1);
for i=1:a*b
c = B(i);
...
end

change a value by a probability value in matlab

I want to change a variable by probability value,
as a example I have [ 0 0 1 1 1 1 0 1 ] in matlab and with probability = 0.01 change any elemet of it , how can I achive this in matlab?
(I want use this in GA and with p =0.01 do mutation of Gen of choromosome )
appreciate any help
First, identify all the elements you want to change
array = [0 0 1 1 1 1 0 1];
sizArray = size(array);
probability = 0.01;
toChangeIdx = rand(sizArray) < probability;
Then, you can flip zeros and ones where needed
array(toChangeIdx) = 1-array(toChangeIdx);
The relevant condition for your code is
if rand() < probability
% Flip your bit here, e.g.
% bitToFlip = randi(length(genome));
% genome(bitToFlip) = 1 - genome(bitToFlip);
end
This will run the code inside the if statement with a probability of exactly probability.