Next: Funções e Variáveis Definidas para polinômios ortogonais, Previous: orthopoly, Up: orthopoly [Contents][Index]

### 65.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).

#### 65.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, você 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 seção see Avaliação em Ponto Flutuante para maiores informaçõesfor more information.

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 você 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

#### 65.1.2 Limitations

Quando uma expressão envolve muitos polinômios ortogonais com ordens simbólicas, é possível que a expressão atualmente tenda para zero, e ainda ocorre também que Maxima estar incapacitado de simplificar essa expressão para zero. Se você faz uma divisão por tal quantidade que tende a zero, você pode estar 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, algorítmos especializados em ponto flutuante são usados para avaliação.

A função `float` do Maxima é até certo ponto indiscriminada; se você 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, você 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 você 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

#### 65.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 coleçã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 atual 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 atual é é 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 usuário 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)

#### 65.1.4 Gráficos e `orthopoly`

Para montar gráficos de expressões que envolvem polinômios ortogonais, você deve azer 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; conseqüê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)

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)`.

#### 65.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

Vocêprecisa 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 fatores 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 diretamente.

    (%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 você precisa de uma função de unidade de passo que é ou contínua à esquerda ou contínua à direita em zero, defina sua própria função de unidade de passo 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.

#### 65.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.

Next: Funções e Variáveis Definidas para polinômios ortogonais, Previous: orthopoly, Up: orthopoly [Contents][Index]