web-dev-qa-db-ja.com

Rの整数変数を使用した非線形最適化/プログラミング

誰かが最適なソリューションのために整数変数を提供できる非線形最適化問題を解決するためにいくつかのパッケージを提案できるかどうか疑問に思いますか?問題は、いくつかの下限と上限の制約を受ける等式制約を使用して関数を最小化することです。

Rの 'nloptr'パッケージを非線形最適化問題に使用しましたが、うまく機能しましたが、一部の変数を整数として持つようにメソッドを拡張したいと思います。これまでのnloptrの使用と理解から、最適なソリューションでは整数変数ではなく連続変数のみを返すことができます。

この種の問題は、混合整数の非線形プログラミングを使用して解決する必要があると思います。

Nloptrの形式での問題の一例:

min f(x) (x-y)^2/y + (p-q)^2/q
so that (x-y)^2/y + (p-q)^2/q = 10.2

where 
x and p are positive integers not equal to 0 
and 
y and q may or may not be positive integers not equal to 0

Rでのnloptrコードは次のようになります

library('nloptr')

x1 <- c(50,25,20,15)

fn <- function(x) {
  (((x[1] - x[2])^2)/x[2]) + (((x[3] - x[4])^2)/x[4])
  }

heq <- function(x) {
  fn(x)-10.2
}

lower_limit <- c(0,0,0,0)
upper_limit <- c(67.314, 78, 76.11, 86)


slsqp(x1, fn, lower = lower_limit, upper = upper_limit,  hin = NULL, heq = heq, control = list(xtol_rel = 1e-8, check_derivatives = FALSE))

これは以下を出力します:

$par
[1] 46.74823 29.72770 18.93794 16.22137

$value
[1] 10.2

$iter
[1] 6

$convergence
[1] 4

$message
[1] "NLOPT_XTOL_REACHED: Optimization stopped because xtol_rel or xtol_abs (above) was reached."

これは私が探している結果の一種ですが、前述のとおり、整数としてxとpが必要です。

私は https://cran.r-project.org/web/views/Optimization.html を見てきましたが、これには混合整数の非線形プログラミング用のパッケージの本当に良いリストがありますが、誰かがそれらのいずれかで経験をしているのか、そして上で述べたように問題を解決するのに最も適切であると彼らが考えていることを疑問に思いました。

7年ほど前に投稿されたこの記事について同様の質問がありましたが、クランページへのリンクが表示されたため、もう一度質問する価値があると考えました。

ご協力ありがとうございます。

乾杯、

アンドリュー

5
andrew_overflow

[〜#〜] roi [〜#〜] はMINLP問題のオプションです。適切なソルバーにアクセスできると思います。これは、neosへのアクセスを許可します(質問への別の回答で説明されています)。

ROI最適化がどのように見えるかに興味がある場合は、LP(線形計画法の例:

#ROI example https://epub.wu.ac.at/5858/1/ROI_StatReport.pdf
#install.packages("ROI")
library(ROI)
ROI_available_solvers()

ROI_registered_solvers() #has one solver loaded by default

## Get and load "lpsolve" solver
#install.packages("ROI.plugin.lpsolve", repos=c("https://r-forge.r-project.org/src/contrib",
#                                   "http://cran.at.r-project.org"),dependencies=TRUE)
library(ROI.plugin.lpsolve)
ROI_registered_solvers() #Now it is available to use

## Describe model
A <- rbind(c(5, 7, 2), c(3, 2, -9), c(1, 3, 1))
dir <- c("<=", "<=", "<=")
rhs <- c(61, 35, 31)
lp <- OP(objective = L_objective(c(3, 7, -12)),
         constraints = L_constraint(A, dir = dir, rhs = rhs),
         bounds = V_bound(li = 3, ui = 3, lb = -10, ub = 10, nobj = 3),
         maximum = TRUE)

## When you have a model, you can find out which solvers can solve it
ROI_available_solvers(lp)[, c("Package", "Repository")]

## Solve model
lp_sol <- ROI_solve(lp, solver = "lpsolve")
2
Mark Neal

この問題は解決が難しいタイプであるため、一般的なアルゴリズムがこの正確な問題に適しているとは限りません(無料のランチ定理を参照)。実際、多くのアルゴリズムは、困難な問題の全体的な最適値に収束することすらありません。興味深いことに、問題の空間のランダム検索は、少なくとも空間全体を検索するため、少なくとも最終的には収束します。

tl/dr問題のあるスペースの列挙を試みます。たとえば、4つの変数が0〜80の整数の場合、ループできるのは〜80 ^ 4 =〜40millionの組み合わせのみです。中間オプションは(2つの変数のみが整数の場合)、2つの整数の値が与えられた残りの2つの変数の最適化メソッドによって問題を解決し(おそらく凸問題になっている可能性がありますか?)、整数値をループします。

2
Mark Neal

私はあなたの例を使用して次のコードを試し、元の質問のnloptrの例を再現しました:

#base example from https://cvxr.rbind.io/cvxr_examples/cvxr_gentle-intro/
#install.packages("CVXR")
library(CVXR)

#modified for Stackoverflow integer MINLP (MIQP) ####
#Solves

# Variables minimized over
x <- Variable(1, integer=TRUE)
y <- Variable(1)
p <- Variable(1, integer=TRUE)
q <- Variable(1)
z <- Variable(1)

# Problem definition (terms not normalised by y and q respectively)
objective <- Minimize((x - y)^2 + (p - q)^2 -z)
constraints <- list(x <= 67.314, y <= 78, p <= 76.11, q <= 86, z == 10.2)
prob2.1 <- Problem(objective, constraints)

# Problem solution
solution2.1 <- solve(prob2.1)
solution2.1$status
solution2.1$value
solution2.1$getValue(x)
solution2.1$getValue(y)
solution2.1$getValue(p)
solution2.1$getValue(q)
solution2.1$getValue(z)

ただし、0であるはずの-10.19989の値としてこれを取得します。

> solution2.1$status
[1] "optimal"
> solution2.1$value
[1] -10.19989
> solution2.1$getValue(x)
[1] -1060371
> solution2.1$getValue(y)
[1] -1060371
> solution2.1$getValue(p)
[1] -1517
> solution2.1$getValue(q)
[1] -1517.002
> solution2.1$getValue(z)
[1] 10.2

上記をnloptrの例のように機能させるために何をする必要があるのか​​わかりませんが、xとpが整数値であることを確認してください!

乾杯、アンドリュー

2
andrew_overflow

rneos は、アクセス可能なパッケージです neos は、MINLP問題に適したもの(BONMINやCouenne、リストを参照)など、多数のアルゴリズムを備えた無料の解決サービスです ここ )。残念ながら、問題はGAMSまたはAMPLモデルとしてフォーマットする必要があります。あなたにとって、これはいくつかの基本的なGAMSを学ぶことを意味するかもしれません、そしてそのシナリオでは、おそらくあなたは単にGAMSソフトウェアを使用することができます ここを参照 ?あなたの目的には無料版で十分かもしれません。コマンドラインとして実行できるため、必要に応じてRから呼び出すことができます。

Neos最適化がどのように見えるかに興味がある場合は、LP(線形プログラミングの例:

#rneos example
#from p11 of https://www.pfaffikus.de/talks/rif/files/rif2011.pdf

#install.packages("rneos")
library(rneos)
#library(devtools)
#install_github("duncantl/XMLRPC")
library(XMLRPC)
## NEOS: ping
Nping()
## NEOS: listCategories
NlistCategories()
## NEOS: listSolversInCategory
NlistSolversInCategory(category = "lp")
## NEOS: getSolverTemplate
template <- NgetSolverTemplate(category = "lp", solvername = "MOSEK", inputMethod = "GAMS")
template
#gams file below sourced from https://github.com/cran/rneos/blob/master/inst/ExGAMS/TwoStageStochastic.gms
modc <- paste(paste(readLines("TwoStageStochastic.gms"), collapse = "\n"), "\n")
cat(modc)
argslist <- list(model = modc, options = "", wantlog = "", comments = "")
xmls <- CreateXmlString(neosxml = template, cdatalist = argslist)
## NEOS: printQueue
NprintQueue()
## NEOS: submitJob
(test <- NsubmitJob(xmlstring = xmls, user = "rneos", interface = "", id = 0))
## NEOS: getJobStatus
NgetJobStatus(obj = test)
## NEOS: getFinalResults
NgetFinalResults(obj = test)
0
Mark Neal