2009-03-09 8 views
11

He estado buscando ejemplos de C# para transformar un DAG en un árbol.Cómo convertir el gráfico acíclico dirigido (DAG) al árbol

¿Alguien tiene ejemplos o indicadores en la dirección correcta?

Aclaración actualización

Tengo un gráfico que contiene una lista de los módulos que se requiere para cargar mi solicitud. Cada módulo tiene una lista de módulos de los que depende. Por ejemplo, aquí están mis módulos, A, BC, D y E

  • A no tiene dependencias
  • B depende de A, C y E
  • C depende de una
  • D depende de una
  • e depende de C y a

Quiero resolver las dependencias y generar un árbol que se parece a esto ...

--A

- + - B

----- + - C

--------- + - D

- + - E

topológica Ordenar

Gracias por la información, si realizo una ordenación topológica y revertir la salida i tendrán el siguiente orden

  • Un
  • B
  • C
  • D
  • E

Quiero mantener la estructura jerárquica para que mis módulos se carguen en el contexto correcto, por ejemplo ... el módulo E debería estar en el mismo recipiente que B

Gracias

Rohan

+0

cómo desea tratar con diamantes ... A -> B, A -> C, B & C -> D – ShuggyCoUk

+0

Esa es una buena pregunta, veo un problema pero no sé cómo resolverlo, ¿qué haría? ¿tú lo haces? Mi experiencia con la teoría de grafos es muy limitada. –

+0

O bien 1) elige el primero, 2) eliges los últimos 3) duplicas el nodo. lo que sea mejor depende por completo de la aplicación, 3 es el más fácil seguido de 1 seguido de 2 ... es difícil decir lo que quiere el árbol en función de la pregunta. las dependencias de diamante son una perra en general – ShuggyCoUk

Respuesta

20

Ahí está la respuesta teórica del gráfico y la respuesta del programador a esto. Supongo que puede manejar la parte de los programadores usted mismo. Para la gráfica respuesta theorethical:

  • Un DAG es un conjunto de módulos donde nunca ocurre que A necesita B, y al mismo tiempo, B (o una de las necesidades módulos B) necesita A, en Modules- hablar: no hay dependencia circular. He visto que ocurren dependencias circulares (busque en los foros de Gentoo ejemplos), por lo que ni siquiera puede estar 100% seguro de que tiene un DAG, pero supongamos que tiene. No es muy difícil verificar las dependencias circulares, por lo que te recomiendo que lo hagas en algún lugar de tu cargador de módulos.
  • En un árbol, algo que nunca puede suceder es que A depende de B y C y que tanto B como C dependen de D (un diamante), pero esto puede ocurrir en un DAG.
  • Además, un árbol tiene exactamente un nodo raíz, pero un DAG puede tener múltiples nodos "raíz" (es decir, módulos de los que nada depende). Por ejemplo, un programa como GIMP, el programa GIMP será el nodo raíz del conjunto de módulos, pero para GENTOO, casi cualquier programa con una GUI es un nodo "raíz", mientras que las bibliotecas, etc., son dependencias de ellos. (Es decir, tanto Konqueror y Kmail dependen de Qtlib, pero nada depende de Konqueror, y nada depende de Kmail)

El Gráfico theorethical respuesta a su pregunta, como otros señalaron, es que un DAG no se puede convertir a un árbol, mientras que cada árbol es un DAG.

Sin embargo, (los programadores de alto nivel responden) si quiere el árbol para las representaciones gráficas, solo está interesado en las dependencias de un módulo específico, no lo que depende de ese módulo. Déjenme darles un ejemplo:

A depends on B and C 
B depends on D and E 
C depends on D and F 

no puedo mostrar esto como un árbol ASCII-art, por la sencilla razón de que esto no se puede convertir en un árbol. Sin embargo, si desea mostrar lo que A depende, puede mostrar esto:

A 
+--B 
| +--D 
| +--E 
+--C 
    +--D 
    +--F 

Como se puede ver, se obtiene entradas dobles en su árbol - en este caso "sólo" D pero si lo hace un " expande todo "en el árbol de Gentoo, te garantizo que tu árbol tendrá al menos 1000 veces más nodos que módulos. (hay al menos 100 paquetes que dependen de Qt, por lo que todo lo que Qt depende estará presente al menos 100 veces en el árbol).

Si tiene un árbol "grande" o "complejo", podría ser mejor expandir el árbol dinámicamente, no de antemano, de lo contrario podría tener un proceso que requiera mucha memoria.

La desventaja del árbol de arriba es que si hace clic en abrir B, entonces D, ve que A y B dependen de D, pero no que también C depende de D. Sin embargo, dependiendo de su situación, esto podría no Sea importante en absoluto: si mantiene una lista de módulos cargados, al cargar C, verá que ya ha cargado D, y no importa que no haya sido cargado para C, sino para B. Está cargado, eso es todo Eso importa. Si mantiene dinámicamente lo que depende directamente de un determinado módulo, también puede manejar el problema opuesto (descarga).

Sin embargo, lo que no puede hacer con un árbol es lo que está en su última frase: conservar el orden topológico, es decir, si B se carga en el mismo contenedor que C, nunca cargará C en el mismo contenedor también. O puede que tenga que soportar poner todo en un contenedor (no es que entienda completamente lo que quiere decir con "cargar en el mismo contenedor")

¡Buena suerte!

+2

Esta respuesta detallada me ayudó a pensar en un problema sin relación en el que estoy trabajando;) –

+0

Un DAG con una sola raíz puede convertirse en árbol si los nodos tienen contenido pero no identidad (si varios nodos comparten un nodo secundario, las referencias a ese nodo se reemplazarán por referencias a copias distintas de él). – supercat

0

Sólo puede hacerlo si todos los subárboles tienen un único nodo raíz.

+1

Siempre puede comenzar con un nodo raíz falso. – ypnos

1

Depende mucho de cómo represente su DAG. Por ejemplo, podría ser una matriz de adyacencia (A [i, j] = 1 si hay un borde del nodo i al nodo j, más 0), o como un sistema de punteros, o como una matriz de nodos y una matriz de bordes ....

Además, no está claro qué transformación está tratando de aplicar.Un DAG conectado es un árbol, así que me temo que debe aclarar un poco su pregunta.

+0

Para ser pedante: cualquier gráfico conectado sin ciclos es un árbol. –

+0

Veo su pedantería y levanto: el conjunto de todos los gráficos acíclicos dirigidos conectados es un subconjunto propio del conjunto de todos los gráficos acíclicos conectados, por lo tanto, su enunciado ("Cualquier gráfico conectado sin ciclos es un árbol") implica formalmente el mío ("Un DAG conectado es un árbol"). – MarkusQ

+0

No debería ser "Cualquier gráfico conectado directo sin ciclos CONTIENE un árbol". Si A depende de B y C; B depende de D y C depende de D, no tienes un árbol, tienes un gráfico que contiene dos árboles. – Eclipse

4

Un DAG y un árbol no son lo mismo matemáticamente. Por lo tanto, cualquier conversión introduce ambigüedad. Un árbol por definición no tiene ciclos, punto.

+1

Tampoco lo hace un DAG (de ahí la parte acíclica del nombre). Un DAG sí permite diamantes y topologías similares donde convergen dos ramas divergentes. (Pero en ningún caso puede volver con un padre). Un árbol no tiene ningún nodo con más de un padre. – Eclipse

+2

Exactamente: un DAG no tiene _directed_ cycles. Un árbol no tiene ciclos en absoluto. – dsimcha

2

Lo que está buscando, para encontrar el orden de carga de sus módulos, es el Topological sort de su DAG. Si los bordes van desde un módulo a los módulos de los que depende (lo que creo que es más probable), tendrá que cargar los módulos en el orden inverso al orden topológico porque aparecerá un módulo antes que todos los módulos De lo que depende

Si representa el DAG de manera que los bordes van desde el dependiente de los módulos a los módulos que dependen de ellos (puede obtenerlo invirtiendo todos los bordes en el gráfico anterior), puede simplemente cargar los módulos en el orden del tipo topológico.

+0

He actualizado la descripción sobre la clasificación topológica, gracias –

Cuestiones relacionadas