¿Cómo puedo obtener una lista de todas las particiones posibles de un vector en R cuando el vector es grande?

Estoy tratando de usar R para encontrar todas las formas posibles de dividir el vector x de longitud n a lo sumo m particiones Sé cómo hacer entonces cuando n es pequeño:

library(partitions)
x <- c(10, 20, 30, 40)
n <- length(x)
m <- 3

# In how many ways can we partition n objects into at most m patitions
parts <- restrictedparts(n, m)
sets <- setparts(parts)

En este ejemplo, el valor de sets es:

[1,] 1 1 1 1 2 1 1 1 1 1 1 2 2 2
[2,] 1 1 1 2 1 2 1 2 2 1 2 1 1 3
[3,] 1 2 1 1 1 2 2 1 3 2 1 3 1 1
[4,] 1 1 2 1 1 1 2 2 1 3 3 1 3 1

Cada columna de sets me dice, para cada arreglo único, en qué partición cada elemento en x debe ser asignado.

El problema ocurre cuando n es largo:

n <- 15
m <- 4
parts <- restrictedparts(n, m)
# This expression will max out your CPU usage and eventually run out of memory.
sets <- setparts(parts)

¿Cómo puedo hacer esta operación sin quedarme sin memoria? Dudo que haya una forma rápida de hacerlo, así que sospecho que tendré que hacerlo por lotes y escribir en el disco.

preguntado el 13 de enero de 13 a las 16:01

cuando tu dices en al menos m puntajes, Quiere decir a lo sumo? -

Sí, gracias por señalar el error tipográfico. -

Consejo: la descripción del nextpart en función de la partition bibliotecas documentación es probablemente la clave. -

La última parte del código escrito anteriormente genera errores de asignación de memoria en mi máquina (OSX 10.8.2, R 2.15.1, partición 1.9-12, 4 GB de memoria). Funciona en el tuyo? -

Estoy viendo el mismo resultado que tú. No creo que @flodel sea correcto es su declaración re: el límite superior para este problema. Si miras primero restrictedparts(15,4) Y luego usar choose(.,.) al mirar los números en cada columna se puede ver la explosión combinatoria. Superé ese límite cuando llegué a ncol( setparts( restrictedparts(15,4)[,1:13])) y hay 54 columnas en restrictedparts(15,4) -

3 Respuestas

Si como yo no eres una superestrella en combinatoria pero confías en eso partitions tiene razón, entonces al menos puede hacer uso del código del paquete para calcular el número final de particiones. Aquí hackeé el setparts función por lo que, en lugar de las particiones en sí, devuelve el número de particiones:

num.partitions <- function (x) {
    if (length(x) == 1) {
        if (x < 1) {
            stop("if single value, x must be >= 1")
        }
        else if (x == 1) {
            out <- 1
        }
        else return(Recall(parts(x)))
    }
    if (is.matrix(x)) {
        out <- sum(apply(x, 2, num.partitions))
    }
    else {
        x   <- sort(x[x > 0], decreasing = TRUE)
        out <- factorial(sum(x))/(prod(c(factorial(x), 
                                         factorial(table(x)))))
    }
    return(out)
}

Verifiquemos que la función devuelva el número correcto de particiones:

num.partitions(restrictedparts(4, 3))
# [1] 14
ncol(setparts(restrictedparts(4, 3)))
# [1] 14

num.partitions(restrictedparts(8, 4))
# [1] 2795
ncol(setparts(restrictedparts(8, 4)))
# [1] 2795

Ahora echemos un vistazo a su gran caso:

num.partitions(restrictedparts(15, 4))
# [1] 44747435

De hecho, son muchas particiones... Sin importar qué tan bien o no setparts está escrito, la salida no puede caber en una sola matriz:

sets <- matrix(1, 15, 44747435)
# Error in matrix(1, 15, 44747435) : 
#  cannot allocate vector of length 671211525

Entonces, sí, tendría que escribir su propio algoritmo y almacenarlo en una lista de matrices, o si es demasiado para su memoria, escribir en un archivo si eso es realmente lo que quiere hacer. De lo contrario, dada la gran cantidad de permutaciones y lo que quiere hacer con ellas, vuelva a la mesa de dibujo...

Respondido el 13 de enero de 13 a las 21:01

Gracias por calcular el tamaño de la matriz de partición; esto la convierte en la respuesta más útil. Estoy seguro de que sería posible aplicar fuerza bruta a esto reescribiendo setparts() con una biblioteca como ff, pero voy a intentar resolver mi problema (la distribución esperada de puntos en un juego de cartas) usando un método de Monte Carlo. - divinanefrona

Si desea calcularlos en lotes, parece que esto puede ser posible para al menos algunas de las columnas. No pude completar un cálculo de varias de las columnas individuales en restrictedparts(15,4) en una máquina como la tuya. Hasta la columna 40 pude tener éxito en lotes de 5-10 columnas a la vez, pero por encima de eso había varias columnas individuales que informaron una cantidad de columnas antes de arrojar un error malloc. Entonces, es posible que simplemente necesite una máquina más grande. En mi Mac que tiene 32 GB, la construcción de la columna 53 consumió la mitad de la memoria. Las estimaciones del número de columnas en la máquina grande coincidieron con el informe de la máquina de 4GB:

> ncol( setparts( restrictedparts(15,4)[,53]))
[1] 6306300
R(317,0xa077a720) malloc: *** mmap(size=378380288) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

(No ofrezco ninguna opinión sobre si este es un proyecto sensato).

Respondido el 13 de enero de 13 a las 18:01

Como no pude instalar el paquete de particiones (bibliotecas faltantes), se me ocurrió esto:

 ## Recursive function to get all partitions of a vector 
 ## Returns a list of logical vectors
 parts <- function(x) { 
   if (length(x) == 1) return(list(FALSE, TRUE))
   do.call(c, lapply(parts(x[-1]), function(y) list(c(FALSE, y), c(TRUE, y))))
 }

Esta función toma un vector y devuelve una lista de vectores lógicos del mismo tamaño. El número de vectores en la lista es el número de particiones posibles, (2^n). No puede manejar un n enorme, pero en mi PC ejecuta n=19 en menos de un segundo.

Si solo desea las particiones no vacías y sin duplicados, use:

 partitions <- parts(x)
 partitions <- partitions[1:(length(partitions)/2)][-1]

Respondido el 30 de enero de 18 a las 11:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.