Finding lengths of 0's separating islands of 1's and assigning them - matlab

I have a vector with alternating 0's and 1's and would like to convert each "1" to the length of the zeros that precede it. For example, I have x and would like to get to y:
x = [0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 1]
y = [0 0 2 0 0 0 0 4 0 0 0 3 0 0 0 2]
I would really appreciate any suggestions on how to achieve this.

One approach with find & diff -
%// Initialize array, y with zeros and of length same as input, x
y = zeros(size(x))
%// Find places/indices where new values would be put
idx = find(x)
%// Calculate new values which would be the differentiated values of indices
%// and subtracted by 1 to account for the number of zeros in between two
%// non-zero values. We need to concatenate the indices array with one zero
%// at the start to account for the starting non-zero value in x
y(idx) = diff([0 idx])-1

Related

Vector to matrix with row sum 1

I have a logical 1-by-n vector with sum m. Now, I need to convert it into a matrix m-by-n in a way that the row sum is equal 1.
vector (1-by-8) with sum 4
[0 1 0 0 1 0 1 1]
matrix (4-by-8) with row sum 1
[0 1 0 0 0 0 0 0;
0 0 0 0 1 0 0 0;
0 0 0 0 0 0 1 0;
0 0 0 0 0 0 0 1]
Is there a mathematically efficient way without calculating the sum, creating a empty matrix, loop through the vector and adding the 1s row by row?
I think that in that case, given your input, you don't even need to calculate the sum.
You can define an identity matrix of size n, then use your input vector to sample the required rows out of it:
I = eye(n);
y = I(x, :) ; % Output Matrix. x is the input vector
Here's another method, using sparse:
matrix = full(sparse(1:m, find(vector), 1, m, n));

How does Y = eye(K)(y, :); replace a "for" loop? Coursera

Working on an assignment from Coursera Machine Learning. I'm curious how this works... From an example, this much simpler code:
% K is the number of classes.
K = num_labels;
Y = eye(K)(y, :);
seems to be a substitute for the following:
I = eye(num_labels);
Y = zeros(m, num_labels);
for i=1:m
Y(i, :)= I(y(i), :);
end
and I have no idea how. I'm having some difficulty Googling this info as well.
Thanks!
Your variable y in this case must be an m-element vector containing integers in the range of 1 to num_labels. The goal of the code is to create a matrix Y that is m-by-num_labels where each row k will contain all zeros except for a 1 in column y(k).
A way to generate Y is to first create an identity matrix using the function eye. This is a square matrix of all zeroes except for ones along the main diagonal. Row k of the identity matrix will therefore have one non-zero element in column k. We can therefore build matrix Y out of rows indexed from the identity matrix, using y as the row index. We could do this with a for loop (as in your second code sample), but that's not as simple and efficient as using a single indexing operation (as in your first code sample).
Let's look at an example (in MATLAB):
>> num_labels = 5;
>> y = [2 3 3 1 5 4 4 4]; % The columns where the ones will be for each row
>> I = eye(num_labels)
I =
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
>> Y = I(y, :)
Y =
% 1 in column ...
0 1 0 0 0 % 2
0 0 1 0 0 % 3
0 0 1 0 0 % 3
1 0 0 0 0 % 1
0 0 0 0 1 % 5
0 0 0 1 0 % 4
0 0 0 1 0 % 4
0 0 0 1 0 % 4
NOTE: Octave allows you to index function return arguments without first placing them in a variable, but MATLAB does not (at least, not very easily). Therefore, the syntax:
Y = eye(num_labels)(y, :);
only works in Octave. In MATLAB, you have to do it as in my example above, or use one of the other options here.
The first set of code is Octave, which has some additional indexing functionality that MATLAB does not have. The second set of code is how the operation would be performed in MATLAB.
In both cases Y is a matrix generated by re-arranging the rows of an identity matrix. In both cases it may also be posible to calculate Y = T*y for a suitable linear transformation matrix T.
(The above assumes that y is a vector of integers that are being used as an indexing variables for the rows. If that's not the case then the code most likely throws an error.)

How to generate a vector that orthogonal to other vectors?

I have a matrix A which is
A=[1 0 0 1 0;
0 1 1 0 0;
0 0 1 1 0;
1 1 1 0 0]
And a given vector v=[ 0 0 1 1 0] which has two elements one. I have to change the position of element one such that the new vector v is orthogonal to all the rows in the matrix A.
How can I do it in Matlab?
To verify the correct answer, just check gfrank([A;v_new]) is 5 (i.e v_new=[0 1 0 0 1]).
Note that: Two vectors uand v whose dot product is u.v=0 (i.e., the vectors are perpendicular) are said to be orthogonal.
As AVK also mentioned in the comments, v_new = [0 1 0 0 1] is not orthogonal to all rows of A.
Explanation:-
A=[1 0 0 1 0;
0 1 1 0 0;
0 0 1 1 0;
1 1 1 0 0]
For A(1,:).*v = 0 to A(4,:).*v = 0,
0 x x 0 x % elements of v so that it's orthagonal to the 1st row of A
x 0 0 x x % -------------------------------------------- 2nd row of A
x x 0 0 x % -------------------------------------------- 3rd row of A
0 0 0 x x % -------------------------------------------- 4th row of A
where 0 represents the terms which have to be 0 and x represents the terms which can be either 0 or 1.
If you look as a whole, first 4 columns of v have to be zero so that the output is orthagonal to all rows of A. The 5th column can either be zero or 1.
So,
v_new can either be: v_new = [0 0 0 0 1] or v_new = [0 0 0 0 0]
From above explanation, you can also see that [0 1 0 0 1] is not orthagonal to 2nd and 4th row of A
Solution:-
To find v_new, you can use null function as: v_new = null(A).'
which gives: v_new = [0 0 0 0 1] for which gfrank([A;v_new]) also gives 5.
Maybe this will help you see the orthogonality between two vectors in N dimension.
N=100;
B1 = ones(1,N);
B2 = -1*ones(1,N/2);
B2 = [ones(1,N/2) B2];
B2 = transpose(B2);
B3 = dot(B1,B2);
The above code generates two vectors in N dimension. To check for orthogonality just transpose one of the vectors and multiply with the other one. You should get zero if they are Orthogonal.
The example I used makes sure that I get zero indeed.

manipulate zeros matrix to put boolean at certain position in rows

So I have a matrix X of size m,10 that is initialized to all zeros.
then I have a vector of size m,1 that contains digits from 1 to 10
what I want to do (hopefully in a single operation with no loops), is for each row of the matrix X and vector y, I want to put a '1' in the column indexed by the value written in the row of vector y.
Here's what I want with a small example: X = [0 0 0; 0 0 0; 0 0 0]; lets say y= [3; 2; 1];
then I would expect the operation to return X = [0 0 1; 0 1 0; 1 0 0]
Do you have a command that can do that easily ?
X(sub2ind(size(X),y',1:numel(y)))=1
or
X((0:numel(y)-1)*size(X,2) + y')=1

How to replace non-zero elements randomly with zero?

I have a matrix including 1 and 0 elements like below which is used as a network adjacency matrix.
A =
0 1 1 1
1 1 0 1
1 1 0 1
1 1 1 0
I want to simulate an attack on the network, so I must replace some specific percent of 1 elements randomly with 0. How can I do this in MATLAB?
I know how to replace a percentage of elements randomly with zeros, but I must be sure that the element that is replaced randomly, is one of the 1 elements of matrix not zeros.
If you want to change each 1 with a certain probability:
p = 0.1%; % desired probability of change
A_ones = find(A); % linear index of ones in A
A_ones_change = A_ones(rand(size(A_ones))<=p); % entries to be changed
A(A_ones_change) = 0; % apply changes in those entries
If you want to randomly change a fixed fraction of the 1 entries:
f = 0.1; % desired fraction
A_ones = find(A);
n = round(f*length(A_ones));
A_ones_change = randsample(A_ones,n);
A(A_ones_change) = 0;
Note that in this case the resulting fraction may be different to that intended, because of the need to round to an integer number of entries.
#horchler's point is a good one. However, if we keep it simple, then you can just multiple your input matrix to a mask matrix.
>> a1=randint(5,5,[0 1]) #before replacing 1->0
a1 =
1 1 1 0 1
0 1 1 1 0
0 1 0 0 1
0 0 1 0 1
1 0 1 0 1
>> a2=random('unif',0,1,5,5) #Assuming frequency distribution is uniform ('unif')
a2 =
0.7889 0.3200 0.2679 0.8392 0.6299
0.4387 0.9601 0.4399 0.6288 0.3705
0.4983 0.7266 0.9334 0.1338 0.5751
0.2140 0.4120 0.6833 0.2071 0.4514
0.6435 0.7446 0.2126 0.6072 0.0439
>> a1.*(a2>0.1) #And the replacement prob. is 0.1
ans =
1 1 1 0 1
0 1 1 1 0
0 1 0 0 1
0 0 1 0 1
1 0 1 0 0
And other trick can be added to the mask matrix (a2). Such as a different freq. distribution, or a structure (e.g. once a cell is replaced, the adjacent cells become less likely to be replaced and so on.)
Cheers.
The function find is your friend:
indices = find(A);
This will return an array of the indices of 1 elements in your matrix A and you can use your method of replacing a percent of elements with zero on a subset of this array. Then,
A(subsetIndices) = 0;
will replace the remaining indices of A with zero.