📜  代数表达式的最大值和最小值(1)

📅  最后修改于: 2023-12-03 15:22:03.197000             🧑  作者: Mango

代数表达式的最大值和最小值

在代数中,我们经常要求一个表达式的最大值和最小值。这在计算机中也经常用到,比如优化算法、机器学习算法等等会用到表达式的最大值和最小值。在本文中,我们将介绍如何求得代数表达式的最大值和最小值。

一、求解一元代数表达式的最大值和最小值

对于一元代数表达式,我们可以使用微积分中的导数来求解。具体来说,若函数 $f(x)$ 在区间 $[a,b]$ 内可导,那么 $f(x)$ 在 $[a,b]$ 内的最大值和最小值分别出现在 $f'(x)=0$ 的解及区间端点处。

1.1 寻找极值点

设 $f(x)$ 在区间 $[a,b]$ 内可导,那么 $f(x)$ 在 $[a,b]$ 内的极值点都是 $f'(x)=0$ 的解。因此,我们只需要找到 $f'(x)=0$ 的解即可找到所有的极值点。

1.2 判断极值点的性质

确定了极值点后,我们需要进一步判断每个极值点的性质(是最大值还是最小值)。具体来说,我们需要进一步比较 $f(x)$ 在极值点左右的大小关系。

以极大值为例,若 $f(x)$ 在极值点左侧单调递减,在极值点右侧单调递增,那么该极值点即为 $f(x)$ 的最大值。

1.3 计算端点处的取值

如果 $f(x)$ 在区间 $[a,b]$ 的端点处也能取到最大值或最小值,则需要将 $a$ 和 $b$ 代入 $f(x)$ 的表达式中进行比较。

1.4 示例代码

以下为求解一元代数表达式最大值和最小值的示例代码:

import sympy

# 定义表达式
x = sympy.Symbol('x')
f = 2*x**3-3*x**2+4*x-5

# 求导并求出解
df = sympy.diff(f, x)
solutions = sympy.solve(df, x)

# 判断每个解的性质
for s in solutions:
    f_l = f.subs(x, s-0.001) # 左侧函数值
    f_r = f.subs(x, s+0.001) # 右侧函数值
    df_s = sympy.diff(f, x, 2).subs(x,s) # 二阶导数
    if f_r < f_l and df_s > 0: # 极大值
        print(f"Max: {f_l}, x={s}")
    elif f_r > f_l and df_s < 0: # 极小值
        print(f"Min: {f_l}, x={s}")
    else: # 不是极值点
        print(f"s={s} 不是极值点")
    
# 计算端点处的取值
if f.subs(x, a) > f.subs(x, b):
    print(f"Max: {f.subs(x, a)}, x={a}")
else:
    print(f"Max: {f.subs(x, b)}, x={b}")

if f.subs(x, a) < f.subs(x, b):
    print(f"Min: {f.subs(x, a)}, x={a}")
else:
    print(f"Min: {f.subs(x, b)}, x={b}")

二、求解多元代数表达式的最大值和最小值

对于多元代数表达式,我们需要使用多元微积分中的偏导数来求解。具体来说,若函数 $f(x_1,x_2,...,x_n)$ 在区域 $D$ 内可导,那么 $f(x_1,x_2,...,x_n)$ 在 $D$ 内的最大值和最小值分别出现在 $f_{x_1}=0,f_{x_2}=0,...,f_{x_n}=0$ 及 $D$ 的边界上。

2.1 寻找驻点

设 $f(x_1,x_2,...,x_n)$ 在区块 $D$ 内可导,那么 $f(x_1,x_2,...,x_n)$ 在 $D$ 内的驻点是 $f_{x_1}=0,f_{x_2}=0,...,f_{x_n}=0$ 的解。因此,我们只需要找到 $f_{x_1}=0,f_{x_2}=0,...,f_{x_n}=0$ 的解即可找到所有的驻点。

2.2 计算 Hessian 矩阵

在找到驻点后,我们需要进一步判断驻点的性质(是最大值还是最小值)。具体来说,需要计算 Hessian 矩阵,如果该矩阵半正定,则为最小值,如果该矩阵半负定,则为最大值。

2.3 计算边界上的取值

如果 $f(x)$ 在区域 $D$ 的边界上也能取到最大值或最小值,则需要将 $D$ 的边界代入 $f(x)$ 的表达式中进行比较。

2.4 示例代码

以下为求解多元代数表达式最大值和最小值的示例代码:

import sympy
import itertools

# 定义表达式和变量
x1, x2 = sympy.symbols('x1 x2')
f = 2*x1**2 + 3*x2**2 - 4*x1*x2 - 6*x1 - 10*x2 + 5

# 求偏导并求出驻点
dfd_x1 = sympy.diff(f, x1)
dfd_x2 = sympy.diff(f, x2)
solutions = sympy.solve([dfd_x1, dfd_x2], [x1, x2])

# 计算 Hessian 矩阵
H = sympy.zeros(2,2)
H[0,0] = sympy.diff(dfd_x1, x1)
H[0,1] = sympy.diff(dfd_x1, x2)
H[1,0] = sympy.diff(dfd_x2, x1)
H[1,1] = sympy.diff(dfd_x2, x2)

# 判断每个驻点的性质
for s in solutions:
    if H.subs([(x1,s[x1]), (x2,s[x2])]).eigenvals()[1] > 0: # 驻点为极小值
        print(f"Min: {f.subs([(x1,s[x1]), (x2,s[x2])])}, x1={s[x1]}, x2={s[x2]}")
    elif H.subs([(x1,s[x1]), (x2,s[x2])]).eigenvals()[1] < 0: # 驻点为极大值
        print(f"Max: {f.subs([(x1,s[x1]), (x2,s[x2])])}, x1={s[x1]}, x2={s[x2]}")
    else: # 矩阵不定,需要进一步分析
        print("需要进一步分析")

# 计算边界上的取值
boundaries = [[x1,-1,2],[x2,-1,1]] # 定义变量、范围
combinations = itertools.product(*(sympy.Interval(s,e).as_relational(x) for (x,s,e) in boundaries)) # 计算笛卡尔积
for c in combinations:
    if f.subs([(x1,c[x1]),(x2,c[x2])]) > f.subs([(x1,c[x1]+0.001),(x2,c[x2]+0.001)]): # 边界为极大值
        print(f"Max: {f.subs([(x1,c[x1]),(x2,c[x2])])}, x1={c[x1]}, x2={c[x2]}")
    elif f.subs([(x1,c[x1]),(x2,c[x2])]) < f.subs([(x1,c[x1]+0.001),(x2,c[x2]+0.001)]): # 边界为极小值
        print(f"Min: {f.subs([(x1,c[x1]),(x2,c[x2])])}, x1={c[x1]}, x2={c[x2]}")
    else: # 不是极值点
        pass

以上就是求解代数表达式最大值和最小值的方法和示例代码。在实际应用中,我们还可以使用数值优化算法来求解最大值和最小值。