流线图

    StreamPlot(expression)绘制一系列平滑的、永不交叉的曲线(即“流线”)来描绘二维向量场的图像。

    1:流体力学 - 一个点源(水龙头滴下一滴水)

    想象在原点有一个水龙头,水均匀地向四面八方流出去。

    画图范围:x从-2到2,y从-2到2(注意避开原点x=0, y=0,因为那里分母为零)。

    它像什么:所有流线都是从原点(源点)直接向外发射的直线。

    StreamPlot(x/(x^2+y^2),y/(x^2+y^2),x=[-2,2],y=[-2,2])

    2:流体力学 - 一个涡旋(水池排水时形成的漩涡)

    想象原点是一个排水口,水在旋转着流下去。

    画图范围:x从-2到2,y从-2到2(同样避开原点)。

    它像什么:所有流线都是围绕原点旋转的圆圈,形成一个涡旋。

    StreamPlot(x/(x^2+y^2),-y/(x^2+y^2),x=[-2,2],y=[-2,2])

    3:电磁学 - 一个偶极子(一个正电荷和一个负电荷靠在一起)

    就像一根磁铁或一个电荷对的磁场/电场。

    画图范围:x从-2到2,y从-1到1。

    它像什么:流线从正电荷(源)出发,弯曲地连接并终止于负电荷(汇)。

    StreamPlot((x+0.5)/(((x+0.5)^2+y^2 )^1.5)-(x-0.5)/(((x-0.5)^2+y^2)^1.5),y/(((x+0.5)^2+y^2)^1.5)-y/(((x-0.5)^2+y^2)^1.5),x=[-2,2],y=[-1,1])

    4:理论模型 - saddle点(鞍点)

    这是一个非常基础但又重要的场结构,像一个山口。

    画图范围:x从-2到2,y从-2到2。

    它像什么:流线沿着x轴向外散开,沿着y轴向内收拢。原点(0,0)这个点就叫做saddle点(鞍点),它既不是源也不是汇,是不稳定点。

    StreamPlot(x,-y,x=[-2,2],y=[-2,2])

    5:最简单的函数 F(z) = z

    表达式:F(z) = z = x + i*y

    对应的向量场:( u, v ) = ( x, y )

    流线图分析:

    这是一个标准的源(Source)。

    所有点的向量都从原点指向外。

    离原点越远,向量长度(模)越大。

    这类似于一个水龙头向平静的水面滴水形成的流场。

    StreamPlot(z,z=[-2-2@i,2+2@i])

    6:F(z) = i * z (乘以虚数单位 i)

    表达式:F(z) = i * (x + i*y) = -y + i*x

    对应的向量场:( u, v ) = ( -y, x )

    流线图分析:

    这是一个纯粹的涡旋(Vortex)。

    所有流线都是围绕原点的同心圆。

    向量方向永远垂直于该点与原点的连线。

    这类似于水池排水时形成的漩涡。

    StreamPlot(z*1@i,z=[-2-2@i,2+2@i])

    7:F(z) = z^2

    表达式:F(z) = (x + i*y)^2 = (x^2 - y^2) + i*(2*x*y)

    对应的向量场:( u, v ) = ( x^2 - y^2, 2*x*y )

    流线图分析:

    这个场看起来会比前两个复杂。

    沿着 x 轴 (y=0) 和 y 轴 (x=0) 看,场的方向很好判断。

    你会看到两个“源”或“汇”挤压在一起形成的复杂图案,流线是双曲线形状。它在原点是一个鞍点(Saddle Point)。

    StreamPlot(z^2,z=[-2-2@i,2+2@i])

    8:F(z) = 1 / z

    表达式:F(z) = 1 / (x + i*y) = (x - i*y) / (x^2 + y^2)

    对应的向量场:( u, v ) = ( x / (x^2+y^2), -y / (x^2+y^2) )

    流线图分析:

    这是源和涡旋的叠加!

    实部 x/(r^2) 代表一个源。

    虚部 -y/(r^2) 代表一个涡旋。

    最终的流线是从原点出发,同时向外且旋转的螺旋线。

    这在物理上对应着一个偶极子(Dipole)的场,但带有旋转效应。原点 z=0 是奇点。

    StreamPlot(1/z,z=[-2-2@i,2+2@i])

    9:F(z) = exp(z) (指数函数)

    表达式:利用欧拉公式 exp(x + i*y) = exp(x) * (cos(y) + i*sin(y))

    对应的向量场:( u, v ) = ( exp(x)*cos(y), exp(x)*sin(y) )

    流线图分析:

    这个场在 y 方向是周期性的(因为包含 cos(y) 和 sin(y))。

    沿着任意一条水平线 (y = constant),场的强度 |F| = exp(x) 随着 x 增大而指数增长。

    流线图会呈现出周期性重复的、从左向右发散的图案。

    StreamPlot(exp(z),z=[-2-2@i,2+2@i])
    
    根据常见的子表达式重写符号表达式

    [r,sigma] = subexpr(expr)根据公共子表达式重写符号表达式expr,用符号变量sigma替换该公共子表达式. 输入表达式expr不能包含变量sigma.

    expr —— 包含常见子表达式的长表达式,符号表达,符号功能

    r —— 用缩写替换普通子表达式的表达式,符号表达,符号功能

    示例1:力学系统中的复杂表达式简化

    mechanical_system = m*g*sin(theta) + (1/2)*m*v**2 + m*g*h*cos(theta)

    力学系统表达式:
    result = subexpr(mechanical_system)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, g*m)]
    #简化表达式: [h*x0*cos(theta) + m*v**2/2 + x0*sin(theta)]

    示例2:复杂电路方程的简化

    circuit_eq = V/(R1 + R2 + R3) + I*(R1*R2 + R2*R3 + R1*R3)/(R1 + R2 + R3)

    电路方程:
    result = subexpr(circuit_eq)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, 1/(R1 + R2 + R3))]
    #简化表达式: [V*x0 + I*x0*(R1*R2 + R1*R3 + R2*R3)]

    示例3:控制系统传递函数的简化

    control_system = [[K/(s*(s+a)), K*(s+b)/(s*(s+a))], [K*c/(s*(s+a)), K*d/(s*(s+a))]]

    控制系统传递函数矩阵:
    result = subexpr(control_system)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, K/(s*(a + s)))]
    #简化表达式:
    #[[x0,x0*(b + s)],
      [c*x0,d*x0]]

    示例4:结构分析中的刚度矩阵

    stiffness_matrix = [[E*A/L, -E*A/L, 0], [-E*A/L, 2*E*A/L, -E*A/L], [0, -E*A/L, E*A/L]]

    结构刚度矩阵:
    result = subexpr(stiffness_matrix)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, E*A/L), (x1, -x0)]
    #简化表达式:
    #[[x0,x1,0],
      [x1,2*x0,x1],
      [0,x1,x0]]

    示例5:热传导问题的系数矩阵

    heat_transfer = [[k*A/dx, -k*A/dx, 0], [-k*A/dx, 2*k*A/dx, -k*A/dx], [0, -k*A/dx, k*A/dx]]

    热传导系数矩阵:
    result = subexpr(heat_transfer)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, A*k/dx), (x1, -x0)]
    #简化表达式:
    #[[x0,x1,0],
      [x1,2*x0,x1],
      [0,x1,x0]]

    示例6:机器人雅可比矩阵的简化

    robot_kinematics = [[-l1*sin(theta1)-l2*sin(theta1+theta2), -l2*sin(theta1+theta2)], [l1*cos(theta1)+l2*cos(theta1+theta2), l2*cos(theta1+theta2)]]

    机器人雅可比矩阵:
    result = subexpr(robot_kinematics)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, theta1 + theta2), (x1, l2*sin(x0)), (x2, l2*cos(x0))]
    #简化表达式:
    #[[-l1*sin(theta1)-x1,-x1],
      [l1*cos(theta1)+x2,x2]]

    示例7:量子力学中的波函数表达式

    wave_function = A*exp(i*k*x - i*omega*t) + B*exp(-i*k*x - i*omega*t)

    量子波函数:
    result = subexpr(wave_function)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, i*k*x), (x1, i*omega*t)]
    #简化表达式: [A*exp(x0 - x1) + B*exp(-x0 - x1)]

    示例8:复杂化学反应速率表达式

    reaction_kinetics = k1*A*B/(1 + K_A*A + K_B*B) + k2*A*C/(1 + K_A*A + K_C*C)

    化学反应动力学:
    result = subexpr(reaction_kinetics)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, A*K_A + 1)]
    #简化表达式: [A*B*k1/(B*K_B + x0) + A*C*k2/(C*K_C + x0)]

    示例9:电磁场中的势函数

    electromagnetic = [[mu0*I/(4*pi*r), 0, 0], [0, mu0*I/(4*pi*r), 0], [0, 0, mu0*I/(4*pi*r)]]

    电磁场势函数矩阵:
    result = subexpr(electromagnetic)

    print("替换规则:", result[0])
    print("简化表达式:", result[1])
    #替换规则: [(x0, I*mu0/(4*pi*r))]
    #简化表达式:
    #[[x0,0,0],
      [0,x0,0],
      [0,0,x0]]
    
    # Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
    # Licensed under the MIT License.
    import sympy as sp

    def subexpression_common_elimination(input_str):
        """
         对标 MATLAB 的 subexpr 函数,通过公共子表达式重写符号表达式

         Args:
             input_str: 可解析为矩阵或符号表达式的字符串

         Returns:
             成功时返回元组 (替换规则列表, 简化后的表达式)
             失败时返回错误描述字符串

         Examples:
             >>> subexpression_common_elimination("[[x + y, (x + y)**2], [exp(x + y), 1/(x + y)]]")
             ([(x0, x + y)], Matrix([
             [   x0,  x0**2],
             [exp(x0),   1/x0]]))

             >>> subexpression_common_elimination("sin(a) + sqrt(a) + a**2")
             ([(x0, a)], sin(x0) + sqrt(x0) + x0**2)
         """
        try:
            expr = sp.sympify(input_str)
            error = False
            result = None

            if expr.free_symbols:
                R, sigma = sp.cse(expr)
                result = R, sigma
            else:
                error = True

            return result if not error else f"输入错误: {input_str}"
        except Exception as e:
            return f"错误:{e}"


    # 示例测试
    if __name__ == "__main__":
        # 矩阵测试用例
        test_cases = [
            "sin(a) + sqrt(a) + a^2",
            # [sqrt(a) + a**2 + sin(a)]
        ]

        for case in test_cases:
            print(f"\n输入: {str(case)[:50]}...")
            result = subexpression_common_elimination(str(case))  # 统一转换为字符串
            if isinstance(result, tuple):
                print("替换规则:", result[0])
                print("简化表达式:", result[1])
            else:
                print("错误输出:", result)