找到元素的最佳排序

时间:2013-04-27 13:33:53

标签: algorithm list sorting

我有一份需要打印的徽标列表(最多4种颜色)。每个徽标都需要设置时间来混合该徽标所需的颜料。如果我可以对数据进行排序,以便使用相同颜色的两个徽标背靠背,那么我们就不必混合尽可能多的颜色来节省金钱和时间。涂料混合后的使用寿命有限。

我正在寻找像这样的数据集......

Red | (Other Color)
Red | Black
(Other Color) | Black

它需要以该顺序结束。这是唯一允许我制作1个红色和1个黑色的顺序。我尝试了一些事情,例如为每种常见颜色指定一个值,但无论如何,我似乎无法正确地对其进行排序。


我使用了以下根据TSP问题编写的SQL过程。 (http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=172154

使用以下测试数据,我收到了正确的输出

delete from routes
delete from cities
insert into cities values ('Black|Red')
insert into cities values ('Red')
insert into cities values ('Blue')
insert into cities values ('Black')
insert into cities values ('Blue|Red')

-- Numeric Value is Colors not Matching

insert into routes values ('Black|Red', 'Red', 3)
insert into routes values ('Black|Red', 'Black', 3)
insert into routes values ('Red', 'Black', 4)
insert into routes values ('Blue|Red', 'Red', 3)
insert into routes values ('Blue|Red', 'Black', 4)
insert into routes values ('Blue', 'Red', 4)
insert into routes values ('Blue', 'Black|Red', 4)
insert into routes values ('Blue', 'Black', 4)
insert into routes values ('Blue', 'Blue|Red', 3)

exec getTSPRoute 'Black'

Results:
Black->Black|Red->Red->Blue|Red->Blue->Black

唯一的问题是回到原来的城市" (黑色返回开始和结束)我必须选择一个"开始城市。"如果选择了错误的选项,我不会得到最优化的路线。

3 个答案:

答案 0 :(得分:4)

看起来像travelling salesman problem (TSP)。让我解释一下。

首先,请考虑一个示例,其中包含四个城市ABCD的地图。 (我在示例中使用了4但它与颜色数无关)。你想找到城市之间的路线,这样你(1)只访问每个城市一次,(2)路线最短。 [D,C,A,B]可能比[B,A,D,C]更短,而您想要的是最短的。{/ p>

现在,您有四个徽标,而不是城市。您希望找到徽标的这种排序,从而在混色方面产生最低成本。如果您想象您的每个徽标都是一个点(城市),并且徽标之间的距离是在一个颜色集与另一个颜色集之间切换的“成本”,那么您需要找到这些点之间的最短“路线”。一旦你有这条最短的路线,它会告诉你如何订购这些标志。例如,可以将两个标识L1和L2之间的“距离”定义为L2中不在L1中的多种颜色。

TSP这是一个众所周知的算法问题。这很难(实际上,NP-hard)。 如果您的输入很小,您可以找到最佳解决方案。如果是4个徽标,则有24个可能的组合。对于10个徽标,您有360万个组合,对于20个徽标,您将获得2432902008176640000组合(如何阅读?)。因此,对于大于10-15的输入,您需要使用一些启发式找到近似解,我相信这对您来说已经足够了。

我要做的是创建一个混色成本图并将其提供给某些TSP solver

修改

  • 澄清。并非每个徽标都是一个单独的点,但徽标中的每个颜色集都是一个点。也就是说:如果您有两个具有相同颜色集的徽标,则将它们视为单个点,因为它们将一起打印。带有红色,蓝色,黑色的徽标位于点上,带有红色,绿色的徽标是另一个点。
  • 它比TSP更Hamiltonian path problem(您不需要以与开头相同的颜色设置结束),但它没有太大变化
  • 如果您的徽标中可能没有匹配项,那么首先将您的徽标拆分为不相关的组,这些组之间没有匹配项,然后分别考虑每个组。如果您的任何徽标之间没有匹配项,那么您就无法做很多事情:)
  • 实际上,我会使用python和networkx库来将您的问题建模为图形,稍后我会将其传递给某些TSP求解器。只需格式化输入并让其他程序完成所有繁琐的工作。

答案 1 :(得分:1)

对于合理数量的徽标和颜色,一种简单的方法是强力方法,在这种方法中,您需要经历所有组合并在每次需要混合时增加计数器。之后,您按该计数器对组合进行排序,并选择具有最低值的组合。

伪代码

foreach combination
    foreach print
        foreeach color 
            if not previous_print.contains(color)
                cost++

order combination by cost (ascending)

您没有提及您是否正在使用(或即将)任何您打算执行此类操作的工具(电子表格,编程语言......)。

编辑:

这是VB.NET中的一个快速实现。请注意,有意留下代码,以便于阅读和理解。

Private Sub GoGoGo()
    ' Adds some logos 
    ' This is where you add them from the database or text file or wherever
    Dim logos() =
    {
        New String() {"Black", "Magenta", "Orange"},
        New String() {"Red", "Green", "Blue"},
        New String() {"Orange", "Violet", "Pink"},
        New String() {"Blue", "Yellow", "Pink"}
    }

    ' Used to store the best combination
    Dim minimumPermutation
    Dim minimumCost = Integer.MaxValue

    ' Calculate all permutations of the logos
    Dim permutations = GetPermutations(logos)

    ' For each permutation
    For i As Integer = 0 To permutations.Count() - 1
        Dim permutation = permutations(i)
        Dim cost = 0

        ' For each logo in permutation
        For j As Integer = 0 To permutation.Count() - 1
            Dim logo = permutation(j)

            ' Check whether the previous logo contains one or more colors of this logo
            For Each color In logo
                If (j > 0) Then
                    If Not permutation(j - 1).Contains(color) Then
                        cost += 1
                    End If
                Else
                    cost += 1
                End If
            Next
        Next

        ' Save the best permutation
        If (i = 0 Or cost < minimumCost) Then
            minimumCost = cost
            minimumPermutation = permutation.Clone()
        End If
    Next

    ' Output the best permutation
    For Each logo In minimumPermutation
        Console.Write(logo(0) + " " + logo(1) + " " + logo(2))
    Next
End Sub

Public Shared Iterator Function GetPermutations(Of T)(values As T(), Optional fromInd As Integer = 0) As IEnumerable(Of T())
    If fromInd + 1 = values.Length Then
        Yield values
    Else
        For Each v In GetPermutations(values, fromInd + 1)
            Yield v
        Next

        For i = fromInd + 1 To values.Length - 1
            SwapValues(values, fromInd, i)
            For Each v In GetPermutations(values, fromInd + 1)
                Yield v
            Next
            SwapValues(values, fromInd, i)
        Next
    End If
End Function

Private Shared Sub SwapValues(Of T)(values As T(), pos1 As Integer, pos2 As Integer)
    If pos1 <> pos2 Then
        Dim tmp As T = values(pos1)
        values(pos1) = values(pos2)
        values(pos2) = tmp
    End If
End Sub

答案 2 :(得分:1)

我怀疑遗传算法对此有好处。如果你有很多徽标,蛮力解决方案可能需要一段时间,贪婪不太可能产生良好的效果。

http://en.wikipedia.org/wiki/Genetic_algorithm