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 Creating and Concatenating Matrices 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!