wasd 10 months ago
parent 78bf0c8788
commit 1f9ee3f6a8

301
极限

@ -0,0 +1,301 @@
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)}"
Loading…
Cancel
Save