insert a row and a line in a matrix - matlab

I create a matrix b from a matrix a in the following way:
a=[1 2 ; 3 4];
b= [a zeros(2); zeros(2) a]
b =
1 2 0 0
3 4 0 0
0 0 1 2
0 0 3 4
Successively, I want to insert a line and a column of zeros at a certain point of the matrix. Let's say at middle way:
idx=2;
c=[b(1:idx,:); zeros(1,4); b(idx+1:end,:)]
c =
1 2 0 0
3 4 0 0
0 0 0 0
0 0 1 2
0 0 3 4
c=[c(:,1:idx) zeros(5,1) c(:,idx+1:end)]
c =
1 2 0 0 0
3 4 0 0 0
0 0 0 0 0
0 0 0 1 2
0 0 0 3 4
Is there a more intelligent way of doing this?

Here is another way(I don't know if it is a more intelligent way).
Assuming that you have the row index as row and the column index as col:
sc = size(b) + 1;
c = zeros(sc);
ROW = true(sc(1), 1);
ROW(row) = false;
COL = true(1, sc(2));
COL(col) = false;
Then in MATLAB r2016b /Octave you can write
c(ROW & COL)=b;
In pre 2016b you can use bsxfun
c(bsxfun(#and, ROW , COL))=b;

Related

Putting 1's in certain places

I have 2 matrices
Matrix A = [7 3 5 2 8 4 1 6 9;
5 2 6 1 4 3 9 7 8;
9 1 4 5 2 6 3 6 7;
4 8 1 6 3 7 2 9 5;
6 1 7 2 8 4 5 9 3]
Matrix B = [1 0 0 0 0 0 0 0 0;
0 1 1 0 0 0 0 0 0;
0 0 0 0 0 0 0 1 0;
0 0 0 1 0 1 0 0 0;
0 0 0 0 0 0 0 0 1]
Matrix A and B are already defined.
Here each column can't have more than 1 what i want to do is that if when i do sum for Matrix B if i found 0 in it i have to add 1's in the places of the zero's but in certain places. In each row the 1's have to be placed in certain groups. For example if a 1 is placed in column 1, then it can be placed as well in column 2 or 3 only. It can't be placed anywhere else. If in another row it is placed in column 5, then it can be placed in column 4 or 6 only and so on. It's like group of 3. Each 3 columns are together.
To be more clear:
Here the sum of matrix B is [1 1 1 1 0 1 0 1 1]. The zeros here are placed in column 5 and 7 and i want to add 1 putting in mind where the 1 is going to be placed in the matrix. So in this example the 1 of column 5 can only be placed in row 4 as the 1's in this row are placed in column 4 and 6. The 1 of column 7 can be placed in row 5 or row 3. If we have choice between 2 rows then the 1 will be placed in the placed of the higher number of Matrix A.
The 1's have to be placed in groups; columns 1, 2 and 3 are together, columns 4,5 and 6 are together and columns 7, 8 and 9 are together. so if the 1 is placed in 1 column of the group then it can't be placed in any other place.
Let me simplify it if we have an array like this [0 0 0 0 0 0 0 1 1] This array has 3 categories, columns 1,2 and 3 are 1st category, columns 4,5 and 6 are 2nd category and so on. here i want to place a 1 so that the 3rd category won't have a zero element. This is what i want to do briefly but with a whole matrix with all the categories.
so here the output will be =
[1 0 0 0 0 0 0 0 0;
0 1 1 0 0 0 0 0 0;
0 0 0 0 0 0 0 1 0;
0 0 0 1 1 1 0 0 0;
0 0 0 0 0 0 1 0 1]
This code was tried but it doesn't give the required output as the 1 was placed in the 1st row not in the place where it has to be (the category that it should be in).
sum_cols_B = sum(B); % Sum of Matrix B (dim 1)
[~, idx] = find(sum_cols_B == 0); % Get indices where sum == 0
% Using loop to go through the indices (where sum = 0)
for ii = idx
B(1,ii) = 1; % Insert 1 in the first position of that
end % column in Matrix B
Ask me if the question is still not clear.!
Here's an updated loop that will add the missing 1's:
sum_cols_B = sum(B);
[~, idx] = find(sum_cols_B == 0);
group_size = 3;
for ii = idx
% Calculate the starting column of the group for column ii
% There are (ii-1)/group_size groups
% Add 1 for 1-based indexing
group_start = floor((ii-1)/group_size)*group_size + 1;
% Determine which rows in the current group have nonzero values
group_mask = sum(B(:,group_start:group_start+group_size-1), 2) > 0;
% Find the row number of the max in A column ii corresponding to mask
[~,rownum] = max(A(:,ii).*group_mask);
% The value in column ii of B should have a 1 inserted
% at the row containing the max in A
B(rownum,ii) = 1;
end
Results for B above are:
B =
1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0
0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 1 0 1
B = [1 0 0 0 0 0 0 0 0;...
0 1 1 0 0 0 0 0 0;...
0 0 0 0 0 0 0 1 0;...
0 0 0 1 0 1 0 0 0;...
0 0 0 0 0 0 0 0 1]; % Matrix - using this as an example
sum_cols_B = sum(B); % Sum of Matrix B (dim 1)
[~, idx] = find(sum_cols_B == 0); % Get indices where sum == 0
% Using loop to go through the indices (where sum = 0)
for ii = idx
B(1,ii) = 1; % Insert 1 in the first position of that
end % column in Matrix B

Loopless submatrix assignment in Matlab

I have a matrix F of size D-by-N and a vector A of length N of random integers in the range [1,a]. I want to create a matrix M of size D * a such that each colum M(:,i) has the vector F(:,i) starting from the index (A(i)-1)*D+1 to (A(i)-1)*D+D.
Example:
F = [1 2 3 10
4 5 6 22]
A = [3 2 1 2]
a = 4
M = [0 0 3 0
0 0 6 0
0 2 0 10
0 5 0 22
1 0 0 0
4 0 0 0
0 0 0 0
0 0 0 0]
I can do it with a simple loop
for i = 1 : N
M((A(i)-1)*D+1:(A(i)-1)*D+D,i) = F(:,i);
end
but for large N this might take a while. I am looking for a way to do it without loop.
You can use bsxfun for a linear-indexing based approach -
[D,N] = size(F); %// Get size of F
start_idx = (A-1)*D+1 + [0:N-1]*D*a; %// column start linear indices
all_idx = bsxfun(#plus,start_idx,[0:D-1]'); %//'# all linear indices
out = zeros(D*a,N); %// Initialize output array with zeros
out(all_idx) = F; %// Insert values from F into output array
Sample run -
F =
1 2 3 10
4 5 6 22
A =
3 2 1 2
a =
4
out =
0 0 3 0
0 0 6 0
0 2 0 10
0 5 0 22
1 0 0 0
4 0 0 0
0 0 0 0
0 0 0 0

Linear span of a vector in MATLAB

I'm looking for a way to generate the spans of a given vector in MATLAB.
For example:
if a = [ 0 1 0 1] I need all vectors of the form [0 x 0 y], 1 <= x <= max1, 1 <= y <= max2,.
or if
a = [ 0 1 0 1 1 0] I need all vectors of the form [0 x 0 y z 0], 1 <= x <= max1, 1 <= y <= max2, 1<= z <= max3.
Note that the vector can have a variable number of 1's.
My first impression is that I would need a variable number of for loops, though I don't know if that is doable in MATLAB. Also any other ideas are welcome!
You don't need multiple for loops for this. The code below generates all required vectors as rows of a tall matrix. It actually creates the columns of the matrix one at a time. Each column will have numbers 1:m(i) arranged in the pattern where
each term repeats the number of times equal to the product of all m-numbers after m(i)
the whole pattern repeats the number of times equal to the product of all m-numbers before m(i)
This is what repmat(kron(1:m(i),ones(1,after)),1,before)' does. (Starting with R2015a you can use repelem to simplify this by replacing the kron command, but I don't have that release yet.)
a = [0 1 0 1 1 0];
m = [2 4 3]; // the numbers max1, max2, max3
A = zeros(prod(m), length(a));
i = 1; // runs through elements of m
for j=1:length(a) // runs through elements of a
if (a(j)>0)
before = prod(m(1:i-1));
after = prod(m(i+1:end));
A(:,j) = repmat(kron(1:m(i),ones(1,after)),1,before)';
i = i+1;
end
end
Output:
0 1 0 1 1 0
0 1 0 1 2 0
0 1 0 1 3 0
0 1 0 2 1 0
0 1 0 2 2 0
0 1 0 2 3 0
0 1 0 3 1 0
0 1 0 3 2 0
0 1 0 3 3 0
0 1 0 4 1 0
0 1 0 4 2 0
0 1 0 4 3 0
0 2 0 1 1 0
0 2 0 1 2 0
0 2 0 1 3 0
0 2 0 2 1 0
0 2 0 2 2 0
0 2 0 2 3 0
0 2 0 3 1 0
0 2 0 3 2 0
0 2 0 3 3 0
0 2 0 4 1 0
0 2 0 4 2 0
0 2 0 4 3 0

How to generate a matrix of vector combinations with zeros for excluded elements?

I want to create a matrix from all combinations of elements of one vector that fulfill a condition
For example, I have this vector
a = [1 2 3 4 5]
and want to create a matrix like
a = [1 0 0 0 0;
1 2 0 0 0;
1 2 3 0 0;
1 2 3 4 0;
1 2 3 4 5;
0 2 0 0 0;
0 2 3 0 0;
........;]
and then get the rows that fulfill the condition I can use the command:
b = sum(a')' > value
but I don't know how to generate the matrix
You can generate all possible binary combinations to determine the matrix you want:
a = [1 2 3];
n = size(a,2);
% generate bit combinations
c =(dec2bin(0:(2^n)-1)=='1');
% remove first line
c = c(2:end,:)
n_c = size(c,1);
a_rep = repmat(a,n_c,1);
result = c .* a_rep
Output:
c =
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
result =
0 0 3
0 2 0
0 2 3
1 0 0
1 0 3
1 2 0
1 2 3

In matlab, increment different column element for every row in without using a loop

Assume you have an 4x4 matrix A of zeros:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
And an 4x1 vector B that represents column indices for matrix A (so values [1:4])
4
2
3
1
Now I want to increment those columnpositions in matrix A on the index on every row from vector B.
I have tried a couple of constructions myself but can't quite manage to do this.
For example I tried:
A(:, B) = A(:, B)+1
Which just increment every element in A.
This is how I want the operation to act:
>> A(somethting(B)) = A(somethting(B)) + 1
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
You can do this by using the linear index to each of the elements you want to address. Compute this using sub2ind:
>> A = zeros(4)
A =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>> B = [4 2 3 1]
B =
4 2 3 1
>> i=sub2ind(size(A),B,1:4)
i =
4 6 11 13
>> A(i) = A(i)+1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
Well just in case you want a looped version :p
A = zeros(4,4);
B = [4, 2, 3, 1];
for i = 1:length(B)
A(i, B(i) ) = A(i, B(i) ) + 1;
end
A = zeros(4);
B = [4 2 3 1];
A(repmat([1:4]',1,4) == repmat(B,4,1)) = 1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0