【问题标题】:Determine if some row permutation of a matrix is Toeplitz确定矩阵的某些行排列是否为 Toeplitz
【发布时间】:2014-01-09 09:23:18
【问题描述】:

Toeplitz 矩阵“是一个矩阵,其中从左到右的每个下降对角线都是常数。”给定一个二进制矩阵 M,是否有一种有效的算法来确定是否存在使其成为 Toeplitz 的行的排列?

例如设置

M= [0 1 1]
   [1 1 0]
   [1 0 1]

如果你交换第一行和第二行,你会得到

[1 1 0]
[0 1 1]
[1 0 1]

这是托普利茨。

在python中,你可以制作一个随机的二进制矩阵,如下所示。

n = 10
h = 10
M =  np.random.randint(2, size=(h,n))

我想将测试应用到 M。

(注意矩阵M不需要是方阵。)

【问题讨论】:

  • 我可以将这个问题简化为找到Hamiltonian path(通过将行视为顶点并连接可能相邻的行),但我认为这不会有很大帮助(因为它是 NP-全部)。

标签: algorithm matrix language-agnostic


【解决方案1】:

这个问题可以在线性 O(h*w) 时间内解决,其中h 是行数,w 是列数。

构造一个图,其中每个顶点对应于(w-1)-length 子字符串,该子字符串可以是矩阵中某行的前缀或后缀。一个顶点可能对应多个重复的子串。用h 边连接这些顶点。每条边对应于矩阵的行。从该行前缀对应的顶点指向该行后缀对应的顶点。

要确定某个行置换是否为 Toeplitz 矩阵,只需检查构造的图是否为欧拉图即可。要查找排列本身,在此图中找到Eulerian path 就足够了。

我们需要一些有效的方法来互连顶点和边。直截了当的方法假设比较每个行子串对。这不是很有趣,因为 O(h2*w) 时间复杂度。

为矩阵的行构建Generalized suffix tree(或后缀数组)只需要 O(h*w) 时间。而且这棵树还允许在线性时间内互连顶点和边:每个深度为w-1 的内部节点代表一些(w-1)-length 子字符串(顶点);连接到该节点的每个叶子都代表某行的后缀(传入边);并且附加到该节点的子节点的每个叶子都表示包含该子字符串作为前缀(出边)的某些行。

其他选择是使用哈希映射。使用矩阵行的(w-1)-length 子字符串作为键,并使用一对行索引列表(对于该子字符串为前缀/后缀的行)作为值。与后缀树/数组方法相比,这允许更简单的实现,需要更少的内存(每个键只需要空间用于散列值和指向子字符串开头的指针),应该更快(平均而言),但具有较低的最坏情况复杂性: O(h2*w).

【讨论】:

    【解决方案2】:

    您可以对淘汰条件进行初步检查:

    1. 找出矩阵所有列的列和。
    2. 现在,在行的任何排列中,列中的值应保持在同一列中。
    3. 因此任何相邻两列之和的差值应最大为 1。

    另外,如果 i 和 i+1 是两个相邻的列,那么:

    1. 如果sum(i+1) = sum(i) + 1,那么我们知道第 i 列中最底部的元素应该是 0,而第 (i+1) 列中最顶部的元素应该是 1。

    2. 如果sum(i+1) = sum(i) - 1,那么我们知道第 i 列中最底部的元素应该是 1,而第 (i+1) 列中最顶部的元素应该是 0。

    3. 如果sum(i+1) = sum(i),那么我们知道第 i 列中最底部的元素应该等于第 (i+1) 列中最顶部的元素。

    您还可以通过对行求和来进行类似的检查,看看是否存在任何相邻两行之和之差最多为 1 的排列。

    当然,您仍然需要进行一些组合搜索,但上述过滤器可能会减少搜索场景。

    这是因为您现在必须为每对相邻列搜索满足上述 3 个条件的一对(候选顶部和底部)行。

    此外,如果行数远大于列数,则此优化不会很有帮助。

    【讨论】:

      【解决方案3】:

      一种适用于小型矩阵的简单方法是:

      Sort the rows of M
      For each choice of start row
          For each choice of end row
               construct a Toeplitz matrix T from the given start and end row
               Sort the rows of T and compare to M
               If you find a match then T is a permutation of M that is Toeplitz
      

      这是基于这样一个事实,即一旦您知道开始行和结束行,Toeplitz 矩阵就是唯一定义的。

      但是,这种方法并不是特别有效。

      示例 Python 代码

      M= [[0, 1, 1],
         [1, 1, 0],
         [1, 0, 1]]
      
      n=len(M)
      M2 = sorted(M)
      for start in M2:
          for end in M2:
              v = end+start[1:]
              T = [v[s:s+n] for s in range(n-1,-1,-1)]
              if sorted(T)==M2:
                  print 'Found Toeplitz representation'
                  print T
      

      打印

      Found Toeplitz representation
      [[0, 1, 1], 
       [1, 0, 1], 
       [1, 1, 0]]
      Found Toeplitz representation
      [[1, 0, 1],
       [1, 1, 0],
       [0, 1, 1]]
      Found Toeplitz representation
      [[1, 1, 0], 
       [0, 1, 1], 
       [1, 0, 1]]
      

      【讨论】:

      • 谢谢。我想知道这个问题是否可以在 n^2 时间内解决。
      • 我认为,如果不是排序,而是构建一个二进制 trie 来保存行,您也许可以在此处删除一个日志因子。
      • 你的意思是:一个 NxN “一旦你知道开始行和结束行,Toeplitz 矩阵是唯一定义的?”在我看来,在 num_rows > num_columns + 1 的 Toeplitz 矩阵中,将存在仅使用开始行和结束行无法确定的内部对角线。
      • @groovy:非常正确,根据问题中的示例,我假设矩阵是正方形的。
      猜你喜欢
      • 1970-01-01
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多