2010-11-22 6 views
5

Czy istnieje sposób na abstrakcję kolejności wierzchołków, jaką GraphPlot dotyczy reguł VertexCoordinate z (FullForm lub InputForm) grafiki generowanej przez GraphPlot? Nie chcę używać funkcji VertexList funkcji GraphUtilities. Jestem również świadomy GraphCoordinates, ale obie te funkcje działają na wykresie, a nie na wyjściu graficznym GraphPlot.Reguły współrzędnych Vertex i VertexList z GraphPlot Graphic

Przykładowo

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}) 

daje następująca lista sześciu par współrzędnych:

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

Skąd wiadomo, która reguła dotyczy danego wierzchołka i czy mogę być pewna, że ​​jest to taki sam jak podany przez VertexList [gr1]?

Przykładowo

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

    VertexList[gr2] 

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

ale ....

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

daje szósty współrzędnych zestawy:

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

Jak mogę, na przykład, wyodrębnić poprawne VertexList dla VertexCoordinateRules dla gr2?

(I sobie sprawę, że można poprawić, co biorąc VertexList po wygenerowaniu GR2 w następujący sposób, na przykład)

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

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

ale informacja, której potrzebuję, wydaje się być obecna na grafice GraphPlot: jak ją uzyskać?

(Powodem przekonwertować wykres na otoczki przylegania, które, jak wskazano przez Carl Woll wolframu, pozwala mi to węzeł sierocych ", tak jak w GP2)

alt text

+1

okazji, w inny sposób stanowią odłączone wykresy z krawędzią lista ma krawędzie i-> i dla każdego węzła. Może wymagać SelfLoopStyle-> Brak podczas drukowania –

+0

Tak, to prawda! Używałem go, zanim dowiedziałem się o metodzie Carla Wolla. Czasami muszę pokazywać własne pętle i (na razie) preferować metodę macierzy sąsiedztwa. – tomd

+0

Sądzę, że obie są użyteczne - matryca dopasowania jest wygodniejsza, jeśli analizujesz wykresy lub robisz modyfikacje, które nie zmieniają liczby wierzchołków, podczas gdy edgelistka jest lepsza, gdy musisz zrobić coś takiego jak podzielenie wykresu na dwie części: –

Odpowiedz

5

W przypadku etykietowania wierzchołków, jednym ze sposobów jest uzyskanie współrzędnych etykiet. Zauważ, że wyjście GraphPlot jest w GraphicsComplex gdzie współrzędne koordynować aliasy są pierwszej etykiety, można je dostać jako

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

Patrząc na FullForm zobaczysz, że etykiety są w obiektach tekstowych, wyodrębnić je jako

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

rzeczywista etykieta wydaje się być głęboko dwa poziomy więc masz

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

współrzędnych alias jest drugim parametrem więc masz je jako

coordAliases = labels[[All, 2]] 

Rzeczywiste współrzędne zostały określone w GraphicsComplex, więc je jako

actualCoords = points[[coordAliases]] 

Tam 1-1 korespondencja między listy współrzędnych i liście etykiet, dzięki czemu można używać wątek zwrócić je jako lista "etykieta" -> pary współrzędnych.

oto funkcja, która to wszystko razem

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] 

Nie, że to działa tylko na oznaczonym GraphPlot. Dla tych bez etykiet można próbować wyodrębnić z innych obiektów graficznych, ale możesz uzyskać różne wyniki w zależności od tego, z jakich obiektów wyodrębnisz mapowanie, ponieważ wydaje się, że istnieje błąd, który czasami przypisuje punkty końcowe linii i wierzchołki etykiet do różnych wierzchołków. Zgłosiłem to. Sposób obejścia błędu polega na tym, że zawsze używaj jawnej specyfikacji wierzchołków-> dla VertexCoordinateList lub zawsze używaj reprezentacji "matrycy sąsiedztwa". Oto przykład rozbieżności

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] 

okazji, na marginesie, tutaj funkcje użytkowe używać do konwersji między matrycą przylegania i krawędzi reprezentacji reguły

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

Dzięki! Doceniam twoją pomoc. Bardzo dużo nauczyłem się z twojej odpowiedzi. Your edges2mat to także gadżet. – tomd

4

Jeśli wykonasz FullForm[gp1], otrzymasz masę danych wyjściowych, których nie będę tu publikować. W pobliżu początku wyjścia znajduje się GraphicsComplex[]. Jest to w istocie lista punktów, a następnie lista zastosowań tych punktów. Tak więc, dla graficznego gp1 początku GraphicsComplex jest:

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]]]], 

Pierwsza lista najbardziej zewnętrzna definiuje pozycje 6 punktów. Druga najbardziej zewnętrzna lista definiuje pęczek linii pomiędzy tymi punktami, używając liczb punktów na pierwszej liście. Prawdopodobnie łatwiej jest zrozumieć, jeśli się z tym bawisz.

EDIT: W odpowiedzi na komentarz OP, jeśli wykonam:

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

uzyskać

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]] 

Wykaz stanowisk wierzchołek jest pierwsza lista wewnątrz GraphicsComplex. Później w FullForm można zobaczyć listę, w której Mathematica dodaje etykiety narzędzi do oznaczania wierzchołków za pomocą identyfikatorów podanych na oryginalnej liście krawędzi. Ponieważ to, na co teraz patrzysz, to kod opisujący grafikę, istnieje tylko pośrednia relacja między twoimi wierzchołkami a tym, co zostanie wykreślone; informacje są dostępne, ale nie całkiem proste do rozpakowania.

+1

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

+0

Działa to tylko wtedy, gdy etykiety odpowiadają położeniu aliasów współrzędnych w Obiekt GraphicsComplex, nie dla wykresu {2-> 1} –

+0

OK, i widzę twój punkt. Ale jeśli spróbuję FullForm [GraphPlot [{3 -> 4, 4 -> 5, 5 -> 6, 6 -> 3}]] Widzę listę [1, 2], listę [2, 3], listę [3 , 4], Lista [4, 1], a nie lista wierzchołków. – tomd

Powiązane problemy