切割模式的算法

时间:2016-07-31 15:40:43

标签: algorithm optimization

我们说我有一个给定的长度c,我需要剪掉几段不同长度a{i},其中i是特定片段的索引。每件的长度小于或等于长度c。我需要找到所有可能的切割模式排列。

是否有人采用智能方法处理此类任务或算法来解决此问题?

该功能看起来与此类似:

Pattern[] getPatternList(double.. a, double c);

因此,输入是不同大小和总可用空间的列表。我的目标是优化/减少修剪损失。 我将使用单纯形算法,但要创建线性编程模型,我需要一种智能方法来确定所有切割模式。

2 个答案:

答案 0 :(得分:1)

  • 一般来说,有许多切割模式。所以构建它们(时间和内存)可能是不可行的
  • 如果您需要根据某个目标优化某些切割,列举所有可能的切割是一种不好的方法(如@harold提到的那样)
    • 一个不好的比喻(这里不完全适用于您的基本问题是np-hard):
    • 在多项式时间内可以解决2-SAT
    • 枚举所有2-SAT解决方案 Sharp-P-complete (一种有效的算法意味着P = NP,所以可能没有!)
  • 一种简单的方法(生成所有有效的切割模式):
    • 如果items =项目的排序(以!n为界)
    • ,则生成所有排列
    • 一个接一个地放置它们,如果超过c则停止
    • (以增量方式执行此操作是个好主意;逐个构建一个排列)
    • 假设:每个项目只能选择一次
    • 假设:在自由范围内移动/移动切割不会产生新的解决方案。它会:解决方案空间可能是一个无数无限的集合

修改

代码

这是一种使用与上述相同的假设来处理问题的更强大的方法。它使用整数编程来最小化修剪损失,使用cvxpy在python中实现(和商业解算器;可以用像cbc这样的开源求解器代替):

import numpy as np
from cvxpy import *
np.random.seed(1)

# random problem
SPACE = 25000
N_ITEMS = 10000
items = np.random.randint(0, 10, size=N_ITEMS)

def minimize_loss(items, space):
    N = items.shape[0]
    X = Bool(N)
    constraint = [sum_entries(mul_elemwise(items, X)) <= space]
    objective = Minimize(space - sum_entries(mul_elemwise(items, X)))
    problem = Problem(objective, constraint)
    problem.solve(solver=GUROBI, verbose=True)

    print('trim-loss: ', problem.value)
    print('validated trim-loss: ', space - sum(np.dot(X.value.flatten(), items)))
    print('# selected items: ', np.count_nonzero(np.round(X.value)))

print('items: ', items)
print('space: ', SPACE)
minimize_loss(items, SPACE)

输出

items:  [5 8 9 ..., 5 3 5]
space:  25000
Parameter OutputFlag unchanged
   Value: 1  Min: 0  Max: 1  Default: 1
Changed value of parameter QCPDual to 1
   Prev: 0  Min: 0  Max: 1  Default: 0
Optimize a model with 1 rows, 10000 columns and 8987 nonzeros
Coefficient statistics:
  Matrix range    [1e+00, 9e+00]
  Objective range [1e+00, 9e+00]
  Bounds range    [1e+00, 1e+00]
  RHS range       [2e+04, 2e+04]
Found heuristic solution: objective -25000
Presolve removed 1 rows and 10000 columns
Presolve time: 0.01s
Presolve: All rows and columns removed

Explored 0 nodes (0 simplex iterations) in 0.01 seconds
Thread count was 1 (of 4 available processors)

Optimal solution found (tolerance 1.00e-04)
Best objective -2.500000000000e+04, best bound -2.500000000000e+04, gap 0.0%
trim-loss:  0.0
validated trim-loss:  [[ 0.]]
# selected items:  6516

编辑v2 在阅读完您的新评论之后,很明显,您的模型描述不完整/不精确,上面没有任何内容可以解决您想要解决的问题。这有点难过。

答案 1 :(得分:0)

您需要枚举a的所有排列,然后选择长度小于或等于c的最长前缀。

这听起来像是背包问题的一个版本(https://en.wikipedia.org/wiki/Knapsack_problem),没有人知道这样做的有效方法。