遞迴函式(四) 全函式與計算的可終止性

2021-09-23 17:58:13 字數 4231 閱讀 7774

遞迴函式(一):開篇

遞迴函式(二):編寫遞迴函式的思路和技巧

遞迴函式(三):歸納原理

遞迴函式(四):全函式與計算的可終止性

遞迴函式(五):遞迴集與遞迴可列舉集

遞迴函式(六):最多有多少個程式

遞迴函式(七):不動點運算元

遞迴函式(八):偏序結構

遞迴函式(九):最小不動點定理

上文我們討論了集合上的關係,還討論了數學歸納法的一種普遍形式,稱為良基歸納法,

它建立在集合上的良基關係之上。

本文開始討論函式,我們將回顧函式的定義,

然後解釋什麼是全函式(total function),什麼是部分函式(partial function)。

我們會看到,在證明乙個遞迴函式是全函式時,

良基歸納法起到了重要作用。

在分析學中,人們似乎很少關心函式的完全性,

只關心它的連續性,可導性,可微性與可積性,等等。

而在電腦科學領域中,人們更在意計算的可終止性,

因此乙個函式在某個點是否有定義將經常被提及。

程式中定義的函式,往往對應於某個集合上的數學函式,

為了描述程式的非終止性,就得擴充這個數學函式的定義域和值域。

為了理解這些事情,我們先要從函式的定義開始。

集合\(a,b\)上的關係,是笛卡爾積\(atimes b\)的乙個子集。

而函式\(f:arightarrow b\),則是集合\(a,b\)上的一種特殊關係,

它要求\(a\)中的每乙個元素,都有\(b\)中唯一確定的元素與之對應。

其中,集合\(a\)稱為函式\(f\)的定義域,集合\(b\)稱為函式的值域。

函式是我們熟悉的概念,這裡只是提到了它本質上是集合上的乙個關係。

(1)部分函式(partial function)

如果\(f\)是從\(a\)到\(b\)的二元關係,且\(forall ain a\),\(f(a)=varnothing \)或\(lbrace brbrace \),

則稱\(f\)是從\(a\)到\(b\)的部分函式,或\(a\)上的部分函式。

其中,如果\(f(a)=lbrace brbrace\),則稱\(f(a)\)有定義,記為\(f(a)downarrow \),

也稱\(b\)為\(f\)在\(a\)點的函式值,記為\(f(a)=b\)。

如果\(f(a)=varnothing \),則稱\(f(a)\)無定義,記為\(f(a)uparrow \)。

(2)全函式(total function)

如果\(forall ain a\)都有\(f(a)downarrow \),則稱\(f\)是\(a\)上的全函式,

此時,可以記為\(f:arightarrow b\)。

可見,我們熟悉的函式,指是全函式。

值得注意的是,部分函式的定義已經包含了我們學過的「函式」的定義,

後文中,我們提到的「函式」如果不強調它的完全性的話,都泛指部分函式。

部分函式在電腦科學中是非常重要的,

因為對於每乙個\(ain a\),乙個演算法可以表示為,計算出集合\(b\)中與之對應元素的過程,

這個演算法可能對於某些值\(ain a\)不會終止,而這種情況是很常見的。

例如:

f :: int -> int

f 1 = 1

f n = n + f(n-2)

這樣定義的函式f,對應了數學上的乙個部分函式\(f\),它只在某些情況下有意義,

只有當n是奇數時,我們才能得到終止性的結果。

而當n是偶數時,演算法會無限的遞迴下去,直到堆疊溢位。

因此,將int解釋為整數集\(n\),將f :: int -> int解釋為整數集上的函式,似乎是有問題的。

因為,\(f(2)\)並不是乙個整數,它的計算不能終止。

為了描述非終止性,就需要對整數集進行擴充,

我們給整數集加上乙個特殊元素「\(perp \)」,稱為bottom,來表示非終止性,

而將f :: int -> int解釋為集合\(ncup lbrace perp rbrace \)上乙個的數學函式。

像這種通過構造表達程式含義的數學物件,來對程式進行分析的方法,來自指稱語義學。

指稱語義中,人們會區分函式的嚴格性,乙個函式稱為嚴格的(strict),

如果接受乙個非終止的輸入表示式,函式的計算仍然不會終止,

即,\(f(perp )=perp \)。

否則,稱函式為不嚴格的(non-strict)。

我們看到在程式中使用遞迴,可能會導致非終止性的計算,而有些遞迴又不會。

這是為什麼呢?

我們可以從遞迴函式論中找到一些線索。

遞迴函式論是和圖靈機以及\(lambda \)演算相等價的計算模型,它從另乙個角度刻畫了可計算性。

可計算性是乙個有趣的話題,後續文章中,我們會詳細討論。

在遞迴函式論中,人們把函式劃分為了3個層次,

原始遞迴函式,遞迴函式,和其他的不能用遞迴函式表示的「函式」。

這些函式集合的範圍越來越大。

本文我們先介紹原始遞迴函式,

為此,我們需要先定義兩種運算。

(1)合成運算

設\(f\)是\(k\)元部分函式,\(g_1,g_2,cdots ,g_k\)是\(k\)個\(n\)元部分函式,令,

\(h(x_1,cdots ,x_n)=f(g_1(x_1,cdots ,x_n),cdots ,g_k(x_1,cdots ,x_n))\)

則稱\(h\)是由\(f\)和\(g_1,g_2,cdots ,g_k\),經過合成運算得到的。

(2)原始遞迴運算

設\(f\)是乙個\(n\)元全函式,\(g\)是\(n+2\)元全函式,令,

\(h(x_1,cdots ,x_n,0)=f(x_1,cdots ,x_n)\)

\(h(x_1,cdots ,x_n,t+1)=g(t,h(x_1,cdots ,x_n,t),x_1,cdots ,x_n)\)

則稱\(h\)是由\(f\)和\(g\)經過原始遞迴運算得到的。

於是,我們就可以定義原始遞迴函式了。

設初始函式包括,

(1)零函式\(n(x)=0\)

(2)後繼函式\(s(x)=x+1\)

(3)投影函式\(u^n_i(x_1,cdots ,x_n)=x_i\),\(ileqslant ileqslant n\)

則由初始函式經過有限次合成運算和原始遞迴運算得到的函式,稱為原始遞迴函式。

原始遞迴函式有以下這些性質:

由原始遞迴函式經過合成或原始遞迴得到的函式仍為原始遞迴函式,

因此,原始遞迴函式的集合在合成與原始遞迴運算下是封閉的。

此外,每乙個原始遞迴函式都是全函式。

這是因為合成運算雖然是在部分函式上定義的,

但是如果\(f\)和\(g_1,g_2,cdots ,g_k\)是全函式,那麼\(h\)也一定是全函式。

另一方面,在進行原始遞迴運算時,如果\(f\)和\(g\)是全函式,則\(h\)也一定是全函式,

這是因為原始遞迴運算在\(h\)的引數集上的定義了乙個良基關係,由良基歸納法可證,\(h\)是全函式。

本文介紹了全函式與部分函式,以及計算可終止性相關的概念,

我們對程式中函式的指稱,進行了定義域和值域的擴充,

隨後,我們進一步了解了原始遞迴函式,以及它的完全性,良基歸納法起到了關鍵作用。

下文,我們將深入到可計算性理論,

討論部分可計算函式和可計算函式的區別,討論遞迴函式與原始遞迴函式的關係,

引出遞迴可列舉集這個重要的概念。

function (mathematics))

strict function

可計算性與計算複雜性導引

數的計算 遞迴與函式自呼叫演算法

題目描述description 我們要求找出具有下列性質數的個數 包含輸入的自然數n 先輸入乙個自然數n n 1000 然後對此自然數按照如下方法進行處理 1.不作任何處理 2.在它的左邊加上乙個自然數,但該自然數不能超過原數的一半 3.加上數後,繼續按此規則進行處理,直到不能再加自然數為止.輸入輸...

可重入函式與不可重入函式的區別

自 可重入函式可以做這樣的基本定義 重入意味著這個函式可以重複進入,可以被並行呼叫,可以被中斷,它只使用自身棧上的資料變數,它不依賴於任務環境,在多任務排程過程中,它是安全的,不必擔心資料出錯。不可重入函式基本上與可重入函式有相反的定義了 不可重入,意味著不可被並行排程,否則會產生不可預料的結果,這...

python中的匿名函式與遞迴函式

匿名函式 無需使用def來命名的函式 用到關鍵字lambda 求最大值的匿名函式 max num lambda num1 num2 num1 if num1 num2 else num2 求和sum num lambda num1 num2 num1 num2 多項和 遞迴函式 自己呼叫自己的函式,...