R语言线性规划优化结果异常:最优解全为0的原因排查
使用lpSolveAPI求解线性规划得到全0解的原因及修正方案
问题背景
在R中使用lpSolveAPI包求解作物种植利润最大化的线性规划问题时,预期最优解为作物A生产10蒲式耳、作物B生产15蒲式耳,但实际运行代码后得到的决策变量值全为0。
原代码
install.packages("stats") install.packages("RMySQL") install.packages("lpSolveAPI") library(lpSolveAPI) library(readr) library(tidyverse) library(lubridate) library(RMySQL) # Decision variables: x = number of bushels A y = number of bushels B # Constraints: x + 2*y ≤ 50 (Land) 2*x + 3*y ≤ 75 (Water) 3*x + 2*y ≤ 60 (Fertilizer) x + 2*y ≤ 40 (Labor) # Objective Function: # Maximize profits lp_crop <- make.lp(0,2) set.objfn(lp_crop, c(20, 30)) add.constraint(lp_crop, c(1, 2), "<=", 50) add.constraint(lp_crop, c(2, 3), "<=", 75) add.constraint(lp_crop, c(3, 2), "<=", 60) add.constraint(lp_crop, c(1, 2), "<=", 40) invisible(lp.control(lp_crop, sense = 'max')) print(lp_crop) solve(lp_crop) # optimal amount of bushels to produce for each crop v <- get.variables(lp_crop) paste0('# A bushels', v[1]) paste0('# B bushels', v[2])
预期结果
## [1] "# A bushels 10" ## [1] "# B bushels 15"
实际结果
paste0('# B bushels', v[2]) # [1] "# B bushels0" paste0('# A bushels', v[1]) # [1] "# A bushels0" paste0('# B bushels', v[2]) # [1] "# B bushels0"
问题原因
核心问题是未添加决策变量的非负约束。线性规划中,作物种植数量不可能为负数,但lpSolveAPI默认不会自动为决策变量设置x ≥ 0、y ≥ 0的约束条件。当缺少该约束时,求解器会考虑负数解,但由于目标是最大化利润(决策变量系数为正),负数解会导致利润降低,最终求解器只能返回0作为可行解。
另外,invisible(lp.control(lp_crop, sense = 'max'))的写法虽能设置最大化目标,但并非导致解为0的直接原因。
修正后的代码
install.packages("lpSolveAPI") library(lpSolveAPI) # 创建LP模型,指定2个决策变量 lp_crop <- make.lp(0, 2) # 设置目标为最大化 lp.control(lp_crop, sense = "max") # 设置目标函数系数(作物A利润20,作物B利润30) set.objfn(lp_crop, c(20, 30)) # 添加各项约束条件 add.constraint(lp_crop, c(1, 2), "<=", 50) # 土地约束 add.constraint(lp_crop, c(2, 3), "<=", 75) # 水约束 add.constraint(lp_crop, c(3, 2), "<=", 60) # 肥料约束 add.constraint(lp_crop, c(1, 2), "<=", 40) # 劳动力约束 # 添加非负约束(关键步骤) set.bounds(lp_crop, lower = c(0, 0), columns = c(1, 2)) # 求解模型 solve(lp_crop) # 获取并输出最优解 v <- get.variables(lp_crop) paste0("# A bushels ", v[1]) paste0("# B bushels ", v[2])
运行修正后的代码,将得到预期的最优解:
[1] "# A bushels 10" [1] "# B bushels 15"
内容的提问来源于stack exchange,提问作者Hades
相关产品推荐
相关产品推荐

