非线性规划——凸优化、凸函数、凸规划(二)

凸规划是指若最优化问题的目标函数为凸函数,不等式约束函数也为凸函数,等式约束函数是线性的。凸规划的可行域为凸集,因而凸规划的局部最优解就是它的全局最优解。当凸规划的目标函数为严格凸函数时,若存在最优解,则这个最优解一定是唯一的最优解

一、凸集

凸集:Cn维欧式空间的一个集合,若C内任意两点间的线段也均在C内,则称集合C为凸集。即

x1,x2C,θ[0,1]x=θx1+(1θ)x2C

凸组合(convex combination):
λ1x1++λkxk

其中,λ1,,λk0,λi=1,二元 k1x1+(1k1)x2就是一个凸组合。

凸集有良好的运算性质:(1) 交集为凸集。(2) 和集为凸集。(3) 直和为凸集。

超平面hyperplane:H={x|aTx=b}(a0);

半平面halfspace:H+=x|aTxb(a0)H={x|aTxb}(a0);

多面体polyhedra:多个线性不等式所刻画的集合:{x|aiTxbi,i=1,,m}
注:线性等式刻画的集合也是多面体!(可以将等式转换为两个不等式,线性规划里称为单纯形

椭球(Ellipsoid):

{x|(xxc)TP1(xxc)1};P;λi

二、凸函数

f为定义在区间I上的函数,若对I上的任意两点x1,x2和任意λ(0,1)

f(λxi+(1λ)x2)λf(xi)+(1λ)f(x2)

将""换成"<"也成立则就是严格凸函数。

性质1: 设 f:Rn>R1C是凸集,若f是凸函数,则对于任意的β,水平集Dβ={x|f(x)β,xC}是凸集。

性质2 : 凸优化问题的局部极小值是全局极小值。

性质3: 若f一阶可微,则函数f为凸函数当且仅当f的定义域domf为凸集,且x,ydomf,f(y)f(x)+f(x)T(yx)

性质4:若f二阶可微,则函数f为凸函数当且仅当f的定义域domf为凸集,且2f(x)0

正定:f(x1,x2,...,xn)=xTAx,(所有的二次齐次式都可以写成这个形式)如果对任意的x0f(x)>0,则称(f(x)为正定二次型,同时称A为正定矩阵。

[定理]f(x):RnR是在凸集XRn上二阶可微。f(x)是凸函数的充分必要条件是f(x)的二阶海塞矩阵2f(x)是半正定的;f(x)是凹函数的充分必要条件是f(x)的二阶海塞矩阵2f(x)是半负定的。

例1:判断下述函数的凸凹性:
(1)f(x)=ex
(2)f(x)=x12
(3)f(x1,x2)=2+x1+x2x12x22
解:
(1) f(x)=ex0, 所以 f(x) 函数是凸集 R 上的的凸函数.
(2) f(x)=14x3/20, 所以 f(x) 函数是凸集 R 上的的凹函数.
(3) f(x1,x2) 的 Hessian 矩阵为:

2f(x)=[2002]

为了判断 2f(x) 的半正 (负) 定性, 计算:

def(2f(x)λI)=def[2λ002λ]=(2λ)2=0

那么, λ1=λ2=2, 所以矩阵 2f(x) 为负定矩阵, f(x) 为凸集 R 上的凹函数.

三、凸规划

基本形式:

minf(x)s.tgi(x)0i=1,,mhj(x)=0j=1,,l

[定理] 上面规划是凸规划的充分条件为:(1)f(x):CR是凸函数;(2)hj:RnR,j=1,2,...,l, 都是线性函数;(3)gi:RnR,i=1,2,...,m, 都是凸函数(gi是凹函数)。

例2:判断下述规划是否为凸规划

minf(X)=x12+x224x1+4{g1(X)=x1+x220g2(X)=x12x2+10x1,x20

解:

2f(X)=[2fx122fx1x22fx2x12fx22]=[2002]

2g1(X)=[2g1x122g1x1x22g1x2x12g1x22]=[0000],2g2(X)=[2g2x122g2x1x22g2x2x12g2x22]=[2000]

该问题是凸规划,有最小值x=(x1,x2)=(1.62,3.62)Tf(x)=13.25,参看下图。

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

# 定义目标函数
def objective(X):
    x1, x2 = X
    return x1**2 + x2**2 - 4*x1 + 4

# 定义约束函数
def constraint1(X):
    return -X[0] + X[1] - 2

def constraint2(X):
    return X[0]**2 - X[1] + 1

# 初始猜测值
initial_guess = [0.5, 0.5]

# 定义约束
constraints = [
    {'type': 'ineq', 'fun': constraint1},
    {'type': 'ineq', 'fun': constraint2},
    {'type': 'ineq', 'fun': lambda X: X[0]},  # x1 >= 0
    {'type': 'ineq', 'fun': lambda X: X[1]}   # x2 >= 0
]

# 记录迭代点
history = []
def callback(X):
    history.append(np.copy(X))

# 进行优化
result = minimize(objective, initial_guess, method='SLSQP', constraints=constraints, callback=callback)

# 打印优化结果
print("Optimization Result:")
print(f"Success: {result.success}")
print(f"Minimum Value of the Function: {result.fun:.2f}")
print(f"Point at which Minimum Occurs: x1 = {result.x[0]:.2f}, x2 = {result.x[1]:.2f}")
print(f"Number of Iterations: {result.nit}")

# 生成等高线图
x1 = np.linspace(-1, 3, 400)
x2 = np.linspace(-1, 5, 600)
X1, X2 = np.meshgrid(x1, x2)
Z = X1**2 + X2**2 - 4*X1 + 4

plt.figure(figsize=(15, 9))
cp = plt.contour(X1, X2, Z, levels=np.logspace(-1, 3, 20), cmap='jet', linewidths=1.5)
plt.colorbar(cp)

# 绘制约束边界
x1_vals = np.linspace(0, 3, 400)
x2_g1 = x1_vals + 2
x2_g2 = x1_vals**2 + 1

plt.plot(x1_vals, x2_g1, 'r--', label='$g_1(x_1, x_2) = 0$', linewidth=1.5)
plt.plot(x1_vals, x2_g2, 'g--', label='$g_2(x_1, x_2) = 0$', linewidth=1.5)

# 绘制可行域
plt.fill_between(x1_vals, np.maximum(x2_g1, 0), 5, color='gray', alpha=0.3)

# 绘制优化路径
history = np.array(history)
plt.plot(history[:, 0], history[:, 1], 'ro-', label='Optimization Path', markersize=5, linewidth=1.5)
plt.plot(result.x[0], result.x[1], 'wo', label='Minimum', markersize=14, markeredgewidth=3, markeredgecolor='black')

# 设置图形参数
plt.title("Contour Plot with Optimization Path")
plt.xlabel('$x_1$')
plt.ylabel('$x_2$')
plt.legend()
plt.xlim(-1, 3)
plt.ylim(-1, 5)
plt.grid()
plt.show()
Optimization Result:
Success: True
Minimum Value of the Function: 13.24
Point at which Minimum Occurs: x1 = 1.62, x2 = 3.62
Number of Iterations: 7

例3:判断下述规划是否为凸规划

min(f(x1,x2,x3)=2x12+x22+2x32+x1x3x1x2+2x2g1(x)=x12+x22x30g2(x)=x1+x2+2x316g3(x)=x1x2+x30

目标函数的凸性

一个函数是凸的,当且仅当其 Hessian 矩阵(即二阶偏导数矩阵)是半正定的。计算目标函数的 Hessian 矩阵:

H=[2fx122fx1x22fx1x32fx2x12fx222fx2x32fx3x12fx3x22fx32]

计算各二阶偏导数:

2fx12=4,2fx22=2,2fx32=42fx1x2=1,2fx1x3=1,2fx2x3=0

因此,Hessian 矩阵为:

H=[411120104]

计算 Hessian 矩阵的特征值来判断其是否为半正定。使用 NumPy 进行计算:

import numpy as np
H = np.array([
    [4, -1, 1],
    [-1, 2, 0],
    [1, 0, 4]
])

# 计算特征值
eigenvalues = np.linalg.eigvals(H)
print("Hessian Matrix Eigenvalues:", eigenvalues)

如果所有特征值均为非负,则 Hessian 矩阵为半正定,即目标函数为凸函数。

约束条件的凸性
约束条件为等式约束,需要检查其是否为仿射函数(即线性函数和常数项的和)。一个仿射函数既是凸函数也是凹函数。
(g1(x)=x12+x22x3) —— 非线性函数,不是仿射函数,因此可能不是凸函数。
(g2(x)=x1+x2+2x316) —— 线性函数,是仿射函数,因此是凸函数。
(g3(x)=x1x2+x3)—— 线性函数,是仿射函数,因此是凸函数。

由于 g1(x) 是非线性函数,我们需要检查其 Hessian 矩阵是否为半正定。计算 g1(x)的 Hessian 矩阵:

Hg1=[200020000]

这个矩阵的特征值是 [2,2,0],均为非负,因此 g1(x) 也是凸函数。

结论

  • 目标函数的 Hessian 矩阵是否为半正定需要通过特征值检查。
  • 约束条件 g1(x)为凸函数(Hessian 矩阵半正定)。
  • 约束条件g2(x)g3(x) 为仿射函数,因此是凸函数。

通过上述分析,目标函数和所有约束条件均为凸函数,这意味着该非线性规划问题是一个凸规划问题。

#求解x1 = 2.67;x2 = 2.67;x3 = 5.33,最小化目标函数值: 93.33
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.optimize import minimize

# 定义目标函数
def objective(x):
    x1, x2, x3 = x
    return 2*x1**2 + x2**2 + 2*x3**2 + x1*x3 - x1*x2 + x1 + 2*x2

# 定义约束条件
def constraint1(x):
    x1, x2, x3 = x
    return x1**2 + x2**2 - x3

def constraint2(x):
    x1, x2, x3 = x
    return x1 + x2 + 2*x3 - 16

def constraint3(x):
    x1, x2, x3 = x
    return -x1 - x2 + x3

# 初始猜测
x0 = [0, 0, 0]

# 约束条件字典
cons = [{'type': 'eq', 'fun': constraint1},
        {'type': 'eq', 'fun': constraint2},
        {'type': 'eq', 'fun': constraint3}]

# 运行优化
solution = minimize(objective, x0, constraints=cons)

# 提取优化结果
x1_opt, x2_opt, x3_opt = solution.x

# 打印结果
print("最优解:")
print("x1 =", x1_opt)
print("x2 =", x2_opt)
print("x3 =", x3_opt)
print("最小化目标函数值:", objective(solution.x))

# 准备数据以进行绘制
x1 = np.linspace(-100, 100, 200)
x2 = np.linspace(-100, 100, 200)
x1, x2 = np.meshgrid(x1, x2)
x3 = (x1**2 + x2**2)  # 从constraint1求解x3

# 计算目标函数值
h = 2*x1**2 + x2**2 + 2*x3**2 + x1*x3 - x1*x2 + x1 + 2*x2
h1 = x1**2 + x2**2 - x3
h2 = x1 + x2 + 2*x3 - 16
h3 = -x1 - x2 + x3

# 绘制图像
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 绘制目标函数值
ax.plot_surface(x1, x2, h, color='r', alpha=0.3)

# 绘制约束条件
ax.plot_surface(x1, x2, h1, color='b', alpha=0.3)
ax.plot_surface(x1, x2, h2, color='g', alpha=0.3)
ax.plot_surface(x1, x2, h3, color='y', alpha=0.3)

# 标记最优解
ax.scatter(x1_opt, x2_opt, objective([x1_opt, x2_opt, x3_opt]), color='k', marker='o', s=100)

ax.set_xlabel('x1')
ax.set_ylabel('x2')
ax.set_zlabel('Objective function value')
plt.show()

例4:求Rosenbrock 香蕉函数f(x,y)=(2x)2+100(yx2)2的最小值

  • 一阶偏导数
    函数的梯度为:

f(x,y)=(fxfy)

其中:

fx=2(200x3200xy+x2)fy=200(yx2)

将这些导数设为零得到临界点:

2(200x3200xy+x2)=0200(yx2)=0

解这些方程得到:

x=2y=4

  • 海森矩阵
    函数的海森矩阵为:

2f(x,y)=(2fx22fxy2fyx2fy2)

其中:

2fx2=1200x2400y+22fxy=400x2fyx=400x2fy2=200

代入(x,y)=(2,4)我们得到:

2f(x,y)=(3202800 800200)

  • 判断其是否为正定矩阵
    首先,我们检查海森矩阵是否对称,它是。然后我们检查它是否满足正定矩阵的任意一个定理。对于2x2矩阵,我们可以通过行列式来判断:

a11=3202|a11a12a21a22|=3202×200(800)×(800)=400

  • 求最小值
    上面求了半天只求了局部极小值。
    局部极小值并不一定是最小值,极大值也不一定大于极小值,可以通过求出所有的极值,选择其中最小的就是最小值。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

# 定义Rosenbrock's banana function
def rosenbrock_banana(x):
    return (2 - x[0])**2 + 100 * (x[1] - x[0]**2)**2

# 定义函数以记录每次迭代的点
history = []
def callback(xk):
    history.append(np.copy(xk))

# 初始猜测值
initial_guess = [0, 0]

# 使用BFGS算法进行优化,并记录迭代过程
result = minimize(rosenbrock_banana, initial_guess, method='BFGS', callback=callback)

# 打印优化结果
print("Optimization Result:")
print(f"Success: {result.success}")
print(f"Minimum Value of the Function: {result.fun:.2f}")
print(f"Point at which Minimum Occurs: x = {result.x[0]:.2f}, y = {result.x[1]:.2f}")
print(f"Number of Iterations: {result.nit}")

# 生成函数的等高线图
x = np.linspace(-1, 3, 400)
y = np.linspace(-1, 5, 600)
X, Y = np.meshgrid(x, y)
Z = rosenbrock_banana([X, Y])

plt.figure(figsize=(10, 6))
cp = plt.contour(X, Y, Z, levels=np.logspace(-1, 3, 20), cmap='jet')
plt.colorbar(cp)
plt.plot([x[0] for x in history], [x[1] for x in history], 'ro-', label='Optimization Path', markersize=5)
plt.plot(result.x[0], result.x[1], 'wo', label='Minimum', markersize=12, markeredgewidth=2, markeredgecolor='black')
plt.title("Contour Plot of Rosenbrock's Banana Function with Optimization Path")
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.xlim(-1, 3)
plt.ylim(-1, 5)
plt.show()
Optimization Result:
Success: True
Minimum Value of the Function: 0.00
Point at which Minimum Occurs: x = 2.00, y = 4.00
Number of Iterations: 30

凸规划的可行域为凸集,其局部最优解即为全局最优解,而且其最优解的集合形成一个凸集。当凸规划的目标函数f(x)为严格凸函数时,其最优解必定唯一(假定最优解存在)。由此可见,凸规划是一类比较简单而又具有重要理论意义的非线性规划。

参考文献

  1. 机器学习——凸优化
  2. 凸集、凸函数与凸规划
  3. 支持向量机 数学推导 Part2
posted @   郝hai  阅读(3241)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示