Introdução ao Apache Commons Math
1. Visão geral
Freqüentemente, precisamos usar ferramentas matemáticas e às vezesjava.lang.Math simplesmente não é suficiente. Felizmente, o Apache Commons tem o objetivo de preencher os vazamentos da biblioteca padrão, comApache Commons Math.
O Apache Commons Math é a maior biblioteca de código aberto de funções e utilitários matemáticos para Java. Como este artigo é apenas uma introdução, forneceremos apenas uma visão geral da biblioteca e apresentaremos os casos de uso mais atraentes.
2. Começando com Apache Commons Math
2.1. Os usos do Apache Commons Math
O Apache Commons Math consiste em funções matemáticas (erf, por exemplo), estruturas que representam conceitos matemáticos (como números complexos, polinômios, vetores, etc.) e algoritmos que podemos aplicar a essas estruturas (localização de raiz, otimização, curva ajuste, cálculo de interseções de figuras geométricas, etc.).
2.2. Configuração do Maven
Se você estiver usando o Maven, basta adicionarthis dependency:
org.apache.commons
commons-math3
3.6.1
2.3. Visão geral do pacote
O Apache Commons Math está dividido em vários pacotes:
-
org.apache.commons.math3.stat – estatísticas e testes estatísticos
-
org.apache.commons.math3.distribution – distribuições de probabilidade
-
org.apache.commons.math3.random – números aleatórios, strings e geração de dados
-
org.apache.commons.math3.analysis – descoberta de raiz, integração, interpolação, polinômios, etc.
-
Matrizesorg.apache.commons.math3.linear –, resolvendo sistemas lineares
-
Geometriaorg.apache.commons.math3.geometry – (espaços euclidianos e partição de espaço binário)
-
Métodos de transformaçãoorg.apache.commons.math3.transform – (Fourier rápido)
-
org.apache.commons.math3.ode – integração de equações diferenciais ordinárias
-
org.apache.commons.math3.fitting – ajuste da curva
-
org.apache.commons.math3.optim – maximização ou minimização da função
-
org.apache.commons.math3.genetics – algoritmos genéticos
-
org.apache.commons.math3.ml – aprendizado de máquina (cluster e redes neurais)
-
org.apache.commons.math3.util – funções matemáticas / estatísticas comuns estendendo java.lang.Math
-
org.apache.commons.math3.special – funções especiais (Gama, Beta)
-
org.apache.commons.math3.complex – números complexos
-
org.apache.commons.math3.fraction – números racionais
3. Estatísticas, probabilidades e aleatoriedade
3.1. Estatisticas
O pacoteorg.apache.commons.math3.stat fornece várias ferramentas para cálculos estatísticos. Por exemplo, para calcular a média, o desvio padrão e muitos mais, podemos usarDescriptiveStatistics:
double[] values = new double[] {65, 51 , 16, 11 , 6519, 191 ,0 , 98, 19854, 1, 32};
DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics();
for (double v : values) {
descriptiveStatistics.addValue(v);
}
double mean = descriptiveStatistics.getMean();
double median = descriptiveStatistics.getPercentile(50);
double standardDeviation = descriptiveStatistics.getStandardDeviation();
Neste pacote, podemos encontrar ferramentas para calcular a covariância, correlação ou para realizar testes estatísticos (usandoTestUtils).
3.2. Probabilidades e Distribuições
No núcleo do Java,Math.random() pode ser usado para gerar valores aleatórios, mas esses valores são distribuídos uniformemente entre 0 e 1.
Às vezes, queremos produzir um valor aleatório usando uma distribuição mais complexa. Para isso, podemos usar a estrutura fornecida pororg.apache.commons.math3.distribution.
Aqui está como gerar valores aleatórios de acordo com a distribuição normal com a média de 10 e o desvio padrão de 3:
NormalDistribution normalDistribution = new NormalDistribution(10, 3);
double randomValue = normalDistribution.sample();
Ou podemos obter a probabilidadeP(X = x) de obter um valor para distribuições discretas ou a probabilidade cumulativaP(X ⇐ x) para distribuições contínuas.
4. Análise
Funções e algoritmos relacionados à análise podem ser encontrados emorg.apache.commons.math3.analysis.
4.1. Root Finding
Uma raiz é um valor em que uma função tem o valor 0. Commons-Math inclui a implementação de váriosroot-finding algorithms.
Aqui, tentamos encontrar a raiz dev → (v * v) – 2:
UnivariateFunction function = v -> Math.pow(v, 2) - 2;
UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 1.0e-8, 5);
double c = solver.solve(100, function, -10.0, 10.0, 0);
Primeiro, começamos definindo a função, depois definimos o solucionador e configuramos a precisão desejada. Finalmente, chamamos a APIsolve().
A operação de localização de raiz será realizada usando várias iterações, então é uma questão de encontrar um meio-termo entre o tempo de execução e a precisão.
4.2. Calculando Integrais
A integração funciona quase como descoberta de raiz:
UnivariateFunction function = v -> v;
UnivariateIntegrator integrator = new SimpsonIntegrator(1.0e-12, 1.0e-8, 1, 32);
double i = integrator.integrate(100, function, 0, 10);
Começamos definindo uma função, escolhemos um integrador entre osavailable integration solutions existentes, definimos a precisão desejada e, por fim, integramos.
5. Álgebra Linear
Se tivermos um sistema linear de equações sob a forma AX = B, em que A é uma matriz de números reais e B um vetor de números reais - o Commons Math fornece estruturas para representar a matriz e o vetor e também fornece soluções para encontrar o valor de X:
RealMatrix a = new Array2DRowRealMatrix(
new double[][] { { 2, 3, -2 }, { -1, 7, 6 }, { 4, -3, -5 } },
false);
RealVector b = new ArrayRealVector(n
ew double[] { 1, -2, 1 },
false);
DecompositionSolver solver = new LUDecomposition(a).getSolver();
RealVector solution = solver.solve(b);
O caso é bastante simples: definimos uma matriza de uma matriz de matriz de duplas e um vetorb de uma matriz de um vetor.
Em seguida, criamos umLUDecomposition que fornece um solucionador para equações na forma AX = B. Como o próprio nome indica,LUDecomposition depende doLU decomposition e, portanto, funciona apenas com matrizes quadradas.
Para outras matrizes, existem diferentes solucionadores, geralmente resolvendo a equação usando o método dos mínimos quadrados.
6. Geometria
O pacoteorg.apache.commons.math3.geometry fornece várias classes para representar objetos geométricos e várias ferramentas para manipulá-los. É importante notar que este pacote é dividido em subpacotes diferentes, em relação ao tipo de geometria que queremos usar:
É importante notar que este pacote é dividido em subpacotes diferentes, em relação ao tipo de geometria que queremos usar:
-
org.apache.commons.math3.geometry.euclidean.oned – 1D geometria euclidiana
-
org.apache.commons.math3.geometry.euclidean.twod – geometria euclidiana 2D
-
org.apache.commons.math3.geometry.euclidean.threed – geometria euclidiana 3D
-
org.apache.commons.math3.geometry.spherical.oned – geometria esférica 1D
-
org.apache.commons.math3.geometry.spherical.twod – geometria esférica 2D
As classes mais úteis são provavelmenteVector2D,Vector3D,Line eSegment. Eles são usados para representar vetores 2D (ou pontos), vetores 3D, linhas e segmentos, respectivamente.
Ao usar as classes mencionadas acima, é possível realizar alguns cálculos. Por exemplo, o código a seguir executa o cálculo da interseção de duas linhas 2D:
Line l1 = new Line(new Vector2D(0, 0), new Vector2D(1, 1), 0);
Line l2 = new Line(new Vector2D(0, 1), new Vector2D(1, 1.5), 0);
Vector2D intersection = l1.intersection(l2);
Também é possível usar essas estruturas para obter a distância de um ponto a uma linha ou o ponto mais próximo de uma linha a outra linha (em 3D).
7. Otimização, Algoritmos Genéticos e Aprendizado de Máquina
O Commons-Math também fornece algumas ferramentas e algoritmos para tarefas mais complexas relacionadas à otimização e aprendizado de máquina.
7.1. Otimização
A otimização geralmente consiste em minimizar ou maximizar as funções de custo. Algoritmos para otimização podem ser encontrados emorg.apache.commons.math3.optimeorg.apache.commons.math3.optimimization. Inclui algoritmos de otimização linear e não linear.
Podemos notar que existem classes duplicadas nos pacotesoptimeoptimization: o pacoteoptimization está em sua maioria obsoleto e será removido do Commons Math 4.
7.2. Algorítmos genéticos
Os algoritmos genéticos são um tipo de meta-heurística: eles são uma solução para encontrar uma solução aceitável para um problema quando os algoritmos determinísticos são muito lentos. Uma visão geral dos algoritmos genéticos pode ser encontradahere.
O pacoteorg.apache.commons.math3.genetics fornece uma estrutura para realizar cálculos usando algoritmos genéticos. Ele contém uma estrutura que pode ser usada para representar uma população e um cromossomo e algoritmos padrão para executar operações de mutação, cruzamento e seleção.
As seguintes classes fornecem um bom ponto de partida:
-
GeneticAlgorithm – a estrutura do algoritmo genético
-
Population – a interface que representa uma população
-
Chromosome – a interface que representa um cromossomo
7.3. Machine Learning
O aprendizado de máquina no Commons-Math é dividido em duas partes: agrupamento e redes neurais.
A parte de agrupamento consiste em colocar um rótulo nos vetores de acordo com sua similaridade em relação à métrica de distância. Os algoritmos de armazenamento em cluster fornecidos são baseados no algoritmo K-means.
8. Serviços de utilidade pública
8.1. FastMath
FastMath é uma classe estática localizada emorg.apache.commons.math3.utile funcionando exatamente comojava.lang.Math.
Seu objetivo é fornecer, pelo menos as mesmas funções que encontramos emjava.lang.Math, mas com implementações mais rápidas. Portanto, quando um programa depende muito de cálculos matemáticos, é uma boa ideia substituir as chamadas paraMath.sin() (por exemplo) para as chamadasFastMath.sin() para melhorar o desempenho do aplicativo. Por outro lado, observe queFastMath é menos preciso do quejava.lang.Math.
8.2. Funções Comuns e Especiais
Commons-Math fornece funções matemáticas padrão que não são implementadas emjava.lang.Math (como o fatorial). Muitas dessas funções podem ser encontradas nos pacotesorg.apache.commons.math3.specialeorg.apache.commons.math3.util.
Por exemplo, se queremos calcular o fatorial de 10, podemos simplesmente fazer:
long factorial = CombinatorialUtils.factorial(10);
As funções relacionadas à aritmética (gcd,lcm, etc.) podem ser encontradas emArithmeticUtils, e as funções relacionadas à combinatória podem ser encontradas emCombinatorialUtils. Algumas outras funções especiais, comoerf, podem ser acessadas emorg.apache.commons.math3.special.
8.3. Fração e números complexos
Também é possível manipular tipos mais complexos usando commons-math: fração e números complexos. Essas estruturas nos permitem realizar cálculos específicos sobre esse tipo de números.
Em seguida, podemos calcular a soma de duas frações e exibir o resultado como uma representação de string de uma fração (ou seja, sob a forma "a / b"):
Fraction lhs = new Fraction(1, 3);
Fraction rhs = new Fraction(2, 5);
Fraction sum = lhs.add(rhs);
String str = new FractionFormat().format(sum);
Ou podemos calcular rapidamente o poder de números complexos:
Complex first = new Complex(1.0, 3.0);
Complex second = new Complex(2.0, 5.0);
Complex power = first.pow(second);
9. Conclusão
Neste tutorial, apresentamos algumas das coisas interessantes que você pode fazer usando o Apache Commons Math.
Infelizmente, este artigo não pode cobrir todo o campo de análise ou álgebra linear e, portanto, apenas fornece exemplos para as situações mais comuns.
No entanto, para obter mais informações, podemos ler o bem escritodocumentation, que fornece muitos detalhes para todos os aspectos da biblioteca.
E, como sempre, as amostras de código podem ser encontradashere on GitHub.