You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
7.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()