2015-02-24 3 views
1

Я хочу, чтобы решить уравнение, которое я должен решить рекурсивно, я загрузил фотографию формулы (К сожалению, я не знаю, как писать математические формулы здесь!) enter image description here I написал код в Python, как показано ниже:Решая математическое уравнение рекурсивно в Python

import math 
alambda = 1.0 
rho = 0.8 
c = 1.0 
b = rho * c/alambda 
P0 = (1 - (alambda*b)) 
P1 = (1-(alambda*b))*(math.exp(alambda*b) - 1) 

def a(n): 
    a_n = math.exp(-alambda*b) * ((alambda*b)**n)/math.factorial(n) 
    return a_n 

def P(n): 
    P(n) = (P0+P1)*a(n) + sigma(n) 

def sigma(n): 
    j = 2 
    result = 0 
    while j <= n+1: 
     result = result + P(j)*a(n+1-j) 
     j += 1 
    return result 

Очевидно, что я не смог закончить функцию P. Поэтому, пожалуйста, помогите мне с этим. , когда n = 1 Я должен извлечь P2, когда n = 2, я должен извлечь P3. Кстати, P0 и P1 записаны в строках 6 и 7. Когда я называю P (5), я хочу видеть P (0), P (1), P (2), P (3), P (4), P (5), P (6) на выходе.

+1

Вам нужна интуитивная ценность. В противном случае эта серия будет бесконечно проходить. В принципе, скажите мне значения P (0) и P (1). –

+0

Я бы сказал, что ваш лучший выбор будет заключаться в том, чтобы ваши «P-s» были списком, к которому добавлена ​​ваша функция; 'p (n) = pvals [n]' зависит от 'p (n-1) = pvals [n-1]'. Не в буквальном смысле рекурсивный, но с использованием рекурсивной логики. – Schilcote

+0

@MalikBrahimi, Thats right. Внутренние значения написаны в строках 6 и 7. –

ответ

2

Вам необходимо реорганизовать формулу, чтобы вам не приходилось вычислять P (3) для вычисления P (2). Это довольно легко сделать, введя последний член суммирования P (n + 1) a (0) в левую часть уравнения и разделив его на a (0). Тогда у вас есть формула для P (n + 1) через P (m), где m < = n, которая разрешима рекурсией.

Как отмечает Брюс, лучше всего кэшировать промежуточные результаты для P (n), сохраняя их в dict, чтобы: a) вам не приходилось пересчитывать P (2) и т. Д. Каждый раз, когда вам это нужно, и b) после получения значения P (n) вы можете просто распечатать dict, чтобы увидеть все значения P (m), где m < = n.

import math 
a_lambda = 1.0 
rho = 0.8 
c = 1.0 
b = rho * c/a_lambda 
p0 = (1 - (a_lambda*b)) 
p1 = (1-(a_lambda*b))*(math.exp(a_lambda*b) - 1) 
p_dict = {0: p0, 1: p1} 

def a(n): 
    return math.exp(-a_lambda*b) * ((a_lambda*b)**n)/math.factorial(n) 

def get_nth_p(n, p_dict): 
    # return pre-calculated value if p(n) is already known 
    if n in p_dict: 
     return p_dict[n] 

    # Calculate p(n) using modified formula 
    p_n = ((get_nth_p(n-1, p_dict) 
      - (get_nth_p(0, p_dict) + get_nth_p(1, p_dict)) * a(n - 1) 
      - sum(get_nth_p(j, p_dict) * a(n + 1 - j) for j in xrange(2, n))) 
     /a(0)) 

    # Save computed value into the dict 
    p_dict[n] = p_n 
    return p_n 

get_nth_p(6, p_dict) 
print p_dict 

Edit 2

Некоторые косметические обновления в коде - укорочение имя и делает p_dict в mutable default argument (что-то я стараюсь использовать только экономно) действительно делает код более удобочитаемым:

import math 

# Customary to distinguish variables that are unchanging by making them ALLCAP 
A_LAMBDA = 1.0 
RHO = 0.8 
C = 1.0 
B = RHO * C/A_LAMBDA 
P0 = (1 - (A_LAMBDA*B)) 
P1 = (1-(A_LAMBDA*B))*(math.exp(A_LAMBDA*B) - 1) 

p_value_cache = {0: P0, 1: P1} 

def a(n): 
    return math.exp(-A_LAMBDA*B) * ((A_LAMBDA*B)**n)/math.factorial(n) 

def p(n, p_dict=p_value_cache): 
    # return pre-calculated value if p(n) is already known 
    if n in p_dict: 
     return p_dict[n] 

    # Calculate p(n) using modified formula 
    p_n = ((p(n-1) 
      - (p(0) + p(1)) * a(n - 1) 
      - sum(p(j) * a(n + 1 - j) for j in xrange(2, n))) 
     /a(0)) 

    # Save computed value into the dict 
    p_dict[n] = p_n 
    return p_n 

p(6) 
print p_value_cache 
0

Вы могли бы исправить, если таким образом:

import math 
alambda = 1.0 
rho = 0.8 
c = 1.0 
b = rho * c/alambda 


def a(n): 
    # you might want to cache a as well 
    a_n = math.exp(-alambda*b) * ((alambda*b)**n)/math.factorial(n) 
    return a_n 


PCache={0:(1 - (alambda*b)),1:(1-(alambda*b))*(math.exp(alambda*b) - 1)} 

def P(n): 
if n in PCache: 
    return PCache[n] 
ret= (P(0)+P(1))*a(n) + sigma(n) 
PCache[n]=ret 
return ret 

def sigma(n): 
    # caching this seems smart as well 
    j = 2 
    result = 0 
    while j <= n+1: 
    result = result + P(j)*a(n+1-j) 
    j += 1 
    return result 

void displayP(n): 
    P(n) # fill cache :-) 
    for x in range(n): 
    print ("%u -> %d\n" % (x,PCache[x])) 

Вместо управление кэшем вручную, вы можете использовать memoize декоратора (см http://www.python-course.eu/python3_memoization.php)

Примечание:

  • не но вы должны получить за это идею.
  • Ваш рекуррент не будет работать P (n) зависит от P (n + 1) на вашем уравнении ... Это никогда не закончится
  • Похоже, я неправильно понял P0 и P1 как обе константы (большие числа) и результаты (небольшие числа, индексы) ... Обозначение не самый лучший выбор. ...
+0

Gee! Вы сделали это немного сложнее для меня, я не профессиональный пользователь Python. Поэтому я не знаю, что такое кеш и пустота. –

+0

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