rs-math 0.1.0

This is a math library, a math library written in Rust. Write in a native way as much as possible in this math library, reducing the use of third-party libraries. There may be some errors in this math library, and we hope that users can provide suggestions for modification. I will continue to track related issues when submitting Issues, and if possible, please also participate in my project.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# 为了学好Rust也是拼了系列-数学库-二维矩阵



二维矩阵是数学中的一个重要概念,它是由元素排列成行和列的矩形数组。通常用大写字母表示矩阵,例如 $$A$$,矩阵中的元素用小写字母表示,例如 $$a_{ij}$$,其中 $$i$$ 表示行索引,$$j$$ 表示列索引。

一个二维矩阵 $$A$$ 可以表示为:

$$ A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} $$

这里,$$m$$ 是矩阵的行数,$$n$$ 是矩阵的列数。矩阵的大小通常以 "行数 × 列数" 的形式表示。

例如,一个 2x3 的矩阵可以写作:

$$ B = \begin{bmatrix} b_{11} & b_{12} & b_{13} \\ b_{21} & b_{22} & b_{23} \end{bmatrix} $$

其中,这个矩阵有两行($$m=2$$)和三列($$n=3$$)。

程序定义如下

```
pub struct Matrix {
    rows: usize,    // 行数
    cols: usize,    // 列数
    data: Vec<Vec<f64>>, // 存储矩阵元素的二维向量
}
```





## 矩阵加减法

矩阵的加法和减法是基本的线性代数运算,它们分别在相同位置对应元素进行加法和减法。以下是矩阵加法和减法的数学定义:

### 矩阵加法:

给定两个相同大小的矩阵 $$A$$ 和 $$B$$,它们的和 $$C$$(记作 $$C = A + B$$)的每个元素 $$c_{ij}$$ 都是对应位置元素的和:

$$ C = A + B $$
$$ c_{ij} = a_{ij} + b_{ij} $$

其中,$$a_{ij}$$ 是矩阵 $$A$$ 中第 $$i$$ 行第 $$j$$ 列的元素,$$b_{ij}$$ 是矩阵 $$B$$ 中相应位置的元素。

### 矩阵减法:

给定两个相同大小的矩阵 $$A$$ 和 $$B$$,它们的差 $$D$$(记作 $$D = A - B$$)的每个元素 $$d_{ij}$$ 都是对应位置元素的差:

$$ D = A - B $$
$$ d_{ij} = a_{ij} - b_{ij} $$

同样,其中 $$a_{ij}$$ 是矩阵 $$A$$ 中第 $$i$$ 行第 $$j$$ 列的元素,$$b_{ij}$$ 是矩阵 $$B$$ 中相应位置的元素。

>    注意:矩阵加法和减法要求两个矩阵的维度必须相同,即它们必须有相同的行数和列数。只有在这种情况下,对应位置的元素才能进行加法或减法运算。

**程序解如下**

```
// 矩阵加法
pub fn add(&self, other: &Matrix) -> Option<Matrix> {
    if self.rows == other.rows && self.cols == other.cols {
        let mut result_data = Vec::with_capacity(self.rows);
        for i in 0..self.rows {
            let mut row = Vec::with_capacity(self.cols);
            for j in 0..self.cols {
                row.push(self.data[i][j] + other.data[i][j]);
            }
            result_data.push(row);
        }
        Some(Matrix {
            rows: self.rows,
            cols: self.cols,
            data: result_data,
        })
    } else {
        None
    }
}

// 矩阵减法
pub fn subtract(&self, other: &Matrix) -> Option<Matrix> {
    if self.rows == other.rows && self.cols == other.cols {
        let mut result_data = Vec::with_capacity(self.rows);
        for i in 0..self.rows {
            let mut row = Vec::with_capacity(self.cols);
            for j in 0..self.cols {
                row.push(self.data[i][j] - other.data[i][j]);
            }
            result_data.push(row);
        }
        Some(Matrix {
            rows: self.rows,
            cols: self.cols,
            data: result_data,
        })
    } else {
        None
    }
}
```



## 矩阵的乘法

矩阵乘法是一个涉及行和列的复杂运算。给定两个矩阵 $$A$$ 和 $$B$$,它们的乘积 $$C$$(记作 $$C = A \cdot B$$)的定义如下:

假设矩阵 $$A$$ 的维度为 $$m \times n$$,矩阵 $$B$$ 的维度为 $$n \times p$$,那么矩阵 $$C$$ 的维度为 $$m \times p$$。

矩阵 $$C$$ 中的每个元素 $$c_{ij}$$ 计算方式如下:

$$ c_{ij} = \sum_{k=1}^{n} a_{ik} \cdot b_{kj} $$

其中,$$a_{ik}$$ 是矩阵 $$A$$ 中第 $$i$$ 行第 $$k$$ 列的元素,$$b_{kj}$$ 是矩阵 $$B$$ 中第 $$k$$ 行第 $$j$$ 列的元素。这个计算过程是对矩阵 $$A$$ 的第 $$i$$ 行和矩阵 $$B$$ 的第 $$j$$ 列进行点积(内积),得到矩阵 $$C$$ 中元素的值。

矩阵乘法的关键要点:
1. 乘法的前提是第一个矩阵的列数等于第二个矩阵的行数。
2. 乘积矩阵的行数等于第一个矩阵的行数,列数等于第二个矩阵的列数。
3. 矩阵乘法不满足交换律,即一般情况下 $$A \cdot B \neq B \cdot A$$。



**程序解如下**

```
/// 矩阵的乘法
pub fn multiply(&self, other: &Matrix) -> Option<Matrix> {
    // 检查矩阵维度是否允许相乘
    if self.cols != other.rows {
        return None;
    }

    let mut result_data = Vec::with_capacity(self.rows);
    for i in 0..self.rows {
        let mut row = Vec::with_capacity(other.cols);
        for j in 0..other.cols {
            let mut sum = 0.0;
            for k in 0..self.cols {
                sum += self.data[i][k] * other.data[k][j];
            }
            row.push(sum);
        }
        result_data.push(row);
    }

    Some(Matrix {
        rows: self.rows,
        cols: other.cols,
        data: result_data,
    })
}
```





## 转置

矩阵的转置是一种操作,通过这种操作,矩阵的行和列交换位置。给定一个矩阵 $$A$$,其转置记作 $$A^T$$。对于矩阵 $$A$$ 中的每一个元素 $$a_{ij}$$,在转置后的矩阵 $$A^T$$ 中,该元素位于 $$A$$ 中的列 $$j$$ 和行 $$i$$ 的位置。

具体来说,如果矩阵 $$A$$ 的维度是 $$m \times n$$,那么它的转置 $$A^T$$ 的维度是 $$n \times m$$。矩阵转置的数学表示如下:

$$ (A^T)_{ij} = A_{ji} $$

其中,$$(A^T)_{ij}$$ 表示转置矩阵 $$A^T$$ 中的第 $$i$$ 行第 $$j$$ 列的元素,而 $$A_{ji}$$ 表示原矩阵 $$A$$ 中的第 $$j$$ 行第 $$i$$ 列的元素。

矩阵转置的性质:
1. $$(A^T)^T = A$$,即对一个矩阵进行两次转置等于原矩阵。
2. $$(A + B)^T = A^T + B^T$$,即转置的和等于和的转置。
3. $$(kA)^T = kA^T$$,其中 $$k$$ 是常数。



下面是一个简单的例子,演示了如何计算矩阵的转置:

假设有矩阵 $$A$$:

$$ A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} $$

那么,矩阵 $$A$$ 的转置 $$A^T$$ 是:

$$ A^T = \begin{bmatrix} 1 & 4 \\ 2 & 5 \\ 3 & 6 \end{bmatrix} $$

你可以看到,原矩阵 $$A$$ 的行变成了转置矩阵 $$A^T$$ 的列,而原矩阵 $$A$$ 的列变成了转置矩阵 $$A^T$$ 的行。



**程序解如下**

```
/// 转置矩阵
pub fn transpose(&self) -> Matrix {
    let mut result_data = Vec::with_capacity(self.cols);
    for j in 0..self.cols {
        let mut row = Vec::with_capacity(self.rows);
        for i in 0..self.rows {
            row.push(self.data[i][j]);
        }
        result_data.push(row);
    }

    Matrix {
        rows: self.cols,
        cols: self.rows,
        data: result_data,
    }
}
```

## 行列式

行列式是一个与方阵相关的数学概念,它为方阵提供了一个标量值。给定一个 $$n \times n$$ 的方阵 $$A$$,其行列式通常表示为 $$|A|$$ 或 $$\text{det}(A)$$。

行列式的计算涉及矩阵的元素,其表达式如下:

$$ |A| = \sum_{\sigma \in S_n} \text{sgn}(\sigma) \cdot a_{1\sigma(1)} \cdot a_{2\sigma(2)} \cdot \ldots \cdot a_{n\sigma(n)} $$

这里,$$S_n$$ 是所有 $$n$$ 阶排列的集合,$$\sigma$$ 是一个排列,$$\text{sgn}(\sigma)$$ 是排列的符号(奇置换为 -1,偶置换为 1),$$a_{i\sigma(i)}$$ 是矩阵 $$A$$ 中的元素。

这个公式展示了一个递归的计算过程,它对所有可能的排列进行了求和。对于每个排列,我们将相应位置的元素相乘,然后乘以符号 $$\text{sgn}(\sigma)$$。最后,将所有这些结果相加得到最终的行列式值。

行列式有一些重要的性质:
1. 行列式的值与矩阵的行列互换无关,即 $$|A| = |A^T|$$。
2. 如果矩阵有两行或两列相同,则行列式为零。
3. 行列式的值等于它的伴随矩阵(adjugate matrix)与原矩阵的乘积。

**程序解如下**

```
// 计算矩阵的行列式
    pub fn determinant(&self) -> Option<f64> {
        // 检查矩阵是否为方阵
        if self.rows != self.cols {
            return None;
        }

        // 递归计算行列式
        self.calculate_determinant(&self.data)
    }

    // 递归计算行列式的辅助函数
    fn calculate_determinant(&self, matrix: &Vec<Vec<f64>>) -> Option<f64> {
        match self.rows {
            1 => Some(matrix[0][0]), // 1x1 矩阵的行列式为其唯一元素的值
            2 => Some(matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]), // 2x2 矩阵的行列式计算公式
            _ => {
                let mut det = 0.0;

                for col in 0..self.cols {
                    // 计算代数余子式
                    let submatrix_data: Vec<Vec<f64>> = matrix
                        .iter()
                        .enumerate()
                        .filter(|&(i, _)| i != 0)
                        .map(|(_, row)| row.iter().enumerate().filter(|&(j, _)| j != col).map(|(_, &val)| val).collect())
                        .collect();

                    let submatrix = Matrix {
                        rows: self.rows - 1,
                        cols: self.cols - 1,
                        data: submatrix_data,
                    };

                    let cofactor = if col % 2 == 0 { 1.0 } else { -1.0 };

                    match self.calculate_determinant(&submatrix.data) {
                        Some(sub_det) => det += cofactor * matrix[0][col] * sub_det,
                        None => return None,
                    }
                }

                Some(det)
            }
        }
    }
```





## 逆矩阵

逆矩阵是与原矩阵相乘后得到单位矩阵的矩阵。给定一个方阵 $$A$$,如果存在一个方阵 $$B$$ 使得 $$AB = BA = I$$,其中 $$I$$ 是单位矩阵,那么矩阵 $$B$$ 就是矩阵 $$A$$ 的逆矩阵,通常表示为 $$A^{-1}$$。

逆矩阵的性质:
1. 只有方阵才有可能有逆矩阵。
2. 如果矩阵 $$A$$ 有逆矩阵,则逆矩阵唯一。

逆矩阵的计算方法:
如果一个 $$n \times n$$ 的矩阵 $$A$$ 可逆,其逆矩阵 $$A^{-1}$$ 可以通过以下公式计算:

$$ A^{-1} = \frac{1}{\text{det}(A)} \cdot \text{adj}(A) $$

其中,$$\text{det}(A)$$ 是矩阵 $$A$$ 的行列式,$$\text{adj}(A)$$ 是矩阵 $$A$$ 的伴随矩阵。伴随矩阵的元素由原矩阵的代数余子式组成,并按矩阵的转置排列。

具体而言,对于 $$n \times n$$ 矩阵 $$A$$,其伴随矩阵的元素 $$(\text{adj}(A))_{ij}$$ 可以通过以下方式计算:

$$ (\text{adj}(A))_{ij} = (-1)^{i+j} \cdot \text{det}(M_{ij}) $$

其中,$$M_{ij}$$ 是去掉矩阵 $$A$$ 的第 $$i$$ 行和第 $$j$$ 列后的子矩阵。



## 特征值和特征向量



特征值和特征向量是矩阵理论中的重要概念,它们在许多数学和工程应用中起着关键的作用。

### 特征值和特征向量的定义

给定一个方阵 $$A$$,非零向量 $$v$$ 是 $$A$$ 的特征向量,如果存在一个标量 $$\lambda$$,使得满足如下关系:

$$ Av = \lambda v $$

这里,$$\lambda$$ 是 $$A$$ 的特征值,$$v$$ 是对应于特征值 $$\lambda$$ 的特征向量。

### 解释和性质

1. **特征值(Eigenvalues):** 特征值是一个标量,它表示了矩阵 $$A$$ 在变换中的缩放因子。一个 $$n \times n$$ 的矩阵 $$A$$ 最多有 $$n$$ 个特征值。

2. **特征向量(Eigenvectors):** 特征向量是与特征值关联的非零向量,其在矩阵变换下只发生缩放而不改变方向。特征向量的长度(模)不是固定的,其方向是关键的。

3. **特征值方程(Characteristic Equation):** 特征值和特征向量的关系由特征值方程表示:

$$ \text{det}(A - \lambda I) = 0 $$

其中,$$\text{det}$$ 表示矩阵的行列式,$$I$$ 是单位矩阵。特征值是满足方程的根。

4. **特征空间:** 与特定特征值关联的所有特征向量形成一个向量空间,称为特征空间。

5. **线性独立性:** 不同特征值对应的特征向量是线性独立的,即它们不可由其他特征向量的线性组合表示。

6. **对角化:** 如果矩阵 $$A$$ 有 $$n$$ 个线性独立的特征向量,可以构成一个特征向量矩阵 $$V$$,则 $$A$$ 可对角化为 $$V^{-1}AV = \Lambda$$,其中 $$\Lambda$$ 是一个对角矩阵,其对角线上的元素是 $$A$$ 的特征值。

**程序解如下**

```
// 计算矩阵的特征值和特征向量
pub fn eigenvalue_eigenvector(&self) -> Option<(Vec<f64>, Vec<Vec<f64>>)> {
    // 检查矩阵是否为方阵
    if self.rows != self.cols {
        return None;
    }

    // 构造特征值方程的左侧矩阵 A - λI
    let a_minus_lambda_i: Matrix = self.subtract_identity();

    // 求解特征值
    let eigenvalues = match a_minus_lambda_i.determinant() {
        Some(det) => self.find_eigenvalues(det),
        None => return None,
    };

    // 求解特征向量
    let mut eigenvectors: Vec<Vec<f64>> = Vec::with_capacity(eigenvalues.len());
    for &eigenvalue in &eigenvalues {
        let eigenvector = self.solve_eigenvector(eigenvalue);
        eigenvectors.push(eigenvector);
    }

    Some((eigenvalues, eigenvectors))
}

// 辅助方法:构造 A - λI
fn subtract_identity(&self) -> Matrix {
    let mut result_data = Vec::with_capacity(self.rows);
    for i in 0..self.rows {
        let mut row = Vec::with_capacity(self.cols);
        for j in 0..self.cols {
            let element = if i == j {
                self.data[i][j] - 1.0 // λ 对应的位置减去 1
            } else {
                self.data[i][j]
            };
            row.push(element);
        }
        result_data.push(row);
    }

    Matrix {
        rows: self.rows,
        cols: self.cols,
        data: result_data,
    }
}

// 辅助方法:求解特征值方程的根
fn find_eigenvalues(&self, det_a_minus_lambda_i: f64) -> Vec<f64> {
    // 这里可以使用任何你喜欢的求根算法,这里简化为一个简单的方式
    // 注意:这里没有处理重根的情况,实际应用中可能需要更复杂的算法
    let mut eigenvalues = Vec::with_capacity(self.rows);
    for i in 0..self.rows {
        eigenvalues.push(self.data[i][i]);
    }
    eigenvalues
}

// 辅助方法:求解特征向量
fn solve_eigenvector(&self, eigenvalue: f64) -> Vec<f64> {
    // 这里可以使用任何你喜欢的求解线性方程组的算法,这里简化为一个简单的方式
    // 注意:这里没有处理奇异矩阵的情况,实际应用中可能需要更复杂的算法
    let mut augmented_matrix_data = Vec::with_capacity(self.rows);
    for i in 0..self.rows {
        let mut row = Vec::with_capacity(self.cols + 1);
        for j in 0..self.cols {
            row.push(self.data[i][j] - eigenvalue * if i == j { 1.0 } else { 0.0 });
        }
        row.push(0.0); // 右侧的常数项
        augmented_matrix_data.push(row);
    }

    let mut  augmented_matrix = Matrix {
        rows: self.rows,
        cols: self.cols + 1,
        data: augmented_matrix_data,
    };

    // 简单的高斯消元法求解线性方程组
    let mut solution = Vec::with_capacity(self.rows);
    for i in 0..self.rows {
        let mut pivot_row = i;
        for j in i + 1..self.rows {
            if augmented_matrix.data[j][i].abs() > augmented_matrix.data[pivot_row][i].abs() {
                pivot_row = j;
            }
        }

        if augmented_matrix.data[pivot_row][i].abs() < EPSILON {
            // 这里可以添加一些处理奇异矩阵的逻辑
            return vec![];
        }

        augmented_matrix.swap_rows(i, pivot_row);

        for j in i + 1..self.rows {
            let factor = augmented_matrix.data[j][i] / augmented_matrix.data[i][i];
            for k in i..self.cols + 1 {
                augmented_matrix.data[j][k] -= factor * augmented_matrix.data[i][k];
            }
        }
    }

    // 回代求解
    for i in (0..self.rows).rev() {
        let mut sum = 0.0;
        for j in i + 1..self.cols {
            sum += augmented_matrix.data[i][j] * solution[j - i - 1];
        }
        solution.push((augmented_matrix.data[i][self.cols] - sum) / augmented_matrix.data[i][i]);
    }

    // 归一化特征向量
    let norm = solution.iter().fold(0.0, |acc, &x| acc + x.powi(2)).sqrt();
    solution.iter().map(|&x| x / norm).collect()
}

// 辅助方法:交换矩阵的两行
fn swap_rows(&self, i: usize, j: usize) {
    let mut data_copy = self.data.clone();
    data_copy.swap(i, j);
    Matrix {
        rows: self.rows,
        cols: self.cols,
        data: data_copy,
    };
}
```