Eine Einführung in SuanShu

Eine Einführung in SuanShu

1. Einführung

The SuanShu is a Java math library for numerical analysis, statistics, root finding, linear algebra, optimization, and lots more. Eines der Dinge, die es bietet, ist die Funktionalität sowohl für reelle als auch für komplexe Zahlen.

Es gibt eine Open-Source-Version der Bibliothek sowie eine Version, für die eine Lizenz erforderlich ist - mit verschiedenen Lizenzformen: akademisch, kommerziell und mitwirkend.

Beachten Sie, dass in den folgenden Beispielen die lizenzierte Version überpom.xmlverwendet wird. Die Open-Source-Version ist derzeit nicht in einem Maven-Repository verfügbar. Für die lizenzierte Version muss ein Lizenzserver ausgeführt werden. Daher gibt es in GitHub keine Tests für dieses Paket.

2. Setup für SuanShu

Beginnen wir mit dem Hinzufügen der Maven-Abhängigkeit zupom.xml:


    
        com.numericalmethod
        suanshu
        4.0.0
    


    
        nm-repo
        Numerical Method's Maven Repository
        http://repo.numericalmethod.com/maven/
        default
    

3. Arbeiten mit Vektoren

The SuanShu library provides classes for both dense vectors and sparse vectors. Eindense-Vektor ist ein Vektor, bei dem die meisten Elemente einen Wert ungleich Null haben, im Gegensatz zu einemsparse-Vektor, bei dem die meisten Werte einen Nullwert haben.

Die Implementierung einesdense-Vektors verwendet einfach ein Java-Array von reellen / komplexen Zahlen, während die Implementierung einessparse-Vektors ein Java-Array vonentries verwendet, wobei jedesentry hat ein Index und ein realer / komplexer Wert.

Wir können sehen, wie sich das auf die Speicherung auswirken würde, wenn wir einen großen Vektor haben, bei dem die meisten Werte Null sind. Die meisten mathematischen Bibliotheken verwenden einen solchen Ansatz, wenn sie Vektoren mit großen Größen unterstützen müssen.

Schauen wir uns einige der grundlegenden Vektoroperationen an.

3.1. Vektoren hinzufügen

Das Hinzufügen von 2 Vektoren ist mit der Methodeadd()ziemlich einfach:

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);
}

Die Ausgabe, die wir sehen werden, ist:

[6.000000, 6.000000, 6.000000, 6.000000, 6.000000]

Mit der Methodeadd(double)können wir auch allen Elementen die gleichen Zahlen hinzufügen.

3.2. Skalieren von Vektoren

Skalieren eines Vektors (d. H. Das Multiplizieren mit einer Konstanten ist ebenfalls sehr einfach:

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);
}

Die Ausgabe:

[2.000000, 4.000000, 6.000000, 8.000000, 10.000000]

3.3. Vektor inneres Produkt

Die Berechnung des inneren Produkts von 2 Vektoren erfordert einen Aufruf derinnerProduct(Vector)-Methode:

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. Umgang mit Fehlern

Die Bibliothek überprüft, ob die Vektoren, mit denen wir arbeiten, mit der von uns ausgeführten Operation kompatibel sind. Beispielsweise sollte das Hinzufügen eines Vektors der Größe 2 zu einem Vektor der Größe 3 nicht möglich sein. Der folgende Code sollte also zu einer Ausnahme führen:

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);
}

Tatsächlich führt das Ausführen dieses Codes zu folgenden Ergebnissen:

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. Arbeiten mit Matrizen

In addition to vectors, the library also provides support for matrix operations. Ähnlich wie Vektoren werden Matrizen im Formatdense undsparse sowie für reelle und komplexe Zahlen unterstützt.

4.1. Matrizen hinzufügen

Das Hinzufügen von Matrizen ist genauso einfach wie das Arbeiten mit Vektoren:

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. Matrizen multiplizieren

Mit der Mathematikbibliothek können Matrizen multipliziert werden:

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);
}

Wenn Sie eine 2 × 3-Matrix mit einer 3 × 2-Matrix multiplizieren, erhalten Sie eine 2 × 2-Matrix.

Um zu beweisen, dass die Bibliothek die Matrixgrößen ordnungsgemäß überprüft, versuchen wir, eine Multiplikation durchzuführen, die fehlschlagen sollte:

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);
}

Wenn Sie dies ausführen, erhalten Sie die folgende Ausgabe.

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. Berechnung einer Matrixinverse

Das Berechnen der Inversen einer Matrix kann ein langwieriger Prozess sein, der manuell ausgeführt werden muss. Die SuanShu-Mathematikbibliothek macht es jedoch einfach:

public void inverseMatrix() {
    Matrix m1 = new DenseMatrix(new double[][]{
        {1, 2},
        {3, 4}
    });

    Inverse m2 = new Inverse(m1);
    log.info("Inverting a matrix: {}", m2);
}

Wir können dies mit der SuanShu-Bibliothek überprüfen, aber die Matrix mit ihrer Umkehrung multiplizieren: Das Ergebnis sollte die Identitätsmatrix sein. Wir können dies tun, indem wir der obigen Methode Folgendes hinzufügen:

log.info("Verifying a matrix inverse: {}", m1.multiply(m2));

5. Polynome lösen

One of the other areas the SuanShu provides support for is polynomials. Es bietet Methoden zum Auswerten eines Polynoms, aber auch zum Finden seiner Wurzel (Eingabewerte, bei denen das Polynom 0 ergibt).

5.1. Polynom erstellen

Ein Polynom kann durch Angabe seiner Koeffizienten erzeugt werden. So kann ein Polynom wie3x2-5x+1 erstellt werden mit:

public Polynomial createPolynomial() {
    return new Polynomial(new double[]{3, -5, 1});
}

Wie wir sehen können, beginnen wir mit dem Koeffizienten für den höchsten Grad zuerst.

5.2. Auswertung eines Polynoms

Dieevaluate()-Methode kann verwendet werden, um das Polynom zu bewerten. Dies kann für reale und komplexe Eingaben erfolgen.

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)));
}

Die Ausgabe, die wir sehen werden, ist:

51.0
-13.000000+2.000000i

5.3. Die Wurzeln eines Polynoms finden

Das Finden der Wurzeln eines Polynoms wird durch die SuanShu-Mathematikbibliothek erleichtert. Es bietet bekannte Algorithmen zum Bestimmen der Wurzeln für Polynome unterschiedlichen Grades. Basierend auf dem höchsten Grad des Polynoms wählt die PolyRoot-Klasse die beste Methode:

public void solvePolynomial() {
    Polynomial p = new Polynomial(new double[]{2, 2, -4});
    PolyRootSolver solver = new PolyRoot();
    List roots = solver.solve(p);
    log.info("Finding polynomial roots: {}", roots);
}

Die Ausgabe:

[-2.0, 1.0]

Für dieses Beispielpolynom wurden also 2 reelle Wurzeln gefunden: -2 und 1. Natürlich werden auch komplexe Wurzeln unterstützt.

6. Fazit

Dieser Artikel ist nur eine kurze Einführung in die SuanShu-Mathematikbibliothek.

Wie immer ist der vollständige Quellcode des Artikelsover on GitHub verfügbar.