【问题标题】:APL: Matrix manipulation trick?APL:矩阵操作技巧?
【发布时间】:2013-07-16 22:37:04
【问题描述】:

我正在尝试找到一种方法(惯用或其他方式)来转换看起来像的矩阵

0 1
0 1
0 1

分成 3 个单独的矩阵

0 1
0 0
0 0

0 0
0 1
0 0

0 0
0 0
0 1

所以当我将它们全部放在一起时,我会得到原件。 这些“子矩阵”中的每一个都必须只有 1 个非零元素,并且必须具有与原始相同的形状。

【问题讨论】:

    标签: matrix apl


    【解决方案1】:

    一个解决方案:

    任何布尔矩阵:

          m←4 3⍴?12⍴2
          m
    0 0 1
    0 0 0
    1 1 0
    0 1 0
    

    注意它的形状:

        d←⍴m
        d
    4 3
    

    将矩阵分解成向量:

          v←,m
          v
    0 0 1 0 0 0 1 1 0 0 1 0
    

    生成索引:

              i ←⍳⍴v
              i
        0 1 2 3 4 5 6 7 8 9 10 11
    

    为原矩阵中的每一个1构造一个矩阵:

          a←d∘⍴¨↓(v/i)∘.=i
          a
     0 0 1  0 0 0  0 0 0  0 0 0 
     0 0 0  0 0 0  0 0 0  0 0 0 
     0 0 0  1 0 0  0 1 0  0 0 0 
     0 0 0  0 0 0  0 0 0  0 1 0 
    

    验证结果:

       ↑∨/a
    0 0 1
    0 0 0
    1 1 0
    0 1 0
    

    使用散点索引也可能是一种很好的方法,首先生成一个 3 维矩阵,然后指定 1 的位置。

    是的,如上使用 v 和 d:

           n←+/v
           b←(n,d)⍴0
           b[↓⍉(⍳n)⍪d⊤v/⍳⍴v]←1
           b
    0 0 1
    0 0 0
    0 0 0
    0 0 0
    
    0 0 0
    0 0 0
    1 0 0
    0 0 0
    
    0 0 0
    0 0 0
    0 1 0
    0 0 0
    
    0 0 0
    0 0 0
    0 0 0
    0 1 0
          ∨⌿b
    0 0 1
    0 0 0
    1 1 0
    0 1 0
    

    【讨论】:

      【解决方案2】:

      给定一个向量 A:

      +A←3 4⍴1 0 1 0 1 0 0 0 0 1 0 1
      
      1 0 1 0
      1 0 0 0
      0 1 0 1
      

      将其分解为组件矩阵,如下所示:

      +(⍴A)∘⍴¨⊂[2](,A)\B B⍴1,(B←+/,A)⍴0
      
      1 0 0 0   0 0 1 0   0 0 0 0   0 0 0 0   0 0 0 0 
      0 0 0 0   0 0 0 0   1 0 0 0   0 0 0 0   0 0 0 0 
      0 0 0 0   0 0 0 0   0 0 0 0   0 1 0 0   0 0 0 1
      

      工作原理

      先把1的个数赋给B:

      B←+/,A          ⍝ 5
      

      创建一个如本文所述的单位矩阵:The most idiomatic way of creating identity matrix in APL:

      B B⍴1,(B←+/,A)⍴0
      
      1 0 0 0 0
      0 1 0 0 0
      0 0 1 0 0
      0 0 0 1 0
      0 0 0 0 1
      

      解开原矩阵:

      ,A              ⍝ 1 0 1 0 1 0 0 0 0 1 0 1
      

      使用 raveled 矩阵来扩展单位矩阵。这将创建一个矩阵,其中每一行都是组件矩阵的分解形式:

      +(,A)\B B⍴1,(B←+/,A)⍴0
      
      1 0 0 0 0 0 0 0 0 0 0 0
      0 0 1 0 0 0 0 0 0 0 0 0
      0 0 0 0 1 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 1 0 0
      0 0 0 0 0 0 0 0 0 0 0 1
      

      将该矩阵转换为行向量:

      +⊂[2](,A)\B B⍴1,(B←+/,A)⍴0
      
      1 0 0 0 0 0 0 0 0 0 0 0  0 0 1 0 0 0 0 0 0 0 0 0  0 0 0 0 1 0 0 0 0 0 0 0  0 0 0 0 0 0 0 0 0 1 0 0  0 0 0 0 0 0 0 0 0 0 0 1
      

      使用 A (⍴A) 的原始形状,创建最终矩阵:

      (⍴A)∘⍴¨⊂[2](,A)\B B⍴1,(B←+/,A)⍴0
      
      1 0 0 0   0 0 1 0   0 0 0 0   0 0 0 0   0 0 0 0 
      0 0 0 0   0 0 0 0   1 0 0 0   0 0 0 0   0 0 0 0 
      0 0 0 0   0 0 0 0   0 0 0 0   0 1 0 0   0 0 0 1
      

      【讨论】:

      • 非常好的解决方案!我喜欢这个,因为它只是重塑 1 和 0,除了 1 的数量之外不需要整数或索引。我曾认为必须有某种方法可以做到这一点并玩弄扩展,但我没有想到生成单位矩阵。确实很不错!
      • @PaulMansour - 谢谢,保罗!我也喜欢你的解决方案,但我对它有点困惑,因为我遇到了↓(v/i)∘.=i 的价错误。左边不应该有一个论据吗?
      • Monadic 向下箭头被称为“split”,其作用与 ⊂[2] 相同,将矩阵转换为向量的向量。可能并非在所有 APL 实现中都可用。
      • @PaulMansour - 可能就是这种情况,因为我使用的是 NARS2000。我会用⊂[2] 试试。感谢您的回复。
      【解决方案3】:

      使用 Dyalog APL 版本 16.0,您现在可以使用默认函数 ⍸{~@(⊂⍺)≠⍨⍵}⍤0 2⊢ 非常简洁地编写此代码。 查看这篇文章的底部,了解如何获取矩阵列表。

      Try it online!

      它是如何工作的?

      这是一个分叉,所以 的结果是{~@(⊂⍺)≠⍨⍵}⍤0 2 的左右参数。

       给出一个索引列表,参数中有 1

       just yields 未修改的参数

      {}⍤0 2 应用以下dfn,左参数的每个rank-0子数组(即1的每个索引)作为左参数,每个rank-2 右参数的子数组(即整个矩阵)作为右参数

      ≠⍨⍵不等自拍正确论据;给出一个形状相同但用零填充的矩阵

      ~@(⊂⍺) this 翻转(逻辑)位左参数指示的位置

      因此,对于每个 1,它都会创建一个全零层,在该层中其位置的位被翻转。


      如何获取矩阵列表:

      ⍸{~@(⊂⍺)≠⍨⍵}¨⊂ 给出所需矩阵的列表。 Try it online!

      这工作原理相同,但不是使用秩运算符对整个数组进行操作,而是使用¨⊂ 将 1 的每个索引与整个矩阵配对。

      【讨论】:

        猜你喜欢
        • 2013-01-24
        • 2014-07-27
        • 2016-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-13
        • 1970-01-01
        相关资源
        最近更新 更多