Перейти к основному содержимому

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

· 6 мин. чтения

1. Введение

SuanShu — это математическая библиотека Java для численного анализа, статистики, поиска корней, линейной алгебры, оптимизации и многого другого . Одна из вещей, которую он предоставляет, — это функциональность как для действительных, так и для комплексных чисел.

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

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

2. Настройка для Суаншу

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

<dependencies>
<dependency>
<groupId>com.numericalmethod</groupId>
<artifactId>suanshu</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>nm-repo</id>
<name>Numerical Method's Maven Repository</name>
<url>http://repo.numericalmethod.com/maven/</url>
<layout>default</layout>
</repository>
</repositories>

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

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

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

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

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

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.foreach.suanshu.SuanShuMath.addingIncorrectVectors(SuanShuMath.java:21)
at com.foreach.suanshu.SuanShuMath.main(SuanShuMath.java:8)

4. Работа с матрицами

В дополнение к векторам библиотека также обеспечивает поддержку матричных операций. Подобно векторам, матрицы поддерживаются в плотном и разреженном формате, а также для действительных и комплексных чисел.

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.foreach.suanshu.SuanShuMath.multiplyIncorrectMatrices(SuanShuMath.java:98)
at com.foreach.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. Решение многочленов

Одной из других областей, для которых SuanShu обеспечивает поддержку, являются полиномы. Он предоставляет методы для оценки полинома, а также для нахождения его корня (входные значения, где полином оценивается как 0).

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

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

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

Как видим, мы начинаем с коэффициента за высшую степень.

5.2. Оценка многочлена

Метод Assessment() можно использовать для оценки многочлена. Это можно сделать для реальных и сложных входных данных.

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<? extends Number> roots = solver.solve(p);
log.info("Finding polynomial roots: {}", roots);
}

Выход:

[-2.0, 1.0]

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

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

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

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