You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R语言nloptr包求解非线性优化问题结果异常求助

烘焙店生产规划优化问题修正

问题背景

店内售卖三款烘焙产品,参数如下:

  • Apple Pie(苹果派):单份利润12美元,生产需30分钟工时、3个鸡蛋
  • Croissant(可颂):单份利润8美元,生产需15分钟工时、2个鸡蛋
  • Donut(甜甜圈):单份利润5美元,生产需10分钟工时、1个鸡蛋

约束条件:

  • 总可用工时:500分钟
  • 总可用鸡蛋:60个
  • 所有产品产量≥0

核心目标:最大化总利润

原代码问题分析

运行原代码得到(0,0,0)的不合理结果,原因有两点:

  1. 目标函数方向错误:nloptr默认执行最小化目标函数,但我们需要最大化利润。原代码直接返回总利润,相当于让算法寻找利润最小的解,自然会得到全0的结果。
  2. 初始值与算法适配性问题:原代码从(0,0,0)开始迭代,加上算法特性,容易陷入局部最优解;同时该问题是标准线性规划问题,用非线性全局优化算法效率低且易出错。

修正方案

方案1:调整nloptr代码适配最大化需求

将目标函数改为返回负利润,把最大化问题转化为最小化问题;同时调整初始值、增加迭代次数,避免陷入局部最优:

library(nloptr)

# 目标函数:返回负利润,将最大化问题转为最小化问题
objective <- function(x) {
  profit <- c(12, 8, 5)  # 三款产品的单份利润
  total_profit <- sum(profit * x)
  return(-total_profit)  # 取负数,最小化负利润等价于最大化利润
}

# 约束函数:返回值需满足 ≥0,代表资源未超支
constraint <- function(x) {
  labor_mins <- c(30, 15, 10)  # 各产品工时消耗
  eggs <- c(3, 2, 1)  # 各产品鸡蛋消耗
  
  labor_constraint <- 500 - sum(labor_mins * x)  # 剩余工时≥0
  egg_constraint <- 60 - sum(eggs * x)  # 剩余鸡蛋≥0
  
  return(c(labor_constraint, egg_constraint))
}

# 优化选项:增加迭代次数,避免过早收敛
opts <- list(
  "algorithm" = "NLOPT_GN_ISRES",
  "xtol_rel" = 1e-8,
  "maxeval" = 10000
)

# 定义优化问题:设置非零初始值,避免从全0开始
res <- nloptr(
  x0 = c(5, 10, 15),
  eval_f = objective,
  lb = rep(0, 3),  # 产量非负约束
  ub = rep(Inf, 3),
  eval_g_ineq = constraint,
  opts = opts
)

# 输出结果
print(res)
cat("最优总利润:", -res$objective, "美元\n")
cat("最优产量:苹果派", round(res$solution[1]), "个,可颂", round(res$solution[2]), "个,甜甜圈", round(res$solution[3]), "个\n")

方案2:改用线性规划专用工具(更高效准确)

该问题是标准线性规划(LP)问题,使用lpSolve包可以直接处理最大化需求,还能轻松设置整数产量约束(符合实际生产场景):

library(lpSolve)

# 目标系数:各产品单份利润(目标是最大化)
obj <- c(12, 8, 5)

# 约束矩阵:每行对应一个约束,每列对应一款产品
const_mat <- matrix(
  c(30, 15, 10,  # 工时约束:总消耗≤500分钟
    3, 2, 1),     # 鸡蛋约束:总消耗≤60个
  nrow = 2, byrow = TRUE
)

# 约束方向:≤
const_dir <- c("<=", "<=")

# 约束右端值:资源总量
const_rhs <- c(500, 60)

# 求解线性规划,设置all.int=TRUE保证产量为整数
res <- lp("max", obj, const_mat, const_dir, const_rhs, all.int = TRUE)

# 输出结果
print(res)
cat("最优总利润:", res$objval, "美元\n")
cat("最优产量:苹果派", res$solution[1], "个,可颂", res$solution[2], "个,甜甜圈", res$solution[3], "个\n")

运行方案2的代码会得到合理的最优解:生产20个可颂和20个甜甜圈,总利润260美元,完全符合资源约束。

内容的提问来源于stack exchange,提问作者Yang-Chun Lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:17:15