Кодекс был просто обновлен (9:24:20 PM Время на форуме)!
Сроки:
Я дам 2 BTC сформировать свои личные сбережения на лучшие представления в течение следующих 5 дней с этого момента!
К лучшему представлению, я имею в виду наименее кумулятивной ошибку по сравнению с идеальным результатом. Вы поймете, что в ближайшее время 😉
Ваш алгоритм будет опробован в 9 различных настроек. Самая высокая накопленная ошибка всех параметров имеет значение. Более того, ниже!
Если у нас есть некоторые очевидные ошибки в коде или в данном описании, тот, который сделал бы все, что мы находим здесь бесполезно, вы соглашаетесь, что мы можем исправить эту ошибку еще до конца этого конкурса. Исправлена ошибка также, если мы имеем в виду что-то по-другому, что мы записали это!
Это прекрасно, чтобы представить возможные решения как можно скорее, чтобы обсудить их открыто. Если несколько решений одинаково хороши (как его случае для копирования кошек), то первое представление выиграет. Очевидная копия кошка будет дисквалифицирована на чистую воле.
Копирование кошек из других монет с либеральными лицензиями с открытым исходным кодом очень приветствуется ... до тех пор, пока он работает!
Ах, и я могу также сделать представление!
Краткая справочная информация теоретического сценария (звучит очень сложной, вы можете пропустить это, если вы чувствуете, повезли)
- 1. Мы имеем blockchain, который растет на 1 блок в от 25 до 120 секунд. Скорость роста uniformely случайным
- 2. У нас есть три типа tansaction, которые могут получить включены в каждый блок, давайте назовем их Спецодежда1, Спецодежда2 Спецодежда3
- 3. Предположим, что Спецодежда1, Спецодежда2 Спецодежда3 транзакции не могут быть получены сколь угодно быстро.
- 4. Предположим, что мы имеем базовую цель Т = 0x000000ffffffffffffffffffffffffff и мишенью может лежать только в интервале [1, 0x000000ffffffffffffffffffffffffff]
- 5. Предположим, что, когда эта цель активна, мы можем генерировать 20 Спецодежда1 сделок, 60 Спецодежда2 сделок и 35 Спецодежда3 транзакций в минуту для каждого пользователя. Может случиться так, что несколько числа пользователей приходят или уходят, так что неизвестно, сколько пользователей будут генерировать эти операции до тех пор, блок не формируются, и мы можем подсчитать реальное число, который был создан.
- 6. Каждый из типов транзакций имеет собственное целевое значение, которое получает первоначально установлен в базовой цели
- 7. Теперь мы можем ограничить скорость трех типов транзакций путем корректировки их целевого значения.
- 8. При умножении целевого значения на 0,5, мы также умножить на скорости, с которой сделки приходят в на 0,5.
- 9. Желаемая цель состоит в том, чтобы иметь 10 транзакций в минуту на каждый тип сделки, независимо от того, насколько быстро они могут быть получены. Таким образом, в конечном счете, три типа транзакций будет в конечном итоге с совершенно разными целевыми значениями
- 10. Независимо от того, каким образом формируются многие операции, жесткий предел не 20 на каждый блок для каждого типа сделки. Таким образом, для 3-х типов транзакций мы можем иметь только 60 транзакций в блок. Все за что получает отбрасываются.
О чем это все?
Основное объяснение: У нас есть три типа транзакций, которые генерируются самими пользователями. Сложность для создания такого типа транзакции коррелирует с целевым значением этого типа транзакции. Если слишком много пользователей генерировать слишком много одного из типов транзакций, мы можем регулировать скорость генерации за счет снижения целевого значения.
Что мы не знаем?
Мы не знаем, число пользователей, которые были порождающих эти операции.
Мы не знаем, количество сделок, которые будут созданы в будущем (когда мы нацелить на блоке X, мы можем только использовать информацию из блоков X-1 ... 0)
Текущий механизм?
Его в методе retarget_retarget_work (), начиная с файла питона в строке 65.
Мы в основном идти назад столько блоков, сколько необходимо, чтобы охватить временной интервал 120 секунд. Затем мы рассмотрим, как было найдено много сделок определенного типа сделки, мы также подсчитать общее количество сделок (всех видов в целом).
Тогда мы посмотрим, сколько мы уже видели, и сколько мы должны были видеть. Согласно другим мы масштабировать цель в пределах от -10% до + 10% (2 других побочных случаев в коде).
Коэффициент масштабирования может быть понят как то
Значения < 1 дроссельной заслонки вниз поколения
Значения > 1 увеличить скорость генерации
Unprecise !!!
Здесь, критические части, когда) мы находимся в самом начале (нет плавного пуска) и б), когда количество "шахтеры" изменения. Помните, каждые 10 блоков один новый Проходчик пинки в в этом примере.
Это unprecise, поскольку эта схема имеет тенденцию к колебаниям по какой-то причине. Пожалуйста, смотрите следующие участки, которые по оси х показывают высоту блока и на оси Y показывают скорость POW за 60-е годы. Это нормализованное значение: Таким образом, если блок занимает 2 минут, и он содержит 10 сделок типа работу1, то скорость ПР / 60 будет 20.
Красная линия изображает идеальное значение.
Сюжет состоит из двух суб участков. Выше для всех видов операций в целом, так и ниже только для типа сделки работу1. В этом случае мы также показать "фактор" значение, которое масштабирует цель.
Здесь вы видите сюжет с нашим окном 120 с (как описано выше)
Если увеличить окно в 1000s, мы имеем большие колебания:
И только с 60-х годов, это лучше, но все еще не очень хорошо. 60 секунд становятся слишком грязными, когда внезапные изменения возникают в структуре шахтера:
Вы думаете, что это гладкое? Тогда пусть не только один новый "шахтер" присоединиться каждые 10 блоков, но 15. Посмотрите на искажения в начале
Другой очень очень плохой пример. Это займет слишком много времени "абсорбировать" внезапные изменения !!!!
Видите ли, все это отстой! Мы хотим быть как можно ближе к красной линии! Я думаю, что нам нужен совершенно другой алгоритм перенацеливания.
PS: Если вы хотите, чтобы ось Y не нормированные на 60 секунд, но показывают фактическое количество транзакций в блоке, использование stretch_number_pows = False в сценарии питона. Затем красная линия идеально будет растягиваться.
Кроме того, вы можете играть с этими переменными
Код:
stretch_number_pows = True
do_not_randomize_block_times_but_do_always_60_sec = True
new_miner_every_xth_second = 10
how_many_miners_come = 5
jitter_size = 1
do_not_randomize_block_times_but_do_always_60_sec = True
new_miner_every_xth_second = 10
how_many_miners_come = 5
jitter_size = 1
Чтобы изменить количество шахтеров войти как часто и сколько "шум" находится в поколения (джиттера)
Питон скрипт
Используйте python2 и установить отборочные:
Код:
Sudo APT-получить установку питона-тк
Судо пункт установить Numpy Matplotlib
Судо пункт установить Numpy Matplotlib
И вот это:
Код:
импорт дата и время
импорт случайных
импорт NumPy в нп
импорт matplotlib.pyplot в PLT
# Sudo APT-получить установку питона-тк
# PIP2 установить Numpy Matplotlib
Защиту create_block (метка времени, num_pow):
вернуться { 'time_stamp': временную метку, 'num_pow': num_pow, 'first_work_factor': 0}
Защиту create_work (IDX, фактор, цель):
возвращать { 'идентификатор': IDX, 'base_executions_per_second': фактор, 'цель': целевой}
Защиту addSecs (тм, сек):
fulldate = TM + datetime.timedelta (секунды = сек)
возвращение fulldate
Защиту randomDuration ():
если do_not_randomize_block_times_but_do_always_60_sec:
вернуться 60
еще:
возвращение INT (random.uniform (25, 120))
CURRENT_TIME = datetime.datetime.now ()
# Эксперимент с количеством рабочих пакетов
works_to_create = 3
generate_blocks = 100
current_height = 0
blockchain = []
work_packages = []
base_target = 0x000000ffffffffffffffffffffffffff
poisson_distribution = np.random.poisson (5, generate_blocks)
stretch_number_pows = True
do_not_randomize_block_times_but_do_always_60_sec = False
new_miner_every_xth_second = 10
how_many_miners_come = 5
jitter_size = 1
maximum_movement = 0,5 # 1 = 100%
Защиту currently_active_miners (current_height):
# Получить текущее активное количество шахтеров в отношении blockchain высоты,
# Но количество шахтеров увеличивается на 1 каждые 10 блоков
увеличивается = INT (current_height / new_miner_every_xth_second) * how_many_miners_come
вернуться 1 + увеличивается
# На данный момент, отпуск Пуассон распределяется подсчитывать переменный шахтер, и принимать только один шахтер
RET = poisson_distribution [current_height]
если в отставке > 0:
возвращение в отставке
еще:
вернуться 1
Защиту miner_pows_based_on_target (работа, высота, дуры):
current_target = работа ["цель"]
Коэффициент = (current_target / base_target) * 1,0 * Dur / 60.0
actual_pow_mined = работа ["base_executions_per_second"]
# Случайный джиттер
actual_pow_mined = ABS ((actual_pow_mined - jitter_size) + random.uniform (0,2 * jitter_size)) * currently_active_miners (высота)
actual_pow_mined = actual_pow_mined * фактор
Ограничение скорости # 20 военнопленных в блок
если actual_pow_mined>20:
actual_pow_mined = 20
если actual_pow_mined < 0:
actual_pow_mined = 0
если actual_pow_mined == 0:
Распечатать "заминированный", Actual_pow_mined работа ["base_executions_per_second"] * Фактор, currently_active_miners (высота)
вернуться actual_pow_mined
Защиту retarget_work (блок, х):
targetI = х ["цель"]
pastMass = 0
account_for_block_max = 10
seconds_passed = 0
totalMass = 0
Счетчик = 0
current_block = блок
current_block_timestamp = blockchain [current_block] ["time_stamp"]
в то время как True:
счетчик = счетчик + 1
pastMass + = blockchain [current_block] ["num_pow"][Икс["Я бы"]]
для у в blockchain [current_block] ["num_pow"]:
totalMass + = blockchain [current_block] ["num_pow"] [У]
seconds_passed = (current_block_timestamp - blockchain [current_block-1] ["time_stamp"]). секунд
current_block = current_block - 1
#Распечатать "трубчатый проход", seconds_passed
если current_block < 1 или seconds_passed >= 60:
ломать
если seconds_passed < 1:
seconds_passed = 1
pows_per_360_seconds = ((pastMass * 360,0) / seconds_passed)
если pows_per_360_seconds>0 и pows_per_360_seconds<1:
pows_per_360_seconds = 1
коэффициент = 1
если pows_per_360_seconds > 0:
фактор = 10 * 6,0 / pows_per_360_seconds
если коэффициент<1-maximum_movement:
коэффициент = 1-maximum_movement
если коэффициент>1 + maximum_movement:
коэффициент = 1 + maximum_movement
Элиф pows_per_360_seconds == 0 и totalMass == 0:
коэффициент = 1,05
еще:
коэффициент = 1
#Распечатать "секунд", Seconds_passed,"блоки", Счетчик,"фактические военнопленные", PastMass,"в 360s:", Pows_per_360_seconds,"разыскивается:", 60,"фактор"фактор
targetI = targetI * фактор
если targetI>base_target:
targetI = base_target
если х ["Я бы"] == 0:
blockchain [блок] ["first_work_factor"] = Коэффициент
Икс["цель"] = TargetI
Защиту retarget_works (блок):
для й в work_packages:
retarget_work (блок, х)
# Здесь мы создаем до трех различных объектов работы
если works_to_create>= 1:
work_packages.append (create_work (0, 20, base_target))
если works_to_create>= 2:
work_packages.append (create_work (1, 60, base_target))
если works_to_create>= 3:
work_packages.append (create_work (2, 35, base_target))
в то время как current_height < generate_blocks:
Dur = randomDuration ()
CURRENT_TIME = addSecs (CURRENT_TIME, Dur) # случайное время генерации блока
block_pows = {}
для й в work_packages:
num_pow = miner_pows_based_on_target (х, current_height, дур) # шахта некоторые военнопленные в зависимости от текущей сложности
block_pows [х ["Я бы"]] = Num_pow
blockchain.append (create_block (CURRENT_TIME, block_pows))
retarget_works (current_height) # Этот метод является перепланирование "критическая часть здесь"
current_height = current_height + 1
Значения = []
target_factors = []
идеальные = []
для IDX в диапазоне (LEN (blockchain)):
если IDX == 0:
Продолжать
х = blockchain [IDX]
x_minus_one = blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
если stretch_number_pows == Ложные:
ideal.append (works_to_create * 10 * strech_normalizer)
еще:
ideal.append (works_to_create * 10)
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (generate_blocks) [1:]
у = значения
#fig = plt.figure ()
Ах0 = plt.subplot (211)
если stretch_number_pows:
ax0.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax0.set_ylabel ( «военнопленные в блоке», цвет = «б»)
ax0.set_xlabel ( 'Блок Высота')
ax0.plot (х, у, '- о', х, идеал, 'r--')
Значения = []
идеальные = []
target_factors = []
для IDX в диапазоне (LEN (blockchain)):
если IDX == 0:
Продолжать
х = blockchain [IDX]
x_minus_one = blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
если stretch_number_pows == Ложные:
ideal.append (10 * strech_normalizer)
еще:
ideal.append (10)
sum_x = 0
sum_x + = х ["num_pow"] [0]
#Распечатать "SUMX", sum_x
если stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (generate_blocks) [1:]
у = значения
plt.title ( «Все Работы: Всего военнопленные»)
ax1 = plt.subplot (212)
ax1.plot (х, у, '- о', х, идеал, 'r--')
ax1.set_xlabel ( 'Блок Высота')
# Сделайте метку у оси и отметьте метки совпадают цвет линии.
если stretch_number_pows:
ax1.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax1.set_ylabel ( «военнопленные в блоке», цвет = «б»)
для ТЛ в ax1.get_yticklabels ():
tl.set_color ( 'б')
ах2 = ax1.twinx ()
ax2.set_ylim (1-maximum_movement-0,05, 1 + maximum_movement + 0,05)
ax2.bar (х, [х ["first_work_factor"] Для й в blockchain] [1:], 0,45, цвета = '# deb0b0', альфа = 0,2)
ax2.set_ylabel ( 'Ретаргетинг фактор', цвет = 'R')
для ТЛ в ax2.get_yticklabels ():
tl.set_color ( 'г')
plt.title ( 'Первые работы: военнопленные + Ретаргетинг Factor')
plt.show ()
импорт случайных
импорт NumPy в нп
импорт matplotlib.pyplot в PLT
# Sudo APT-получить установку питона-тк
# PIP2 установить Numpy Matplotlib
Защиту create_block (метка времени, num_pow):
вернуться { 'time_stamp': временную метку, 'num_pow': num_pow, 'first_work_factor': 0}
Защиту create_work (IDX, фактор, цель):
возвращать { 'идентификатор': IDX, 'base_executions_per_second': фактор, 'цель': целевой}
Защиту addSecs (тм, сек):
fulldate = TM + datetime.timedelta (секунды = сек)
возвращение fulldate
Защиту randomDuration ():
если do_not_randomize_block_times_but_do_always_60_sec:
вернуться 60
еще:
возвращение INT (random.uniform (25, 120))
CURRENT_TIME = datetime.datetime.now ()
# Эксперимент с количеством рабочих пакетов
works_to_create = 3
generate_blocks = 100
current_height = 0
blockchain = []
work_packages = []
base_target = 0x000000ffffffffffffffffffffffffff
poisson_distribution = np.random.poisson (5, generate_blocks)
stretch_number_pows = True
do_not_randomize_block_times_but_do_always_60_sec = False
new_miner_every_xth_second = 10
how_many_miners_come = 5
jitter_size = 1
maximum_movement = 0,5 # 1 = 100%
Защиту currently_active_miners (current_height):
# Получить текущее активное количество шахтеров в отношении blockchain высоты,
# Но количество шахтеров увеличивается на 1 каждые 10 блоков
увеличивается = INT (current_height / new_miner_every_xth_second) * how_many_miners_come
вернуться 1 + увеличивается
# На данный момент, отпуск Пуассон распределяется подсчитывать переменный шахтер, и принимать только один шахтер
RET = poisson_distribution [current_height]
если в отставке > 0:
возвращение в отставке
еще:
вернуться 1
Защиту miner_pows_based_on_target (работа, высота, дуры):
current_target = работа ["цель"]
Коэффициент = (current_target / base_target) * 1,0 * Dur / 60.0
actual_pow_mined = работа ["base_executions_per_second"]
# Случайный джиттер
actual_pow_mined = ABS ((actual_pow_mined - jitter_size) + random.uniform (0,2 * jitter_size)) * currently_active_miners (высота)
actual_pow_mined = actual_pow_mined * фактор
Ограничение скорости # 20 военнопленных в блок
если actual_pow_mined>20:
actual_pow_mined = 20
если actual_pow_mined < 0:
actual_pow_mined = 0
если actual_pow_mined == 0:
Распечатать "заминированный", Actual_pow_mined работа ["base_executions_per_second"] * Фактор, currently_active_miners (высота)
вернуться actual_pow_mined
Защиту retarget_work (блок, х):
targetI = х ["цель"]
pastMass = 0
account_for_block_max = 10
seconds_passed = 0
totalMass = 0
Счетчик = 0
current_block = блок
current_block_timestamp = blockchain [current_block] ["time_stamp"]
в то время как True:
счетчик = счетчик + 1
pastMass + = blockchain [current_block] ["num_pow"][Икс["Я бы"]]
для у в blockchain [current_block] ["num_pow"]:
totalMass + = blockchain [current_block] ["num_pow"] [У]
seconds_passed = (current_block_timestamp - blockchain [current_block-1] ["time_stamp"]). секунд
current_block = current_block - 1
#Распечатать "трубчатый проход", seconds_passed
если current_block < 1 или seconds_passed >= 60:
ломать
если seconds_passed < 1:
seconds_passed = 1
pows_per_360_seconds = ((pastMass * 360,0) / seconds_passed)
если pows_per_360_seconds>0 и pows_per_360_seconds<1:
pows_per_360_seconds = 1
коэффициент = 1
если pows_per_360_seconds > 0:
фактор = 10 * 6,0 / pows_per_360_seconds
если коэффициент<1-maximum_movement:
коэффициент = 1-maximum_movement
если коэффициент>1 + maximum_movement:
коэффициент = 1 + maximum_movement
Элиф pows_per_360_seconds == 0 и totalMass == 0:
коэффициент = 1,05
еще:
коэффициент = 1
#Распечатать "секунд", Seconds_passed,"блоки", Счетчик,"фактические военнопленные", PastMass,"в 360s:", Pows_per_360_seconds,"разыскивается:", 60,"фактор"фактор
targetI = targetI * фактор
если targetI>base_target:
targetI = base_target
если х ["Я бы"] == 0:
blockchain [блок] ["first_work_factor"] = Коэффициент
Икс["цель"] = TargetI
Защиту retarget_works (блок):
для й в work_packages:
retarget_work (блок, х)
# Здесь мы создаем до трех различных объектов работы
если works_to_create>= 1:
work_packages.append (create_work (0, 20, base_target))
если works_to_create>= 2:
work_packages.append (create_work (1, 60, base_target))
если works_to_create>= 3:
work_packages.append (create_work (2, 35, base_target))
в то время как current_height < generate_blocks:
Dur = randomDuration ()
CURRENT_TIME = addSecs (CURRENT_TIME, Dur) # случайное время генерации блока
block_pows = {}
для й в work_packages:
num_pow = miner_pows_based_on_target (х, current_height, дур) # шахта некоторые военнопленные в зависимости от текущей сложности
block_pows [х ["Я бы"]] = Num_pow
blockchain.append (create_block (CURRENT_TIME, block_pows))
retarget_works (current_height) # Этот метод является перепланирование "критическая часть здесь"
current_height = current_height + 1
Значения = []
target_factors = []
идеальные = []
для IDX в диапазоне (LEN (blockchain)):
если IDX == 0:
Продолжать
х = blockchain [IDX]
x_minus_one = blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
если stretch_number_pows == Ложные:
ideal.append (works_to_create * 10 * strech_normalizer)
еще:
ideal.append (works_to_create * 10)
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (generate_blocks) [1:]
у = значения
#fig = plt.figure ()
Ах0 = plt.subplot (211)
если stretch_number_pows:
ax0.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax0.set_ylabel ( «военнопленные в блоке», цвет = «б»)
ax0.set_xlabel ( 'Блок Высота')
ax0.plot (х, у, '- о', х, идеал, 'r--')
Значения = []
идеальные = []
target_factors = []
для IDX в диапазоне (LEN (blockchain)):
если IDX == 0:
Продолжать
х = blockchain [IDX]
x_minus_one = blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
если stretch_number_pows == Ложные:
ideal.append (10 * strech_normalizer)
еще:
ideal.append (10)
sum_x = 0
sum_x + = х ["num_pow"] [0]
#Распечатать "SUMX", sum_x
если stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (generate_blocks) [1:]
у = значения
plt.title ( «Все Работы: Всего военнопленные»)
ax1 = plt.subplot (212)
ax1.plot (х, у, '- о', х, идеал, 'r--')
ax1.set_xlabel ( 'Блок Высота')
# Сделайте метку у оси и отметьте метки совпадают цвет линии.
если stretch_number_pows:
ax1.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax1.set_ylabel ( «военнопленные в блоке», цвет = «б»)
для ТЛ в ax1.get_yticklabels ():
tl.set_color ( 'б')
ах2 = ax1.twinx ()
ax2.set_ylim (1-maximum_movement-0,05, 1 + maximum_movement + 0,05)
ax2.bar (х, [х ["first_work_factor"] Для й в blockchain] [1:], 0,45, цвета = '# deb0b0', альфа = 0,2)
ax2.set_ylabel ( 'Ретаргетинг фактор', цвет = 'R')
для ТЛ в ax2.get_yticklabels ():
tl.set_color ( 'г')
plt.title ( 'Первые работы: военнопленные + Ретаргетинг Factor')
plt.show ()
Что будет испытано?
Мы будем тестировать алгоритм с 9 все же, чтобы определить сценарии, включая различные распределения числа шахтеров на временный шаг, с различными длинами blockchain и различными моделями горных работ. Сейчас все три типа транзакций генерируется одновременно, мы можем думать, чтобы проверить, что происходит, если поколение фокусируется только на одном из них, а затем переходит к другому в течение долгого времени. Сценарии будут определены в некоторый более поздний момент времени, произвольно, но будет одинаковым для всех представлений. Тестирование может проводиться в расширенной версии коды, тот, который имитирует различные виды настроек.
РЕДАКТИРОВАТЬ:
Это будет обкатка:
Тестер Код:
tester.py
Здесь, в качестве примера, мой собственный метод Retarget встроен в тестовый класс:
retarget.py
Там будет 9 случайные тестовые случаи, генерируемые с затравкой генератором случайных чисел, который будет затравку с первым блоком после того, как хэш-конкурс закончен.
Средняя ошибка в блоке возвращается после каждого испытания, самые высокие счетчики ошибок.
Алгоритм с наименьшими побед ошибок.
Тестер Код:
tester.py
Код:
от Retarget импорта RetargetTest
нацелить = RetargetTest ()
max_error = 0
retarget.seeder ("BLOCK_HASH_OF_FIRST_BLOCK_AFTER_CONTEST_GOES ЗДЕСЬ")
для г в диапазоне (9):
Распечатать "Выполнение запуска",я
retarget.reset_chain ()
retarget.randomize_params ()
retarget.generate_chain ()
ERR = retarget.get_total_error ()
retarget.plot (я)
Распечатать "Бег",я,"-","Общая погрешность =", заблуждаться
если max_error max_error = ERR
Распечатать "Самая большая ошибка:", max_error
нацелить = RetargetTest ()
max_error = 0
retarget.seeder ("BLOCK_HASH_OF_FIRST_BLOCK_AFTER_CONTEST_GOES ЗДЕСЬ")
для г в диапазоне (9):
Распечатать "Выполнение запуска",я
retarget.reset_chain ()
retarget.randomize_params ()
retarget.generate_chain ()
ERR = retarget.get_total_error ()
retarget.plot (я)
Распечатать "Бег",я,"-","Общая погрешность =", заблуждаться
если max_error
Распечатать "Самая большая ошибка:", max_error
Здесь, в качестве примера, мой собственный метод Retarget встроен в тестовый класс:
retarget.py
Код:
импорт дата и время
импорт случайных
импорт NumPy в нп
импорт matplotlib.pyplot в PLT
# Sudo APT-получить установку питона-тк
# PIP2 установить Numpy Matplotlib
Класс RetargetTest ():
# Эксперимент с количеством рабочих пакетов
Защиту __init __ (Я):
self.current_time = datetime.datetime.now ()
self.works_to_create = 3
self.generate_blocks = 100
self.current_height = 0
self.blockchain = []
self.work_packages = []
self.base_target = 0x000000ffffffffffffffffffffffffff
self.stretch_number_pows = True
self.do_not_randomize_block_times_but_do_always_60_sec = True
self.new_miner_every_xth_second = 10
self.how_many_miners_come_or_go = 70242
self.initial_miners = 50
self.miners_kick_in_at_block = 50
self.miners_drop_at = 0
self.miners_drop_for = 20
self.jitter_size = 0
Защита сеялка (я, мясорубка):
random.seed (мясорубка)
Защиту randomize_params (самостоятельно):
self.generate_blocks = random.randint (80500)
self.new_miner_every_xth_second = random.randint (5,50)
self.how_many_miners_come_or_go = random.randint (0,1000000)
self.initial_miners = random.randint (0,1000000)
self.miners_kick_in_at_block = random.randint (0,40)
self.jitter_size = random.randint (1,7)
self.miners_drop_at = random.randint (self.generate_blocks / 2, self.generate_blocks)
проходить
Защиту create_block (самость, метка времени, num_pow):
вернуться { 'time_stamp': временную метку, 'num_pow': num_pow, 'first_work_factor': 0}
Защиту create_work (самость, IDX, фактор, цель):
возвращать { 'идентификатор': IDX, 'base_executions_per_second': фактор, 'цель': целевой}
Защиту addSecs (самоповреждения, Tm, ИКС):
fulldate = TM + datetime.timedelta (секунды = сек)
возвращение fulldate
Защиту randomDuration (самостоятельно):
если self.do_not_randomize_block_times_but_do_always_60_sec:
вернуться 60
еще:
возвращение INT (random.uniform (25, 120))
Защиту currently_active_miners (самоповреждения, current_height):
если self.current_height вернуться 0
если self.current_height>= Self.miners_drop_at и self.current_height<= Self.miners_drop_at + self.miners_drop_for:
вернуться 0
# Получить текущее активное количество шахтеров в отношении blockchain высоты,
# Но количество шахтеров увеличивается на 1 каждые 10 блоков
увеличивается = INT (self.current_height / self.new_miner_every_xth_second) * self.how_many_miners_come_or_go
вернуться self.initial_miners + увеличивается
Защиту miner_pows_based_on_target (самость, работа, рост, дуры):
current_target = работа ["цель"]
Коэффициент = (current_target / self.base_target) * 1,0 * Dur / 60.0
actual_pow_mined = работа ["base_executions_per_second"]
# Случайный джиттер
actual_pow_mined = ABS ((actual_pow_mined - self.jitter_size) + random.uniform (self.jitter_size, 2 * self.jitter_size)) * self.currently_active_miners (высота)
если actual_pow_mined < 0:
actual_pow_mined = 0
actual_pow_mined = actual_pow_mined * фактор
Ограничение скорости # 20 военнопленных в блок
если actual_pow_mined > 20:
actual_pow_mined = 20
если actual_pow_mined < 0:
actual_pow_mined = 0
вернуться actual_pow_mined
Защита Кимото (я, х):
вернуться 1 + (0,7084 * Pow (((х) / (144)), -1,228));
Защиту retarget_work (я, блок, х):
targetI = х ["цель"]
pastMass = 0
account_for_block_max = 10
seconds_passed = 0
totalMass = 0
Счетчик = 0
current_block = блок
current_block_timestamp = self.blockchain [current_block] ["time_stamp"]
massive_retarget = False
deviation_too_high = False
last_two_deviation = 0.0
в то время как True:
счетчик = счетчик + 1
curmass = self.blockchain [current_block] ["num_pow"][Икс["Я бы"]]
pastMass + = curmass
# Если был достигнут максимальный блок-ТХ-предел 20, сделать массивную переориентацию
если счетчик == 1 и pastMass == 20:
massive_retarget = True
ломать
# Кроме того, если отклонение последних двух блоков было слишком высоко, сделать некоторые "магия"
если счетчик == 1 и curmass > 0:
last_two_deviation = curmass / 10
если last_two_deviation > 1,25 или last_two_deviation < -0,75: #deviation более чем 25% плохо
Распечатать "Последние два отклонения", Last_two_deviation,"в блоке", блок
deviation_too_high = True
ломать
для у в self.blockchain [current_block] ["num_pow"]:
totalMass + = self.blockchain [current_block] ["num_pow"] [У]
seconds_passed = (current_block_timestamp - self.blockchain [current_block-1] ["time_stamp"]). секунд
current_block = current_block - 1
если current_block < 1 или seconds_passed >= 60: # нацелить каждые 120 секунд ~ 1 блок в среднем
ломать
коэффициент = 1
если massive_retarget == True:
коэффициент = 0,4 # ниже, только 40%
Элиф deviation_too_high == True:
коэффициент = 1 / last_two_deviation
еще:
если seconds_passed < 1:
seconds_passed = 1
pows_per_360_seconds = ((pastMass * 360,0) / seconds_passed)
если pows_per_360_seconds>0 и pows_per_360_seconds<1:
pows_per_360_seconds = 1
коэффициент = 1
если pows_per_360_seconds > 0:
фактор = 10 * 6,0 / pows_per_360_seconds
если коэффициент<0,9:
коэффициент = 0,9
если коэффициент>1,1:
коэффициент = 1,1
Элиф pows_per_360_seconds == 0 и totalMass == 0:
коэффициент = 1,05
еще:
коэффициент = 1
#Распечатать "секунд", Seconds_passed,"блоки", Счетчик,"фактические военнопленные", PastMass,"в 360s:", Pows_per_360_seconds,"разыскивается:", 60,"фактор"фактор
targetI = targetI * фактор
если targetI>self.base_target:
targetI = self.base_target
если х ["Я бы"] == 0:
self.blockchain [блок] ["first_work_factor"] = Коэффициент
Икс["цель"] = TargetI
Защиту retarget_works (самоповреждения, блок):
для й в self.work_packages:
self.retarget_work (блок, х)
Защиту reset_chain (самостоятельно):
self.blockchain = []
self.work_packages = []
self.current_height = 0
self.current_time = datetime.datetime.now ()
# Здесь мы создаем до трех различных объектов работы
если self.works_to_create>= 1:
self.work_packages.append (self.create_work (0, 20, self.base_target))
если self.works_to_create>= 2:
self.work_packages.append (self.create_work (1, 60, self.base_target))
если self.works_to_create>= 3:
self.work_packages.append (self.create_work (2, 35, self.base_target))
Защиту generate_chain (самостоятельно):
в то время как self.current_height < self.generate_blocks:
если self.current_height% 1000 == 0:
Распечатать " -> блок генерируется", self.current_height
Dur = self.randomDuration ()
self.current_time = self.addSecs (self.current_time, Dur) # случайное время генерации блока
block_pows = {}
для й в self.work_packages:
num_pow = self.miner_pows_based_on_target (х, self.current_height, дур) # шахта некоторые военнопленные в зависимости от текущей сложности
block_pows [х ["Я бы"]] = Num_pow
self.blockchain.append (self.create_block (self.current_time, block_pows))
self.retarget_works (self.current_height) # Этот метод является перепланирование "критическая часть здесь"
self.current_height = self.current_height + 1
Защиту get_total_error (самостоятельно):
Значения = []
идеальные = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (self.works_to_create * 10 * strech_normalizer)
еще:
ideal.append (self.works_to_create * 10)
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
значения #print
#print идеал
total_error = 0
для й в диапазоне (LEN (значения)):
Soll = идеал [х]
IST = значения [х]
total_error + = абс (Soll-IST)
возвращать total_error / LEN (значения)
Защита сюжет (я, бег):
Значения = []
target_factors = []
идеальные = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (self.works_to_create * 10 * strech_normalizer)
еще:
ideal.append (self.works_to_create * 10)
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (self.generate_blocks) [1:]
у = значения
#Распечатать "LEN: х", Длина (х),"Y", Длина (у),"идеальный", Len (идеально)
#fig = plt.figure ()
Ах0 = plt.subplot (211)
если self.stretch_number_pows:
ax0.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax0.set_ylabel ( «военнопленные в блоке», цвет = «б»)
ax0.set_xlabel ( 'Блок Высота')
ax0.plot (х, у, '- о', х, идеал, 'r--')
Значения = []
идеальные = []
target_factors = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
sum_x + = х ["num_pow"] [0]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (10 * strech_normalizer)
еще:
ideal.append (10)
#Распечатать "SUMX", sum_x
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (self.generate_blocks) [1:]
у = значения
plt.title ( «Все Работы: Всего военнопленные»)
#Распечатать "LEN: х", Длина (х),"Y", Длина (у),"идеальный", Len (идеально)
ax1 = plt.subplot (212)
ax1.plot (х, у, '- о', х, идеал, 'r--')
ax1.set_xlabel ( 'Блок Высота')
# Сделайте метку у оси и отметьте метки совпадают цвет линии.
если self.stretch_number_pows:
ax1.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax1.set_ylabel ( «военнопленные в блоке», цвет = «б»)
для ТЛ в ax1.get_yticklabels ():
tl.set_color ( 'б')
ах2 = ax1.twinx ()
ax2.set_ylim (0.4, 1.6)
ax2.bar (х, [х ["first_work_factor"] Для й в self.blockchain] [1:], 0,45, цвета = '# deb0b0', альфа = 0,2)
ax2.set_ylabel ( 'Ретаргетинг фактор', цвет = 'R')
для ТЛ в ax2.get_yticklabels ():
tl.set_color ( 'г')
plt.title ( 'Первые работы: военнопленные + Ретаргетинг Factor')
plt.savefig ( 'render-' ул (бег +) + '.png')
plt.close ()
импорт случайных
импорт NumPy в нп
импорт matplotlib.pyplot в PLT
# Sudo APT-получить установку питона-тк
# PIP2 установить Numpy Matplotlib
Класс RetargetTest ():
# Эксперимент с количеством рабочих пакетов
Защиту __init __ (Я):
self.current_time = datetime.datetime.now ()
self.works_to_create = 3
self.generate_blocks = 100
self.current_height = 0
self.blockchain = []
self.work_packages = []
self.base_target = 0x000000ffffffffffffffffffffffffff
self.stretch_number_pows = True
self.do_not_randomize_block_times_but_do_always_60_sec = True
self.new_miner_every_xth_second = 10
self.how_many_miners_come_or_go = 70242
self.initial_miners = 50
self.miners_kick_in_at_block = 50
self.miners_drop_at = 0
self.miners_drop_for = 20
self.jitter_size = 0
Защита сеялка (я, мясорубка):
random.seed (мясорубка)
Защиту randomize_params (самостоятельно):
self.generate_blocks = random.randint (80500)
self.new_miner_every_xth_second = random.randint (5,50)
self.how_many_miners_come_or_go = random.randint (0,1000000)
self.initial_miners = random.randint (0,1000000)
self.miners_kick_in_at_block = random.randint (0,40)
self.jitter_size = random.randint (1,7)
self.miners_drop_at = random.randint (self.generate_blocks / 2, self.generate_blocks)
проходить
Защиту create_block (самость, метка времени, num_pow):
вернуться { 'time_stamp': временную метку, 'num_pow': num_pow, 'first_work_factor': 0}
Защиту create_work (самость, IDX, фактор, цель):
возвращать { 'идентификатор': IDX, 'base_executions_per_second': фактор, 'цель': целевой}
Защиту addSecs (самоповреждения, Tm, ИКС):
fulldate = TM + datetime.timedelta (секунды = сек)
возвращение fulldate
Защиту randomDuration (самостоятельно):
если self.do_not_randomize_block_times_but_do_always_60_sec:
вернуться 60
еще:
возвращение INT (random.uniform (25, 120))
Защиту currently_active_miners (самоповреждения, current_height):
если self.current_height
если self.current_height>= Self.miners_drop_at и self.current_height<= Self.miners_drop_at + self.miners_drop_for:
вернуться 0
# Получить текущее активное количество шахтеров в отношении blockchain высоты,
# Но количество шахтеров увеличивается на 1 каждые 10 блоков
увеличивается = INT (self.current_height / self.new_miner_every_xth_second) * self.how_many_miners_come_or_go
вернуться self.initial_miners + увеличивается
Защиту miner_pows_based_on_target (самость, работа, рост, дуры):
current_target = работа ["цель"]
Коэффициент = (current_target / self.base_target) * 1,0 * Dur / 60.0
actual_pow_mined = работа ["base_executions_per_second"]
# Случайный джиттер
actual_pow_mined = ABS ((actual_pow_mined - self.jitter_size) + random.uniform (self.jitter_size, 2 * self.jitter_size)) * self.currently_active_miners (высота)
если actual_pow_mined < 0:
actual_pow_mined = 0
actual_pow_mined = actual_pow_mined * фактор
Ограничение скорости # 20 военнопленных в блок
если actual_pow_mined > 20:
actual_pow_mined = 20
если actual_pow_mined < 0:
actual_pow_mined = 0
вернуться actual_pow_mined
Защита Кимото (я, х):
вернуться 1 + (0,7084 * Pow (((х) / (144)), -1,228));
Защиту retarget_work (я, блок, х):
targetI = х ["цель"]
pastMass = 0
account_for_block_max = 10
seconds_passed = 0
totalMass = 0
Счетчик = 0
current_block = блок
current_block_timestamp = self.blockchain [current_block] ["time_stamp"]
massive_retarget = False
deviation_too_high = False
last_two_deviation = 0.0
в то время как True:
счетчик = счетчик + 1
curmass = self.blockchain [current_block] ["num_pow"][Икс["Я бы"]]
pastMass + = curmass
# Если был достигнут максимальный блок-ТХ-предел 20, сделать массивную переориентацию
если счетчик == 1 и pastMass == 20:
massive_retarget = True
ломать
# Кроме того, если отклонение последних двух блоков было слишком высоко, сделать некоторые "магия"
если счетчик == 1 и curmass > 0:
last_two_deviation = curmass / 10
если last_two_deviation > 1,25 или last_two_deviation < -0,75: #deviation более чем 25% плохо
Распечатать "Последние два отклонения", Last_two_deviation,"в блоке", блок
deviation_too_high = True
ломать
для у в self.blockchain [current_block] ["num_pow"]:
totalMass + = self.blockchain [current_block] ["num_pow"] [У]
seconds_passed = (current_block_timestamp - self.blockchain [current_block-1] ["time_stamp"]). секунд
current_block = current_block - 1
если current_block < 1 или seconds_passed >= 60: # нацелить каждые 120 секунд ~ 1 блок в среднем
ломать
коэффициент = 1
если massive_retarget == True:
коэффициент = 0,4 # ниже, только 40%
Элиф deviation_too_high == True:
коэффициент = 1 / last_two_deviation
еще:
если seconds_passed < 1:
seconds_passed = 1
pows_per_360_seconds = ((pastMass * 360,0) / seconds_passed)
если pows_per_360_seconds>0 и pows_per_360_seconds<1:
pows_per_360_seconds = 1
коэффициент = 1
если pows_per_360_seconds > 0:
фактор = 10 * 6,0 / pows_per_360_seconds
если коэффициент<0,9:
коэффициент = 0,9
если коэффициент>1,1:
коэффициент = 1,1
Элиф pows_per_360_seconds == 0 и totalMass == 0:
коэффициент = 1,05
еще:
коэффициент = 1
#Распечатать "секунд", Seconds_passed,"блоки", Счетчик,"фактические военнопленные", PastMass,"в 360s:", Pows_per_360_seconds,"разыскивается:", 60,"фактор"фактор
targetI = targetI * фактор
если targetI>self.base_target:
targetI = self.base_target
если х ["Я бы"] == 0:
self.blockchain [блок] ["first_work_factor"] = Коэффициент
Икс["цель"] = TargetI
Защиту retarget_works (самоповреждения, блок):
для й в self.work_packages:
self.retarget_work (блок, х)
Защиту reset_chain (самостоятельно):
self.blockchain = []
self.work_packages = []
self.current_height = 0
self.current_time = datetime.datetime.now ()
# Здесь мы создаем до трех различных объектов работы
если self.works_to_create>= 1:
self.work_packages.append (self.create_work (0, 20, self.base_target))
если self.works_to_create>= 2:
self.work_packages.append (self.create_work (1, 60, self.base_target))
если self.works_to_create>= 3:
self.work_packages.append (self.create_work (2, 35, self.base_target))
Защиту generate_chain (самостоятельно):
в то время как self.current_height < self.generate_blocks:
если self.current_height% 1000 == 0:
Распечатать " -> блок генерируется", self.current_height
Dur = self.randomDuration ()
self.current_time = self.addSecs (self.current_time, Dur) # случайное время генерации блока
block_pows = {}
для й в self.work_packages:
num_pow = self.miner_pows_based_on_target (х, self.current_height, дур) # шахта некоторые военнопленные в зависимости от текущей сложности
block_pows [х ["Я бы"]] = Num_pow
self.blockchain.append (self.create_block (self.current_time, block_pows))
self.retarget_works (self.current_height) # Этот метод является перепланирование "критическая часть здесь"
self.current_height = self.current_height + 1
Защиту get_total_error (самостоятельно):
Значения = []
идеальные = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (self.works_to_create * 10 * strech_normalizer)
еще:
ideal.append (self.works_to_create * 10)
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
значения #print
#print идеал
total_error = 0
для й в диапазоне (LEN (значения)):
Soll = идеал [х]
IST = значения [х]
total_error + = абс (Soll-IST)
возвращать total_error / LEN (значения)
Защита сюжет (я, бег):
Значения = []
target_factors = []
идеальные = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
для у в х ["num_pow"]:
sum_x + = х ["num_pow"] [У]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (self.works_to_create * 10 * strech_normalizer)
еще:
ideal.append (self.works_to_create * 10)
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (self.generate_blocks) [1:]
у = значения
#Распечатать "LEN: х", Длина (х),"Y", Длина (у),"идеальный", Len (идеально)
#fig = plt.figure ()
Ах0 = plt.subplot (211)
если self.stretch_number_pows:
ax0.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax0.set_ylabel ( «военнопленные в блоке», цвет = «б»)
ax0.set_xlabel ( 'Блок Высота')
ax0.plot (х, у, '- о', х, идеал, 'r--')
Значения = []
идеальные = []
target_factors = []
для IDX в диапазоне (LEN (self.blockchain)):
если IDX == 0:
Продолжать
х = self.blockchain [IDX]
x_minus_one = self.blockchain [IDX-1]
time_passed = (х ["time_stamp"] - x_minus_one ["time_stamp"]). секунд
strech_normalizer = time_passed / 60.0
sum_x = 0
sum_x + = х ["num_pow"] [0]
если sum_x == 0:
ideal.append (0)
еще:
если self.stretch_number_pows == Ложные:
ideal.append (10 * strech_normalizer)
еще:
ideal.append (10)
#Распечатать "SUMX", sum_x
если self.stretch_number_pows == Ложные:
values.append (sum_x)
еще:
values.append (sum_x / strech_normalizer)
х = диапазон (self.generate_blocks) [1:]
у = значения
plt.title ( «Все Работы: Всего военнопленные»)
#Распечатать "LEN: х", Длина (х),"Y", Длина (у),"идеальный", Len (идеально)
ax1 = plt.subplot (212)
ax1.plot (х, у, '- о', х, идеал, 'r--')
ax1.set_xlabel ( 'Блок Высота')
# Сделайте метку у оси и отметьте метки совпадают цвет линии.
если self.stretch_number_pows:
ax1.set_ylabel ( 'Скорость Военнопленный в 60-х', цвет = 'B')
еще:
ax1.set_ylabel ( «военнопленные в блоке», цвет = «б»)
для ТЛ в ax1.get_yticklabels ():
tl.set_color ( 'б')
ах2 = ax1.twinx ()
ax2.set_ylim (0.4, 1.6)
ax2.bar (х, [х ["first_work_factor"] Для й в self.blockchain] [1:], 0,45, цвета = '# deb0b0', альфа = 0,2)
ax2.set_ylabel ( 'Ретаргетинг фактор', цвет = 'R')
для ТЛ в ax2.get_yticklabels ():
tl.set_color ( 'г')
plt.title ( 'Первые работы: военнопленные + Ретаргетинг Factor')
plt.savefig ( 'render-' ул (бег +) + '.png')
plt.close ()
Там будет 9 случайные тестовые случаи, генерируемые с затравкой генератором случайных чисел, который будет затравку с первым блоком после того, как хэш-конкурс закончен.
Средняя ошибка в блоке возвращается после каждого испытания, самые высокие счетчики ошибок.
Алгоритм с наименьшими побед ошибок.