根据采购量最小化成本 Pyomo [英] Minimize cost based on purchased volume Pyomo

查看:70
本文介绍了根据采购量最小化成本 Pyomo的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到从供应商处购买商品的最佳解决方案,其中运输成本取决于从给定供应商处购买的商品成本.我正在使用 Pyomo.到目前为止,我的代码是:

I'd like to find the optimal solution for buying goods from suppliers where the shipping cost is dependent on the cost of goods bought from given supplier. I'm using Pyomo. My code so far is:

model = ConcreteModel(name="(MN_2)")

# products
N = ['prod1', 'prod2', 'prod3']

# suppliers
M = ['A', 'B']

# price
p = {('prod1', 'A'): 10,
     ('prod2', 'A'): 9,
     ('prod3', 'A'): 50,
     ('prod1', 'B'): 16,
     ('prod2', 'B'): 20,
     ('prod3', 'B'): 35}

# user quantity contraint
q_u = {('prod1', 'A'): 2,
     ('prod2', 'A'): 1,
     ('prod3', 'A'): 1,
     ('prod1', 'B'): 1,
     ('prod2', 'B'): 1,
     ('prod3', 'B'): 1}

# seller quantity contraint
q_s = {('prod1', 'A'): 20,
     ('prod2', 'A'): 10,
     ('prod3', 'A'): 10,
     ('prod1', 'B'): 10,
     ('prod2', 'B'): 10,
     ('prod3', 'B'): 10}


# quantity of product n bough in shop m
model.x = Var(N, M, bounds=(0,10))

def obj_rule(model):
    return sum(p[n,m]*model.x[n,m] for n in N for m in M)
model.obj = Objective(rule=obj_rule)

def user_quantity(model, n, m):
    return model.x[n,m] >= q_u[n,m]
model.user_quantity = Constraint(N, M, rule=user_quantity)

def seller_quantity(model, n, m):
    return model.x[n,m] <= q_s[n,m]
model.seller_quantity = Constraint(N, M, rule=seller_quantity)

solver = SolverFactory('glpk')
solver.solve(model)
model.x.pprint()

我正在努力解决的问题是如何包括取决于从给定供应商处购买的商品成本的运输成本.例如:

What I'm struggling with is how to include the shipping cost that is dependent on the cost of goods bought from given supplier. For example:

对于供应商 A:运费是 =

For supplier A: shipping cost is =

  • 10 如果从他们那里购买的产品的总成本 <= 100,
  • 0 如果从他们那里购买的产品的成本总和 >100

对于供应商 B:运费是 =

For supplier B: shipping cost is =

  • 8 如果从他们那里购买的产品的总成本 <= 150,
  • 0 如果从他们那里购买的产品的总成本大于等于 0150

推荐答案

您描述的约束是 if-then 条件的实现,描述为 此处.奇怪的是,如果您的采购成本小于或等于某个阈值而不是严格小于阈值,则您的条件要求二元变量为 1.我们可以在不影响遵守条件的阈值上添加一个非常小的数字 (0.0001),并允许我们在严格小于不等式中使用新值.

The constraints you're describing are an implementation of if-then condition which is described here. The quirk is that your conditions require the binary variable to be 1 if your procurement costs are less than or equal to some threshold rather than strictly less than the threshold. We can add a very small number (0.0001) to the threshold that doesn't affect adherence to the condition and allow us to use the new value in a strictly less than inequality.

在您的初始模型中,您可以为每个卖家添加一个新的二元变量 (model.shipping_bin),并为每个二元变量添加一个约束,如果成本小于阈值,否则为 0.然后我们可以用这些变量乘以目标函数中的运费.

To your initial model, you can add one new binary variable per seller (model.shipping_bin) and one constraint per binary variable that forces the binary variable to be 1 if the cost is less than the threshold and 0 otherwise. We can then multiply by the shipping cost in the objective function by these variables.

# add new binary variables to track costs per supplier
model.shipping_bin = Var(M,within = Binary)
shipping_costs = {'A':10,'B':8}
shipping_thresholds = {'A':100,'B':150} # threshold to meet to not incur shipping

# We need big M values to multiply the binaries to enforce the constraint without constraining the procurement cost incurred.
# We can set to the maximum amount we expect to procure from the seller
# The largest cost you could incur from each seller is
# the price times the max quantity
shipping_big_m = {seller: sum([p[(prod,seller)] * q_s[(prod,seller)] for prod in N])
                  for seller in M}


# add constraints
def shipping_bin_rule(model,seller):
    # Sets shipping binary var to 1 if threshold not met
    # Allows it to be 0 otherwise
    # 790 * (model.shipping_bin['A']) >= 100.0001 + cost of products from seller 'A'
        # if cost of products from 'A' < 100.0001 then binary variable = 1
    # 710 * (model.shipping_bin['B']) >= 150.0001 + cost of products from seller 'B'
        # if cost of products from 'B' < 150.0001 then binary variable = 1
    epsilon = .0001 # to make sure case where cost == threshold is still accounted for
    return(shipping_big_m[seller] * model.shipping_bin[seller] >= shipping_thresholds[seller] + epsilon - sum([p[(product,seller)] * model.x[product,seller]
                                                                             for product in N]))

model.shipping_bin_con = Constraint(M,rule = shipping_bin_rule)

# new objective function adding the shipping cost
def obj_with_shipping_rule(model):
    orig_cost = obj_rule(model) # call the original function, but can combine into one function if desired
    # apply the shipping cost if cost of products is less than threshold (binary is 0)
    shipping_cost = sum([shipping_costs[seller] * model.shipping_bin[seller]
                         for seller in M])
    return(orig_cost + shipping_cost)

# deactivate the original objective to apply the new one
model.obj.deactivate()
model.obj_with_shipping = Objective(rule = obj_with_shipping_rule)


# solve the model with new obj
solver.solve(model)
model.x.pprint() # x values remain unchanged
# x : Size=6, Index=x_index
#     Key            : Lower : Value : Upper : Fixed : Stale : Domain
#     ('prod1', 'A') :     0 :   2.0 :    10 : False : False :  Reals
#     ('prod1', 'B') :     0 :   1.0 :    10 : False : False :  Reals
#     ('prod2', 'A') :     0 :   1.0 :    10 : False : False :  Reals
#     ('prod2', 'B') :     0 :   1.0 :    10 : False : False :  Reals
#     ('prod3', 'A') :     0 :   1.0 :    10 : False : False :  Reals
#     ('prod3', 'B') :     0 :   1.0 :    10 : False : False :  Reals

# cost from A = 2 * 10 + 1 * 9 + 1 * 50 = 79 < 100 so model.shipping_bin['A'] = 1
# cost from B = 1 * 16 + 1 * 20 + 1 * 35 = 71 < 150 so model.shipping_bin['B'] = 1
model.shipping_bin.pprint()
# shipping_bin : Size=2, Index=shipping_bin_index
#     Key : Lower : Value : Upper : Fixed : Stale : Domain
#       A :     0 :   1.0 :     1 : False : False : Binary
#       B :     0 :   1.0 :     1 : False : False : Binary
value(model.obj_with_shipping) # 168 (18 units larger than original because of shipping)

这篇关于根据采购量最小化成本 Pyomo的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆