跳至內容

守衛命令語言

維基百科,自由的百科全書

守衛命令語言GCL:Guarded Command Language)是艾茲赫爾·戴克斯特拉謂詞變換語義英語predicate transformer semantics定義的一門語言[1]。它以精簡方式組合了編程概念,它們處在以某種實際的程式語言書寫程序之前。它的簡單性使得採用霍爾邏輯證明程序的正確性更加容易。

守衛命令[編輯]

守衛(guarded)命令是守衛命令語言的最重要元素。在守衛命令中,同名字所說一樣,這個命令是被守衛着的。這個守衛是先決條件,在這個語言被執行英語execution (computers)之前,它必須為真。在這個語句執行開始時,可以假定這個守衛為真。還有,如果這個守衛為假,這個語句將不被執行。使用守衛命令使得證明程序滿足規定英語Formal specification更加容易。這個語句也經常是另一個守衛命令。

語法[編輯]

一個守衛命令是形如G → S的一個語句,這裏的

如果G為真,守衛命令可以簡單的寫為S。

語義[編輯]

當在計算中遇到G的時刻,求值它。

  • 如果G為真,執行S;
  • 如果G為假,查看上下文來決定做什麼(在任何情況下,都不執行S)。

躍過和中止[編輯]

在守衛命令語言中,躍過(skip)和中止(abort)是非常簡單也是非常重要的語句。中止是未定義指令:做任何事情。中止語句甚至不需要終止(terminate)。在公式化一個證明的時候,它被用來描述一個程序,在這種情況下證明通常失敗。躍過是空指令:什麼事情都不做。它被用在程序自身中,當語法要求一個語句的時候,而編程者卻不想要機器改變狀態英語state (computer science)

語法[編輯]

skip
abort

語義[編輯]

  • Skip: 什麼事情都不做
  • Abort: 做任何事情

賦值[編輯]

將值指派給變量

語法[編輯]

v := E

v0, v1, ..., vn := E0, E1, ..., En

這裏的

  • v是程序變量,
  • E是數據類型同於其對應變量的表達式。

串接[編輯]

語句由分號(;)來分割。

選擇:if[編輯]

選擇(經常叫做「條件語句」或「if語句」)是守衛命令的列表,從中選取一個來執行。如果多於一個守衛為真,非確定性的選取一個語句來執行。如果沒有守衛為真,結果是未定義的。因為至少一個守衛必須為真,空語句"skip"經常是需要的。

語法[編輯]

if G0 → S0
|  G1 → S1
...
|  Gn → Sn
fi

語義[編輯]

在執行一個選擇的時候求值所有的守衛。如果沒有守衛被求值為真,則選擇的執行會abort,否則非確定性的選擇其值為真的守衛之一,並執行對應的語句[2]

例子[編輯]

簡單[編輯]

偽代碼

if a < b then c := True
else c := False

用守衛命令語言:

if a < b → c := true
|  a ≥ b → c := false
fi

使用skip[編輯]

用偽代碼:

if error = True then x := 0

用守衛命令語言:

if error = true → x := 0
|  error = false → skip
fi

如果第二個守衛被省略,並且error = False,結果是abort。

多個守衛為真[編輯]

if a ≥ b → max := a
|  b ≥ a → max := b
fi

如果a = b,要麼a要麼b被選取為極大值的新值,具有相同的結果。但是,在實現這個例子的時候,可能會發現一個比另一個更容易或更快。因為對於編程者這裏沒有區別,可以隨意實現任何一種方式。

重複:do[編輯]

重複會反覆的執行守衛命令知道沒有守衛為真。通常,這裏只有一個守衛。

語法[編輯]

do G0 → S0
|  G1 → S1
...
|  Gn → Sn
od

語義[編輯]

當執行重複的時候所有守衛都求值。如果所有守衛都求值為假,則執行skip。否則非確定性的選取其值為真的守衛之一,並執行對應的語句,此後再次執行重複。

例子[編輯]

歐幾里德算法[編輯]

a, b := A, B;
do a < b → b := b - a
|  b < a → a := a - b
od

這個重複在a = b時候結束,在這種情況下a和b持有A和B的最大公約數。

戴克斯特拉在這個算法中見到了兩個無限循環a := a - bb := b - a同步的一種方式,在這種方式下a≥0b≥0保持為真。

擴展歐幾里德算法[編輯]

a, b, x, y, u, v := A, B, 1, 0, 0, 1;
do b ≠ 0 →
|  q, r := a div b, a mod b;
|  a, b, x, y, u, v := b, r, u, v, x - q*u, y - q*v
od

這個重複在b = 0的時候結束,在這種情況下變量持有對貝祖等式:xA + yB = gcd(A,B)的解。

非確定性排序[編輯]

do a>b → a, b := b, a
|  b>c → b, c := c, b
|  c>d → c, d := d, c
od

這個程序在其中一個元素大於它的後續者的時候持續的置換元素。這個非確定性冒泡排序不比它的確定性版本更加有效率, 但是易於證明:只要元素仍未有序它就不會停止並且它每步至少排序2個元素。

Arg max[編輯]

x, y = 1, 1 
do x≠n →
|  if f(x) ≤ f(y) → x := x+1
|  |  f(x) ≥ f(y) → y := x; x := x+1
|  fi
od

這個算法找到值1 ≤ yn,對於它給定整數函數是最大的。不只是這個計算而且最終狀態都不是必然唯一確定的。

應用[編輯]

構造正確程序[編輯]

將觀察的守衛命令的同餘關係推廣成導致了精製演算英語Refinement Calculus[3]。這已經機制化於形式化方法B方法英語B-Method中,它允許從它們的規定形式化的導出程序。

異步電路[編輯]

守衛命令適合於准延遲不敏感電路英語quasi-delay-insensitive circuit設計,因為重複允許不同命令選擇的任意相對延遲。在這種應用之,在電路中驅動一個節點y的邏輯門構成自兩個守衛命令如下:

PullDownGuard → y := 0
PullUpGuard → y := 1

這裏的PullDownGuard和PullUpGuard是邏輯門輸入的函數,它描述了什麼時候這個邏輯門分別將輸出拉下或拉上。不同於經典的電路評估模型,一組守衛命令的重複(對應於一個異步電路)可以準確的描述這個電路的所有可能的動態行為。[4]

模型檢查[編輯]

守衛命令可以用在Promela英語Promela程式語言中,它被用於SPIN模型檢查器英語SPIN model checker。SPIN驗證並發軟件應用的正確操作。

其他[編輯]

Perl模塊Commands::Guarded實現了戴克斯特拉的守衛命令的一個確定性的校正變體。

引用[編輯]

  1. ^ Dijkstra, Edsger W. EWD472: Guarded commands, non-determinacy and formal. derivation of programs. (PDF). [August 16, 2006]. (原始內容存檔 (PDF)於2021-01-18). 
  2. ^ Anne Kaldewaij, Programming: The Derivation of Algorithms, Prentice Hall, 1990 
  3. ^ Back, Ralph J. On the Correctness of Refinement Steps in Program Development (Phd-Thesis) (PDF). 1978 [2021-02-17]. (原始內容 (pdf)存檔於2011-07-20). 
  4. ^ Martin, Alain J. Synthesis of Asynchronous VLSI Circuits. 

參見[編輯]