#---------------------------------------------------------------#
# grafos                                                       #

if(require("igraph")==FALSE) 
  install.packages("igraph", 
                   dependencies=c("Depends", "Suggests"))
library(igraph)

G<- graph.formula(1-2, # un grafo simple
                  1-3,
                  1-4,
                  2-5,
                  5-1)
plot(G)                # plot sin argumentos
V(G)                   # vértices (nodos)
E(G)                   # aristas (bordes)

                       # opciones gráficas globale
igraph.options(vertex.size = 10,
               edge.arrow.size =0.2)
           
G<- graph.formula(1-+2, # directed G
                  1-+3,
                  1-+4,
                  2-+5,
                  5-+1)
plot(G)                # plot sin argumentos
V(G)                   # vertices (nodos)
E(G)                   # aristas (arcos)


#---------------------------------------------------------------#
set.seed(1)
G<- graph.formula(un-+deux, # directed G
                  un-+trois,
                  un-+quatre,
                  deux-+cinq,
                  cinq-+un)
V(G)                   # vertices (nodos)
E(G)                   # aristas (arcos)
set.seed(1)
plot(G,
     main= "grafo con texto y opciones", # título
     vertex.label.dist = 1.5, # etiquetas desplazadas
     vertex.color = "yellow",
     vertex.frame.color = "blue", # color de trazo de nodos
     vertex.label.color = "black", # color de la etiqueta
     vertex.label.font = 3, # fuente
     vertex.label.cex = 1.5, # tamaño de fuente
     vertex.forma = "sphere", #forma
     vertex.label.degree = - pi, # etiqueta a la izquierda
     edge.arrow.size = 0.1, # tamaño de punta de flecha
     edge.arrow.mode = 2, # flecha de fin de arco normal
     edge.curved = -0.2, #curvatura aristas
     edge.lty = 2, # tipo de línea
     edge.width = 2, # grosor de línea
     edge.arrow.width = 2, # ancho de punta de flecha
     margin=0.1) # margen de cuadro

# para guardar un grafo
png(filename="mi_grafo.png",
    height=800,
    width = 600) # abrir dispositivo de salida png
plot(G)
dev.off() # ¡atención, debe estar CERRADO!

# exportar un gráfico
write.graph(G, file='mi_grafo.dl', format="pajek")
                              # importar un grafo
G_ <- read.graph(file='mi_grafo.dl', format="pajek")
plot(G_)

neighbors(G,5, mode ="total") # vecinos
neighbors(G,5, mode ="in")    # vecinos antes
neighbors(G,5, mode ="out")   # vecinos después
incident(G,5, mode = "total") # aristas incidentes
incident(G,5, mode = "in")    # aristas entrantes
incident(G,5, mode = "out")   # aristas salientes
are_adjacent(G, 1, 2)         # adyacentes orientadas
are_adjacent(G, 2, 1)         # adyacentes orientadas

E(G)[inc(5)]                  # arcos con  nodo 5
E(G)[from(5)]                 # arcos  de   nodo 5
E(G)[to(5)]                   # arcos  hacie nodo 5

A <- get.adjacency(G)  # matrice de adyacencia
A                      # sparse Matrix
A[2:3,]
A[,1:2]
sum(A) # podemos hacer cálculos

# operaciones básicas
set.seed(15) # dominio aleatorio
G <- make_graph("HouseX") # casa con cruz
vcount(G) # número de nodos
ecount(G) # número de aristas
set.seed(15);plot(G)
vertex_attr(G) # vacío porque no tiene atributo
edge.attributes(G) # igual para los bordes

# actualizar atributos de borde
# para todas las aristas
# usando el pipe: %>% 
G <- G %>% 
       set_edge_attr("label", value = letters[1:ecount(G)])
set.seed(15);plot(G)
edge.attributes(G)
str(G)

#  manipulación de atributos por
# asignación y $
V(G)$color <- "green" # color de los nodos
# solo para estos nodos:
V(G)(c(1,3,5)]$color <- "white"
V(G)$size <- 20 # tamaño de nodos

# cambiar etiquetas
x <- "N_" ; y <- sapply(V(G),(function(z) paste0(x,z)))
V(G)$label <- y
vertex_attr(G)             # lista de los atributos 
set.seed(15);plot(G)

                           # creación nuevo atributo
V(G)[c(1,3,5)]$nuevo_atributo <- "top" 
V(G)$nuevo_atributo       # contiene los NA
                           # búsqueda según una condición
top <- which(V(G)$nuevo_atributo == "top")
                           # complementarios de los tops
pas_top <- setdiff(1:vcount(G),top)
pas_top
                           # información adicional
V(G)[pas_top]$nuevo_atributo <- "p_top"
V(G)$nuevo_atributo      

V(G)[[]]                   # descripción exhaustiva de los nodos
E(G)[[]]                   # descripción exhaustiae de los bordes

V(G)[ nuevo_atributo == "p_top" ]

#---------------------------------------------------------------#

# diferente aspecto mismo grafo
op <- par() # almacena el valor de diseño anterior
par(mfrow = c(1,4)) #
#diferentes aspectos mismo grafo
# tamaño de caracteres aristas
G <- G %>% 
     set_edge_attr("label.cex",value = 1.6)    %>% 
     set_vertex_attr("label.cex",value = 1)  %>%
     set_vertex_attr("size", value =40)
     
set.seed(15);plot(G)         
set.seed(15);plot(G, layout=layout.circle)         
set.seed(15);plot(G, layout=layout.reingold.tilford(G,circular=T))
set.seed(15);plot(G, layout=layout.reingold.tilford)  # PELIGRO
par(op)                      #

#---------------------------------------------------------------#
                             # un grafo  3-conexo
G <- graph_from_literal( A:B:C -- A:B:C ) +
     graph_from_literal( D:E:F:G -- D:E:F:G) +
     graph_from_literal( I-- K, I--L, I--M) 
plot(G)
diameter(G)                  # diámetro de un grafo

#---------------------------------------------------------------#
                             # subgraph a partir de los nodos
Ha <- induced.subgraph(G, V(G)[c("D","E","F")]) # subgrafo
V(Ha)
E(Ha)

#---------------------------------------------------------------#
# cálculo de cuatro medidas de centralidad                        #

set.seed(26); G <- make_graph("Zachary") # gráfico conocido
diámeter(G) # su diámetro

nodos <- as.vector(V(G)) # etiquetas de nodos
df <- data.frame( # almacenamiento en data.frame
  nodos,
  degree(G), # grado de nodos
  closeness(G), # proximidad a los nodos
  betweenness(G), # intermedio de nodos
  eigen_centrality(G)$vector # centralidad eigen de los nodos
)
nombres(df) <- c("nodos", # cambiar los nombres de las columnas
               "degree",
               "closeness",
               "betweenness",
               "eigen_centrality")

#---------------------------------------------------------------#
# visualización de cuatro medidas de centralidad #

op <- par() # almacena el valor de diseño anterior
par(mfrow = c(1,2)) # dos grafos por línea
for(j en 2:5) { # hacer para 4 tipo de centralidad
  nodos <- as.vector(V(G)) # etiquetas de nodos
  c <- df[,j] # valores de normalización
  Mc <- max(c)
  mc <- min(c)
  c <- 20 * (c - mc) /abs(Mc-mc) # y escalar el grafo
  # entonces 20 * valor_estandar
  
  w <- cut(c, # conservamos el 15% de los nodos
           breaks = quantile(c, probs = c(0.1,0.85,1)),
           labels = FALSO)
  w <- ifelse(is.na(w),1,w) # eliminación de NA
  c <- ifelse(w == 2, c,0) # tamaño de nodos: 0 o proporción
  nodos[which(c == 0)]<-NA # eliminación de valores pequeños
  set.seed(16);
  plot(G,
          main = names(df)[j], # título = c nombre de la medida
          layout=layout.fruchterman.reingold,# diseño visual
          vertex.size = c, # tamaño del siguiente nodo
          vertex.label=nodos, # etiqueta de algunos
          vertex.label.color= "blue", # colores de etiqueta
          vertex.color = "white", # círculos de color
          edge.width=1) # ancho de línea
}
par(op) # restaurar parámetro

#---------------------------------------------------------------#
                            # determination de comunidades
CG_1 <- cluster_walktrap(G)
set.seed(16);plot(CG_1, G)

#---------------------------------------------------------------#

num_cluster <- max(membership(CG_1)) # número de clústeres
for (i in 1:num_cluster){            # para cada clúster
  l <- V(G)[membership(CG_1) == i]  # lista de sus nodos
  H <- induced.subgraph(G,l)        # el clúster
  d <- diameter(H)                  # su diámetro
  cat("Clúster",i,"de diámetro",d,"con los nodos :",l, "\n")
  }


#---------------------------------------------------------------#

CG_2 <- cluster_spinglass(G)
CG_3 <- cluster_leading_eigen(G)
op <- par()                  # almacena antiguo valor disposición
par(mfrow = c(1,3))          # troeis grafos por línea
set.seed(16);plot(CG_1, G)
set.seed(16);plot(CG_2, G)
set.seed(16);plot(CG_3, G)
par(op)                      # restauración par

#---------------------------------------------------------------#
# análisis diferencias entre clustering

t1 <- c(                     # comparación info mutua
       compare(CG_1, CG_2, method="nmi"), 
       compare(CG_1, CG_3, method="nmi"), 
       compare(CG_2, CG_3, method="nmi"),
       compare(CG_1, CG_1, method="nmi") # truco:max
       )

t2 <- c(                    # comparación contenido
       compare(membership(CG_1), membership(CG_2)),
       compare(membership(CG_1), membership(CG_3)),
       compare(membership(CG_2), membership(CG_3)),
       compare(membership(CG_1), membership(CG_1)) # truco:min
       )

t0 <- c("información mutua","nodos diferentes")
df <- data.frame(cbind(t0,rbind(round(t1,2),round(t2,2))))
names(df) <- c("Indicador",
               "Walk-Spin",
               "Walk-Eign",
               "Spin-Eign",
               "reference 100% similar")
row.names(df)<-NULL
 
modularity(CG_1) # calidad de la separación
modularity(CG_2)
modularity(CG_3)

#---------------------------------------------------------------#
# Cliques y Kn

op <- par() # almacenar valor antiguo
par(mfrow = c(2,4),pty = "s") # 2 ln, 4 columnas, cuadrado
for(i en 1:8) { # ocho Ki
  a_G <--diag(1,i)+1 # matriz de 1 excepto diag
  # gráfico de matriz
  K <- graph_from_adjacency_matrix(a_G,mode = "undirected")
  # estético
  t <- paste0("K",i," , con numb edge(s) = ",i*(i-1)/2)
  t <- ifelse(i == 1, paste('(Singleton : )',t),t)
  t <- ifelse(i == 2, paste('(Trazo: )',t),t)
  t <- ifelse(i == 3, paste('(Triángulo: )',t),t)
  s <- ifelse(i < 3 , 30,100/i)
  plot(K, main = t,
       vertex.size = s, 
       vertex.label = NA,
       vertex.color = "pink",
       layout=layout.circle)
  }
par(op)                      # restauracion par


c <- cliques(G, min = 4)     # cliques de tamaño al menos 4
length(c)                 
c <- max_cliques(G, min = 4) # cliques max no en otros cl
length(c)
largest_cliques(G)           # el o los cliques más grades

#---------------------------------------------------------------#
