A.2 Generate example matrix suitable for row-reduction

My most-used example generator is the genrowred function which starts with a random matrix in REF, then does \(n + m\) random row operations.

Warning

Most \(m\times n\) matrices created with integers suffer from the problem that row-reducing them by-hand often produces ugly denominators.

The genrowred function itself calls several other functions, all of which are shown below.

The genrowred function code

function myMatrix = genrowred(M, N, k)
    % Input Validation
    arguments
        M (1,1) {mustBeInteger, mustBePositive}
        N (1,1) {mustBeInteger, mustBePositive}
        k (1,1) double = M + N;
    end
    % Additionally, n <= 8
    m = min(8, M);
    n = min(8, N);

% Initialize matrix C to ensure the while loop runs at least once
C = eye(2)*100*n*m;

while (sum(sum(C))) > max(100,10 * m * n ) | (sum(sum(isnan(C))) > 0)
    A = genpivots(m,n);
    B = fillAbovePivots(A);
    C = fillZeroCols(B);
    D = randRowOps(C,k);
end
myMatrix = D;
% Can use code below to add result to clipboard
clipboard('copy',myMatrix);
end

Watch it run

I executed the code block below and printed out the final matrices \(A,B,C,D\) the function produced.

genrowred(3,5)
\[\begin{split}A = \left[\begin{array}{rrrrr}4&0&0&0&0\\0&4&0&0&0\\0&0&0&3&0\\\end{array}\right] \\ B = \left[\begin{array}{rrrrr}4&5&0&0&0\\0&4&0&-1&0\\0&0&0&3&0\\\end{array}\right] \\ C = \left[\begin{array}{rrrrr}4&5&0&3&0\\0&4&5&-1&0\\0&0&0&3&5\\\end{array}\right] \end{split}\]
\[\begin{split}D = \left[\begin{array}{rrrrr}-40&-42&10&-17&25\\40&46&-5&16&-25\\4&5&0&3&0\\\end{array}\right]\end{split}\]

The Subroutines

genpivots

function myMatrix = genpivots(M,N)
% Input Validation
    arguments
        M (1,1) {mustBeInteger, mustBePositive};
        N (1,1) {mustBeInteger, mustBePositive};
    end
    % Additionally, m,n <= 8
    m = min(10, M);
    n = min(10, N);

% Determine maximal square dimensions inside matrix
minLength = min(m,n);

% Random diagonal square matrix with dimension minLength
A = gendiag(minLength);

% Add rows or columns of zeros until matrix M has dimensions m x n
while ( length(A) < m )  | ( length(A) < n )
    if length(A) < m
        v = zeros(1,length(A(1,:)));
        A = [A;v];
    else
        v = zeros(length(A(:,1)),1);
        A = [A , v];
    end
end

    % Take zero-columns from end, inserts them randomly in between non-zero-columns.
    if m < n
        [m,n] = size(A);
        p = 1:length(A);
        q = p;
        r = max(m,n);
        s = min(m,n);
        t = r-s;
        v = sort(randsample(1:s,min(t,s)), 'descend');
        for k = v
            p = [p(1:k),p(end),p(k+1:end-1)];
        end
    A(:,q) = A(:,p);
    end

% Move all zero-rows to bottom of matrix, required for REF
myMatrix = zRows2btm(A);
end

fillAbovePivots

function myMatrix = fillAbovePivots(A)
    arguments
        A (:,:,:)
    end

[m,n] = size(A);

for j = 1:n
        nZ = firstNonZero(A(:,j));
        if ( nZ <= m) & ( nZ > 1 ) & ( sum(A(:,j) ~= 0) )
            for i = 1:(nZ - 1)
                A(i,j) = randsample([-2:5],1);
            end
        end
    end
myMatrix = A;
end

fillZeroCols

function myMatrix = fillZeroCols(A)
    % Input Validation
    arguments
        A (:,:,:)
    end
[m,n] = size(A);
for j = 2:n
    for i = 1:m
        if ( A(i,j) == 0) & ( sum(A(i,1:j)) ~= 0 )
            A(i,j) = randsample(-2:5,1);
    end
end
    
myMatrix = A;
% Can use code below to add result to clipboard
% clipboard('copy',myMatrix);
end

randRowOps

function myMatrix = randRowOps(A,N)
    % Input Validation
    arguments
        A (:,:,:) 
        N (1,1) {mustBeInteger, mustBePositive}
    end
    % Additionally, n <= 8
    n = min(20, N);

[m,q] = size(A);
    
for i = 1:n
    k = randsample(1:6,1);
    if k == 1
        A = randRowOp1(A);
    else if k < 3
            A = randRowOp2(A);
        else
            A = randRowOp3(A);
        end
    end
end

for i = 1:m
    A(i,:) = A(i,:) / gcd(sym( A(i,:)));
end

myMatrix = A;
end