レポート課題でなんでもいいからラグランジュ緩和法で制約付き最適化問題を解いてくるものを作ってこいといわれたので。Pythonで解いてみました。
子問題に分解できる簡単なパターンです。(制約は2つ、変数も2つ)おんなじ状況に陥った人は使てやってください。
Pythonでラグランジュ緩和法によるスケジューリング問題を解く
こちらがクラス
class Lagrangian_relaxation(): def __init__(self, a): #適当にパラメーターを初期化、aはラグランジュ乗数の更新幅 self.a = a self.x1=0 self.x2=0 self.h1=0 self.h2=0 self.f=10000000 self.df=0 self.F = 0 self.z1 = 0 self.z2 = 0 def set_func(self, funcf, funch, funcx):#与えられた条件を関数として設定 self.funcf = funcf self.funch = funch self.funcx = funcx def funcF(self):#最小化する関数の値を計算f 前回との変化量も計算df p_f = self.f self.f = self.funcf(self.x1, self.x2) self.df = self.f - p_f return self.f, self.df def update_h(self):#制約条件式H(x)>=0の値を計算 self.h1, self.h2 = self.funch(self.x1, self.x2) return self.h1, self.h2 def update_Z(self):#次に使うラグランジュ乗数を決定 self.z1 = max(self.z1 + self.a*self.h1,0) self.z2 = max(self.z2 + self.a*self.h2,0) return self.z1, self.z2 def update_x(self):#この時のx1,x2を計算 self.x1, self.x2 = self.funcx(self.z1, self.z2) return self.x1, self.x2 def running(self,t,th):#tは最大繰り返し関数、thは繰り返しを終了するdfの値 for i in range(t): X1, X2 = self.update_x() H1, H2 = self.update_h() Z1, Z2 = self.update_Z() result,df = self.funcF() if(abs(df) <= th): break print("x1:", X1, "x2:", X2,"h1:", H1, "h2:", H2, "z1:", Z1, "z2:", Z2, "F:", result, "df:", df)
で、関数はこんな感じで定義(ここは適宜問題に合わせて変えてください)
def funcf(x1, x2):#最小化したい関数 return ((x1 - 1)**2 + (x2 -1)**2 +1) def funch(x1, x2):#x1とx2の子問題 return -x1 + 0.5 * x2, x1 + x2 -1 def funcx(z1, z2):#与えられた制約を表す関数(H(x)>=0) return 0.5 * (z1 - z2) + 1, -0.5 * (0.5*z1 + z2) + 1
で、ラグランジェ乗数の更新幅と関数を与えてrunしてください。
lrm = Lagrangian_relaxation(0.5)#更新幅設定 lrm.set_func(funcf, funch, funcx)#関数は設定 lrm.running(20, 0.01)#ラン! (最大繰り返し回数、繰り返しをやめるdfの値)
こんな感じでございます。素直にやってるので効率とか考えてないです。変数の数などが違う人は多少改修して使ってください。
結果はこちら。
x1: 1.0 x2: 1.0 h1: -0.5 h2: 1.0 z1: 0 z2: 0.5 F: 1.0 df: -9999999.0 x1: 0.75 x2: 0.75 h1: -0.375 h2: 0.5 z1: 0 z2: 0.75 F: 1.125 df: 0.125 x1: 0.625 x2: 0.625 h1: -0.3125 h2: 0.25 z1: 0 z2: 0.875 F: 1.28125 df: 0.15625 x1: 0.5625 x2: 0.5625 h1: -0.28125 h2: 0.125 z1: 0 z2: 0.9375 F: 1.3828125 df: 0.1015625 x1: 0.53125 x2: 0.53125 h1: -0.265625 h2: 0.0625 z1: 0 z2: 0.96875 F: 1.439453125 df: 0.056640625 x1: 0.515625 x2: 0.515625 h1: -0.2578125 h2: 0.03125 z1: 0 z2: 0.984375 F: 1.46923828125 df: 0.02978515625 x1: 0.5078125 x2: 0.5078125 h1: -0.25390625 h2: 0.015625 z1: 0 z2: 0.9921875 F: 1.4844970703125 df: 0.0152587890625
こんな感じ出てきます。
レポート課題の助けになれば何よりです。
もし、pythonの実行環境がなくて、このページで結果をだせるようにしてほしいという人はコメントに書いてください。
それでは。