Введение в Суаншу

Введение в Суаншу

1. Вступление

The SuanShu is a Java math library for numerical analysis, statistics, root finding, linear algebra, optimization, and lots more. Одна из вещей, которые он предоставляет, - это функциональность как для действительных, так и для комплексных чисел.

Существует версия библиотеки с открытым исходным кодом, а также версия, для которой требуется лицензия - с разными формами лицензии: академической, коммерческой и спонсорской.

Обратите внимание, что в приведенных ниже примерах используется лицензионная версия черезpom.xml. Версия с открытым исходным кодом в настоящее время недоступна в репозитории Maven; лицензионная версия требует наличия сервера лицензий. В результате на GitHub нет никаких тестов для этого пакета.

2. Настройка для SuanShu

Начнем с добавления зависимости Maven кpom.xml:


    
        com.numericalmethod
        suanshu
        4.0.0
    


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

3. Работа с векторами

The SuanShu library provides classes for both dense vectors and sparse vectors. Векторdense - это вектор, в котором большинство элементов имеет ненулевое значение, в отличие от вектораsparse, в котором большинство значений имеют нулевое значение.

Реализация вектораdense просто использует массив вещественных / комплексных чисел Java, в то время как реализация вектораsparse использует массив Javaentries, где каждыйentry имеет индекс и действительное / комплексное значение.

Мы можем видеть, как это будет иметь огромное значение в хранении, когда у нас большой вектор, где большинство значений равны нулю. Большинство математических библиотек используют такой подход, когда им необходимо поддерживать векторы больших размеров.

Давайте посмотрим на некоторые из основных векторных операций.

3.1. Добавление векторов

Добавить 2 вектора довольно просто, используя методadd():

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

Результат, который мы увидим:

[6.000000, 6.000000, 6.000000, 6.000000, 6.000000]

Мы также можем добавить одинаковые числа ко всем элементам, используя методadd(double).

3.2. Масштабирование векторов

Масштабирование вектора (т.е. умножение на постоянную) тоже очень просто:

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

Выход:

[2.000000, 4.000000, 6.000000, 8.000000, 10.000000]

3.3. Вектор внутренний продукт

Для вычисления внутреннего произведения двух векторов требуется вызов методаinnerProduct(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. Работа с ошибками

Библиотека проверяет, что векторы, над которыми мы работаем, совместимы с выполняемой нами операцией. Например, добавление вектора размера 2 к вектору размера 3 не должно быть возможным. Поэтому приведенный ниже код должен привести к исключению:

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

И это действительно так - выполнение этого кода приводит к:

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. Работа с матрицами

In addition to vectors, the library also provides support for matrix operations. Как и векторы, матрицы поддерживаются в форматеdense иsparse, а также для действительных и комплексных чисел.

4.1. Добавление матриц

Добавить матрицы так же просто, как работать с векторами:

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. Умножение матриц

Математическая библиотека может использоваться для умножения матриц:

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

Умножение матрицы 2 × 3 на матрицу 3 × 2 приведет к матрице 2 × 2.

И чтобы доказать, что библиотека правильно проверяет размеры матриц, давайте попробуем произвести умножение, которое должно закончиться неудачей:

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

Выполнение этого приведет к следующему выводу.

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. Вычисление обратной матрицы

Вычисление обратной матрицы может быть длительным процессом, выполняемым вручную, но математическая библиотека SuanShu делает это легко:

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

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

Мы можем проверить это, используя библиотеку SuanShu, но умножив матрицу на ее обратную: результатом должна быть единичная матрица. Мы можем сделать это, добавив следующее в метод выше:

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

5. Решение многочленов

One of the other areas the SuanShu provides support for is polynomials. Он предоставляет методы для вычисления многочлена, а также для поиска его корня (входные значения, где многочлен равен 0).

5.1. Создание полинома

Полином можно создать, указав его коэффициенты. Таким образом, многочлен, подобный3x2-5x+1, может быть создан с помощью:

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

Как мы видим, сначала мы начнем с коэффициента для наивысшей степени.

5.2. Вычисление полинома

Для вычисления полинома можно использовать методevaluate(). Это может быть сделано для реальных и сложных входных данных.

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

Результат, который мы увидим:

51.0
-13.000000+2.000000i

5.3. Поиск корней многочлена

Поиск корней многочлена упрощается благодаря математической библиотеке SuanShu. Он предоставляет хорошо известные алгоритмы для определения корней для многочленов различных степеней и на основе наивысшей степени многочлена, класс PolyRoot выбирает лучший метод:

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

Выход:

[-2.0, 1.0]

Таким образом, для этого выборочного полинома было найдено 2 реальных корня: -2 и 1. Естественно, сложные корни также поддерживаются.

6. Заключение

Эта статья - только краткое введение в математическую библиотеку SuanShu.

Как всегда доступен полный исходный код статьиover on GitHub.