Coverage for flexnetsim/network.py: 100%

187 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-22 20:03 +0000

1from .node import Node 

2from .link import Link 

3import json 

4 

5 

6class Network(): 

7 

8 def __init__(self, arg=None): 

9 self.__link_counter = 0 

10 self.__node_counter = 0 

11 self.__nodes = [] 

12 self.__links = [] 

13 self.__links_in = [] 

14 self.__links_out = [] 

15 self.__nodes_in = [] 

16 self.__nodes_out = [] 

17 

18 self.nodes_in.append(0) 

19 self.nodes_out.append(0) 

20 

21 if arg != None: 

22 if isinstance(arg, Network): 

23 self.__link_counter = arg.link_counter 

24 self.__node_counter = arg.node_counter 

25 self.__nodes = arg.nodes 

26 self.__links = arg.links 

27 self.__links_in = arg.links_in 

28 self.__links_out = arg.links_out 

29 self.__nodes_in = arg.nodes_in 

30 self.__nodes_out = arg.nodes_out 

31 else: 

32 f = open(arg) 

33 NSFnet = json.load(f) 

34 f.close() 

35 nummber_of_nodes = len(NSFnet["nodes"]) 

36 number_of_links = len(NSFnet["links"]) 

37 for i in range(0, nummber_of_nodes): 

38 id = NSFnet["links"][i]["id"] 

39 node = Node(id) 

40 self.add_node(node) 

41 

42 for i in range(0, number_of_links): 

43 id = NSFnet["links"][i]["id"] 

44 length = NSFnet["links"][i]["length"] 

45 slots = NSFnet["links"][i]["slots"] 

46 link = Link(id, length, slots) 

47 self.add_link(link) 

48 

49 src = NSFnet["links"][i]["src"] 

50 id = NSFnet["links"][i]["id"] 

51 dst = NSFnet["links"][i]["dst"] 

52 self.connect(src, id, dst) 

53 

54 @property 

55 def nodes(self): 

56 return self.__nodes 

57 

58 @property 

59 def links(self): 

60 return self.__links 

61 

62 @property 

63 def node_counter(self): 

64 return self.__node_counter 

65 

66 @property 

67 def nodes_in(self): 

68 return self.__nodes_in 

69 

70 @property 

71 def nodes_out(self): 

72 return self.__nodes_out 

73 

74 @property 

75 def link_counter(self): 

76 return self.__link_counter 

77 

78 @property 

79 def links_out(self): 

80 return self.__links_out 

81 

82 @property 

83 def links_in(self): 

84 return self.__links_in 

85 

86 def get_link(self, link_pos): 

87 if(link_pos < 0) or (link_pos >= len(self.__links)): 

88 raise ValueError("Cannot get Link from a position out of bounds.") 

89 return self.__links[link_pos] 

90 

91 def get_node(self, node_pos): 

92 if (node_pos < 0) or (node_pos >= len(self.__nodes)): 

93 raise ValueError("Cannot get Node from a position out of bounds.") 

94 return self.__nodes[node_pos] 

95 

96 def add_node(self, node: Node): 

97 if node.id != self.__node_counter: 

98 raise ValueError( 

99 "Cannot add a Node to this network with Id mismatching node counter.") 

100 self.__node_counter += 1 

101 self.__nodes.append(node) 

102 self.__nodes_in.append(0) 

103 self.__nodes_out.append(0) 

104 

105 def add_link(self, link: Link): 

106 if link.id != self.__link_counter: 

107 raise ValueError( 

108 "Cannot add a Link to this network with Id mismatching link counter.") 

109 self.__link_counter += 1 

110 self.__links.append(link) 

111 

112 def connect(self, src, link_pos, dst): 

113 if(src < 0) or (src >= self.__node_counter): 

114 raise ValueError( 

115 f"Cannot connect src {src} because its ID is not in the network. Number of nodes in network: {self.node_counter}") 

116 

117 if(dst < 0) or (dst >= self.__node_counter): 

118 raise ValueError( 

119 f"Cannot connect dst {dst} because its ID is not in the network. Number of nodes in network: {self.node_counter}") 

120 

121 if(link_pos < 0) or (link_pos >= self.__link_counter): 

122 raise ValueError( 

123 f"Cannot use link {link_pos} because its ID is not in the network. Number of links in network: {self.link_counter}") 

124 

125 self.__links_out.insert(self.__nodes_out[src], self.__links[link_pos]) 

126 for i in range((src+1), len(self.__nodes_out)): 

127 self.__nodes_out[i] += 1 

128 self.__links_in.insert(self.__nodes_in[dst], self.__links[link_pos]) 

129 for i in range((dst+1), len(self.__nodes_in)): 

130 self.__nodes_in[i] += 1 

131 self.__links[link_pos].src = src 

132 self.__links[link_pos].dst = dst 

133 

134 def is_connected(self, src, dst): 

135 for i in range(self.__nodes_out[src], self.__nodes_out[src+1]): 

136 for j in range(self.__nodes_in[dst], self.__nodes_in[dst+1]): 

137 if self.__links_out[i].id == self.__links_in[j].id: 

138 return self.__links_out[i].id 

139 return -1 

140 

141 def use_slot(self, link_pos, *, slot_pos=None, slot_from=None, slot_to=None): 

142 if (link_pos < 0) or (link_pos >= len(self.__links)): 

143 raise ValueError("Link position out of bounds") 

144 if (slot_pos != None) and (slot_from == None) and (slot_to == None): 

145 if(slot_pos < 0) or (slot_pos >= self.__links[link_pos].slots_number()): 

146 raise ValueError("Slot position out of bounds.") 

147 self.__links[link_pos].set_slot(slot_pos, True) 

148 

149 elif (slot_pos == None) and (slot_from != None) and (slot_to != None): 

150 if(slot_from < 0) or (slot_from >= self.__links[link_pos].slots_number()): 

151 raise ValueError("Slot position out of bounds.") 

152 if(slot_to < 0) or (slot_to >= self.__links[link_pos].slots_number()): 

153 raise ValueError("Slot position out of bounds.") 

154 if(slot_from > slot_to): 

155 raise ValueError( 

156 "Initial slot position must be lower than the final slot position.") 

157 if(slot_from == slot_to): 

158 raise ValueError("Slot from and slot To cannot be equals.") 

159 

160 for i in range(slot_from, slot_to): 

161 self.__links[link_pos].set_slot(i, True) 

162 

163 else: 

164 raise ValueError("Incorrect arguments given.") 

165 

166 def unuse_slot(self, link_pos, *, slot_pos=None, slot_from=None, slot_to=None): 

167 if (link_pos < 0) or (link_pos >= len(self.__links)): 

168 raise ValueError("Link position out of bounds") 

169 if (slot_pos != None) and (slot_from == None) and (slot_to == None): 

170 if(slot_pos < 0) or (slot_pos >= self.__links[link_pos].slots_number()): 

171 raise ValueError("Slot position out of bounds.") 

172 self.__links[link_pos].set_slot(slot_pos, False) 

173 

174 elif (slot_pos == None) and (slot_from != None) and (slot_to != None): 

175 if(slot_from < 0) or (slot_from >= self.__links[link_pos].slots_number()): 

176 raise ValueError("Slot position out of bounds.") 

177 if(slot_to < 0) or (slot_to >= self.__links[link_pos].slots_number()): 

178 raise ValueError("Slot position out of bounds.") 

179 if(slot_from > slot_to): 

180 raise ValueError( 

181 "Initial slot position must be lower than the final slot position.") 

182 if(slot_from == slot_to): 

183 raise ValueError("Slot from and slot To cannot be equals.") 

184 

185 for i in range(slot_from, slot_to): 

186 self.__links[link_pos].set_slot(i, False) 

187 

188 else: 

189 raise ValueError("Incorrect arguments given.") 

190 

191 def is_slot_used(self, link_pos, *, slot_pos=None, slot_from=None, slot_to=None): 

192 if (link_pos < 0) or (link_pos >= len(self.__links)): 

193 raise ValueError("Link position out of bounds") 

194 if (slot_pos != None) and (slot_from == None) and (slot_to == None): 

195 if(slot_pos < 0) or (slot_pos >= self.__links[link_pos].slots_number()): 

196 raise ValueError("Slot position out of bounds.") 

197 return self.__links[link_pos].get_slot(slot_pos) 

198 

199 elif (slot_pos == None) and (slot_from != None) and (slot_to != None): 

200 if(slot_from < 0) or (slot_from >= self.__links[link_pos].slots_number()): 

201 raise ValueError("Slot position out of bounds.") 

202 if(slot_to < 0) or (slot_to >= self.__links[link_pos].slots_number()): 

203 raise ValueError("Slot position out of bounds.") 

204 if(slot_from > slot_to): 

205 raise ValueError( 

206 "Initial slot position must be lower than the final slot position.") 

207 if(slot_from == slot_to): 

208 raise ValueError("Slot from and slot To cannot be equals.") 

209 

210 for i in range(slot_from, slot_to): 

211 if self.__links[link_pos].get_slot(i): 

212 return True 

213 return False 

214 

215 else: 

216 raise ValueError("Incorrect arguments given.") 

217 

218 def average_neighborhood(self): 

219 if self.__node_counter == 0: 

220 raise ValueError("The network must be have at least one node.") 

221 result = self.__link_counter/self.__node_counter 

222 return result 

223 

224 def normal_average_neighborhood(self): 

225 if self.__node_counter == 0: 

226 raise ValueError("The network must be have at least one node.") 

227 result = self.__link_counter / \ 

228 (self.__node_counter * (self.__node_counter - 1)) 

229 return result 

230 

231 def nodal_variance(self): 

232 if self.__node_counter == 0: 

233 raise ValueError("The network must be have at least one node.") 

234 result = 0.0 

235 average = self.average_neighborhood() 

236 for i in range(self.__node_counter): 

237 result += pow((self.__nodes_out[i+1] - 

238 self.__nodes_out[i])-average, 2) 

239 result /= self.__node_counter 

240 return result