import numpy as np import matplotlib.pyplot as plt import streamlit as st # === Параметры модели === SEQ_LEN = 100 # длина последовательности HISTORY_LEN = 200 # сколько шагов хранить в статистике JUMP = 10 # максимальный шаг изменения угла ENTROPY_BINS = 36 # шаг 10 градусов # === Инициализация состояния === if "seq" not in st.session_state: st.session_state.seq = np.random.randint(-180, 180, size=SEQ_LEN) st.session_state.history = [] st.session_state.bist_counts = [] st.session_state.entropy = [] st.session_state.autocorr = [] st.session_state.step = 0 # === Функции анализа === def find_local_min_runs(profile, threshold=10): """Находит устойчивые участки ("машины"), где значения углов почти не меняются.""" runs = [] start = 0 for i in range(1, len(profile)): if abs(profile[i] - profile[i - 1]) > threshold: if i - start > 2: runs.append((start, i - 1)) start = i if len(profile) - start > 2: runs.append((start, len(profile) - 1)) return runs def compute_autocorr(profile): """Автокорреляция – структурность, насколько повторяется рисунок""" profile = profile - np.mean(profile) result = np.correlate(profile, profile, mode='full') mid = len(result) // 2 return result[mid + 1] / result[mid] def compute_entropy(profile): """Энтропия – мера хаотичности, насколько случайна структура""" hist, _ = np.histogram(profile, bins=ENTROPY_BINS, range=(-180, 180), density=True) hist = hist[hist > 0] return -np.sum(hist * np.log2(hist)) # === Функция отрисовки === def draw_world(seq, axs, step, stat_bist_counts, stat_entropy, stat_autocorr): axs[0].cla() axs[1].cla() axs[2].cla() axs[3].cla() # Отображение профиля axs[0].plot(seq, label=f"Шаг {step}", color='skyblue') axs[0].set_title("Торсионный профиль (углы)") axs[0].set_ylim(-180, 180) # Визуальное выделение устойчивых "машин" stable_zones = find_local_min_runs(seq) for start, end in stable_zones: axs[0].axvspan(start, end, color='yellow', alpha=0.3) axs[0].text((start + end) // 2, 160, f'▲{end - start}', ha='center', va='center', fontsize=8, color='darkgreen') # График количества "стромбистов" axs[1].plot(stat_bist_counts, color='orchid') axs[1].set_title("Кол-во устойчивых машин (стромбистов)") # Энтропия axs[2].plot(stat_entropy, color='crimson') axs[2].set_title("Энтропия торсионного поля") # Автокорреляция axs[3].plot(stat_autocorr, color='seagreen') axs[3].set_title("Автокорреляция (память)") for ax in axs: ax.legend() # === Функция обновления === def update_step(): seq = st.session_state.seq history = st.session_state.history stat_bist_counts = st.session_state.bist_counts stat_entropy = st.session_state.entropy stat_autocorr = st.session_state.autocorr step = st.session_state.step # Случайная мутация i = np.random.randint(0, len(seq)) delta = np.random.randint(-JUMP, JUMP + 1) seq[i] = (seq[i] + delta + 180) % 360 - 180 history.append(seq.copy()) if len(history) > HISTORY_LEN: history.pop(0) stable_regions = find_local_min_runs(seq) stat_bist_counts.append(len(stable_regions)) stat_entropy.append(compute_entropy(seq)) stat_autocorr.append(compute_autocorr(seq)) st.session_state.step += 1 # === Интерфейс Streamlit === st.set_page_config(layout="wide") st.title("🧬 Стромбистный анализ торсионного поля") col1, col2 = st.columns([1, 2]) with col1: if st.button("🔁 Следующий шаг"): update_step() st.markdown(f"**Текущий шаг**: {st.session_state.step}") st.markdown("**Стромбисты** — устойчивые участки структуры, подобные памяти или машинам.") st.markdown("**Автокорреляция** — отражает повторяемость паттерна.") st.markdown("**Энтропия** — мера хаоса.") with col2: fig, axs = plt.subplots(4, 1, figsize=(10, 10), sharex=True) draw_world( st.session_state.seq, axs, st.session_state.step, st.session_state.bist_counts, st.session_state.entropy, st.session_state.autocorr ) st.pyplot(fig)