НОВОСТИ [recovery mode] деградация связной структуры

BDFpromo
Оффлайн

BDFpromo

.
.
Регистрация
23.09.18
Сообщения
12.347
Реакции
176
Репутация
0
Кролики и удавы
Вирусы и питоны

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

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

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


# количество тиков времени до попадания в карантин.
# Или до выпадения из структуры компрометированного узла
# т.е. узел скомпрометирован/болен, но это еще не обнаружено и он несколько тиков
# времени продолжает заражать других
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 то изолирован, >dead - отключен
# патч применен
map_stat = np.zeros((w_size), dtype="int16")

# храним связную структуру в виде списка списков связности.
# Т.е. map_conn - список с номерами узлов связанных с узлом 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.append(j)
map_conn[j].append(i)

for i in range(w_size):
map_conn = list(set(map_conn))

# очевидно, что возможно и больше max_conn связей.
# Мы создаем случайно для каждого узла max_conn//2 связей,
# но связность симметрична.

# состояние узла. Если 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 < 0:
map_stat = tmp_map_stat
continue

# если узел был инфицирован и более чем quarantine тиков времени/дней
# увеличиваем счетчик тиков на 1
if tmp_map_stat >= quarantine:
map_stat = tmp_map_stat + 1
continue

# если узел был инфицирован и менее чем quarantine тиков времни/дней
# то он выздоравливает с вероятностью pr_recover
# или счетчик тиков деградации увеличивается на один
if tmp_map_stat > 0:
if np.random.rand() < pr_recover:
map_stat = -tmp_map_stat
else:
map_stat = tmp_map_stat + 1
# если узел в деградации больше quarantine тиков,
# то наверно это обнаружится и узел изолируют и начнут восстанавливать
# и все его связи исчезнут и связи с ним тоже
if map_stat >= quarantine:
for j in tmp_map_conn:
if i in map_conn[j]:
map_conn[j].remove(i)
map_conn = []
continue

# если узел здоров, то в общении со своим контактом может
# заразиться с вероятностью infection_probably
if tmp_map_stat == 0:
map_stat = 0
for j in tmp_map_conn:
t = np.random.rand()
if (
t < infection_probably
and tmp_map_stat[j] > 0
and tmp_map_stat[j] < quarantine
):
map_stat = 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 это не зависит.
 
Сверху Снизу