如何在Python中通过矩阵等式A=B求解未知变量d、e、f
求解矩阵等式A=B中的未知变量d、e、f(Python实现)
你的问题本质是求解一个超定非线性方程组:矩阵A的前3×3元素与B的对应元素相等,共9个方程但只有3个未知变量(d,e,f)。这类问题最适合用数值优化中的最小二乘法来求解——我们不需要严格满足每一个方程(毕竟变量数远少于方程数),而是找到能让A和B整体误差最小的变量值。
实现步骤与完整代码
我们用scipy.optimize.least_squares来完成这个任务,它专门处理这类超定非线性最小二乘问题,收敛性和稳定性都不错。
1. 导入必要的库
import numpy as np from scipy.optimize import least_squares
2. 定义残差函数
这个函数的作用是:给定一组(d,e,f),计算矩阵A与B对应元素的差值,把所有差值整理成一维数组供优化器使用。
def residual(x, target_B): d, e, f = x # 构建矩阵A的前3×3核心部分 A_core = np.array([ [np.sin(f)*np.cos(e), np.sin(d)*np.sin(e)*np.cos(f) - np.sin(f)*np.cos(d), np.sin(d)*np.sin(f) + np.sin(e)*np.cos(d)*np.cos(f)], [np.sin(f)*np.cos(e), # 注意:你给出的A矩阵第一、二行首个元素相同,若为笔误请自行修正 np.sin(d)*np.sin(e)*np.sin(f) + np.cos(d)*np.cos(f), -np.sin(d)*np.cos(f) + np.sin(e)*np.sin(f)*np.cos(d)], [-np.sin(e), np.sin(d)*np.cos(e), np.cos(d)*np.cos(e)] ]) # 计算残差:A与B前3×3元素的差值,展平为一维数组 return (A_core - target_B[:3, :3]).flatten()
3. 设置已知矩阵与初始猜测值
# 已知的目标矩阵B B = np.array([ [0.23, -0.45, 1.6, 0], [0.8, 1.7, 1.4, 0], [0.43, 0.72, 0.6, 0], [0, 0, 0, 1] ]) # 初始猜测值(可以根据实际情况调整,比如全0或π/4这类常见角度) initial_guess = np.array([0.0, 0.0, 0.0])
4. 调用求解器并验证结果
# 执行最小二乘求解 solution = least_squares(residual, initial_guess, args=(B,)) # 输出求解结果(同时转换为度数方便阅读) d_opt, e_opt, f_opt = solution.x print("求解得到的变量值:") print(f"d = {d_opt:.4f} 弧度(约 {np.degrees(d_opt):.2f} 度)") print(f"e = {e_opt:.4f} 弧度(约 {np.degrees(e_opt):.2f} 度)") print(f"f = {f_opt:.4f} 弧度(约 {np.degrees(f_opt):.2f} 度)") # 验证:用求得的变量构建完整矩阵A,查看与B的差异 A_opt = np.array([ [np.sin(f_opt)*np.cos(e_opt), np.sin(d_opt)*np.sin(e_opt)*np.cos(f_opt) - np.sin(f_opt)*np.cos(d_opt), np.sin(d_opt)*np.sin(f_opt) + np.sin(e_opt)*np.cos(d_opt)*np.cos(f_opt), 0], [np.sin(f_opt)*np.cos(e_opt), np.sin(d_opt)*np.sin(e_opt)*np.sin(f_opt) + np.cos(d_opt)*np.cos(f_opt), -np.sin(d_opt)*np.cos(f_opt) + np.sin(e_opt)*np.sin(f_opt)*np.cos(d_opt), 0], [-np.sin(e_opt), np.sin(d_opt)*np.cos(e_opt), np.cos(d_opt)*np.cos(e_opt), 0], [0, 0, 0, 1] ]) print("\n验证:优化后的矩阵A与B的元素差异:") print(np.round(A_opt - B, 4)) # 保留4位小数,方便查看
关键注意事项
- 弧度/度数转换:Python中
numpy.sin和numpy.cos默认使用弧度计算,如果你的问题中角度以度数为单位,记得先转换为弧度再代入计算,或者像代码中一样把结果转换为度数。 - 初始值的影响:非线性优化的结果可能受初始猜测值影响,如果第一次求解的误差较大,可以尝试调整
initial_guess(比如换成np.array([np.pi/4, np.pi/4, np.pi/4]))。 - 超定方程组的特性:因为我们有9个方程但只有3个变量,最小二乘法会找到整体误差最小的解,而不是严格满足每一个方程——除非B恰好是某个符合A结构的矩阵。
替代方案:精确求解方程组(若存在精确解)
如果你确定存在一组(d,e,f)能让A完全等于B,可以选择3个独立方程,用scipy.optimize.root求解。比如选第一行第一列、第三行第一列、第三行第三列的方程:
def exact_equations(x, target_B): d, e, f = x eq1 = np.sin(f)*np.cos(e) - target_B[0,0] eq2 = -np.sin(e) - target_B[2,0] eq3 = np.cos(d)*np.cos(e) - target_B[2,2] return [eq1, eq2, eq3] from scipy.optimize import root exact_solution = root(exact_equations, initial_guess, args=(B,)) print("\n用精确方程组求解的结果:") print(f"d = {exact_solution.x[0]:.4f} 弧度,e = {exact_solution.x[1]:.4f} 弧度,f = {exact_solution.x[2]:.4f} 弧度")
不过这种方法需要确保所选方程独立且有解,否则可能无法收敛。
内容的提问来源于stack exchange,提问作者Siddharth Singh
相关产品推荐
相关产品推荐

