【问题标题】:Finding minimum value of a function wit 11,390,625 variable combinations查找具有 11,390,625 个变量组合的函数的最小值
【发布时间】:2019-03-20 02:48:11
【问题描述】:

我正在编写代码来解决管道数量的直径大小的最佳组合。目标函数是找到六个管道中压降的最小总和。

因为我有 15 种离散直径尺寸可供选择,它们是 [2,4,6,8,12,16,20,24,30,36,40,42,50,60,80] 可用于我在系统中拥有的六个管道中的任何一个,可能的解决方案列表变为 15^6,等于 11,390,625

为了解决这个问题,我使用 Pulp 包使用混合整数线性规划。我能够找到相同直径组合的解决方案(例如 [2,2,2,2,2,2] 或 [4,4,4,4,4,4]),但我需要的是去通过所有组合(例如 [2,4,2,2,4,2] 或 [4,2,4,2,4,2] 找到最小值。我试图这样做,但这个过程需要很长时间是时候遍历所有组合了。有没有更快的方法来做到这一点?

请注意,我无法计算每条管道的压降,因为直径的选择会影响系统中的总压降。因此,在任何时候,我都需要计算系统中每个组合的压降。

我还需要约束问题,使管道面积的速率/横截面> 2。

非常感谢您的帮助。

我的代码的第一次尝试如下:

from pulp import * 
import random 
import itertools
import numpy

rate = 5000
numberOfPipelines = 15 

def pressure(diameter):
    diameterList = numpy.tile(diameter,numberOfPipelines)
    pressure = 0.0
    for pipeline in range(numberOfPipelines):
        pressure +=  rate/diameterList[pipeline]
    return pressure 
diameterList = [2,4,6,8,12,16,20,24,30,36,40,42,50,60,80]

pipelineIds = range(0,numberOfPipelines)
pipelinePressures = {} 

for diameter in diameterList: 
   pressures = [] 
   for pipeline in range(numberOfPipelines): 
      pressures.append(pressure(diameter))
   pressureList = dict(zip(pipelineIds,pressures))
   pipelinePressures[diameter] = pressureList 
   print 'pipepressure', pipelinePressures 
prob = LpProblem("Warehouse Allocation",LpMinimize)

use_diameter = LpVariable.dicts("UseDiameter", diameterList, cat=LpBinary) 
use_pipeline = LpVariable.dicts("UsePipeline", [(i,j) for i in pipelineIds for j in diameterList], cat = LpBinary)

## Objective Function: 
prob += lpSum(pipelinePressures[j][i] * use_pipeline[(i,j)] for i in pipelineIds for j in diameterList)

## At least each pipeline must be connected to a diameter: 
for i in pipelineIds: 
   prob += lpSum(use_pipeline[(i,j)] for j in diameterList) ==1 

## The diameter is activiated if at least one pipelines is assigned to it: 
for j in diameterList: 
  for i in pipelineIds: 
     prob += use_diameter[j] >= lpSum(use_pipeline[(i,j)])


## run the solution

prob.solve()
print("Status:", LpStatus[prob.status])

for i in diameterList:
    if use_diameter[i].varValue> pressureTest:
        print("Diameter Size",i)

for v in prob.variables():
    print(v.name,"=",v.varValue)

这是我为组合部分所做的,花了很长时间。

xList = np.array(list(itertools.product(diameterList,repeat = numberOfPipelines)))
        print len(xList)
        for combination in xList:
            pressures = [] 
            for pipeline in range(numberOfPipelines):
               pressures.append(pressure(combination))
            pressureList = dict(zip(pipelineIds,pressures))
            pipelinePressures[combination] = pressureList
            print 'pipelinePressures',pipelinePressures

【问题讨论】:

  • 所涉及的数字通过蛮力似乎相当可行。您是否尝试过计算所有组合的目标函数,然后挑选出优化值?
  • 如果 itertools.product 很慢并且你的问题有固定数量的管道,考虑使用循环或递归来生成组合
  • 我会支持以下使用动态编程的建议。如果没有对问题的完整描述,我无法确定,但我非常有信心可以将问题分解为一系列阶段,因此可以使用动态编程有效地解决。

标签: python optimization linear-programming pulp mixed-integer-programming


【解决方案1】:

我会遍历所有组合,我认为您会遇到内存问题,否则尝试在 MIP 中对所有组合进行建模。

如果您可能使用多处理库来遍历问题以使用所有内核,则应该不会花费很长时间,只需记住仅保存有关迄今为止最佳组合的信息,而不是尝试立即生成所有组合然后评估它们。

如果问题变得更大,您应该考虑动态规划算法或使用具有列生成的纸浆。

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 2018-10-05
    • 1970-01-01
    • 2020-09-07
    • 2019-02-24
    • 1970-01-01
    • 2021-12-10
    • 2019-06-08
    • 2016-05-11
    相关资源
    最近更新 更多