【问题标题】:PuLP: How to structure this factory coverage problem纸浆:如何构建这个工厂覆盖率问题
【发布时间】:2021-01-12 13:07:08
【问题描述】:

努力在 PuLP 中为以下 MIP 场景制定目标函数。

每个城市都有 N 人居住。
各厂址 可以方便一组城市。
尽量减少工厂数量 打开,这样促成的人数>= 4000

我的主要问题是不同的工厂可以为同一个城市提供服务。因此,将每个工厂的可服务人口总数相加并单独考虑是不公平的。

cities = ['London', 'Paris', 'Berlin', 'Amsterdam', 'Vienna', 'Prague']
factories = ['A', 'B', 'C', 'D']

city_populations = {'London': 898, 'Paris': 222, 'Berlin': 767, 'Amsterdam': 111, 'Vienna': 854, 'Prague': 908}

factories_service = {'A': ['London', 'Prague'], 'B': ['London', 'Paris', 'Vienna'], 'C': ['Amsterdam', 'Vienna', 'Prague'], 'D': ['London', 'Vienna', 'Prague']}

这是我目前所拥有的,但它不正确,因为它只选择最大的城市,而不考虑人口重叠。

prob = pl.LpProblem("Factory Coverage",pl.LpMinimize)
​
decision_vars = pl.LpVariable.dicts("Factories", factories, cat='Binary')
​
prob += pl.lpSum(decision_vars)
prob += pl.lpSum([sum([city_populations[x] for x in factories_service[i]])*decision_vars[i] for i in factories]) >= 4000
​
​
prob.solve()

输出:
工厂_A, 0.0
工厂_B, 1.0
工厂_C, 0.0
工厂_D,1.0

【问题讨论】:

    标签: python python-3.x mathematical-optimization pulp mixed-integer-programming


    【解决方案1】:

    主要问题是您重复计算了人口。如果两个工厂服务于同一个城市,并且都建成了,那么该城市的人口应该只计算一次服务。

    您可以通过为城市创建另一组二进制变量来完成此操作,指示该城市是否得到服务。然后添加逻辑,确定只有在有工厂为城市提供服务的情况下才能为城市提供服务。

    您遇到的另一个小问题是,自 sum(city_populations.values()) == 3760 以来,您的整个模型中没有 4000 个公民

    这是一个如何解决此问题的示例,尽管它不是最有效的实现:

    prob = pl.LpProblem("Factory Coverage",pl.LpMinimize)
    
    factories_vars = pl.LpVariable.dicts("Factories", factories, cat='Binary')
    cities_vars = pl.LpVariable.dicts("Cities", cities, cat='Binary')
    
    # Objective function
    prob += pl.lpSum(factories_vars)
    # Population served is greater than 4000
    prob += pl.lpSum([city_populations[c]*cities_vars[c] for c in cities]) >= 2000
    # City is served only if there is a factory that serves it
    bigM = len(factories)
    for c in cities:
        prob +=  bigM * cities_vars[c] >= pl.lpSum([factories_vars[f] for f in factories_vars if c in factories_service[f]])
        prob +=  cities_vars[c] <= pl.lpSum([factories_vars[f] for f in factories_vars if c in factories_service[f]])
    
    prob.solve()
    

    结果:

    for f in factories_vars:
        print(f, factories_vars[f].value())
    for c in cities_vars:
        print(c, cities_vars[c].value())
    
    A 0.0
    B 0.0
    C 0.0
    D 1.0
    London 1.0
    Paris 0.0
    Berlin 0.0
    Amsterdam 0.0
    Vienna 1.0
    Prague 1.0
    

    【讨论】:

    • 谢谢 - 效果很好。只是好奇 bigM 乘数的意义。
    • Big-M 是分离约束的最简单的重新表述,就像这里需要的那样。此链接有更多信息:optimization.mccormick.northwestern.edu/index.php/…。在这种情况下,bigM 因素是确保一个城市可以由多个工厂提供服务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 2022-07-26
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多