数学建模
解析方法与几何模型
- 数学建模
-
- [1.1 向量表示法与几何建模基本案例](#1.1 向量表示法与几何建模基本案例)
-
- [1.1.1 几何建模的思想](#1.1.1 几何建模的思想)
- [1.1.2 向量表示与坐标变换](#1.1.2 向量表示与坐标变换)
- [1.2 Numpy 与线性代数](#1.2 Numpy 与线性代数)
-
- [1.2.1 Numpy向量与矩阵的操作](#1.2.1 Numpy向量与矩阵的操作)
- [1.2.2 利用Numpy进行线性代数基本运算](#1.2.2 利用Numpy进行线性代数基本运算)
- [1.2.3 `numpy.linalg` 的使用](#1.2.3
numpy.linalg
的使用)
1.1 向量表示法与几何建模基本案例
1.1.1 几何建模的思想
人类对于数学世界的探索起源于两样东西:一是计数,二是丈量。计数用以表示多少,要计算多了多少少了多少,于是有了数字的概念和四则运算,也就有了后来的代数学;丈量是测量土地的长宽面积、测量角度、分析几何关系等,也就有了后来的几何学。高中毕业以后,我们对于数学模型的理解其实还很浅薄,但几何模型对我们来讲是最直观的东西。有一张图,我们就可以直观地感受:哪两个平面平行,哪两条线垂直......通过一系列的几何定理还可以推算线段的长度等等。所以,我们就以几何模型作为了解数学建模的切入点。
1.1.2 向量表示与坐标变换
在数学中,坐标变换通常涉及到一系列的矩阵运算,这些矩阵描述了一个坐标系相对于另一个坐标系的位置和方向。旋转变换就是其中的一个典型例子。当我们说一个坐标系相对于另一个坐标系进行了旋转,我们通常是指它绕着一个轴或者点旋转了一定的角度。二维空间的旋转可以简化为点绕原点旋转,而三维空间则涉及到更复杂的轴向旋转。
在二维空间中,如果我们要将坐标系绕原点旋转一个角度,就可以通过旋转矩阵来实现。旋转矩阵是一个非常简单而又强大的工具,它可以将原始坐标系中的点通过线性变换映射到新坐标系中。对于逆时针旋转,二维旋转矩阵的形式是
cos θ − sin θ sin θ cos θ \] . (1.1.2) \\left\[ \\begin{matrix} \\cos \\theta \& -\\sin \\theta\\\\ \\sin \\theta \& \\cos \\theta \\end{matrix} \\right\] . \\tag{1.1.2} \[cosθsinθ−sinθcosθ\].(1.1.2) 这里, θ \\theta θ是旋转角度,当应用这个旋转矩阵于一个点 ( x , y ) (x, y) (x,y),它会给出新的坐标 ( x ′ , y ′ ) (x', y') (x′,y′),这表示了原始点在新坐标系中的位置。 使用NumPy进行这样的变换非常简单。首先,我们创建一个表示点坐标的NumPy数组,然后创建表示旋转矩阵的二维数组。通过对这两个数组进行点积运算(也就是矩阵乘法),我们就可以得到新的坐标,在Python中可以这样实现: ````python import numpy as np # 设定旋转角度,这里我们以30度为例 theta = np.radians(30) # 将30度转换为弧度 # 创建旋转矩阵 rotation_matrix = np.array([ [np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)] ]) # 假设我们有一个点 (a, b) point = np.array([a, b]) # 通过旋转矩阵变换这个点的坐标 rotated_point = rotation_matrix.dot(point) print("原坐标为:", point) print("旋转后的坐标为:", rotated_point) # 原坐标为: [5 3] # 旋转后的坐标为: [2.83012702 5.09807621] 在三维空间中,物体的旋转可以围绕三个主轴进行:$\mathrm{x}$轴, $\mathrm{y}$轴和$\mathrm{z}$轴。这些轴旋转代表了不同方向的运动,并且可以通过旋转矩阵来数学描述。例如,一个点$P(x, y, z)$绕$\mathrm{z}$轴旋转角度$\alpha$可以表示为 $$ R_{\mathrm{z}}(\alpha) = \left[ \begin{matrix} \cos\alpha & -\sin\alpha & 0\\sin\alpha & \cos\alpha & 0\\0 & 0 &1 \end{matrix} \right], \tag{1.1.3} $$ 这个旋转保持$\mathrm{z}$坐标不变,同时在$XY$平面上变换$\mathrm{x}$和$\mathrm{y}$坐标。相似地,点$P$绕$\mathrm{y}$轴旋转角度$\beta$的旋转矩阵为 $$ R_{\mathrm{y}}(\beta) = \left[ \begin{matrix} \cos\beta & 0 & \sin\beta\\ 0 & 1 & 0\\ -\sin\beta & 0 & \sin\beta \end{matrix} \right], \tag{1.1.4} $$ 这个旋转保持$\mathrm{y}$坐标不变,同时在$XZ$平面上变换$\mathrm{x}$和$\mathrm{z}$坐标。而点$P$绕$\mathrm{x}$轴旋转角度$\gamma$的旋转矩阵为 $$ R_{\mathrm{x}}(\gamma) = \left[ \begin{matrix} 1 & 0 & 0\\ 0 & \cos\gamma & -\sin\gamma\\ 0 & \sin\gamma & \cos\gamma \end{matrix} \right], \tag{1.1.5} $$ 这个旋转保持$\mathrm{x}$坐标不变,同时在$YZ$平面上变换$\mathrm{y}$和$\mathrm{z}$坐标。若点$P$需同时围绕三个轴旋转,则最终旋转矩阵$R$为这三个矩阵的乘积,即$R = R_{\mathrm{z}}(\alpha)R_{\mathrm{y}}(\beta)R_{\mathrm{x}}(\gamma)$。需要注意的是,由于矩阵乘法的非交换性,旋转的顺序会影响最终结果。 在实际应用中,如机器人学、航空航天和计算机图形学,旋转顺序对于模拟和预测物体如何移动至关重要。例如,飞机的姿态控制就极依赖于绕不同轴的旋转顺序,以精确地模拟和控制飞机的行动。在三维建模和动画制作中,这些旋转变换同样是创建动态、逼真场景的基础。 在Python中,利用NumPy库,我们可以使用如下代码片段来实现三维旋转变换: ```python import numpy as np # 定义旋转角度(以弧度为单位) alpha = np.radians(30) # 绕 Z 轴旋转 beta = np.radians(45) # 绕 Y 轴旋转 gamma = np.radians(60) # 绕 X 轴旋转 # 定义旋转矩阵 R_z = np.array([[np.cos(alpha), -np.sin(alpha), 0], [np.sin(alpha), np.cos(alpha), 0], [0, 0, 1]]) R_y = np.array([[np.cos(beta), 0, np.sin(beta)], [0, 1, 0], [-np.sin(beta), 0, np.cos(beta)]]) R_x = np.array([[1, 0, 0], [0, np.cos(gamma), -np.sin(gamma)], [0, np.sin(gamma), np.cos(gamma)]]) # 总旋转矩阵 R = R_z @ R_y @ R_x # 定义点P的坐标 P = np.array([1, 2, 3]) # 计算旋转后的坐标 P_rotated = R @ P print("旋转后P点的坐标为:", P_rotated) # 旋转后P点的坐标为: [3.39062937 0.11228132 1.57829826] ```` 在该代码中,点 P P P经过由 α \\alpha α, β \\beta β,和 γ \\gamma γ定义的旋转后,其新坐标由 P rotated P_{\\text{rotated}} Protated给出。该代码首先创建了绕 z \\mathrm{z} z, y \\mathrm{y} y,和 x \\mathrm{x} x轴的三个旋转矩阵,然后将它们相乘得到一个总的旋转矩阵 R R R,并应用这个矩阵来转换点 P P P的坐标。 正是通过这些准确的数学变换和编程实现,我们能够在计算机模拟和实际应用中处理复杂的三维空间问题。无论是设计复杂的机械系统、创建逼真的三维动画,还是开发高级的虚拟现实环境,三维旋转都是不可或缺的基础。 欧拉角是三维空间中用于表示一个物体相对于一个固定坐标系(通常是参考坐标系或世界坐标系)的方向的一组角。这种表示方法定义了三次旋转,将物体从其初始方向旋转到期望方向。欧拉角通常表示为三个角度: α \\alpha α, β \\beta β,和 γ \\gamma γ分别对应于绕 z \\mathrm{z} z轴, x \\mathrm{x} x轴(或 y \\mathrm{y} y轴),以及再次 y \\mathrm{y} y轴(或 x \\mathrm{x} x轴)的旋转。 欧拉角旋转顺序的不同,定义了不同的旋转方式,最常见的是: * **Z-Y-X(Roll-Pitch-Yaw)** :首先绕 z \\mathrm{z} z轴旋转 α \\alpha α(Yaw),然后绕*新位置的* y \\mathrm{y} y轴旋转 β \\beta β(Pitch),最后绕*新位置的* x \\mathrm{x} x轴旋转 γ \\gamma γ(Roll)。 * **Z-X-Y(Yaw-Pitch-Roll)** :首先绕 z \\mathrm{z} z轴旋转 α \\alpha α(Yaw),然后绕*新位置的* x \\mathrm{x} x轴旋转 β \\beta β(Pitch),最后再次绕 y \\mathrm{y} y轴旋转 γ \\gamma γ(Roll)。 每次旋转都是围绕变换后的轴,而不是初始的固定轴。这些旋转通常通过旋转矩阵进行计算,并且可以合成为一个单一的矩阵,它描述了总的旋转。在实际应用中,如飞行动力学和计算机图形学,欧拉角非常重要。 这里是Python中计算欧拉角旋转的代码示例,假设采用 Z Z Z- Y Y Y- X X X顺序: ```python import numpy as np # 定义欧拉角(以弧度为单位) alpha = np.radians(30) # 绕 z 轴的 Yaw 角度 beta = np.radians(45) # 绕 y 轴的 Pitch 角度 gamma = np.radians(60) # 绕 x 轴的 Roll 角度 # 构建对应的旋转矩阵 R_z = np.array([[np.cos(alpha), -np.sin(alpha), 0], [np.sin(alpha), np.cos(alpha), 0], [0, 0, 1]]) R_y = np.array([[np.cos(beta), 0, np.sin(beta)], [0, 1, 0], [-np.sin(beta), 0, np.cos(beta)]]) R_x = np.array([[1, 0, 0], [0, np.cos(gamma), -np.sin(gamma)], [0, np.sin(gamma), np.cos(gamma)]]) # 总旋转矩阵,注意乘法的顺序 R = np.dot(R_x, np.dot(R_y, R_z)) print("组合旋转矩阵为:") print(R) # 组合旋转矩阵为: # [[ 0.61237244 -0.35355339 0.70710678] # [ 0.78033009 0.12682648 -0.61237244] # [ 0.12682648 0.9267767 0.35355339]] ``` ### 1.2 Numpy 与线性代数 在本节中,我们将探讨Python中最强大的科学计算库之一:NumPy。在深入学习之前,我们需要弄清楚线性代数在实际应用中的重要性。线性代数不仅是理解数据结构、解决数学问题的基础,也是计算机图形学、机器学习等高级领域不可或缺的工具。NumPy库在这里扮演了至关重要的角色,因为它为我们提供了一个高效、便捷的平台来处理数值计算和线性代数运算。接下来的内容,将通过实际的例子展示如何使用NumPy来执行一些基础但强大的线性代数操作。 #### 1.2.1 Numpy向量与矩阵的操作 在科学计算的世界里,NumPy的数组对象是我们解决问题的得力助手。它能让我们轻松地执行向量化运算,这意味着可以一次性处理数据集而不需要使用循环。这种处理方式不仅代码更加简洁,而且运行速度也远快于传统的Python循环。在Numpy中,向量和矩阵都可以用二维数组表示,让我们来看看基本操作。 **创建向量和矩阵** ```python import numpy as np # 创建向量 vector = np.array([1, 2, 3]) # 创建矩阵 matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) ``` **向量和矩阵的基本属性** ```python # 向量的维度 print(vector.shape) # (3, ) # 矩阵的维度 print(matrix.shape) # (3, 3) # 矩阵的行数和列数 print(matrix.shape[0]) # 行数, 3 print(matrix.shape[1]) # 列数, 3 ``` **索引和切片** ```python # 索引 print(vector[0]) # 输出第一个元素, 1 print(matrix[1, 1]) # 输出第二行第二列的元素, 5 # 切片 print(vector[0:2]) # 输出前两个元素, [1, 2] print(matrix[0:2, 0:2]) # 输出左上角的2x2子矩阵, [[1, 2], [4, 5]] ``` **向量和矩阵的运算** ```python # 向量加法 vector1 = np.array([1, 2, 3]) vector2 = np.array([4, 5, 6]) print(np.add(vector1, vector2)) # [5, 7, 9] # 矩阵乘法 matrix1 = np.array([[1, 2], [3, 4]]) matrix2 = np.array([[5, 6], [7, 8]]) print(np.dot(matrix1, matrix2)) # 或使用 matrix1 @ matrix2 # [[19, 22], # [43, 50]] ``` #### 1.2.2 利用Numpy进行线性代数基本运算 在NumPy中,我们可以利用数组的**广播机制**来进行各种线性代数运算。例如,你可以轻松地将一个标量与一个向量或矩阵相乘,而不需要编写任何循环。NumPy也提供了计算矩阵的转置、行列式、逆矩阵等常见操作的函数。 ```python import numpy as np # 数量乘法示例 scalar = 5 scaled_vector = scalar * vector print("Scaled vector:", scaled_vector) # Scaled vector: [ 5 10 15] # 矩阵的转置示例 transposed_matrix = matrix.T print("Transposed matrix:\n", transposed_matrix) # Transposed matrix: # [[1, 4, 7] # [2, 5, 8] # [3, 6, 9]] # 计算行列式示例 matrix_determinant = np.linalg.det(matrix) print("Matrix determinant:", matrix_determinant) # Matrix determinant: 0.0 # 求解线性方程组示例 A = np.array([[3, 1], [1, 2]]) b = np.array([9, 8]) solution = np.linalg.solve(A, b) print("Solution of the linear system:", solution) # Solution of the linear system: [2. 3.] ``` #### 1.2.3 `numpy.linalg` 的使用 最后,我们不能不提NumPy中的 `linalg` 子模块,它包含了一系列关于线性代数的函数。无论是求解方程组,还是计算特征值、特征向量,乃至执行奇异值分解,`linalg` 模块都能够提供帮助。通过这些工具,我们可以探索矩阵的深层属性,并应用于各种数学和工程问题。下面是一些 `numpy.linalg` 模块的使用示例: **计算逆矩阵** ```python import numpy as np # If the matrix is singular, use the pseudo-inverse pseudo_inverse_matrix = np.linalg.pinv(matrix) print("Pseudo-inverse of the matrix:") print(pseudo_inverse_matrix) # Pseudo-inverse of the matrix: # [[-6.38888889e-01 -1.66666667e-01 3.05555556e-01] # [-5.55555556e-02 4.20756436e-17 5.55555556e-02] # [ 5.27777778e-01 1.66666667e-01 -1.94444444e-01]] ``` **特征值和特征向量** ```python eigenvalues, eigenvectors = np.linalg.eig(matrix) print(eigenvalues) # [ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15] print(eigenvectors) # [[-0.23197069 -0.78583024 0.40824829] # [-0.52532209 -0.08675134 -0.81649658] # [-0.8186735 0.61232756 0.40824829]] ``` **奇异值分解** ```python U, S, V = np.linalg.svd(matrix) print(U) # [[-0.21483724 0.88723069 0.40824829] # [-0.52058739 0.24964395 -0.81649658] # [-0.82633754 -0.38794278 0.40824829]] print(S) # [1.68481034e+01 1.06836951e+00 4.41842475e-16] print(V) # [[-0.47967118 -0.57236779 -0.66506441] # [-0.77669099 -0.07568647 0.62531805] # [-0.40824829 0.81649658 -0.40824829]] ``` **范数计算** ```python norm = np.linalg.norm(vector) print(norm) # 3.7416573867739413 ```