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


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дається в секундах? Якщо так, чи буде задана швидкість в одиницях в секунду, чи щось менше?
Р. Кап

@R. Kap Це не має значення. tзадається в одиницю часу, що б це не було, і швидкість буде використовувати ту саму одиницю. Буде це за секунди чи години, відповідь буде однаковою.
soktinpk

nearly massless catНу, якою була б точна маса кота? Чи варто просто використовувати 0як значення для маси цієї кішки?
Р. Кап

@R. Кап Так. Але на нього все ще впливає гравітація (зазвичай, Ньютон не вважав, що предмети без маси не впливають на гравітацію). Тому ми повинні вважати, що вона має довільно малу масу, і ваша відповідь - це фактично положення, коли маса кота йде до нуля. Головний момент у тому, що на саму планету кішка взагалі не впливає.
soktinpk

2
@soktinpk, можливо, буде простіше просто відверто сказати, що центральний орган фіксований.
Мальтісен

Відповіді:


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.
Anders Kaseorg

Чудово, що це гольф, але це виклик коду, ви можете зробити це трохи зрозуміліше, у мене були зроблені якісь подряпини в Python, і я можу обчислити аномалію, тету, ексцентриситет, період тощо, але я затримався у визначенні знак тети і визначення обертання від опорної площини xy до 3d простору. І все-таки це справді чудові речі
милі

@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.