Is there an efficient way to create a matrix with all permutations of inserting one array into another?
1 view (last 30 days)
Show older comments
Hi!
In order to compute the fitness of a specific population with genetic algorithm, I need to generate the population first.
In my case, every chromosome should be created by concatenating 2 partial sub-chromosomes as following:
The 1st sub-chromosome is called as reversing chromosome, which is a flipping left to right of part of an existing array, e.g., the initial array is [1:1:6] and the part of it is selected as [2, 3, 4], thus the reversing chromosome should be [4, 3, 2];
The 2nd sub-chromosome is called as remaining chromosome, which is the subtraction of full array, saying, [1:1:6], and the partial array as mentioned above, [2, 3, 4], thus the remaining chromosome here should be [1, 5, 6];
Next, by inserting the 1st sub-chromosome to every possible position among the 2nd sub-chromosome, saying, the 4 potential spots occupied by "^" of the 2nd sub-chromosome
[ ^, 1, 5, 6 ]
[ 1, ^, 5, 6 ]
[ 1, 5, ^, 6 ]
[ 1, 5, 6, ^ ]
This operation provides 4 chromosomes that I do need, as following:
[ 4, 3, 2, 1, 5, 6 ]
[ 1, 4, 3, 2, 5, 6 ]
[ 1, 5, 4, 3, 2, 6 ]
[ 1, 5, 6, 4, 3, 2 ]
I wrote some codes which worked but they were cumbersome and inefficient:
InitialChromosome = [1:1:6];
poscut1 = 4;
poscut2 = 2;
reverseChromosome = fliplr( InitialChromosome( min([poscut1,poscut2]):1:max([poscut1,poscut2]) ) );
remainingChromosome = InitialChromosome( [1:1:min([poscut1,poscut2])-1,max([poscut1,poscut2])+1:1:end] );
[LB,Ld] = spdiags( tril( ones(length(remainingChromosome),1)*remainingChromosome ) );
[UB,Ud] = spdiags( triu( ones(length(remainingChromosome),1)*remainingChromosome ) );
D = ones(length(remainingChromosome)+1, 1 )*reverseChromosome;
tempMatrix = [[zeros(1,length(remainingChromosome));fliplr( spdiags(LB) )],D,[fliplr( spdiags(UB) );zeros(1,length(remainingChromosome))]];
tempIdx = [Ld-1;[0:1:length(reverseChromosome)-1]';Ud+length(reverseChromosome)];
Population = full( spdiags( tempMatrix,tempIdx,length(remainingChromosome)+1, length(InitialChromosome) ) )
And I also found a way to use the function arrayfun like
tempMatrix = arrayfun(@(ii) [remainingChromosome(1:1:ii-1), reverseChromosome, remainingChromosome(ii:1:end)]', [1:1:length( remainingChromosome )+1] ,'UniformOutput',false);
Population = horzcat(tempMatrix{:})'
Is there any way to create the whole population matrix directly, or more efficiently?
I am not sure if my objective matrix is one of the specific matrix forms such as Toeplitz or Circulant Matrix that could be generated easily with a single built-in command.
Please don't hesitate to post your advices. Any suggestions would be appreciated!
Thanks!
1 Comment
Stephen23
on 14 Jan 2019
InitialChromosome = [1:1:6];
Note that square brackets are a concatenation operator, so they are completely superfluous on that line.
Accepted Answer
Stephen23
on 14 Jan 2019
Edited: Stephen23
on 14 Jan 2019
Perhaps something like this:
>> A = [1,5,6]; % remaining
>> B = [4,3,2]; % reversed
>> N = numel(A);
>> M = toeplitz([B,zeros(1,N)],[B(1),zeros(1,N)]);
>> M(M==0) = repmat(A(:),N+1,1);
>> M = M.'
M =
4 3 2 1 5 6
1 4 3 2 5 6
1 5 4 3 2 6
1 5 6 4 3 2
You can probably simplify the selection of those vectors too, e.g.:
mnp = min([poscut1,poscut2]);
mxp = max([poscut1,poscut2]);
B = InitialChromosome(mxp:-1:mnp);
A = InitialChromosome([1:mnp-1,mxp+1:end]);
More Answers (0)
See Also
Categories
Find more on Frequently-used Algorithms in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!