Permuting elements in an symmetrical matrix with restricted outcomes
Afficher commentaires plus anciens
I would like to derive all possible permutations of a matrix A = [0 2 0 1; 2 0 1 0; 0 1 0 1; 1 0 1 0] by permuting the positions of elements with the following restrictions:
[1] Diagonal elements can only be "0" or "2" (i.e. the permuated matrix A = [0 2 0 1; 0 1 2 0; 0 1 0 1; 1 0 1 0] would NOT be valid as "1" is a diagonal element
[2] The positions and values (i.e. 0, 1 or 2) of elements (not including diagonal elements) must be "mirrored" across the diagonal (i.e. the permuted matrix A = [0 2 0 1; 2 0 1 0; 1 0 0 1; 0 1 1 0] is NOT valid
Can someone help me with a code for this ?
Thus far I have been generating all possible permutation matrices for this 4 x 4 matrix (4!) and iteratively multiplying the matrix A by each permutation matrix but I am not sure if I can derive all possible permutations using this method (not to mention it being extremely time consuming as eventually I will be permuting many more, larger matrices)
Réponse acceptée
Plus de réponses (2)
Maxwell Day
le 26 Jan 2020
0 votes
3 commentaires
Adam Danz
le 26 Jan 2020
Something like this?
for i = 1:size(A_PERM_UNQ,3)
A2 = A_PERM_UNQ(:,:,i) * A1 * A_PERM_UNQ(:,:,i)^(-1);
end
Maxwell Day
le 26 Jan 2020
Adam Danz
le 26 Jan 2020
A_PERM_UNQ came from my answer - it contains the the permutations of A.
I don't know what A1 is supposed to be.
Maxwell Day
le 1 Fév 2020
Modifié(e) : Stephen23
le 1 Fév 2020
10 commentaires
Adam Danz
le 1 Fév 2020
I don't recall claiming that it would work on 6x6 arrays. With that matrix size, you've got 15 values in the lower triangle below the diagonal. That's 1.3077e+12 permutations which, as you can see, is beyond the maximum array size set in the preferences.
factorial(numel(trilIdx))
1.3077e+12
The development of this algorithm changed a lot over time as the rules were changed and new rules were added. In the end, the algorithm is doing a heck of a lot of work and then toss most of it away. That's inefficient. There's likely a better solution. Could you summarize all of the rules as precisely as possible in a bulleted list? That may help in inspire an alternative.
Maxwell Day
le 10 Fév 2020
Adam Danz
le 10 Fév 2020
The bottleneck is the perms() function that causes memory problems when the input vector exceeds ~10 elements (or even less).
1) Instead of computing all of the permutations at once (which will not be possible), you'll need to compute the permutations in chunks and fully analyze each chunk prior to generating the next chunk. Here are two FEX functions that you can check out (I haven't used either of them).
2) Most of the algorithm we already have will still be used. However, instead of building all possible matrix combinations and then eliminating the ones that don't fulfill all of the requirements, generate the permuted matrices one at a time within a loop and run each test on that matrix. If it doesn't pass all of the tests, toss it. Most will be tossed and this could still take a while to run. But it should avoid the memory restrictions imposed by perms().
Maxwell Day
le 10 Fév 2020
Adam Danz
le 10 Fév 2020
"I am assuming all the perms() functions need to be replaced or changed. How do we do this to permute only a "chunk" of matrices ?"
The perms() function will need replaced. In my previous comment I recommended two functions to check out on the file exchange (I've never used either of them - you can decided which one is best).
After you do that, "trilPerms" will not be a full list of permutations, I will only contain a subset of them, or maybe even just one permutation at a time, depending on which function you choose and how you use it. Perhaps it would be easiest just to produce one at a time. If you do it in small chunks it might (?) be faster but you'll still need to loop over single permutations.
You can probably still use the permn function since there are only 2 possible values.
The code is currently computing all permutation and looping through them starting at
for i = 1:size(trilPerms,1)
for j = 1:size(diagPerms,1)
But now trilPerms will only be 1 permutation or a chunk of permutations. The permuted matrix is called 'base' and the current code is saving all of them. You'll change this. Instead, you'll perform all of the tests on "base" and only if it passes all of the tests will you store it in A_PERM. Otherwise, you won't store it and you'll move on to the next permutation.
It's a good idea to save a copy of your current code so you can go back and reference it. When you're done with the new version, run a small input matrix through both versions and make sure you're getting the same results.
Lastly, it would be a good investment of your time to go through the existing code you shared above, line by line, to make sure you understand exactly what's happening. It will be much easire to redesign it if you know what it's doing.
Maxwell Day
le 12 Fév 2020
Maxwell Day
le 27 Fév 2020
Adam Danz
le 27 Fév 2020
Looks like you're missing the comma
trilPerms = nthperm(trilIdx, 1)
^
Maxwell Day
le 27 Fév 2020
Adam Danz
le 27 Fév 2020
goodRows = ismember(squeeze(sort(sum(A_PERM,2))).',[2 2 3 3],'rows');
goodRows (a column vector) is all False values. In other words, the [2 2 3 3] vector is not found anywhere in the permuration sums.
squeeze(sort(sum(A_PERM,2))).'
Catégories
En savoir plus sur Matrices and Arrays dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!