线性与非线性规划:随机方向法

文章目录

  • 前言
  • 一、随机方向法
  • 二、算法实现
    • 1.算法步骤
    • 2.算法细节
    • 3.代码示例
    • 4.示例
  • 总结


前言

本系列涉及线性与非线性规划中的几种规划算法

1.本节介绍随机方向法
2.参考:陈宝林-最优化理论与算法
3.采用python编程实现,已测试,代码可行


一、随机方向法

随机方向法是一种原理简单的直接解法,用于求解有约束问题,和参考书中的Powell方法相似。
基本原理是在可行域内选择一个初始点,然后产生若干个随机方向,并从中选择一个能使目标函数值下降最快的随机方向作为可行搜索方向,然后从初始点出发,沿着这个方向以一定步长进行搜索,得到新点且满足题目的约束条件,至此完成一次迭代。然后重复上述过程。

二、算法实现

1.算法步骤

下面是随机方向法的算法步骤
线性与非线性规划:随机方向法_第1张图片
里面涉及的部分公式如下

2.算法细节

线性与非线性规划:随机方向法_第2张图片
线性与非线性规划:随机方向法_第3张图片
线性与非线性规划:随机方向法_第4张图片

3.代码示例

#随机方向法:输入初始点,初始步长,目标函数,约束函数(G<=0),自变量的初始随机区间
import random
from sympy import *
import numpy as np
class Random_direction:
    def __init__(self,F,G,Xi,X0_R,a0,k,X0=None):
        self.f = F
        self.G = G
        self.X0_R = X0_R
        self.i = len(X0_R)#自变量个数
        self.a0 = a0
        self.Xi = Xi#定义自变量
        self.k = k #产生的随机方向数
        if not X0:
            self.random_X()
        else:
            self.x_dict(np.array(X0))
    # 生成自变量字典
    def x_dict(self,X):
        x = {}
        self.X = X
        for index,item in enumerate(self.Xi):
            x[item] = X[index]
        self.X_dict = x
    # 生成随机初始值
    def random_X(self):
        while True:
            X = []
            for index,item in enumerate(self.Xi):
                X.append(random.uniform(self.X0_R[index][0],self.X0_R[index][1]))
            if self.condition_G(np.array(X)):
                break
    # 约束条件
    def condition_G(self,X):
        self.x_dict(X)
        n = 0
        for i in self.G:
            if i.subs(self.X_dict) > 0:
                n += 1
        if n == 0:
            self.X = np.array(X)
            return 1
    # 生成随机方向
    def random_direction(self):
        ej = []
        for i in range(self.k):
            e = []
            for n in range(self.i):
                e.append(random.uniform(-1,1))
            e_j = np.array(e)
            len_e = np.linalg.norm(np.array(e_j), ord=None)
            ej.append(e_j/len_e)
        ek = np.array(ej)
        xk = self.X + self.a0*ek #所有的k个方向
        self.xk = xk
    #计算目标函数值
    def f_value(self,X):
        self.x_dict(X)
        self.fX = self.f.subs(self.X_dict)
        #self.fX = np.array(self.f.subs(self.X_dict))
        return self.fX
    # 确定下个可行点,###如何进行numpy的向量计算
    def find_XL(self):
        f_min = []
        x_min = []
        for i in self.xk:
            if self.condition_G(i):
                x_min.append(self.X)
                f_min.append(self.f_value(self.X))
        min_f = min(f_min)
        minx= x_min[f_min.index(min_f)]
        self.x_dict(minx)
        self.fL = min_f
    # 迭代计算,b1,b2分别存放收敛条件数,t0用来放缩a0,t放缩a,a1判断是否是局部点
    def iter_compute(self,t0,t,a0,a1,b1,b2):
        while True:
            X_0 = self.X#把初始值保存
            fX0 = self.f_value(X_0)
            self.random_direction()
            self.find_XL()
            if self.fL < fX0:
                d = self.X - X_0
                self.a = t*self.a0
                self.a0 = self.a
                self.X += self.a*d
                fX1 = self.f_value(self.X)#计算新的值
                if (abs(fX1 - fX0) <= b1)&(np.linalg.norm(self.X-X_0,ord=1) <= b2):
                    print(f'得到极值点X={self.X},最优值f(x*)={fX1}')
                    break
            else:
                self.a0 *= t0
                if self.a0 <= a1:
                    print(f'X0={X_0}是一个局部点,更换初始点')
                    self.random_X()

xi = symbols('x1 x2')
F = xi[0]**2+xi[1]
g1 = xi[0]**2+xi[1]**2-9
g2 = xi[0]+xi[1]-1
G= [g1,g2]
X0_R =[[-5,2],[-5,2]]
a0 = 0.5
k = 50
X0 = [-2,2]
q1 = Random_direction(F,G,xi,X0_R,a0,k,X0)
q1.iter_compute(0.5,1.3,a0,2E-15,1E-5,1E-5)

4.示例

得到极值点X=[ 0.01476 -2.9999636],最优值f(x*)=-2.99974574250101


总结

根据代码就可以理解随机方向法的思路了。

你可能感兴趣的:(线性与非线性规划,最优化,python)