官术网_书友最值得收藏!

2.3 計(jì)算整個(gè)朱利亞集合

本節(jié)詳細(xì)介紹生成朱利亞集合的代碼。本章后面將以各種方式對(duì)這些代碼進(jìn)行分析。如示例2-1所示,在模塊開(kāi)頭,我們?yōu)橹С值谝环N剖析方法導(dǎo)入了模塊time,還定義了一些坐標(biāo)常量。

示例2-1 定義表示坐標(biāo)空間的全局常量

"""Julia set generator without optional PIL-based image drawing"""
import time
 
# area of complex space to investigate
x1, x2, y1, y2 = -1.8, 1.8, -1.8, 1.8
c_real, c_imag = -0.62772, -.42193

為生成圖形,需要?jiǎng)?chuàng)建兩個(gè)包含輸入數(shù)據(jù)的列表。第一個(gè)列表為zs(復(fù)平面坐標(biāo)z),第二個(gè)列表為cs(表示初始條件的復(fù)數(shù))。這兩個(gè)列表都是不變的,且對(duì)于列表cs,可將其優(yōu)化為單個(gè)常量值c。這里創(chuàng)建兩個(gè)輸入列表,旨在提供一些看起來(lái)合理的數(shù)據(jù),以便本章后面能夠剖析RAM占用情況。

要想創(chuàng)建列表zs和cs,需要知道每個(gè)z的坐標(biāo)。在示例2-2中,使用了xcoord和ycoord以及步長(zhǎng)x_step和y_step來(lái)生成這些坐標(biāo)。這里所做的設(shè)置工作有點(diǎn)煩瑣,但有助于將代碼移植到其他工具(如numpy)和其他Python環(huán)境中,因?yàn)槊鞔_地定義了方方面面,這有助于調(diào)試。

示例2-2 創(chuàng)建用作計(jì)算函數(shù)輸入的坐標(biāo)列表

def calc_pure_python(desired_width, max_iterations):
"""Create a list of complex coordinates (zs) and complex parameters (cs),
build Julia set"""
    x_step = (x2 - x1) / desired_width
    y_step = (y1 - y2) / desired_width
    x = []
    y = []
    ycoord = y2
while ycoord > y1:
        y.append(ycoord)
        ycoord += y_step
    xcoord = x1
while xcoord < x2:
        x.append(xcoord)
        xcoord += x_step
# build a list of coordinates and the initial condition for each cell.
# Note that our initial condition is a constant and could easily be removed,
# we use it to simulate a real-world scenario with several inputs to our
# function
    zs = []
    cs = []
for ycoord in y:
for xcoord in x:
            zs.append(complex(xcoord, ycoord))
            cs.append(complex(c_real, c_imag))
print("Length of x:", len(x))
print("Total elements:", len(zs))
    start_time = time.time()
    output = calculate_z_serial_purepython(max_iterations, zs, cs)
    end_time = time.time()
    secs = end_time - start_time
print(calculate_z_serial_purepython._ _name_ _ + " took", secs, "seconds")
 
# This sum is expected for a 1000^2 grid with 300 iterations
# It ensures that our code evolves exactly as we'd intended
assert sum(output) == 33219980

創(chuàng)建列表zs和cs后,我們輸出一些關(guān)于列表長(zhǎng)度的信息,并調(diào)用函數(shù)calculate_z_serial_purepython生成列表output。最后,我們對(duì)列表output中的值求和,并使用assert確認(rèn)結(jié)果與預(yù)期的輸出值相同。這里這樣做旨在確認(rèn)書(shū)中沒(méi)有出現(xiàn)錯(cuò)誤。

由于上述代碼是完整且正確的,因此可以對(duì)計(jì)算得到的值求和來(lái)驗(yàn)證函數(shù)是否按預(yù)期工作。這種完整性檢查很有用——當(dāng)我們修改代碼時(shí),檢查我們沒(méi)有破壞算法是明智的。理想情況下,應(yīng)使用單元測(cè)試進(jìn)行檢查,還應(yīng)檢查多個(gè)方面。

接下來(lái),我們定義函數(shù)calculate_z_serial_purepython,它擴(kuò)展了本章前面討論的算法,如示例2-3所示。注意,這個(gè)函數(shù)開(kāi)頭定義了列表output,其長(zhǎng)度與輸入列表zs和cs相同。

示例2-3 CPU密集型計(jì)算函數(shù)

def calculate_z_serial_purepython(maxiter, zs, cs):
"""Calculate output list using Julia update rule"""
    output = [0] * len(zs)
for i in range(len(zs)):
        n = 0
        z = zs[i]
        c = cs[i]
while abs(z) < 2 and n < maxiter:
            z = z * z + c
            n += 1
        output[i] = n
return output

現(xiàn)在可以調(diào)用calc_pure_python了,如示例2-4所示。將調(diào)用該函數(shù)的語(yǔ)句放在一條執(zhí)行_ _main_ _檢查的if語(yǔ)句中,這樣可在嘗試剖析方法時(shí)安全地導(dǎo)入這個(gè)模塊,而不啟動(dòng)計(jì)算。請(qǐng)注意,這里沒(méi)有列出繪制輸出的方法。

示例2-4 主函數(shù)

if _ _name_ _ == "_ _main_ _":
# Calculate the Julia set using a pure Python solution with
# reasonable defaults for a laptop
    calc_pure_python(desired_width=1000, max_iterations=300)

如果此時(shí)運(yùn)行這些代碼,我們將看到有關(guān)問(wèn)題復(fù)雜性的輸出:

    # running the above produces:
    Length of x: 1000
    Total elements: 1000000
    calculate_z_serial_purepython took 8.087012767791748 seconds

在圖2-1所示的偽灰度圖中,顏色對(duì)比度較高,這讓我們知道在各個(gè)地方函數(shù)開(kāi)銷的變化速度是快還是慢。圖2-3顯示的是線性顏色映射圖,其中的黑色表示計(jì)算時(shí)間短,而白色表示計(jì)算時(shí)間長(zhǎng)。

圖2-3 純灰度的朱利亞集合圖

通過(guò)呈現(xiàn)數(shù)據(jù)的兩種表示方式,我們可以看到線性顏色映射會(huì)丟失大量的細(xì)節(jié)。在有些情況下,使用不同的表示方式對(duì)研究函數(shù)開(kāi)銷很有幫助。

主站蜘蛛池模板: 灵丘县| 卢氏县| 庆阳市| 嘉义市| 德州市| 嘉黎县| 柏乡县| 嵊泗县| 衡阳市| 广安市| 灵山县| 兖州市| 高唐县| 白山市| 黄浦区| 调兵山市| 五河县| 英吉沙县| 高州市| 凤阳县| 二连浩特市| 黑河市| 运城市| 佛山市| 喀什市| 亳州市| 巴林左旗| 合江县| 黄龙县| 丰镇市| 高州市| 正宁县| 桐乡市| 文昌市| 新闻| 福建省| 高台县| 永安市| 井冈山市| 灵山县| 北流市|