의미론과 재귀 (2)

2022년 9월 16일

while  B  C\mathtt{while} \; B \; C의 표시적 의미론denotational semantics 적 관계는 다음과 같았다:

while  B  C(m)={while  B  C(C(m))if  B(m)=truemif  B(m)=false \llbracket \mathtt{while} \; B \; C \rrbracket (m) = \begin{cases} \llbracket \mathtt{while} \; B \; C \rrbracket (\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases}

하지만, 이 관계를 통해 while  B  C\mathtt{while} \; B \; C의 의미를 제대로 나타내지 못한다는 결론을 얻었다. 유한한 반복 안에 이 의미가 끝난다는 보장이 없기 때문이다.

여기서 while  B  C\llbracket \mathtt{while} \; B \; C \rrbracketXX로 바꿔서 적어보자.

X(m)={X(C(m))if  B(m)=truemif  B(m)=false X(m) = \begin{cases} X(\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases}

이 식을 모든 메모리 mMm \in \mathbb{M}에 대하여 만족하는 함수 X를 찾으면, 그게 while  B  C\llbracket \mathtt{while} \; B \; C \rrbracket의 의미이다. 다시 적으면,

X=FB,C(X)where  FB,C(X)=λm.{X(C(m))if  B(m)=truemif  B(m)=false X = \mathcal{F}_{B,C} (X) \quad \text{where} \; \mathcal{F}_{B,C} (X) = \lambda m. \begin{cases} X(\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases}

의 해가 while  B  C\llbracket \mathtt{while} \; B \; C \rrbracket이다.

그러면 이 X=FB,C(X)X = \mathcal{F}_{B,C} (X)고정점을 찾는 문제에 대해 두 가지 의문이 생긴다.

  1. 해가 존재하는가?
  2. 여러 개의 해가 존재한다면, 어떤 해를 고를 것인가?

이 의문들만 해결된다면, 표시적 의미론에서 재귀 관계에 놓인 문법의 의미를 표현하는 문제가 풀린다. 해의 존재성은, ‘해가 존재한다’는 공간을 앞으로 정의할 것이고, 해의 선택은 최소 고정점least fixed point을 정의해서 선택할 것이다. 그러면 다음의 결과가 while의 의미이다.

while  B  C=lfpFB,C \llbracket \mathtt{while} \; B \; C \rrbracket = \textbf{lfp} \mathcal{F}_{B,C}

이제 구체적으로 의문들을 어떻게 해결하는 지 알아볼 때이다.

의미론과 도메인 이론

우선 XX가 속하는 의미semantics 의 공간을 서술하는 이론을 알아야 하는데, 이를 도메인 이론domain theory 라고 부른다. 이 이론은 완비 부분 순서complete partial order로부터 시작한다.

부분순서 집합

부분 순서partial order는 집합의 포함관계를 떠올리면 된다. 엄밀하게는 집합 DD에서 정의된 부분순서 \sqsubseteq는 다음 성질을 만족하는 관계이다.

  1. 반사성reflexivity: 모든 aDa \in D에 대해 aaa \sqsubseteq a이다.
  2. 추이성transitivity: aba \sqsubseteq b이고 bcb \sqsubseteq c이면 aca \sqsubseteq c이다.
  3. 비대칭성antisymmetry: aba \sqsubseteq b이고 bab \sqsubseteq a이면 a=ba = b이다.

부분적인 순서라 불리는 이유는, 집합에서 임의의 두 원소를 골랐을 때 비교가 가능하다는 보장을 하지 않기 떄문이다. 부분순서이면서 일반적인 수의 대소 관계처럼 어떤 두 원소를 골라도 비교가 가능한 경우에는 전순서total order라고 부른다.

부분순서 집합의 완비성

부분 순서 집합의 완비성completeness은 해석학에서 실수의 완비성 공리에서 다루는 그것과 거의 동일하다. 실수의 완비성 공리는 상계upper bound가 있는 공집합이 아닌 부분집합은 언제나 상한least upper bound이 있다, 즉 실수가 충분히 빽빽하게 채워져 있다는 내용이다. 완비 부분 순서도 상계가 있는 부분집합이 언제나 상한을 가지는 관계를 의미한다. 엄밀하게는 다음과 같다:

부분 순서 집합 (D,)(D, \sqsubseteq)에서, 일부 XDX \subseteq D를 가져왔을 때 dDd \in DXX상계라는 것은 다음을 의미한다.

xX,  xd \forall x \in X, \; x \sqsubseteq d

이런 상계 dd는 여러 개 있을 수 있다. 만약 dd가 모든 다른 XX의 상계보다 작다면, 이를 상한 또는 최소상계라고 부르고, X\bigsqcup X로 표기한다.

부분순서 집합에서 부분집합을 취했을 때 전순서이면 이를 체인이라고 부른다. 부분순서집합 (D,)(D, \sqsubseteq)이 완비하다complete는 것은, 모든 체인 XDX \subset D의 상한이 집합 DD에 속함을 의미한다.

XD \bigsqcup X \in D

흥미롭게도, 아무것도 없는 빈 집합도 체인이기 때문에, 이의 상한 =\bot = \bigsqcup \emptyset이라는, 최소원소가 DD에 존재한다.

연속성

두 부분순서 집합 D1,D2D_1, D_2에 대해, 함수 f:D1D2f: D_1 \to D_2가 연속이라는 것은, 체인의 상한이 함수에 의해 보존될 때를 의미한다:

chain  XD1,  f(X)=f(X) \forall \text{chain} \; X \subseteq D_1, \; \bigsqcup f(X) = f (\bigsqcup X)

의미론과 도메인

프로그래밍 언어에서 메모리의 집합 M\mathbb{M}은 변수를 값으로 대응시키는 함수들의 집합 XV\mathbb{X} \to \mathbb{V}로 볼 수 있고, 코드의 의미는 이전 글에서 다루었듯, MM\mathbb{M} \to \mathbb{M}에 속한다. 부울 값을 반환하는 식의 의미는 MB\mathbb{M} \to \mathbb{B}가 될 것이다.

우리가 풀고자 하는 FB,C:MM\mathcal{F}_{B,C}: \mathbb{M} \to \mathbb{M}의 고정점을 찾기 위해서, 이 대상 도메인들이 어떤 좋은 성질을 만족했으면 좋겠고, 그것이 바로 완비부분순서 관계의 존재와 함수의 연속성이다. 완비부분순서를 주기 위해서 몇 가지 테크닉이 필요하다:

들어올려진 집합

어떤 집합 SS에 대해, 새로운 원소 \bot을 추가한 집합 S=S+S_{\bot} = S + \\{\bot \\}을 고려하자. 여기에 순서를

dd    (d=d)(d=) d \sqsubseteq d' \iff (d = d') \lor (d = \bot)

로 주면, (S,)(S_{\bot}, \sqsubseteq)는 완비부분순서집합이고, SS의 들어올려진 집합lifted set이라 불린다.

곱집합

두 완전부분순서 집합 (D1,1)(D_1, \sqsubseteq_1), (D2,2)(D_2, \sqsubseteq_2)에 대해, 이들의 곱집합Cartesian product D1×D2D_1 \times D_2에서 관계를

(d1,d2)(d1,d2)    (d11d1)(d22d2) (d_1, d_2) \sqsubseteq(d_1 ^\prime, d_2 ^\prime) \iff (d_1 \sqsubseteq_1 d_1^\prime ) \wedge (d_2 \sqsubseteq_2 d_2 ^\prime)

으로 자연스럽게 주었을 때, (D1×D2,)(D_1 \times D_2, \sqsubseteq) 역시 완전부분순서 집합이다.

분리합

두 완전부분순서 집합 (D1,1)(D_1, \sqsubseteq_1), (D2,2)(D_2, \sqsubseteq_2)에 대해,

D1+D2={(d1,1)d1D1}{(d2,2)d2D2}{} D_1 + D_2 = \left\{ (d_1, 1) \mid d_1 \in D_1 \right\} \cup \left\{ (d_2, 2) \mid d_2 \in D_2 \right\} \cup \left\{ \bot \right\}

으로 D1D_1D2D_2의 분리합separated sum을 정의하고,

(d1,1)(d1,1)    d11d1(d2,2)(d2,2)    d22d2 (d_1, 1) \sqsubseteq (d_1 ^\prime, 1) \iff d_1 \sqsubseteq_1 d_1 ^\prime \\ (d_2, 2) \sqsubseteq (d_2 ^\prime, 2) \iff d_2 \sqsubseteq_2 d_2 ^\prime

으로 관계를 주면 (D1+D2,)(D_1 + D_2, \sqsubseteq)는 완전부분순서 집합이다.

연속 함수

두 완전부분순서 집합 (D1,1)(D_1, \sqsubseteq_1), (D2,2)(D_2, \sqsubseteq_2)에 대해, DDD1D_1에서 D2D_2로 가는 연속함수들의 집합이라 했을 때,

ff    d1D1,  f(d1)2f(d1) f \sqsubseteq f^\prime \iff \forall d_1 \in D_1,\; f(d_1) \sqsubseteq_2 f^{\prime}(d_1)

이면 (D,)(D, \sqsubseteq)는 완전부분순서 집합이다. 편의상 이제부터 DD를 연속이라는 개념을 내포하는 의미의 D1D2D_1 \to D_2로 표현하자.

또한, 이 공간에서 가장 작은 원소 \bot은,

d1D1,  f(d1)=2 \forall d_1 \in D_1, \; f(d_1) = \bot_2

어떤 원소든지 D2D_2의 가장 작은 원소인 2\bot_2로 보내버리는 함수가 되는데, 그 이유는 어떤 D1D2D_1 \to D_2인 함수 ff를 들고오더라도 f\bot \sqsubseteq f이기 때문이다.

집합에 완비부분순서를 주기

위 기술들을 이용하면, 완비부분순서를 가지는 집합들을 정의할 수 있다.

그리고 FB,C\mathcal{F}_{B,C}는 프로그램의 의미를 받아서 의미를 내놓는 함수이므로, (MM)(MM)(\mathbb{M} \to \mathbb{M}) \to (\mathbb{M} \to \mathbb{M})이다.

고정점으로 돌아와서

이제 FB,C\mathcal{F}_{B,C}가 연속이고, 코드의 의미를 완비부분순서가 있는 공간에 속한 원소로 생각할 수 있게 되었다.

최소 고정점

(D,)(D, \sqsubseteq)가 부분순서 집합일 때, 함수 f:DDf: D \to D의 최소 고정점 lfpf\textbf{lfp} f는 고정점 중 최소인 원소를 의미한다.

f(lfpf)=lfpfdD,  f(d)=d    lfpfd f(\textbf{lfp} f) = \textbf{lfp} f \wedge \forall d \in D, \; f(d) = d \implies \textbf{lfp} f \sqsubseteq d

아직은 고정점이 존재하는 지도 모르고, 모든 고정점이 한 고정점과 비교가 가능해서 그 고정점보다 큰 지도 알 수가 없다. 하지만 아주 쓸만한 정리가 있는데,

Kleene의 고정점 정리

(D,)(D, \sqsubseteq)가 부분순서 집합이고 f:DDf: D \to D가 연속함수일 때, ff는 최소고정점이 존재하고, 그 값은

lfpf=i0fi() \textbf{lfp}f = \bigsqcup _{i \ge 0 } f^i (\bot)

이다.

최소 고정점과 재귀의 관계

FB,C\mathcal{F} _{B,C}(MM)(MM)(\mathbb{M} \to \mathbb{M}) \to (\mathbb{M} \to \mathbb{M})인 연속함수로 정의했으므로, Kleene의 고정점 정리에 의하면 최소고정점이

lfpFB,C=i0FB,Ci() \textbf{lfp} \mathcal{F}_{B,C} = \bigsqcup _{i \ge 0} \mathcal{F} _{B,C} ^i (\bot)

가 된다. 그러면 우리가 통상적으로 아는 while의 의미를 이 최소고정점이라는 개념이 잘 설명하고 있을까?

값 도메인의 최소인 V\bot_\mathbb{V}는 분리합 B+Z\mathbb{B}_{\bot} + \mathbb{Z}_{\bot}의 최소 원소이고,

메모리 도메인의 최소인 M:XV\bot_{\mathbb{M}} : \mathbb{X}_\bot \to \mathbb{V}은 어떤 변수를 들고오더라도 V\bot_{\mathbb{V}}를 반환하는 함수이고,

MM\bot \in \mathbb{M} \to \mathbb{M}은, 어떤 메모리를 들고오더라도 M\bot_{\mathbb{M}}을 반환하는 함수이다.

FB,C(X)=λm.{X(C(m))if  B(m)=truemif  B(m)=false \mathcal{F}_{B,C} (X) = \lambda m. \begin{cases} X(\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases}

였으니,

FB,C()=λm.{(C(m))if  B(m)=truemif  B(m)=false=λm.{Mif  B(m)=truemif  B(m)=false \begin{aligned} \mathcal{F}_{B,C} (\bot) &= \lambda m. \begin{cases} \bot(\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases} \\ & = \lambda m. \begin{cases} \bot_{\mathbb{M}} & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases} \end{aligned}

로 적어볼 수 있고,

FB,C2()=λm.{FB,C()(C(m))if  B(m)=truemif  B(m)=false=λm.{{Mif B(C(m))=trueC(m)if B(C(m))=falseif  B(m)=truemif  B(m)=false \begin{aligned} \mathcal{F}_{B,C} ^2 (\bot) &= \lambda m. \begin{cases} \mathcal{F}_{B,C} (\bot) (\llbracket C \rrbracket (m)) & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases} \\ &= \lambda m. \begin{cases} { \begin{cases} \bot_\mathbb{M} & \text{if } \llbracket B \rrbracket (\llbracket C \rrbracket (m)) = \texttt{true}\\ \llbracket C \rrbracket (m) & \text{if } \llbracket B \rrbracket (\llbracket C \rrbracket (m)) = \texttt{false} \end{cases} } & \text{if} \; \llbracket B \rrbracket (m) = \texttt{true} \\ m & \text{if} \; \llbracket B \rrbracket (m) = \texttt{false} \end{cases} \end{aligned}

이다. 비슷하게,

FB,C3()=λm.{mif B(m)=falseC(m)if B(m)=trueBC(m)=falseCC(m)if B(m)=trueBC(m)=trueBCC(m)=falseMif B(m)=trueBC(m)=trueBCC(m)=true \mathcal{F} _{B,C} ^3 (\bot) = \lambda m. \begin{cases} m & \text{if } \llbracket B \rrbracket (m) = \texttt{false} \\ \llbracket C \rrbracket (m) & \text{if } \llbracket B \rrbracket(m) = \texttt{true} \wedge \llbracket B \rrbracket \circ \llbracket C \rrbracket (m) = \texttt{false} \\ \llbracket C \rrbracket \circ \llbracket C \rrbracket (m) & \text{if } \llbracket B \rrbracket (m) = \texttt{true} \wedge \llbracket B \rrbracket \circ \llbracket C \rrbracket (m) = \texttt{true} \wedge \\ & \quad \llbracket B \rrbracket \circ \llbracket C \rrbracket \circ \llbracket C \rrbracket (m) = \texttt{false} \\ \bot_{\mathbb{M}} & \text{if } \llbracket B \rrbracket (m) = \texttt{true} \wedge \llbracket B \rrbracket \circ \llbracket C \rrbracket (m) = \texttt{true} \wedge \\ & \quad \llbracket B \rrbracket \circ \llbracket C \rrbracket \circ \llbracket C \rrbracket (m) = \texttt{true} \end{cases}

이다. 반복적으로 이를 하면서 결국에는 조건 BB의 결과가 참이 될 때까지 돌리는 while문에 가까워진다는 점이 놀랍게도 관찰된다. 이들의 상한

lfpFB,C=i0FB,Ci() \textbf{lfp} \mathcal{F}_{B,C} = \bigsqcup _{i \ge 0} \mathcal{F} _{B,C} ^i (\bot)

은, 각 메모리 mMm \in \mathbb{M}에 대하여 lfpFB,C(m)\textbf{lfp} \mathcal{F}_{B,C} (m)이 모든 ii에 대해 FB,Ci()(m)\mathcal{F} _{B,C} ^i (\bot)(m)보다 메모리의 대소관계 M\sqsubseteq_{\mathbb{M}}에서 크거나 같아야 한다는 의미인데,

i0.mM.FB,Ci()(m)MlfpFB,C(m) \forall i \ge 0. \quad \forall m \in \mathbb{M}. \quad \mathcal{F} _{B,C} ^i (\bot)(m) \sqsubseteq _\mathbb{M} \textbf{lfp} \mathcal{F}_{B,C} (m)

충분히 많은 수의 반복을 했을 때 가지는 메모리라도 최소고정점의 결과에 포함된다. 즉, 실행적 의미론operational semantics이 풀어내는 while에 등장하는 재귀적인 관계를 표시적 의미론도 최소고정점을 통해 내포하고 있는 것이다.

참고자료