# How do I create a matrix with the diagonals set to 10 and non-diagonals a random integer (0 to 2) where each row sums to 10 (without including diagonal)?

5 views (last 30 days)

Show older comments

I need to create a 15x15 matrix where the diagonals are all 10 and the numbers off the diagonal are a random integer between 0 and 2. I also need that non-diagonal numbers to sum to 10 for each row. See the below matrix, first row for an example.

M =

10 1 0 0 2 0 2 1 1 0 2 0 0 1 0

0 10 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 10 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 10 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 10 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 10 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 10 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 10 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 10 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 10 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 10 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 10 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 10 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 10 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 10

##### 0 Comments

### Accepted Answer

Kirby Fears
on 2 Feb 2016

Edited: Kirby Fears
on 2 Feb 2016

Here's a solution where you can change the values of matrix size, diagonal value, and non diagonal sum. Values between 0 and 2 are drawn to fill the rows. If they sum to the desired value, the row is filled. Otherwise they are redrawn, which ensures randomness.

% settings

matSize = 15;

diagVal = 10;

nonDiagSum = 10;

% Initialize matrix with diagonal filled in

targetMatrix = zeros(matSize);

targetMatrix(1:(matSize+1):end) = diagVal;

% Fill in matrix with random row that sums to nonDiagSum

i = 1;

while i<=matSize,

randValues = randi(3,1,matSize-1)-1;

if (sum(randValues)==nonDiagSum),

idx = true(1,matSize);

idx(i) = false;

targetMatrix(i,idx) = randValues;

i = i+1;

end

end

This executes quickly for your example, but it could take an exceedingly long time to execute if matSize is very different from nonDiagSum.

Hope this helps.

##### 2 Comments

Star Strider
on 2 Feb 2016

### More Answers (2)

John D'Errico
on 2 Feb 2016

Simple.

First, generate all possible partitions of the number 10, as a sum of the integer [0,1,2]. I'll use my partitions function to see how to do it.

partitions(10,[0 1 2],[],10)

ans =

0 10 0

1 8 1

2 6 2

3 4 3

4 2 4

5 0 5

Thus, we can write 10 as

10 ones

8 ones and a 2

6 ones, and a pair of twos

4 ones and 3 twos

2 ones and 4 twos

5 twos

Your matrix has 9 columns in it, if we exclude the diagonal, so we can exclude the case where we have 10 ones.

Once you have generated all possible rows, just select randomly from that set to fill each row.

##### 1 Comment

the cyclist
on 2 Feb 2016

John, that syntax of partitions() gives the error

Error using partitions (line 143)

All members of candidate_set must be > 0

the cyclist
on 2 Feb 2016

matSize = 10;

% Partitions of matSize; Use's John D'Errico's utility from FEX

p = partitions(matSize);

% Exclude those that have values 3-10 in them.

p = p(sum(p(:,3:end),2)==0,:);

% Exclude the partition that is ten 1's, because there are only 9 spots to fill

p(1,:) = [];

% Remove the spurious columns

p(:,all(p==0)) = [];

% Append the zero counts

p = [matSize-1 - sum(p,2), p];

numberRows = size(p,1);

% For each partition, construct all the permutations

allPermutations = [];

for nr = 1:numberRows

basis = [zeros(1,p(nr,1)) ones(1,p(nr,2)) 2*ones(1,p(nr,3))];

thesePermutations = unique(perms(basis),'rows');

allPermutations = [allPermutations; thesePermutations];

end

numberAllPermutations = size(allPermutations,1);

M = matSize * eye(matSize);

for nr = 1:matSize,

rowRand = allPermutations(randi(numberAllPermutations),:);

M(nr,1:nr-1) = rowRand(1:nr-1);

M(nr,nr+1:end) = rowRand(nr:end);

end

##### 2 Comments

the cyclist
on 2 Feb 2016

### See Also

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!