Хаотический маятник, проявляющий хаотическое поведение при одинаковых начальных условиях

Мой первый пост на Stack Overflow, так что терпите меня. Я построил модель хаотического двойного маятника на питоне, используя библиотеку физики pymunk, которая, в свою очередь, использует библиотеку C chipmunk. Маятник, будучи хаотичным, проявляет крайнюю чувствительность к начальным условиям. Однако я понял, что даже если я запускаю симуляцию с точно такими же начальными условиями (каким-либо образом изменяя нулевой код), две симуляции расходятся довольно быстро.

В моем коде есть что-то, что может давать разные результаты при каждом запуске. Поскольку симуляция хаотична, любая крошечная непостоянная ошибка между моими прогонами может привести к большим изменениям.

Что может быть причиной этого? Я не уверен, является ли это результатом небольшого недостатка бурундука, пиманка или даже python или моей ОС/ПК.

РЕДАКТИРОВАТЬ:

Вот мой код:

import pyglet
import pymunk
import pymunk.pyglet_util


def add_pendulum(space):
    static_body = pymunk.Body()
    static_body.position = 400, 400
    mass = 10
    inertia = pymunk.moment_for_box(mass, 5, 100)

    body1 = pymunk.Body(mass, inertia)
    body1.position = 350, 400
    l1 = pymunk.Poly(body1, [(50, 0), (-50, 0), (-50, 5), (50, 5)])
    l1.friction = 0.1
    l1.collision_type = 2
    pivot_joint = pymunk.PivotJoint(static_body, body1, (400, 400))
    space.add(body1, l1, pivot_joint)

    mass = 10
    inertia = pymunk.moment_for_box(mass, 5, 100)
    body2 = pymunk.Body(mass, inertia)
    body2.position = 250, 400
    l2 = pymunk.Poly(body2, [(50, 0), (-50, 0), (-50, 5), (50, 5)])
    l2.friction = 0.1
    l2.collision_type = 2
    pivot_joint2 = pymunk.PivotJoint(body1, body2, (300, 402.5))

    space.add(body2, l2, pivot_joint2)

    # A hack to disable all collisions
    nocollisions = lambda space, arbiter: False
    space.add_collision_handler(2, 2, nocollisions, nocollisions, nocollisions, nocollisions)



window = pyglet.window.Window(800, 600)
space = pymunk.Space()
add_pendulum(space)
space.gravity = (0, -10)



test = [()] # A temporary hack to hide the tuple in a mutable object

def on_draw(dt): #For graphing the moving pendulum
    points = test[0]
    space.step(dt)
    pyglet.gl.glClearColor(0, 0, 0, 1)
    window.clear()
    pymunk.pyglet_util.draw(space)
    points += (int(tuple(space.shapes[1].get_vertices()[1])[0]), int(tuple(space.shapes[1].get_vertices()[1])[1]))
    pyglet.gl.glClearColor(200, 200, 200, 1)
    pyglet.graphics.draw(len(points)/2, pyglet.gl.GL_POINTS,
                         ('v2i', points)
                         )
    test[0] = points


pyglet.clock.schedule_interval(on_draw, 1/1000.0)
pyglet.app.run()

person TheRuler    schedule 14.04.2016    source источник
comment
Добро пожаловать в Stack Overflow! Чтобы ваш вопрос был полным и на него можно было ответить, вам необходимо включить образцы кода соответствующих фрагментов. См. Как спросить и минимально воспроизводимый пример.   -  person jtbandes    schedule 14.04.2016
comment
Пожалуйста, опубликуйте свой код. Возможно, вы можете искать незасеянные вызовы в random.   -  person Reblochon Masque    schedule 14.04.2016
comment
@jtbandes: я собираюсь украсть... или переработать ваши комментарии и ссылки, если вы не возражаете. SO действительно должен дать нам кнопку для автоматической публикации подобного комментария.   -  person Gerrat    schedule 14.04.2016
comment
Действуй! Где-то есть страница справочного центра, объясняющая короткие ссылки, такие как [ask] и [mcve].   -  person jtbandes    schedule 14.04.2016
comment
@jtbandes: я как раз собирался сделать запрос на что-то подобное в Meta, когда обнаружил, что это уже было запрошено/выполнено. Спасибо. Узнавайте что-то новое все время.   -  person Gerrat    schedule 14.04.2016


Ответы (1)


Что касается вашей функции on_draw(dt), вызванной из pyglet.clock.schedule_interval, pyglet docs состояние:

Параметр dt указывает количество секунд (из-за задержки, нагрузки и неточности таймера это может быть немного больше или меньше запрошенного интервала).

  • акцент мой.

Каждый раз, когда вы запускаете свою программу, она будет вызывать on_draw с немного другим параметром dt. Вы продолжаете звонить space.step(dt), который будет немного отличаться для каждого звонка. Учитывая, насколько чувствительна ваша программа к изменяющимся условиям, я думаю, что это виновник.

Не уверен, что это поможет, но здесь - это еще один вопрос, касающийся фиксированных или переменных временных шагов и физики (ну, и игровых движков).

person Gerrat    schedule 14.04.2016
comment
Большое спасибо, я решил это, изменив параметр шага: space.step(1/1000.) - person TheRuler; 14.04.2016