Search code examples
algorithmmatlabsparse-matrixalgebratelecommunication

How to increase the speed of a doping matrix construction algorithm


I'm using the algorithm shown below to build specific matrices to apply code doping in a quantum error correction scenario. The matrices are binary and must abide by a specific set of construction laws:

  1. There must be p rows with a single unit entry. The rest of the entries of that row will be null, as befits the binary nature of the matrices. Moreover, these unit entries must be placed in different columns for each row. In other words, the unit entries in these p rows can't be placed in the same column, they can't overlap.

  2. The rest of the rows must contain a specific number of unit entries, sb_degree. As I will explain shortly, herein lies the issue.

  3. For a matrix to be suitable for the required purposes (doping of a quantum LDPC code) every row and column must have at least one unit entry. Essentially, the matrix can't have an all zero row or column.

My code works reasonably well for specific combinations of the input algorithm parameters: p (number of rows with a single unit entry), m1 (number of rows of M), N (number of columns of M), and sb_degree (number of ones in the rows that have more than a single unit entry). For instance, it has no trouble finding matrices provided that the values of p and sb_degree aren't too large or small, respectively. However, due to the nature of the problem these matrices aim to solve, I require matrices with a large value of p (about 65% of the value of m1) and a small value of sb_degree. This becomes an issue for my algorithm, as small values of sb_degree make finding a matrix that satisfies the second and third construction requirements an ardous task.

Ideally, I'd like to be able to speed up this search so that I can get my hands on the type of matrices that I need to help in my quantum error correction research. I have included my Matlab code to provide context on how I am constructing the matrices. I'd be grateful if any of you can think of a way to make my code faster or come up with a different way to perform the construction of these matrices.

The algorithm is called as M = Create_Doping_Matrix(m1,N,p,sb_degree) and is implemented as follows

M = zeros(m1,N);
p_indexes = randperm(m1,p);
all_indexes = 1:m1;
idx = ~ismember(all_indexes,p_indexes);
loc = find(idx~=0);
c_indexes = randperm(N,p);
% Create the rows with a single unit entry
for ii=1:p
    M(p_indexes(ii),c_indexes(ii)) = 1;
end
M_orig = M;
% Create the rows with more than a single unit entry
for jj = 1:length(loc)
    M(loc(jj), randperm(N,sb_degree))=1;
end

while nnz(sum(M,1)) ~= N % Check that there are no all-zero rows
    M = M_orig;
    for jj = 1:length(loc)
        M(loc(jj), randperm(N,sb_degree))=1;
    end
end

Solution

  • Rather than place values randomly until all columns have an entry, I would assign a row to all of the columns, and then fill in the m1-p rows until they each have sb_degree nonzero entries.

    M = zeros(m1,N);
    p_indexes = randperm(m1,p);
    all_indexes = 1:m1;
    idx = ~ismember(all_indexes,p_indexes);
    loc = find(idx~=0);
    c_indexes = randperm(N,p);
    % Create the rows with a single unit entry
    for ii=1:p
        M(p_indexes(ii),c_indexes(ii)) = 1;
    end
    

    Code is the same up to here. Now, ensure that every column has exactly one nonzero entry. Note that the loc rows can be assigned more than one 1 value by this process, up to sb_degree.

    % Add one entry to each unfilled column of M on an unfilled row of M(loc,:)
    missing = find(sum(M,1) == 0);
    
    for fillcol = missing
       addtoidx = randi(numel(loc));   % select random row from loc 
       fillrow = loc(addtoidx);   % row number in M
       M(fillrow, fillcol) = 1;
       if (sum(M(fillrow,:)) >= sb_degree)   % this row is now full 
          loc(addtoidx) = [];   % remove it from loc 
       end
    end
    

    And finally, fill up the loc rows with sb_degree ones.

    % Fill the rows that need more than a single unit entry
    % but still contain less than sb_degree
    for jj = 1:length(loc)   
       thisrow = M(loc(jj),:);   % unfilled row from M
       emptycols = find(thisrow == 0);   % indices of columns of thisrow not yet filled
       fillidx = randperm(numel(emptycols), sb_degree - sum(thisrow));
       M(loc(jj), emptycols(fillidx))=1;
    end