Cidr4 merge algorithm #5

Merged
PavelPatsey merged 91 commits from CIDR4_merge_algorithm into main 2025-01-27 22:05:39 +03:00
Showing only changes of commit bb269f380a - Show all commits
+39 -13
View File
@@ -1,4 +1,4 @@
import ipaddress from copy import deepcopy
Fedor-Lyanguzov commented 2025-01-07 17:54:03 +03:00 (Migrated from github.com)
Review

Здесь за один проход объединяются все возможные объединения, таким образом мы можем промахнуться мимо цели в M элементов списка.

Здесь за один проход объединяются все возможные объединения, таким образом мы можем промахнуться мимо цели в `M` элементов списка.
Fedor-Lyanguzov commented 2025-01-07 17:55:32 +03:00 (Migrated from github.com)
Review

Здесь не хватает возвращения количества адресов, "попавших под раздачу": не принадлежащих начальному списку, но попавших в результат из-за объединения. Это количество позволит найти оптимальное решение.

Здесь не хватает возвращения количества адресов, "попавших под раздачу": не принадлежащих начальному списку, но попавших в результат из-за объединения. Это количество позволит найти оптимальное решение.
Fedor-Lyanguzov commented 2025-01-07 17:57:45 +03:00 (Migrated from github.com)
Review

Я думаю, использование внешней библиотеки (и вообще любой библиотеки) размывает смысл алгоритма: хотя из следующих строк понятно, что будет сделано; однако не очевидно, как это будет сделано, и будет ли оптимальный ответ, и будет ли оптимальное решение (что не обязательно).

Я думаю, использование внешней библиотеки (и вообще любой библиотеки) размывает смысл алгоритма: хотя из следующих строк понятно, что будет сделано; однако не очевидно, как это будет сделано, и будет ли оптимальный ответ, и будет ли оптимальное решение (что не обязательно).
Fedor-Lyanguzov commented 2025-01-12 17:46:01 +03:00 (Migrated from github.com)
Review

Мне кажется, что функция merge_nodes содержит не все свои обязанности, некоторые из них похоже вложись в функцию reduce_nodes. Стоит их переместить.

Мне кажется, что функция `merge_nodes` содержит не все свои обязанности, некоторые из них похоже вложись в функцию `reduce_nodes`. Стоит их переместить.
Fedor-Lyanguzov commented 2025-01-12 19:00:28 +03:00 (Migrated from github.com)
Review

Алгоритм слишком много делает каждый шаг, из-за этого работает медленно. Как мне кажется, для оптимизации стоит разработать алгоритм начиная с рекурсии, возможно их будет штук 5 связанных, зато это позволит определить характеристики отдельных кусков и принять решение по оптимизации.

Алгоритм слишком много делает каждый шаг, из-за этого работает медленно. Как мне кажется, для оптимизации стоит разработать алгоритм начиная с рекурсии, возможно их будет штук 5 связанных, зато это позволит определить характеристики отдельных кусков и принять решение по оптимизации.
Fedor-Lyanguzov commented 2025-01-12 19:01:34 +03:00 (Migrated from github.com)
Review

Пора перенести тесты в отдельный файл?

Пора перенести тесты в отдельный файл?
from ipaddress import IPv4Address from ipaddress import IPv4Address
from typing import List, Tuple from typing import List, Tuple
@@ -20,40 +20,66 @@ def cidr4_to_binary(cidr4: str) -> Tuple[str, int]:
def binary_to_cidr4(binary_ip: str, vlsm: int) -> str: def binary_to_cidr4(binary_ip: str, vlsm: int) -> str:
int_ip = int(binary_ip, 2) int_ip = int(binary_ip, 2)
ip_str = str(ipaddress.IPv4Address(int_ip)) ip_str = str(IPv4Address(int_ip))
return f"{ip_str}/{vlsm}" return f"{ip_str}/{vlsm}"
def reduce_bin_ip(bin_ip: str, vlsm: int) -> Tuple[str, int]: def reduce_bin_ip(bin_ip: str, vlsm: int) -> Tuple[str, int]:
if vlsm == 0: if vlsm == 0:
return bin_ip, vlsm return "0" * 32, vlsm
new_vlsm = vlsm - 1 new_vlsm = vlsm - 1
new_bin_ip = bin_ip[:new_vlsm] + "0" * (32 - new_vlsm) new_bin_ip = bin_ip[:new_vlsm] + "0" * (32 - new_vlsm)
if new_bin_ip == "0" * 32:
return "0" * 32, 0
return new_bin_ip, new_vlsm return new_bin_ip, new_vlsm
def rough_merge_ips(
bin_ips: List[Tuple[str, int]], req_len: int
) -> List[Tuple[str, int]]:
ips = deepcopy(bin_ips)
reduction_limit_reached = False
while len(ips) > req_len and not reduction_limit_reached:
max_vlsm = max(ips, key=lambda x: x[1])[1]
ips_to_reduce = []
merged_ips = []
for ip_vlsm in ips:
if ip_vlsm[1] == max_vlsm:
ips_to_reduce.append(ip_vlsm)
else:
merged_ips.append(ip_vlsm)
reduced_ips = map(lambda x: reduce_bin_ip(*x), ips_to_reduce)
reduced_ips = set(reduced_ips)
reduced_ips = filter(lambda x: "1" in x[0], reduced_ips)
merged_ips.extend(list(reduced_ips))
if len(merged_ips) > req_len:
ips = merged_ips
else:
reduction_limit_reached = True
return ips
def main(): def main():
file = "cidr4.txt" file = "cidr4.txt"
data = get_data(file) data = get_data(file)
bin_ips = list(map(cidr4_to_binary, data)) bin_ips = list(map(cidr4_to_binary, data))
for b in bin_ips[:5]: rough_merged_bin_ips = rough_merge_ips(bin_ips, 20)
print(b) print(f"{len(rough_merged_bin_ips)=}")
sorted_ips = sorted(rough_merged_bin_ips)
for ip in sorted_ips:
print(ip)
if __name__ == "__main__": if __name__ == "__main__":
assert cidr4_to_binary("4.78.139.0/24") == ("00000100010011101000101100000000", 24) assert cidr4_to_binary("4.78.139.0/24") == ("00000100010011101000101100000000", 24)
assert binary_to_cidr4("00000100010011101000101100000000", 24) == "4.78.139.0/24" assert binary_to_cidr4("00000100010011101000101100000000", 24) == "4.78.139.0/24"
assert reduce_bin_ip("00000100010011101000101100000000", 24) == ( assert reduce_bin_ip("00000100010011101000101100000000", 24) == (
"00000100010011101000101000000000", "00000100010011101000101000000000",
23, 23,
) )
assert reduce_bin_ip("10000000000000000000000000000000", 1) == ( assert reduce_bin_ip("10000000000000000000000000000000", 1) == ("0" * 32, 0)
"00000000000000000000000000000000", assert reduce_bin_ip("10000000000000000000000000000000", 0) == ("0" * 32, 0)
0, assert reduce_bin_ip("0" * 32, 0) == ("0" * 32, 0)
)
assert reduce_bin_ip("10000000000000000000000000000000", 0) == (
"10000000000000000000000000000000",
0,
)
main() main()