Para onde o gato vai? (mecânica orbital)


16

Um gato quase sem massa é jogado no espaço (não se preocupe, com um traje espacial e tudo) no ponto (x, y, z)com velocidade (vx, vy, vz). Existe um planeta fixo infinitamente denso (com volume de 0) no ponto (0, 0, 0)e atrai objetos à distância rcom aceleração 1/r^2. De acordo com a gravidade newtoniana, para onde o objeto vai depois do tempo t?

Quase sem massa, neste caso, significa que você está produzindo o valor de lim (mass --> 0) <position of cat>. A massa é afetada pela gravidade do planeta, mas o planeta não é afetado pela gravidade do gato. Em outras palavras, o corpo central é fixo.

Isso é um pouco semelhante ao Code Golf: Qual é o destino da nave espacial? [versão de ponto flutuante] , mas isso é diferente porque está medindo a precisão.

Você pode implementar uma solução com base em uma simulação, que deve ser executada em menos de 3 segundos, OU você pode implementar um programa que fornece um valor exato (também deve ser executado em menos de 3 segundos). Veja os detalhes da pontuação abaixo. Se você implementar uma simulação, ela não precisa ser exata, mas sua pontuação será mais baixa devido à imprecisão.

Entrada : x y z vx vy vz t, não necessariamente inteiros representando x, y, z coordenadas, velocidade em x, y, z e indicações e tempo, respectivamente. É garantido que a velocidade do gato é estritamente menor que a velocidade de escape nessa altitude. A entrada pode ser obtida de qualquer lugar, incluindo parâmetros para uma função. O programa deve ser executado em menos de três segundos no meu laptop t < 2^30, o que significa que, se você estiver executando uma simulação, deverá ajustar o timestep de acordo. Se você planeja atingir o limite de 3 segundos para cada caso de teste, verifique se existe um parâmetro ajustável que possa torná-lo mais preciso / menos preciso para ganhos de velocidade, para que eu possa executá-lo em três segundos no meu computador.

Saída : x y z, a posição após o tempo t.

Como o problema de dois corpos pode ser resolvido perfeitamente, é possível, em teoria, obter uma resposta perfeita e correta.

Pontuação : para qualquer caso de teste, o erro é definido como a distância entre a saída e a saída "true". A saída verdadeira é definida como aquela que o trecho de caso de teste gera. Se o erro for menor que 10^(-8), o erro será arredondado para zero. Sua pontuação é o erro médio em 100 (ou mais) casos de teste aleatórios. Se você escrever uma resposta perfeitamente precisa, receberá uma pontuação 0; a pontuação mais baixa vence e os empates serão interrompidos pelo tamanho do código.

Casos de teste :

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

Nesse caso, a órbita é perfeitamente circular com o período 2 * pi; portanto, depois de circular 159154943 vezes, o gato termina em aproximadamente (0,83789, -0,54584). Este não é um caso de teste em que seu código será testado; se você enviar uma resposta perfeitamente precisa, no entanto, convém testá-la.

O trecho abaixo gera casos de teste adicionais aleatórios e será usado para julgar envios; deixe-me saber se há um erro com isso:


O tempo é tdado em segundos? Nesse caso, a velocidade seria dada em unidades por segundo ou algo menor?
R. Kap

@R. Kap Não importa. té dado em tempo unitário, seja o que for, e a velocidade usará a mesma unidade. Seja em segundos ou horas, a resposta será a mesma.
soktinpk

nearly massless catBem, qual seria a massa exata do gato? Devemos apenas usar 0como um valor para a massa deste gato?
R. Kap

@R. Kap Sim. Mas ainda é afetado pela gravidade (normalmente, Newton não considerava objetos sem massa afetados pela gravidade). Portanto, devemos considerar que ela possui massa arbitrariamente pequena, e sua resposta é realmente a posição em que a massa do gato chega a zero. O ponto principal é que o próprio planeta não é afetado pelo gato.
precisa saber é o seguinte

2
@soktinpk, pode ser mais fácil dizer explicitamente que o corpo central é fixo.
Maltysen 04/04

Respostas:


6

Python 3.5 + NumPy, exato, 186 bytes

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

Esta é uma solução exata, usando uma fórmula que eu desenvolvi com base em Jesper Göranssonhis, “Simetrias do problema de Kepler”, 2015 . Ele usa uma pesquisa binária para resolver a equação transcendental Ax + B cos x + C sin x = D, que não possui solução de forma fechada.

A função espera que a posição e a velocidade sejam passadas como matrizes 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])

O que @faz?
R. Kap

1
É um novo operador no Python 3.5 que o NumPy sobrecarrega numpy.dot(multiplicação de produtos por ponto / matriz). Veja PEP 465.
Anders Kaseorg

É ótimo jogar golfe, mas isso é um desafio ao código, você poderia deixar um pouco mais claro, eu fiz algumas modificações em Python e posso calcular a anomalia, teta, excentricidade, período, etc., mas estou decidido a determinar o sinal de teta e determinando a rotação do plano de referência xy para o espaço 3d. Ainda assim, isso é realmente ótimo
milhas

@miles Como os empates são quebrados pelo tamanho do código, faz sentido que isso seja praticado.
Mego

Isso é verdade, já que eu estava trabalhando em uma solução exata, já que o gerador de casos de teste cria apenas órbitas elípticas
milhas

2

Javascript

Isso é apenas para fazer a bola rolar, já que ninguém parece postar respostas. Aqui está uma maneira simples e muito ingênua que pode ser melhorada bastante:

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];
}

Teste:

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

Ei, isso é muito bom. Ele possui um erro de aproximadamente 3.333 * 10 ^ (- 6), que não é suficiente para ser arredondado para baixo ... está próximo.

Apenas por diversão:

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

Ah bem; então não é o melhor.

E em um caso de teste aleatório do gerador:

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]

Com um erro de apenas aproximadamente 0,32305!

Isso pode ser melhorado muito usando algo como a integração Verlet ou algum algoritmo sofisticado. De fato, esses algoritmos podem até obter pontuações perfeitas, apesar de serem simulações.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.