¿Cómo extraer ciertos tipos de ruta en igraph?

TLDR: me gustaría extraer los tipos de borde de cada ruta entre dos vértices en igraph. ¿Hay una manera relativamente sensata de hacer esto?


La clínica para la que trabajo emprendió recientemente una investigación de contactos de tuberculosis bastante grande (1400 personas) en una escuela secundaria. Tengo horarios de clases para todos los estudiantes y profesores (!) y los puse en una red (usando igraph en R), con cada estudiante y cada combinación de salón-período como un vértice (por ejemplo, la clase en el Salón 123 en Período 1 es un vértice con un borde dirigido a la clase que está en la habitación 123 para el período 2). También sé qué habitaciones comparten sistemas de ventilación, un mecanismo plausible pero poco probable de infección. El gráfico se dirige desde el caso de fuente única, por lo que cada ruta en la red tiene solo dos personas: la fuente y un contacto, separados por un número variable de vértices de período de habitación. Conceptualmente, hay cuatro tipos de caminos:

  • exposiciones de contacto personal (fuente -> solo contacto)
  • exposiciones de clase compartida (fuente -> período de habitación -> contacto)
  • exposiciones del próximo período (fuente-> Sala 123 Periodo 1 -> Sala 123 Periodo 2 -> contacto)
  • exposiciones de ventilación (fuente -> Habitación 123 Periodo 1 -> Habitación 125 Periodo 1 -> contacto)

Cada borde tiene un atributo que indica si se trata de una exposición de persona a persona, una misma habitación en un período diferente o un borde de ventilación.

Como paso intermedio para modelar la infección en esta red, me gustaría obtener un recuento simple de cuántas exposiciones de cada tipo ha tenido un estudiante. Por ejemplo, un estudiante podría haber compartido una clase con la fuente, luego haber estado en una habitación en la que había estado la fuente pero un período más tarde, y quizás al día siguiente haber estado en una habitación contigua a la ventilación. Los indicadores de ese alumno serían entonces:

personal.contact: 0
shared.class:     1
next.period:      1
vent:             1

Sin embargo, no estoy seguro de cuál es la mejor manera de obtener este tipo de información: veo funciones para obtener más corto caminos, lo que facilita la identificación de enlaces de contacto personal, pero creo que necesito evaluar todos los caminos (que parece una locura pedir en una red social típica, pero no es tan loco cuando solo la fuente y los períodos de habitación tienen bordes). Si pudiera llegar al punto en el que cada ruta de origen a contacto estuviera representada por un vector ordenado de tipos de borde, creo que podría subdividirlos fácilmente en mis criterios. Simplemente no sé cómo llegar allí. Si igraph no es el marco adecuado para esto y solo necesito escribir algunos bucles grandes y horribles sobre los horarios de los estudiantes, ¡que así sea! Pero agradecería alguna orientación antes de sumergirme en ese agujero.


Aquí hay un gráfico de muestra de un contacto con cada una de las tres rutas indirectas:

# Strings ain't factors
options(stringsAsFactors = FALSE)  
library(igraph)

# Create a sample case
edgelist <- data.frame(out.id = c("source", "source", 
                                  "source", "Rm 123 Period 1", 
                                  "Rm 125 Period 2", "Rm 125 Period 3", 
                                  "Rm 127 Period 4", "Rm 129 Period 4"),
                       in.id = c("Rm 123 Period 1", "Rm 125 Period 2", 
                                 "Rm 127 Period 4", "contact", 
                                 "Rm 125 Period 3", "contact", 
                                 "Rm 129 Period 4", "contact"),
                       edge.type = c("Source in class", "Source in class",
                                     "Source in class", "Student in class",
                                     "Class-to-class", 
                                     "Student in class", "Vent link",
                                     "Student in class"
                                     )
)

samp.graph <- graph.data.frame(edgelist, directed = TRUE)

# Label the vertices with meaningful names
V(samp.graph)$label <- V(samp.graph)$name

plot(samp.graph, layout = layout.fruchterman.reingold)

preguntado el 22 de mayo de 12 a las 18:05

¿Podría esto ser modelado de una manera más simple. Digamos, solo teniendo a los estudiantes como vértices y luego conectando los bordes a los estudiantes que representan si los estudiantes estaban en la misma clase, en la siguiente clase, en la clase después de la siguiente clase o en una clase que comparte un sistema de ventilación. Luego, podría resumir los tipos de aristas que inciden en cada vértice para producir la tabla que necesita. También podría asignar pesos a cada tipo de borde, por ejemplo, con el mismo salón de clases como 1 (más probable) y ventilación como 10 (menos probable). Entonces busca shortest.paths() entre una fuente y el vértice de infección. -

@PaulG Ciertamente podría, aunque parte del objetivo de esta pregunta es evitar ir por ese camino. El truco es obtener esos atributos de borde en primer lugar; Sólo puedo pensar en dos formas de hacerlo. Uno sería un enfoque de red (¡que es de lo que trata esta pregunta!) -

Un segundo sería iterar sobre las clases de cada persona, preguntando "¿Esta clase se comparte con la fuente? ¿Esta clase está en una clase después de la fuente? ¿Esta clase es adyacente a la ventilación?" y generando bordes a medida que avanzo (o podría omitir el gráfico por completo y simplemente resumir la cantidad de clases de cada tipo). Eso realmente no es tan malo: ¡solo esperaba poder usar el gráfico que había ensamblado con tanto cuidado! -

¿No sería igual de costoso desde el punto de vista computacional construir el gráfico más simple con los estudiantes solo como vértices, como el que ha mostrado aquí? Su red tiene dos tipos distintos de vértices; son realmente los vértices de los estudiantes los que son de interés y los vértices del "lugar geométrico de contacto" son un gráfico separado que está utilizando para derivar el tipo de borde entre los estudiantes. -

El gasto computacional no es realmente un problema, y ​​estoy de acuerdo en que su red propuesta solo para estudiantes tiene sentido. Pero... básicamente, ya hice el gráfico de clase de persona y tiene la información que necesito; Parece que no puedo encontrar la manera correcta de extraer esa información. Hacer el gráfico alumno-alumno significa reelaborar el código de construcción del gráfico, lo que estoy haciendo ahora, ya que las respuestas no parecen estar disponibles, pero que esperaba evitar por su cognitivo gastos. -

1 Respuestas

No estoy del todo seguro de entender su modelo gráfico, pero si la pregunta es:

I have two vertices and I wish to extract every path between them,
then extract the edge attributes of those edges.

entonces tal vez esto podría funcionar.

Vaya con una búsqueda primero en amplitud. Igraph contiene uno, pero es bastante fácil crear el tuyo propio, y esto te dará más flexibilidad en cuanto a la información que deseas obtener. Supongo que no tiene ciclos en su gráfico; de lo contrario, obtendrá una cantidad infinita de rutas. No sé mucho de Python (aunque uso igraph en R), así que aquí hay un pseudocódigo.

list <- empty

allSimplePaths(u, v, thisPath)
  if (u == v) return
  for (n in neighborhood(u))
    if (n in thisPath)
      next
    if (u == v)
      list <- list + (thisPath + v)
  for (n in neighborhood(u))
    thisPath <- thisPath + n
    allSimplePaths(n, v, thisPath)
    thisPath <- thisPath - thisPath.end

Básicamente dice "desde cada vértice, intenta todos los caminos posibles de expansión para llegar al final". Es una cuestión simple agregar otro thisPathEdges e insertar bordes, pasándolo a través de la función, así como los vértices. Por supuesto, esto funcionaría mejor si no fuera recursivo. Tenga cuidado, ya que este algoritmo podría arruinar su pila con suficientes nodos.

Es posible que aún desee usar el modelo de @PaulG y solo tener múltiples bordes entre los nodos de los estudiantes. Podría hacer cosas geniales como ejecutar una búsqueda en amplitud para ver cómo se propagó la enfermedad o encontrar un árbol de expansión mínimo para obtener una estimación de tiempo, o encontrar un corte mínimo para poner en cuarentena una infección en curso o algo así.

Respondido 01 ago 12, 02:08

¡Gracias! Terminé usando la sugerencia de Paul, pero me gustaría probar la tuya; podría llevarme un tiempo retroceder en el control de versiones al lugar correcto y configurar esto. Gracias por dar seguimiento a esta vieja pregunta. Informaré cómo va. - Matt Parker

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.