-
[계산이론] #07. Countable Set2023-2학기/계산이론 2023. 10. 15. 15:49
Countable Set
이번 글은 조금 수학적인 이야기로 시작할 텐데요, 다들 아시겠지만 간단한 정의부터 먼저 짚고 넘어갑시다. 아래와 같이 A에서 B로의 함수 f가 있다고 합시다.
이때, 함수 f가 ∀a1,a2∈As.ta1≠a2→f(a1)≠f(a2)를 만족하면 f를 One-to-one, Injective, 한국어로는 단사라고 부릅니다. 수학적 표현을 말로 고치면 A의 모든 원소가 B의 서로 다른 원소에 대응됨을 의미합니다.
또, 함수 f가 ∀b∈B,∃a∈As.tf(a)=b를 만족하면 f를 Onto, Surjective, 한국어로는 전사라고 부릅니다. 말로 고치면 B의 모든 원소가 대응되는 값이 A에 있음을 의미합니다.
마지막으로 함수 f가 단사이면서 전사일 경우, f를 Bijection, 한국어로는 전단사라고 부릅니다.
여기서 만약 A와 B가 전부 유한한 집합이면서 A에서 B로의 전단사 함수 f가 존재한다면, A와 B는 같은 개수의 원소를 갖는다는 사실을 쉽게 알 수 있습니다. 근데 재밌는 사실은 위 사실은 두 집합이 무한 집합이어도 성립한다는 것입니다.
2개의 무한 집합 N={1,2,3,⋯}과 N0={0,1,2,⋯}이 존재한다고 생각합시다. 이 두 집합은 같은 크기를 가질까요? 그렇습니다. 왜냐하면 N에서 N0으로의 전단사 함수 f(n)=n−1이 존재하기 때문이죠.
만약 집합 A가 유한 집합이거나, |A|=|N|일 경우 A를 Countable이라고 합니다.
예를 들어 모든 정수의 집합 Z는 Countable입니다. 이를 증명하기 위해서는 N에서 Z로의 전단사 함수가 존재함을 보여야 합니다. 대표적인 예시로 N의 원소 n에 대해서 n이 짝수일 경우 n2, n이 홀수일 경우 −n−12를 출력하는 함수가 있겠죠? 따라서 Z은 Countable입니다.
다르게 생각하면, Z={0,1,−1,2,−2,3,−3,⋯}처럼 Z를 나열할 수 있기 때문에 Z가 Countable이라고 말할 수도 있을 것입니다.
같은 방법으로 생각해서, 유리수의 집합 Q 역시 Countable입니다. 먼저 아래와 같은 Cartesian Product N×N이 Countable임을 알 수 있습니다.
먼저 두 수의 합이 2인 순서쌍을 먼저 나열합니다. (1, 1)
그리고 나서 두 수의 합이 3인 순서쌍을 나열합니다. (1, 1), (1, 2), (2, 1)
그다음에는 두 수의 합이 4인 순서쌍을 나열합니다. (1, 1), (1, 2), (2, 1), (1, 3), (2, 2), (3, 1)
이렇게 N×N의 모든 원소를 나열한 List를 만들 수 있기 때문에, N에서 N×N으로의 전단사 함수가 존재함을 확인할 수 있습니다.
이제 위 집합의 원소 (p, q)를 분수 pq에 대응시키면 아래와 같은 List가 만들어집니다.
{11,12,21,13,22,31,14,23,32,41,⋯}
여기서 이미 22는 앞에 나왔던 11과 중복이고, 24는 12과 중첩이므로, 이런 것들만 삭제해 주면 아래와 같습니다.
{11,12,21,13,31,14,23,32,41,⋯}
따라서 위와 같이 원소들을 나열할 수 있다는 사실은 N에서 Q로의 전단사 함수가 존재함을 의미하므로, Q 역시 Countable Set입니다.
Cantor's Diagonalization Principle
그럼 이제 Uncountable한 무한집합의 예시를 한번 보겠습니다. N에서 {0,1}으로의 함수의 집합 B를 한번 생각해 보겠습니다.
이해를 돕기 위해 예시를 들자면, n이 짝수이면 0, 홀수이면 1을 출력하는 함수 g가 있다고 생각합시다. 이 함수는 문자열 10101010... 에 대응됩니다.
그러면 이 함수 g는 B의 원소가 됩니다.
이제부터 이러한 집합 B가 Uncountable임을 증명할 건데요, B가 Countable 하다고 가정한 뒤 모순임을 보여서 증명해 보도록 하겠습니다. B={b1,b2,b3,⋯} 라고 두겠습니다. 이를 표로 나타내면 대략적으로 이러한 모습이겠죠?
함수 b1은 아까 예시로 들었던 g와 같은 함수이며, 1010101010... 에 대응됩니다. 함수 b2는 그냥 임의로 정한 함수입니다. 001001101... 에 대응됩니다. 이렇게 B의 원소를 나타낸 표에서, 정확히 대각선에 위치한 원소들만 한번 보겠습니다.
101100011... 이 문자열을 뒤집으면 010011100... 이 됩니다. 여기서 생각을 해봅시다. 010011100... 에 대응되는 함수가 위의 표에 존재할 수 있을까요? 불가능합니다.
왜? 010011100... 과 b1에 대응되는 문자열을 비교해 보면 첫번째 원소가 항상 다릅니다. 대각선에 있는 원소를 나열한 101100011...의 첫번째 원소는 b1의 첫번째 원소와 항상 같은데, 이 문자열을 뒤집어서 010011100...이 된 것이기 때문이죠. 마찬가지로, 010011100...과 b2에 대응되는 문자열을 비교해보면 두번째 원소가 항상 다르고, b3에 대응되는 문자열과 비교해보면 세 번째 원소가 항상 다릅니다.
엄밀한 표현으로, 아래와 같은 함수 d:N→{0,1}을 정의하겠습니다.
d(n)=1−bn(n)={0ifbn(n)=11ifbn(n)=0
이렇게 정의된 함수 d는 절대 bn과 같을 수 없으므로 모순이 발생합니다. 이런 증명 방식을 Cantor's Diagonalization Principle이라고 합니다.
또 다른 예시를 한번 보겠습니다. 실수의 집합 R은 Countable일까요? 그렇지 않습니다.
A={x∈R:0≤x<1}라고 두고, A가 Uncountable임을 증명하겠습니다. 그러면 A는 R의 부분집합이므로 R 역시 Uncountable임이 증명됩니다.
만약 A가 Countable이라고 가정하겠습니다. 그러면 A를 아래와 같이 표현할 수 있습니다.
A={f(1),f(2),f(3),⋯}
각 f(n)는 f(n)=0.dn1dn2dn3⋯를 의미한다고 생각하면 됩니다. 그러면 이때, 아래와 같은 실수 x를 생각할 수 있습니다.
x=0.d1d2d3⋯
dn={4ifdnn≠45ifdnn≠4
그러면 이 실수 x는 0 이상 1 이하이며 실수이지만 A에 포함되지 않습니다. 왜냐? x∈A이려면 f(n)=x인 n이 존재해야 하는데, f(n)의 소수점 n번째 자리수는 x의 소숫점 n번째 자릿수와 항상 다르기 때문입니다. 따라서 모순이 발생, A는 Uncountable입니다. 따라서 R 역시 Uncountable입니다.
Power Set의 Countability
집합 A에 대해서, 이의 Power Set은 아래와 같이 정의되죠.
P(A)={B:B⊆A}
여기서 A의 모든 원소 a에 대해 {a}는 항상 P(A)의 원소이기 때문에, P(A)는 적어도 A의 크기보다는 크다고 생각할 수 있습니다. 이에 대한 증명을 해보겠습니다.
먼저 A가 유한 집합일 경우, |P(A)|=2|A|이므로 쉽게 증명할 수 있습니다.
무한 집합일 경우에는 P(A)와 A가 같은 크기를 가진다고 가정한 뒤에, 모순임을 보여서 증명해 보도록 하겠습니다. P(A)와 A가 같은 크기를 가진다는 것은 A에서 P(A)으로의 전단사 함수 g가 존재한다는 것을 의미합니다.
이때, 집합 B를 B={a∈A:a∉g(a)} 라고 정의하겠습니다. 그러면 B는 당연하게도 A의 부분집합이므로 P(A)의 원소입니다. g는 전사 함수이기 때문에, g(a)=B인 a∈A가 항상 존재하게 됩니다.
만약 이 a가 B의 원소라고 생각해 봅시다. 그러면 g(a)=B이므로 a∈g(a)가 되는데, 이는 모순입니다. B의 정의에 의해서 a는 B의 원소가 될 수 없기 때문이죠.
반대로 a가 B의 원소가 아닐 경우 g(a)=B이므로 a∉g(a)가 되는데, 이 역시 모순이 됩니다.
따라서, 이러한 전단사 함수 g는 존재할 수 없으며, 이는 P(A)와 A가 같은 크기를 가질 수 없음을 의미합니다.
이 전 글에서 아래와 같은 Language Halt가 Undecidable임을 보였습니다.
Halt={⟨P,w⟩:P is C++ programm that terminates w}
이를 이번에는 살짝 다른 방법으로 증명해 보겠습니다. 먼저, 모든 C++ 프로그램은 Countable이라는 사실에서 출발하겠습니다. 왜냐하면 모든 C++ 프로그램은 Binary String ⟨P⟩로 표현 가능하고, 길이가 n인 Binary String의 개수는 2n개로 고정되어 있기 때문에 모든 C++ 프로그램을 List 할 수 있기 때문이죠.
이제 Halt가 Decidable이라고 가정하고, 모순임을 보여 Halt는 Undecidable임을 보이도록 하겠습니다. 모든 C++ 프로그램이 정확히 한 번씩 포함된 Infinite List P1,P2,P3,⋯를 생각합시다. 그러면 Halt 자체가 해결 가능한지, 불가능한지를 판단하는 C++ 프로그램, H가 존재할 것입니다.
이러한 프로그램 H는 ⟨P,w⟩를 입력받아 P가 w를 실행할 수 있으면 True를, P가 w를 실행할 수 없으면 False를 출력합니다.
여기서 ⟨Pn⟩를 입력받아 아래와 같은 작업을 수행하는 C++ 프로그램 D를 생각합시다.
- H에 ⟨Pn,⟨Pn⟩⟩를 집어넣는다.
- H가 True를 반환하면 무한루프로 보낸다.
- H가 False를 반환하면 D는 True를 출력하고 계산을 종료(Terminate)한다.
말로 풀어서 설명하겠습니다. D에 ⟨Pn⟩를 넣었을 때
- H에 ⟨Pn,⟨Pn⟩⟩을 넣은 값이 False이면 (= Pn이 ⟨Pn⟩을 입력받았을 때 Terminate 되지 않으면) D는 Terminate 됩니다.
- H에 ⟨Pn,⟨Pn⟩⟩을 넣은 값이 True이면 (= Pn이 ⟨Pn⟩을 입력받았을 때 Terminate 되면) D는 Terminate 되지 않습니다.
그리고 이 D는 C++ 프로그램이므로, D=Pn인 어떤 n이 존재합니다. 따라서, D는 D를 입력받았을 때, D가 D를 입력받았았을 때 Terminate되지 않으면 Terminate 됩니다. 역시 말이 안 되기 때문에 모순이 발생, Halt가 Undecidable임을 다시 한번 보일 수 있었습니다.
감사합니다.
이 글은 컴퓨터공학과 학부생이 개인 공부 목적으로 작성한 글이므로, 부정확하거나 틀린 내용이 있을 수 있으니 참고용으로만 봐주시면 좋겠습니다. 레퍼런스 및 글에 대한 기본적인 정보는 이 글을 참고해 주세요.
'2023-2학기 > 계산이론' 카테고리의 다른 글
[계산이론] #09. Non-Enumerability (1) 2023.11.13 [계산이론] #08. Enumerability (1) 2023.10.15 [계산이론] #06. Decidability와 Halting Problem (0) 2023.10.15 [계산이론] #05. Turing Machine (1) 2023.10.06 [계산이론] #04. Pumping Lemma (0) 2023.10.05