Uma introdução ao SuanShu
1. Introdução
The SuanShu is a Java math library for numerical analysis, statistics, root finding, linear algebra, optimization, and lots more. Uma das coisas que ele fornece é a funcionalidade para números reais e complexos.
Há uma versão de código aberto da biblioteca, bem como uma versão que requer uma licença - com diferentes formas de licença: acadêmica, comercial e de contribuidor.
Observe que os exemplos abaixo usam a versão licenciada por meio depom.xml. A versão de código aberto atualmente não está disponível em um repositório Maven; a versão licenciada exige que um servidor de licenças esteja em execução. Como resultado, não há nenhum teste para este pacote no GitHub.
2. Configuração para SuanShu
Vamos começar adicionando a dependência Maven aopom.xml:
com.numericalmethod
suanshu
4.0.0
nm-repo
Numerical Method's Maven Repository
http://repo.numericalmethod.com/maven/
default
3. Trabalhando com Vetores
The SuanShu library provides classes for both dense vectors and sparse vectors. Um vetordense é um vetor onde a maioria dos elementos tem um valor diferente de zero, ao contrário de um vetorsparse onde a maioria dos valores tem um valor zero.
A implementação de um vetordense simplesmente usa um array Java de números reais / complexos, enquanto a implementação de um vetorsparse usa um array Java deentries, onde cadaentry tem um índice e um valor real / complexo.
Podemos ver como isso faria uma enorme diferença no armazenamento quando temos um vetor grande, onde a maioria dos valores é zero. A maioria das bibliotecas matemáticas usa uma abordagem como essa quando precisa oferecer suporte a vetores de tamanhos grandes.
Vejamos algumas das operações básicas de vetor.
3.1. Adicionando Vetores
Adicionar 2 vetores é bastante simples usando o métodoadd():
public void addingVectors() throws Exception {
Vector v1 = new DenseVector(new double[] {1, 2, 3, 4, 5});
Vector v2 = new DenseVector(new double[] {5, 4, 3, 2, 1});
Vector v3 = v1.add(v2);
log.info("Adding vectors: {}", v3);
}
O resultado que veremos é:
[6.000000, 6.000000, 6.000000, 6.000000, 6.000000]
Também podemos adicionar os mesmos números a todos os elementos usando o métodoadd(double).
3.2. Dimensionamento de vetores
Escalando um vetor (ou seja, multiplicar por uma constante) também é muito fácil:
public void scaleVector() throws Exception {
Vector v1 = new DenseVector(new double[]{1, 2, 3, 4, 5});
Vector v2 = v1.scaled(2.0);
log.info("Scaling a vector: {}", v2);
}
A saída:
[2.000000, 4.000000, 6.000000, 8.000000, 10.000000]
3.3. Produto Interno Vector
Calcular o produto interno de 2 vetores requer uma chamada para o métodoinnerProduct(Vector):
public void innerProductVectors() throws Exception {
Vector v1 = new DenseVector(new double[]{1, 2, 3, 4, 5});
Vector v2 = new DenseVector(new double[]{5, 4, 3, 2, 1});
double inner = v1.innerProduct(v2);
log.info("Vector inner product: {}", inner);
}
3.4. Lidando com Erros
A biblioteca verifica se os vetores em que estamos operando são compatíveis com a operação que estamos executando. Por exemplo, adicionar um vetor de tamanho 2 a um vetor de tamanho 3 não deve ser possível. Portanto, o código abaixo deve resultar em uma exceção:
public void addingIncorrectVectors() throws Exception {
Vector v1 = new DenseVector(new double[] {1, 2, 3});
Vector v2 = new DenseVector(new double[] {5, 4});
Vector v3 = v1.add(v2);
}
E, de fato, sim - executar esse código resulta em:
Exception in thread "main" com.numericalmethod.suanshu.vector.doubles.IsVector$SizeMismatch: vectors do not have the same size: 3 and 2
at com.numericalmethod.suanshu.vector.doubles.IsVector.throwIfNotEqualSize(IsVector.java:101)
at com.numericalmethod.suanshu.vector.doubles.dense.DenseVector.add(DenseVector.java:174)
at com.example.suanshu.SuanShuMath.addingIncorrectVectors(SuanShuMath.java:21)
at com.example.suanshu.SuanShuMath.main(SuanShuMath.java:8)
4. Trabalhando com matrizes
In addition to vectors, the library also provides support for matrix operations. Semelhante a vetores, matrizes são suportadas no formatodenseesparse, e para números reais e complexos.
4.1. Adicionando Matrizes
Adicionar matrizes é tão simples quanto trabalhar com vetores:
public void addingMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{3, 2, 1},
{6, 5, 4}
});
Matrix m3 = m1.add(m2);
log.info("Adding matrices: {}", m3);
}
4.2. Matrizes de multiplicação
A biblioteca matemática pode ser usada para multiplicar matrizes:
public void multiplyMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{1, 4},
{2, 5},
{3, 6}
});
Matrix m3 = m1.multiply(m2);
log.info("Multiplying matrices: {}", m3);
}
Multiplicar uma matriz 2 × 3 por uma matriz 3 × 2 resultará em uma matriz 2 × 2.
E para provar que a biblioteca faz verificações adequadas dos tamanhos das matrizes, vamos tentar fazer uma multiplicação que deve falhar:
public void multiplyIncorrectMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{3, 2, 1},
{6, 5, 4}
});
Matrix m3 = m1.multiply(m2);
}
A execução resultará na seguinte saída.
Exception in thread "main" com.numericalmethod.suanshu.matrix.MatrixMismatchException:
matrix with 3 columns and matrix with 2 rows cannot multiply due to mis-matched dimension
at com.numericalmethod.suanshu.datastructure.DimensionCheck.throwIfIncompatible4Multiplication(DimensionCheck.java:164)
at com.numericalmethod.suanshu.matrix.doubles.matrixtype.dense.DenseMatrix.multiply(DenseMatrix.java:374)
at com.example.suanshu.SuanShuMath.multiplyIncorrectMatrices(SuanShuMath.java:98)
at com.example.suanshu.SuanShuMath.main(SuanShuMath.java:22)
4.3. Calculando uma matriz inversa
Calcular o inverso de uma matriz pode ser um processo demorado, mas a biblioteca de matemática SuanShu facilita:
public void inverseMatrix() {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2},
{3, 4}
});
Inverse m2 = new Inverse(m1);
log.info("Inverting a matrix: {}", m2);
}
Podemos verificar isso usando a biblioteca SuanShu, mas multiplicando a matriz por sua inversa: o resultado deve ser a matriz de identidade. Podemos fazer isso adicionando o seguinte ao método acima:
log.info("Verifying a matrix inverse: {}", m1.multiply(m2));
5. Resolvendo Polinômios
One of the other areas the SuanShu provides support for is polynomials. Fornece métodos para avaliar um polinômio, mas também para encontrar sua raiz (valores de entrada onde o polinômio é avaliado como 0).
5.1. Criando um polinômio
Um polinômio pode ser criado especificando seus coeficientes. Portanto, um polinômio como3x2-5x+1 pode ser criado com:
public Polynomial createPolynomial() {
return new Polynomial(new double[]{3, -5, 1});
}
Como podemos ver, começamos com o coeficiente do mais alto grau primeiro.
5.2. Avaliando um polinômio
O métodoevaluate() pode ser usado para avaliar o polinômio. Isso pode ser feito para entradas reais e complexas.
public void evaluatePolynomial(Polynomial p) {
log.info("Evaluating a polynomial using a real number: {}", p.evaluate(5));
log.info("Evaluating a polynomial using a complex number: {}", p.evaluate(new Complex(1, 2)));
}
O resultado que veremos é:
51.0
-13.000000+2.000000i
5.3. Encontrando as raízes de um polinômio
Encontrar as raízes de um polinômio é facilitado pela biblioteca de matemática SuanShu. Ele fornece algoritmos conhecidos para determinar as raízes de polinômios de vários graus e, com base no grau mais alto do polinômio, a classe PolyRoot escolhe o melhor método:
public void solvePolynomial() {
Polynomial p = new Polynomial(new double[]{2, 2, -4});
PolyRootSolver solver = new PolyRoot();
List extends Number> roots = solver.solve(p);
log.info("Finding polynomial roots: {}", roots);
}
A saída:
[-2.0, 1.0]
Então, 2 raízes reais foram encontradas para este polinômio da amostra: -2 e 1. Naturalmente, raízes complexas também são suportadas.
6. Conclusão
Este artigo é apenas uma breve introdução à biblioteca de matemática SuanShu.
Como sempre, o código-fonte completo do artigo está disponívelover on GitHub.