InkBlot & Bitrex
Только что пришла в голову мысль: а что, если бы мы смогли преобразовать твои спонтанные всплески в какую-то предсказуемую систему, но чтобы она всё равно чувствовалась живой, соединив хаос с порядком?
Ого, это та ещё безумная идея, от которой аж мысли искрят. Представь себе каркас уравнений, который бьётся, сетка, которая дышит, а сверху – щепотка случайности, чтобы совсем не походила на нудного робота. Мы можем создать структуру, которая живая, и хаос, который невозможно укротить – как пульс, который не хочет стоять на месте. Давай набросаем и посмотрим, где начнутся шероховатости.
Зачетно. Давай сначала разберёмся с основой: определим вектор состояния X, потом Xdot будет равен линейной части A·X плюс нелинейное ядро N(X), и в конце добавим стохастический член σ·ξ(t). Выбери A так, чтобы собственные значения лежали на мнимой оси – для колебаний, подстрой N, чтобы амплитуда оставалась ограниченной, а ξ пусть будет гауссовским белым шумом, чтобы добавить импульс. Если σ сделать небольшим, хаос будет оставаться незаметным; увеличь его, и получишь этот эффект "бешеного" сердцебиения. Накинь конкретные A и N, которые у тебя на уме, и будем двигаться дальше.
Хорошо, давай сделаем это лаконичным и интересным. Используй двухмерное состояние X = (x, y). Выбери ω = 1, чтобы линейная часть была A = [[0, -1], [1, 0]] – это даст чистый поворот, без затухания и роста.
Теперь нелинейное ядро N будет сдерживать амплитуду от разрастания или затухания. Классический выбор – кубическое демпфирование, которое влияет на радиус: N(x, y) = (−α x (x² + y²), −α y (x² + y²)) с α – маленькой положительной константой, например, 0.1.
Получаются такие уравнения:
ẋ = −y − α x (x² + y²) + σ ξ₁(t)
ẏ = x − α y (x² + y²) + σ ξ₂(t)
При σ = 0 это даст стабильный предельный цикл, а гауссовский шум добавит ритму этот вайб буйного сердцебиения, если ты увеличишь σ. Можешь поиграть с α или добавить небольшое смещение к линейной части, если хочешь, чтобы цикл находился на определенном радиусе. Давай попробуем и посмотрим, какие импульсы у нас получатся.
Отлично, чистый результат. Поставлю альфа на 0.1, сигма – на 0.05, запущу и посмотрю, как орбита будет колыхаться вокруг радиуса 1. Если нужен этот выброс, увеличь сигму до 0.2 или добавь небольшую подстройку к матрице вращения, чтобы она никогда не попадала в одну и ту же фазу. Давай перенесём числа в код и посмотрим, как дрожит предельный цикл.
Вот небольшой Python-скрипт, который можно просто скопировать и вставить в твой блокнот.
import numpy as np
import matplotlib.pyplot as plt
import random
# параметры
α = 0.1
σ = 0.05 # увеличь до 0.2 для сумасшедшего импульса
dt = 0.01
T = 2000
steps = int(T/dt)
# инициализация
x, y = 0.5, 0.0
trajectory = []
for _ in range(steps):
# детерминированная часть
dx = -y - α*x*(x**2 + y**2)
dy = x - α*y*(x**2 + y**2)
# случайный толчок
dx += σ * np.random.randn()
dy += σ * np.random.randn()
# шаг Эйлера
x += dx*dt
y += dy*dt
trajectory.append((x, y))
# построение графика
traj = np.array(trajectory)
plt.figure(figsize=(4,4))
plt.plot(traj[:,0], traj[:,1])
plt.xlabel('x')
plt.ylabel('y')
plt.title('Стохастический предельный цикл')
plt.axis('equal')
plt.show()
Просто запусти и смотри, как орбита дрожит. Не стесняйся менять α или уровень шума, чтобы посмотреть, как цикл содрогается. Приятного глючения!