基于二进制变量的线性优化结果异常问询(R语言lpSolveAPI)
我来帮你拆解一下这个问题——你的模型没输出那个更优解,核心是约束条件的逻辑没写对,没有准确还原你设定的产量调整规则。咱们一步步梳理:
你研究的是一家分4个时段生产的企业,核心目标是最小化产量与平均销量S0=90的差值,初始产量固定为110,调整规则是:
- 若前一时段产量≥100,下一时段可增减10
- 若前一时段产量<100,下一时段仅可增减5
你用lpSolveAPI实现的模型得到的解是[110,100,100,90],误差为10,但理论上[110,100,90,85]的误差更小(6.25),却没被模型识别到。
你的代码里试图用二进制变量(第7-10位)标记时段产量是否≥100,但约束的写法没有正确关联「前一时段产量状态」和「当前时段调整幅度」的关系,具体问题如下:
1. 产量调整幅度的约束逻辑混乱
你写的这段调整幅度约束:
#maximum increase for (i in 1:3){ for (j in 7:10){ x[i+1]=1 x[i]=-1 x[j]=-5 add.constraint(error, x, "<=", 5) x[i]=0 x[i+1]=0 x[j]=0 } } #maximum decrease for (i in 1:3){ for (j in 7:10){ x[i]=-1 x[i+1]=1 x[j]=5 add.constraint(error, x, ">=", -5) x[i]=0 x[i+1]=0 x[j]=0 } }
这段代码没有把二进制变量和前一时段的产量状态绑定。你想表达的是「前一时段产量≥100时,当前时段可±10;否则仅可±5」,但当前约束反而给调整幅度加了错误的限制,导致模型无法生成90→85的调整(这个调整需要前一时段产量<100时允许减5,但你的约束没正确放开这个规则)。
2. 二进制变量与产量状态的约束缺失
你写了这段代码试图关联产量和二进制变量:
for (i in 1:3){ for (j in 7:10){ x[i]=1 x[j]=-100 add.constraint(error, x, ">=", 0) x[i]=0 x[j]=0 } }
这个约束的逻辑是p_i ≥ 100*b_i(如果二进制变量b_i=1,则p_i≥100),但缺少反向约束:如果p_i≥100,则对应的二进制变量b_i必须为1。没有这个反向约束,二进制变量就无法准确标记产量状态,调整幅度的约束自然无法生效。
3. 目标函数的定义可能存在歧义
你的目标函数是set.objfn(error,x),其中x=c(0,0,0,0,0,1,0,0,0,0,0),看起来是把第6个变量作为误差项,但你需要确认这个误差项是否准确代表了「产量与销量的差值」——比如是所有时段产量与S0的绝对差之和?还是平均产量与S0的差值?如果目标函数定义不对,也会导致模型找到的不是你想要的最优解。
要正确实现你的规则,需要重新梳理约束逻辑:
明确变量定义
p1,p2,p3,p4:4个时段的产量(对应代码前4个变量)b1,b2,b3,b4:二进制变量,b_i=1当且仅当p_i≥100(对应代码第7-10位变量)e:误差项,需准确代表你要最小化的目标(比如所有时段产量与S0的绝对差之和,或平均差值)
补充二进制变量与产量的双向约束
给每个时段添加双向约束,让二进制变量准确标记产量状态:M <- 200 # 足够大的常数 for (i in 1:4) { # 若b_i=1,则p_i≥100 add.constraint(error, c(rep(0,i-1),1,rep(0,4-i),0,0,rep(0,i-1),-100,rep(0,4-i)), ">=",0) # 若b_i=0,则p_i<100(线性化处理为p_i ≤99 + M*b_i) add.constraint(error, c(rep(0,i-1),1,rep(0,4-i),0,0,rep(0,i-1),M,rep(0,4-i)), "<=",99+M) }正确定义产量调整幅度的约束
关联前一时段的二进制变量和当前时段的调整幅度:for (i in 1:3) { # 调整上限:前一时段≥100时允许+10,否则允许+5 add.constraint(error, c(rep(0,i-1),-1,1,rep(0,3-i),0,0,rep(0,i-1),5,rep(0,3-i)), "<=",5) # 调整下限:前一时段≥100时允许-10,否则允许-5 add.constraint(error, c(rep(0,i-1),-1,1,rep(0,3-i),0,0,rep(0,i-1),5,rep(0,3-i)), ">=",-5) }修正目标函数
如果要最小化所有时段产量与S0的绝对差之和,需要线性化处理绝对差:# 添加4个绝对差变量e1-e4(可扩展变量数量) # 目标函数设为最小化e1+e2+e3+e4 # 给每个时段添加约束: # p_i - S0 ≤ e_i # S0 - p_i ≤ e_i # e_i ≥0
内容的提问来源于stack exchange,提问作者Jeppebirk

