【问题标题】:How do I find all sets of matrix columns that together contain a value for every row?如何找到所有矩阵列集,它们一起包含每一行的值?
【发布时间】:2011-03-07 01:17:13
【问题描述】:

给定一个布尔值矩阵(示例):

    a  b  c
  +--------
X | 1  0  1  
Y | 1  1  1
Z | 0  1  1
  +--------

找到所有序列 [a|b|c] 的最佳方法是什么,使得每个序列对于 X、Y 和 Z 中的每一个都至少有一个“真”(1) 值。

在上面的例子中,序列集是(不分先后):

  abc, ab, ac, bc, c

而这些序列不满足要求:

  a (doesn't provide Z)
  b (doesn't provide X)

我实际上是在寻找任意矩阵的通用算法。

有什么想法吗?

【问题讨论】:

    标签: algorithm matrix


    【解决方案1】:

    基本上你正在解决X & Y & Z where X = a | c, Y = a | b | c, Z = b | c for a, b and c.

    所以基本上你是在conjunctive normal form 中的一个公式上寻找SAT 的所有解决方案。尽管存在一些简化,但基本上任何方法都是 O(2N)。在wikipedia article 中列出了有效找到此类问题的解决方案的算法;但是,如果您想要所有解决方案,无论如何您都将迭代 2N 种可能性,因此只需枚举它们并进行测试就足够了。

    一些琐碎的优化:

    • 公式中没有否定,所以如果你有一个解决方案,那么在该解决方案中添加任何其他变量也将是一个解决方案。您的 OP 说您想要所有解决方案;对于大型矩阵,将有许多基于相同必要基础和所有不必要值选择的解决方案。
    • 如果您 and 列中的所有值并得到 1,则该列是解决方案的基础(该列和其他列的任何选择都是解决方案)
    • 如果你or一列中的所有值并得到0,那么该列对任何解决方案的基础都没有贡献
    • 基于组合集合查找基的方法(仅在选择未选择的行时向集合添加一列)可能比查找所有解决方案的方法更好
    • 如果您采用组合解决/确实解决问题的集合的方法 - 非解决方案的联合或解决方案的交集 - 最好将行分成两行,并对具有少数 1,以及针对少数 0 的行的否定方法。

    由于它是一个 2N 问题,因此假设 N

    【讨论】:

    • 嘿Pete--非常感谢非常。你的帖子很有帮助。
    【解决方案2】:

    将您的矩阵表示为图形,然后您可以找到所有集群。我很确定这可以概括(以 graphviz 表示法),因为您可以将矩阵视为邻接矩阵并使用

    graph G {
    
    A -- X;
    A -- Y;
    B -- X;
    B -- Y;
    C -- X;
    C -- Y;
    C -- Z;
    
    }
    

    ABC 可以到达 XYZ BC可以到达XYZ AC可以到达XYZ AB可以到达XYZ C可以到达XYZ

    A 无法到达 XYZ B 无法到达 XYZ

    http://rollerjm.free.fr/pro/graphs.html

    【讨论】:

      【解决方案3】:

      您可以确定满足 X (a,ab,ac,abc,bc,c) 的集合,将其与满足 Y (a,ab,ac,abc,b,b​​c,c) 的集合相交,并且将结果与填充 Z (ab, ac, abc, b, bc, c) 等的集合相交。

      对于更大的矩阵,您可以使用此操作中的分而治之模式:取一半条件并确定它们的集合,取另一半条件并确定它们的集合,然后将这两个集合相交。对两个部分重复...

      【讨论】:

        【解决方案4】:

        在 O(2^n) 时间内运行的一种可能算法是递归地尝试每种可能性。

        所以在伪代码中:

        validSequence(vector<columns> cols, vector<columns> sequence)
            // base case for recursion
            if (cols.empty)
                if (validSequence(sequence))
                    printSequence(sequence)
                else
                    // invalid sequence
            // now we recurse using the next row and not using the next row
            column nextRow = pop(cols)
            validSequence(cols, sequence)
            sequence.push(nextRow)
            validSequence(cols, sequence)
        

        显然你仍然需要实现validSequence(sequence) 函数,但我很确定这会起作用

        希望对你有帮助

        【讨论】:

          【解决方案5】:
          1. 获取每行的非序列。
          2. 确定这些序列的所有子序列。
          3. 你的答案是剩下的所有序列。

          本质上,您将 (不提供 X 的序列) 和 (不提供 Y 的序列) 和 (不提供 Z 的序列) 并集,并取该集合的补集.

          我认为这可以概括。

          【讨论】:

          • 如果任意矩阵的 0 比 1 多,这比正数版本更糟糕 - 如果它在前导对角线上只有 1,那么您正在计算 N2(N- 1) 不匹配的集合以找到匹配的集合。这是适用于某些矩阵的优化;没有比 2N 更好的通用方法
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-11
          • 1970-01-01
          • 2018-12-05
          • 1970-01-01
          相关资源
          最近更新 更多