線形不等式制約付きの最適化関数 constrOptim()
constrOptim 関数は adaptive barrier アルゴリズム(制約領域の境界に近付くと目的関数値が増加するような付加項を適宜付け加える?)を用い、線形不等式制約(つまり無限もしくは有界な多角形内での最小値求める)下で関数を最小化する。内部的に optim() 関数を使う。矩形制約付きの最適化は otpim の method="L-BFGS-B" が使える。
constrOptim(theta, f, grad, ui, ci, mu = 1e-04, control = list(), method = if(is.null(grad)) "Nelder-Mead" else "BFGS", outer.iterations = 100, outer.eps = 1e-05, ...)
> fr <- function(x) { ## Rosenbrock Banana function x1 <- x[1] x2 <- x[2] 100 * (x2 - x1 * x1)^2 + (1 - x1)^2 } > grr <- function(x) { ## fr のグラディェント関数 x1 <- x[1] x2 <- x[2] c(-400 * x1 * (x2 - x1 * x1) - 2 * (1 - x1), 200 * (x2 - x1 * x1)) } > optim(c(-1.2,1), fr, grr) # 制約無しの最小化 $par # 真の解は 1,1 [1] 1.000260 1.000506 $value # 真の最小値は 0 [1] 8.825241e-08 $counts function gradient 195 NA $convergence [1] 0 $message NULL
> constrOptim(c(-1.2,0.9), fr, grr, ui=rbind(c(-1,0),c(0,-1)), ci=c(-1,-1)) $par # 最小値を与えるパラメータ値(矩形境界線上) [1] 0.9999761 0.9999522 # ほぼ境界線上 $value # 最小値 [1] 5.708627e-10 # 不思議なことに制約無しの場合よりも零に近い! $counts # 関数評価回数 function gradient 6 1 $convergence # 完全な収束 [1] 0 $message NULL $outer.iterations # 内部での optim 関数の呼出し回数 [1] 14 $barrier.value # 収束点でのバリヤ関数の値(零に近い方が良い?) [1] -0.0001999198
> constrOptim(c(.5,0), fr, grr, ui=rbind(c(-1,0),c(1,-1)), ci=c(-0.9,0.1)) $par [1] 0.8891335 0.7891335 # ほぼ境界上? $value [1] 0.01249441 $counts function gradient 18 1 $convergence [1] 0 $message NULL $outer.iterations [1] 5 $barrier.value [1] -7.399944e-05
> fQP <- function(b) {-sum(c(0,5,0)*b)+0.5*sum(b*b)} > Amat <- matrix(c(-4,-3,0,2,1,0,0,-2,1),3,3) > bvec <- c(-8,2,0) > constrOptim(c(2,-1,-1), fQP, NULL, ui=t(Amat),ci=bvec) $par [1] 0.4761374 1.0477253 2.0954507 $value [1] -2.380952 $counts function gradient 252 NA $convergence [1] 0 $message NULL $outer.iterations [1] 5 $barrier.value [1] -0.0006243786
> gQP <- function(b) {-c(0,5,0)+b} > constrOptim(c(2,-1,-1), fQP, gQP, ui=t(Amat), ci=bvec) $par [1] 0.4761908 1.0476188 2.0952376 $value [1] -2.380952 $counts function gradient # グラディエントを与えた分、呼出し回数が劇的に減少している 21 1 $convergence [1] 0 $message NULL $outer.iterations [1] 5 $barrier.value [1] -0.0006243894
> hQP <- function(b) {sum(c(0,5,0)*b)-0.5*sum(b*b)} > constrOptim(c(2,-1,-1), hQP, NULL, ui=t(Amat), ci=bvec, control=list(fnscale=-1)) $par [1] 0.4763538 1.0477181 2.0954838 $value [1] 2.380751 $counts function gradient 300 NA $convergence [1] 0 $message NULL $outer.iterations [1] 1 $barrier.value [1] -0.001142111