0

我创建了一个 PDL 矩阵。我需要在每一行之间进行成对比较。目前我正在使用“where”和“cov”命令返回两个切片的成对比较(在 perl 循环中生成)。

我的问题:如何使用“范围”和“切片”以成对的方式遍历行?如何返回我的索引位置?我已经使用 perl 遍历了矩阵。我读过用 perl 循环真的削弱了 PDL 的力量。

期望的输出:

indexA indexB Value
pos1   pos5   1
pos1   pos6   5
pos1   pos0   7 

需要明确的是,我只想使用 PDL 功能。

这是一些伪代码(希望)可以更好地说明我的观点。

p $b

[
 [1 0 3 0]
 [0 1 0 1]
 [1 3 1 3]   <- example piddle y
 [0 1 0 1]   <- example piddle z
]

my concept function{


slice $b (grab row z) - works fine
slice $b (grab row y) - works fine


($a, $b) = where($a,$b, $a < 3 && $b < 3 ) - works fine

p $a [1 1] 
p $b [0  0] 

cov($a $b) - works just fine.

}

我只需要一种在所有行中成对执行的方法。我需要进行阶乘(n 行)比较。

4

2 回答 2

1

PDL 线程是您在这里寻找的概念。沿维度循环的一般技术是在适当的位置添加虚拟维度,以便计算生成所需的隐式线程循环。对于多维问题,可以有多种不同的方法来添加暗淡,从而创建线程循环。

对于成对行计算,您可以在切片索引上选择两个嵌套循环,该循环在两个索引计数上具有 perl 循环,并将沿行生成 PDL 线程。您可以只对索引使用一个 perl 循环,但利用隐式线程循环一次计算所有行。

完全 PDL 线程循环计算将是为每个参数的行上的循环添加一个虚拟维度,以便您一次计算整个 N**2 行计算。这是一个形状 [4,3] 数组的示例,其计算是 == 运算符:

pdl> $b = floor(random(4,3)*5)

pdl> p $b

[
 [0 4 3 3]
 [3 3 4 2]
 [4 0 1 4]
]

pdl> p $b(,*3)==$b(,,*3)

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

结果是一个形状 [4,3,3] piddle,第 0 维对应于成对计算产生的行,第 1 和第 2 暗对应于 == 操作中涉及的行索引。

如果您需要来自这些线程循环计算之一的索引值,请使用xvalsyvalszvalsaxisvals生成一个带有与该数组轴对应的索引值的 piddle。

pdl> p $b->xvals

[
 [0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]
]


pdl> p $b->yvals

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

有很多与 PDL 线程实现相关的细节(与 perl 线程或 posix 线程不同)。我推荐perldl 邮件列表供其他 PDL 用户和开发人员参考和讨论。此外,请参阅PDL Book的第一个在线草稿,其中更全面地涵盖了 PDL 计算和线程。

于 2012-04-21T19:00:12.437 回答
0

我认为您正在寻找的是一种方法来查找数组中所有不同的行对,然后使用cov? 如果这是正确的,那么我还没有听说过,cov快速搜索文档也无济于事。但是,我可以说一些可能会有所帮助的事情。

我认为您对退出PDLPerl 代码过于谨慎,如果您所做的只是循环所有行对的索引并使用slice. 这显示在下面的一些示例代码中。

此外,您不能这样称呼where,因为$a < 3etc. 本身就是 piddles,并且布尔运算符不会对它们执行您想要的操作。请改用&运算符,并添加一些括号以确保表达式以正确的顺序执行。

除此之外,除非您纠正我对您的问题的理解或指导我查看cov子例程的一些文档,否则我无能为力。

use strict;
use warnings;

use PDL;

my $dat = pdl <<END;
[
 [1 0 3 0]
 [0 1 0 1]
 [1 3 1 3]
 [0 1 0 1]
]
END

my $max2 = $dat->dim(1) - 1;

for my $i (0 .. $max2 - 1) {
  for my $j ($i + 1 .. $max2) {

    my $row1 = $dat->slice(",($i)");
    my $row2 = $dat->slice(",($j)");

    ($row1, $row2) = where($row1, $row2, ($row1 < 3) & ($row2 < 3));

    cov($row1, $row2);
  }
}
于 2012-03-02T07:59:17.907 回答