[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse capítulo descreve funções para procura de raízes multidimensionais (resolvendo sistemas não lineares com n equações em n incógnitas). A biblioteca fornece componentes de baixo nível para uma variedade de resolvedores iterativos e testes de convergência. Esses resolvedores e testes podem ser combinados pelo usuário para encontrar a solução desejada, com acesso completo aos passos intermediários da iteração. Cada classe de métodos usa a mesma estrutura, de forma que você pode alternar entre resolvedores durante a execução sem precisar recompilar seu programa. Cada instância de um resolvedor mantém registros de seu próprio estado, permitindo aos resolvedores serem usados em programas com suporte a multiplas linhas de execução. Os resolvedores são baseados na bilioteca fortran original MINPACK.
O arquivo de cabeçalho ‘gsl_multiroots.h’ contém protótipos para funções de procura de raízes multidimensionais e declarações relacionadas.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O problema de procura de raízes multidimensionais requer a solução
simultânea de n equações, f_i, em n variáveis,
x_i,
|
|
Muitos algoritmos de procura por raízes estão disponíveis dentro de uma estrutura simples. O usuário fornece um norteador de alto nível para os algoritmos, e a biblioteca fornece as funções individuais necessárias para cada um dos passos. Existem três principais fases da iteração. Os passos são,
A avaliação da matriz de Jacobi pode ser problemática, ou pelo fato de a programação das derivadas é intratável ou pelo fato de a computação dos n^2 termos da matriz torna-se muito dispendiosa. Por essas razões os algoritmos fornecidos pela biblioteca são divididos em duas classes conforme se as derivadas estão disponíveis ou não.
O estado para resolvedores com uma matriz analítica de Jacobi é mantida em uma
estrutura gsl_multiroot_fdfsolver
. O procedimento de atualização requer que
ambas a função e suas derivadas sejam fornecidas pelo usuário.
O estado de resolvedores que não usam uma matriz analítica de Jacobi é
mantido em uma estrutura gsl_multiroot_fsolver
. O procedimento de atualização
usa somente avaliações de função (não derivadas). Os algoritmos
fazem estimativa da matriz J ou J^{-1} por métodos aproximados.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As seguintes funções inicializam um resolvedor multidimensional, ou com ou sem derivadas. O resolvedor propriamente dito depende somente da dimensão do problema e do algoritmo e pode ser reusado para diferentes problemas.
Essa função retorna um apontador para uma instância recentemente alocada de um resolvedor do tipo T para um sistema de n dimensões. Por exemplo, o seguinte código cria uma instância de um resolvedor híbrido, para resolver um sistema tridimensional de equações.
const gsl_multiroot_fsolver_type * T = gsl_multiroot_fsolver_hybrid; gsl_multiroot_fsolver * s = gsl_multiroot_fsolver_alloc (T, 3);
Se não houver memória suficiente para criar o resolvedor então a função
retorna um apontador nulo e o controlador de erro é chamado com um código de
erro de GSL_ENOMEM
.
Essa função retorna um apontador para uma instância recentemente alocada de um resolvedor derivativo do tipo T para um sistema de n dimensões. Por exemplo, o seguinte código cria uma instância de resolvedor Newton-Raphson, para um sistema bidimensional de equações.
const gsl_multiroot_fdfsolver_type * T = gsl_multiroot_fdfsolver_newton; gsl_multiroot_fdfsolver * s = gsl_multiroot_fdfsolver_alloc (T, 2);
Se não houver memória insuficiente para criar o resolvedor então a função
retorna um apontador nulo e o controlador de erro é chamado com um código
de erro GSL_ENOMEM
.
Essas funções ajustam, ou zeram, um resolvedor existente s para usar a função f ou função e derivada fdf (69), e a suposição inicial x. Note que a posição inicial é copiada a partir de x, esse argumento não é modificado por subsequentes iterações.
Essas funções liberam toda a memória associada ao resolvedor s.
Essas funções retornam um apontador para o nome do resolvedor. Por exemplo,
printf ("s é um resolvedor '%s'\n", gsl_multiroot_fdfsolver_name (s));
pode imprimir algo como s é um resolvedor 'newton'
.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Vcê deve fornecer n funções de n variáveis para a rotina de procura de raízes trabalhar sobre essas funções e essas variáveis. Com o objetivo de permitir parâmetros em geral as funções são definidas pelos seguintes tipos de dados:
Esse tipo de dados define um sistema geral de funções com parâmetros.
int (* f) (const gsl_vector * x, void * params, gsl_vector * f)
essa função deve armazenar o vetor resultado f(x,params) em f para o argumento x e parâmetros params, retornando um código de erro apropriado se a função não puder ser calculada.
size_t n
a dimensão do sistema, i.e. o número de componentes dos vetores x e f.
void * params
um apontador para os parâmetros da função.
Aqui está um exemplo usando a função do teste de Powell,
|
gsl_multiroot_function
F
que você deve informar para um
resolvedor:
struct powell_params { double A; }; int powell (gsl_vector * x, void * p, gsl_vector * f) { struct powell_params * params = (struct powell_params *)p; const double A = (params->A); const double x0 = gsl_vector_get(x,0); const double x1 = gsl_vector_get(x,1); gsl_vector_set (f, 0, A * x0 * x1 - 1); gsl_vector_set (f, 1, (exp(-x0) + exp(-x1) - (1.0 + 1.0/A))); return GSL_SUCCESS } gsl_multiroot_function F; struct powell_params params = { 10000.0 }; F.f = &powell; F.n = 2; F.params = ¶ms;
Esse tipo de dados define um sistema geral de funções com parâmetros e a correspondente matriz de Jacobi de derivadas,
int (* f) (const gsl_vector * x, void * params, gsl_vector * f)
essa função deve armazenar o vetor resultado f(x,params) em f para argumento x e parâmetros params, retornando um código de erro apropriado se a função não puder ser calculada.
int (* df) (const gsl_vector * x, void * params, gsl_matrix * J)
essa função deve armazenar a matriz resultado n-por-n J_ij = d f_i(x,params) / d x_j em J para argumento x e parâmetros params, retornando um código de erro apropriado se a função não puder ser calculada.
int (* fdf) (const gsl_vector * x, void * params, gsl_vector * f, gsl_matrix * J)
Essa função deve ajustar os valores de f e J como acima, para argumentos x e parâmetros params. Essa função fornece uma otomização de funções separadas para f(x) e J(x)—essa otimização separada é sempre mais rápido de calcular a função e sua derivada ao mesmo tempo.
size_t n
a dimensão do sistema, i.e. o número de componentes dos vetores x e f.
void * params
um apontador para os parâmetros da função.
O exemplo da função de teste de Powell definida acima pode ser extendida para incluir derivadas analíticas usando o seguinte código,
int powell_df (gsl_vector * x, void * p, gsl_matrix * J) { struct powell_params * params = (struct powell_params *)p; const double A = (params->A); const double x0 = gsl_vector_get(x,0); const double x1 = gsl_vector_get(x,1); gsl_matrix_set (J, 0, 0, A * x1); gsl_matrix_set (J, 0, 1, A * x0); gsl_matrix_set (J, 1, 0, -exp(-x0)); gsl_matrix_set (J, 1, 1, -exp(-x1)); return GSL_SUCCESS } int powell_fdf (gsl_vector * x, void * p, gsl_matrix * f, gsl_matrix * J) { struct powell_params * params = (struct powell_params *)p; const double A = (params->A); const double x0 = gsl_vector_get(x,0); const double x1 = gsl_vector_get(x,1); const double u0 = exp(-x0); const double u1 = exp(-x1); gsl_vector_set (f, 0, A * x0 * x1 - 1); gsl_vector_set (f, 1, u0 + u1 - (1 + 1/A)); gsl_matrix_set (J, 0, 0, A * x1); gsl_matrix_set (J, 0, 1, A * x0); gsl_matrix_set (J, 1, 0, -u0); gsl_matrix_set (J, 1, 1, -u1); return GSL_SUCCESS } gsl_multiroot_function_fdf FDF; FDF.f = &powell_f; FDF.df = &powell_df; FDF.fdf = &powell_fdf; FDF.n = 2; FDF.params = 0;
Note que a função powell_fdf
é capaz de reutilizar termos existentes
da função ao fazer o cálculo da matriz de Jacobi, dessa forma economizando tempo.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As seguintes funções norteiam a iteração de cada algoritmo. Cada função executa uma iteração para atualizar o estado de qualquer resolvedor de tipo correspondente. A mesma função trabalha para todos os resolvedores de forma que diferentes métodos podem ser substituídos durante a execução sem modificações no código.
Essas funções executam uma simples iteração do resolvedor s. Se a iteração encontrar um problema inesperado então um código de erro irá ser retornado,
GSL_EBADFUNC
a iteração encontrou um ponto singular onde a função ou sua
derivada avaliou para Inf
ou para NaN
.
GSL_ENOPROG
a iteração não está fazendo qualquer progresso, evitando que o algoritmo continue trabalhando indefinidamente.
O resolvedor mantém uma atual melhor estimativa da raíz s->x
e seu valor de função s->f
em todas as vezes. Essa informação pode
ser acessada com as seguintes funções auxiliares,
Essas funções retornam a atual estimativa de raíz para o resolvedor s, fornecida por s->x
.
Essas funções retornam o valor de função f(x) na atual
estimativa de raíz para o resolvedor s, fornecida por s->f
.
Essas funções retornam o último passo dx tomado pelo resolvedor
s, fornecido por s->dx
.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Um procedimento de procura de raíz deve parar quando uma das seguintes condições for verdadeira:
A manipulação dessas condições está sob o controle do usuário. As funções abaixo permitem ao usuário testar a precisão do atual resultado de muitas maneiras padronizadas.
Essa função testa a convergência da sequência comparando o
último passo dx com o erro absoluto epsabs e com o erro
relativo epsrel na posição atual x. O teste retorna
GSL_SUCCESS
se a seguinte condição for alcançada,
|
GSL_CONTINUE
de outra forma.
essa função testa o valor do resíduo de f contra o limite de
erro absoluto epsabs. O teste retorna GSL_SUCCESS
se a
seguinte condição for encontrada,
|
GSL_CONTINUE
de outra forma. Esse critério é adequado
para situações onde a precisa localização da raíz, x, é
secundáriamente fornecida um valor pode ser encontrado onde o resíduo seja pequeno
o suficiente.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os algoritmos de procura de raízes descritos nessa seção fazem uso de ambas a função e sua derivada. Eles requerem uma suposição inicial para a localização da raíz, mas não existe garantia absoluta de convergência—a função deve ser adequada a essa técnica e a suposição inicial deve estar suficientemente próxima da raíz para o método funcionar. Quando as condições forem satisfeitas então a convergência é quadrática.
Essa é uma versão modificada do método Híbrido de Powell da forma que foi implementado no algoritmo HYBRJ no pacote MINPACK. O Minpack foi escrito por Jorge J. Moré, Burton S. Garbow e Kenneth E. Hillstrom. O algoritmo Híbrido reté a convergência rápida do método de Newton mas irá também reduzir o resíduo quando o método de Newton for inseguro.
O algoritmo usa uma região de confiabilidade para manter cada passo sob controle. Com o objetivo de ser aceita uma nova posição proposta x' deve satisfazer a condição |D (x' - x)| < \delta, onde D é uma matriz diagonal escalonada e \delta é o tamanho da região de confiabilidade. As componentes de D são calculadas internamente, usando os módulos de coluna do determinante de Jacobi para estimar a sensibilidade do resíduo para cada componente de x. Isso melhora o comportamento do algoritmos para funções péssimamente escalonadas.
A cada iteração o algoritmo primeiramente determina o passo padrão de
Newton resolvendo o sistema J dx = - f. Se esse passo localizar-se dentro
da região de confiabilidade é usado como um passo de teste no estágio seguinte. Se não,
o algoritmo usa a combinação linear de Newton e direções de
coeficiente angular que é previsto para minimizar a norma da função enquanto
aguardando dentro da região de confiabilidade,
|
O passo proposto é agora testado por meio de uma avaliação de função no ponto resultante, x'. Se o passo reduzir a norma da função suficientemente então é aceita e o tamanho da região de confiabilidade é aumentado. Se o passo proposto falha em melhorar a solução então o tamanho da região de confiabilidade é diinuído e outro passo de teste é calculado.
A velocidade do algoritmo é aumentada calculando as mudanças para o determinante de Jacobi aproximadamente, usando uma atualização rank-1 (70). Se duas sucessivas tentativas em reduzir o resíduo o determinante de Jacobi em sua totalidade é recalculada. O algoritmo também monitora o progresso da solução e retorna um erro se muitos passos falharem em fazer qualquer melhoria,
GSL_ENOPROG
a iteração não está fazendo qualquer progresso, evita que o algoritmo continue.
GSL_ENOPROGJ
reavaliações do determinante de Jacobi indicam que a iteração não está fazendo qualquer progresso, evitando que o algoritmo continue.
Esse algoritmo é uma versão não escalonada de hybridsj
. Os passos são
controlados por uma região de confiabilidade esférica |x' - x| < \delta, ao invés de
por uma região generalizada. Pode ser útil se a região generalizada
estimada por hybridsj
seja inapropriada.
O método de Newton é o algoritmo padrão para melhoria de raízes. O algoritmo
inicia-se com uma suposição inicial para a localização da solução. A cada
iteração uma aproximação linear para a função F é usada para
estimar o passo que irá zerar todos os componentes do resíduo.
A iteração é definida pela seguinte sequência,
|
|
GSL_EDOM
é retornado.
Essa é uma versão modificada do método de Newton que tenta melhorar
a convergência global requerendo a cada passo para reduzir o módulo Euclidiano
do resíduo, |f(x)|. Se o passo de Newton levar a um incremento
do módulo Euclideano então um passo reduzido de tamanho relativo,
|
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os algoritmos descritos nessa seção não requerem que quaisquer informações de derivadas sejam fornecidas pelo usuário. Quaisquer derivadas necessárias são aproximadas por meio de diferenças finitas. Note que se o tamanho do passo da diferenciação finita mudado por essas rotinas for inapropriado, uma derivada numérica explícita fornecida pelo usuário pode sempre ser usada com os algoritmos descritos na seção anterior.
Essa é uma versão do algoritmo Híbrido que substitui chamadas à
função de cálculo do determinante de Jacobi por suas aproximações de diferenças finitas. A aproximação
por diferenças finitas é calculado usando gsl_multiroots_fdjac
com um tamanho de passo relativo de GSL_SQRT_DBL_EPSILON
. Note que
esse tamanho de passo não irá ser adequado para todos os problemas.
Essa é uma versão por diferenças finitas do algoritmo Híbrido sem escalonamento interno.
O algoritmo de Newton discreto é o mais simples método de resolver um
sistema multidimensional. Usa uma iteração de Newton
|
|
O algoritmos de Broyden é uma versão do algoritmo discreto
de Newton que tenta evitar atualização dispendiosa da matriz de
Jacobi a cada iteração. As modificações no determinante de Jacobi são também
aproximadas, usando uma atualização posto-1,
|
Essa aproximação fornece uma atualização rápida mas sem confiabilidade se as modificações não forem pequenas, e a estimativa do inverso do determinante de Jacobi torna-se pior com o decorrer do tempo. O algoritmo tem uma tendência a tornar-se instável a menos que comece perto da raíz. O determinante de Jacobi é atualizado se essa instabilidade for detectada (consulte o código fonte para detalhes).
Esse algoritmo é incluído somente com propósitos demonstrativos, e é recomendado seu uso somente para em testes superficiais e eventuais.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os resolvedores multidimensionais são suados de forma similar aos algoritmos
unidimensionais de procura de raízes. O primeiro exemplo
demonstra algoritmo híbrido escalonado, hybrids
, que não
requer derivadas. O rograma resolve o sistema de equaçẽos de Rosenbrock,
|
O primeiro estágio do programa é definir o sistema de equações,
#include <stdlib.h> #include <stdio.h> #include <gsl/gsl_vector.h> #include <gsl/gsl_multiroots.h> struct rparams { double a; double b; }; int rosenbrock_f (const gsl_vector * x, void *params, gsl_vector * f) { double a = ((struct rparams *) params)->a; double b = ((struct rparams *) params)->b; const double x0 = gsl_vector_get (x, 0); const double x1 = gsl_vector_get (x, 1); const double y0 = a * (1 - x0); const double y1 = b * (x1 - x0 * x0); gsl_vector_set (f, 0, y0); gsl_vector_set (f, 1, y1); return GSL_SUCCESS; }
O programa principal inicia criando o objeto de função f
, com
os argumentos (x,y)
e parâmetros (a,b)
. O resolvedor
s
é inicializado para usar essa função, com método
hybrids
.
int main (void) { const gsl_multiroot_fsolver_type *T; gsl_multiroot_fsolver *s; int status; size_t i, iter = 0; const size_t n = 2; struct rparams p = {1.0, 10.0}; gsl_multiroot_function f = {&rosenbrock_f, n, &p}; double x_init[2] = {-10.0, -5.0}; gsl_vector *x = gsl_vector_alloc (n); gsl_vector_set (x, 0, x_init[0]); gsl_vector_set (x, 1, x_init[1]); T = gsl_multiroot_fsolver_hybrids; s = gsl_multiroot_fsolver_alloc (T, 2); gsl_multiroot_fsolver_set (s, &f, x); print_state (iter, s); do { iter++; status = gsl_multiroot_fsolver_iterate (s); print_state (iter, s); if (status) /* check if solver is stuck */ break; status = gsl_multiroot_test_residual (s->f, 1e-7); } while (status == GSL_CONTINUE && iter < 1000); printf ("status = %s\n", gsl_strerror (status)); gsl_multiroot_fsolver_free (s); gsl_vector_free (x); return 0; }
Note que é importante verificar a situação atual de retorno de cada passo de resolvedor, no caso do algoritmo travar. Se uma condição de erro for detectada, indicando que o algoritmo não pode continuar, então o erro pode ser informado ao usuário, um novo ponto de início é escolhido ou um diferente algoritmo usado.
O estado intermediário da solução é mostrado pela seguinte
função. O estado do resolvedor contém o vetor s->x
que é a
posição atual, e o vetor s->f
com os correspondentes valores de
função.
int print_state (size_t iter, gsl_multiroot_fsolver * s) { printf ("iter = %3u x = % .3f % .3f " "f(x) = % .3e % .3e\n", iter, gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), gsl_vector_get (s->f, 0), gsl_vector_get (s->f, 1)); }
Aqui está os resultados de execução do programa. O algoritmo é iniciado em (-10,-5) longe da solução. Uma vez que a solução está escondida em um vale estreito os primeiros passos seguem o coeficiente angular da função morro abaixo, em uma tentativa de reduzir o grande valor do resíduo. Uma vez que a raíz tenha sido aproximadamente localiada, na iteração 8, o comportamento de Newton assume e a convergência é muito rápida.
iter = 0 x = -10.000 -5.000 f(x) = 1.100e+01 -1.050e+03 iter = 1 x = -10.000 -5.000 f(x) = 1.100e+01 -1.050e+03 iter = 2 x = -3.976 24.827 f(x) = 4.976e+00 9.020e+01 iter = 3 x = -3.976 24.827 f(x) = 4.976e+00 9.020e+01 iter = 4 x = -3.976 24.827 f(x) = 4.976e+00 9.020e+01 iter = 5 x = -1.274 -5.680 f(x) = 2.274e+00 -7.302e+01 iter = 6 x = -1.274 -5.680 f(x) = 2.274e+00 -7.302e+01 iter = 7 x = 0.249 0.298 f(x) = 7.511e-01 2.359e+00 iter = 8 x = 0.249 0.298 f(x) = 7.511e-01 2.359e+00 iter = 9 x = 1.000 0.878 f(x) = 1.268e-10 -1.218e+00 iter = 10 x = 1.000 0.989 f(x) = 1.124e-11 -1.080e-01 iter = 11 x = 1.000 1.000 f(x) = 0.000e+00 0.000e+00 status = success
Note que o algoritmo não atualiza a localização a cada iteração. Algumas iterações são usadas para ajustar o parâmetro de região de confiabilidade, após tentar um passo encontrado que era divergente, ou recalcular a matriz de Jacobi, quando comportamento pobre de convergência é detectado.
O programa exemplo seguinte adiciona informações de derivada, com o objetivo de
acelerar a solução. Existem duas funções de derivadas
rosenbrock_df
e rosenbrock_fdf
. O último calcula ambas
a função e sua derivada simultâneamente. Isso permite a
otimização de quaisquer termos comuns. Por simplicidade substituimos chamadas
separadas às funções f
e df
nesse ponto no código
abaixo.
int rosenbrock_df (const gsl_vector * x, void *params, gsl_matrix * J) { const double a = ((struct rparams *) params)->a; const double b = ((struct rparams *) params)->b; const double x0 = gsl_vector_get (x, 0); const double df00 = -a; const double df01 = 0; const double df10 = -2 * b * x0; const double df11 = b; gsl_matrix_set (J, 0, 0, df00); gsl_matrix_set (J, 0, 1, df01); gsl_matrix_set (J, 1, 0, df10); gsl_matrix_set (J, 1, 1, df11); return GSL_SUCCESS; } int rosenbrock_fdf (const gsl_vector * x, void *params, gsl_vector * f, gsl_matrix * J) { rosenbrock_f (x, params, f); rosenbrock_df (x, params, J); return GSL_SUCCESS; }
O programa principal faz chamadas para as correspondentes versões
fdfsolver
das funções,
int main (void) { const gsl_multiroot_fdfsolver_type *T; gsl_multiroot_fdfsolver *s; int status; size_t i, iter = 0; const size_t n = 2; struct rparams p = {1.0, 10.0}; gsl_multiroot_function_fdf f = {&rosenbrock_f, &rosenbrock_df, &rosenbrock_fdf, n, &p}; double x_init[2] = {-10.0, -5.0}; gsl_vector *x = gsl_vector_alloc (n); gsl_vector_set (x, 0, x_init[0]); gsl_vector_set (x, 1, x_init[1]); T = gsl_multiroot_fdfsolver_gnewton; s = gsl_multiroot_fdfsolver_alloc (T, n); gsl_multiroot_fdfsolver_set (s, &f, x); print_state (iter, s); do { iter++; status = gsl_multiroot_fdfsolver_iterate (s); print_state (iter, s); if (status) break; status = gsl_multiroot_test_residual (s->f, 1e-7); } while (status == GSL_CONTINUE && iter < 1000); printf ("status = %s\n", gsl_strerror (status)); gsl_multiroot_fdfsolver_free (s); gsl_vector_free (x); return 0; }
A adição de informações de derivadas para o resolvedor hybrids
não
faz qualquer diferença significativa em seu comportamento, uma vez que o programa está apto a
aproximar o determinante de Jacobi numericamente com suficiente precisão. Para
ilustrar o comportamento de um resolvedor derivativo diferente mudamos para
gnewton
. É um tradicional resolvedor do tipo Newton com a restrição
que escalona de volta seu passo se o passo completo conduzir “morro acima”. Aqui
está a saída para o algoritmo gnewton
,
iter = 0 x = -10.000 -5.000 f(x) = 1.100e+01 -1.050e+03 iter = 1 x = -4.231 -65.317 f(x) = 5.231e+00 -8.321e+02 iter = 2 x = 1.000 -26.358 f(x) = -8.882e-16 -2.736e+02 iter = 3 x = 1.000 1.000 f(x) = -2.220e-16 -4.441e-15 status = success
A convergência é muito mais rápida, mas faz uma grande excursão para fora no ponto (-4.23,-65.3). Isso pode fazer com que o algoritmo extravie em uma aplicação realista. O algoritmo híbrido segue o caminho morro abaixo para a solução mais confiável.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A versão original do método Híbrido é descrito no seguintes artigos de autoria de Powell,
Os seguintes de artigos são relevantes para os algoritmos descritos nessa seção,
[ << ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.