Advertisement
999ms

Untitled

Jul 26th, 2020
1,478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.46 KB | None | 0 0
  1. import ipaddress
  2. from random import randint
  3. from random import shuffle
  4. import time
  5.  
  6.  
  7. #############################################################
  8. class BinaryTrie():
  9.     def __init__(self):
  10.         self.MASK = (1 << 31) - 1
  11.         self.nodes = [0 for _ in range(64)]
  12.         self.empty_nodes = [63 - i for i in range(63)]
  13.  
  14.     def __sizeof__(self):
  15.         return self.nodes.__sizeof__() + self.empty_nodes.__sizeof__()
  16.  
  17.     def _get_left(self, value):
  18.         return (value >> 1) & self.MASK
  19.  
  20.     def _get_right(self, value):
  21.         return value >> (31 + 1)
  22.  
  23.     def _get_type(self, value):
  24.         return value & 1
  25.  
  26.     def _create_node(self):
  27.         if len(self.empty_nodes) == 0:
  28.             self.empty_nodes = [31 + len(self.nodes) - i for i in range(32)]
  29.             self.nodes += [0 for _ in range(32)]
  30.         index = self.empty_nodes.pop()
  31.         return index
  32.  
  33.     def _remove_nodes(self, node):
  34.         if node == 0:
  35.             return
  36.         self.empty_nodes.append(node)
  37.         left_node = self._get_left(self.nodes[node])
  38.         self._remove_nodes(left_node)
  39.         right_node = self._get_right(self.nodes[node])
  40.         self._remove_nodes(right_node)
  41.         self.nodes[node] = 0
  42.  
  43.     def add(self, address):
  44.         value, size = self.change_format(address)
  45.         current_node = 0
  46.         for i in range(size):
  47.             bit = 31 - i
  48.             if self._get_type(self.nodes[current_node]) == 1:  # leaf
  49.                 return
  50.             if (value >> bit) & 1 == 0:
  51.                 current_left = self._get_left(self.nodes[current_node])
  52.                 if current_left == 0:
  53.                     current_left = self._create_node()
  54.                     self.nodes[current_node] |= current_left << 1
  55.                 current_node = current_left
  56.             else:
  57.                 current_right = self._get_right(self.nodes[current_node])
  58.                 if current_right == 0:
  59.                     current_right = self._create_node()
  60.                     self.nodes[current_node] |= current_right << (31 + 1)
  61.                 current_node = current_right
  62.  
  63.         current_left = self._get_left(self.nodes[current_node])  # delete children if a vertex added
  64.         current_right = self._get_right(self.nodes[current_node])
  65.  
  66.         self._remove_nodes(current_left)
  67.         self._remove_nodes(current_right)
  68.  
  69.         self.nodes[current_node] = 1  # leaf
  70.  
  71.     def __contains__(self, address):
  72.         value, size = self.change_format(address)
  73.         current_node = 0
  74.         for i in range(size):
  75.             bit = 31 - i
  76.             if self._get_type(self.nodes[current_node]) == 1:
  77.                 return True
  78.             if (value >> bit) & 1 == 0:
  79.                 current_left = self._get_left(self.nodes[current_node])
  80.                 if current_left == 0:
  81.                     return False
  82.                 current_node = current_left
  83.             else:
  84.                 current_right = self._get_right(self.nodes[current_node])
  85.                 if current_right == 0:
  86.                     return False
  87.                 current_node = current_right
  88.         return self._get_type(self.nodes[current_node]) == 1
  89.  
  90.     def change_format(self, address):
  91.         if '/' in address:
  92.             address, routing_prefix = address.split('/')
  93.             size = 32 - int(routing_prefix)
  94.         else:
  95.             size = 0
  96.  
  97.         address = list(map(int, address.split('.')))
  98.  
  99.         value = 0
  100.         for item in address:
  101.             value <<= 8
  102.             value ^= item
  103.  
  104.         value >>= size
  105.         value <<= size
  106.         return value, 32 - size
  107.  
  108.  
  109. ##############################################################
  110. def add_set(subnet):
  111.     try:
  112.         addresses_set.add(ipaddress.ip_network(subnet))
  113.     except Exception:
  114.         subnet = ipaddress.ip_interface(subnet)
  115.         addresses_set.add(subnet.network)
  116.  
  117.  
  118. def contains_set(address):
  119.     address = ipaddress.ip_address(address)
  120.     for subnet in addresses_set:
  121.         if address in subnet:
  122.             return True
  123.     return False
  124.  
  125.  
  126. def add_list(subnet):
  127.     try:
  128.         addresses_list.append(ipaddress.ip_network(subnet))
  129.     except Exception:
  130.         subnet = ipaddress.ip_interface(subnet)
  131.         addresses_list.append(subnet.network)
  132.  
  133.  
  134. def contains_list(address):
  135.     address = ipaddress.ip_address(address)
  136.     for subnet in addresses_list:
  137.         if address in subnet:
  138.             return True
  139.     return False
  140.  
  141.  
  142. #### TEST PART ####
  143.  
  144. def get_rand_address(N):
  145.     mask = [str(randint(1, 255)) + '.' + str(randint(1, 255)) + '.' + str(randint(1, 255)) + '.' + str(randint(1, 255))
  146.             for i in range(N)]
  147.     submask = [mask[i] + '/' + str(randint(8, 32)) for i in range(N) for _ in range(8)]
  148.     return submask
  149.  
  150.  
  151. def test_add(N):
  152.     addresses = get_rand_address(N)
  153.     times = [[] for _ in range(3)]
  154.     memories = [[] for _ in range(3)]
  155.  
  156.     for i in range(0, N, 100):
  157.         current_addresses = [addresses[i + j] for j in range(100)]
  158.         start = time.time()
  159.         for address in current_addresses:
  160.             add_set(address)
  161.         time_set = time.time() - start
  162.         times[0].append(time_set + (times[0][-1] if len(times[0]) else 0))
  163.         memories[0].append(addresses_set.__sizeof__())
  164.  
  165.         start = time.time()
  166.         for address in current_addresses:
  167.             add_list(address)
  168.         time_list = time.time() - start
  169.         times[1].append(time_list + (times[1][-1] if len(times[1]) else 0))
  170.         memories[1].append(addresses_list.__sizeof__())
  171.  
  172.         start = time.time()
  173.         for address in current_addresses:
  174.             binaryTrie.add(address)
  175.         time_SUPERTREE = time.time() - start
  176.         times[2].append(time_SUPERTREE + (times[2][-1] if len(times[2]) else 0))
  177.         memories[2].append(binaryTrie.__sizeof__())
  178.  
  179.     return [times, memories]
  180.  
  181.  
  182. check1 = []
  183. check2 = []
  184. check3 = []
  185.  
  186.  
  187. def test_contains(N):
  188.     addresses = get_rand_address(N)
  189.  
  190.     for i in range(len(addresses)):
  191.         if '/' in addresses[i]:
  192.             pref, suf = addresses[i].split('/')
  193.             addresses[i] = pref
  194.  
  195.     times = [[] for _ in range(3)]
  196.     for i in range(0, N, 100):
  197.         current_addresses = [addresses[i + j] for j in range(100)]
  198.  
  199.         start = time.time()
  200.         for address in current_addresses:
  201.             check1.append(contains_set(address))
  202.         time_set = time.time() - start
  203.         times[0].append(time_set + (times[0][-1] if len(times[0]) else 0))
  204.  
  205.         start = time.time()
  206.         for address in current_addresses:
  207.             check2.append(contains_list(address))
  208.         time_list = time.time() - start
  209.         start = time.time()
  210.         times[1].append(time_list + (times[1][-1] if len(times[1]) else 0))
  211.  
  212.         for address in current_addresses:
  213.             check3.append(binaryTrie.__contains__(address))
  214.         time_SUPERTREE = time.time() - start
  215.         times[2].append(time_SUPERTREE + (times[2][-1] if len(times[2]) else 0))
  216.  
  217.     return times
  218.  
  219.  
  220. addresses_set = set()
  221. addresses_list = []
  222. binaryTrie = BinaryTrie()
  223. import matplotlib.pyplot as plt
  224.  
  225. N = 100000
  226. print(N)
  227. times_add, memories = test_add(N)
  228. print('test_add done')
  229. ox = [i for i in range(0, N, 100)]
  230.  
  231. fig, axes = plt.subplots(nrows=1, ncols=1)
  232. axes.plot(ox, times_add[0], color='#00dd00', label="Set")
  233. axes.plot(ox, times_add[1], color='#dd0000', label="List")
  234. axes.plot(ox, times_add[2], color='#0000dd', label="Trie")
  235. axes.legend(loc="upper left")
  236. axes.set_xlabel("Количество подсетей")
  237. axes.set_ylabel("Время работы add")
  238. fig.set_size_inches(10, 7)
  239. plt.show()
  240.  
  241. fig, axes = plt.subplots(nrows=1, ncols=1)
  242. axes.plot(ox, memories[0], color='#00dd00', label="Set")
  243. axes.plot(ox, memories[1], color='#dd0000', label="List")
  244. axes.plot(ox, memories[2], color='#0000dd', label="Trie")
  245. axes.legend(loc="upper left")
  246. axes.set_xlabel("Количество подсетей")
  247. axes.set_ylabel('Memory')
  248. fig.set_size_inches(10, 7)
  249. plt.show()
  250.  
  251. N = 1000
  252. ox = [i for i in range(0, N, 100)]
  253. times_contains = test_contains(N)
  254. print('test contains done')
  255. fig, axes = plt.subplots(nrows=1, ncols=1)
  256. axes.plot(ox, times_contains[0], color='#00dd00', label="Set")
  257. axes.plot(ox, times_contains[1], color='#dd0000', label="List")
  258. axes.plot(ox, times_contains[2], color='#0000dd', label="Trie")
  259. axes.legend(loc="upper left")
  260. axes.set_xlabel("Количество подсетей")
  261. axes.set_ylabel("Время работы contains")
  262. fig.set_size_inches(10, 7)
  263. plt.show()
  264.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement