Деградация связной структуры

Кролики и удавы
Вирусы и питоны

Всё, что один человек написал, другой может переврать!

В прессе масса информации про разные вирусы — страшилки, наив, бесстрашие с безумием и откровенные роботексты, но проверить ничего из этого нельзя. Поэтому решил проверить сам как и какие параметры влияют на состояние, развитие и деградацию связной структуры и сделать выводы.

Перейдем к делу, у нас есть узлы(может это и люди) связанные между собой. Узлы деградируют/болеют и их можно лечить, изолировать в карантине, ну и они отключаются, увы иногда навсегда.

# количество тиков времени до попадания в карантин. # Или до выпадения из структуры компрометированного узла # т.е. узел скомпрометирован/болен, но это еще не обнаружено и он несколько тиков # времени продолжает заражать других quarantine = 2  # если после стольких дней узел не исправлен - удаляем окончательно dead = 14  #  вероятность деградации узла, заражения здорового, появления вируса и т.д.  #  за один тик времени при общении с зараженным узлом вне карантина infection_probably = 0.5  #  вероятность починки узла, выздоровления больного, #  исчезновения вируса и т.д. за один тик времени pr_recover = 0.5  #  число узлов/жителей w_size = 1024 * 32  #  связность, пытаемся создать у каждого узла не более max_conn связей max_conn = 6  import numpy as np from tqdm import tqdm  map_conn = []  # храним тут состояние узла. =0 исправен, >0  но <quarantine то заразен # и не изолирован, >quarantine то изолирован, >dead - отключен # <0 - вылечен и обладает иммунитетом/патч применен map_stat = np.zeros((w_size), dtype="int16")  # храним связную структуру в виде списка списков связности. # Т.е. map_conn[i] - список с номерами узлов связанных с узлом i for i in range(w_size):     map_conn.append([])      for i in tqdm(range(w_size)):     t = np.random.randint(0, max_conn//2)     tt = np.random.randint(0, w_size, (t))     for j in tt:         map_conn[i].append(j)         map_conn[j].append(i)  for i in range(w_size):     map_conn[i] = list(set(map_conn[i]))      # очевидно, что возможно и больше max_conn связей. # Мы создаем случайно для каждого узла max_conn//2 связей, # но связность симметрична.  # состояние узла. Если 0 то здоров, если <0 переболел, восстановлен и  # не будет больше болеть # если >0 то инфицирован/деградирует, если >quarantine, то в изоляции # если >dead отключен окончательно, увы. map_stat[:] = 0 # в начале все здоровы  map_stat[np.random.randint(1, w_size)] = 1 # случайный узел деградировал, первый день деградации.  day = 1  print("map num ", w_size)  while True:      tmp_map_conn = map_conn.copy()     tmp_map_stat = map_stat.copy() # тут сохраняем структуру во временное хранилище и  # начнем вычислять новое состояние      for i in range(w_size): # если узел был инфицирован и восстановлен. # Болел - выздоровел/патч накатили - иммунитет # состояние сохраняется         if tmp_map_stat[i] < 0:             map_stat[i] = tmp_map_stat[i]             continue  # если узел был инфицирован и более чем quarantine тиков времени/дней # увеличиваем счетчик тиков на 1         if tmp_map_stat[i] >= quarantine:             map_stat[i] = tmp_map_stat[i] + 1             continue  # если узел был инфицирован и менее чем quarantine тиков времни/дней # то он выздоравливает с вероятностью pr_recover # или счетчик тиков деградации увеличивается на один         if tmp_map_stat[i] > 0:             if np.random.rand() < pr_recover:                 map_stat[i] = -tmp_map_stat[i]             else:                 map_stat[i] = tmp_map_stat[i] + 1 # если узел в деградации больше quarantine тиков, # то наверно это обнаружится и узел изолируют и начнут восстанавливать # и все его связи исчезнут и связи с ним тоже                 if map_stat[i] >= quarantine:                     for j in tmp_map_conn[i]:                         if i in map_conn[j]:                             map_conn[j].remove(i)                     map_conn[i] = []             continue  # если узел здоров, то в общении со своим контактом может # заразиться с вероятностью infection_probably         if tmp_map_stat[i] == 0:             map_stat[i] = 0             for j in tmp_map_conn[i]:                 t = np.random.rand()                 if (                     t < infection_probably                     and tmp_map_stat[j] > 0                     and tmp_map_stat[j] < quarantine                 ):                     map_stat[i] = 1                     break  # считаем число элементов до 0, от 0 до quarantine # от quarantine до dead      immun = np.count_nonzero(map_stat < 0)     quar = np.count_nonzero((map_stat >= quarantine) & (map_stat < dead))     dead_s = np.count_nonzero(map_stat >= dead)     infl = np.sum((map_stat > 0) & (map_stat < dead))     print(         "day {0:3d} infl {1:6d} immun {2:6d} quarantine {3:6d} dead {4:6d}".format(             day, infl, immun, quar, dead_s         )     ) # если больных нет, считать прекращаем     if infl == 0:         break # и так далее     day += 1 

Тут самое время сказать — ну и что, что такого могут открыть десяток строк питона! Мне результат был интересен и полезен. Получилось вот что (и был бы рад, если кто проверит и ткнет в ошибку): при infection_probably = 0.9 и max_conn = 4, т.е. при страшной заразности и при минимуме общения массовой деградации нет. Десяток запусков конечно не статистика, но мне достаточно. А вот при infection_probably = 0.1 и max_conn = 40 погибает половина. Причем от величины quarantine это не зависит.

ссылка на оригинал статьи https://habr.com/ru/post/494092/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *