对二进制2D矩阵进行排序?

时间:2009-11-19 01:57:19

标签: algorithm sorting matrix

我正在寻找一些指示,因为我不知道从哪里开始研究这个。

我在每个单元格中都有一个0或1的2D矩阵,例如:

  1 2 3 4
A 0 1 1 0
B 1 1 1 0
C 0 1 0 0
D 1 1 0 0

我想对它进行排序,使其尽可能为“上三角”,如下:

  4 3 1 2
B 0 1 1 1
A 0 1 0 1
D 0 0 1 1
C 0 0 0 1

行和列必须保持完整,即元素不能单独移动,只能“整体”交换。

据我所知,可能存在一种病态情况,其中矩阵具有多个可能的排序结果(即相同的形状,但“原始”行/列的标识不同。)

那么,任何人都可以建议我在哪里找到一些起点吗?现有的库/算法会很棒,但我会知道我想要解决的问题的名称!

我怀疑这是一个线性代数问题,也许有一种适用的图像处理技术。

除了其他任何想法,我最初的猜测只是在行上写一个简单的插入排序,然后对列进行迭代,直到它稳定(并希望检测病理情况不太难。)

更多细节:有关我正在尝试做的更多信息可能有助于澄清。每行代表一个竞争者,每列代表一个挑战。每个1或0代表竞争对手在特定挑战中的“成功”。

通过对矩阵进行排序以使所有1都位于右上方,我希望随后提供每个挑战的内在难度和竞争对手排名的排名(这将考虑他们成功的挑战的难度) at,而不仅仅是成功的数量。)

关于已接受答案的说明:我已接受模拟退火作为“答案”,但需要注意的是此问题没有正确答案。这似乎是一个很好的方法,虽然我实际上没有设法得到一个适用于我的问题的评分函数。

6 个答案:

答案 0 :(得分:6)

基于simulated annealing的算法可以在没有太多麻烦的情况下处理这类事情。如果你的小矩阵很可能是一个固定的解决方案,那就太好了,但如果你的矩阵变得更大并且问题变得更加困难,那就太棒了。

(但是,你也不希望插入可以逐步完成。)

<强>预赛

  1. 设计一个“得分”矩阵的表现函数 - 更接近三角形的矩阵应得到比三角形y更小的矩阵。

  2. 在矩阵上设计一组允许的操作。您的描述有点模棱两可,但如果您可以交换行,那么一个操作将是SwapRows(a, b)。另一个可能是SwapCols(a, b)

  3. 退火循环

    我不会在这里给出完整的论述,但这个想法很简单。您可以使用操作对矩阵执行随机转换。您可以测量操作后矩阵的“更好”程度(使用操作前后的性能函数)。然后你决定是否提交转换。你重复这个过程很多

    决定是否提交转换是有趣的部分:您需要决定是否执行该操作。在退火过程结束时,您只接受改善矩阵分数的转换。但是在早些时候,在一个更混乱的时代,你允许转换不会提高分数。在一开始,算法是“热”的,任何事情都会发生。最终,算法冷却,只允许良好的转换。如果线性冷却算法,则选择是否接受转换是:

    public bool ShouldAccept(double cost, double temperature, Random random) {
        return Math.Exp(-cost / temperature) > random.NextDouble();
    }
    

    您应该阅读Numerical Recipes中包含的优秀信息,以获取有关此算法的更多信息。

    长话短说,你应该学习一些这些通用算法。这样做可以解决难以分析解决的大类问题。

    评分算法

    这可能是最棘手的部分。你需要设计一个能够指导退火过程实现目标的记分员。记分员应该是一个连续的函数,当矩阵接近理想的解时,它会产生更大的数字。

    您如何衡量“理想解决方案” - 三角形?这是一个天真而简单的得分手:对于每一点,你都知道它应该是1还是0。如果矩阵是正确的,则为分数添加+1,如果是错误则为-1。这里有一些代码,所以我可以明确(未经过测试!请查看!)

    int Score(Matrix m) {
        var score = 0;
        for (var r = 0; r < m.NumRows; r++) {
            for (var c = 0; c < m.NumCols; c++) {
                var val = m.At(r, c);
                var shouldBe = (c >= r) ? 1 : 0;
                if (val == shouldBe) {
                    score++;
                }
                else {
                    score--;
                }
            }
        }
        return score;
    } 
    

    使用这种评分算法,1和0的随机字段将得分为0.“相反”三角形将给出最大的负分数,正确的解决方案将给出最大的正分数。两个分数的差异会给你带来成本。

    如果这个得分手不适合你,那么你需要“调整”它直到它产生你想要的矩阵。

    此算法基于这样一个前提,即调整此记分器比设计用于对矩阵进行排序的最佳算法要简单得多。

答案 1 :(得分:1)

我提出了以下算法,它似乎正常工作。

阶段1:移动大多数1 s的行和大多数1 s的行。

  1. 首先是行。通过计算1 s来对行进行排序。我们不在乎 如果2行具有相同数量的1 s。
  2. 现在列。按cols排序 计算他们的1。我们不在乎 如果2个cols的数量相同 1秒。
  3. 阶段2:重复阶段1 ,但要有额外的标准,以便我们满足三角矩阵变形。
    行标准:如果2行具有相同数量的1 s,我们将向上移动以较少0秒开头的行。

    cols的标准:如果2个col具有相同数量的1 s,我们将向右移动在底部具有较少0 s的col。


    示例:

    第1阶段

      1 2 3 4                     1 2 3 4                   4 1 3 2
    A 0 1 1 0                   B 1 1 1 0                 B 0 1 1 1
    B 1 1 1 0  - sort rows->    A 0 1 1 0  - sort cols->  A 0 0 1 1
    C 0 1 0 0                   D 1 1 0 0                 D 0 1 0 1
    D 1 1 0 0                   C 0 1 0 0                 C 0 0 0 1
    

    第2阶段

      4 1 3 2                     4 1 3 2
    B 0 1 1 1                   B 0 1 1 1
    A 0 0 1 1  - sort rows->    D 0 1 0 1  - sort cols-> "completed"
    D 0 1 0 1                   A 0 0 1 1
    C 0 0 0 1                   C 0 0 0 1
    

    编辑:事实证明我的算法始终没有给出正确的三角矩阵 例如:

    第1阶段

       1 2 3 4                    1 2 3 4                
    A  1 0 0 0                  B 0 1 1 1                
    B  0 1 1 1 - sort rows->    C 0 0 1 1  - sort cols-> "completed"
    C  0 0 1 1                  A 1 0 0 0                
    D  0 0 0 1                  D 0 0 0 1                
    

    第2阶段

       1 2 3 4                    1 2 3 4                   2 1 3 4
    B  0 1 1 1                  B 0 1 1 1                 B 1 0 1 1
    C  0 0 1 1 - sort rows->    C 0 0 1 1  - sort cols->  C 0 0 1 1
    A  1 0 0 0                  A 1 0 0 0                 A 0 1 0 0
    D  0 0 0 1                  D 0 0 0 1                 D 0 0 0 1
                               (no change)
    

    (*)或许阶段3 会增加良好的结果。在该阶段,我们将以较少0 s开头的行放在顶部。

答案 2 :(得分:1)

寻找Anna Lubiw关于“矩阵的双重词汇排序”的1987年论文。

下面有一个引文。订单与您要查找的内容不同,但非常接近。如果不出意外,你应该可以从中获得一个好主意。

http://dl.acm.org/citation.cfm?id=33385

答案 3 :(得分:0)

这是一个起点:

将每行从二进制位转换为数字

按降序对数字进行排序。

然后将每一行转换回二进制。

答案 4 :(得分:0)

基本算法:

  1. 确定行总和并存储 值。确定列总和 和存储值。
  2. 按升序对行总和进行排序。对列进行排序 按升序排列。
  3. 希望你应该有一个尽可能靠近右上角三角形区域的矩阵。

答案 5 :(得分:0)

将行视为二进制数,最左边的列为最高位,并按降序排列,从上到下

将列视为二进制数,最下面的行为最高位,并按从左到右的升序排序。

重复直到达到固定点。该算法终止的证据留给读者作为练习。