En R, si configuro.seed () y luego uso la función de muestra para aleatorizar una lista, ¿puedo garantizar que no generaré la misma permutación?
es decir...
set.seed(25)
limit <- 3
myindex <- seq(0,limit)
for (x in seq(1,factorial(limit))) {
permutations <- sample(myindex)
print(permutations)
}
Esto produce
[1] 1 2 0 3
[1] 0 2 1 3
[1] 0 3 2 1
[1] 3 1 2 0
[1] 2 3 0 1
[1] 0 1 3 2
¿Todas las permutaciones impresas serán permutaciones únicas? ¿O hay alguna posibilidad, en función de la forma en que se implementa, de que pueda obtener algunas repeticiones?
Quiero poder hacer esto sin repeticiones, garantizado. ¿Como podría hacerlo?
(También quiero evitar tener que usar una función como permn (), que tiene un método muy mecanicista para generar todas las permutaciones --- no parece aleatorio).
Además, nota al margen --- parece que este problema es O ((n!)!), Si no me equivoco.
r
sampling
combinatorics
resampling
Mittenchops
fuente
fuente
limit
excede de 12, es probable que se quede sin RAM cuando R intente asignar espacio paraseq(1,factorial(limit))
. (12! Requiere aproximadamente 2 GB, por lo que 13! Necesitará aproximadamente 25 GB, 14!Respuestas:
La pregunta tiene muchas interpretaciones válidas. Los comentarios, especialmente el que indica que se necesitan permutaciones de 15 o más elementos (15! = 1307674368000 se está haciendo grande), sugieren que lo que se desea es una muestra aleatoria relativamente pequeña , sin reemplazo, de todo n! = n * (n-1) (n-2) ... * 2 * 1 permutaciones de 1: n. Si esto es cierto, existen soluciones (algo) eficientes.
La siguiente función,
rperm
acepta dos argumentosn
(el tamaño de las permutaciones para muestrear) ym
(el número de permutaciones de tamaño n para dibujar). Si m se aproxima o excede n !, la función tomará mucho tiempo y devolverá muchos valores de NA: está destinada a usarse cuando n es relativamente grande (digamos, 8 o más) ym es mucho más pequeño que n !. Funciona almacenando en caché una representación de cadena de las permutaciones encontradas hasta ahora y luego generando nuevas permutaciones (al azar) hasta que se encuentre una nueva. Explota la capacidad asociativa de indexación de listas de R para buscar rápidamente la lista de permutaciones encontradas previamente.La naturaleza de
replicate
es devolver las permutaciones como vectores de columna ; por ejemplo , lo siguiente reproduce un ejemplo en la pregunta original, transpuesta :Los tiempos son excelentes para valores pequeños a moderados de m, hasta aproximadamente 10,000, pero se degradan para problemas más grandes. Por ejemplo, se obtuvo una muestra de m = 10,000 permutaciones de n = 1000 elementos (una matriz de 10 millones de valores) en 10 segundos; una muestra de m = 20,000 permutaciones de n = 20 elementos requirió 11 segundos, a pesar de que la salida (una matriz de 400,000 entradas) fue mucho menor; y la muestra de cálculo de m = 100,000 permutaciones de n = 20 elementos fue abortada después de 260 segundos (no tuve la paciencia para esperar a que se completara). Este problema de escala parece estar relacionado con las ineficiencias de escala en el direccionamiento asociativo de R. Uno puede evitarlo generando muestras en grupos de, digamos, aproximadamente 1000, luego combinando esas muestras en una muestra grande y eliminando duplicados.
Editar
Podemos lograr un rendimiento asintótico casi lineal al dividir el caché en una jerarquía de dos cachés, de modo que R nunca tenga que buscar en una lista grande. Conceptualmente (aunque no según lo implementado), cree una matriz indexada por los primeros elementos de una permutación. Las entradas en esta matriz son listas de todas las permutaciones que comparten esos primeros elementos. Para verificar si se ha visto una permutación, use sus primeros elementos para encontrar su entrada en el caché y luego busque esa permutación dentro de esa entrada. Podemos elegir para equilibrar los tamaños esperados de todas las listas. La implementación real no usa unak k k kk k k k k -fold array, que sería difícil de programar con suficiente generalidad, pero en su lugar usa otra lista.
Estos son algunos tiempos transcurridos en segundos para un rango de tamaños de permutación y números de permutaciones distintas solicitadas:
(La aceleración aparentemente anómala de tamaño = 10 a tamaño = 15 se debe a que el primer nivel de la memoria caché es más grande para tamaño = 15, lo que reduce el número promedio de entradas en las listas de segundo nivel, lo que acelera la búsqueda asociativa de R. En algunos costo en RAM, la ejecución podría hacerse más rápido aumentando el tamaño de caché de nivel superior. Simplemente aumentando
k.head
en 1 (que multiplica el tamaño de nivel superior por 10) acelerórperm(100000, size=10)
de 11.77 segundos a 8.72 segundos, por ejemplo. caché 10 veces más grande pero no logró una ganancia apreciable, registrando a 8.51 segundos).A excepción del caso de 1,000,000 de permutaciones únicas de 10 elementos (una porción sustancial de los 10! = Alrededor de 3.63 millones de permutaciones), prácticamente no se detectaron colisiones. En este caso excepcional, hubo 169.301 colisiones, pero no hubo fallas completas (de hecho, se obtuvo un millón de permutaciones únicas).
Tenga en cuenta que con tamaños de permutación grandes (más de 20 o menos), la posibilidad de obtener dos permutaciones idénticas incluso en una muestra tan grande como 1,000,000,000 es muy pequeña. Por lo tanto, esta solución es aplicable principalmente en situaciones donde (a) un gran número de permutaciones únicas de (B) entre y o así elementos son a generarse pero aún así, (c) sustancialmente menos de todos losSe necesitan permutaciones.n = 15 n !n=5 n=15 n!
El código de trabajo sigue.
fuente
> rperm(6,3) $failures [1] 9 $sample [,1] [,2] [,3] [1,] 3 1 3 [2,] 2 2 1 [3,] 1 3 2 [4,] 1 2 2 [5,] 3 3 1 [6,] 2 1 3
Usar
unique
de la manera correcta debería hacer el truco:fuente
I "m va a paso de lado a su primera pregunta un poco, y sugieren que si su están tratando con vectores relativamente cortos, simplemente podría generar todas las permutaciones usando
permn
y les ordenará al azar los utilizandosample
:fuente
permn(10)
o lo que sea solo una vez.set.seed
: describe cómo guardar el estado del RNG y restaurarlo más tarde.