{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "89d7e2bc",
   "metadata": {},
   "source": [
    "行列式与逆矩阵\n",
    "det能判断可逆；能solve就不要用inv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "258d32ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "plt.rcParams['axes.unicode_minus'] = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e2f3046",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "det 手算 2*3-1*1 = 5\n",
      "det numpy = 5.000000000000001\n",
      "逆 =\n",
      " [[ 0.6 -0.2]\n",
      " [-0.2  0.4]]\n",
      "A @ 逆 ≈\n",
      " [[ 1.  0.]\n",
      " [-0.  1.]]\n"
     ]
    }
   ],
   "source": [
    "A = np.array([[2.0, 1.0], [1.0, 3.0]])\n",
    "print('det 手算 2*3-1*1 =', 2*3-1*1)\n",
    "print('det numpy =', np.linalg.det(A))\n",
    "Ainv = np.linalg.inv(A)#使用 np.linalg.inv() 函数计算矩阵 A 的逆矩阵，并将结果赋值给变量 Ainv。\n",
    "print('逆 =\\n', Ainv)\n",
    "print('A @ 逆 ≈\\n', np.round(A @ Ainv, 10))\n",
    "#由于浮点数计算的精度问题，结果可能会有极小的误差（例如 2.22e-16），这行代码将结果四舍五入保留10位小数，使其呈现为干净的单位矩阵。\n",
    "#在 IEEE 浮点数标准中，负的极小值四舍五入后，会保留符号位，变成“负零”（-0.），而不是正零（0.）。NumPy 严格遵循了这个底层标准。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d36d1695",
   "metadata": {},
   "source": [
    "我们为什么是 float 型呢？自己在旁边笔记记一下啊，避免 int 型 int 就是整数啊，带来的一个计算异常。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cbc0a0f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "det(B) 0.0\n",
      "solve 报错: Singular matrix\n",
      "inv 报错 Singular matrix\n"
     ]
    }
   ],
   "source": [
    "#奇异矩阵\n",
    "B = np.array([[1.0, 2.0], [2.0, 4.0]])\n",
    "print('det(B)', np.linalg.det(B))\n",
    "try:\n",
    "    print(np.linalg.solve(B, np.array([1.0, 2.0])))\n",
    "except np.linalg.LinAlgError as e:\n",
    "    print('solve 报错:', e)\n",
    "try:\n",
    "    print(np.linalg.inv(B))\n",
    "except np.linalg.LinAlgError as e:\n",
    "    print('inv 报错', e)\n",
    "\n",
    "#对于数学上严格奇异的方阵，在 NumPy 中调用 inv 或 solve，通常都会得到 Singular matrix 的报错。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc67c1f8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "列向量矩阵 det = 3.749999999999999 (有向面积)\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 500x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "v1, v2 = np.array([2.0, 0.5]), np.array([0.5, 2.0])\n",
    "M = np.column_stack([v1, v2])#使用 np.column_stack 将这两个向量作为列拼接起来，形成一个2x2的矩阵\n",
    "det = np.linalg.det(M)# 二阶矩阵的行列式，其几何意义等于：由该矩阵的两个列向量所围成的“平行四边形的有向面积”。\n",
    "print('列向量矩阵 det =', det, '(有向面积)')\n",
    "plt.figure(figsize=(5, 5))\n",
    "pts = np.array([[0, 0], v1, v1+v2, v2, [0, 0]])\n",
    "plt.fill(pts[:,0], pts[:,1], alpha=0.3)\n",
    "plt.plot([0,v1[0]], [0,v1[1]], '-o', label='v1')\n",
    "plt.plot([0,v2[0]], [0,v2[1]], '-o', label='v2')\n",
    "plt.gca().set_aspect('equal')#（关键设置） 设置坐标轴比例相等，确保 x 轴和 y 轴的单位长度在屏幕上看起来一样长，这样画出来的几何图形才不会变形。\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.legend()\n",
    "plt.title(f'平行四边形面积 |det|={abs(det):.3f}')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd00b9b5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "solve: [2. 1.]\n",
      "inv@b: [2. 1.]\n",
      "相同? True\n",
      "优先solve\n"
     ]
    }
   ],
   "source": [
    "A = np.array([[2.0, 1.0], [1.0, 3.0]])\n",
    "b = np.array([5.0, 5.0])\n",
    "x1 = np.linalg.solve(A, b)#LU分解数值稳定性好，浮点误差小\n",
    "x2 = np.linalg.inv(A) @ b#先算完整逆矩阵，再去乘b-->多了一步求逆，计算量变大，数值精度会变差-->Engineering不推荐首先考虑成本和项目可行性\n",
    "print('solve:', x1)\n",
    "print('inv@b:', x2)\n",
    "print('相同?', np.allclose(x1, x2))\n",
    "print('优先solve')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
