圖靈機的簡單例子

最近剛考完可計算理論,考前看習題總有一些題讓設計一個圖靈機來實現某個算法什麼的(≖-≖)(雖然考試題裏完全沒有考到!然而我還是勤勤懇懇地想了很久)當時看圖靈機定義看了無數遍,但依然不是很明白怎麼設計啊摔(手動翻桌…)後來在衆多友人的幫助下終於想通了!(〃'▽'〃)接下來讓本小白用最白的話舉幾個小例子幫助更好地理解圖靈機:

首先簡單講一下圖靈機的構成成分(這個定義並不官方,就本小白瞎定義的,不過基本包括了下面例子裏會提到的所有概念):M=(Q,A,B,R,t,f,Q0,Qaccept,Qreject) 其中:

Q:有限的狀態集合;

A:有限的輸入字母表(不包含空白符B);

R:代表無限長度的紙帶,紙帶上可能出現A裏的任意字母,也可能是空白符B(可以把紙帶看做是一個磁盤);

t:代表圖靈機的讀寫頭,可以在紙帶上左右移動並進行讀寫操作;

f:轉移函數(f:Q × A -> Q × A × {L,R} 轉移函數實際上是定義在圖靈機的有限控制機裏的一張狀態轉換圖的表,我理解的是,在根據當前控制機的狀態q以及讀寫頭t讀取的當前輸入a,在表裏找到其對應的新的狀態q',在當前紙帶的格子上寫入的a',以及讀寫頭下一步應該往哪邊移動{Left,Right});

Q0:Q0∈Q,圖靈機的初始狀態(讀寫頭t的初始位置一般都是紙帶的第一格);

Qaccept:接受狀態(有限的狀態集合); 
Qreject:拒絕狀態,且Qreject≠Qaccept.

1. 設計一個能識別aaabbb類似字符串的圖靈機:輸入類似ab,aabb,aaabbb,aaa……bbb……(a,b的數量相等)的字符串則接受該輸入,否則拒絕。

在這個問題裏面A = {a,b,*} (PS.*代表其他可能的字符)

首先看一下在我的想象中這大概是個啥情況(B是空白字符啊切記):


這時候最重要的就是定義轉移函數,定義轉移函數就相當於設計算法(對於一個可計算的問題,我們可以設計很多個圖靈機,每個圖靈機就對應着不同的算法)。

例如我們的解題思路是:

從字符串aa……bb的左右兩邊依次交替消除a和b(即用空白符B代替當前字符),如果紙帶上的a,b恰好能消除完,那證明a,b的數量相等,否則a,b的數量不相等。那這個算法在圖靈機上如何實現呢?

狀態圖可以幫我們很好地理解圖靈機的運作過程:

(PS:【讀/寫,移動】,例如【a/B,R】表示讀寫頭t讀到當前格子上的字符爲a,讀寫頭t把當前格子上的字符改寫成空白B,讀寫頭t向右移動一格)

Q0:初始狀態,讀寫頭在紙帶的左端第一格(無限長的紙帶只有左端,沒有右端),若當前字符爲空白B,則寫B(即不修改當前字符),然後t向右移動,這個時候狀態是不變的,控制機停留在Q0狀態。

當t讀到第一個a的時候,t將a改寫成B(即消除字符串的左邊第一個a),t向右移動,控制機切換到Q1狀態。那如果沒有讀到a卻讀到一個b呢?這代表該字符串b多於a,不滿足要求,於是輸出拒絕

下一步我們要到達字符串的最右端,找到最右端的b並消除它。

Q1:在Q1狀態時,t繼續讀取字符,讀a寫a右移,讀b寫b右移,直到讀到一個空白B,這代表我們讀到了字符串的末尾!這時最右端的b就應該在當前t的左邊一格,所以這時要讀B寫B左移找到最右端的b,控制機切換到Q2。

Q2:讀寫頭t現在處在字符串最右端一格,如果當前字符爲a則代表a的數量多於b,輸出拒絕,如果爲b則消除b改寫爲B,讀寫頭t左移,控制機切換到Q3。這樣就完成了一次(a,b)的消除。接下來我們要做的就是回到字符串的最左端,開始新一輪的消除。

Q3:現在t需要往左走,如果往左讀到第一個字符是a代表已經沒有b了,因此a,b的數量是不對等的,輸出拒絕如果讀到字符爲空白B,則代表沒有a也沒有b,那麼aa……bb恰好被消除完,那麼這個字符是滿足要求的,輸出接受。如果讀到b,則讀b寫b左移,狀態切換到Q4。

Q4:讀b寫b左移,讀a寫a左移。讀到空白符B則代表到了字符串最左邊,讀B寫B右移找到字符串的第一個字符,此時控制機又回到了狀態Q0。

根據狀態圖我們可以寫出一張狀態轉換表,這就相當於是在控制機內的轉移函數了。

當前狀態讀B讀a讀b
Q0(寫B,右移,Q0)(寫B,右移,Q1)(寫b,右移,Qreject)
Q1(寫B,左移,Q2)(寫a,右移,Q1)(寫b,右移,Q1)
Q2(寫B,左移,Qreject)(寫a,左移Qreject)(寫B,左移,Q3)
Q3(寫B,左移,Qaccept)(寫a,左移,Qreject)(寫b,左移,Q4)
Q4(寫B,右移,Q0)(寫a,左移,Q4)(寫b,左移,Q4)

2.計算3+5。

在初始圖靈機的定義裏是沒有內存的,也就是我讀了第N格上的數字,當我移到N+1的時候,我已經忘記了N上寫的是什麼了,那我們怎麼設計一個圖靈機來定義一個用任何編程語言都能輕易寫出來的加法運算呢?

在當前問題中A = {0,1,2,3……}

假設輸入紙帶是長這樣:

BBB35BBBBBBBB

B

B

BBBBB

思想其實也很簡單,移動t找到第一個數字3, 寫入3-1,右移到第二個數字5,寫入5+1,然後再左移到第一個數字,遞減1,直到第一個數字爲0,則第二個數字所寫的數字即爲兩者之和。

3.輸入abbacc,輸出abbaccccabba(即將輸入字符串翻轉並與原字符串相連)。

在這個問題裏A = {a,b,c,*}

基本思想:引入其他字符分別代表原字符串的字符用來標記已讀和還原!

假設輸入紙帶是長這樣:

BabbaccBBBBBB

B

B

BBBBB

既然是要翻轉,那最好是從字符串的右端開始,首先讀寫頭先移到最右的c處,將c改寫成X,然後t右移到最近的一個空白格,寫下c。此處的狀態轉換爲:

(Qi:讀c,寫X,右移,Qj)->(Qj:讀B,寫c,左移,Qk)

BabbacXcBBBBB

B

B

BBBBB

然後t左移,移到最近的屬於A的字符,如上圖即爲c,讀c寫X右移,找到空白格B寫c。

BabbaXXccBBBB

B

B

BBBBB

接下來安同樣的套路,讀a寫Y右移,讀B寫a左移。直到字符串變成:

BYZZYXXccabba

B

B

BBBBB
這樣右邊我們已經製造出了原字符串的翻轉字符串,接下來就是還原原字符串,這個部分就很簡單了。讀寫頭往左移,直到讀到B也沒有其他屬於A的字符出現則代表原字符串已經翻轉完了,現在我們向右移,讀X寫c右移,讀Y寫a右移,讀Z寫b右移,直到再次讀到屬於A的字符。

通過上面的幾個小例子應該可以理解一個簡單粗暴的圖靈機是怎麼工作的了吧~~雖然很粗糙,但是設計的過程還是挺有意思的ヾ(◍°∇°◍)ノ゙

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章