Il mio grafico è planare?


29

Il tuo compito è determinare se un grafico è planare.

Un grafico è planare se può essere incorporato nel piano o, in altre parole, se può essere disegnato senza bordi incrociati.

Input: ti verrà dato un grafico non orientato nella tua scelta dei seguenti formati:

  • Elenco dei bordi, ad es [(0, 1), (0, 2), (0, 3)]

  • Mappa di adiacenza, ad es {0: [1, 2, 3], 1:[0], 2:[0], 3:[0]}

  • Matrice adiacente, ad es [[0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

I nomi dei nodi possono essere numeri, stringhe o simili, ma il formato scelto deve essere in grado di supportare un grafico arbitrario. Non inserire codice nei nomi dei nodi. Non ci saranno loop automatici.

Scelta standard dell'input, inclusi STDIN, argomenti della riga di comando e argomenti della funzione.

Output: è necessario restituire un output specifico per tutti i grafici planari e un output specifico diverso per tutti i grafici non planari.

Scelta standard dell'uscita, incluso STDOUT, valore di ritorno della funzione.

Esempi:

Planar:

[]
[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6)]
[(0,1), (0,2), (0,3), (1,2), (1,3), (2,3)]
[(0,2), (0,3), (0,4), (0,5), (1,2), (1,3), (1,4), (1,5), (2,3),
 (2,5), (3,4), (4,5)]

non piano:

[(0,1), (0,2), (0,3), (0,4), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)]
[(0,3), (0,4), (0,5), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5)]
[(0,3), (0,4), (0,6), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (5,6), 
 (7,8), (8,9), (7,9)]

È vietata qualsiasi funzione che esegue esplicitamente test di planarità o che fa riferimento in modo specifico a incorporamenti planari.

Questo è il codice golf. Che vinca il codice più corto.


Bella domanda!

È fantastico che questo sia un problema classico e ci sono ancora diversi approcci possibili, inclusi quelli non utilizzati nel codice per gli scopi abituali.
lirtosiast,

Un caso di test per un grafico non connesso con un componente connesso planare e uno non planare sarebbe buono.
Peter Taylor,

@PeterTaylor Certo, ne aggiungerò uno.
Isaacg,

5
@RenaeLider Siamo spiacenti, ma non capisco. La domanda non ha nulla a che fare con i numeri in virgola mobile - non usa nemmeno numeri, in realtà, solo etichette.
Isaacg,

Risposte:


14

Mathematica, 201 byte

f@g_:=EdgeCount@g<9||!(h=g~IsomorphicGraphQ~CompleteGraph@#&)@5&&!h@{3,3}&&And@@(f@EdgeDelete[g,#]&&f@EdgeContract[g,#]&/@EdgeList@g);And@@(f@Subgraph[g,#]&/@ConnectedComponents[g=Graph[#<->#2&@@@#]])&

Questo restituisce una funzione senza nome, che accetta un edge list come

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

Questo è un approccio ricorsivo orribilmente inefficiente basato sul teorema di Wagner :

Un grafico finito è planare se e solo se non ha K 5 o K 3,3 come minore.

Qui, K 5 è il grafico completo con 5 vertici e K 3,3 è il grafico bipartito completo con 3 vertici in ciascun gruppo. Un grafico A è un minore del grafico B se può essere ottenuto da B mediante una sequenza di eliminazioni e contrazioni dei bordi.

Quindi questo codice controlla solo se il grafico è isomorfo a K 5 o K 3,3 e in caso contrario si chiama ricorsivamente una volta per ogni possibile cancellazione o contrazione del bordo.

Il problema è che l'eliminazione o la contrazione dei bordi in un componente di un grafico non collegato non elimineranno mai tutti i vertici lì, quindi non troveremo mai gli isomorfismi desiderati. Pertanto, applichiamo questa ricerca a ciascun componente collegato del grafico di input separatamente.

Funziona molto velocemente per gli input dati, ma se aggiungi qualche spigolo in più richiederà rapidamente un tempo catastrofico (e occuperà anche molta memoria).

Ecco una versione rientrata di f(la funzione senza nome dopo aver appena generato un oggetto grafico dall'input:

f@g_ := 
  EdgeCount@g < 9 || 
  ! (h = g~IsomorphicGraphQ~CompleteGraph@# &)@5 && 
  ! h@{3, 3} &&
  And @@ (f@EdgeDelete[g, #] && f@EdgeContract[g, #] & /@ EdgeList@g)

E questa è la funzione senza nome che converte l'input in un grafico e chiama fper ciascun componente collegato:

And @@ (
  f @ Subgraph[g, #] & /@ ConnectedComponents[
    g=Graph[# <-> #2 & @@@ #]
  ]
)&

Posso salvare un paio di byte modificando la condizione di terminazione da EdgeCount@g<9a g==Graph@{}, ma ciò farà esplodere significativamente il tempo di esecuzione. Il secondo caso di test richiede quindi 30 secondi e l'ultimo non è stato ancora completato.


È possibile provare a rimuovere la funzione denominata utilizzando il #0quale si riferisce alla funzione più interna più pura.
LegionMammal978,

@ LegionMammal978 Lo so, ma in realtà non salva nulla, perché quindi ho bisogno di parentesi e anche di assegnarle manualmente #a una variabile g.
Martin Ender,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.