Filling up gaps in matrix's rows - matlab

Let g be a matrix containing ones\zeroes. I want to fill up gaps of zeros (complete ones sequences) in the rows of g which are smaller then a given k.
For example fill up with ones all gaps smaller then three zeros. This code will work:
[m,n]=size(g);
k=3
for i=1:m
j=1
while (j<n)
if(g(i,j)==0)
flag=0;
for w=1:k
if(g(i,j+w-1)==1)
flag=1;
end
end
if(flag)
for w=1:k
g(i,j+w-1)=1;
end
else
while(~flag&j<n)
j=j+1;
if(g(i,j)==1)
flag=1;
end
end
end
end
j=j+1;
end
end
Is there a way to do so without all the for loops?

A short version using some built-in function:
M = [1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1]
Mopen = ~imopen(~padarray(M,[0,1],1),strel('line',3,0));
Mfill = Mopen(:,2:end-1);

A vectorized version:
k = 3;
d = diff( g,1,2);
L = d ~= 0;
c = cumsum([zeros(size(g,1),1) L],2)+1;
b = bsxfun(#plus, c, cumsum([0; c(1:end-1,end)]));
a =accumarray(reshape(b.',[],1),1);
f= find(a<k);
g(ismember(b,f) & g==0) = 1;
Example :
g =
1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1
result =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 0 0 0
1 1 1 1 1

Another potential solution is to cast each row to a char array and then perform substitutions based on a regular expressions
g = round(rand(30,70));
figure();
subplot(121);
imagesc(g)
[m,n]=size(g);
k=3;
pattern = ['(?<!',char(0),')(',char(0),'{1,',num2str(k-1),'})(?!',char(0),')'];
for i=1:m
[matchstart,matchend] = regexp(char(g(i,:)),pattern);
for j = 1:length(matchstart)
g(i,matchstart(j):matchend(j)) = 1;
end
end
subplot(122);
imagesc(g)

Related

How to crate cells contain subvectors from logical vector in MATLAB

For example I have a logial vector in MATLAB:
idx1 = [0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0]
And I want to get numbers (count each block) of such blocks: 1 1 1, i.e. such block contain N elements == 1 (N "1"). idx1 - array, and his dimension can be any, for example 3820000.
How count many blocks (sequences of ones) occur in the entire array idx1?
counts_idx = 0;
init_counts_idx = 0;
arr = 0;
for i = 1:length(idx1) -1
for kk = 1 : length(idx1) - 1
if idx1(kk + 1) == 1
init_counts_idx = init_counts_idx + 1;
arr = init_counts_idx;
else
init_counts_idx = counts_idx;
end
C = {i,arr};
end
end
I try to using cells...
You can calculate the start and end indices of each block by diff([0 idx1 0]). Then, use this information to calculate block lengths Ns. Finally express the result as a cell array using the function C = mat2cell(A,rowDist).
idx1 = [0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0];
diffs = diff([0 idx1 0]);
% find start index of the blocks
loc = find(diffs == 1);
% calc block lengths by subtracting end - start indices
Ns = find(diffs == -1) - loc;
C = mat2cell([loc' Ns'],ones(size(loc)))
4×1 cell array
{[ 4 3]}
{[ 9 3]}
{[16 6]}
{[29 3]}
If you are interested only in the number of such blocks, length(loc) will give you the answer, it is similar to bwconncomp(idx1).NumObjects.
bwconncomp(idx1).NumObjects
See bwconncomp()

Need to create upper triangular matrix but the loops are not working properly

Hi I am trying to make a matrix upper triangular by using elementary row operations
a = [1 1 0 1;2 1 -1 1;4 -1 -2 2;3 -1 -1 1]
function [c,d,e] = elim(a)
for i = 2:4
a(i,:) = a(i,:) - a(1,:)*(a(i,1)/a(1,1))
end
c = a
for j=3:4
c(j,:) = c(j,:) - c(1,:)*(c(j,1)/c(1,1))
end
d = c
for k=4:4
d(k,:) = d(k,:) - d(1,:)*(d(k,1)/d(1,1))
end
e = d
and the output is
1 1 0 1
0 -1 -1 -1
0 -5 -2 -2
0 -4 -1 -2
so only the first column has been changed by the first 'for' loop in the code and the rest of the two 'for' loops seem to be not working. Any help?
Thanks to Dmitri for the insight; I made a general program as follows
% this program takes input as a square matrix with arguments for
% function as the matrix itself(a) and the order of the matrix(m)
function [c] = elim_ut_gen(a,m)
for j=1:(m-1)
for i = (j+1):m
a(i,:) = a(i,:) - a(j,:)*(a(i,j)/a(j,j))
end
end
c=a
a =
1 1 0 1
2 1 -1 1
4 -1 -2 2
3 -1 -1 1
ans =
1 1 0 1
0 -1 -1 -1
0 0 3 3
0 0 0 -1
There are a few minor mistakes in your function. Below they are fixed
function [c,d,e] = elim(a)
c = a;
for i = 2:4
c(i,:) = c(i,:) - c(1,:)*(c(i,1)/c(1,1));
end
d = c;
for j=3:4
d(j,:) = d(j,:) - d(2,:)*(d(j,2)/d(2,2));
end
e = d;
for k=4:4
e(k,:) = e(k,:) - e(3,:)*(e(k,3)/e(3,3));
end
end
On subsequent steps of elimination you should use the elements of the corresponding row. That is on step two you should use the second row to eliminate elements of the second column, and so on.
The result:
>> [c,d,e] = elim(a)
c =
1 1 0 1
0 -1 -1 -1
0 -5 -2 -2
0 -4 -1 -2
d =
1 1 0 1
0 -1 -1 -1
0 0 3 3
0 0 3 2
e =
1 1 0 1
0 -1 -1 -1
0 0 3 3
0 0 0 -1
There are a few problems remaining:
The function should check if the diagonal element used for elimination is not zero and report an error
The function can easily be generalized to handle matrices of arbitrary shape.
What I love about Matlab is that, for a majority of situations, there is no need to reinvent the wheel:
a = [1 1 0 1;2 1 -1 1;4 -1 -2 2;3 -1 -1 1];
e = tril(a,-1) + triu(a);

How to make a parity check matrix from non-systematic to systematic in Matlab? thanks

I am trying to make a parity check matrix from non-systematic to systematic. Hence, I am attaching my code below. Somewhat it is correct, but there are some problems. It would be really great if someone could help me in this.
Subject: Information theory and coding. I am working on LDPC coding and decoding. Please check the code below
MATLAB CODE:
H = [1 0 1 1 0; 0 0 1 0 1; 1 0 0 1 0; 1 0 1 1 1]
[m,n] = size(H);
k = n-m;
for i = k+1:n
%H(:,i)
ind = find(H(:,i),1,'last');
% exchanging (ind)th row and (i-k)th row
if ind < i-k
continue;
end
if ind ~= i-k
temp = H(ind,:);
H(ind,:) = H(i-k,:);
H(i-k,:) = temp;
end
I = find(H(:,i));
% Guassian elimination
for j = 1:length(I)
if I(j) ~= i-k
H(I(j),:) = mod(H(I(j),:)+H(i-k,:),2);
end
end
end
Hsys = H
For e.g.
This is my H matrix:
H =
1 0 1 1 0
0 0 1 0 1
1 0 0 1 0
1 0 1 1 1
I want to have an identity matrix inside the matrix. The dimension on H matrix here is (mxn) which is (4x5).
Generally we use Gaussian elimination method to make the Identity matrix.hence, we make operations between rows. This is how we make it systematic.
I should have matrix as this in the result:
Hsys =
0 1 0 0 0
0 0 1 0 0
1 0 0 1 0
0 0 0 0 1
I should have an identity matrix of dimension m.
Here is how I'd do it (using Gauss-Jordan elimination):
% Not your matrix since it does not have any ones in the second column.
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
rows = size(H, 1);
cols = size(H, 2);
r = 1;
for c = cols - rows + 1:cols
if H(r,c) == 0
% Swap needed
for r2 = r + 1:rows
if H(r2,c) ~= 0
tmp = H(r, :);
H(r, :) = H(r2, :);
H(r2, :) = tmp;
end
end
end
% Ups...
if H(r,c) == 0
error('H is singular');
end
% Forward substitute
for r2 = r + 1:rows
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Back Substitution
for r2 = 1:r - 1
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Next row
r = r + 1;
end

Split Matrix into several depending on value matlab

I am trying to split an nx3 matrix into submatrices in matlab. So my matrix C is of this shape
C =
1 1 1
0 0 0
0 0 0
1 1 1
1 1 1
1 1 1
0 0 0
1 1 1
1 1 1
It either has rows of zeros or rows of ones. I want to split this matrix to only keep matrices of ones. So here for instance there's three 'groups' of ones. so I want to get
C1 =
1 1 1
C2 =
1 1 1
1 1 1
1 1 1
C3 =
1 1 1
1 1 1
However my real matrix is an n by 3, so i don't know where the ones are.
Edit 1:
Now, i need to split x1 and y1 (individual row vectors with same length as C) to x(1), x(2),.. (similarly for y vector) based on how the matrix C was split
Sample Input:
x1 = (1:9)';
y1 = (2:2:18)';
Desired Output:
x(1)=[1], x(2)=[4 5 6]' and x(3)=[8 9]'
y(1)=[2], y(2) =[8 10 12]' and y(3)=[16 18]'
Use find function to the first column to find the indices of 1-elements. Then, calculate the relative distance between any two consecutive elements of the obtained vector to determine the boundary. After that, use matrix indexing to get the blocks of 1-element-matrices. Let me know if you have a better idea.
c=[1 1 1;
0 0 0;
0 0 0;
1 1 1;
1 1 1;
1 1 1;
0 0 0;
1 1 1;
1 1 1;]
b=c(:, 1);
find(b);
I will leave the rest to yourself.
Input:
c = [1 1 1;
0 0 0;
0 0 0;
1 1 1;
1 1 1;
1 1 1;
0 0 0;
1 1 1;
1 1 1;]
x1 = (1:9)';
y1 = (2:2:18)';
Code:
elementalLengthA = cellfun('length',regexp(sprintf('%i',all(C,2)),'1+','match'));
elementalStartA = regexp(sprintf('%i',all(C,2)),'1+','start');
result = cell(length(elementalLengthA),1);
x = cell(length(elementalLengthA),1);
y = cell(length(elementalLengthA),1);
for i = 1:length(elementalLengthA)
result(i) = {C(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
x(i) = {x1(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
y(i) = {y1(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
end
Output:
>> cell2mat(result(1))
ans =
1 1 1
>> cell2mat(result(2))
ans =
1 1 1
1 1 1
1 1 1
>> cell2mat(result(3))
ans =
1 1 1
1 1 1
>> cell2mat(x(3)) %similarly do it for other cells to get results
ans =
8
9

Generate derived matrix from index vector in matlab

Consider an index vector consisting of ones and zeros:
I=[0 0 1 0 1 1 0 0 0];
How can I easily generate the following matrix in matlab:
J=[0 2;
1 1;
0 1;
1 2;
0 3];
Use diff:
I = [0 0 1 0 1 1 0 0 0];
d = diff(I);
ind = [1 find(d~=0)+1]; %// starting index of each new value
rep = diff([ind numel(I)+1]); %// number of repetitions of each new value
J = [ I(ind).' rep.' ];
Using strfind for a slightly bigger example -
I =[1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0]
zero_pos = ['0' num2str(bsxfun(#eq,I,0),'%1d') '0']
ind3 = [ strfind(zero_pos,'01') ; strfind(zero_pos,'10')]
counts = diff(ind3(:))
var = zeros(numel(counts),1);
var(2:2:end)=1;
J = [var counts];
if ind3(1,1)-1>0
J = [1 ind3(1,1)-1;J];
end
Output
J =
1 2
0 2
1 1
0 1
1 2
0 3
1 4
0 2