2014-11-21 5 views
1

В настоящее время я пытаюсь проанализировать данные временных рядов с помощью Python. В качестве ориентира для этого я ориентировался на сценарий MATLAB, который делает почти все, что я хотел бы сделать. До сих пор это работало нормально, но теперь я столкнулся с этим полиномом Лежандра, который использовался в этом скрипте.Python эквивалент функции Legendre MATLAB

Я попробовал NumPy implementation, но не смог найти способ, который (более или менее) дал те же результаты, что и the MATLAB function.

В принципе, это то, что я хотел бы знать. Как я могу сделать код Python таким же, как и код MATLAB?

В небольшой демонстрации,

k= [0 1 1;1 1 0 ;0 0 1] 
    legendre(2,k) 

дает:

ans(:,:,1) = 

-0.5000 1.0000 -0.5000 
0   0   0 
3.0000   0 3.0000 


ans(:,:,2) = 

1.0000 1.0000 -0.5000 
    0   0   0 
    0   0 3.0000 


ans(:,:,3) = 

1.0000 -0.5000 1.0000 
    0   0   0 
    0 3.0000   0 

В то время как моя версия Python из него выходит так: как я попробовал это выглядит так:

legendre = np.polynomial.legendre.Legendre([0,1,2]) 
    legendre(k) 

И дает:

array([[-1., 3., 3.], 
    [ 3., 3., -1.], 
    [-1., -1., 3.]]) 

Я вижу несколько вещей, которые немного странны, но, к сожалению, я понятия не имею, как их проверить, потому что это первый раз, когда я слышал о такой вещи, как полином Лежандра, и ни документация NumPy, ни Wikipedia большая помощь в понимании этого.

ответ

1

Хорошо, я думаю, что вам не удастся воспроизвести эти резуль таты, используя этот модуль, поскольку суждение по имени касается только полиномов legendre (это решения уравнения легенды, где mu = 0, иначе известный как порядок 0 решения)

Я не знаю, что делать, но, глядя на документацию, ваш ввод вычисляет результаты функций legendre до порядка указанной степени.

В питоне, что вы, кажется, делают это создание состава zeroeth первого и второго Лежандра порядка полиномов

0 * L_0 + 1 * l_1 + 2 * l_2

вы можете оценить Лежандра многочлены в точках, указанных:

l0 = np.polynomial.legendre.Legendre([0,1]) 

и вы можете убедиться в том, что

l0(0.5) == 0.5 

Я надеюсь, что это полезно - не стесняйтесь задавать больше вопросов

Edit:

def coefficients(order): 
    for i in range(1, order): 
     base = np.zeros(order) 
     base[i] = 1 
     yield base 

def a(n, m): 
    return 1.0*(2*n+1)/((n*(n+1))**m) 

def g(const_dist, m, order): 
    legendres = [np.polynomial.legendre.Legendre(n) for n in coefficients(order)] 
    terms = [a(n+1,m)*legendres[n](const_dist) for n,_ in enumerate(legendres)] 
    return sum(terms) 


>>> g(0.4, 4, 6) 
0.073845698737654328 

Я надеюсь, что это работает для вас, дайте мне знать, если я перепутались что-то

+0

Спасибо, я понимаю это сейчас немного лучше. Итак, чтобы имитировать легендарный matlab в python, я не могу использовать этот модуль, но мне нужно будет написать свою собственную функцию legendre? Считаете ли вы, что достаточно (и выполнимо) поставить формулу Родригеса (см. Wiki) в python, чтобы я мог создавать многочлены отдельно и оценивать каждую из них в определенных точках? Btw. формула, которую мне действительно нужно перевести, является первой на слайде 14 в этом [pdf] (http://jallen.faculty.arizona.edu/sites/jallen.faculty.arizona.edu/files/Chapter_22_Surface_Laplacian.pdf). Любые идеи, как это сделать? – userE

+0

На самом деле, я думаю, что здесь достаточно модуля python, поскольку вы только рассчитываете вычислять легендарные полиномы, а не легендарные функции. Я попытаюсь добавить возможный расчет этой функции к моему ответу. – user3684792

+0

Есть ли причина, по которой вы выбрали «заказ» как «6» и «m» как «4»? Разве это не нормальный случай, когда вы берете каждый полином до последнего, или я ничего не получаю? – userE

1

@ user3684792 Спасибо для кода, но это не совсем то, что необходимо, например cosdist обычно является матрицей, так что sum(terms) не хватит (легко исправить).

Основываясь на ваших комментариях и this определениях многочленов Legrande, я попробовал это сам. То, что я закончил, - это этот код. Могу ли я попросить ваше мнение об этом?

def P(n,x): 
     if n == 0: 
      return 1 
     elif n==1: 
      return x 
     elif n>1: 
      return (2*n-1)/n * x * P(n-1,x) - (n-1)/n * P(n-2,x) 

    #some example data 
    order = 4 
    cosdist= np.array(((0.4,0.1),(-0.2,0.3))) 
    m = 3 
    dim1_cosdist, dim2_cosdist = cosdist.shape 

    Gf = np.zeros((order, dim1_cosdist, dim2_cosdist)) 
    for n in range(1,order): 
     Gf[n] = 1.0*(2*n+1)/((n*(n+1))**m) * P(n,cosdist) 

    G = np.sum(Gf,axis = 0) 

В случае, если cosdist является целым числом, этот скрипт дает те же результаты, что и ваш. Меня раздражает то, что эти результаты все еще несколько отличаются от результатов, полученных в результате кода Matlab, т. Е. Результирующий массив имеет даже разные размеры. Спасибо. Редактировать: случайно, я смутил m с order. Теперь это должно быть правильно

+0

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

+0

Я согласен с тем, что, вероятно, лучше рассчитать это со связностью как матрицей, но при условии, что матрица представляет собой всего лишь набор коэффициентов (например, числа), вы можете фактически вычислить Gij, запустив уравнение для каждого из кодирусованных чисел Ij. – user3684792

+0

по размеру, вы можете проверить здравомыслие, убедившись, что Gij имеет те же размеры, что и Codistance ij. Обратите внимание, что размеры отличаются от вашего кода matlab. Я помню, когда я просматривал эту функцию, впервые увидел, что она также вычисляет функции legendre, так что это может быть то, что вы также видите там (что, если да, это не то, что вы хотите увидеть). – user3684792

1

SciPy имеет associated Legendre polynomials. Это не то же самое, что версия MATLAB, но она должна обеспечить большую часть того, что вы хотите.

3

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

legendre(10,linspace(-1,1,10)) 

И мне нужно, чтобы произвести эквивалент в Python. Вот код:

import numpy as np 
from scipy import special as sp 

def legendre(N,X) : 
    matrixReturn = np.zeros((N+1,X.shape[0])) 
    for i in enumerate(X) : 
     currValues = sp.lpmn(N,N,i[1]) 
     matrixReturn[:,i[0]] = np.array([j[N] for j in currValues[0]]) 
    return matrixReturn 

Я очень новичок в Python, поэтому я уверен, что вышеупомянутое может быть улучшено.

1

У меня была такая же проблема и была успешной с созданием следующих:

from scipy import special 

def legendre(n,X) : 
res = [] 
for m in range(n+1): 
    res.append(special.lpmv(m,n,X)) 
return res 

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

Смежные вопросы