Próximo: , Anterior:   [Conteúdo][Índice]

61, orthopoly


61.1, Introdução a polinómios ortogonais

orthopoly é um pacote para avaliação simbólica e numérica de muitos tipos de polinómios ortogonais, incluindo polinómios de Chebyshev, Laguerre, Hermite, Jacobi, Legendre, e ultraesférico (Gegenbauer). Adicionalmentey, orthopoly inclui suporte funções esféricas segundo o critério de Bessel, esféricas segundo o critério de Hankel, e funções harmônica esféricas.

Em sua maior parte, orthopoly segue as convenções de Abramowitz e Stegun Handbook of Mathematical Functions, Chapter 22 (10th printing, December 1972); adicionalmente, usamos Gradshteyn e Ryzhik, Table of Integrals, Series, and Products (1980 corrected and enlarged edition), e Eugen Merzbacher Quantum Mechanics (2nd edition, 1970).

Barton Willis da University de Nebraska e Kearney (UNK) escreveu o pacote orthopoly e sua documetação. O pacote é liberado segundo a licença pública geral GNU (GPL).

61.1.1, Iniciando com orthopoly

load ("orthopoly") torna o pacote orthopoly disponível para uso.

Para encontrar o polinómio de Legendre de terceira ordem,

(%i1) legendre_p (3, x);
                      3             2
             5 (1 - x)    15 (1 - x)
(%o1)      - ---------- + ----------- - 6 (1 - x) + 1
                 2             2

Para expressar esse polinómio como uma soma de potências de x, aplique ratsimp ou rat para o resultado anterior.

(%i2) [ratsimp (%), rat (%)];
                        3           3
                     5 x  - 3 x  5 x  - 3 x
(%o2)/R/            [----------, ----------]
                         2           2

Alternativamente, faça o segundo argumento para legendre_p (sua variável “principal”) uma expressão racional canónica (CRE) usando rat(x) em lugar de somente x.

(%i1) legendre_p (3, rat (x));
                              3
                           5 x  - 3 x
(%o1)/R/                   ----------
                               2

Para avaliação em ponto flutuante, orthopoly usa uma análise de erro durante a execução para estimar uma associação superior para o erro. Por exemplo,

(%i1) jacobi_p (150, 2, 3, 0.2);
(%o1) interval(- 0.062017037936715, 1.533267919277521E-11)

intervalos possuem a forma interval (c, r), onde c é o centro e r é o raio do intervalo. Uma vez que Maxima não suporta aritmética sobre intervalos, em algumas situações, tais como em gráficos, vai querer suprimir o erro e sair somente com o centro do intervalo. Para fazer isso, escolha a variável de opção orthopoly_returns_intervals para false.

(%i1) orthopoly_returns_intervals : false;
(%o1)                         false
(%i2) jacobi_p (150, 2, 3, 0.2);
(%o2)                  - 0.062017037936715

Veja a secção veja Avaliação em Ponto Flutuante para maiores informações.

Muitas funções em orthopoly possuem uma propriedade gradef; dessa forma

(%i1) diff (hermite (n, x), x);
(%o1)                     2 n H     (x)
                               n - 1
(%i2) diff (gen_laguerre (n, a, x), x);
              (a)               (a)
           n L   (x) - (n + a) L     (x) unit_step(n)
              n                 n - 1
(%o2)      ------------------------------------------
                               x

A função de um único passo no segundo exemplo previne um erro que poderia de outra forma surgir através da avaliação de n para 0.

(%i3) ev (%, n = 0);
(%o3)                           0

A propriedade gradef somente aplica para a variável “principal”; dderivadas com relação a outros argumentos usualmente resultam em uma mensagem de erro; por exemplo

(%i1) diff (hermite (n, x), x);
(%o1)                     2 n H     (x)
                               n - 1
(%i2) diff (hermite (n, x), n);

Maxima doesn't know the derivative of hermite with respect the first argument
 -- an error.  Quitting.  To debug this try debugmode(true);

Geralmente, funções em orthopoly mapeiam sobre listas e matrizes. Para o mapeamento para avaliação total, as variáveis de opção doallmxops e listarith devem ambas serem true (o valor padrão). Para ilustrar o mapeamento sobre matrizes, considere

(%i1) hermite (2, x);
                                     2
(%o1)                    - 2 (1 - 2 x )
(%i2) m : matrix ([0, x], [y, 0]);
                            [ 0  x ]
(%o2)                       [      ]
                            [ y  0 ]
(%i3) hermite (2, m);
               [                             2  ]
               [      - 2        - 2 (1 - 2 x ) ]
(%o3)          [                                ]
               [             2                  ]
               [ - 2 (1 - 2 y )       - 2       ]

No segundo exemplo, o elemento i, j do valor é hermite (2, m[i,j]); isso não é o mesmo que calcular -2 + 4 m . m, como visto no próximo exemplo.

(%i4) -2 * matrix ([1, 0], [0, 1]) + 4 * m . m;
                    [ 4 x y - 2      0     ]
(%o4)               [                      ]
                    [     0      4 x y - 2 ]

Se avaliar uma função em um ponto fora do seu domínio, geralmente orthopoly retorna uma função não avaliada. Por exemplo,

(%i1) legendre_p (2/3, x);
(%o1)                        P   (x)
                              2/3

orthopoly suporta tradução em TeX; orthopoly também faz saídas bidimensionais em um terminal.

(%i1) spherical_harmonic (l, m, theta, phi);
                          m
(%o1)                    Y (theta, phi)
                          l
(%i2) tex (%);
$$Y_{l}^{m}\left(\vartheta,\varphi\right)$$
(%o2)                         false
(%i3) jacobi_p (n, a, a - b, x/2);
                          (a, a - b) x
(%o3)                    P          (-)
                          n          2
(%i4) tex (%);
$$P_{n}^{\left(a,a-b\right)}\left({{x}\over{2}}\right)$$
(%o4)                         false

61.1.2, Limitations

Quando uma expressão envolve muitos polinómios ortogonais com ordens simbólicas, é possível que a expressão actualmente tenda para zero, e ainda ocorre também que Maxima estar incapacitado de simplificar essa expressão para zero. Se fizer uma divisão por tal quantidade que tende a zero, poderá ficar em apuros. Por exemplo, a seguinte expressão tende para zero para inteiros n maiores que 1, e ainda ocorre também que Maxima está incapacitado de simplificar essa expressão para zero.

(%i1) (2*n - 1) * legendre_p (n - 1, x) * x - n * legendre_p (n, x) + (1 - n) * legendre_p (n - 2, x);
(%o1)  (2 n - 1) P     (x) x - n P (x) + (1 - n) P     (x)
                  n - 1           n               n - 2

Para um n específico, podemos reduzir a expressão a zero.

(%i2) ev (% ,n = 10, ratsimp);
(%o2)                           0

Geralmente, a forma polinomial de um polinómio ortogonal esteja adequada de forma hostil para avaliaçao em ponto flutuante. Aqui está um exemplo.

(%i1) p : jacobi_p (100, 2, 3, x)$

(%i2) subst (0.2, x, p);
(%o2)                3.4442767023833592E+35
(%i3) jacobi_p (100, 2, 3, 0.2);
(%o3)  interval(0.18413609135169, 6.8990300925815987E-12)
(%i4) float(jacobi_p (100, 2, 3, 2/10));
(%o4)                   0.18413609135169

O verdadeiro valor está em torno de 0.184; ess calculo suporta erro de cancelamento por extremo subtrativo.Expandindo o polinómio e então avaliando, fornecendo um melhor resultado.

(%i5) p : expand(p)$
(%i6) subst (0.2, x, p);
(%o6) 0.18413609766122982

Essa não é uma regra geral; expandindo o polinómio não resulta sempre em expressões que são melhores adaptadas a avaliação numérica. Com grande folga, o melhor caminho para fazer avaliação numérica é fazer um ou mais argumentos da função serem números em ponto flutuante. Em função disso, algoritmos especializados em ponto flutuante são usados para avaliação.

A função float do Maxima é até certo ponto indiscriminada; se aplicar float a uma expressão envolvendo um polinómio ortogonal com um grau simbólico ou um parâmetro de ordem, esses parâmetos (inteiros) podem ser convertido em números em ponto flutuante; após o que, a expressão não irá avaliar completamente. Considere

(%i1) assoc_legendre_p (n, 1, x);
                               1
(%o1)                         P (x)
                               n
(%i2) float (%);
                              1.0
(%o2)                        P   (x)
                              n
(%i3) ev (%, n=2, x=0.9);
                             1.0
(%o3)                       P   (0.9)
                             2

A expressão em (%o3) não irá avaliar para um número em ponto flutuante; orthopoly não reconhece valores em ponto flutuante em lugares onde deve haver valores inteiros. Similarmente, avaliação numérica da função pochhammer para ordens que excedam pochhammer_max_index pode ser perturbador; considere

(%i1) x :  pochhammer (1, 10), pochhammer_max_index : 5;
(%o1)                         (1)
                                 10

Aplicando float não avalia x para um número em ponto flutuante

(%i2) float (x);
(%o2)                       (1.0)
                                 10.0

Para avaliar x para um número em ponto flutuante, irá precisar associar pochhammer_max_index a 11 ou mais e aplicar float a x.

(%i3) float (x), pochhammer_max_index : 11;
(%o3)                       3628800.0

O valor padrão de pochhammer_max_index é 100; modifique esse valor após chama orthopoly.

Finalmente, tenha consciência que os livros citados nas referências adotam diferentes definições de polinómios ortogonais; geralmente adotamos as convenções citadas nas convenções de Abramowitz e Stegun.

Antes de suspeitar de um erro no pacote orthopoly, verifique alguns casos especiais para determinar se suas definições coincidem com aquelas usadas por orthopoly. Definitions muitas vezes diferem por uma normalização; ocasionalmente, autores utilizam versões “modificadas” das funções que fazem a família ortogonal sobre um intervalo diferente do intervalo (-1, 1). Para definir, por exemplo, um polinómio de Legendre que é ortogonal a (0, 1), defina

(%i1) shifted_legendre_p (n, x) := legendre_p (n, 2*x - 1)$

(%i2) shifted_legendre_p (2, rat (x));
                            2
(%o2)/R/                 6 x  - 6 x + 1
(%i3) legendre_p (2, rat (x));
                               2
                            3 x  - 1
(%o3)/R/                    --------
                               2

61.1.3, Avaliação em Ponto Flutuante

Muitas funções em orthopoly utilizam análise de erro durante a execução para estimar o erro em avaliações em ponto flutuante; as exceções são funções de Bessel esféricas e os polinómios associados de Legendre do segundo tipo. Para avaliações numéricas, as funções de Bessel esféricas chamam funções da colecção de programas SLATEC. Nenhum método especializado é usado para avaliação numérica dos polinómios associados de Legendre do segundo tipo.

A análise de erro durante a execução ignora erros que são de segunda ordem ou maior na máquina (também conhecida como perda de algarismos). A análise de erro durante a execução também ignora alguns poucos outros tipos de erro. É possível (embora não provável) que o erro actual exceda o estimado.

Intervalos possuem a forma interval (c, r), onde c é o centro do intervalo e r é seu raio. O centro de um intervalo pode sr um número complexo, e o raio é sempre um número real positivo.

Aqui está um exemplo.

(%i1) fpprec : 50$

(%i2) y0 : jacobi_p (100, 2, 3, 0.2);
(%o2) interval(0.1841360913516871, 6.8990300925815987E-12)
(%i3) y1 : bfloat (jacobi_p (100, 2, 3, 1/5));
(%o3) 1.8413609135168563091370224958913493690868904463668b-1

Vamos testar o quanto o erro actual é é menor que o erro estimado

(%i4) is (abs (part (y0, 1) - y1) < part (y0, 2));
(%o4)                         true

Realmente, por esse exemplo o erro estimado é um maior que o erro verdadeiro.

Maxima não suporta aritmética sobre intervalos.

(%i1) legendre_p (7, 0.1) + legendre_p (8, 0.1);
(%o1) interval(0.18032072148437508, 3.1477135311021797E-15)
        + interval(- 0.19949294375000004, 3.3769353084291579E-15)

Um utilizador pode definir operadores aritméticos que fazem matemática de intervalos. Para definir adição de intervalos, podemos definir

(%i1) infix ("@+")$

(%i2) "@+"(x,y) := interval (part (x, 1) + part (y, 1), part (x, 2) + part (y, 2))$

(%i3) legendre_p (7, 0.1) @+ legendre_p (8, 0.1);
(%o3) interval(- 0.019172222265624955, 6.5246488395313372E-15)

As rotinas eseciais em ponto flutuante são chamadas quando os argumentos forem complexos. Por exemplo,

(%i1) legendre_p (10, 2 + 3.0*%i);
(%o1) interval(- 3.876378825E+7 %i - 6.0787748E+7, 
                                           1.2089173052721777E-6)

Let’s compare this to the true value.

(%i1) float (expand (legendre_p (10, 2 + 3*%i)));
(%o1)          - 3.876378825E+7 %i - 6.0787748E+7

Adicionalmente, quando os argumentos forem grandes números em ponto flutuante, as rotinas especiais de ponto flutuante são chamadas; todavia, tos grandes números em ponto flutuante são convertidos para números em ponto flutuante de dupla precisão e o resultado final é número em ponto flutuante de precisão dupla.

(%i1) ultraspherical (150, 0.5b0, 0.9b0);
(%o1) interval(- 0.043009481257265, 3.3750051301228864E-14)

61.1.4, Gráficos e orthopoly

Para desenhar gráficos de expressões que envolvem polinómios ortogonais, deverá fazer duas coisas:

  1. Escolher a variável de opção orthopoly_returns_intervals para false,
  2. Colocar apóstrofo em qualquer chamada a funções do pacote orthopoly.

Se chamadas a funções não receberem apóstrofo, Maxima irá avaliá-las para polinómios antes de montar o gráfico; consequêntemente, as rotinas especializadas em ponto flutuante não serão chamadas. Aqui está um exemplo de como montar o gráfico de uma expressão que envolve um polinómio de Legendre.

(%i1) plot2d ('(legendre_p (5, x)), [x, 0, 1]), orthopoly_returns_intervals : false;
(%o1)
./figures/orthopoly1

A expressão completa legendre_p (5, x) recebe apóstrofo; isso é diferente de apenas colocar apóstrofo no nome da função usando 'legendre_p (5, x).

61.1.5, Funções Diversas

O pacote orthopoly define o síbolo de Pochhammer e uma função de passo de unidade. orthopoly utiliza a função delta de Kronecker e a função de passo de unidade em declarações gradef.

Para converter os símbolos Pochhammer em quocientes da funções gama, use makegamma.

(%i1) makegamma (pochhammer (x, n));
                          gamma(x + n)
(%o1)                     ------------
                            gamma(x)
(%i2) makegamma (pochhammer (1/2, 1/2));
                                1
(%o2)                       ---------
                            sqrt(%pi)

Derivadas de símbolos de Pochhammer são fornecidas em termos de psi function.

(%i1) diff (pochhammer (x, n), x);
(%o1)             (x)  (psi (x + n) - psi (x))
                     n     0             0
(%i2) diff (pochhammer (x, n), n);
(%o2)                   (x)  psi (x + n)
                           n    0

É preciso ser cuidadoso com expressões como (%o1); a diferença das funções psi possuem polinómios quando x = -1, -2, .., -n. Esses polinómios cacelam-se com factores em pochhammer (x, n) fazendo da derivada um polinómio de grau n - 1 quando n for um inteiro positivo.

O símbolo de Pochhammer é definido de ordens negativas até sua representação como um quociente de funções gama. Considere

(%i1) q : makegamma (pochhammer (x, n));
                          gamma(x + n)
(%o1)                     ------------
                            gamma(x)
(%i2) sublis ([x=11/3, n= -6], q);
                               729
(%o2)                        - ----
                               2240

Alternativamente, podemos tomar ese resultado directamente.

(%i1) pochhammer (11/3, -6);
                               729
(%o1)                        - ----
                               2240

A função passo de unidade é contínua à esquerda; dessa forma

(%i1) [unit_step (-1/10), unit_step (0), unit_step (1/10)];
(%o1)                       [0, 0, 1]

Se precisar de uma função de degrau unitário que seja ou contínua à esquerda ou contínua à direita do zero, defina a sua própria função usando signum; por exemplo,

(%i1) xunit_step (x) := (1 + signum (x))/2$

(%i2) [xunit_step (-1/10), xunit_step (0), xunit_step (1/10)];
                                1
(%o2)                       [0, -, 1]
                                2

Não redefina a própria unit_step; alguns código em orthopoly requerem que a função de passo de unidade seja contínua à esquerda.

61.1.6, Algorítmos

Geralmente, orthopoly faz avaliações simbólicas pelo uso de uma representação hipergeométrica de polinómios ortogonais. As funções hipegeométricas são avaliadas usando as funções (não documetadas) hypergeo11 e hypergeo21. As excessões são as funções de Bessel metade inteiras e a função de Legendre associada de segundo tipo. As funções de Bessel metade inteiras são avaliadas usando uma representação explícita, e a função de Legendre associada de segundo tipo é avaliada usando recursividade.

Para avaliação em ponto flutuante, nós novamente convertemos muitas fuções em uma forma hipergeométrica; nós avaliamos as funções hipergeométricas usando recursividade para frente. Novamente, as excessões são as funções de Bessel metade inteiras e a função de Legendre associada de segundo tipo. Numericamente, as funções de Bessel meio inteiras são avaliadas usando o código SLATEC.


61.2, Definições para polinómios ortogonais

Função: assoc_legendre_p (n, m, x)

As funções de Legendre associadas de primeiro tipo.

Referência: Abramowitz e Stegun, equações 22.5.37, página 779, 8.6.6 (segunda equação), página 334, e 8.2.5, página 333.

Função: assoc_legendre_q (n, m, x)

A função de Legendre associada de segundo tipo.

Referência: Abramowitz e Stegun, equação 8.5.3 e 8.1.8.

Função: chebyshev_t (n, x)

A função de Chebyshev de primeiro tipo.

Referência: Abramowitz e Stegun, equação 22.5.47,página 779.

Função: chebyshev_u (n, x)

A função de Chebyshev do segundo tipo.

Referência: Abramowitz e Stegun, equação 22.5.48,página 779.

Função: gen_laguerre (n, a, x)

O poliômio generalizado de Laguerre.

Referência: Abramowitz e Stegun, equação 22.5.54,página 780.

Função: hermite (n, x)

O polinómio de Hermite.

Referência: Abramowitz e Stegun, equação 22.5.55,página 780.

Função: intervalp (e)

Retorna true se a entrada for um intervalo e retorna false se não for.

Função: jacobi_p (n, a, b, x)

o polinómio de Jacobi.

Os polinómios de Jacobi são actualmente definidos para todo a e b; todavia, o peso do polinómio de Jacobi (1 - x)^a (1 + x)^b não é integrável para a <= -1 ou b <= -1.

Referência: Abramowitz e Stegun, equação 22.5.42,página 779.

Função: laguerre (n, x)

O polinómio de Laguerre.

Referência: Abramowitz e Stegun, equatções 22.5.16 e 22.5.54,página 780.

Função: legendre_p (n, x)

O polinómio de Legendre de primeiro tipo.

Referência: Abramowitz e Stegun, equações 22.5.50 e 22.5.51,página 779.

Função: legendre_q (n, x)

O polinómio de Legendre de primeiro tipo.

Referência: Abramowitz e Stegun, equações 8.5.3 e 8.1.8.

Função: orthopoly_recur (f, args)

Retorna uma relação recursiva para a família de funções ortogonais f com argumentos args. A recursividade é com relação ao grau do polinómio.

(%i1) orthopoly_recur (legendre_p, [n, x]);
                (2 n - 1) P     (x) x + (1 - n) P     (x)
                           n - 1                 n - 2
(%o1)   P (x) = -----------------------------------------
         n                          n

O segundo argumento a orthopoly_recur deve ser uma lista com o número correcto de argumentos para a função f; se o número de argumentos não for o correcto, Maxima sinaliza com um erro.

(%i1) orthopoly_recur (jacobi_p, [n, x]);

Function jacobi_p needs 4 arguments, instead it received 2
 -- an error.  Quitting.  To debug this try debugmode(true);

Adicionalmente, quando f não for o nome de uma das famílias de polinómios ortogonais, um erro é sinalizado.

(%i1) orthopoly_recur (foo, [n, x]);

A recursion relation for foo isn't known to Maxima
 -- an error.  Quitting.  To debug this try debugmode(true);
Variable: orthopoly_returns_intervals

Valor por omissão: true

Quando orthopoly_returns_intervals for true, resultados em ponto flutuante são retornados na forma interval (c, r), onde c é o centro de um intervalo e r é seu raio. O centro pode ser um número complexo; nesse caso, o intervalo é um disco no plano complexo.

Função: orthopoly_weight (f, args)

Retorna uma lista de três elementos; o primeiro elemento é a fórmula do peso para a família de polinómios ortogonais f com argumentos fornecidos pela lista args; os segundos e terceiros elementos fornecem os pontos finais inferior e superior do intervalo de ortogonalidade. Por exemplo,

(%i1) w : orthopoly_weight (hermite, [n, x]);
                            2
                         - x
(%o1)                 [%e    , - inf, inf]
(%i2) integrate (w[1] * hermite (3, x) * hermite (2, x), x, w[2], w[3]);
(%o2)                           0

A variável principal de f deve ser um símbolo; Se não for, Maxima sinaliza com um erro.

Função: pochhammer (n, x)

O símbolo de Pochhammer. Para inteiros não negativos n com n <= pochhammer_max_index, a expressão pochhammer (x, n) avalia para o produto x (x + 1) (x + 2) ... (x + n - 1) when n > 0 e para 1 quando n = 0. Para valores negativos de n, pochhammer (x, n) é definido como (-1)^n / pochhammer (1 - x, -n). Dessa forma

(%i1) pochhammer (x, 3);
(%o1)                   x (x + 1) (x + 2)
(%i2) pochhammer (x, -3);
                                 1
(%o2)               - -----------------------
                      (1 - x) (2 - x) (3 - x)

Para converter um símbolo de Pochhammer em um quociente de funções gama, (veja Abramowitz e Stegun, equação 6.1.22) use makegamma; por exemplo

(%i1) makegamma (pochhammer (x, n));
                          gamma(x + n)
(%o1)                     ------------
                            gamma(x)

Quando n exceder pochhammer_max_index ou quando n for simbólico, pochhammer retorna uma forma substantiva.

(%i1) pochhammer (x, n);
(%o1)                         (x)
                                 n
Variável: pochhammer_max_index

Valor por omissão: 100

pochhammer (n, x) expande para um produto se e somente se n <= pochhammer_max_index.

Exemplos:

(%i1) pochhammer (x, 3), pochhammer_max_index : 3;
(%o1)                   x (x + 1) (x + 2)
(%i2) pochhammer (x, 4), pochhammer_max_index : 3;
(%o2)                         (x)
                                 4

Referência: Abramowitz e Stegun, equação 6.1.16,página 256.

Função: spherical_bessel_j (n, x)

A Função de Bessel esférica de primeiro tipo.

Referência: Abramowitz e Stegun, equações 10.1.8,página 437 e 10.1.15,página 439.

Função: spherical_bessel_y (n, x)

A Função de Bessel esférica de segundo tipo.

Referência: Abramowitz e Stegun, equações 10.1.9,página 437 e 10.1.15,página 439.

Função: spherical_hankel1 (n, x)

A Função de Hankel esférica de primeiro tipo.

Referência: Abramowitz e Stegun, equação 10.1.36,página 439.

Função: spherical_hankel2 (n, x)

A Função de Hankel esférica de segundo tipo.

Referência: Abramowitz e Stegun, equação 10.1.17,página 439.

Função: spherical_harmonic (n, m, x, y)

A função armônica esférica.

Referência: Merzbacher 9.64.

Função: unit_step (x)

A função de passo de unidade contínua à esquerda; dessa forma unit_step (x) tende para x <= 0 e é igual a 1 para x > 0.

Se quiser uma função de degrau unitário que tome o valor 1/2 em zero, use (1 + signum (x))/2.

Função: ultraspherical (n, a, x)

A função polinômial ultraesférica (também conhecida como função polinomial de Gegenbauer).

Referência: Abramowitz e Stegun, equação 22.5.46,página 779.


Próximo: , Anterior:   [Conteúdo][Índice]