Python的符号运算和函数最小值计算
符号运算计算最小值
sympy有个minimum函数可以用来计算函数的最小值。其用法如下:
# -*- coding: utf-8 -*-
import sympy
x, y = sympy.symbols('x y')
fz = x * x + 2 * x + 3 * y * y + 5
fz_min_x = sympy.minimum(fz, x)
print(fz_min_x) # 输出 3*y**2 + 4
fz_min_xy = sympy.minimum(fz_min_x, y)
print(fz_min_xy) # 输出 4
这个函数只能接收一个变量,如果需要计算多个变量的最小值,需要分多步执行。
如果需要计算函数取最小值时,各个变量的值,可以将函数对各自变量求(偏)导数后,组合方程求解:
dx = sympy.diff(fz, x)
dy = sympy.diff(fz, y)
r = sympy.solve([dx, dy], [x, y])
print(r) # 输出 {x: -1, y: 0}
用符号计算函数的极值不能设置变量的取值范围,如果在限定的范围上求函数极值,可以用scipy.optimize.minimize函数。
scipy.optimize.minimize计算函数极值
这个极小值函数里面用了另一个函数来表示待计算的函数表达式,还是有三个参数分别是设置自变量的初始值,计算极小值的方法以及自变量的取值范围。
import numpy
import scipy.optimize
def fz(var):
x, y = var[0], var[1]
return x * x + 2 * x + 3 * y * y + 5
x0 = numpy.array([1, 3])
fmin = scipy.optimize.minimize(fz, x0=x0, method='slsqp', bounds=[(0, 5), (2, 6)])
print(fmin)
# 输出
# fun: 17.0
# jac: array([ 2., 12.])
# message: 'Optimization terminated successfully'
# nfev: 6
# nit: 2
# njev: 2
# status: 0
# success: True
# x: array([0., 2.])
可用来计算一些复杂函数的极小值。
附件条件的处理方法
有些情况下计算函数的极小值,会有一些附加的条件,比如:
y = f(a,b,c,d)
g(a,b,c) = 0
这种情况下 可以考虑如下的计算方法:
如果g(a,b,c) 函数比较简单,可以转化为 a = h(b,c)的形式,代入函数 y,可消除一个自变量,然后用scipy.optimize.minimize函数求解
如果 g(a,b,c) 计算复杂,一种方式是使用sympy 来进行消元计算,第二种方式是 设 y = f(a,b,c,d) + k * g(a,b,c)**2 ,k取值为一个比较大的正数,再使用scipy.optimize.minimize函数求解,但这样算出来的结果只是一个近似值,可能并不能严格满足 g(a,b,c) = 0的条件