GoGPT Best VPN GoSearch

OnWorks 网站图标

PDL::Threadingp - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管服务提供商中运行 PDL::Threadingp

这是 PDL::Threadingp 命令,可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器

程序:

您的姓名


PDL::Threading - PDL 的线程功能教程

引言


PDL 最强大的功能之一是 穿线,这可以产生非常紧凑和
通过避免 C 和 BASIC 用户可能使用的多个嵌套 for 循环来实现非常快速的 PDL 代码
熟悉。 问题是它可能需要一些时间来适应,而新用户可能不会
欣赏线程的好处。

其他基于向量的语言,例如 MATLAB,使用线程技术的一个子集,但是
PDL 通过将它们完全概括为各种基于矢量的应用程序而大放异彩。

术语: 皮德尔


MATLAB 通常是指向量、矩阵和数组。 Perl 已经有数组,并且
术语“向量”和“矩阵”通常指的是一维和二维集合
数据。 由于没有好的术语来描述他们的对象,PDL 开发人员创造了这个术语
"iddle" 为其数据类型命名。

A iddle 由一系列组织为 N 维数据集的数字组成。 皮德尔斯
提供大型 N 维矩阵的高效存储和快速计算。 他们是
高度优化的数值工作。

思维 IN 条款 OF THREADING


如果您已经使用 PDL 一段时间了,那么您可能一直在使用线程
意识到它。 启动 PDL shell(在终端上输入“perldl”或“pdl2”)。 大多数例子
在本教程中使用 PDL shell。 确保 PDL::NiceSlice 和 PDL::AutoLoader 是
已启用。 例如:

% pdl2
perDLL 外壳 v1.352
...
已启用 ReadLines、NiceSlice、MultiLines
...
注意:未启用 AutoLoader(推荐使用“使用 PDL::AutoLoader”)

pdl>

在此示例中,自动启用了 NiceSlice,但未启用 AutoLoader。 启用
输入“使用 PDL::AutoLoader”。

让我们从二维开始 iddle:

pdl> $a = 序列(11,9)
pdl> p $a
[
[0 1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20 21]
[22 23 24 25 26 27 28 29 30 31 32]
[33 34 35 36 37 38 39 40 41 42 43]
[44 45 46 47 48 49 50 51 52 53 54]
[55 56 57 58 59 60 61 62 63 64 65]
[66 67 68 69 70 71 72 73 74 75 76]
[77 78 79 80 81 82 83 84 85 86 87]
[88 89 90 91 92 93 94 95 96 97 98]
]

"info" 方法为您提供有关一个的基本信息 iddle:

pdl> p $a-> 信息
PDL:双 D [11,9]

这告诉我们 $a 是一个 11 x 9 iddle 由双精度数组成。 要是我们
想要在“nxm”piddle 中的所有元素中添加 3,传统语言会使用两个
嵌套 for 循环:

# 伪代码。 将 3 添加到数组的传统方法。
对于 (x=0; x < n; x++) {
for (y=0; y < m; y++) {
a(x,y) = a(x,y) + 3
}
}

备注:请注意,索引从 0 开始,就像在 Perl、C 和 Java 中一样(与 MATLAB 和 IDL 不同)。

但是使用 PDL,我们可以只写:

pdl> $b = $a + 3
pdl> p $b
[
[3 4 5 6 7 8 9 10 11 12 13]
[14 15 16 17 18 19 20 21 22 23 24]
[25 26 27 28 29 30 31 32 33 34 35]
[36 37 38 39 40 41 42 43 44 45 46]
[47 48 49 50 51 52 53 54 55 56 57]
[58 59 60 61 62 63 64 65 66 67 68]
[69 70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89 90]
[91 92 93 94 95 96 97 98 99 100 101]
]

这是线程最简单的例子,它是所有数值软件
工具做。 “+ 3”操作沿两个维度自动应用。 现在假设
你想从 $a 的每一行中减去一行:

pdl> $line = 序列(11)
pdl> p $line
[0 1 2 3 4 5 6 7 8 9 10]
pdl> $c = $a - $line
pdl> p $c
[
[0 0 0 0 0 0 0 0 0 0 0]
[11 11 11 11 11 11 11 11 11 11 11]
[22 22 22 22 22 22 22 22 22 22 22]
[33 33 33 33 33 33 33 33 33 33 33]
[44 44 44 44 44 44 44 44 44 44 44]
[55 55 55 55 55 55 55 55 55 55 55]
[66 66 66 66 66 66 66 66 66 66 66]
[77 77 77 77 77 77 77 77 77 77 77]
[88 88 88 88 88 88 88 88 88 88 88]
]

这里要注意两点:首先,$a 的值仍然相同。 尝试“p $a”来检查。
其次,PDL 自动从 $a 中的每一行减去 $line。 为什么这样做? 让我们
查看$a、$line和$c的尺寸:

pdl> p $line->info => PDL:双 D [11]
pdl> p $a->info => PDL:双 D [11,9]
pdl> p $c->info => PDL:双 D [11,9]

因此,$a 和 $line 在第 0 维中具有相同数量的元素! 那么什么 PDL
did 是在 $a 中的更高维度上线程并重复相同的操作 9 次以
$a 上的所有行。 这是 PDL 线程在起作用。

如果你只想从 $a 的第一行减去 $line 怎么办? 你可以这样做
明确指定行:

pdl> $a(:,0) -= $line
pdl> p $a
[
[0 0 0 0 0 0 0 0 0 0 0]
[11 12 13 14 15 16 17 18 19 20 21]
[22 23 24 25 26 27 28 29 30 31 32]
[33 34 35 36 37 38 39 40 41 42 43]
[44 45 46 47 48 49 50 51 52 53 54]
[55 56 57 58 59 60 61 62 63 64 65]
[66 67 68 69 70 71 72 73 74 75 76]
[77 78 79 80 81 82 83 84 85 86 87]
[88 89 90 91 92 93 94 95 96 97 98]
]

请参阅 PDL::Indexing 和 PDL::NiceSlice 以了解有关从 piddles 指定子集的更多信息。

当您意识到 piddle 可以有任意数量的线程时,线程的真正力量就来了
方面! 让我们制作一个 4 维 piddle:

pdl> $piddle_4D = 序列(11,3,7,2)
pdl> $c = $piddle_4D - $line

现在 $c 是与 $piddle_4D 相同尺寸的 piddle。

pdl> p $piddle_4D->info => PDL:双 D [11,3,7,2]
pdl> p $c->info => PDL:双 D [11,3,7,2]

这次 PDL 已经自动穿过三个更高的维度,减去 $line
一路走来。

但是,也许您不想从行(维度 0)中减去,而是从列中减去
(维度 1)。 如何从 $a 中的每一列中减去一列数字?

pdl> $cols = 序列(9)
pdl> p $a->info => PDL:双 D [11,9]
pdl> p $cols->info => PDL:双 D [9]

当然,我们不能只输入“$a - $cols”。 尺寸不匹配:

pdl> p $a - $cols
PDL:PDL::Ops::minus(a,b,c):参数'b'
PDL:不匹配的隐式线程维度 0:应该是 11,是 9

我们如何告诉 PDL 我们想要从第 1 维中减去?

操纵 尺寸


有许多 PDL 函数可让您重新排列 PDL 数组的维度。 他们是
主要涵盖在 PDL::Slices 中。 最常见的三种是:

西格
mv
重新排序

方法: “xchg”
“xchg”方法“交流" 两个维度:

pdl> $a = 序列(6,7,8,9)
pdl> $a_xchg = $a->xchg(0,3)

pdl> p $a->info => PDL:双 D [6,7,8,9]
pdl> p $a_xchg->info => PDL:双 D [9,7,8,6]
| |
VV
(昏暗0) (昏暗3)

请注意,尺寸 0 和 3 已交换,而不会影响其他尺寸。
另请注意,“xchg”不会改变 $a。 原始变量 $a 保持不变。

方法: “MV”
“mv”方法“移动“一个维度,在一个小玩意中,将其他维度转换为
必要。

pdl> $a = 序列(6,7,8,9) (dim 0)
pdl> $a_mv = $a->mv(0,3) |
pdl> V _____
pdl> p $a->info => PDL:双 D [6,7,8,9]
pdl> p $a_mv->info => PDL:双 D [7,8,9,6]
-----|
V
(昏暗3)

请注意,当尺寸 0 移动到位置 3 时,所有其他尺寸都必须
也转移了。 另请注意,“mv”不会改变 $a。 原始变量 $a 保持不变
无动于衷。

方法: “重新排序”
“重新排序”方法是“xchg”和“mv”方法的概括。 它 ”重新订购"
您指定的任何方式的尺寸:

pdl> $a = 序列(6,7,8,9)
pdl> $a_reorder = $a->reorder(3,0,2,1)
pdl>
pdl> p $a->info => PDL:双 D [6,7,8,9]
pdl> p $a_reorder->info => PDL:双 D [9,6,8,7]
| | | |
VV 对 V
尺寸:0 1 2 3

注意发生了什么。 当我们编写“reorder(3,0,2,1)”时,我们指示 PDL:

* 将维度 3 放在首位。
* 接下来放维度 0。
* 接下来放维度 2。
* 接下来放维度 1。

当您使用“重新排序”方法时,所有维度都会被打乱。 注意“重新排序”
不会改变 $a。 原始变量 $a 保持不变。

陷阱: 链接 VS 分配


链接
默认情况下,piddles 是 链接 一起 以便对一个的更改将返回并影响
原版的 as .

pdl> $a = 序列(4,5)
pdl> $a_xchg = $a->xchg(1,0)

在这里,$a_xchg is 而不去 a 分开 对象. 这只是看待 $a 的不同方式。 任何
$a_xchg 的变化也会出现在 $a 中。

pdl> p $a
[
[0 1 2 3]
[4 5 6 7]
[8 9 10 11]
[12 13 14 15]
[16 17 18 19]
]
pdl> $a_xchg += 3
pdl> p $a
[
[3 4 5 6]
[7 8 9 10]
[11 12 13 14]
[15 16 17 18]
[19 20 21 22]
]

转让
有时,链接不是您想要的行为。 如果你想制作piddles
独立,使用“复制”方法:

pdl> $a = 序列(4,5)
pdl> $a_xchg = $a->copy->xchg(1,0)

现在 $a 和 $a_xchg 是完全独立的对象:

pdl> p $a
[
[0 1 2 3]
[4 5 6 7]
[8 9 10 11]
[12 13 14 15]
[16 17 18 19]
]
pdl> $a_xchg += 3
pdl> p $a
[
[0 1 2 3]
[4 5 6 7]
[8 9 10 11]
[12 13 14 15]
[16 17 18 19]
]
pdl> $a_xchg
[
[3 7 11 15 19]
[4 8 12 16 20]
[5 9 13 17 21]
[6 10 14 18 22]
]

投入 IT 全部 一起


现在我们准备解决引发整个讨论的问题:

pdl> $a = 序列(11,9)
pdl> $cols = 序列(9)
pdl>
pdl> p $a->info => PDL:双 D [11,9]
pdl> p $cols->info => PDL:双 D [9]

我们如何告诉 PDL 沿维度 1 而不是维度 0 减去 $cols? 这
最简单的方法是使用“xchg”方法并依赖 PDL 链接:

pdl> p $a
[
[0 1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20 21]
[22 23 24 25 26 27 28 29 30 31 32]
[33 34 35 36 37 38 39 40 41 42 43]
[44 45 46 47 48 49 50 51 52 53 54]
[55 56 57 58 59 60 61 62 63 64 65]
[66 67 68 69 70 71 72 73 74 75 76]
[77 78 79 80 81 82 83 84 85 86 87]
[88 89 90 91 92 93 94 95 96 97 98]
]
pdl> $a->xchg(1,0) -= $cols
pdl> p $a
[
[0 1 2 3 4 5 6 7 8 9 10]
[10 11 12 13 14 15 16 17 18 19 20]
[20 21 22 23 24 25 26 27 28 29 30]
[30 31 32 33 34 35 36 37 38 39 40]
[40 41 42 43 44 45 46 47 48 49 50]
[50 51 52 53 54 55 56 57 58 59 60]
[60 61 62 63 64 65 66 67 68 69 70]
[70 71 72 73 74 75 76 77 78 79 80]
[80 81 82 83 84 85 86 87 88 89 90]
]

一般策略:
将您要操作的维度移动到 piddle 维度的开头
列表。 然后让 PDL 线程在更高的维度上。

例: 康威 游戏 OF 生活


好吧,足够的理论。 让我们做一些更有趣的事情:我们会写 康威 游戏
of 生活 在 PDL 中,看看 PDL 有多强大!

这个 游戏 of 生活 是在大型二维网格上运行的模拟。 网格中的每个单元格
可以是活的也可以是死的(用 1 或 0 表示)。 下一代细胞
根据网格中活细胞的数量,用简单的规则计算网格
邻近地区:

1) 如果一个空单元格恰好有三个邻居,则生成一个活单元格。

2)如果一个活细胞的邻居少于两个,它就会死于过度喂养。

3) 如果一个活细胞有 4 个或更多的邻居,它就会饿死。

只有第一代单元格是由程序员决定的。 在那之后,
模拟完全按照这些规则运行。 计算下一代,你
需要查看2D字段中的每个单元格(需要两次循环),计算
与此单元格相邻的活单元格(需要另外两个循环),然后填充下一个
生成网格。

古典 履行
这是在 Perl 中编写此程序的经典方法。 我们只使用 PDL 进行寻址
单个细胞。

#!/usr/bin/perl -w
使用 PDL;
使用 PDL::NiceSlice;

# 为生命的游戏制作一个棋盘。
我的 $nx = 20;
我的 $ny = 20;

# 当前这一代。
我的 $a = zeroes($nx, $ny);

# 下一代。
我的 $n = zeroes($nx, $ny);

# 放入​​一个简单的滑翔机。
$a(1:3,1:3) .= pdl ( [1,1,1],
[0,0,1]
[0,1,0]);

for (我的 $i = 0; $i < 100; $i++) {
$n = 零($nx, $ny);
$new_a = $a->copy;
for ($x = 0; $x < $nx; $x++) {
for ($y = 0; $y < $ny; $y++) {

# 对于每个单元格,查看周围的邻居。
for ($dx = -1; $dx <= 1; $dx++) {
for ($dy = -1; $dy <= 1; $dy++) {
$px = $x + $dx;
$py = $y + $dy;

# 在边缘环绕。
如果 ($px < 0) {$px = $nx-1};
如果 ($py < 0) {$py = $ny-1};
如果 ($px >= $nx) {$px = 0};
如果 ($py >= $ny) {$py = 0};

$n($x,$y) .= $n($x,$y) + $a($px,$py);
}
}
# 不要计算中心单元本身。
$n($x,$y) -= $a($x,$y);

# 计算细胞是存活还是死亡:
# 如果 n = 3,死细胞还活着
# 如果 n 不是 2 或 3,活细胞就会死亡
如果 ($a($x,$y) == 1) {
如果 ($n($x,$y) < 2) {$new_a($x,$y) .= 0};
如果 ($n($x,$y) > 3) {$new_a($x,$y) .= 0};
} {
如果 ($n($x,$y) == 3) {$new_a($x,$y) .= 1}
}
}
}

打印 $a;

$a = $new_a;
}

如果你运行它,你会看到一个小滑翔机在零点网格上对角爬行。
在我的机器上,它每秒打印几代。

螺纹的 PDL 履行
这是 PDL 中的线程版本。 只有四行 PDL 代码,其中之一是
打印出最新一代!

#!/usr/bin/perl -w
使用 PDL;
使用 PDL::NiceSlice;

我的 $a = zeroes(20,20);

# 放入​​一个简单的滑翔机。
$a(1:3,1:3) .= pdl ( [1,1,1],
[0,0,1]
[0,1,0]);

我的 $n;
for (我的 $i = 0; $i < 100; $i++) {
# 计算每个单元格的邻居数。
$n = $a->range(ndcoords($a)-1,3,"periodic")->reorder(2,3,0,1);
$n = $n->sumover->sumover - $a;

# 计算下一代。
$a = ((($n == 2) + ($n == 3))* $a) + (($n==3) * !$a);

打印 $a;
}

线程 PDL 版本要快得多:

经典 => 32.79 秒。
线程 => 0.41 秒。

说明
线程版本如何工作?

有许多 PDL 函数旨在帮助您执行 PDL 线程。 在这
例如,关键功能是:

方法: “范围”

在最简单的层面上,“范围”方法是选择一部分的不同方式
拨弄。 我们不使用“$a(2,3)”符号,而是使用另一个 piddle。

pdl> $a = 序列(6,7)
pdl> p $a
[
[0 1 2 3 4 5]
[6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]
[36 37 38 39 40 41]
]
pdl> p $a->range( pdl [1,2] )
13
pdl> p $a(1,2)
[
[13]
]

此时,“范围”方法看起来与常规 PDL 切片非常相似。 但该
“范围”方法更通用。 例如,您可以一次选择多个组件:

pdl> $index = pdl [ [1,2],[2,3],[3,4],[4,5]]
pdl> p $a->range( $index )
[13 20 27 34]

此外,“range”采用第二个参数来确定块的大小
返回:

pdl> $size = 3
pdl> p $a->range( pdl([1,2]) , $size )
[
[13 14 15]
[19 20 21]
[25 26 27]
]

我们可以使用它来选择一个或多个 3x3 框。

最后,“范围”可以采用称为“边界”条件的第三个参数。 它告诉 PDL
如果您要求的尺寸框超出了小球的边缘,该怎么办。 我们不会去
在所有选项中。 我们只会说选项“定期”意味着 piddle
“环绕”。 例如:

pdl> p $a
[
[0 1 2 3 4 5]
[6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]
[36 37 38 39 40 41]
]
pdl> $size = 3
pdl> p $a->range( pdl([4,2]) , $size , "periodic" )
[
[16 17 12]
[22 23 18]
[28 29 24]
]
pdl> p $a->range( pdl([5,2]) , $size , "periodic" )
[
[17 12 13]
[23 18 19]
[29 24 25]
]

请注意盒子是如何环绕在 piddle 的边界上的。

方法: “nd坐标”

“ndcoords”方法是一个方便的方法,它返回一个枚举列表
适用于“范围”方法的坐标。

pdl> p $piddle = 序列(3,3)
[
[0 1 2]
[3 4 5]
[6 7 8]
]
pdl> p ndcoords($piddle)
[
[
[0 0]
[1 0]
[2 0]
]
[
[0 1]
[1 1]
[2 1]
]
[
[0 2]
[1 2]
[2 2]
]
]

这可能有点难以阅读。 基本上它是说每个坐标
$piddle 中的元素由下式给出:

(0,0)(1,0)(2,0)
(1,0)(1,1)(2,1)
(2,0)(2,1)(2,2)

技术与 “范围” “nd坐标”

真正重要的是“ndcoords”旨在与“range”一起工作,没有
$size 参数,你会得到同样的 piddle。

pdl> p $piddle
[
[0 1 2]
[3 4 5]
[6 7 8]
]
pdl> p $piddle->range( ndcoords($piddle) )
[
[0 1 2]
[3 4 5]
[6 7 8]
]

为什么这会有用? 因为现在我们可以为整个请求一系列“盒子”
拨弄。 例如,2x2 盒子:

pdl> p $piddle->range( ndcoords($piddle) , 2 , "周期性" )

此函数的输出难以阅读,因为最后两个的“框”
尺寸。 我们可以通过重新排列维度使结果更具可读性:

pdl> p $piddle->range( ndcoords($piddle) , 2 , "periodic" )->reorder(2,3,0,1)
[
[
[
[0 1]
[3 4]
]
[
[1 2]
[4 5]
]
...
]

在这里你可以更清楚地看到

[0 1]
[3 4]

是从$piddle 的(2) 元素开始的2x0,0 盒子吗?

我们还没有完成。 对于生命游戏,我们需要 $a 中的 3x3 盒子:

pdl> p $a
[
[0 1 2 3 4 5]
[6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]
[36 37 38 39 40 41]
]
pdl> p $a->range( ndcoords($a) , 3 , "periodic" )->reorder(2,3,0,1)
[
[
[
[0 1 2]
[6 7 8]
[12 13 14]
]
...
]

我们可以确认这是从 $a 的 (3) 元素开始的 3x0,0 盒子。 但是有
是一个问题。 我们实际上希望 3x3 盒子是 中心 在 (0,0) 上。 那不是一个
问题。 只需从“ndcoords($a)”中的所有坐标中减去 1。 请记住,
“定期”选项负责让一切都环绕。

pdl> p $a->range( ndcoords($a) - 1 , 3 , "periodic" )->reorder(2,3,0,1)
[
[
[
[41 36 37]
[5 0 1]
[11 6 7]
]
[
[36 37 38]
[0 1 2]
[6 7 8]
]
...

现在我们看到一个 3x3 的盒子,盒子的中心是 (0,0) 元素。

方法: “总结”

“sumover”方法仅沿第一维相加。 如果我们应用它两次,我们将
添加每个 3x3 盒子的所有元素。

pdl> $n = $a->range(ndcoords($a)-1,3,"periodic")->reorder(2,3,0,1)
pdl> p $n
[
[
[
[41 36 37]
[5 0 1]
[11 6 7]
]
[
[36 37 38]
[0 1 2]
[6 7 8]
]
...
pdl> p $n->sumover->sumover
[
[144 135 144 153 162 153]
[72 63 72 81 90 81]
[126 117 126 135 144 135]
[180 171 180 189 198 189]
[234 225 234 243 252 243]
[288 279 288 297 306 297]
[216 207 216 225 234 225]
]

用计算器确认144是第一个3x3框内所有元素的总和
135 是第二个 3x3 盒子中所有元素的总和。

计数 邻居

我们就快到了!

将 3x3 框中的所有元素相加不是 相当 我们想要什么。 我们不想数
中心框。 幸运的是,这是一个简单的修复:

pdl> p $n->sumover->sumover - $a
[
[144 134 142 150 158 148]
[66 56 64 72 80 70]
[114 104 112 120 128 118]
[162 152 160 168 176 166]
[210 200 208 216 224 214]
[258 248 256 264 272 262]
[180 170 178 186 194 184]
]

当应用于康威的生命游戏时,这将告诉我们每个邻居有多少个活着的邻居
单元格有:

pdl> $a = 零(10,10)
pdl> $a(1:3,1:3) .= pdl ( [1,1,1],
..( > [0,0,1],
..( > [0,1,0] )
pdl> p $a
[
[0 0 0 0 0 0 0 0 0 0
[0 1 1 1 0 0 0 0 0 0
[0 0 0 1 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 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
]
pdl> $n = $a->range(ndcoords($a)-1,3,"periodic")->reorder(2,3,0,1)
pdl> $n = $n->sumover->sumover - $a
pdl> p $n
[
[1 2 3 2 1 0 0 0 0 0
[1 1 3 2 2 0 0 0 0 0
[1 3 5 3 2 0 0 0 0 0
[0 1 1 2 1 0 0 0 0 0
[0 1 1 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 0 0
[0 0 0 0 0 0 0 0 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 个活着的邻居,而单元格 (2,2) 有 5 个
生活邻居。

计算 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 下页

此时,变量 $n 具有每个单元格的活邻居数。 现在我们
应用生命游戏规则来计算下一代。

如果一个空单元格恰好有三个相邻单元格,则生成一个活单元格。
获取恰好具有三个邻居的单元格列表:

pdl> p ($n == 3)
[
[0 0 1 0 0 0 0 0 0 0
[0 0 1 0 0 0 0 0 0 0
[0 1 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 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
]

获取列表 空的 恰好有三个邻居的单元格:

pdl> p ($n == 3) * !$a

如果一个活细胞的邻居少于 2 个或多于 3 个,它就会死亡。
获取恰好有 2 或 3 个邻居的单元格列表:

pdl> p (($n == 2) + ($n == 3))
[
[0 1 1 1 0 0 0 0 0 0
[0 0 1 1 1 0 0 0 0 0
[0 1 0 1 1 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 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
]

获取列表 活的 恰好有 2 或 3 个邻居的单元格:

pdl> p (($n == 2) + ($n == 3)) * $a

综上所述,下一代是:

pdl> $a = ((($n == 2) + ($n == 3)) * $a) + (($n == 3) * !$a)
pdl> p $a
[
[0 0 1 0 0 0 0 0 0 0
[0 0 1 1 0 0 0 0 0 0
[0 1 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 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
[0 0 0 0 0 0 0 0 0 0
]

奖金 功能: 图形!
如果您安装了 PDL::Graphics::TriD,您可以制作该程序的图形版本
只需更改三行:

#!/usr/bin/perl
使用 PDL;
使用 PDL::NiceSlice;
使用 PDL::Graphics::TriD;

我的 $a = zeroes(20,20);

# 放入​​一个简单的滑翔机。
$a(1:3,1:3) .= pdl ( [1,1,1],
[0,0,1]
[0,1,0]);

我的 $n;
for (我的 $i = 0; $i < 100; $i++) {
# 计算每个单元格的邻居数。
$n = $a->range(ndcoords($a)-1,3,"periodic")->reorder(2,3,0,1);
$n = $n->sumover->sumover - $a;

# 计算下一代。
$a = ((($n == 2) + ($n == 3))* $a) + (($n==3) * !$a);

# 展示。
nokeeptwiddling3d();
图像 [$a];
}

但是如果我们真的想看到一些有趣的东西,我们应该再做一些改变:

1) 从 1 和 0 的随机集合开始。

2)使网格更大。

3)添加一个小超时,以便我们可以看到游戏更好地发展。

4) 使用while 循环,以便程序可以根据需要运行。

#!/usr/bin/perl
使用 PDL;
使用 PDL::NiceSlice;
使用 PDL::Graphics::TriD;
使用 Time::HiRes qw(usleep);

我的 $a = 随机(100,100);
$a = ($a < 0.5);

我的 $n;
while(1){
# 计算每个单元格的邻居数。
$n = $a->range(ndcoords($a)-1,3,"periodic")->reorder(2,3,0,1);
$n = $n->sumover->sumover - $a;

# 计算下一代。
$a = ((($n == 2) + ($n == 3))* $a) + (($n==3) * !$a);

# 展示。
nokeeptwiddling3d();
图像 [$a];

# 休眠 0.1 秒。
使用睡眠(100000);
}

结论: 一般 策略


一般策略是: 移动 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 尺寸 操作 on 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 开始 of 您的
皮德的 尺寸 名单。 然后 PDL 超过 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 更高 尺寸。

线程是一个强大的工具,它有助于消除 for 循环并使你的代码更
简洁的。 希望本教程已经说明了为什么值得掌握线程
在 PDL 中。

版权


版权所有 2010 马修肯沃西 ([email protected]) 和丹尼尔·卡雷拉
([email protected])。 您可以在相同条款下分发和/或修改本文档
作为当前的 Perl 许可证。

请参见: http://dev.perl.org/licenses/

使用 onworks.net 服务在线使用 PDL::Threadingp


免费服务器和工作站

下载 Windows 和 Linux 应用程序

Linux 命令

Ad




×
广告
❤️在这里购物、预订或购买——免费,有助于保持服务免费。