2010-09-14 8 views
11

Un dispositivo contiene una matriz de ubicaciones, algunas de las cuales contienen valores que queremos leer periódicamente.Algoritmo para encontrar grupos óptimos

Nuestra lista de ubicaciones que queremos leer periódicamente también especifica con qué frecuencia queremos leerlas. Se permite leer un valor con mayor frecuencia que la especificada, pero no con menos frecuencia.

Una sola operación de lectura puede leer una secuencia contigua de ubicaciones de la matriz, por lo que es posible devolver un grupo de valores múltiples desde una operación de lectura. El número máximo de ubicaciones contiguas que se pueden leer en una sola operación es M.

El objetivo es agrupar las ubicaciones para minimizar el número promediado en el tiempo de las operaciones de lectura. En el caso de que haya más de una forma de hacerlo, el desempate consiste en minimizar el número de ubicaciones promediado en el tiempo.

(puntos de bonificación se otorgan si el algoritmo para hacer esto permite que los cambios graduales en la lista de ubicaciones - es decir, agregar o quitar un lugar a/de la lista no requiere las agrupaciones que volver a calcular a partir de cero)

Trataré de aclarar esto con algunos ejemplos donde M = 6.

El siguiente diagrama muestra la matriz de ubicaciones. Los números representan el período de lectura deseado para esa ubicación.

| 1 | 1 | | | 1 | | | | | | 5 | | 2 | 
\-------------------/     \-----------/ 
    group A        group B 

En este primer ejemplo, el grupo A se lee cada segundo y el grupo B cada 2 segundos. Tenga en cuenta que la ubicación que debe leerse cada 5 segundos se lee realmente cada 2 segundos, lo cual está bien.

| 1 | | | | | 1 | 1 | | 1 | 
\-----------------------/\----------/ 
     group A   group B   (non-optimal!) 

En este ejemplo se muestra un error de mi algoritmo simplista inicial, que consistía en llenar el primer grupo hasta la saciedad y luego comenzar otra. La siguiente agrupación es más óptima porque aunque el número de grupo lee por segundo es el mismo, el número de ubicaciones leer en esos grupos es menor:

| 1 | | | | | 1 | 1 | | 1 | 
\---/    \---------------/ 
group A     group B   (optimal) 

Finalmente, un ejemplo en el que tres grupos es mejor que dos:

| 5 | | | | | 1 | 1 | | | | | 5 | 
\-----------------------/\----------------------/ 
     group A     group B (non-optimal) 

Esta solución requiere dos lecturas grupales por segundo. Una mejor solución es la siguiente:

| 5 | | | | | 1 | 1 | | | | | 5 | 
\---/    \-------/    \---/ 
group A    group B    group C 

Esto requiere dos lecturas cada 5 segundos (grupos A y C) más uno cada segundo (grupo B): 1,4 grupo lee por segundo.

Editar: (Hay una solución aún mejor para este ejemplo si permite que las lecturas sean no periódicas. En el 1er segundo, lea los dos grupos de la primera solución. En los segundos 2, 3, 4 y 5 lea el grupo B de la segunda solución. Repita. Esto da como resultado 1.2 lecturas grupales por segundo. Pero no lo permitiré porque haría que el código sea responsable de programar las lecturas mucho más complicado.)

Busqué algoritmos de clústeres pero este no es un problema de agrupamiento También encontré Algorithm to allocate a list of numbers to N groups under certain condition, lo que apuntó al problema del "contenedor de basura", pero tampoco creo que sea esto.

Por cierto, perdón por el título vago. No puedo pensar en una descripción concisa, ni siquiera en palabras clave de búsqueda relevantes.

Nuevos ejemplos añadido 28 Septiembre 2010:

Esto es como el ejemplo anterior, pero todos los elementos de la actualización a la misma velocidad. Ahora dos grupos es mejor que tres:

| 1 | | | | | 1 | 1 | | | | | 1 | 
\-----------------------/\----------------------/ 
     group A     group B   (optimal) 

He empezado a tratar de ver cómo se pueden implementar las mejoras iterativas. Supongamos que un algoritmo de agrupación se acercó con:

| 1 | | | | | 1 | 1 | | | | | 1 | 1 | | | | | 1 | 
\---/    \-------/    \-------/    \---/ 
group A    group B     group C    group D (non-optimal) 
\-----------------------/\----------------------/\----------------------/ 
     group A     group B     group C   (optimal) 

Esto puede ser mejorado a tres grupos adyacentes cada uno de 6. Rex sugirió (comentario a continuación) que podía probar la combinación de tripletes en parejas. Pero en este caso tendría que combinar un cuarteto en un triplete, porque no hay una disposición intermedia legal en la que A + B + C (o B + C + D) se pueda reorganizar en un par dejando D tal como está.

Originalmente pensé que esto era una indicación de que en el caso general no hay garantía de que se pueda crear una nueva solución válida a partir de una solución válida existente haciendo una modificación local. Esto habría significado algoritmos como el recocido simulado, algoritmos genéticos, etc., podrían usarse para tratar de refinar una solución subóptima.

Pero Rex señaló (comenta a continuación) que siempre puedes dividir un grupo existente en dos. A pesar de que esto siempre aumenta la función de costos, todo lo que significa es que la solución necesita salir de su mínimo local para alcanzar el mínimo global.

+0

que iba a decir siempre se puede agrupar elementos adyacentes con el mismo tiempo (grupo B en su último ejemplo) pero eso puede no ser cierto es en casos de esquina donde M entra en juego. Señala una estrategia de construir progresivamente grupos más grandes con reglas sensatas.¿Qué tan grande es el tamaño de su problema? – phkahler

+0

Parece que podría ser un problema NP-Completo o al menos un problema NP-Hard en el caso teóricamente óptimo. Puede intentar volver a publicarlo en [CS Theory Stack Exchange] (http://cstheory.stackexchange.com/). –

+0

@phkahler: En mi caso particular, M es alrededor de 100, el tamaño de la matriz puede ser de 1 a 30000 o más, pero normalmente unos pocos cientos, y el número de ubicaciones quería algo entre 1 y 100 más o menos. –

Respuesta

4

Este problema tiene la misma propiedad de inestabilidad en la adición de elementos nuevos que los problemas NP-completos similares, así que supongo que es uno también. Como sospecho que quiere algo que funciona razonablemente bien en lugar de una prueba de por qué es difícil, me centraré en un algoritmo para dar una solución aproximada.

Resolvería este problema convirtiendo esto en un gráfico donde los contenedores se valoraban en 1/N si tenían que leerse N veces por segundo, y desenfoque el gráfico con un ancho de M (por ejemplo 6), picos en el original. (Para 6, podría usar la ponderación (1/6 1/5 1/4 1/3 1/2 1 1/2 1/3 1/4 1/5 1/6). Luego arroje los contenedores a todos los locales maxima (clasifique los pares por distancia y cubra los pares cercanos de los máximos si puede). Ahora tendrá cubiertos la mayoría de sus valores más importantes. Luego capture los grupos que faltan al extender las lecturas existentes o agregando nuevas lecturas si es necesario. Dependiendo de la estructura, es posible que desee agregar algún refinamiento cambiando las ubicaciones entre lecturas, pero si tiene suerte, eso ni siquiera será necesario.

Dado que este es esencialmente un algoritmo local, si realiza un seguimiento del gráfico borroso, puede fácilmente agregar nuevos elementos y volver a hacer el cubrimiento máximo localmente (y el refinamiento localmente).

Sólo para ver cómo funcionaría en sus datos, el caso de dos grupos se vería así (multiplicando por 60, así que no tengo que llevar un registro de los pesos fraccionarios)

60 30 20 15 12 10 00 00 00 <- contribution from left-most location 
10 12 15 20 30 60 30 20 15 <- second 
00 10 12 15 20 30 60 30 20 <- third 
00 00 00 10 12 15 20 30 60 <- rightmost 
-------------------------- 
70 42 47 50 74 B5 B0 80 95 (using "B" to represent 11) 
^^    ^^  ^^ Local maxima 
    ------------- ------- 
    dist=6  dist=4 
       |===========| <- Hit closely-spaced peaks first 
|==|       <- Then remaining 

Así que' re hecho, y la solución es óptima.

Para el ejemplo de tres grupos, ponderando "5" como "1/5" y multiplicando por 300 todo lo que de nuevo no hay fracciones,

060 030 020 015 012 010 000 000 000 000 000 000 <- from 5 on left 
050 060 075 100 150 300 150 100 075 060 050 000 <- 1 on left 
000 050 060 075 100 150 300 150 100 075 060 050 <- on right 
000 000 000 000 000 000 010 012 015 020 030 060 <- 5 on right 
----------------------------------------------- 
110 140 155 190 262 460 460 262 190 155 140 110 
        |=======|      <- only one peak, grab it 
===           === <- missed some, so pick them back up 
+0

OK, estoy de vuelta en esto ahora. Desafortunadamente, el algoritmo anterior falla en el último ejemplo si todos los elementos se actualizan a la misma velocidad: obtienes los mismos tres grupos, mientras que solo debes obtener dos. Estoy tratando de ver si puedo ajustar el algoritmo para corregir esto, pero parece fundamentalmente difícil hacer que prefiera un grupo más grande para satisfacer lo que es esencialmente un criterio no local (mininizing number of groups). –

+0

Podría intentar repetidamente triplicar a pares hasta que no se mejoren las tripletas si se reescriben como pares. –

+0

He agregado un poco más a la pregunta original. Tal vez debería explicar por qué estoy tan preocupado por esto. Espero que, en la mayoría de los casos prácticos, el número de grupos en el caso óptimo sea pequeño: solo uno, dos o tres tal vez. Por lo tanto, agregar un solo grupo adicional es un costo adicional muy grande, en términos relativos. Me hace preguntarme si un ataque de fuerza bruta podría ser la respuesta ... –

Cuestiones relacionadas