在带有任意分布锥体的传送带上进行最佳冰淇淋圆锥填充过程

时间:2016-10-12 16:23:56

标签: algorithm optimization dynamic-programming

我有一个由现实生产问题引起的算法问题。

设置。空的冰淇淋甜筒随机分布在移动的传送带上。配料设备有一个软管,可以在一定范围内在带上方移动(远小于带的长度)。为了填充空锥体,将软管放置在锥体的正上方并锁定在其上一段时间直到填充过程结束。因此,这意味着在填充过程中,锥体必须保留在软管管道到达区域中。完成后,软管可以移动到另一个锥体上。显然,如果速度不够大并且填充过程需要一些时间,如果锥体足够多且不方便放置,则系统将错过一些锥体。所以问题是通过预先安排填充顺序来填充尽可能多的锥体。

ice cream cone filling process

正式我们有输入:

  • U - 皮带速度

  • V - 软管的速度

  • W - 腰带的宽度

  • L - 腰带的长度

  • P - 软管到达区域的长度

  • T - 填充过程的时间

  • cones - 腰带上锥体的坐标数组

理想情况下,输出是连续填充的锥体列表,可确保填充锥体的最大数量。或者至少估计可能填充的最大锥体数量。

非常感谢任何有关如何解决这个问题的建议!

1 个答案:

答案 0 :(得分:2)

使用仅向前分配器进行最佳锥形填充

假设传送带从右向左移动。下面我将描述一种方法,以填充最大可能数量的锥体的方式来制定和解决问题,假设分配器从不向左移动比传送带更快确实。对于n个锥体,基本算法具有非常宽松(见后面)O(n ^ 3)时间和O(n ^ 2)空间的上限 - 这对于多达1000个锥体左右应该是可行的。如果你有比这更多的锥体,你可以将它们分成最多这个大小的块,然后简单地一个接一个地处理每个块。还有一种方法可以在某种程度上放松永不左移的快速限制,从而可能填充更多的锥体,而不会使整个问题成为指数时间 - 我将在稍后对此进行描述。

假设所有锥体都有正x坐标,并且软管到达区域(最初从x = 0向左延伸到x = -P)向右移动到锥体上,锥体本身保持静止。所以在时间t,软管到达区域将从x = U * t向左延伸到x = U * t-P。当描述分配器的位置时,我总是使用相同的(即绝对的)坐标系;通过确保在任何时间t,其x位置在U * t-P和U * t之间,我们确保它保持在有效位置(在软管到达区域内)。请注意,(时间,锥形ID)对足以完全确定软管到达区域和分配器的位置,如果我们将其解释为意味着分配器在给定时间直接在给定锥体上方。 (稍后这将有助于简化对系统状态的描述。)最后,我将调用分配器的任何动作,该动作不会降低其绝对x度(这包括相对于其外壳的任何向后运动,它的速度比U低,而且根本没有运动)a"前进"动作,以及任何后退"运动。

动态编程公式

通过增加x位置对锥体进行排序,任意打破关系。设(x_i,y_i)是此排序顺序中第i个圆锥的位置。

让e(i)成为我们可以将分配器放在锥体上的最早时间,如果它是我们唯一关心的锥体,并且分配器已经等待了#34;在软管管道到达区域最右端的正确垂直位置(即y_i):这只是x_i / U.

设m(i,j)是将分配器从锥形i移动到锥形j所需的时间,假设它可以这样做,而不必等待任何一个到#39;滚动到视图":这可以很容易地从它们的坐标和速度V和U计算任何一对(i,j)(即使分配器可以同时以x和x中的任意速度V_x和V_y移动,这仍然是正确的y指示)。

现在我们来看看有效解决这个问题的关键功能:

设f(i,j)是我们可以完成填充锥i的最早时间,这样我们到目前为止已经准确地填充了j个锥体(包括这个,所以1< = j< = i如果不可行,则为无穷大。设g(i,j)是一个以相同方式定义的辅助函数,除了我们允许最后一个锥形填充步骤将分配器推到太远离开(你会在一分钟内看到原因)。我们可以如下计算g(i,j),更重要的是,f(i,j):

g(i, j) = max(e(i), minimum of f(k, j-1) + m(k, i) over all k s.t. j <= k < i) + T
f(i, j) = IF U * g(i, j) - P <= x_i THEN g(i, j) ELSE infinity
真是一团糟!让我们分一部分。

f(k, j-1) + m(k, i)项是填充j-1锥体所需的最短时间,以锥体k结束,然后将分配器移至锥体i。这周围的max(e(i), ...)确保,如果上述术语暗示的运动会导致分配器向右移动太远(即,某些x-co-ord> U * t),它会赢得&# 39;采取。相反,我们将分配器移动到(U * t,y_i) - 也就是说,移动到锥体i和尽可能正确的y-co-ord - 然后等待锥体i滚动(并且因此在时间e(i)处直接出现在分配器下方。无论我们采取哪种行动,都需要更多的T时间单位来填充锥体。

(从技术上讲,上述计算假定,如果可以将分配器移动到(x_i,y_i)某个给定时间t,那么它也可以将它移动到(U * t&lt; x_i,y_i)最迟在同一时间。但是由于我们的起始x位置是&lt; = U * t,这可能无法保持的唯一方法是如果函数描述需要在2之间移动所需的时间这些点违反了三角形不等式 - 当软管相对于其外壳以恒定速度V移动时,或者在恒定速度V_x和V_y下独立地在2个方向上移动时,或者确实使用任何非疯狂的驱动系统时,都不会发生这种情况。)

软管到达区域的左边缘怎么样? U * g(i, j) - P是时间g(i,j)处该区域左边缘的位置。由于那个时间是尽可能早的时间,我们可以完成填充j锥体的任务,最后一个是锥体i,该表达式给出了软管管道左边缘可能达到的最左边位置区域可以在任务完成时进入。因此,如果该位置仍在x_i的左侧,则意味着我们可以在j-1之前的锥体之后切实填充锥体 - 但如果它不是,我们知道尝试这样做也将迫使分配器最左边(这可能发生在试图移动到锥形i,或填充它时 - 它并不重要)。所以在后一种情况下,我们将与任务f(i,j)相关的时间成本一直淹没到无穷大,保证它不会被用作任何更大子问题的解决方案的一部分。

时间和空间使用

计算任何特定的f(i,j)值需要O(n)时间,因此计算这些值的所有O(n ^ 2)需要O(n ^ 3)时间。然而在实践中,我们几乎不需要在上述最小值中考虑k小于i的所有可能值。除了确保f(i, j)隐含的运动顺序仍然可行之外,max(e(i), ...)也是实际加速的关键:一旦我们发生导致e(i)项的ak到&#34;踢进去&#34; (成为max()比较的两个术语中较大的一个),它仍然是最好的可行选项 - 因为任何后续的k声称允许更快地完成任务必然涉及将分配器推到右边太远在最后一步。这意味着我们不需要尝试任何其他k值:e(i)确实是真正的最小值。

如果我们想要计算的是填充一定数量锥体所需的最小时间,我们实际上可以在O(n)空间中进行,通过利用计算f(i,j)时的事实,我们只访问f()的先前值,第二个参数等于j-1。但是,由于我们真正想要的是与最小时间相对应的动作序列,我们需要记录一个前辈p [i] [j]的表,这确实需要O(n ^ 2)空间。

伪代码

Sort cone[1 .. n] by increasing x co-ord.
Compute e[i] for all 1 <= i <= n.
Set f[i][1] = e[i] + T for all 1 <= i <= n.
Set f[i][j] = infinity for all 1 <= i <= n, 2 <= j <= i.
maxCones = 0.
bestTime = infinity.

# Compute f(i, j) for all i, j.
For j from 2 up to n:
    For i from j up to n:
        g = infinity.             # Best time for f(i, j) so far.
        For k from j up to i-1:
            z = f[k][j-1] + m(k, i) + T.
            If z < g:
                p[i][j] = k.
                If z < e[i] + T:
                    g = e[i] + T.
                    Break out of innermost (k) loop.
                Else:
                    g = z.

        If U * g - P <= cone[i].x:
            f[i][j] = g.
            If maxCones < j or (maxCones == j and g < bestTime):
                maxCones = j.     # New record!
                bestI = i.
                bestTime = g.
        Else:
            f[i][j] = infinity.

# Trace back through p[][] to find the corresponding action sequence.
For j from maxCones down to 1:
    fill[j] = bestI.
    bestI = p[bestI][j].

运行此操作后,maxCones将包含可以填写的最大锥体数量,如果这是> = 1,那么fill[1]fill[maxCones]将包含相应的要填充的maxCone个圆锥ID(排序顺序中的位置)的序列,所需的总时间将在bestTime

可能的增强功能

上述算法只能在分配器不会向后移动的限制下最佳地解决问题,而且速度太快&#34;。这在实践中可能是非常严格的限制:例如,像以下

的锥体模式
X X X X


 X X X X

将使分配器在填充的每个锥体之间进行长时间的垂直移动(假设它能够填充所有这些)。在同一行填充几个锥体,然后移动到另一行将节省大量时间。

在没有上述限制的情况下最佳地解决问题的困难在于它开始看起来非常像某些NP难问题,例如欧几里德TSP问题。我没有时间寻找正式的缩减,但我确信你的问题的无限制版本是NP难的,所以我们希望用多项式时间算法做的最好的就是寻找良好的启发式方法。为此:

上面的DP解决方案基本上为每个锥体i找到了总共填充j个锥体的最佳方法,以锥体i结束并且仅使用其他锥体到其左侧。我们可以通过将锥体的排序序列分成b个锥体的连续块来解决一个稍微更普遍的问题,然后为每个锥体i找到填充j锥体的最佳方法,该锥体在锥体i处结束并且仅使用锥体这是(a)在较早的块中(这些锥体必须在i的左侧)或(b)在与i相同的块中(这些锥体不是必须的)。这种方法忽略的唯一解决方案是那些需要我们在某个区块中填充圆锥体然后在较早的区域中填充圆锥体的那些解决方案(这尤其包括我们在某个区域中填充圆锥体的所有解决方案,锥形区域一个不同的块,然后再次在第一个块中的另一个锥体 - 块之间的两个移动中的至少一个必须移动到前一个块。)

显然,如果我们选择b = n,那么这将找到整体最优(一百万年),但是b不需要在这么大的附近,以获得最佳解决方案。使用the O(n^2*2^n) DP algorithm for solving TSP的变体来帮助计算块内最优路径,例如,选择b = 10是非常可行的。

还有一个建议是,不是将块大小精确地固定为b,而是可以首先将锥体更智能地分割成大小最多 b的块,也就是说,(以这种方式)未知)最优解很少需要填充前一个块中的锥形。事实上,只要可以启发式地获得断点&#34;质量&#34; (例如,通过使用2个块中任意一对点之间的最小距离),使用(不同的)DP可以在O(bn)时间内轻松地计算最大化得分的阻塞模式!