Skip to main content

trosna-gisteresis

Гистерезис с выдержкой времени и периодом охлаждения — правило принятия решения о перераспределении ресурсов (например, оперативной памяти между виртуальными машинами) по индексу неравномерности. Подавляет дребезг решений вблизи порога, не реагирует на короткоживущие всплески и не повторяет бесполезные перераспределения, если дисбаланс не устраняется.

Постановка

Пусть I_t — индекс неравномерности в точке мониторинга t (размах, коэффициент вариации, индекс Джини долей свободной памяти; для индекса Джейна берут 1 − J), Δt_t — интервал между точками мониторинга. Параметры: верхний и нижний пороги θ⁺ > θ⁻, выдержка T_d, период охлаждения T_c. Тогда

d_t = (d_{t−1} + Δt_t) · [I_t > θ⁺]                         (время непрерывного превышения θ⁺)
g_t = max{g_{t−1}, [I_t < θ⁻]}                               (флаг готовности)
δ_t = 1  ⇔  I_t > θ⁺ ∧ d_t ≥ T_d ∧ g_t = 1 ∧ t − τ ≥ T_c     (решение)

где [·] равно 1 при истинном условии и 0 иначе, τ — момент последнего срабатывания. После срабатывания τ = t, g_t = 0, d_t = 0: повторное решение возможно только после снижения индекса ниже θ⁻ и не раньше, чем через T_c.

  • Выдержка отсекает кратковременные выбросы: решение принимается, только если дисбаланс держится не меньше T_d.
  • Два порога не дают решению «дребезжать», пока индекс колеблется около одного порога.
  • Флаг готовности не даёт повторять перераспределение, если ограничения не позволяют устранить дисбаланс (индекс остаётся выше θ⁺).
  • Период охлаждения ограничивает частоту перераспределений сверху.

Необязательное расширение rearm_after = T_r взводит правило и по истечении времени T_r после срабатывания:

g_t = max{g_{t−1}, [I_t < θ⁻], [t − τ ≥ T_r]}

Без него правило блокируется, если перераспределение не опустило индекс ниже θ⁻ (например, решение было принято во время кратковременного выброса и после его окончания распределение памяти оказалось перекошенным).

Время задаётся в секундах (или любых единицах, одинаковых для t, T_d, T_c), поэтому правило корректно работает при переменном интервале мониторинга. Сложность — O(1) на точку.

Использование

import numpy as np
from trosna_gisteresis import Hysteresis, hysteresis

# Ряд целиком: индекс и отметки времени (здесь — мониторинг раз в 5 с).
t = np.arange(0.0, 600.0, 5.0)
index = np.where((t >= 100) & (t < 300), 0.5, 0.1)
trace = hysteresis(index, t, upper=0.35, lower=0.25, dwell=30.0, cooldown=120.0)
# Выдержка отсчитывается от последней точки ниже θ⁺ (t = 95), поэтому решение — в t = 125.
print(trace.fire_times)  # [125.]

# Поток: по одной точке мониторинга.
rule = Hysteresis(upper=0.35, lower=0.25, dwell=30.0, cooldown=120.0)
for t_i, index_i in [(0, 0.5), (10, 0.5), (20, 0.5), (30, 0.5)]:
    step = rule.step(index_i, t_i)
    if step.fired:
        print(f"перераспределить в t = {step.t}")  # перераспределить в t = 30.0

# Состояние можно сохранить и продолжить после перезапуска управляющей системы.
saved = rule.state
rule = Hysteresis(rule.params, state=saved)

hysteresis возвращает Trace с массивами fired (δ_t), dwell (d_t), armed (g_t), since_fired (t − τ) — значения, по которым проверялось условие решения, — и итоговым состоянием state. Без t точки считаются идущими с шагом 1.

Параметры

Параметр Обозначение Смысл
upper θ⁺ порог значимого дисбаланса
lower θ⁻ порог, ниже которого правило снова взводится, θ⁻ < θ⁺
dwell T_d выдержка, в единицах времени
cooldown T_c период охлаждения, в единицах времени
dwell_from "interval" (по умолчанию, как в формуле) — первая точка выше θ⁺ засчитывает весь интервал от предыдущей; "sample" — отсчёт от первой точки выше θ⁺
missing пропуск (NaN): "reset" (по умолчанию) — выдержка обнуляется; "hold" — продолжает идти
armed g_0 начальное значение флага готовности, по умолчанию True
rearm_after T_r взведение по времени после срабатывания; None (по умолчанию) — только по θ⁻

Подробное обоснование доопределений, которых нет в исходной формулировке (начальные условия, отсчёт выдержки, пропуски, T_d = 0, округление времени), — в docs/design.md.

Разработка

uv sync                      # окружение
uv run pytest                # тесты (детерминированные, ~1 мин)
uv run ruff check . && uv run ruff format --check .
uv run python examples/demo.py

Тесты сравнивают реализацию с буквальной записью формул в точной арифметике на случайных рядах (hypothesis с фиксированным порядком генерации), проверяют инварианты правила (разнесение срабатываний не меньше T_c, обязательное снижение ниже θ⁻ между срабатываниями, непрерывность превышения на протяжении T_d, инвариантность к сдвигу и масштабу времени), эквивалентность потоковой и пакетной обработки и сценарии с дребезгом, короткоживущими процессами и переменным интервалом мониторинга.

Поддерживаются Python 3.11–3.14.

Metadata

Release files for trosna-gisteresis 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trosna-gisteresis 0.1.0
File Size Uploaded
trosna_gisteresis-0.1.0.tar.gz 8.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trosna-gisteresis 0.1.0
File Interpreter ABI Platform
trosna_gisteresis-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.6 kB

Release files / trosna_gisteresis-0.1.0.tar.gz

Download URL trosna_gisteresis-0.1.0.tar.gz
Size 8.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f28b14c0243c54eb7ad091b0d23badae74049feabec9ae48bba5c0c914107298
BLAKE2b-256 checksum
How to use checksums
048842b32d298bf3f06ad3e323e93093b056a5899a8204c02e885d285897e1ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / trosna_gisteresis-0.1.0-py3-none-any.whl

Download URL trosna_gisteresis-0.1.0-py3-none-any.whl
Size 10.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3ea7bdcf2274349374acf2f34c386205973de70c5d25e35e873d2fef1b158c0
BLAKE2b-256 checksum
How to use checksums
1f70f98c1a8b906788162996459bc8c742c7bfd5439cb56e6a4eb549d18400ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page