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)?

12 ビュー (過去 30 日間)
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

採用された回答

Kirby Fears
Kirby Fears 2016 年 2 月 2 日
編集済み: Kirby Fears 2016 年 2 月 2 日
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 件のコメント
Josh
Josh 2016 年 2 月 2 日
This works great! Thank you!!
Star Strider
Star Strider 2016 年 2 月 2 日
@Kirby — Write your code up as a function and contribute it to the File Exchange. I did with a similar Answer that I thought was a one-off, and it's already gotten a bunch of downloads. I was quite pleasantly surprised.

サインインしてコメントする。

その他の回答 (2 件)

John D'Errico
John D'Errico 2016 年 2 月 2 日
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 件のコメント
the cyclist
the cyclist 2016 年 2 月 2 日
編集済み: the cyclist 2016 年 2 月 2 日
John, that syntax of partitions() gives the error
Error using partitions (line 143)
All members of candidate_set must be > 0
for me, using R2015b on a Mac. I have the latest update from here.

サインインしてコメントする。


the cyclist
the cyclist 2016 年 2 月 2 日
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 件のコメント
the cyclist
the cyclist 2016 年 2 月 2 日
編集済み: the cyclist 2016 年 2 月 2 日
This is vastly slower than Kirby's solutions, probably because I am lazily generating many more partitions than required. Combining John's own more efficient use of partitions() in his answer would be much better. Unfortunately, I could not get his syntax to work.
the cyclist
the cyclist 2016 年 2 月 2 日
Oops. Nope. I just profiled my code. The slowness is NOT the partitioning, even though I am using it dumbly. The slow part is generating the permutations.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeOperating on Diagonal Matrices についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by