-
Notifications
You must be signed in to change notification settings - Fork 0
/
grafo_utils.py
executable file
·151 lines (138 loc) · 5.19 KB
/
grafo_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
from grafo import Grafo
import collections
import random
D = 0.85
def camino_minimo_bfs(grafo, inicio, fin):
'''Esta función devuelve el camino mínimo entre un vértice origen y un vértice destino'''
visitados = set()
padres = {}
camino_minimo = []
distancias = {}
padres[inicio] = None
camino_minimo.append(inicio)
distancias[inicio] = 0
if inicio == fin:
return padres, distancias
visitados.add(inicio)
cola = collections.deque()
cola.append(inicio)
while(cola):
v = cola.popleft()
for w in grafo.adyacentes(v):
if w not in visitados:
padres[w] = v
distancias[w] = distancias[v] + 1
visitados.add(w)
cola.append(w)
if w == fin:
return padres, distancias
return padres, distancias
def cantidad_en_rango(grafo, vertice, n):
'''Esta funcion devuelve la cantidad de vertices que se encuentran exactamente a n de distancia del vertice pasado por parametro'''
if n<0:
return 0
visitados = set()
distancias = {}
cantidad = 0
visitados.add(vertice)
distancias[vertice] = 0
cola = collections.deque()
cola.append(vertice)
while(cola):
v = cola.popleft()
for w in grafo.adyacentes(v):
if w not in visitados:
distancias[w] = distancias[v] + 1
visitados.add(w)
if distancias[w] < n:
cola.append(w)
else:
cantidad += 1
return cantidad
def backtracking(grafo, origen, vertice, n, camino):
'''Algoritmo llamado en buscar_ciclo'''
if((len(camino) == n+1) and (vertice == origen)):
return True, camino
for adyacente in grafo.adyacentes(vertice):
if (adyacente != origen):
if adyacente in camino:
continue
if (adyacente == origen):
if len(camino) != n:
continue
if len(camino) > n:
return False, camino
camino.append(adyacente)
booleano, camino = backtracking(grafo, origen, adyacente, n, camino)
if booleano == False:
camino.remove(adyacente)
else:
return True, camino
return False, camino
def buscar_ciclo(grafo, origen, n):
'''Esta funcion se encarga de buscar un ciclo de n vertices que comience y termine en el vertice pasado por parametro'''
camino = []
camino.append(origen)
return backtracking(grafo, origen, origen, n, camino)
def pageRank_personalizado(grafo, v, n, rol = None):
'''Calcula el pagerank personalizado de un grafo'''
valores_vertices = {}
grados_vertices = grafo.obtener_grado_vertices()
acumulador = 1
for i in range(n*n):
w = random.choice(grafo.adyacentes(v))
acumulador *= (1 / grados_vertices[v])
valores_vertices[w] = acumulador
v = w
return valores_vertices
def coeficiente_clustering_promedio(grafo):
'''Calcula el clustering promedio de un grafo'''
sumatoria_de_coeficientes = 0
for vertice in grafo.obtener_vertices():
sumatoria_de_coeficientes += coeficiente_clustering(grafo, vertice)
return sumatoria_de_coeficientes/len(grafo.obtener_vertices())
def coeficiente_clustering(grafo, vertice):
'''Calcula el coeficiente de clustering a partir de un vertice en particular'''
adyacentes = grafo.adyacentes(vertice)
grado_vertices = grafo.obtener_grado_vertices()
if(len(adyacentes) < 2):
return 0
contador = 0
total_adyacentes = len(adyacentes)
visitados = set()
for i in adyacentes:
for j in adyacentes:
if i == j:
continue
if ((i, j) in visitados) or ((j, i) in visitados):
continue
visitados.add((i, j))
if grafo.estan_unidos(i, j):
contador += 1
numerador = 2 * contador
denominador = grado_vertices[vertice] * (grado_vertices[vertice] - 1)
return numerador / denominador
def suma_pageranks(grafo, lista_de_adyacentes, diccionario_pageranks):
sumatoria = 0
grados = grafo.obtener_grado_vertices()
for vertice in lista_de_adyacentes:
grado_vertice = grados[vertice]
sumatoria += diccionario_pageranks[vertice]/grado_vertice
return sumatoria
def pagerank(grafo, rol = None):
'''Permite calcular el pagerank de un grafo. Se puede pasar opcionalmente
un rol como parametro, que sirve como filtro, para 'pagerankear' unicamente
el tipo de vertice de interes en el grafo. Sin embargo, el calculo se hace
sobre todo el grafo'''
diccionario_pageranks = {}
acumulador = ((1 - D)/len(grafo))
for vertice in grafo.obtener_vertices():
diccionario_pageranks[vertice] = 0
for c in range(50):
for v in grafo.obtener_vertices():
diccionario_pageranks[v] = acumulador + D * suma_pageranks(grafo, grafo.adyacentes(v), diccionario_pageranks)
diccionario_filtrado = {}
for elemento in diccionario_pageranks:
if grafo.obtener_rol(elemento) == rol:
diccionario_filtrado[elemento] = diccionario_pageranks[elemento]
return diccionario_filtrado