【问题标题】:Unable to Optimize with range value for sum of parameters constraint in r无法使用 r 中参数总和约束的范围值进行优化
【发布时间】:2022-10-08 11:02:52
【问题描述】:

我是新手优化技术,并试图找出价值3个参数

New_budget_fb,

New_budget_tv,

New_budget_radio

最小化CPO 的值。

但我不确定如何添加以下约束,即参数之和:

New_budget_fb + New_budget_tv + New_budget_radio <= 550 &

New_budget_fb + New_budget_tv + New_budget_radio >= 350

下面是我尝试过但给我一个错误的代码。已经添加了多个print() 来弄清楚。

library(tidyverse)

fn_budget_optim_test <- function(params){
  
  
  # Unknown params used in below equations
  New_budget_fb = params[1]
  New_budget_tv = params[2]
  New_budget_radio = params[3]
  
  print(paste("Parameters 1,2,3:",New_budget_fb,New_budget_tv,New_budget_radio))
  
  contribution_fb = ((70.6 * 1.0 + New_budget_fb)^0.3596438) * 2.015733
  contribution_tv = ((16 * 0.001 + New_budget_tv)^0.8996762) * 1.073207
  contribution_radio = (40.8 * 0.001 + New_budget_radio)^0.001 * -6086.523408
  contribution_intercept = 6081.045489
  
  sales_prediction = sum(contribution_fb,contribution_tv,contribution_radio,contribution_intercept)
  
  print(paste("sales prediction:", sales_prediction))
  
  CPO = (New_budget_fb + New_budget_tv + New_budget_radio) / sales_prediction
  
  print(paste("CPO:",CPO))
  
  
  ## Adding constraint
  if(
    (New_budget_fb + New_budget_tv + New_budget_radio) <= 550 & 
    (New_budget_fb + New_budget_tv + New_budget_radio) >= 350
  ) return(CPO)
  
  else return(NA)
}

optim(par = c(150,150,50),
      fn = fn_budget_optim_test, 
      # lower = c(350,350,350),
      # upper = c(550,550,550),
      method = "L-BFGS-B")

输出和错误:

[1] "Parameters 1,2,3: 150 150 50"
[1] "sales prediction: 82.0849314406196"
[1] "CPO: 4.26387637605802"
[1] "Parameters 1,2,3: 150.001 150 50"
[1] "sales prediction: 82.0849543262375"
[1] "CPO: 4.26388736977254"
[1] "Parameters 1,2,3: 149.999 150 50"
[1] "sales prediction: 82.0849085549353"
[1] "CPO: 4.26386538234082"
Error in optim(par = c(150, 150, 50), fn = fn_budget_optim_test, method = "L-BFGS-B") : 
  non-finite finite-difference value [1]

我从Optim with constrains video 理解了这种编写约束的方式。

将在这里感谢任何形式的帮助。

更新:

能够尝试这个等式约束使用Rsolnp::solnp但仍然无法做到不等式因为我不清楚在这个函数中使用不等式。

下面的代码尝试适用于相等,即参数总和 = 350

opt_func <- function(params){
  
  # Unknown params used in below equations
  New_budget_fb = params[1]
  New_budget_tv = params[2]
  New_budget_radio = params[3]
  
  print(paste("Parameters 1,2,3:",New_budget_fb,New_budget_tv,New_budget_radio))
  
  contribution_fb = ((70.6 * 1.0 + New_budget_fb)^0.3596438) * 2.015733
  contribution_tv = ((16 * 0.001 + New_budget_tv)^0.8996762) * 1.073207
  contribution_radio = (40.8 * 0.001 + New_budget_radio)^0.001 * -6086.523408
  contribution_intercept = 6081.045489
  
  sales_prediction = sum(contribution_fb,contribution_tv,contribution_radio,contribution_intercept)
  
  print(paste("sales prediction:", sales_prediction))
  
  CPO = (New_budget_fb + New_budget_tv + New_budget_radio) / sales_prediction
  
  print(paste("CPO:",CPO))
  return(CPO)  
}

  ## Adding constraint
equality_func <- function(params){
  New_budget_fb = params[1]
  New_budget_tv = params[2]
  New_budget_radio = params[3]
  
  New_budget_fb + New_budget_tv + New_budget_radio
}

Rsolnp::solnp(c(5,5,5),
      opt_func, #function to optimise
      eqfun=equality_func, #equality constrain function 
      eqB=350,   #the equality constraint value
      LB=c(0,0,0) #lower bound for parameters i.e. greater than zero      
)

【问题讨论】:

  • 看来您可以使sale_prediction 变得非常小和负数。例如params = c(254.67552, 29.38246, 228.07362)。因为sale_prediction 是分母,所以您的最小值是极负数。
  • 是的,这是我想添加另一个约束的地方:CPO &gt;=0,我也不知道如何添加这个约束。

标签: r optimization constraints


【解决方案1】:

我已经能够在目标函数中添加不同的约束并进行最小化:

library(DEoptim)

fn_budget_optim_test <- function(params)
{
  New_budget_fb <- params[1]
  New_budget_tv <- params[2]
  New_budget_radio <- params[3]

  contribution_fb <- ((70.6 * 1.0 + New_budget_fb) ^ 0.3596438) * 2.015733
  contribution_tv <- ((16 * 0.001 + New_budget_tv) ^ 0.8996762) * 1.073207
  contribution_radio <- (40.8 * 0.001 + New_budget_radio) ^ 0.001 * -6086.523408
  contribution_intercept <- 6081.045489
  
  sales_prediction <- sum(contribution_fb, contribution_tv, contribution_radio, contribution_intercept)
  CPO <- (New_budget_fb + New_budget_tv + New_budget_radio) / sales_prediction
  
  if(is.nan(CPO))
  {
    return(10 ^ 30)
    
  }else
  {
    if((New_budget_fb + New_budget_tv + New_budget_radio) <= 550 & 
       (New_budget_fb + New_budget_tv + New_budget_radio) >= 350 &
       (CPO >= 0))
    {
      return(CPO)
      
    }else
    {
      return(10 ^ 30)
    } 
  }
}

obj_DEoptim <- DEoptim(fn = fn_budget_optim_test, lower = rep(0, 3), upper = rep(550, 3),
                       control = list(itermax = 1000))

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    相关资源
    最近更新 更多