-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.py
132 lines (110 loc) · 4.24 KB
/
graph.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
import numpy as np
import itertools
class Graph:
def __init__(self, N, weight=1):
self.N = N
self.init_nodes()
self.edges = []
self.isolated_nodes = []
self.list_edges = []
self.weight = weight #For unweighted graphs
def is_symmetric(self, matrix):
return np.allclose(matrix, matrix.T, rtol=1e-05, atol=1e-08)
def from_adjacency_matrix(self, A):
if self.is_symmetric(A):
self.init_nodes()
for n_i in range(self.N):
for n_j in range(n_i, self.N):
self.add_edge(n_i+1, n_j+1, A[n_i, n_j])
else:
raise Exception('Adjacency matrix is not symmetric')
def init_nodes(self):
self.graph = {int_val: dict() for int_val in range(1, self.N+1)}
def nodes(self):
return list(self.graph.keys())
def number_of_edges(self):
return len(self.edges)
def get_neighbors(self, node):
return list(self.graph[node].keys())
def get_neighbors_weights(self, node):
return np.asarray(list(self.graph[node].values()))
def node_degree(self, node):
return sum(list(self.graph[node].values()))
def find_edge(self, node1, node2):
try:
return self.graph[node1][node2]
except KeyError:
return None
def add_edge(self, node1, node2, weight = 1):
u,v = sorted([node1, node2])
if (u-1, v-1) not in self.edges and u != v:
self.graph[u][v] = weight
self.graph[v][u] = weight
self.edges.append((u-1, v-1))
def remove_edge(self, node1, node2):
u, v = sorted([node1, node2])
if self.find_edge(u, v) != None:
del self.graph[u][v]
del self.graph[v][u]
self.edges.remove((u-1, v-1))
def remove_node(self, node):
node_neighbors = self.get_neighbors(node)
for neighbor in node_neighbors:
self.remove_edge(node,neighbor)
if len(self.get_neighbors(node)) == 0:
del self.graph[node]
else:
raise Exception('something went wrong')
def create_new_node(self):
new_node_idx = max(self.nodes())+1
self.graph[new_node_idx] = {}
def enhance_edge_weight(self, node1, node2, delta):
self.graph[node1][node2] += delta
self.graph[node2][node1] += delta
def get_knn(self, padded_list, j, m):
return sorted(padded_list[j-m:j][::-1] + padded_list[j+1:j+m+1])
def add_nn_edges(self, k, weight):
m = int(k/2)
#Set lattice vertices
padded_list = self.nodes()*3
self.graph = {self.nodes()[i]: {w: self.weight for w in self.get_knn(padded_list, j, m)}
for i, j in zip(range(self.N), range(self.N, 2*self.N))}
nodes = self.nodes()
self.list_edges = [l for sl in
[[(u,v) for u,v in zip(nodes, nodes[j:] + nodes[0:j])] for j in range(1, k//2+1)]
for l in sl]
for e in self.list_edges:
u ,v = e
self.edges.append(tuple(sorted([u-1, v-1])))
def find_isolated_nodes(self):
if any(edges != {} for edges in self.graph.values()):
pass
else:
for node, edges in self.graph.items():
if edges == {}: self.isolated_nodes.append(node)
def adjacency_matrix(self):
A = np.zeros((self.N, self.N))
for i in self.edges:
r, c = i
A[r][c] = self.graph[r+1][c+1]
A[c][r] = A[r][c]
return A
def is_connected(self):
self.find_isolated_nodes()
if any(self.isolated_nodes):
return False
v0 = self.nodes()[0]
queue = []
visited = []
queue.append(v0)
while (queue):
v = queue[0]
visited.append(v)
queue.remove(queue[0])
for node in self.graph[v]:
if node not in visited and node not in queue:
queue.append(node)
if set(visited) == set(self.nodes()):
return True
else:
return False