2015-05-27 19 views
6

Ich versuche, das lokale Minimum einer Funktion zu finden, und die Parameter haben eine feste Summe. Zum BeispielR Optimierung mit Gleichheit und Ungleichheit Einschränkungen

Fx = 10 - 5x1 + 2x2 - x3

und die Bedingungen sind wie folgt,

x1 + x2 + x3 = 15

(x1, x2, x3)> = 0

Wo die Summe von x1, x2 und x3 einen bekannten Wert haben, und sie alle größer als Null sind. In R, würde es in etwa so aussehen,

Fx = function(x) {10 - (5*x[1] + 2*x[2] + x[3])} 
opt = optim(c(1,1,1), Fx, method = "L-BFGS-B", lower=c(0,0,0), upper=c(15,15,15)) 

Ich habe auch versucht mit constrOptim Ungleichheiten zu verwenden, um die Summe zu zwingen, fixiert werden. Ich denke immer noch, dass dies eine plausible Arbeit ist, aber ich konnte es nicht zum Laufen bringen. Dies ist ein vereinfachtes Beispiel für das eigentliche Problem, aber jede Hilfe wäre sehr willkommen.

Antwort

6

Bei dieser Gelegenheit optim wird nicht offensichtlich funktionieren, weil Sie Gleichheitsbedingungen haben. constrOptim funktioniert nicht aus dem gleichen Grund (ich versuchte, die Gleichheit in zwei Ungleichungen zu konvertieren, d. H. Größer und kleiner als 15, aber dies funktionierte nicht mit constrOptim).

Allerdings gibt es ein Paket für diese Art von Problem und das ist Rsolnp.

Sie verwenden es die folgende Art und Weise:

#specify your function 
opt_func <- function(x) { 
    10 - 5*x[1] + 2 * x[2] - x[3] 
} 

#specify the equality function. The number 15 (to which the function is equal) 
#is specified as an additional argument 
equal <- function(x) { 
    x[1] + x[2] + x[3] 
} 

#the optimiser - minimises by default 
solnp(c(5,5,5), #starting values (random - obviously need to be positive and sum to 15) 
     opt_func, #function to optimise 
     eqfun=equal, #equality function 
     eqB=15, #the equality constraint 
     LB=c(0,0,0), #lower bound for parameters i.e. greater than zero 
     UB=c(100,100,100)) #upper bound for parameters (I just chose 100 randomly) 

Ausgang:

> solnp(c(5,5,5), 
+  opt_func, 
+  eqfun=equal, 
+  eqB=15, 
+  LB=c(0,0,0), 
+  UB=c(100,100,100)) 

Iter: 1 fn: -65.0000  Pars: 14.99999993134 0.00000002235 0.00000004632 
Iter: 2 fn: -65.0000  Pars: 14.999999973563 0.000000005745 0.000000020692 
solnp--> Completed in 2 iterations 
$pars 
[1] 1.500000e+01 5.745236e-09 2.069192e-08 

$convergence 
[1] 0 

$values 
[1] -10 -65 -65 

$lagrange 
    [,1] 
[1,] -5 

$hessian 
      [,1]  [,2]  [,3] 
[1,] 121313076 121313076 121313076 
[2,] 121313076 121313076 121313076 
[3,] 121313076 121313076 121313076 

$ineqx0 
NULL 

$nfuneval 
[1] 126 

$outer.iter 
[1] 2 

$elapsed 
Time difference of 0.1770101 secs 

$vscale 
[1] 6.5e+01 1.0e-08 1.0e+00 1.0e+00 1.0e+00 

So die daraus resultierenden optimalen Werte sind:

$pars 
[1] 1.500000e+01 5.745236e-09 2.069192e-08 

was bedeutet, dass der erste Parameter 15 und der Rest ist Null und Null. Dies ist in der Tat das globale Minimum in Ihrer Funktion, da das x2 der Funktion hinzugefügt wird und 5 * x1 einen viel größeren (negativen) Einfluss als x3 auf das Ergebnis hat. Die Wahl von 15, 0, 0 ist die Lösung und das globale Minimum für die Funktion gemäß den Beschränkungen.

Die Funktion hat super funktioniert!

4

Dies ist eigentlich ein lineares Programmierproblem, also wäre ein natürlicher Ansatz, einen linearen Programmierlöser wie das lpSolve-Paket zu verwenden. Sie müssen eine Zielfunktion und eine Beschränkungsmatrix schaffen, und der Solver erledigt den Rest:

library(lpSolve) 
mod <- lp("min", c(-5, 2, -1), matrix(c(1, 1, 1), nrow=1), "=", 15) 

Dann können Sie die optimale Lösung zugreifen und den objektiven Wert (Hinzufügen der konstanten Größe 10, die nicht an die vorgesehen ist, Löser):

mod$solution 
# [1] 15 0 0 
mod$objval + 10 
# [1] -65 

eine lineare Programmierung Solver ein gutes Geschäft schneller als eine allgemeine nichtlineare Optimierung Löser die genaue optimale Lösung Probleme und sollte nicht (statt einem nahe gelegenen Punkt sein sollte, die Rückkehr zu Rundungsfehlern ausgesetzt sein können).

+1

Nice one! Wenn das OP sagt: "Dies ist ein vereinfachtes Beispiel für das wirkliche Problem", so denke ich, dass das tatsächliche Problem nichtlinear ist. Also, um sicher zu sein, schlug ich eine nichtlineare Methode vor (die auch dann funktioniert, wenn sie langsamer ist). Durch die Bereitstellung des Gradienten (in diesem Fall einfach) wird es sogar schneller, wenn Geschwindigkeit ein Problem darstellt. Jedenfalls meine ich nicht schlecht, es ist wirklich gut, dass du diese Antwort hinzugefügt hast, definitiv hilfreich. – LyzandeR