Визуализация странных аттракторов в Plotly — это шедеврально

    Поэзия — это очень красивый, зачастую глубокомысленный слог, которым мы не пользуемся в обыденной жизни, но так им любим наслаждаться. То же самое можно сказать и о математике. В фильме «Пи» главный герой называет математику «языком природы», а в фильме «Игры разума» главный герой говорит о ней, как об «особом виде искусства». Мы же, в обыденной жизни, можем напрочь забыть об этом.

    Облик странных аттракторов необычен и притягателен даже в двумерном измерении. Plotly позволяет строить их в трех измерениях, причем он дает возможность очень легко получить именно 3D-модель, которую можно «вертеть» и сквозь которую можно «пролетать» — ощущение «прикосновения».

    image



    С чего все началось


    Все началось очень давно, где-то в 2007 году в университете я познакомился с теорией самоорганизации и впервые увидел аттрактор Лоренца, его черно-белую иллюстрацию в какой-то книге. Тогда мне показалось слишком странным, что нечто может двигаться по столь необычной траектории. Еще более странным мне казалась сама идея того, что практически все на свете может быть описано одной-единственной теорией.

    В общем, все как обычно — мое мировоззрение поменялось, жизнь продолжалась, время шло. И вот, совсем недавно я натыкаюсь на ссылку и вижу вот это:

    Image from chaoticatmospheres.com
    Изображение взято с сайта chaoticatmospheres.com

    «Красиво.» — подумал я. Мысль о том, что все это можно построить в Matplotlib тоже промелькнула, но я уже заранее знал, что ничего впечатляющего не получится. И вот совсем недавно, буквально две недели назад, я познакомился с Plotly и сразу понял, что из этого может что-то получиться.

    Первая попытка построения сразу же провалилась. Оказалось, что формулы на некоторых изображениях «Галереи странных аттракторов» содержат ошибки. Впрочем, автор галереи, честно предупреждает о том, что не является математиком, как и автор этой статьи.

    Недолгое «гугление» позволило найти вот этот код, который оказался чрезвычайно полезен, а создал его Michael Tyka. Этот замечательный человек сделал целый плагин для Blender-а, позволяющий строить модели (!) 60-ти аттракторов. Фактически, их можно распечатать на 3D-принтере, а учитывая, что есть технологии печати воском, то можно довольно легко получить форму для отливки в бронзе.

    Код для визуализации


    Что ж, помимо, того что я являюсь математиком-любителем, я так же являюсь любителем-программистом. Так что не судите строго за качество кода.
    ################################
    ###  ИМПОРТИРУЕМ БИБЛИОТЕКИ  ###
    ################################
    
    import numpy as np
    from scipy.integrate import odeint
    import plotly.graph_objects as go
    
    
    ##################################
    ###  РЕШАЕМ СИСТЕМУ УРАВНЕНИЙ  ###
    ##################################
    
    # Система уравнений:
    def LorenzMod1(XYZ, t, alpha, beta, xi, delta):
        x, y, z = XYZ
        x_dt = -alpha*x + y*y - z*z + alpha*xi
        y_dt = x*(y - beta*z) + delta
        z_dt = -z + x*(beta*y + z)
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.1
    beta = 4
    xi = 14
    delta = 0.08
    
    x_0, y_0, z_0 = 0, 1, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 100, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(LorenzMod1, (x_0, y_0, z_0), t, args=(alpha, beta, xi, delta))
    X, Y, Z = f.T
    
    
    #######################
    ###  ВИЗУАЛИЗИРУЕМ  ###
    #######################
    
    # Массив, отвечающий за изменение цвета:
    c = np.linspace(0, 1, n)
    
    # Готовим данные для отрисовки:
    DATA = go.Scatter3d(x=X, y=Y, z=Z,
                        line=dict(color= c,
                                  width=3,
                                  # Выбираем цветовую палитру:
                                  # Greys,YlGnBu,Greens,YlOrRd,Bluered,RdBu,
                                  # Reds,Blues,Picnic,Rainbow,Portland,Jet,
                                  # Hot,Blackbody,Earth,Electric,Viridis,Cividis.
                                  colorscale="Cividis"),
                        #  Рисуем только линии:
                        mode='lines')
    
    fig = go.Figure(data=DATA)    
    
    # Задаем параметры отрисовки:
    fig.update_layout(width=1000, height=1000,
                      margin=dict(r=10, l=10, b=10, t=10),
                      # Устанавливаем цвет фона:
                      paper_bgcolor='rgb(0,0,0)',
                      scene=dict(camera=dict(up=dict(x=0, y=0, z=1),
                                             eye=dict(x=0, y=1, z=1)),
                                 # Устанавливаем пропорциональное
                                 # соотношение осей друг к другу:
                                 aspectratio = dict(x=1, y=1, z=1),
                                 # Отображаем, как указано в "aspectratio"
                                 aspectmode = 'manual',
                                 # Скрываем оси:
                                 xaxis=dict(visible=False),
                                 yaxis=dict(visible=False),
                                 zaxis=dict(visible=False)
                                )
                     )
    
    ######################
    #!!  ВОСТОРГАЕМСЯ  !!#
    ######################
    
    fig.show()

    В результате должна появиться 3D-модель странного аттрактора, называемого Lorenz Mod 1:
    image

    Нужно сразу отметить, что для решения систем дифференциальных уравнений была выбрана функция odeint из модуля SciPy, которая показалась мне самым простым и быстрым выходом для создания работающего кода. Однако, все уравнения могут решаться обычным методом Эйлера.

    Для обозначения коэффициентов в коде я по привычке использовал названия греческих букв принятых в LaTeX-е. В работе с блокнотами Jupyter это иногда бывает очень полезно, так-как формулы могут быстро стать кодом, а код может быстро превратиться в формулы.

    Если вы новичок в экосистеме Python, но хотите, что бы код гарантированно выполнился, то лучше всего установите последнюю версию дистрибутива Python Anaconda, а пакет Plotly через conda — встроенный менеджер пакетов дистрибутива.

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

    The Chen-Lee Attractor


    # Система уравнений:
    def ChenLee(XYZ, t, alpha, beta, delta):
        x, y, z = XYZ
        x_dt = alpha*x - y*z
        y_dt = beta*y + x*z
        z_dt = delta*z + x*y/3
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 5
    beta = -10
    delta = -0.38
    
    x_0, y_0, z_0 = 1, 1, 1
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 200, 30000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(ChenLee, (x_0, y_0, z_0), t,
               args=(alpha, beta, delta))

    image

    The Chua Attractor


    # Система уравнений:
    def ChuaAttractor(XYZ, t, alpha, beta, zeta, delta):
        x, y, z = XYZ
        h = zeta*x + (0.5*(delta - zeta))*(np.abs(x + 1) - np.abs(x - 1))
        x_dt = alpha*(-x + y - h)
        y_dt = x - y + z
        z_dt = -beta*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 15.6
    beta = 25.58
    zeta = -5/7
    delta = -8/7
    
    x_0, y_0, z_0 = 1.8, -0.7, -2.85
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 200, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(ChuaAttractor, (x_0, y_0, z_0), t,
               args=(alpha, beta, zeta, delta))

    image

    The Coullet Attractor


    # Система уравнений:
    def Coullet(XYZ, t, alpha, beta, zeta, delta):
        x, y, z = XYZ
        x_dt = y
        y_dt = z
        z_dt = alpha*x + beta*y + zeta*z + delta*x**3
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.8
    beta = -1.1
    zeta = -0.4
    delta = -1
    
    x_0, y_0, z_0 = 0.1, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 200, 20000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(Coullet, (x_0, y_0, z_0), t,
               args=(alpha, beta, zeta, delta))

    image

    The Dadras Attractor


    # Система уравнений:
    def DadrasAttractor(XYZ, t, rho, sigma, tau, zeta, epsilon):
        x, y, z = XYZ
        x_dt = y - rho*x + sigma*y*z
        y_dt = tau*y - x*z + z
        z_dt = zeta*x*y - epsilon*z
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    rho = 3
    sigma = 2.7
    tau = 1.7
    zeta = 2
    epsilon = 9
    
    x_0, y_0, z_0 = 0.1, 0.03, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 220, 40000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(DadrasAttractor, (x_0, y_0, z_0), t,
               args=(rho, sigma, tau, zeta, epsilon))

    image

    The Dequan Li Attractor


    # Система уравнений:
    def DequanLi(XYZ, t, alpha, beta, delta, epsilon, rho, xi):
        x, y, z = XYZ
        x_dt = alpha*(y - x) + delta*x*z
        y_dt = rho*x + xi*y -x*z
        z_dt = beta*z + x*y  - epsilon*x*x
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 40
    beta = 1.833
    delta = 0.16
    epsilon = 0.65
    rho = 55
    xi = 20
    
    x_0, y_0, z_0 = 0.01, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 50, 40000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(DequanLi, (x_0, y_0, z_0), t,
               args=(alpha, beta, delta, epsilon, rho, xi))

    image

    The Finance Attractor


    # Система уравнений:
    def FinanceAttractor(XYZ, t, alpha, beta, zeta):
        x, y, z = XYZ
        x_dt = (1/beta - alpha)*x + x*y + z
        y_dt = -beta*y - x**2
        z_dt = -x - zeta*z
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.001
    beta = 0.2
    zeta = 1.1
    
    x_0, y_0, z_0 = 0.1, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 300, 40000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(FinanceAttractor, (x_0, y_0, z_0), t,
               args=(alpha, beta, zeta))

    image

    The Four-Wing Attractor


    # Система уравнений:
    def FourWing(XYZ, t, alpha, beta, zeta):
        x, y, z = XYZ
        x_dt = alpha*x + y + y*z
        y_dt = -x*z + y*z
        z_dt = -z - zeta*x*y + beta
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 5
    beta = 16
    zeta = 2
    
    x_0, y_0, z_0 = 1, -1, 1
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 100, 60000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(FourWing, (x_0, y_0, z_0), t,
               args=(alpha, beta, zeta))

    image

    The Hadley Attractor


    # Система уравнений:
    def HadleyAttractor(XYZ, t, alpha, beta, xi, delta):
        x, y, z = XYZ
        x_dt = -y*y - z*z - alpha*x + alpha*xi
        y_dt = x*y - beta*x*z - y + delta
        z_dt = beta*x*y + x*z-z
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.2
    beta = 4
    xi = 8
    delta = 1
    
    x_0, y_0, z_0 = 0.39, -1, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 100, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(HadleyAttractor, (x_0, y_0, z_0), t,
               args=(alpha, beta, xi, delta))

    image

    The Halvorsen Attractor


    # Система уравнений:
    def HalvorsenAttractor(XYZ, t, alpha):
        x, y, z = XYZ
        x_dt = -alpha*x - 4*y - 4*z - y*y
        y_dt = -alpha*y - 4*z - 4*x - z*z
        z_dt = -alpha*z - 4*x - 4*y - x*x
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 1.4
    
    x_0, y_0, z_0 = -5, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 100, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(HalvorsenAttractor, (x_0, y_0, z_0), t,
               args=(alpha,))

    image

    The Liu-Chen Attractor


    # Система уравнений:
    def LiuChen(XYZ, t, alpha, beta, sigma, delta, epsilon, xi):
        x, y, z = XYZ
        x_dt = alpha*y + beta*x + sigma*y*z
        y_dt = delta*y - z + epsilon*x*z
        z_dt = xi*z - x*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 2.4
    beta = -3.75
    sigma = 14
    delta = -11
    epsilon = 4
    xi = 5.58
    
    x_0, y_0, z_0 = 1, 3, 5
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 55, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(LiuChen, (x_0, y_0, z_0), t,
               args=(alpha, beta, sigma, delta, epsilon, xi))

    image

    The Lorenz Mod 2 Attractor


    # Система уравнений:
    def LorenzMod2(XYZ, t, alpha, beta, xi, delta):
        x, y, z = XYZ
        x_dt = -alpha*x + y**2 -z**2 + alpha*xi
        y_dt = x*(y - beta*z) + delta
        z_dt = -z + x*(beta*y + z)
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.9
    beta = 5
    xi = 9.9
    delta = 1
    
    x_0, y_0, z_0 = 5, 5, 5
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 50, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(LorenzMod2, (x_0, y_0, z_0), t,
               args=(alpha, beta, xi, delta))

    image

    The Modified Chua Chaotic Attractor


    # Система уравнений:
    def ChuaModified(XYZ, t, alpha, beta, gamma, delta, zeta):
        x, y, z = XYZ
        h = -delta*np.sin((np.pi*x)/(2*gamma))
        x_dt = alpha*(y - h)
        y_dt = x - y + z
        z_dt = -beta*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 10.82
    beta = 14.286
    gamma = 1.3
    delta = 0.11
    zeta = 7
    
    x_0, y_0, z_0 = 1, 1, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 200, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(ChuaModified, (x_0, y_0, z_0), t,
               args=(alpha, beta, gamma, delta, zeta))

    image

    The Newton Leipnik Attractor


    # Система уравнений:
    def NewtonLeipnik(XYZ, t, alpha, beta):
        x, y, z = XYZ
        x_dt = -alpha*x + y + 10*y*z
        y_dt = -x - 0.4*y + 5*x*z
        z_dt = beta*z - 5*x*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.4
    beta = 0.175
    
    x_0, y_0, z_0 = 0.349, 0, -0.16
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 300, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(NewtonLeipnik, (x_0, y_0, z_0), t,
               args=(alpha, beta))

    image

    The Nose-Hoover Attractor


    # Система уравнений:
    def NoseHoover(XYZ, t, alpha):
        x, y, z = XYZ
        x_dt = y
        y_dt = -x + y*z
        z_dt = alpha - y*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 1.5
    
    x_0, y_0, z_0 = 1, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 150, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(NoseHoover, (x_0, y_0, z_0), t,
               args=(alpha,))

    image

    The Roessler Attractor


    # Система уравнений:
    def Roessler(XYZ, t, alpha, beta, sigma):
        x, y, z = XYZ
        x_dt = -(y + z)
        y_dt = x + alpha*y
        z_dt = beta + z*(x - sigma)
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.2
    beta = 0.2
    sigma = 5.7
    
    x_0, y_0, z_0 = 1, 1, 1
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 300, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(Roessler, (x_0, y_0, z_0), t,
               args=(alpha, beta, sigma))

    image

    The Sakarya Attractor


    # Система уравнений:
    def SakaryaAttractor(XYZ, t, alpha, beta):
        x, y, z = XYZ
        x_dt = -x + y + y*z
        y_dt = -x - y + alpha*x*z
        z_dt = z - beta*x*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.4
    beta = 0.3
    
    x_0, y_0, z_0 = 1, -1, 1
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 100, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(SakaryaAttractor, (x_0, y_0, z_0), t,
               args=(alpha, beta))

    image

    The Thomas Attractor


    # Система уравнений:
    def Thomas(XYZ, t, beta):
        x, y, z = XYZ
        x_dt = -beta*x + np.sin(y)
        y_dt = -beta*y + np.sin(z)
        z_dt = -beta*z + np.sin(x)
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    beta = 0.19
    
    x_0, y_0, z_0 = 0.1, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 185, 10000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(Thomas, (x_0, y_0, z_0), t,
               args=(beta,))

    image

    The Three-Scroll Unified Chaotic System Attractor (TSUCS1)


    # Система уравнений:
    def TSUCS1(XYZ, t, alpha, beta, delta, epsilon, xi):
        x, y, z = XYZ
        x_dt = alpha*(y - x) + delta*x*z
        y_dt = xi*y - x*z
        z_dt = beta*z + x*y  - epsilon*x*x
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 40
    beta = 0.833
    delta = 0.5
    epsilon = 0.65
    xi = 20
    
    x_0, y_0, z_0 = 0.01, 0, 0
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 70, 50000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(TSUCS1, (x_0, y_0, z_0), t,
               args=(alpha, beta, delta, epsilon, xi))

    image

    The Wang-Sun Attractor


    # Система уравнений:
    def WangSunAttractor(XYZ, t, alpha, beta, zeta, delta, epsilon, xi):
        x, y, z = XYZ
        x_dt = alpha*x + zeta*y*z
        y_dt = beta*x + delta*y - x*z
        z_dt = epsilon*z + xi*x*y
        return x_dt, y_dt, z_dt
    
    # Параметры системы и начальные условия:
    alpha = 0.2
    beta = -0.01
    zeta = 1
    delta = -0.4
    epsilon = -1
    xi = -1
    
    x_0, y_0, z_0 = 0.5, 0.1, 0.1
    
    # Максимальное время и общее количество
    # временных точек:
    tmax, n = 500, 30000
    
    # Интегрируем систему уравнений в каждой точке
    # временного интервала t:
    t = np.linspace(0, tmax, n)
    f = odeint(WangSunAttractor, (x_0, y_0, z_0), t,
               args=(alpha, beta, zeta, delta, epsilon, xi))

    image

    В заключение


    Огонь, вода, земля, небо, солнце, луна, звезды — все это самые древние поэтические сущности. Очень часто мне удается найти в математике что-то такое же прекрасное. Но гораздо чаще я даже не понимаю, как обо всем этом говорить на математическом языке и языке обычном. Не понимаю, но хочется научиться.

    Но вот что я осознал на все 100%, так это то, что современные инструменты визуализации дают фантастическую возможность выразить свое отношение к тому чем ты сейчас занят, возможность показать, как это важно для тебя и как тебе это интересно. Сделать все это без слов.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 31

      +2
      Это великолепно, спасибо!
        +2
        Красивенько!
          +2
          Шикарно! Попробую перетолмачить это на Lua для движка Instead. Спасибо!
            0
            Добрый день. А вы можете пояснить почему собираетесь использовать Instead, а не Love2d?
              0
              Потому, что мне нравится API этого движка, а Love2d — скорее фреймворк для написания поверх него своего движка. В Instead можно без мороки раскидать визуализации по разным комнатам или объектам и получить удобное меню для навигации. Дополнить текстовыми пояснениями, если надо. Кроме того, у Instead есть репозиторий, куда можно будет эту программу выложить и она точно не затеряется среди всех этих сотен энтертейнмента на итче, стиме, гоге и т.д.
            +2
            Спасибо!
              +8
              Класс! Немного покопался и смог нарисовать аттрактор Aizawa. Спасибо автору за статью!
              image
                +1
                Потрясающе!
                  0
                  Не подскажите как вы сделали анимацию?
                    0
                    Вращаю камеру вокруг оси Z и с помощью imageio генерирую серию изображений, в конце объединяю изображения в видео.
                  +1
                  Есть еще такая программулина как «Chaoscope», можно подглядеть режимы визуализации, для еще более красивых картинок.
                    0
                    Да, занимательная программа. У моей визуализации есть большой минус, который портит все впечатление — приходится каждый раз возвращаться в код, что бы изменить какой-нибудь параметр. Можно добавить виджетов и сделать интерфейс подобный «Chaoscope». Даже не знаю почему мне эта идея не пришла раньше. Но, насколько я помню, в «Chaoscope» изображение является статичным, а в Plotly его можно «вертеть» — мне это очень сильно понравилось.

                    Arneodo Attractor:
                    image
                    image
                    image
                    image
                      +1
                      Там в chaoscope, кроме слайдеров, ещё можно рендерить результат с повышенным качеством:


                      Медленно, правда, он рендерит.
                        0
                        Да, нельзя + он уже 10-ть лет, как не разрабатывается, но ведь ничто не мешает взять лучшее)
                      +2
                      Боже мой, это великолепно! Спасибо, за то, что напомнили об этом мире. (удивительном мире и самой поэзии математики)

                      Как бы хотелось иметь как минимум ещё одну жизнь, что бы посветить её познанию именно её (математики) безграничных горизонтов!
                      Она потрясающа!

                      Спасибо!
                        0
                        Да, математикой можно наслаждаться. Даже не помню, когда в последний раз смотрел какой-нибудь фильм или сериал. Все свободное время — это музыка, крепкий чай и математика.
                        +2
                        * Подавил в себе желание написать что-то цинично-ядовитое, про любителей и про карьеру профессионалов. * I wish you luck, man.
                          0
                          * Спасибо.
                          * Взаимно.
                          +1
                          В школе на спеки рисовал подобные вещи. Вот бы тому мне из прошлого тысячелетия рассказать, что оказывается это были аттракторы. Был бы отличный эффект бабочки.
                            +2

                            Если запускать код по методике:
                            https://habr.com/ru/post/448316/
                            то все уже установлено

                              0
                              Да, в Google Colaboratory все уже установлено — можно с ходу начинать работать. Я как-то забыл об этом. Спасибо, что напомнили.
                                0
                                В дополнение можно сказать, что такой код при запуске не требует подтверждения аккаунта.
                                Включил и нарисовало.
                                Еще можно:
                                %pip install numpy-stl
                                %pip install plotly --upgrade
                                

                                И еще есть список на несколько листов, что можно установить.

                                Если данные записывать на облачный диск, тогда пару раз в день может потребовать подтверждения аккаунта.
                                  +1
                                  Я когда Google Colaboratory первый раз увидел, впал в небольшой ступор. До сих пор кажется невероятным, что кто-то может вот просто-так подарить какие-то мощности для вычислений.

                                  А когда сработал
                                  import numba
                                  я впал в ступор во второй раз (ничего про бесплатные GPU и TPU я тогда еще не знал).

                                  Определенно хорошая штука. Можно работать на двух машинах, что иногда бывает ну ооочень как надо.
                                +1
                                Я как раз такое задание давал на экзамене, только мы делали сетку начальных условий и со слайдерами.

                                Видео: www.youtube.com/watch?v=B9-sxUs-3wo.
                                Тоже питон, но не в браузере: pyqt, pyqtgraph, numba.
                                  0
                                  Вашим студентам повезло с преподавателем.
                                    0
                                    Спасибо, это студенты меня вдохновляют! Бывает, дашь им старую, изученную со всех сторон задачу из учебника – а они возьмут и решат её лучше, чем в учебнике )
                                  +1

                                  Рис  Семейство из пяти аттракторов

                                  Чтобы отобразить семейство из пяти аттракторов, позволил себе немного изменить код, и сразу хочется выразить благодарности автору за хороший код для вхождения в тему:
                                  import numpy as np
                                  from scipy.integrate import odeint
                                  import plotly.graph_objects as go
                                  
                                  
                                  ##################################
                                  ###  РЕШАЕМ СИСТЕМУ УРАВНЕНИЙ  ###
                                  ##################################
                                  
                                  # Система уравнений:
                                  def LorenzMod1(XYZ, t, alpha, beta, xi, delta):
                                      x, y, z = XYZ
                                      x_dt = -alpha*x + y*y - z*z + alpha*xi
                                      y_dt = x*(y - beta*z) + delta
                                      z_dt = -z + x*(beta*y + z)
                                      return x_dt, y_dt, z_dt
                                  
                                  # Параметры системы и начальные условия:
                                  alpha = 0.1
                                  beta = 4
                                  xi = 14
                                  delta = 0.08
                                  
                                  
                                  
                                  #1111111111111111111111111111111
                                  x_0, y_0, z_0 = 0, 1, 0
                                  print ("1")
                                  
                                  
                                  # Максимальное время и общее количество
                                  # временных точек:
                                  tmax, n = 100, 40000
                                  
                                  # Интегрируем систему уравнений в каждой точке
                                  # временного интервала t:
                                  
                                  t = np.linspace(0, tmax, n)
                                  c = np.linspace(0, 1, n)
                                  
                                  
                                  
                                  f = odeint(LorenzMod1, (x_0, y_0, z_0),t,  args=(alpha, beta, xi, delta))
                                  X, Y, Z = f.T
                                  
                                  # Параметры системы и начальные условия:
                                  alpha = 0.1
                                  beta = 4
                                  xi = 14
                                  delta = 0.08
                                  #111111111111111111111111111111111111111111111111111111111111111111111
                                  
                                  
                                  
                                  
                                  
                                  
                                  #2222222222222222222222
                                  for ii in range(100001,100005,1):
                                  
                                      i=ii/100000.0
                                      print (i)
                                      x_0, y_0, z_0 = 0, i, 0
                                  
                                      # Максимальное время и общее количество
                                      # временных точек:
                                      tmax, n = 100, 40000
                                  
                                      # Интегрируем систему уравнений в каждой точке
                                      # временного интервала t:
                                      t = np.linspace(0, tmax, n)
                                      c1 = np.linspace(0, 1, n)
                                  
                                  
                                      f = odeint(LorenzMod1, (x_0, y_0, z_0),t,  args=(alpha, beta, xi, delta))
                                      X1, Y1, Z1 = f.T
                                  
                                    
                                      X=np.hstack((X1, X))    
                                      Y=np.hstack((Y1, Y))    
                                      Z=np.hstack((Z1, Z))    
                                      c=np.hstack((c1, c))    
                                  #22222222222222222222222222222222222222222222222222222222222222222222
                                    
                                  
                                  
                                  
                                  
                                  #######################
                                  ###  ВИЗУАЛИЗИРУЕМ  ###
                                  #######################
                                  
                                  # Массив, отвечающий за изменение цвета:
                                  
                                  
                                                                              #c = np.linspace(0, 1, len(X))
                                  
                                  # Готовим данные для отрисовки:
                                  DATA = go.Scatter3d(x=X, y=Y, z=Z,
                                                      line=dict(color= c,
                                                                width=3,
                                                                # Выбираем цветовую палитру:
                                                                # Greys,YlGnBu,Greens,YlOrRd,Bluered,RdBu,
                                                                # Reds,Blues,Picnic,Rainbow,Portland,Jet,
                                                                # Hot,Blackbody,Earth,Electric,Viridis,Cividis.
                                                                colorscale="Cividis"),
                                                      #  Рисуем только линии:
                                                      mode='lines')
                                  
                                  fig = go.Figure(data=DATA)    
                                  
                                  # Задаем параметры отрисовки:
                                  fig.update_layout(width=1000, height=1000,
                                                    margin=dict(r=10, l=10, b=10, t=10),
                                                    # Устанавливаем цвет фона:
                                                    paper_bgcolor='rgb(0,0,0)',
                                                    scene=dict(camera=dict(up=dict(x=0, y=0, z=1),
                                                                           eye=dict(x=0, y=1, z=1)),
                                                               # Устанавливаем пропорциональное
                                                               # соотношение осей друг к другу:
                                                               aspectratio = dict(x=1, y=1, z=1),
                                                               # Отображаем, как указано в "aspectratio"
                                                               aspectmode = 'manual',
                                                               # Скрываем оси:
                                                               xaxis=dict(visible=False),
                                                               yaxis=dict(visible=False),
                                                               zaxis=dict(visible=False)
                                                              )
                                                   )
                                  
                                  ######################
                                  #!!  ВОСТОРГАЕМСЯ  !!#
                                  ######################
                                  
                                  fig.show()
                                  

                                  Как уже говорили выше, все считается быстро, а отображается медленно.

                                  Аналогичная проблема существует в отображении файлов формата STL, Выходом может быть сокращение входной информации перед отображением — это сечения. Для формата STL в сечении получатся отрезки в треугольниках, а в аттракторах, это будут точки и поэтому нужно много точек, которые в сечении уже можно соединить. В данном случае это будут семейство кривых по пяти точкам. И это в другой форме будет отражать решение системы уравнений. 

                                  Когда нужны подробности, сразу ищем карту с линиями уровня, или томограмму. Сечения это как аналог, и карты, и томограммы.


                                  Рис   Пример вывода сечений для формата STL 

                                   
                                  .    

                                    0
                                    Отображать по несколько аттракторов — очень интересная идея. Есть все шансы (без всякой иронии) получить изображения на грани высокого искусства. Одни товарищи уже напечатали такое на бумаге формата А3 и кому-то подарили.

                                    А отображается и правда медленно. Спасибо что разъяснили почему так происходит. Я думал, что все медленно считается и уже было серьезно подумывал о покупке нового компьютера.
                                    0
                                    Вот такой вопрос возник — можно ли как-то преобразовать треки аттракторов в поверхности? Ну, например, с помошью реймаршинга и SDF-функций?
                                      0
                                      Я думаю — можно. Правда не знаю как, но используя NumPy и SciPy мне кажется все это получится сделать без всяких лишних танцев с бубном. А Plotly, кстати, очень качественно такие поверхности может отобразить.
                                        +1
                                        Хорошо строятся поверхности типа колокола (без складок ), и на регулярных данных, когда соседние образующие линии имеют одинаковое количество точек и еще есть точка начала линии.

                                        Если со складками, соседние образующие линии должны быть близко расположены.

                                        Как раз в семействе аттракторов можно провести линии близко друг другу. И дальше может помочь формат STL. Берем две соседние линии, на каждой линии по две точки. По четырем точкам можно построить два треугольника, это и есть формат STL.

                                        solid 
                                           facet normal 0.000000e+000 -9.144431e-001 4.047146e-001
                                              outer loop
                                                 vertex 2.350000e+001 -1.070718e-001 1.283354e-001
                                                 vertex 2.425000e+001 -1.070718e-001 1.283354e-001
                                                 vertex 2.350000e+001 9.528544e-002 5.855569e-001
                                              endloop
                                           endfacet
                                           facet normal 0.000000e+000 -9.144431e-001 4.047146e-001
                                              outer loop
                                                 vertex 2.425000e+001 9.528544e-002 5.855569e-001
                                                 vertex 2.350000e+001 9.528544e-002 5.855569e-001
                                                 vertex 2.425000e+001 -1.070718e-001 1.283354e-001
                                              endloop
                                           endfacet
                                        


                                        Это и есть два треугольника.
                                        В каждой строчке по точке

                                        При просмотре файла, для отображения объема, берут данные нормалей из формата или нормали считают сами программы. Есть и цветные STL.

                                        При отображении поверхности можно задать прозрачность и отобразить только видимые поверхности.

                                        Если поверхность STL полностью замкнута, тогда программы могут рассматривать поверхность как тело и взять то же сечение, только с ограничениями по количеству треугольников. У разных программ это разные цифры.

                                        Еще есть порядок записи точек в треугольнике, это как направление обхода точек треугольника. При отображении свет будет по разному отражаться от таких треугольников, если один треугольник светлый, второй темный, хотя треугольники расположены рядом.

                                      Only users with full accounts can post comments. Log in, please.