main
Mu_Xin 9 months ago
parent 63b950ebad
commit 365e78162f

@ -1,301 +0,0 @@
from sympy import *
import itertools
x,y,z = symbols('x y z')
#累次极限:f为函数; var_points为字典,其中key为变量,value为变量趋近值
def repeated_limit(f, var_points, direction='+'):
if not isinstance(var_points, dict):
return "错误:var_points 必须是字典,例如 {x: 0, y: 0}"
if not all(isinstance(var, Symbol) for var in var_points.keys()):
return "错误:字典的键必须是 SymPy 符号变量,例如 x, y, z"
try:
for var, point in var_points.items():
limitation = limit(f,var,point, dir=direction)
if f in (zoo, nan) or f.has(zoo, nan):
raise ValueError("极限不存在")
f = limitation
return f
except TypeError as e:
return f"类型错误:{str(e)}。请检查函数表达式和极限点是否为有效数学表达式"
except ValueError as e:
return f"值错误:{str(e)}。请检查极限点是否有效"
except Exception as e:
return f"计算极限时出错:{str(e)}。请检查输入格式是否正确"
#重极限:f为函数; var_points为字典,其中key为变量,value为变量趋近值
def mult_limit(f, var_points):
vars = list(var_points.keys())
values = list(var_points.values())
n = len(vars)
if n == 0:
return f
if n == 1:
return limit(f, vars[0], values[0])
t = symbols('t')
paths = []
# 基本坐标轴路径 (每个变量单独变化)
for i in range(n):
path = {}
for j, var in enumerate(vars):
if i == j:
path[var] = values[j] + t # 当前变量沿t变化
else:
path[var] = values[j] # 其他变量固定于趋近值
paths.append(path)
# 对角线路径 (所有变量同时变化)
path_all_t = {var: values[i] + t for i, var in enumerate(vars)}
paths.append(path_all_t)
# 二次混合路径
for i in range(n):
path = {}
for j, var in enumerate(vars):
if i == j:
path[var] = values[j] + t**2 # 当前变量二次变化
else:
path[var] = values[j] + t # 其他变量线性变化
paths.append(path)
# 三角函数路径
trig_funcs = [sin(t), cos(t), tan(t), sinh(t), cosh(t)]
for func in trig_funcs:
# 单变量三角函数路径
for i in range(n):
path = {var: values[j] for j, var in enumerate(vars)}
path[vars[i]] = values[i] + func
paths.append(path)
# 双变量三角函数路径
for i in range(n):
for j in range(i+1, n):
path = {var: values[k] for k, var in enumerate(vars)}
path[vars[i]] = values[i] + func
path[vars[j]] = values[j] + func
paths.append(path)
# 计算所有路径极限
path_limits = []
for path in paths:
try:
expr = f.subs(path)
lim = limit(expr, t, 0)
path_limits.append(lim)
except:
path_limits.append(None)
# 检查路径极限一致性
valid_limits = [lim for lim in path_limits if lim is not None]
if not valid_limits:
return '重极限不存在' # 所有路径极限计算失败
if not all(lim == valid_limits[0] for lim in valid_limits):
return '重极限不存在' # 路径极限不一致
# 计算累次极限 (所有顺序)
iterated_limits = []
for perm in itertools.permutations(range(n)):
try:
current = f
for idx in perm:
current = limit(current, vars[idx], values[idx])
iterated_limits.append(current)
except:
iterated_limits.append(None)
# 检查累次极限一致性
valid_iter_limits = [lim for lim in iterated_limits if lim is not None]
if not valid_iter_limits:
return '重极限不存在' # 所有累次极限计算失败
if not all(lim == valid_iter_limits[0] for lim in valid_iter_limits):
return '重极限不存在' # 累次极限不一致
# 检查路径极限与累次极限一致性
if valid_limits[0] != valid_iter_limits[0]:
return '重极限不存在'
return valid_limits[0] # 所有检查通过,返回极限值
#偏导数:f为函数; var_list为变量及其求导次数的列表
def partial_derivative(f, var_list):
if not isinstance(var_list, list):
raise ValueError("var_list 必须是列表,例如 [('x1', 1), ('y2', 2), ('x3', 1)]")
if not all(isinstance(item, tuple) and len(item) == 2 for item in var_list):
raise ValueError("var_list 中的每个元素必须是长度为2的元组,例如 ('x', 1)")
try:
for var_s, n in var_list:
if not isinstance(var_s, str):
raise ValueError("变量名必须是字符串")
if not isinstance(n, int) or n < 0:
raise ValueError("求导次数必须是非负整数")
var = symbols(re.sub(r'\d+$', '', var_s)) # 去掉数字并转为符号
dif = diff(f, var, n)
f = dif
return dif
except Exception as e:
return f"求导失败: {e}"
#全微分:f为函数; vars为变量组成的列表
def total_differential(f, vars):
if not isinstance(vars, list):
raise TypeError("vars 必须是变量列表,例如 [x, y, z]")
if not all(isinstance(v, (str, Symbol)) for v in vars):
raise TypeError("vars 中的每个元素必须是字符串或 SymPy 符号")
try:
derivs = [0 for i in range(len(vars))]
for i in range(len(vars)):
derivs[i] = partial_derivative(f, [(str(vars[i]),1)])
diff_symbols = [Symbol(f'd{v}') for v in vars]
return sum(derivs[i]*diff_symbols[i] for i in range(len(vars)))
except Exception as e:
return f"全微分计算失败: {e}"
#梯度:f为函数; vars为变量组成的列表
def grad_vector(f, vars):
if not isinstance(vars, list):
raise TypeError("vars 必须是变量列表,例如 [x, y, z]")
if not all(isinstance(v, (str, Symbol)) for v in vars):
raise TypeError("vars 中的每个元素必须是字符串或 SymPy 符号")
try:
expr = f
return Array([diff(expr, v) for v in vars])
except Exception as e:
return f"梯度计算失败: {e}"
#方向导数:f为函数; vars为变量组成的列表; direction为方向向量
def direct_derivative(f, vars, direction):
if not isinstance(vars, list):
raise TypeError("vars 必须是变量列表,例如 [x, y, z]")
if not isinstance(direction, list):
raise TypeError("direction 必须是列表,例如 [1, 2, 3]")
if len(direction) != len(vars):
raise ValueError("方向向量维度必须与变量数量一致")
try:
grad = grad_vector(f, vars)
directs = 0
for i in range(len(vars)):
cos_ = direction[i]/sqrt((sum([i**2 for i in direction]))) #方向余弦
directs += grad[i]*cos_
return directs
except Exception as e:
return f"方向导数计算失败: {e}"
#极值、鞍点
def extrema(f, vars, domain=None):
try:
if domain is None:
domain = Reals
expr = f
derivs = [diff(expr, v) for v in vars]
system = [Eq(d, 0) for d in derivs]
# 求解临界点
if len(vars) == 1:
points = solveset(system[0], vars[0], domain=domain)
else:
points = nonlinsolve(system, vars)
# 如果解集不是 FiniteSet直接返回提示
if not isinstance(points, FiniteSet):
return f"函数在定义域 {domain} 内有复杂或无限多个临界点:{points}"
points = list(points)
# 构建黑塞矩阵
hessian = Matrix([[diff(expr, vi, vj) for vj in vars] for vi in vars])
min_p = []
max_p = []
sad_p = []
for point in points:
if len(vars) == 1:
point_dict = {vars[0]: point}
else:
point_dict = {vars[i]: point[i] for i in range(len(vars))}
# 检查 point_dict 是否包含复杂集合类型
if any(isinstance(val, (ConditionSet, Intersection, Union, ImageSet)) for val in point_dict.values()):
continue # 跳过复杂解
try:
S = hessian.subs(point_dict)
except Exception as e:
continue # 跳过无法代入的点
if S.is_positive_definite:
min_p.append(point_dict)
elif (-S).is_positive_definite:
max_p.append(point_dict)
else:
sad_p.append(point_dict)
return {'临界点': points,
'极大值点': max_p,
'极小值点': min_p,
'鞍点': sad_p}
except Exception as e:
return f'计算过程中出错: {str(e)}'
#连续性
def is_continuous(f, var_points):
limit_value = mult_limit(f, var_points)
if limit_value == '重极限不存在':
return False
func_value = f.subs(var_points)
return limit_value == func_value
#拉格朗日乘数法求条件极值
#f目标函数; constraints约束条件; vars变量列表
def lagrange_multiplier(f, constraints, vars):
if not isinstance(constraints, (list, tuple)):
return "约束条件必须是一个列表或元组"
if not isinstance(vars, (list, tuple)):
return "变量列表必须是一个列表或元组"
if len(constraints) == 0:
return "至少需要一个约束条件"
if len(vars) == 0:
return "至少需要一个变量"
try:
n = len(constraints)
λ = symbols(f'λ1:{n+1}') #拉格朗日乘子
L = f
#构造拉格朗日函数
for i in range(n):
L += λ[i] * constraints[i]
#对所有变量和乘子求偏导
equations = [diff(L, var) for var in vars] + list(constraints)
solutions = solve(equations, vars + list(λ), dict=True)
if not solutions:
return "方程组无解或无法找到解析解"
return solutions
except TypeError as e:
return f"类型错误: {str(e)} - 请确保输入的函数和约束是有效的 sympy 表达式"
except AttributeError as e:
return f"属性错误: {str(e)} - 请确保输入的函数和约束包含正确的符号变量"
except Exception as e:
return f"求解过程中发生错误: {str(e)}"

@ -0,0 +1,212 @@
import sympy
from sympy import symbols, limit, diff, Eq, solve
from convert_formula import convert_formula
def compute_limit(f, vars, points, direction=None):
"""
计算多元函数的重极限或累次极限
Args:
f (sympy.Expr): 待计算极限的多元函数表达式
vars (list[sympy.Symbol]): 函数中的变量列表[x, y]
points (list[float]): 极限点的坐标列表与vars顺序对应[1, 2]
direction (str, optional): 累次极限方向可选'x_first'先x后y'y_first'先y后x默认None表示计算重极限
Returns:
sympy.Expr: 计算得到的极限值
"""
if direction == 'x_first':
lim_x = limit(f, vars[0], points[0])
return limit(lim_x, vars[1], points[1])
elif direction == 'y_first':
lim_y = limit(f, vars[1], points[1])
return limit(lim_y, vars[0], points[0])
else:
return limit(f, *zip(vars, points))
def check_continuity(f, vars, points):
"""
检查多元函数在指定点的连续性极限值是否等于函数值
Args:
f (sympy.Expr): 待检查的多元函数表达式
vars (list[sympy.Symbol]): 函数中的变量列表
points (list[float]): 待检查点的坐标列表与vars顺序对应
Returns:
bool: 连续返回True不连续返回False
"""
f_value = f.subs(dict(zip(vars, points)))
lim = compute_limit(f, vars, points)
return Eq(lim, f_value)
def partial_derivative(f, vars_list):
"""
计算多元函数对指定变量列表的高阶偏导数按顺序求导
Args:
f (sympy.Expr): 待求导的多元函数表达式
vars_list (list[sympy.Symbol]): 求导的变量列表按求导顺序排列[x, y]表示先对x再对y求导
Returns:
sympy.Expr: 计算得到的高阶偏导数表达式
"""
return diff(f, *vars_list)
def total_differential(f, vars):
"""
计算多元函数的全微分表达式
Args:
f (sympy.Expr): 待计算全微分的多元函数
vars (list[sympy.Symbol]): 函数中的所有变量列表
Returns:
sympy.Expr: 全微分表达式如df = f_x*dx + f_y*dy
"""
diffs = [diff(f, var) for var in vars]
return sum(d * sympy.Derivative(var) for d, var in zip(diffs, vars))
def directional_derivative(f, vars, points, direction_vec):
"""
计算多元函数在指定点沿给定方向的方向导数
Args:
f (sympy.Expr): 待计算的多元函数
vars (list[sympy.Symbol]): 函数中的变量列表
points (list[float]): 计算点的坐标列表与vars顺序对应
direction_vec (list[float]): 方向向量[1, 1]表示45度方向
Returns:
float: 方向导数的数值结果
"""
grad = gradient(f, vars)
grad_val = [g.subs(dict(zip(vars, points))) for g in grad]
dir_unit = [v / sympy.sqrt(sum(d**2 for d in direction_vec)) for v in direction_vec]
return sum(g * d for g, d in zip(grad_val, dir_unit))
def gradient(f, vars):
"""
计算多元函数的梯度向量
Args:
f (sympy.Expr): 待计算的多元函数
vars (list[sympy.Symbol]): 函数中的变量列表[x, y]
Returns:
list[sympy.Expr]: 梯度向量各分量为对应变量的偏导数
"""
return [diff(f, var) for var in vars]
def find_extrema(f, vars):
"""
寻找多元函数的无条件极值点并判断极值类型
Args:
f (sympy.Expr): 待分析的多元函数
vars (list[sympy.Symbol]): 函数中的变量列表
Returns:
list[tuple[dict, str]]: 极值点信息列表每个元素为(极值点字典, 极值类型)
"""
critical_points = solve([diff(f, var) for var in vars], vars, dict=True)
hessian = sympy.hessian(f, vars)
extrema = []
for point in critical_points:
hess_val = hessian.subs(point)
eigvals = hess_val.eigenvals()
if all(v > 0 for v in eigvals):
extrema.append((point, '极小值'))
elif all(v < 0 for v in eigvals):
extrema.append((point, '极大值'))
else:
extrema.append((point, '鞍点'))
return extrema
def constrained_extrema(f, constraints, vars):
"""
使用拉格朗日乘数法求解带约束条件的极值问题
Args:
f (sympy.Expr): 目标函数待求极值的函数
constraints (list[sympy.Expr]): 约束条件列表[Eq(x**2+y**2, 1)]
vars (list[sympy.Symbol]): 函数中的变量列表
Returns:
list[dict]: 满足约束条件的极值点解包含拉格朗日乘子
"""
lambdas = symbols('lambda:' + str(len(constraints)))
lagrangian = f - sum(l * c for l, c in zip(lambdas, constraints))
equations = [diff(lagrangian, var) for var in vars] + constraints
variables = vars + list(lambdas)
solutions = solve(equations, variables, dict=True)
return solutions
def UI():
vars_dict = {'x': symbols('x'), 'y': symbols('y'), 'z': symbols('z')}
while True:
print("\n多元函数导数分析系统")
print("1. 计算重极限/累次极限")
print("2. 检查连续性")
print("3. 计算偏导数")
print("4. 计算全微分")
print("5. 计算方向导数")
print("6. 计算梯度")
print("7. 寻找无条件极值")
print("8. 求解条件极值")
print("0. 退出")
choice = input("请选择功能(0-8): ")
if choice == '0':
print("系统已退出")
break
try:
expr = convert_formula(input("请输入多元函数表达式(如x**2+y**2): "))
f = sympy.sympify(expr)
vars_list = list(f.free_symbols)
if choice in ['1','2','5','7']:
points = [float(p) for p in eval(input("请输入极限点/求值点坐标(用,分隔): "))]
if choice == '1':
direction = input("是否计算累次极限?(x_first/y_first/直接回车为重极限): ")
res = compute_limit(f, vars_list, points, direction)
print(f"计算结果: {res}")
elif choice == '2':
res = check_continuity(f, vars_list, points)
print(f"连续性判断: {res}")
elif choice == '3':
vars_input = input("请输入求偏导的变量名(用,分隔如x,y表示先对x再对y求导: ")
vars_list = [vars_dict.get(var.strip(), symbols(var.strip())) for var in vars_input.split(',')]
res = partial_derivative(f, vars_list)
print(f"偏导数结果: {res}")
elif choice == '4':
res = total_differential(f, vars_list)
print(f"全微分结果: {res}")
elif choice == '5':
dir_vec = [float(v) for v in eval(input("请输入方向向量(用,分隔): "))]
res = directional_derivative(f, vars_list, points, dir_vec)
print(f"方向导数结果: {res}")
elif choice == '6':
res = gradient(f, vars_list)
print(f"梯度结果: {res}")
elif choice == '7':
res = find_extrema(f, vars_list)
print(f"无条件极值点: {res}")
elif choice == '8':
constraints_expr = convert_formula(input("请输入约束条件表达式(用,分隔): "))
constraints = [sympy.sympify(c) for c in constraints_expr.split(',')]
res = constrained_extrema(f, constraints, vars_list)
print(f"条件极值解: {res}")
except Exception as e:
print(f"输入错误: {str(e)}")
if __name__ == '__main__':
UI()
Loading…
Cancel
Save