Каждый цикл возвращает результат - PullRequest
0 голосов
/ 14 ноября 2009

Я новичок, и у меня возникла проблема, иди прямо сейчас.

Вот код:

n=3   #time step
#f, v and r are arrays,eg [3,4,5]
#r,v,f all have initial array which is when n=0
def force():
    r=position()
    f=r*2
    return f

def position(n):
    v=velocity(n)
    for i in range(n):    #This part may wrong...
        r=v*i             #How can I return results when i=0,1...5?
    return r

def velocity(n):
    f=force
    for i in range(n):
        v=f*i              #Same problem here.....
    return v

Другая проблема - сила. Это функция положения, которая является функцией скорости, а скорость является функцией силы. Итак, это своего рода логический цикл. Я не могу даже Начните. Физически он должен начинаться с силы в момент времени = 0, а затем продолжать цикл. Но я просто не знаю, как это сделать в Python. Кроме того, как я могу сделать строку r, v результатами с течением времени?

Ответы [ 4 ]

4 голосов
/ 14 ноября 2009

Вы можете использовать доходность.

<code>
def velocity(n):
  f=force
  for i in range(n):
    v=f*i
    yield(v)</p>

<p>for vel in velocity(n):
  //do something

Один рабочий пример. Он напечатает вывод теста функции, как только получит результат. Поэтому вам не нужно ждать следующей итерации цикла.

<code>
import time
def test():
  for i in range(10):
    time.sleep(i)
    yield(i)</p>

<p>for k in test():
  print k
2 голосов
/ 14 ноября 2009

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

Этот пример для мяча на пружине, к которому, я думаю, вы стремитесь. Я являюсь примером, мои начальные условия - бросать по диагонали вдоль оси xz, и я также включил гравитацию (если вы не намеревались использовать векторы, вы можете просто заменить все векторные величины скалярами, например, t, x , v = 0, 0, 2; и т. д.)

from numpy import *

# set the start conditions, etc.
n_timesteps = 100
dt, m, k = .1, 1., 2. # timestep, mass, spring-const (I'll write the equations correctly so the units make sense)
t, x, v = 0., array([0.,0.,0.]), array([2., 0., 2.])  # initial values
gravity = array([0., 0., -9.8])  # to make the problem a little more interesting
result = zeros((4, n_timesteps))

# run the simulation, looping through the timesteps
for n in range(n_timesteps):
    # do the calculation
    f = -k*x + gravity
    a = f/m
    v += a*dt
    x += v*dt
    # store the results
    t += dt  # just for easy record keeping
    result[0,n] = t
    result[1:4, n] = x

Обратите внимание, что цикл for выполняет циклы по временным шагам (а все циклы по векторам обрабатываются с помощью широковещательной трансляции, например, f = -k * x + gravity, что может быть проще?) Также обратите внимание, что сначала устанавливается сила, а затем мы проходим по цепочке интегрирования производных, затем возвращаемся к вершине и снова начинаем с силы. (Вы правы, что это немного асимметрично, и на самом деле мы должны обновлять их все одновременно или что-то в этом роде, и это недостаток метода Эйлера, но он работает достаточно хорошо для небольших временных шагов.)

Вот как выглядят графики ... шар колеблется, как и ожидалось alt text

Редактировать : Чтобы прояснить ваш вопрос: по сути, проблема вашего кода не в том, что вы подразумеваете «запуск функций»; вместо этого ваш код подходит к проблеме неправильно, поэтому вам нужно исправить этот подход. Похоже, вы пытаетесь перебрать свои временные шаги внутри каждой функции. Это неверно! Вместо этого вам нужно выполнить итерацию обтекания через временные шаги, и для каждого временного шага обновлять состояние current каждой переменной, используемой в расчете на этом шаге . Вы можете написать это обновление как отдельную функцию или, например, вы можете сделать это встроенным, как я. Но нет смысла повторять временные шаги в каждой функции вычисления переменной. Вместо этого, чтобы ваш пример имел смысл, force, velocity и другие функции должны иметь в качестве входных данных вещи на текущем временном шаге и возвращать обновление состояния этой переменной, которое будет использоваться на следующем временном шаге. Посмотрите, как мой пример делает это: он просто циклически перебирает временные шаги и в пределах каждого цикла временного шага, он последовательно обновляет все переменные, основывая каждую обновленную переменную на переменных, которые были обновлены непосредственно перед ней в этом текущем * 1030 временный шаг *.

0 голосов
/ 14 ноября 2009

Для добавления в список необходимо использовать append.

def position(n):
    v=velocity(n)
    r = array()
    for i in range(n):    #this part may wrong...
        r.append(v*i)             #how can I return results when i=0,1...5?
    return r
0 голосов
/ 14 ноября 2009

Вы можете использовать понимание списка:

def position(n):
    v=velocity(n)
    return [v*i for i in range(n)]

Или, поскольку вы используете numpy:

v=np.array([1,2,3])
# array([1, 2, 3])

Вы можете использовать цифровую трансляцию, чтобы выразить весь расчет одним ударом:

i=np.arange(5)
# array([0, 1, 2, 3, 4])

v[:]*i[:,np.newaxis]
# array([[ 0,  0,  0],
#        [ 1,  2,  3],
#        [ 2,  4,  6],
#        [ 3,  6,  9],
#        [ 4,  8, 12]])

В приведенном выше расчете скалярные значения в i (например, 0,1,2,3,4) умножаются на массив v. Результаты собираются в двумерный массив с нулевыми значениями. Каждая строка соответствует разному значению i. См. http://www.scipy.org/EricsBroadcastingDoc для ознакомления с бесшумным вещанием.

@ OP: Чтобы ответить на ваш вопрос относительно «логического цикла»: Обычно вы определяете «состояние» системы. Возможно, в вашем случае состояние будет состоять из кортежа (время, позиция, скорость). Затем вы определяете функцию, которой в качестве входных данных присваивается кортеж состояния, а в качестве выходных данных возвращается новый кортеж состояния.

Учитывая (время, положение, скорость), сила может быть вычислена (главным образом из старой позиции). Из силы вы затем вычисляете новую скорость. По скорости вы вычисляете новую позицию.

Не пишите код первым.

В этом случае сядьте с бумагой и карандашом и сделайте расчет вручную на конкретном примере. Делайте достаточно итераций, пока не увидите четко схему выполнения расчета. Каков порядок шагов? Какие части повторяются? Как только вы поймете, как это сделать вручную, станет намного понятнее, как писать код на Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...