流线图
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)