目標函式存在累加的非線性優化問題的求解思路zzzzzzzzzzzzzzzzzzzz(1)

愛情就想流沙發表於2022-01-04

馬上要畢業了,最近正在弄畢業論文(快馬加編),這幾天被一個優化問題卡住了,花了點時間對matlab和lingo的對非線性規劃問題的求解方法進行了一個總結,適合小白或者懂一點點相關知識的朋友,希望能幫上有需要的朋友,要是哪裡有問題歡迎交流,但是不要罵我,我玻璃心。

首先簡單說一下線性規劃問題的形式,下面是矩陣形式:

 

一般就是上面這種形式,一個優化問題中可能存在不等式約束、等式約束、變數範圍約束和變數型別約束。先來個簡單的例項:

 

 

如果用matlab求解,要先把它轉化成標準型(標準型為求極小值,約束條件中常數項在右側):

 

 

來看matlab的求解方法:

Matlab的非線性約束最優化問題的求解器是fmincon,如果要解線性問題或者無約束問題也有類似的求解器,呼叫方式都差不多。

求解器的具體形式是: [x,fval]=fmincon(fun,x0,A,b,Aeq,beq,lb,ub)

這裡的fun就是優化目標,x0是初始解,A是不等式約束的係數項,b是不等式約束對應的常數項,Aeq,beq對應等式約束,lb與xb就是範圍約束。Fun,x0,A,b為必選,其他的為可選。x是求解器得到的解,fval是求解器得到的最優值。

由於我們的約束中只存在不等式約束,所以只需要設定fun,x0,A,b。

fun就是我們的優化目標,這裡可以利用matlab的匿名函式(優化目標簡單的時候就可以用匿名函式),具體形式是:

  fun=@(x) -x(1)*x(2)*x(3)

這裡的@是用於宣告變數,@(x)就是表示我們的自變數為x。

之後就是A與b:

  A = [1,2,3;-1,-2,-3]

  b = [72;0]

A與b的每一行要對應,用;來分割行

x0是初始解,需要我們自己設定,這個理論上隨便設定,這裡設定為:

  x0 = [5,5,5]

在優化問題中可能存在多個解,我們可以試著多次改變x0,看看能不能得到其他解。

下面就是整體程式碼:

  fun=@(x) -x(1)*x(2)*x(3);

  A = [1,2,3;-1,-2,-3];

  b = [72;0];

  x0 = [5,5,5];

  [x,fval]=fmincon(fun,x0,A,b);

執行之後在matlab的變數欄就能看到求解結果了。

 

但其實很多時候,我們的目標函式不可能這麼簡單,比如我們的優化目標中存在變數累加的情況,或者約束條件中存在奇怪的形式,如我要解的東西就存在下面形式:

 

這看著還可以,但寫起來很噁心的,特別是這種累加形式,理論上我們可以把累加拆開,然後採用匿名函式的形式,一個一個寫(我一開始就這麼幹的),結果我的目標函式就變成了:

 

 

 

這只是一部分,我還沒寫完,寫到一半發現好丟人啊,這也太沒水平了。

感覺這種累積形式的函式應該能用for迴圈來寫,但由於之前沒怎麼寫過也不太明白。後面百度搜了一下也沒搜到相關內容,可能是我沒學好資訊檢索這門課。之後看了下書,大概知道怎麼操作了。

這裡把我的目標函式改改,舉個例子來做說明for迴圈怎麼用於目標函式的定義。

 

 

後面這項的Xavg是指x的平均值,這一項類似於一個平方差。

首先新建一個matlab指令碼,我們把優化目標寫成一個函式,第一行寫上:

function f= qiujie(x) //我的指令碼名稱就是qiujie,這個可以自己修改

分析一下這個目標項,後面那個有點複雜,需要求平均,因為for迴圈是從x1一個一個加到x50的,所以一開始沒有這個資訊,因此我們可以用兩個迴圈來做,第一個迴圈就是優化目標的第一項,同時記錄x1...x50,根據記錄的x1...x50,第二個迴圈就可以加上第二項了。

這裡的ck,tk都是常數項,所以我們提前設定好,比如

  ck = [1,2,3,...,50]

  tk = [1,2,3...50]

先定義一個f,再定義一個t用於儲存x1...x50的資訊

  f = 0;

  t = 0;//t用來記錄

接下來就可以用for迴圈來寫了,

  for k= 1:50

         f = f+(x(k)-c(k))*x(k)^t(k);//第一項

         t = t+x(k);

  end

現在求一下平均值,並加上後面那項

  t = t/50

  for k = 1:50

         f = f -(x(k)-t)^2;//第二項

  end

這樣我們的優化目標項就定義好了,之後我們把約束項定義好,就可以進行求解了,形式為:

  [x,fval]=fmincon(@qiujie,x0,A,b);

上面就是整個求解過程的思路,具體情況需要根據自己的需求來寫。

不過這樣看其實也還好,但很多時候約束項才是讓人頭疼的,比如我們的係數矩陣A,當變數比較多時,係數矩陣會很大,如果有規律,我們可以利用for迴圈來寫,但如果係數矩陣沒有規律,通常需要我們人工輸入,目前我還不知道在matlab中怎麼能很好解決這個問題,有知道的可以v我一下。(我覺得一般應該是有規律的)

Lingo求解非線性約束優化問題:

暫時還沒學完,學完再寫。

 

相關文章