Rで数理計画
(例題など、どんどん付け足してください。)
ここでは、Rの関数を利用した数理計画問題の解法を説明します。 Rでも既存の関数を利用して、制約条件付き最適化問題を解くことができます。
LP。目的関数が1次(linear)で、制約条件が1次不等式で表現される数理計画問題。
パッケージ boot の関数 simplex() を利用します。
シンプレックス法を用いてLPを解く。linprogパッケージには,MPS形式のファイルを読みこむ,readMPS関数なども含まれている。 LPの解(最適解,最大(小)値)とともに,双対変数(シャドウバリュー)や感度分析の結果を得ることもできる。 linprog(線形計画/最適化)パッケージ中のオブジェクト一覧
ソルバーとして,lp_solveを利用している。整数計画法(および0‐1整数計画問題)にも対応*1。 lpSolve パッケージには割り当て問題や輸送問題の関数もある。lpSolve(線形・整数問題解法用 Lp_solve インターフェース)パッケージ中のオブジェクト一覧
機能は上と同じ?
glpk(Gnu Linear Programming Kit)へのインターフェイスを提供。
R interface to the GNU Linear Programing Kit (GLPK version 4.25). GLPK is open source software for solving large-scale linear programming (LP), mixed integer linear programming (MILP) and other related problems. Rglpk(R/GNU 線形計画キットインターフェース)パッケージ中のオブジェクト一覧
subplex 最適化アルゴリズム
QP。目的関数が2次で制約条件が1次の不等式で表現される数理計画問題。
解法アルゴリズムには,Goldfarb-Idnani法が採用されているので狭義凸2次計画問題(いわゆる行列Qが正定値対称行列の場合)を解くために利用できます。
Weighted and lexicographical goal programming and optimization.
制約条件が線形不等式の場合には、パッケージ base の関数 constrOptim() も利用することができます(線形不等式制約付きの最適化関数 constrOptim 参照)。
orloca(オペレーションリサーチの立地分析モデルを扱う)パッケージ中のオブジェクト一覧
Optimization and Mathematical Programming
x1 + 9x2 + 3 x3
上の式の最大化
x1 + 2 x2 + 3 x3 <= 9 3 x1 + 2 x2 + 2 x3 <= 15
f.obj <- c(1, 9, 3)
f.con <- matrix (c(1, 2, 3, 3, 2, 2), nrow=2, byrow=TRUE) f.dir <- c("<=", "<=") f.rhs <- c(9, 15)
x1 + 9 x2 + 3 x3
上の式の最大化
x1 + 2 x2 + 3 x3 <= 9 3 x1 + 2 x2 + 2 x3 <= 15
lp ("max", f.obj, f.con, f.dir, f.rhs)
lp ("max", f.obj, f.con, f.dir, f.rhs)$solution
f.obj <- c(1, 9, 3)
f.con <- matrix (c(1, 2, 3, 3, 2, 2), nrow=2, byrow=TRUE) f.dir <- c("<=", "<=") f.rhs <- c(9, 15)
lp ("max", f.obj, f.con, f.dir, f.rhs, int.vec=1:3)
lp ("max", f.obj, f.con, f.dir, f.rhs)$solution
library(quadprog) #二次計画法ルーティンのロード n <- 100 #銘柄数(自由に変更してください) return <- matrix(rnorm(1000*n,0.03,0.30), ncol=n) return[,n] <- return[,n]+0.05 #共分散行列を計算するためにリターンの系列を乱数で発生させてます ################################################## # n変数の有効フロンティア(リターン条件あり/ショートなし) # min(-d^T b + 1/2 b^T D b) # with the constraints A^T b >= b_0. # リターン一定で最小のリスクを算出しています(←ちょっと説明わかりにくい) ################################################## Dmat <- cov(return) #共分散行列 dvec <- rep(0,n) #0です tmp <- matrix(0,nrow=n,ncol=n) #ショートなし制約のための行列 diag(tmp) <- 1 Amat <- cbind(rep(1,n),apply(return,2,mean),tmp) #↑制約条件行列(ウエイトの合計が1/各銘柄の期待収益率/ショートなし) bvec <- c(1.0, 0.030, rep(0,n)) #↑制約条件行列(ウエイトの合計が1/ポートフォリオの期待収益率3%/ショートなし) sol <- solve.QP(Dmat,dvec,Amat,bvec=bvec,meq=2) #二次計画法実行 sum(sol$sol) #ウエイトの合計が1になっているかどうかの確認 t(matrix(sol$sol))%*%Dmat%*%matrix(sol$sol) #リスク t(matrix(sol$sol))%*%matrix(apply(return,2,mean)) #リターン(ちゃんと3%になってます) sol <- list(sol) #上の結果をリスト型として保存 for(iret in seq(0.03,0.05,by=0.0005)){ #リターンを3%から5%までうごかす bvec[2] <- iret sol <- c(sol,list(solve.QP(Dmat,dvec,Amat,bvec=bvec,meq=2))) #計算結果を変数「sol」に保存 } RetSigma<- sapply(sol, function(x){ c( sigma=sqrt(t(matrix(x$sol))%*%Dmat%*%matrix(x$sol)), ret=t(matrix(x$sol))%*%matrix(apply(return,2,mean)) ) } ) #↑結果を元にリターンとリスクを計算 RetSigma <- t(RetSigma) plot(RetSigma) #↑表示 #system.time(apply(matrix(1:100),1,function(x){sol <- solve.QP(Dmat,dvec,Amat,bvec=bvec,meq=2)}))
実行例(発送地が8, 目的地が5の場合)
>costs <- matrix (100000, 8, 5);#最大輸送費用 10,000 >costs[4,1] <- costs[-4,5] <- 0 >costs[1,2] <- costs[2,3] <- costs[3,4] <- 7; costs[1,3] <- costs[2,4] <- 7.7 >costs[5,1] <- costs[7,3] <- 8; costs[1,4] <- 8.4; costs[6,2] <- 9 >costs[8,4] <- 10; costs[4,2:4] <- c(.7, 1.4, 2.1)
>row.signs <- rep ("<", 8) >row.rhs <- c(200, 300, 350, 200, 100, 50, 100, 150)
>col.signs <- rep (">", 5) >col.rhs <- c(250, 100, 400, 500, 200)
>lp.transport (costs, row.signs, row.rhs, col.signs, col.rhs)
>lp.transport (costs, row.signs, row.rhs, col.signs, col.rhs)$solution [,1] [,2] [,3] [,4] [,5] [1,] 0 100 0 100 0 [2,] 0 0 300 0 0 [3,] 0 0 0 350 0 [4,] 200 0 0 0 0 [5,] 50 0 0 0 50 [6,] 0 0 0 0 50 [7,] 0 0 100 0 0 [8,] 0 0 0 50 100