В этом случае optim
не будет работать, очевидно, потому что у вас есть ограничения на равенство. constrOptim
не будет работать по той же причине (я попытался преобразовать равенство в два неравенства, то есть больше и меньше 15, но это не с constrOptim
).
Однако есть пакет, посвященный этой проблеме, и это Rsolnp
.
Вы можете использовать его следующим образом:
#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)
Выход:
> 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
Таким образом, полученные оптимальные значения:
$pars
[1] 1.500000e+01 5.745236e-09 2.069192e-08
, что означает, что первый параметр 15 и остальные ноль и ноль. Это действительно глобальный минимум в вашей функции, поскольку x2 добавляет функцию, а 5 * x1 имеет гораздо большее (отрицательное) влияние, чем x3 на результат. Выбор 15, 0, 0 - это решение и глобальный минимум функции в соответствии с ограничениями.
Функция работала отлично!
Nice one! Когда ОП говорит: «Это упрощенный пример реальной проблемы», это заставляет меня думать, что фактическая проблема может быть нелинейной. Поэтому, чтобы быть уверенным, я предложил нелинейный метод (который работает в любом случае, даже если он медленнее). Предоставление градиента (простое для этого случая) делает его еще быстрее, если скорость является проблемой. Во всяком случае, я не имею в виду плохое, это действительно хорошо, что вы добавили этот ответ, безусловно, полезно. – LyzandeR