2010-11-22 8 views
5

¿Hay alguna forma de abstraer el orden de los vértices que GraphPlot aplica a VertexCoordinate Rules desde (FullForm o InputForm) del gráfico producido por GraphPlot? No quiero usar la función GraphUtilities VertexList. También conozco GraphCoordinates, pero ambas funciones funcionan con el gráfico, NO con la salida de gráficos de GraphPlot.VertexCoordinate Rules y VertexList de GraphPlot Graphic

Por ejemplo,

gr1 = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 1}; 
gp1 = GraphPlot[gr1, Method -> "CircularEmbedding", 
    VertexLabeling -> True]; 

[email protected](gp1 /. Graphics[Annotation[x___], ___] :> {x}) 

dicta la siguiente lista de seis pares de coordenadas:

VertexCoordinateRules -> {{2., 0,866025}, {1,5, 1,73205}, {0,5, 1,73205} , {0., 0.866025}, {0.5, 1.3469 * 10^-10}, {1.5, 0.}}

¿Cómo sé qué regla se aplica a qué vértice, y puedo estar seguro de que esto es lo mismo que el dado por VertexList [gr1]?

Por ejemplo

Needs["GraphUtilities`"]; 
gr2 = [email protected] 
     Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]]; 

    VertexList[gr2] 

da {1, 2, 3, 4, 5}

Pero ....

gp2 = GraphPlot[gr2, VertexLabeling -> True, 
     VertexCoordinateRules -> 
     Thread[VertexList[gr1] -> 
     [email protected](gp1 /. Graphics[Annotation[x___], ___] :> {x})[[2]]]]; 
[email protected](gp2 /. Graphics[Annotation[x___], ___] :> {x}) 

da seis coordenadas conjuntos:

VertexCoordinateRules -> {{2., 0.866025}, {1.5, 1.73205}, {0.5, 1.73205}, {0., 0.866025}, {0.5, 1.3469 * 10^- 10}, {1.5, 0.}}

¿Cómo puedo abstraer la VertexList correcta para VertexCoordinateRules para gr2, por ejemplo?

(Soy consciente de que puedo corregir cosas mediante la adopción de la VertexList después de generar GR2 de la siguiente manera, por ejemplo)

[email protected] 
SparseArray[ 
    Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]], {6, 6}] 

{1, 2, 3, 4, 5, 6}

pero la información que necesito parece estar presente en el gráfico GraphPlot: ¿cómo puedo obtenerla?

(La razón convierto el gráfico para una matriz de adyacencia él que, como se ha señalado por Carl Woll de Wolfram, que me permite incluir un nodo 'huérfano', como en la GP2)

alt text

+1

por cierto, otra manera de representar gráficos desconectados con el borde list es tener i-> bordes para cada nodo. Puede necesitar SelfLoopStyle-> None durante el trazado –

+0

Sí, ¡eso es cierto! Solía ​​usarlo antes de enterarme del método de Carl Woll. A veces necesito mostrar bucles automáticos y (por ahora) prefiero el método de la matriz de adyacencia. – tomd

+0

Creo que ambos son útiles: la matriz de adyacencia es más conveniente si está examinando gráficos o haciendo modificaciones que no cambian el número de vértices, mientras que edgelist es mejor cuando necesita hacer cosas como dividir el gráfico en dos –

Respuesta

5

Con el etiquetado de vértices, una forma es obtener las coordenadas de las etiquetas. Observe que el resultado de GraphPlot está en GraphicsComplex donde las coordenadas de coordinar los alias son como primera etiqueta, que puede conseguirlo como

points = Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // First 

En cuanto a FullForm verá que las etiquetas están en los objetos de texto, extraerlos como

labels = Cases[gp1, Text[___], Infinity] 

la etiqueta real parece que hay dos niveles de profundidad para que pueda obtener

actualLabels = labels[[All, 1, 1]]; 

de coordenadas alias es el segundo parámetro que pueda obtener como

coordAliases = labels[[All, 2]] 

coordenadas reales se especificaron en GraphicsComplex, por lo que les reciben como

actualCoords = points[[coordAliases]] 

Hay una correspondencia entre 1-1 lista de coordenadas y la lista de etiquetas, para que pueda utilizar hilo para volver como lista de "etiqueta" -> pares de coordenadas.

aquí es una función que todo esto junto

getLabelCoordinateMap[gp1_] := 
Module[{points, labels, actualLabels, coordAliases, actualCoords}, 
    points = 
    Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // 
    First; 
    labels = Cases[gp1, Text[___], Infinity]; 
    actualLabels = labels[[All, 1, 1]]; 
    coordAliases = labels[[All, 2]]; 
    actualCoords = points[[coordAliases]]; 
    Thread[actualLabels -> actualCoords] 
    ]; 
getLabelCoordinateMap[gp1] 

No es que esto sólo funciona en GraphPlot etiquetado. Para los que no tienen etiquetas, puede intentar extraer de otros objetos gráficos, pero puede obtener diferentes resultados según los objetos de los que extraiga la asignación, ya que parece haber un error que a veces asigna puntos finales de línea y etiquetas de vértices a diferentes vértices. Lo he informado. La forma de evitar el error es usar siempre la especificación de coordenadas vertex-> explícita para VertexCoordinateList, o siempre usar la representación de "matriz de adyacencia". Aquí está un ejemplo de discrepancia

graphName = {"Grid", {3, 3}}; 
gp1 = GraphPlot[Rule @@@ GraphData[graphName, "EdgeIndices"], 
    VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
    VertexLabeling -> True] 
gp2 = GraphPlot[GraphData[graphName, "AdjacencyMatrix"], 
    VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
    VertexLabeling -> True] 

Por cierto, como un aparte, aquí están las funciones de utilidad que utilizo para la conversión entre matriz de adyacencia y representación regla borde

edges2mat[edges_] := Module[{a, nodes, mat, n}, 
    (* custom flatten to allow edges be lists *) 

    nodes = Sequence @@@ edges // Union // Sort; 
    nodeMap = (# -> (Position[nodes, #] // Flatten // First)) & /@ 
    nodes; 
    n = Length[nodes]; 
    mat = (({#1, #2} -> 1) & @@@ (edges /. nodeMap)) // 
    SparseArray[#, {n, n}] & 
    ]; 
mat2edges[mat_List] := Rule @@@ Position[mat, 1]; 
mat2edges[mat_SparseArray] := 
Rule @@@ (ArrayRules[mat][[All, 1]] // Most) 
+0

¡Gracias! Aprecio tu ayuda. Aprendí muchísimo de tu respuesta. Su edges2mat también es un regalo. – tomd

4

Si ejecuta FullForm[gp1] obtendrá un montón de resultados que no publicaré aquí. Cerca del inicio de la salida encontrará un GraphicsComplex[]. Esto es, esencialmente, una lista de puntos y luego una lista de usos de esos puntos. Por lo tanto, para su gráfico gp1 el comienzo de la GraphicsComplex es:

GraphicsComplex[ 
List[List[2., 0.866025], List[1.5, 1.73205], List[0.5, 1.73205], 
    List[0., 0.866025], List[0.5, 1.3469*10^-10], List[1.5, 0.]], 
List[List[RGBColor[0.5, 0., 0.], 
    Line[List[List[1, 2], List[2, 3], List[3, 4], List[4, 5], 
    List[5, 6], List[6, 1]]]], 

La primera lista más externa define las posiciones de 6 puntos. La segunda lista más externa define un grupo de líneas entre esos puntos, usando los números de los puntos dentro de la primera lista. Probablemente sea más fácil de entender si juegas con esto.

EDIT: En respuesta al comentario de OP, si ejecuto:

FullForm[GraphPlot[{3 -> 4, 4 -> 5, 5 -> 6, 6 -> 3}]] 

me sale

Graphics[Annotation[GraphicsComplex[List[List[0.`,0.9997532360813222`], 
List[0.9993931236462025`,1.0258160108662504`],List[1.0286626995939243`, 
0.026431169015735057`],List[0.02872413637035287`,0.`]],List[List[RGBColor[0.5`,0.`,0.`], 
Line[List[List[1,2],List[2,3],List[3,4],List[4,1]]]],List[RGBColor[0,0,0.7`], 
Tooltip[Point[1],3],Tooltip[Point[2],4],Tooltip[Point[3],5],Tooltip[Point[4],6]]], 
List[]],Rule[VertexCoordinateRules,List[List[0.`,0.9997532360813222`], 
List[0.9993931236462025`,1.0258160108662504`], 
List[1.0286626995939243`,0.026431169015735057`],List[0.02872413637035287`,0.`]]]], 
Rule[FrameTicks,None],Rule[PlotRange,All],Rule[PlotRangePadding,Scaled[0.1`]], 
Rule[AspectRatio,Automatic]] 

La lista de posiciones de los vértices es la primera lista dentro de la GraphicsComplex. Más adelante en el FullForm puede ver la lista donde Mathematica agrega tooltips para etiquetar los vértices con los identificadores que ha proporcionado en la lista de bordes original. Como lo que estás viendo ahora es el código que describe un gráfico, solo hay una relación indirecta entre tus vértices y lo que se trazará; la información está allí, pero no del todo sencilla de desempaquetar.

+1

Pruebe 'Transpose @ {First/@ # [[1, 1, 2, 1, 2, 1]], # [[1, 1, 1]]} & [gp1] ' – Timo

+0

Esto solo funciona si las etiquetas corresponden a la posición de alias de coordenadas en el objeto GraphicsComplex, no para el gráfico {2-> 1} –

+0

OK, y veo tu punto. Pero si pruebo FullForm [GraphPlot [{3 -> 4, 4 -> 5, 5 -> 6, 6 -> 3}]] veo Lista [1, 2], Lista [2, 3], Lista [3 , 4], Lista [4, 1] y no una lista de vértices. – tomd

Cuestiones relacionadas