1. 简介

SuanShu 是一个用于数值分析、统计学、求根、线性代数、优化等领域的 Java 数学库。它不仅支持实数运算,还支持复数运算。

该库提供开源版本和商业授权版本两种形式。商业版本根据用途分为学术版、商业版和贡献者版。不同版本的授权方式有所区别。

⚠️ 注意:本文中的示例使用的是经过 fork 的商业授权版本,并通过 pom.xml 引入。目前开源版本尚未发布到 Maven 中央仓库;而商业版本需要运行一个许可证服务器。因此,GitHub 上并没有针对这个库的单元测试代码。

2. SuanShu 配置

我们首先在项目的 pom.xml 文件中添加以下依赖项:

<dependency>    
    <groupId>io.deephaven</groupId>    
    <artifactId>SuanShu</artifactId>    
    <version>0.1.0</version>    
</dependency>

3. 向量操作

SuanShu 提供了对稠密向量(dense vector)稀疏向量(sparse vector)的支持。

  • ✅ 稠密向量:大多数元素为非零值。
  • ❌ 稀疏向量:大多数元素为零值。

稠密向量底层使用 Java 数组存储实数或复数;而稀疏向量则通过“索引-值”条目(entry)数组进行存储,这样在处理大规模且多数元素为零的向量时能显著节省内存空间。这是许多数学库处理大向量的标准做法。

3.1. 向量相加

两个向量相加非常简单,调用 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. 错误处理机制

SuanShu 在执行向量运算前会自动校验维度是否匹配。例如,试图将长度为 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.baeldung.suanshu.SuanShuMath.addingIncorrectVectors(SuanShuMath.java:21)
    at com.baeldung.suanshu.SuanShuMath.main(SuanShuMath.java:8)

4. 矩阵操作

除了向量外,SuanShu 还提供了完整的矩阵运算支持,包括稠密矩阵和稀疏矩阵,以及实数和复数类型。

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.baeldung.suanshu.SuanShuMath.multiplyIncorrectMatrices(SuanShuMath.java:98)
    at com.baeldung.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);
}

我们可以通过将原矩阵与其逆矩阵相乘来验证结果是否为单位矩阵:

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

5. 多项式求解

SuanShu 还支持多项式的创建、求值和求根。

5.1. 创建多项式

可以通过指定系数来构造一个多项式。例如,构造多项式 3x² - 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<? extends Number> roots = solver.solve(p);
    log.info("Finding polynomial roots: {}", roots);
}

输出结果:

[-2.0, 1.0]

说明该多项式有两个实根:-2 和 1。当然,也支持复数根。

6. 总结

本文只是对 SuanShu 数学库的一个初步介绍。它涵盖了向量、矩阵、多项式等多个方面,功能强大且接口清晰。

一如既往,完整源码可以在 GitHub 上找到。


原始标题:An Introduction to SuanShu