PuLP Python - 如何线性化涉及变量的不等式
PuLP Python - How to linearize an inequality involving a variable
我正在研究应付铜问题,其中 objective 函数是最大化一段时间内应付铜的总和,T。
是否可以制定一个动态比较变量 with/between 和两个常量的约束条件:
即
lower_bound, operator_1 (>, >=), variable, operator_2(<, <=) up_bound
问题描述
应付吨数总额,即客户支付的金额取决于销售的铜含量material。
- 根据以下示例数据,每个客户都有许多表示为铜规格可操作范围的应付条款:
客户数据
import io
import pandas as pd
customer_payables = """customer, tier, specvalue_1, specoperator_1, specvalue_2, \
specoperator_2, coeff
'abc', 1, 0, '>=', 20, '<=', 96.0
'abc', 2, 20, '>', 24, '<=', 96.5
'abc', 3, 24, '>', 100, '<=', 96.65
'def', 1, 0, '>=', 20, '<=', 96.0
'def', 2, 20, '>=', 22, '<=', 96.66
'def', 3, 22, '>=', 100', '<=', 97.0
"""
_cust_data = io.StringIO(customer_payables)
cust_df = pd.read_csv(_cust_data, sep=",")
cust_df = cust_df.set_index('customer')
cust_df
- 我有可用 material 的数据框,以吨为单位,具有两个仓库和两个库存的特定铜含量。请注意,此 material 的质量随时间变化:
##库存数据
stockpile_data_dict = {
'Warehouse 1':{
'Stockpile 1': {'cu': 27},
'Stockpile 2': {'cu': 18}
},
'Warehouse 2': {
'Stockpile 1':{'cu': 22},
'Stockpile 2': {'cu': 16}}}
stockpile_df = pd.concat({k: pd.DataFrame(v).T for k, v in stockpile_data_dict.items()}, axis=0)
stockpile_df
问题
我创建了一个变量来表示每个仓库、库存的铜浓度。这被保留为一个变量,因为目的是随着时间的推移对库存进行建模,允许模型选择何时出售 material 以最大化应付账款:
cu_spec_of_sale_material = pulp.LpVariable.dicts(
'Copper spec of sale material',
((warehouse, stockpile)
for warehouse, stockpile in stockpile_df.index),
cat='Continuous')
如何创建一个线性约束,returns 相对于该变量的铜浓度 VALUE 的正确应付系数?
用伪代码术语来说,它的计算结果如下:
for customer, effective_tier in effective_payable_coefficient:
if customer_lower_bound_val < cu_spec_sales_material[warehouse, stockpile] < customer_up_bound_val:
PULP += effective_payable_coefficient[customer, effective_tier] == 1
我不经常使用 Pulp,所以请多多包涵。
感谢所有帮助,谢谢。
我认为您正在寻找蕴含的线性公式:
a < x < b => y = 1
其中 a,b 是常量,x 是连续变量,y 是二进制变量。
我们可以这样写:
x ≤ a + M1 ⋅ δ + M1 ⋅ y
x ≥ b - M2 ⋅ (1-δ) - M2 ⋅ y
δ,y ∈ {0,1}
x ∈ [L,U]
M1 = U-a
M2 = b-L
δ
是另一个二进制变量,L
、U
是 lower/upper 在 x
、M1
、[=18= 上的边界] 是常量。
直觉:这些约束实现了蕴涵:
y = 0 => x ≤ a or x ≥ b
这意味着如果 a < x < b
我们必须有 y=1
.
要得出这些约束,最好离开计算机并使用老式的笔和纸。
我正在研究应付铜问题,其中 objective 函数是最大化一段时间内应付铜的总和,T。
是否可以制定一个动态比较变量 with/between 和两个常量的约束条件:
即
lower_bound, operator_1 (>, >=), variable, operator_2(<, <=) up_bound
问题描述
应付吨数总额,即客户支付的金额取决于销售的铜含量material。
- 根据以下示例数据,每个客户都有许多表示为铜规格可操作范围的应付条款:
客户数据
import io
import pandas as pd
customer_payables = """customer, tier, specvalue_1, specoperator_1, specvalue_2, \
specoperator_2, coeff
'abc', 1, 0, '>=', 20, '<=', 96.0
'abc', 2, 20, '>', 24, '<=', 96.5
'abc', 3, 24, '>', 100, '<=', 96.65
'def', 1, 0, '>=', 20, '<=', 96.0
'def', 2, 20, '>=', 22, '<=', 96.66
'def', 3, 22, '>=', 100', '<=', 97.0
"""
_cust_data = io.StringIO(customer_payables)
cust_df = pd.read_csv(_cust_data, sep=",")
cust_df = cust_df.set_index('customer')
cust_df
- 我有可用 material 的数据框,以吨为单位,具有两个仓库和两个库存的特定铜含量。请注意,此 material 的质量随时间变化:
##库存数据
stockpile_data_dict = {
'Warehouse 1':{
'Stockpile 1': {'cu': 27},
'Stockpile 2': {'cu': 18}
},
'Warehouse 2': {
'Stockpile 1':{'cu': 22},
'Stockpile 2': {'cu': 16}}}
stockpile_df = pd.concat({k: pd.DataFrame(v).T for k, v in stockpile_data_dict.items()}, axis=0)
stockpile_df
问题 我创建了一个变量来表示每个仓库、库存的铜浓度。这被保留为一个变量,因为目的是随着时间的推移对库存进行建模,允许模型选择何时出售 material 以最大化应付账款:
cu_spec_of_sale_material = pulp.LpVariable.dicts(
'Copper spec of sale material',
((warehouse, stockpile)
for warehouse, stockpile in stockpile_df.index),
cat='Continuous')
如何创建一个线性约束,returns 相对于该变量的铜浓度 VALUE 的正确应付系数?
用伪代码术语来说,它的计算结果如下:
for customer, effective_tier in effective_payable_coefficient:
if customer_lower_bound_val < cu_spec_sales_material[warehouse, stockpile] < customer_up_bound_val:
PULP += effective_payable_coefficient[customer, effective_tier] == 1
我不经常使用 Pulp,所以请多多包涵。
感谢所有帮助,谢谢。
我认为您正在寻找蕴含的线性公式:
a < x < b => y = 1
其中 a,b 是常量,x 是连续变量,y 是二进制变量。
我们可以这样写:
x ≤ a + M1 ⋅ δ + M1 ⋅ y
x ≥ b - M2 ⋅ (1-δ) - M2 ⋅ y
δ,y ∈ {0,1}
x ∈ [L,U]
M1 = U-a
M2 = b-L
δ
是另一个二进制变量,L
、U
是 lower/upper 在 x
、M1
、[=18= 上的边界] 是常量。
直觉:这些约束实现了蕴涵:
y = 0 => x ≤ a or x ≥ b
这意味着如果 a < x < b
我们必须有 y=1
.
要得出这些约束,最好离开计算机并使用老式的笔和纸。