外點(diǎn)复亏、內(nèi)點(diǎn)和混合罰函數(shù)法(最優(yōu)化3)

最優(yōu)化實(shí)驗(yàn)報(bào)告

——外點(diǎn)趾娃、內(nèi)點(diǎn)和混合罰函數(shù)法

實(shí)驗(yàn)?zāi)康?/h2>

之前我們已經(jīng)實(shí)驗(yàn)過無約束最優(yōu)化問題,這次我們將實(shí)驗(yàn)一下缔御,在有約束條件下抬闷,優(yōu)化算法應(yīng)該怎么做。

由于處理約束條件的辦法不同,約束優(yōu)化法可以分為直接間接兩類笤成。間接法的思想是將問題轉(zhuǎn)化成無約束的评架,然后無約束方法求解,雖然算法復(fù)雜炕泳,但可以求解高維問題纵诞,效率高、魯棒性好培遵。直接法構(gòu)造迭代過程浙芙,使迭代點(diǎn)在可行域D中,一步一步降低目標(biāo)函數(shù)值籽腕。算法簡單嗡呼,但是計(jì)算量大,一般只用于求解不等式約束問題皇耗。

罰函數(shù)法又稱乘子法南窗,是指將有約束最優(yōu)化問題轉(zhuǎn)化為求解無約束最優(yōu)化問題:其中M為足夠大的正數(shù), 起"懲罰"作用郎楼, 稱之為罰因子万伤,F(xiàn)(x, M )稱為罰函數(shù)。內(nèi)部罰函數(shù)法也稱為障礙罰函數(shù)法呜袁。

這種方法是在可行域內(nèi)部進(jìn)行搜索壕翩,約束邊界起到類似圍墻的作用,如果當(dāng)前解遠(yuǎn)離約束邊界時(shí)傅寡,則罰函數(shù)值是非常小的放妈,否則罰函數(shù)值接近無窮大的方法。在進(jìn)化計(jì)算中荐操,研究者選擇外部罰函數(shù)法的原因主要是該方法不需要提供初始可行解芜抒。其中B(x)是優(yōu)化過程中新的目標(biāo)函數(shù),Gi和Hj分別是約束條件gi(x)和hj(x)的函數(shù)托启,ri和cj是常數(shù)宅倒,稱為罰因子。

本次實(shí)驗(yàn)將驗(yàn)證間接法中的內(nèi)點(diǎn)屯耸、外點(diǎn)拐迁、混合罰函數(shù)法。

實(shí)驗(yàn)環(huán)境

本次實(shí)驗(yàn)疗绣,使用的程序語言為Python3.5.2线召,使用符號系統(tǒng)解析法推導(dǎo)計(jì)算,依賴的工具包為:

import math

import sympy

import numpy as np

from matplotlib import pyplot as plt

from mpl_toolkits.mplot3d import Axes3D

要想在IDE(集成開發(fā)環(huán)境)中實(shí)現(xiàn)畫圖的交互式效果多矮,還得寫

plt.ion()

實(shí)驗(yàn)內(nèi)容及步驟

  • 定義函數(shù)和符號
  • 求解最優(yōu)X
  • 畫出構(gòu)造函數(shù)變化圖

1. 外點(diǎn)罰函數(shù)法基本原理與步驟

問題:

minf(X)=?x1+x2

s.t.{g1(X)=lnx2≥0h1(X)=x1+x2?1≥0

構(gòu)造一個(gè)增廣函數(shù):

F(X,Mk)=f(X)+Mkα(X)

其中懲罰函數(shù):

α(X)=∑j=1m[hj(X)]2+∑i=1l[gi(X)]2u(gi(X))

α(X){0,當(dāng)X∈D時(shí),0,當(dāng)X?D時(shí).

u(gi(X))={0,當(dāng)gi(X)≥0時(shí),1,當(dāng)gi(X)<0時(shí).i=1,2,?,l.

Mk
是一個(gè)逐漸增大的參數(shù)缓淹,稱為懲罰因子哈打。


當(dāng)X∈D
時(shí)

F(X,Mk)=f(X)

算法流程圖:


  1. 內(nèi)點(diǎn)罰函數(shù)法基本原理與步驟

問題:

x(1+1)3+x213min

s.t.{g1(X)=x1?1≥0,g2(X)=x2≥0.

構(gòu)造一個(gè)增廣函數(shù):

F(X,rk)=f(X)+rk∑i=1l1gi(X)

其中rk
稱為障礙因子。


算法流程圖:


  1. 混合罰函數(shù)法基本原理與步驟

問題:

minf(X)=?x1+x2

s.t.{g1(X)=lnx2≥0h1(X)=x1+x2?1≥0

構(gòu)造一個(gè)增廣函數(shù):

F(X,rk)=f(X)+rk∑i=1l1gi(X)+1rk∑j=1m[hj(X)]2

算法流程圖:

實(shí)驗(yàn)結(jié)果及分析

  1. 外點(diǎn)罰函數(shù)法:

起初讯壶,實(shí)驗(yàn)發(fā)生了錯(cuò)誤料仗,使用數(shù)值計(jì)算的方法做最速下降收斂增廣函數(shù),在接近理論最優(yōu)解時(shí)伏蚊,梯度爆炸立轧,變得很大,經(jīng)過多次參數(shù)調(diào)整躏吊,也只能求得不精確(+-0.02)的解氛改。

然后使用了 符號解析法 ,配合 最優(yōu)步長法 颜阐,取得了極好的效果。

起始點(diǎn):


迭代中逐漸增大非可行域的值(Z軸數(shù)值F明顯變化吓肋,最優(yōu)解也在變):


經(jīng)過幾十次迭代凳怨,就取得最后結(jié)果:


  1. 內(nèi)點(diǎn)罰函數(shù)法

吸取調(diào)參經(jīng)驗(yàn)教訓(xùn),結(jié)合間接求解有約束問題能轉(zhuǎn)化成無約束問題是鬼,并且函數(shù)顯然在定義域內(nèi)連續(xù)可導(dǎo)肤舞。所以,這次直接用了解非線性方程組均蜜,求極值取極限的方法李剖。

很快取得了結(jié)果:


  1. 混合罰函數(shù)法

復(fù)用上一題程序,只需改進(jìn)解的可行范圍檢查即可得:


程序

失敗的數(shù)值計(jì)算方法——會爆炸.py

'''
失敗的數(shù)值方法
'''
import sympy
import math
import numpy as np


C = 10  # 放大系數(shù)
M = 1  # 懲罰因子
epsilon = 1e-5  # 終止限

f=lambda x:-x[0] + x[1]

h=lambda x:x[0] + x[1] - 1
g=lambda x:max(-math.log(x[1]),0)

alpha=lambda x:h(x)**2+g(x)**2
F=lambda x:f(x)+M*alpha(x)

# 梯度下降來最小化F
def GD(x):
    delta_x = 1e-11  # 數(shù)值求導(dǎo)
    t = 0.0001  # 步長
    # t=sympy.symbols('t')
    e = 0.01  # 極限
    # my_print(e)
    np.array(x)
    for i in range(500):
        grad = np.asarray([(F([x[0] + delta_x, x[1]]) - F(x)) / delta_x, (F([x[0], x[1] + delta_x]) - F(x)) / delta_x])
        # print('x',x)
        print('g',grad)
        # t=sympy.solve(sympy.diff(F(x-t*grad),t),t)
        x = x - t * grad
        #         my_print(np.linalg.norm(grad))
        if (np.linalg.norm(grad) < e):
            # print(np.linalg.norm(grad))
            # print('g', grad)
            break
    return list(x)
    pass


x = [-0.5, 0.2]
for i in range(20):
    x = GD(x)
    print('-------', i, x)

    if (M * alpha(x) <= epsilon):
        print(alpha(x))
        break
    else:
        M = C * M
print(x, f(x))

外點(diǎn)罰.py

'''
這是有用的
外點(diǎn)罰函數(shù)
'''

import math
import sympy
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.ion()
fig = plt.figure()
ax = Axes3D(fig)
def draw(x,index,M):

    # F = f + MM * alpha
    # FF = sympy.lambdify((x1, x2), F, 'numpy')
    Z = FF(*(X, Y,M))
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow',alpha=0.5)
    ax.scatter(x[0], x[1], FF(*(x[0],x[1],M)), c='r',s=80)
    ax.text(x[0], x[1], FF(*(x[0],x[1],M)), 'here:(%0.3f,%0.3f)' % (x[0], x[1]))
    ax.set_zlabel('F')  # 坐標(biāo)軸
    ax.set_ylabel('X2')
    ax.set_xlabel('X1')

    plt.pause(0.1)
    # plt.show()

    # plt.savefig('./image/%03d' % index)
    plt.cla()
C = 10  # 放大系數(shù)
M = 1  # 懲罰因子
epsilon = 1e-5  # 終止限

x1, x2 = sympy.symbols('x1:3')
MM=sympy.symbols('MM')
f = -x1 + x2
h = x1 + x2 - 1
# g=sympy.log(x2) if sympy.log(x2)<0 else 0
g = sympy.Piecewise((x2-1, x2 < 1), (0, x2 >= 1))
# u=lambda x:
alpha = h ** 2 + g ** 2
F = f + MM * alpha


# 梯度下降來最小化F
def GD(x,M,n):
    # F = f + M * alpha
    # delta_x = 1e-11  # 數(shù)值求導(dǎo)
    # t = 0.0001  # 步長

    e = 0.001  # 極限
    # my_print(e)
    np.array(x)
    for i in range(15):
        t = sympy.symbols('t')
        grad = np.asarray(
            [sympy.diff(F, x1).subs([(x1, x[0]), (x2, x[1]),(MM,M)]), sympy.diff(F, x2).subs([(x1, x[0]), (x2, x[1]),(MM,M)])])

        # print('g',grad)
        # print((x-t*grad))
        # print(F.subs([(x1,(x-t*grad)[0]),(x2,(x-t*grad)[1])]))
        t = sympy.solve(sympy.diff(F.subs([(x1, (x - t * grad)[0]), (x2, (x - t * grad)[1]),(MM,M)]), t), t)
        print('t',t)
        x = x - t * grad
        print('x', x)
        # print('mmm',M)
        draw(x,n*10+i,M)
        #         my_print(np.linalg.norm(grad))
        # print(type(grad))
        if (abs(grad[0]) < e and abs(grad[1]) < e):
            # print(np.linalg.norm(grad))
            print('g', grad)
            break
    return list(x)
    pass


x = [-0.5, 0.2]

X = np.arange(0, 4, 0.25)
Y = np.arange(0, 4, 0.25)
X, Y = np.meshgrid(X, Y)
FF = sympy.lambdify((x1, x2,MM), F, 'numpy')
# ff=sympy.lambdify((x1, x2), f, 'numpy')
for n in range(5):
    x = GD(x,M,n)
    # print(FF(*(x[0],x[1],M)))

    print('-------', n, x)
    if (M * alpha.subs([(x1, x[0]), (x2, x[1])]) <= epsilon):
        print("aaaaaaaaaaaa", M*alpha.subs([(x1, x[0]), (x2, x[1])]))
        break
    else:
        M = C * M
        # print(M)
print("實(shí)際最優(yōu)值",x,FF(*(x[0],x[1],M)))
print("理論最優(yōu)值",FF(*(0,1,0)))

內(nèi)點(diǎn)罰.py

'''
內(nèi)點(diǎn)罰函數(shù)

'''
import sympy
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
plt.ion()

fig = plt.figure()
ax = Axes3D(fig)

def draw(ff, x, name):

    X = np.arange(0, 4, 0.25)
    Y = np.arange(0, 4, 0.25)
    X, Y = np.meshgrid(X, Y)
    Z = ff(*(X, Y))
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow', alpha=0.5)
    ax.scatter(x[0], x[1], ff(*(x)), c='r', s=80)
    ax.text(x[0], x[1], ff(*(x)), 'here:(%0.3f,%0.3f)' % (x[0], x[1]))
    ax.set_zlabel('f')  # 坐標(biāo)軸
    ax.set_ylabel('X2')
    ax.set_xlabel('X1')

    plt.pause(0.2)
    plt.savefig(name)
    plt.cla()


# 極值法最小化F
def OPT(F, x1, x2, r):
    x = [[]] * 2
    # 1 F(x1,x2,r)
    # 2 偏導(dǎo)
    F_x1 = sympy.diff(F, x1)
    F_x2 = sympy.diff(F, x2)
    # print(F_x1)
    # print(F_x2)
    # 3 求解
    # try:
    #     sol=[sympy.solve(F_x1,x1,real=True),sympy.solve(F_x2,x2,real=True)]
    # except NotImplementedError:
    sol = sympy.nonlinsolve([F_x1, F_x2, sympy.Eq(F_x1, F_x2)], [x1, x2])
    # print('sol_set:', sol)
    # exit(0)
    # sol=[sol[0][0],sol[1][0]]
    # print(sol)
    # 4 取極限判斷
    x_set = []
    for s in sol:
        x_temp = [[]] * 2
        for i, x_ in enumerate(s):
            x_ = sympy.limit(x_, r, 0)
            x_temp[i] = x_
        # print(x_temp)
        x_set.append(x_temp)
    return x_set
    # s_set=[[x01,x02,x03],[]]
    pass


if __name__ == '__main__':

    ####################### start
    # 定義
    x1, x2 = sympy.symbols('x1:3')
    r = sympy.symbols('r')
    f = 1 / 3 * (x1 + 1) ** 3 + x2
    g1 = x1 - 1
    g2 = x2
    alpha = 1 / g1 + 1 / g2
    F = f + r * alpha
    # c = 0.1  # 縮小系數(shù)
    # r = 10  # 障礙因子
    # epsilon = 1e-5  # 終止限
    # x = [3, 4]

    ff = sympy.lambdify((x1, x2), f, 'numpy')
    x_set = OPT(F, x1, x2, r)
    # print(x_set)
    # 判斷得到符合條件的解
    account=0
    for x in x_set:
        if (g1.subs(x1, x[0]) >= 0 and g2.subs(x2, x[1]) >= 0):
            print(x)
            draw(ff, x, './image1/6_'+str(account))
            print("實(shí)際"+str(account), x, ff(*(x)))
            account+=1
    print("理論最優(yōu)值", ff(*(1, 0)))

混合罰.py

'''
混合罰函數(shù)法
'''
import sympy

from OP6_2 import OPT, draw

if __name__ == '__main__':
    # x = [0.00000, 1.00000]
    ####################### start
    # 定義
    x1, x2 = sympy.symbols('x1:3')
    r = sympy.symbols('r')

    f = -x1 + x2
    h = x1 + x2 - 1
    # g = sympy.log(x2)
    g = x2 - 1
    F = f + r * 1 / g + 1 / sympy.sqrt(r) * h ** 2

    # epsilon = 1e-5  # 終止限

    ff = sympy.lambdify((x1, x2), f, 'numpy')
    x_set = OPT(F, x1, x2,r)
    # 判斷得到符合條件的解
    account = 0
    for x in x_set:
        if (g.subs([(x1,x[0]),(x2,x[1])])>=0 and h.subs([(x1,x[0]),(x2,x[1])])==0):
            print(x)
            draw(ff, x, './image1/7_' + str(account))
            print("實(shí)際" + str(account), x, ff(*(x)))
            account += 1
    print("理論最優(yōu)值",ff(*(1,0)))

im2gif.py

'''
轉(zhuǎn)成動(dòng)圖
'''
import os
import imageio


def create_gif(image_list, gif_name):
    frames = []
    for image_name in image_list:
        frames.append(imageio.imread(image_name))
        # Save them as frames into a gif
    imageio.mimsave(gif_name, frames, 'GIF', duration=0.2)

    return


def main():
    os.chdir('./image/')
    image_list = os.listdir('./')
    gif_name = 'created_gif.gif'
    create_gif(image_list, gif_name)


if __name__ == "__main__":
    main()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末囤耳,一起剝皮案震驚了整個(gè)濱河市篙顺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌充择,老刑警劉巖德玫,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異椎麦,居然都是意外死亡宰僧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門观挎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琴儿,“玉大人,你說我怎么就攤上這事嘁捷≡斐桑” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵雄嚣,是天一觀的道長谜疤。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么夷磕? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任履肃,我火速辦了婚禮,結(jié)果婚禮上坐桩,老公的妹妹穿的比我還像新娘尺棋。我一直安慰自己,他們只是感情好绵跷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布膘螟。 她就那樣靜靜地躺著,像睡著了一般碾局。 火紅的嫁衣襯著肌膚如雪荆残。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天净当,我揣著相機(jī)與錄音内斯,去河邊找鬼。 笑死像啼,一個(gè)胖子當(dāng)著我的面吹牛俘闯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忽冻,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼真朗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了僧诚?” 一聲冷哼從身側(cè)響起遮婶,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湖笨,沒想到半個(gè)月后蹭睡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赶么,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年肩豁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辫呻。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡清钥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出放闺,到底是詐尸還是另有隱情祟昭,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布怖侦,位于F島的核電站篡悟,受9級特大地震影響谜叹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搬葬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一荷腊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧急凰,春花似錦女仰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至床三,卻和暖如春一罩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撇簿。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工聂渊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人补疑。 一個(gè)月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓歧沪,卻偏偏與公主長得像歹撒,于是被迫代替她去往敵國和親莲组。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容