Random integers (no permutation)

Let’s say that I have this working example:
lover_bound = 10;
upper_bound = 180;
steps = 10;
NumeroCestelli = 8;
livello = [lover_bound:steps:upper_bound];
L = length(livello);
n_c = ceil((factorial(L+NumeroCestelli-1))/(factorial(NumeroCestelli)*factorial(L-1)));
randIdxs = randi([1,L],n_c,NumeroCestelli);
PianoSperimentale = single(livello(randIdxs));
I need to perform an `n_c x NumeroCestelli` matrix (called `PianoSperimentale`) where each row is unique. It's not allowed any form of permutation. Using randi I can't perform what I'm asking.
[10 20 30 40 50 60 70 80] is equal to [80 70 60 50 40 30 20 10]
`PianoSperimentale` should be a `1081575x8` matrix. In the past I was using the [Combinator](<http://www.mathworks.com/matlabcentral/fileexchange/24325-combinator-combinations-and-permutations)>) function but is very slow for very large matrix.
[PianoSperimentale] = combinator(L,NumeroCestelli,'c','r');
for i=1:L
PianoSperimentale(PianoSperimentale==i)=livello(i);
end
So, there is a way to perform the same matrix that `combinator` do but with `randi` speed?

Respuestas (2)

Sean de Wolski
Sean de Wolski el 8 de Nov. de 2013
Use randperm with 'k' option
randperm(10,3)
And for more info:
doc randperm

3 comentarios

Gianmarco
Gianmarco el 8 de Nov. de 2013
Editada: Gianmarco el 8 de Nov. de 2013
randperm force me to make something like this:
R = []
for k = 1:n_c
R(k,:) = randperm(L, NumeroCestelli);
end
livello(R);
RR = sort(R')';
unique(RR, 'rows');
toc
but is unusable because is very very slow. I need to perform very very large matrix (1081575x8)
Sean de Wolski
Sean de Wolski el 8 de Nov. de 2013
Editada: Sean de Wolski el 8 de Nov. de 2013
The biggest thing here is preallocation. Simply preallocating R will make this run super fast:
tic
n_c = 1081575;
NumeroCestelli = 8;
L = 180;
R = zeros(n_c,NumeroCestelli);
for k = 1:n_c
R(k,:) = randperm(L, NumeroCestelli);
end
toc
Elapsed time is 3.779653 seconds.
On my relatively wimpy laptop :)
Also, you can specify dimension to sort along, e.g.:
sort(magic(3),2)
Rather than double transposing.

Iniciar sesión para comentar.

Roger Stafford
Roger Stafford el 9 de Nov. de 2013
You can use matlab's 'nchoosek' function to generate your desired matrix. It will find all combinations of k=8 things out of n+k-1=25 where n=18 and where no repetitions are allowed. There will be 25!/17!/8! = 1081575 of these. Then these are manipulated so as to find all combinations of k things out of n where repetitions are permitted. Again there will be 1081575 of these.
Here is code that would accomplish that:
v = 10:10:180; % <-- Your livello
n = length(v); % <-- Your L
k = 8; % <-- Your NumeroCestelli
c = nchoosek(1:n+k-1,k)';
N = size(c,2);
q = false(n+k-1,N);
q(c+(n+k-1)*repmat(0:N-1,k,1)) = true;
p = cumsum(~q,1)+1;
r = reshape(v(p(q)),k,[])'; % <-- Your PianoSperimentale
However I doubt that this is any faster than, or even as fast as, Matt Fig's 'combinator' function.
Note: There is a logical flaw in your for-loop code
[PianoSperimentale] = combinator(L,NumeroCestelli,'c','r');
for i=1:L
PianoSperimentale(PianoSperimentale==i)=livello(i);
end
which you presented. With the first value of i = 1, PianoSperimentale will have every element equal to 1 replaced by 10. Unfortunately when you get to i = 10, these same elements will then all be replaced by 100, which I believe is not what you meant to happen.

Categorías

Más información sobre Random Number Generation en Centro de ayuda y File Exchange.

Productos

Preguntada:

el 8 de Nov. de 2013

Respondida:

el 9 de Nov. de 2013

Community Treasure Hunt

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

Start Hunting!

Translated by