2010-12-28 9 views
5

Supongamos que tenemos billones de conjuntos almacenados en alguna parte. El dominio para cada uno de estos conjuntos es el mismo. También es finito y discreto. Por lo tanto, cada conjunto puede almacenarse como un campo de bits (p. Ej .: 0000100111 ...) de una longitud relativamente corta (p. Ej .: 1024). Es decir, el bit X en el campo de bits indica si el elemento X (de 1024 elementos posibles) está incluido en el conjunto dado o no.La forma más rápida de realizar una operación de prueba de subconjuntos en una gran colección de conjuntos con el mismo dominio

Ahora, quiero diseñar una estructura de almacenamiento y un algoritmo para responder eficientemente a la consulta: lo que los conjuntos en el almacén de datos han establecido Y como un subconjunto. El conjunto Y no está presente en el almacén de datos y se especifica en tiempo de ejecución.

Ahora, la forma más simple de resolver esto sería AND Y el campo de bits para el conjunto Y con campos de bits de cada conjunto en el almacén de datos uno por uno, seleccionando aquellos cuyo resultado Y coincida con el campo de bits de Y.

¿Cómo puedo acelerar esto? ¿Existe una estructura de árbol (índice) o algún algoritmo inteligente que me permita realizar esta consulta sin tener que ANDAR cada campo de bit del conjunto almacenado?

¿Existen bases de datos que ya admitan tales operaciones en grandes colecciones de conjuntos?

+0

¿Qué tipo de base de datos está utilizando? ¿Un formato propietario? ¿Servidor SQL? –

+0

La elección de DB dependerá de si admite de manera eficiente las operaciones de conjunto dadas en conjuntos enormes. Ninguno de los SQL DBS se escalará al tamaño requerido (RDMS DBs sería una mala elección para este problema de todos modos). Entonces, la elección es una base de datos especializada o una base de datos que implementaré yo mismo. – niktech

+0

¿Has encontrado alguna solución? Es extraño que no haya bases de datos conocidas para esta tarea. – actual

Respuesta

0

Tiendo a decir que la respuesta es no, debido al campo de bit muy baja cardinalidad.

0

Esto sería un tramo en un RDBMS convencional basado en su volumen, ¿ha mirado en Neo4j que se basa en un modelo de almacenamiento de gráficos?

+1

¿Admite de manera eficiente el trabajo con juegos grandes?Desde mi punto de vista, es más útil para almacenar gráficos, no conjuntos. – niktech

4

Si puede preprocesar los conjuntos, la relación del subconjunto es representable como un DAG (porque está describiendo un poset). Si se calcula la reducción transitiva, entonces creo que puede evitar probar todos los conjuntos simplemente realizando un DFS comenzando desde los conjuntos más grandes y deteniéndose cuando Y ya no sea un subconjunto del conjunto actual que se está visitando.

+0

¿Puedes elaborar? ¿Estás hablando básicamente de construir un DAG como el siguiente http://en.wikipedia.org/wiki/File:Hypercubeorder_binary.svg pero solo con nodos de la colección de conjuntos existentes? ¿Cómo elegiría el nodo inicial cuando hago el DFS? – niktech

+2

sí, esencialmente. hay un borde desde un conjunto A hasta un conjunto B si A es un superconjunto de B. Usar la reducción transitiva es mejor porque el número de bordes disminuye (por lo que el factor de ramificación también debe disminuir para examinar menos nodos inútiles). Dado que el gráfico es acíclico, va a haber un conjunto de nodos que no tienen bordes que los ingresen, y puede comenzar desde allí (estos representan los conjuntos que no tienen superconjuntos en su colección). Tendría que iniciar DFS en todos estos (o simplemente comenzar desde un nodo virtual conectado a todos estos conjuntos-sin-superconjuntos). – lijie

+0

Interesante. Mantendré este algoritmo en mente, aunque es poco probable que la colección de conjuntos en el almacén de datos tenga muchas relaciones subconjunto/superconjunto, así que terminaría haciendo DFS en muchos nodos iniciales. – niktech

1

Dependiendo de la cardinalidad del conjunto del que se extraen todos los conjuntos, una opción podría ser construir un mapeo de índice invertido desde los elementos hasta los conjuntos que los contienen. Dado un conjunto Y, podría encontrar todos los conjuntos que tienen Y como un subconjunto al encontrar todos los conjuntos que contienen cada elemento individualmente y calcular su intersección. Si almacena las listas en orden ordenado (por ejemplo, enumerando todos los conjuntos en su base de datos con los valores 0, 1, etc.), entonces debería poder calcular esta intersección de manera bastante eficiente, suponiendo que ningún elemento está contenido en muchos juegos

+0

Buen punto. La cardinalidad de los conjuntos en el almacén de datos es ~ <= 1024. Ahora la parte difícil hará la intersección de manera eficiente. El resultado de la intersección puede ser tan grande como toda la colección de conjuntos o tan pequeño como un par de docenas de conjuntos. ¿Qué algoritmos de intersección recomendarías? – niktech

+0

Sé que en el caso de que tenga dos secuencias ordenadas y desee calcular la intersección, puede hacerlo repitiendo lo siguiente: mientras las dos listas no están vacías, mire el primer valor de cada secuencia. Si no son lo mismo, elimine el más pequeño de los dos. Si son iguales, entonces ha detectado un valor en la intersección. Esto se ejecuta en el tiempo O (n + m), donde n y m son las longitudes de las dos secuencias. Si ejecuta este procedimiento en pares de secuencias, entonces en los resultados, etc. esto se ejecuta en O (n lg k), donde k es el número de secuencias y n la longitud máxima de una secuencia. – templatetypedef

0

Un vistazo rápido me hace pensar en BDD, que es algo similar a la idea de la solución DAG. Alternativamente un ZDD.

Cuestiones relacionadas