Is there an efficient way to create a matrix with all permutations of inserting one array into another?

4 views (last 30 days)
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!

Accepted Answer

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

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!