2010-06-24 13 views
9

Si bien esto puede parecer una tarea, te aseguro que no es así. Sin embargo, se deriva de una tarea que hice.Generando un gráfico cúbico aleatorio con probabilidad uniforme (o menos)

Llamemos a un gráfico no dirigido sin bordes propios "cúbico" si cada vértice tiene un grado exactamente tres. Dado un número entero positivo N, me gustaría generar un gráfico cúbico aleatorio en N vértices. Me gustaría que tuviera una probabilidad uniforme, es decir, si hay M gráficos cúbicos en N vértices, la probabilidad de generar cada uno es 1/M. Una condición más débil que todavía está bien es que cada gráfico cúbico tiene una probabilidad distinta de cero.

I feel hay una manera rápida e inteligente de hacer esto, pero hasta ahora no he tenido éxito.

soy una mala codificador, por favor tengan con este código horrible:

PRE:/2, los nodos es par, las constantes se seleccionan de tal manera bordes = (3 * nodos) que las obras de hash (BIG_PRIME es más grande que los bordes, SMALL_PRIME es más grande que los nodos, LOAD_FACTOR es pequeño).

void random_cubic_graph() { 

int i, j, k, count; 
int *degree; 
char guard; 

count = 0; 
degree = (int*) calloc(nodes, sizeof(int)); 

while (count < edges) { 

    /* Try a new edge at random */ 

    guard = 0; 
    i = rand() % nodes; 
    j = rand() % nodes; 

    /* Checks if it is a self-edge */ 

    if (i == j) 
     guard = 1; 

    /* Checks that the degrees are 3 or less */ 

    if (degree[i] > 2 || degree[j] > 2) 
     guard = 1; 

    /* Checks that the edge was not already selected with an hash */ 

    k = 0; 
    while(A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] != 0) { 
     if (A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] % SMALL_PRIME == j) 
      if ((A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] - j)/SMALL_PRIME == i) 
       guard = 1; 
     k++; 
    } 

    if (guard == 0) 
     A[(j + k*BIG_PRIME) % (LOAD_FACTOR*edges)] = hash(i,j); 

    k = 0; 
    while(A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] != 0) { 
     if (A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] % SMALL_PRIME == i) 
      if ((A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] - i)/SMALL_PRIME == j) 
       guard = 1; 
     k++; 
    } 

    if (guard == 0) 
     A[(i + k*BIG_PRIME) % (LOAD_FACTOR*edges)] = hash(j,i); 

    /* If all checks were passed, increment the count, print the edge, increment the degrees. */ 

    if (guard == 0) { 
     count++; 
     printf("%d\t%d\n", i, j); 
     degree[i]++; 
     degree[j]++; 
    } 

} 

El problema es que su borde final que debe seleccionarse puede ser un borde propio. Eso sucede cuando los vértices N - 1 ya tienen el grado 3, solo 1 tiene el grado 1. Por lo tanto, es posible que el algoritmo no termine. Además, no estoy del todo convencido de que la probabilidad sea uniforme.

Probablemente haya mucho que mejorar en mi código, pero ¿puede sugerirme un mejor algoritmo para implementar?

+2

Sugiero no usar el lenguaje C para algoritmos de gráficos cuando eres solo un principiante. –

+0

Entonces, ¿estás representando tu gráfica como una matriz cuadrada? Por cierto, ¿qué es este negocio small_prime, big_prime y load_factor? Me parece que ha copiado la solución de otra persona y está intentando darle sentido. –

+2

No hay matriz cuadrada: A es un vector de longitud LOAD_FACTOR * bordes que contiene los bordes. Vamos a pretender que hay una función blackbox is_edge_present (int i, int j) que comprueba si el borde (i, j) ya estaba seleccionado. Ese fragmento de código hace eso, y si el borde no se seleccionó, lo selecciona para futuras búsquedas. ¿No es un poco grosero asumir que he copiado? Yo escribí esa. Es intrincado y desordenado, pero es por eso que hay una etiqueta para principiantes. –

Respuesta

10

Supongamos que N es par. (De lo contrario, no puede haber un gráfico cúbico en N vértices).

Usted puede hacer lo siguiente:

quitar puntos 3N y dividirlos en grupos N de 3 puntos cada uno.

Ahora empareje estos puntos 3N aleatoriamente (nota: 3N es par). es decir, se casan dos puntos aleatoriamente y forman matrimonios 3N/2).

Si hay un emparejamiento entre el grupo iy el grupo j, cree una ventaja entre i y j. Esto da un gráfico en N vértices.

Si este emparejamiento aleatorio no crea bordes o bucles múltiples, tiene un gráfico cúbico.

Si no lo intenta nuevamente. Esto se ejecuta en el tiempo lineal esperado y genera una distribución uniforme.

Nota: todos los gráficos cúbicos en N vértices se generan con este método (en respuesta a los comentarios de Hamish).

Para ver esto:

Sea G un gráfico cúbico de n vértices.

Sean los vértices ser, 1, 2, ... N.

Deje que los tres vecinos de j sean A (j), B (j) y C (j).

Para cada j, construye el grupo de pares ordenados {(j, A (j)), (j, B (j)), (j, C (j))}.

Esto nos da 3N pares ordenados. Los emparejamos: (u, v) está emparejado con (v, u).

Así, cualquier grafo cúbico corresponde a una pareja y viceversa ...

Más información sobre este algoritmo y los algoritmos más rápidos se puede encontrar aquí: Generating Random Regular Graphs Quickly.

+0

¿Qué pasa si esto omite algunos "gráficos cúbicos"? ¿Qué pasa si algunos DEBEN generarse utilizando algún otro método? –

+0

Gracias, creo que esto resuelve mi pregunta. Esperaré unas horas más antes de aceptar tu respuesta en caso de que surja una solución aún mejor. –

+1

@Hamish: Ver mi edición. Todos los gráficos cúbicos se generan ... –

2

Advertencia: Hago muchas afirmaciones intuitivas pero incorrectas en esta respuesta. Definitivamente debe probarlos si tiene la intención de utilizar esta idea.

enumerarse los gráficos cúbicos

Cuando se trata de una elección al azar, un buen punto de partida es averiguar cómo enumerar sobre todas sus posibles elementos. Esto podría revelar parte de la estructura y conducirlo a un algoritmo.

Aquí está mi estrategia para enumerar gráficos cúbicos: elija el primer vértice e itere sobre todas las opciones posibles de tres vértices adyacentes. Durante esas iteraciones, recurse en el siguiente vértice, con la advertencia de que realiza un seguimiento de cuántos bordes se necesitan para que cada grado de vértice llegue a 3. Continúe de esa manera hasta que se alcance el nivel más bajo. Ahora tienes tu primer gráfico cúbico. Deshaga los bordes recientemente agregados y continúe con la próxima posibilidad hasta que no quede ninguno. Hay algunos detalles de implementación que debe tener en cuenta, pero en general sencillos.

Generalizar Enumeración en Elección

vez que usted puede enumerar todos los elementos, es trivial para hacer una elección al azar. Por ejemplo, puede escanear la lista una vez para calcular su tamaño, luego elegir un número aleatorio en [0, tamaño) y luego escanear la secuencia nuevamente para obtener el elemento en ese desplazamiento. Esto es increíblemente ineficiente, tomando al menos tiempo proporcional al O (n^3) número de gráficos cúbicos, pero funciona.

Sacrificio de probabilidad uniforme para la eficiencia

La aceleración aquí es para tomar decisiones borde al azar en cada nivel, en lugar de iterar sobre cada una posibilidad obvia. Desafortunadamente, esto favorecerá algunos gráficos debido a cómo sus elecciones tempranas afectan la disponibilidad de opciones posteriores. Teniendo en cuenta la necesidad de rastrear los vértices libres restantes, debe poder lograr el tiempo O (n log n) y el espacio O (n). Significativamente mejor que el algoritmo de enumeración.

...

Es probable que sea posible hacerlo mejor. Probablemente mucho mejor. Pero esto debería hacerte comenzar.

+0

Esta es una estrategia general interesante que pasé por alto. Es posible que desee recurrir a esta estrategia la próxima vez. ¡Gracias! –

+0

Tenga en cuenta que puede elegir un elemento de manera aleatoria de una lista al escanearlo solo una vez, sin necesidad de calcular primero el tamaño: http://en.wikipedia.org/wiki/Reservoir_sampling (let k = 1) – Paulpro

1

Otro término para cubic graph es 3- regular graph o gráfico trivalente.

Su problema necesita un poco más aclaraciones porque "el número de gráficos cúbicos" podría significar que el número de gráficos cúbicos en 2 n nodos que no son isomorfos entre sí o el número de (no isomorfos) cúbico gráficos en 2 n nodos etiquetados. El primero está dado por la secuencia de enteros A005638, y es probable que un problema no trivial para elegir de manera uniforme una clase aleatoria de isomorfismos de gráficos cúbicos de manera eficiente (es decir, no enumerarlos todos y luego elegir una clase). El último está dado por A002829.

Hay un artículo en la Wikipedia acerca de random regular graphs que debe consultar.

+1

[ Gráfico cúbico] (http://en.wikipedia.org/wiki/Cubic_graph) es un término perfectamente estándar. –

+0

Gracias por la aclaración. Estoy buscando un gráfico 3-regular sin bucles en 2n nodos etiquetados. Tengo que corregirlo: no estoy buscando multiedres, de hecho descarto una ventaja (i, j) si ya se ha seleccionado. Gracias por el enlace de la wiki, ya que proporciona el mismo algoritmo de la primera respuesta. –

+0

@BlueRaja - Danny Pflughoeft: De hecho lo es. Necesito actualizar mi respuesta. –

Cuestiones relacionadas