我正在了解计算(和绘制(Julia集的矢量化方法。在网上,我发现了以下代码(注释主要是我的,基于我对代码背后思想的不断理解(:
import numpy as np
import matplotlib.pyplot as plt
c = -0.74543+0.11301j # Example value for this picture (Julia set)
n = 512 # Maximum number of iterations
x = np.linspace(-1.5, 1.5, 2000).reshape((1, 2000)) # 1 row, 2000 columns
y = np.linspace(-1.2, 1.2, 1600).reshape((1600, 1)) # 1600 rows, 1 column
z = x + 1j*y # z is an array with 1600 * 2000 complex entries
c = np.full(z.shape, c) # c is a complex number matrix to be added for the iteration
diverge = np.zeros(z.shape) # 1600 * 2000 zeroes (0s), contains divergent iteration counts
m = np.full(z.shape, True) # 1600 * 2000 True, used as a kind of mask (convergent values)
for i in range(0,n): # Do at most n iterations
z[m] = z[m]**2 + c[m] # Matrix op: Complex iteration for fixed c (Julia set perspective)
m[np.abs(z) > 2] = False # threshold for convergence of absolute(z) is 2
diverge[m] = i
plt.imshow(diverge, cmap='magma') # Color map "magma" applied to the iterations for each point
plt.show() # Display image plotted
我不懂这条线的原理diverge[m] = i
我推测m是布尔值的1600*2000元素数组。似乎m被用作一种掩码,使其仅代表divide[]中的那些值,其中m中的相应元素为True。然而,我想更详细地理解这个概念。语法CCD_ 2似乎暗示数组被用作某种广义的";索引";到另一个数组(divert(,我可以帮助理解这个概念。(代码按预期运行,我只是在理解它的工作时遇到了问题。(
谢谢。
是的,您可以使用一个数组来索引另一个数组。在许多方面。这是一个复杂的问题。即使我现在很得意地理解了numpy,我有时还是会遇到数组索引,这让我在理解之前有点挠头。
但这种情况并不是一个非常复杂的
M=np.array([[1,2,3],
[4,5,6],
[7,8,9]])
msk=np.array([[True, False, True],
[True, True, True],
[False, True, False]])
M[msk]
返回array([1, 3, 4, 5, 6, 8])
。我相信,你可以很容易地理解其中的逻辑。
但更重要的是,指数化是一个l值。这意味着M[msk]
可以在=
的左侧。然后M的值受到的影响
因此,这意味着
M[msk]=0
M
显示
array([[0, 2, 0],
[0, 0, 0],
[7, 0, 9]])
同样,
M=np.array([[1,2,3],
[4,5,6],
[7,8,9]])
A=np.array([[2,2,4],
[4,6,6],
[8,8,8]])
msk=np.array([[True, False, True],
[True, True, True],
[False, True, False]])
M[msk] = M[msk]+A[msk]
M
结果是
array([[ 3, 2, 7],
[ 8, 11, 12],
[ 7, 16, 9]])
回到你的案子,
z[m] = z[m]**2 + c[m] # Matrix op: Complex iteration for fixed c (Julia set perspective)
在某种程度上只是一种优化。您也可以只使用z=z**2+c
。但是,为什么即使在已经发生溢出的情况下也要计算呢。因此,它只在还没有溢出的地方计算z=z**2+c
m[np.abs(z) > 2] = False # threshold for convergence of absolute(z) is 2
np.abs(s)>2
是真/假值的2d数组。m被设置为False;像素";其中CCD_ 9。m的其他值保持不变。因此,如果他们已经是假的,他们就会保持虚假。请注意,这个有点过于复杂。由于前一行的原因,z在变为>2
后不会改变,因此实际上,没有np.abs(z)<=2
和m
已经为False的像素。所以
m=np.abs(z)<=2
也会起作用。而且它不会更慢,因为最初的版本无论如何都是这样计算的。事实上,它会更快,因为我们省去了指数化/影响操作。在我的电脑上,我的版本比原来的运行速度快1.3秒(计算时间为12秒。大约10%(但原始版本的优点是使下一行更容易理解,因为它明确了一点:m从所有True值开始,然后只要算法运行,一些值就会变为False,但没有一个值再变为True。
diverge[m] = i
m是尚未发散的像素的掩码(它从所有True开始,只要我们迭代,m的值就会越来越多(。因此,在任何地方更新divert到i都没有发生divert(变量的名称不是最相关的(。
因此,z值变为>2,因此其m值在迭代50变为False,将被更新为1,然后是2,然后是3,然后是4。。。,然后是48,然后是49。但不到50,51。。。
所以在最后;"发散";是最后一个我,我仍然是真的。这是算法仍在收敛的最后一个i。或者,在1个单位移位时,算法发散的第一个单位移位。