使用R的lpSolve求解线性优化问题遇全零解求助
解决线性规划解全为0的问题
我来帮你排查这个问题!你的目标是最小化总水足迹,约束总用地量等于2958700,但得到全0的解显然不符合约束(总用地会是0≠2958700),这说明求解过程存在隐藏问题,我们一步步来解决:
1. 先检查求解状态
你当前的代码只提取了solution,但没有查看lp求解的状态码。状态码能直接告诉你求解器是否找到可行解、最优解,或者问题是否无解/无界。先修改代码加入状态检查:
land<-c(0.03448276,0.09090909,0.06346154,0.25099602,0.26731171) water_footprint<-c(2990.3, 5980.1, 31679.5,8802.3,16404.3) crop_name<-c("banana","guava","mango","maize","rice") crop_dataframe<-data.frame(crop_name,land,water_footprint) const.mat<-matrix(land, nrow=1) # 明确转为矩阵,避免向量维度歧义 const.dir<-c("=") const.rhs<-2958700 library(lpSolve) # 保存完整的lp结果对象,方便排查问题 lp_result <- lp(direction = "min", objective.in = water_footprint, const.mat = const.mat, const.dir = const.dir, const.rhs = const.rhs) # 检查状态码:0=找到最优解,1=问题不可行,2=目标函数无界,3=解退化,4=数值计算异常 cat("求解状态码:", lp_result$status, "\n") # 提取解并命名,方便查看 min_waterfootprint <- lp_result$solution names(min_waterfootprint) <- crop_name print(min_waterfootprint) # 验证约束是否满足 cat("总用地量验证:", sum(min_waterfootprint * land), "\n")
2. 问题根源分析
你的模型逻辑是成立的:最小化sum(water_i * x_i),约束sum(land_i * x_i) = 2958700,且x_i >= 0(lpSolve默认变量非负)。理论上最优解应该是把所有种植量集中在单位土地用水最少的作物上(也就是water_i/land_i最小的那个,这里是maize,计算得≈35069升/单位土地)。
你之前得到全0解,大概率是因为约束矩阵的维度问题:当直接传入向量land作为const.mat时,lpSolve可能误将其识别为列向量(每列对应一个约束),导致约束条件变成「每个作物的土地用量单独等于2958700」,这显然不可能满足,所以求解器返回了无效的全0解(或触发数值异常)。
3. 修正后的预期结果
当你把const.mat转为1行5列的矩阵后,求解器会正确识别约束。运行修正后的代码,你应该得到类似这样的结果:
求解状态码: 0 banana guava mango maize rice 0 0 0 11787799.7 0 总用地量验证: 2958700
总水足迹为8802.3 * 11787799.7 ≈ 1.037e11,这是满足约束的最小可能值。
额外提示
- 永远记得检查lp求解的状态码,这是排查线性规划问题的第一步
- 当约束只有一行时,显式将向量转为矩阵可以避免维度歧义
- 如果需要添加其他约束(比如作物种植量上限),只需要在
const.mat中添加新行,同时扩展const.dir和const.rhs即可
内容的提问来源于stack exchange,提问作者Zara Liew
相关产品推荐
相关产品推荐

