Куда пойдет кот? (орбитальная механика)


16

Почти безмассовый кот упал в космос (не волнуйтесь, с скафандром и всем остальным) в точке (x, y, z)со скоростью (vx, vy, vz). В этой точке находится фиксированная, бесконечно плотная планета (с объемом 0), (0, 0, 0)которая притягивает объекты на расстоянии rс ускорением 1/r^2. Согласно ньютоновской гравитации, куда движется объект после времени t?

Почти безмассовое в этом случае означает, что вы выводите значение lim (mass --> 0) <position of cat>. На массу влияет гравитация планеты, но гравитация кошки не влияет на планету. Другими словами, центральное тело является фиксированным.

Это несколько похоже на Code Golf: какова судьба космического корабля? [версия с плавающей запятой] , но это отличается, потому что это измерение точности.

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

Ввод : x y z vx vy vz tне обязательно целые числа, представляющие координаты x, y, z, скорость в направлениях x, y и z и время соответственно. Гарантируется, что скорость кошки строго меньше, чем скорость спасения на этой высоте. Ввод может быть взят из любого места, включая параметры для функции. Программа должна работать менее чем за три секунды на моем ноутбуке t < 2^30, а это означает, что если вы запускаете симуляцию, вы должны соответствующим образом скорректировать свой временной шаг. Если вы планируете использовать ограничение в 3 секунды для каждого тестового случая, убедитесь, что есть настраиваемый параметр, который может сделать его более точным / менее точным для увеличения скорости, чтобы я мог запустить его за три секунды на моем компьютере.

Выход : x y zпозиция после времени t.

Поскольку проблема двух тел может быть полностью решена, теоретически можно получить идеальный, правильный ответ.

Оценка : для любого тестового случая ошибка определяется как расстояние между вашим выходом и «истинным» выходом. Истинный вывод определен как тот, который генерирует фрагмент теста. Если ошибка меньше чем 10^(-8), ошибка округляется до нуля. Ваша оценка - это средняя ошибка на 100 (или более) случайных тестовых случаях. Если вы напишите совершенно точный ответ, вы должны получить оценку 0; выигрывает наименьшее количество очков, и связи будут нарушены по длине кода.

Тестовые случаи :

1 0 0 0 -1 0 1000000000 --> 0.83789 -0.54584 0

В этом случае орбита идеально круглая с периодом 2 * пи, поэтому после оборота 159154943 раз кошка окажется примерно на (0,83789, -0,54584). Это не тестовый пример, на котором будет проверяться ваш код; однако, если вы отправите совершенно точный ответ, вы можете проверить его на этом.

Фрагмент ниже генерирует случайные дополнительные тестовые случаи и будет использоваться для оценки представлений; дайте мне знать, если есть ошибка с этим:


Время tдается в секундах? Если да, будет ли скорость указываться в единицах в секунду или что-то меньшее?
Р. Кап

@Р. Кап Это не имеет значения. tдается в единицу времени, что бы это ни было, и скорость будет использовать ту же единицу. Будь то в секундах или часах, ответ будет одинаковым.
soktinpk

nearly massless catНу, а какой будет точная масса кошки? Должны ли мы просто использовать 0в качестве значения массы этой кошки?
Р. Кап

@Р. Кап Да. Но это все еще зависит от силы тяжести (обычно Ньютон не считал объекты без массы подверженными влиянию силы тяжести). Поэтому мы должны считать, что она имеет сколь угодно малую массу, и ваш ответ на самом деле является положением, когда масса кошки стремится к нулю. Главное, что сама планета не подвержена влиянию кошки.
soktinpk

2
@soktinpk может быть проще просто явно сказать, что центральное тело фиксировано.
Maltysen

Ответы:


6

Python 3.5 + NumPy, точный, 186 байт

from math import*
def o(r,v,t):
 d=(r@r)**.5;W=2/d-v@v;U=W**1.5;b=[0,t*U+9]
 while 1:
  a=sum(b)/2;x=1-cos(a);y=sin(a)/U;k=r@v*x/W+d*y*W
  if a in b:return k*v-r*x/W/d+r
  b[k+a/U-y>t]=a

Это точное решение с использованием формулы I, разработанной на основе Йеспера Йоранссониса, «Симметрии задачи Кеплера», 2015 . Он использует бинарный поиск для решения трансцендентного уравнения Ax + B cos x + C sin x = D, которое не имеет решения в замкнутой форме.

Функция ожидает, что позиция и скорость будут переданы как массивы NumPy:

>>> from numpy import array
>>> o(array([1,0,0]),array([0,-1,0]),1000000000)
array([ 0.83788718, -0.54584345,  0.        ])
>>> o(array([-1.1740058273269156,8.413493259550673,0.41996042044140003]),array([0.150014367067652,-0.09438816345868332,0.37294941703455975]),7999.348650387233)
array([-4.45269544,  6.93224929, -9.27292488])

Что делает @?
Р. Кап

1
Это новый оператор в Python 3.5, для которого перегружается NumPy numpy.dot(умножение произведения на матрицу). См. PEP 465.
Андерс Касеорг

Это здорово, что это игра в гольф, но это вызов кода, не могли бы вы сделать это немного яснее, я немного поработал в Python и могу вычислить аномалию, тета, эксцентриситет, период и т. Д., Но я застрял в определении знак тета и определение поворота от базовой плоскости xy в трехмерное пространство. Тем не менее, это действительно отличная вещь
мили

@ Miles Поскольку связи разбиты по длине кода, имеет смысл, чтобы это было в гольф.
Мего

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

2

Javascript

Это просто для того, чтобы начать работать, так как никто, кажется, не публикует ответы. Вот очень наивный, простой способ, который можно значительно улучшить:

function simulate(x, y, z, vx, vy, vz, t) {
  var loops = 1884955; // tune this parameter
  var timestep = t / loops;
  for (var i = 0; i < t; i += timestep) {
    var distanceSq = x*x + y*y + z*z; // distance squared from origin
    var distance = Math.sqrt(distanceSq);
    var forceMag = 1/distanceSq; // get the force of gravity
    var forceX = -x / distance * forceMag;
    var forceY = -y / distance * forceMag;
    var forceZ = -z / distance * forceMag;
    vx += forceX * timestep;
    vy += forceY * timestep;
    vz += forceZ * timestep;
    x += vx * timestep;
    y += vy * timestep;
    z += vz * timestep;
  }
  return [x, y, z];
}

Тестирование:

simulate(1, 0, 0, 0, -1, 0, Math.PI*2) --> [0.9999999999889703, -0.0000033332840909716455, 0]

Эй, это очень хорошо. Он имеет ошибку около 3.333 * 10 ^ (- 6), которой недостаточно для округления вниз ... это близко.

Просто для удовольствия:

console.log(simulate(1, 0, 0, 0, -1, 0, 1000000000))
--> [-530516643639.4616, -1000000000.0066016, 0]

Ну что ж; так что это не самый лучший.

И на случайном тестовом примере от генератора:

simulate(-1.1740058273269156,8.413493259550673,0.41996042044140003,0.150014367067652,-0.09438816345868332,0.37294941703455975,7999.348650387233)
-->    [-4.528366392498373, 6.780385554803544, -9.547824236472668]
Actual:[-4.452695438880813, 6.932249293597744, -9.272924876103785]

С ошибкой только приблизительно 0.32305!

Это можно значительно улучшить, используя что-то вроде интеграции Verlet или какой-нибудь необычный алгоритм. Фактически, эти алгоритмы могут даже получить отличные результаты, несмотря на то, что они являются симуляциями.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.