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