简体   繁体   English

纸浆 Python - 如何线性化涉及变量的不等式

[英]PuLP Python - How to linearize an inequality involving a variable

I am working on a Copper payables problem where the objective function is to maximise the sum of copper payable over a time period, T.我正在研究应付铜问题,其中目标 function 是在一段时间内最大化应付铜的总和,T。

Is it possible to formulate a constraint that compares a variable with/between two constants, dynamically:是否可以制定一个约束来动态地比较一个变量与两个常量之间的关系:

ie IE

lower_bound, operator_1 (>, >=), variable, operator_2(<, <=) up_bound

Description of the problem问题描述

The total amount of payable tonnes ie what the customer will pay for is dependent on the copper content of the sales material.应付吨的总量,即客户将支付的金额取决于销售材料的铜含量。

  1. Each customer has a number of payable terms expressed as copper specification operable bounds, as per the below example data:根据以下示例数据,每个客户都有许多以铜规格可操作范围表示的应付条款:

Customer data客户资料

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
  1. I have a dataframe of available material, in tonnes, with specific copper content in two warehouses with two stockpiles.我有一个 dataframe 可用材料,以吨为单位,在两个有两个库存的仓库中具有特定的铜含量。 Note that the quality of this material changes over time:请注意,此材料的质量会随着时间而变化:

##Stockpile data ##库存数据

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

Question I have created a variable to represent the copper concentration for each warehouse, stockpile.问题我创建了一个变量来表示每个仓库的铜浓度,即 stockpile。 This is kept as a variable as the intention is to model inventory over time, allowing the model a choice of when to sell material in order to maximise the payables:这保留为变量,因为目的是随着时间的推移 model 库存,允许 model 选择何时出售材料以最大化应付账款:

cu_spec_of_sale_material = pulp.LpVariable.dicts(
    'Copper spec of sale material',
    ((warehouse, stockpile)
      for warehouse, stockpile in stockpile_df.index),
      cat='Continuous')

How can I create a linear constraint that returns the correct payable coefficient with respect to the copper concentration VALUE of this variable?如何创建一个线性约束,以返回关于此变量的铜浓度 VALUE 的正确应付系数?

In pseudo code terms, it evaluates something like the below:在伪代码术语中,它评估如下内容:

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

I do not use Pulp very often, so please bear with me.我不经常使用 Pulp,所以请多多包涵。

All help gratefully received, thank you.感谢所有帮助,谢谢。

I think you are looking for a linear formulation for the implication:我认为您正在寻找含义的线性公式:

a < x < b => y = 1

where a,b are constants, x is a continuous variable and y is a binary variable.其中 a,b 是常数,x 是连续变量,y 是二进制变量。

We can write this as:我们可以这样写:

 x ≤ a + M1 ⋅ δ + M1 ⋅ y
 x ≥ b - M2 ⋅ (1-δ) - M2 ⋅ y
 δ,y ∈ {0,1}
 x ∈ [L,U]
 M1 = U-a
 M2 = b-L

δ is another binary variable, L , U are lower/upper bounds on x , M1 , M2 are constants. δ是另一个二元变量, LUx的下限/上限, M1M2是常数。

Intuition: these constraints implement the implication:直觉:这些约束实现了含义:

 y = 0 =>  x ≤ a or x ≥ b

which means that if a < x < b we must have y=1 .这意味着如果a < x < b我们必须有y=1

To derive these constraints it is best to move away from your computer and use old-fashioned pen-and-paper.要得出这些限制,最好远离计算机并使用老式的笔和纸。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM