계산을 수학적으로 정의하다
튜링의 논문이 런던수학회에 접수되었고, 처치의 독립적인 연구와 함께 계산 가능성의 개념이 정밀하게 정리되었습니다.
THE PROOFS HUMANKIND PURSUED · 12
프로그램이 끝나는지 판단하는 만능 검사기가 가능할까요? 앨런 튜링의 연구를 따라, 프로그램을 데이터로 나타내고 그 실행을 예측하는 계산 절차가 마주치는 한계를 증명합니다.
모든 프로그램과 모든 입력의 종료 여부를 반드시 끝내면서 정확하게 판정할 수 있을까?
동아리에서 만든 간단한 프로그램부터 튜링의 실제 연구 배경과 기계 모델까지 읽습니다. 먼저 프로그램, 입력, 종료의 뜻을 정확히 구별합니다.
동아리 학생이 학교 축제의 참가 신청을 정리하는 프로그램을 만든다고 생각합시다. 첫 번째 프로그램은 참가자가 제출한 신청서 500장의 이름을 한 번씩 읽고 중복을 제거합니다. 파일을 정상적으로 읽을 수 있고 처리 규칙이 정해져 있다면 이 프로그램은 500장을 처리하고 종료합니다. 데이터가 많아 오래 걸릴 수는 있어도 끝나는 지점이 분명합니다.
두 번째 프로그램은 자연수 n을 입력받아 n이 0이 될 때까지 1씩 줄이는 단순한 계산을 합니다. 입력이 5라면 n의 값은 5, 4, 3, 2, 1, 0 순서로 변하고, 여섯 번째 상태를 확인한 뒤 종료합니다. 입력이 100만이면 더 오래 걸리지만 여전히 끝납니다. 이 사례에서는 매 반복마다 n이 감소하며 0 아래로 내려가지 않는다는 사실을 이용해 종료를 증명할 수 있습니다.
세 번째 프로그램은 0보다 큰 정수 x를 입력받아 x = x + 1이라는 명령을 끝없이 반복합니다. 정수를 무한히 크게 표현할 수 있다는 수학적 계산 모델에서 이 프로그램에는 종료 명령이 없습니다. 실제 컴퓨터에서는 메모리 부족이나 시스템 종료 같은 외부 요인으로 실행이 중단될 수 있습니다. 하지만 우리가 묻는 것은 운영체제가 프로그램을 강제로 닫을 수 있는지가 아니라, 그 프로그램이 규정된 계산 절차에 따라 스스로 종료 상태에 도달하는가입니다.
네 번째 프로그램은 주어진 자연수 n에 대해 k = 0부터 시작하여 k² = n을 만족하는 자연수 k를 찾을 때까지 k를 하나씩 증가시킵니다. n이 16이면 k = 4에서 끝나고, n이 2이면 끝나지 않습니다. 이 프로그램을 수학적으로 살펴보면 입력값에 따른 결과를 알아낼 수 있습니다. 특히 n = 2의 경우 자연수의 제곱이 2가 될 수 없음을 증명하면 무한 반복이라는 결론을 얻습니다. 반대로 n = 16의 경우 k = 4라는 실제 증거가 있습니다.
여기까지의 사례에서는 우리가 프로그램을 충분히 이해했기 때문에 답을 냈습니다. 정지 문제는 이해하기 쉬운 네 프로그램의 종료 여부를 판별할 수 있는가에서 출발하지만, 곧 질문의 범위를 규칙에 맞게 작성할 수 있는 모든 프로그램으로 넓힙니다. 프로그램 길이나 실행 시간에 상한을 두지 않고, 입력값도 임의로 허용한다는 조건이 뒤에 나올 증명에서 중요합니다.
프로그램을 1초 동안 돌렸는데 결과가 없었다고 합시다. 1시간, 하루, 한 달을 기다려도 결과가 나오지 않을 수 있습니다. 여기서 확인된 사실은 그 기간에 실행이 끝나지 않았다는 것뿐입니다. 처음 백만 번째 단계까지 반복하다가 백만한 번째 단계에 종료하는 프로그램도 어렵지 않게 만들 수 있습니다. 따라서 유한한 시간 동안 멈추지 않았다는 관찰만으로 영원히 멈추지 않는다고 결론 내릴 수는 없습니다.
모든 프로그램에 실행 횟수 제한을 정하는 검사를 생각해 봅시다. 예를 들어 1억 번의 계산 단계 안에 종료하면 종료, 그렇지 않으면 시간 초과라고 답합니다. 이 검사는 입력된 프로그램을 정해진 단계만큼 실행해 보면 되므로 절차 자체는 언제나 끝납니다. 다만 시간 초과라는 결과는 영원히 종료하지 않음과 다릅니다. 1억 1번째 단계에 끝나는 프로그램도 같은 판정을 받기 때문입니다.
한 가지 가능성은 검사 시간을 계속 늘리는 방법입니다. 먼저 천 번, 다음에는 만 번, 다시 십만 번을 실행해 봅니다. 언젠가 종료하는 프로그램은 충분히 오래 기다리면 종료하는 순간을 확인할 수 있습니다. 하지만 끝나지 않는 프로그램에서는 어디까지 더 검사할 것인가라는 질문이 계속 남습니다. 이 차이는 정지 문제를 설명할 때 중요한 단서가 됩니다. 종료했다는 사실에는 실제로 종료한 계산 이력이 증거가 되지만, 모든 프로그램이 종료하지 않는다는 판단을 동일한 방식의 단순 실행으로 확인할 수는 없습니다.
여기서 컴퓨터의 성능이나 계산 속도는 부차적입니다. 초당 백만 단계를 실행하든 백조 단계를 실행하든, 미리 정한 유한한 검사 시간 밖에서 끝나는 프로그램을 만들 수 있습니다. 우리가 알아보려는 것은 성능 개선의 여지가 있는가가 아니라, 시간제한 없이 모든 입력의 종료 여부를 정확히 결정하는 알고리즘이 이론적으로 가능한가입니다.
앨런 매시슨 튜링(Alan Mathison Turing, 1912–1954)은 영국 런던에서 태어난 수학자이자 논리학자입니다. 케임브리지대학교 킹스칼리지에서 수학을 공부했고, 이후 미국 프린스턴대학교에서 연구했습니다. 제2차 세계대전에는 영국의 암호 분석에 참여했으며, 전후에는 계산 기계와 프로그램에 관한 연구를 이어 갔습니다. 정지 문제를 이해할 때 중요한 업적은 전쟁기의 암호 해독보다 앞선 1936년의 계산 가능성 연구입니다.
그가 연구하던 시기에는 다비트 힐베르트와 빌헬름 아커만이 제기한 판정 문제(Entscheidungsproblem, 어떤 논리식이 모든 해석에서 성립하는지를 일반적인 절차로 판정하는 문제)가 중요한 과제였습니다. 제09회에서 살핀 괴델의 1차 논리 완전성 정리에 따르면, 모든 모형에서 성립하는 1차 논리식에는 형식적 증명이 존재합니다. 그러나 증명이 존재한다는 사실과, 임의의 논리식을 받았을 때 언제나 유한한 시간 안에 증명 가능 여부를 판정하는 절차가 있다는 사실은 서로 다릅니다.
튜링은 계산한다는 행위를 작은 단계의 규칙으로 분해했습니다. 기계가 읽는 기호, 기계가 기억하는 상태, 다음 행동을 정하는 규칙을 명시하면 계산 절차를 수학의 대상으로 다룰 수 있습니다. 그는 기계가 끝없이 기호를 출력할 수 있는가와 관련한 판정 불가능성을 연구하여, 이를 판정 문제의 부정적인 해답으로 연결했습니다.
출판 연혁은 분명히 구분해야 합니다. 튜링의 논문 「계산 가능한 수와 판정 문제에 대한 응용」(On Computable Numbers, with an Application to the Entscheidungsproblem)은 1936년 5월 28일 접수되었고, Proceedings of the London Mathematical Society 제42권 230–265쪽의 1937년 발행 기록이 있습니다. 학술 문헌에서 튜링 1936–1937년 논문이라고 쓰는 이유입니다. 독립적으로 유사한 결론에 이른 알론조 처치(Alonzo Church)의 1936년 연구 역시 이 역사에서 중요합니다. 어느 한 사람의 성과로 계산 가능성 이론 전체를 환원해서는 안 됩니다.
또 한 가지 주의할 부분이 있습니다. 오늘날 교과서에 널리 실리는 주어진 프로그램과 입력이 정지할지 판정하는 문제의 두 갈래 증명은 튜링의 1936년 원논문에 수록된 설명을 한 문장도 바꾸지 않고 옮긴 것이 아닙니다. 튜링의 원논문은 무한히 숫자를 출력하는 기계의 성질, 원형 기계(circular machine), 만족스러운 기술 번호(satisfactory description number) 등을 통해 논증을 진행합니다. 이번 글은 원논문의 역사적 질문과 현대적인 정지 문제 증명을 구별해서 설명합니다.
튜링 기계(Turing machine)는 여러 종류의 계산 장치를 비교할 수 있도록 규칙을 단순하게 만든 수학적 기계입니다. 길게 이어진 칸에 기호를 적는 테이프가 있고, 어느 한 칸을 읽는 머리와 현재 상태를 기억하는 장치가 있습니다. 한 번의 계산 단계에서 기계는 지금 읽는 기호와 자신의 상태를 확인한 뒤, 새 기호를 쓰고, 머리를 왼쪽이나 오른쪽으로 움직이고, 다음 상태로 바꿀 수 있습니다. 실제 컴퓨터의 회로를 재현하는 장치는 아닙니다. 규칙으로 수행되는 계산을 분석하기 위한 모형입니다.
이 기계에는 유한한 개수의 상태와 유한한 종류의 테이프 기호를 부여합니다. 프로그램으로 볼 수 있는 전이 규칙표도 유한합니다. 반면 필요에 따라 사용할 수 있는 테이프 칸의 개수에는 미리 정한 상한을 두지 않습니다. 어떤 한 시점에 실제로 사용한 칸은 유한하더라도 계산을 계속하면서 새로운 칸을 사용할 수 있습니다. 이러한 구분 덕분에 입력은 유한하고 명령도 유한하지만 계산은 끝없이 이어질 수 있다는 상황을 다룰 수 있습니다.
아주 단순한 규칙표를 생각해 봅시다. 상태가 읽는 중일 때 기호 1을 만나면 0으로 바꾸고 오른쪽으로 이동한 뒤 계속 읽습니다. 빈칸을 만나면 종료 상태로 바꿉니다. 오른쪽에 유한한 개수의 1이 있다면 이 기계는 마지막 1을 지나 빈칸을 읽고 끝납니다. 이 사례에서 실제 프로그램과 튜링 기계의 공통점은 현재 상태와 읽은 자료를 토대로 다음 동작이 결정된다는 점입니다.
튜링이 제시한 중요한 발상 가운데 하나는 범용 기계(universal machine)입니다. 서로 다른 계산 기계마다 물리적 장치를 하나씩 새로 만들지 않아도, 기계의 규칙표 자체를 부호로 나타내면 하나의 범용 기계가 다른 기계의 계산을 따라 할 수 있습니다. 현대적인 기호로 쓰면 U(⌜P⌝, x)입니다. 여기서 ⌜P⌝는 프로그램 P의 규칙을 나타내는 유한한 부호, x는 그 프로그램에 넣을 입력입니다. 범용 기계 U는 P를 묘사한 부호를 읽어 P가 입력 x에서 하는 계산을 단계별로 모사합니다.
이렇게 프로그램을 자료로 바꿀 수 있어야 뒤의 논증이 가능합니다. 프로그램을 읽는 검사는 프로그램의 규칙을 입력받아야 합니다. 그 프로그램 자체의 부호도 다시 입력 자료로 사용할 수 있습니다. 이는 컴퓨터가 코드를 파일로 저장하거나 다른 프로그램이 그 파일을 읽는 일과 같은 형식적 성질입니다. 다만 이 설명에서 프로그램은 무작위의 자연어 지시가 아니라, 문법과 실행 의미가 정확히 정해진 계산 절차를 뜻합니다.
튜링의 논문이 런던수학회에 접수되었고, 처치의 독립적인 연구와 함께 계산 가능성의 개념이 정밀하게 정리되었습니다.
『계산 가능한 수와 판정 문제에 대한 응용』이 학회지 제42권 230–265쪽에 실렸습니다.
정지 여부 판정기의 정의, 반대로 행동하는 프로그램, 자기 부호 입력, 두 갈래 모순을 순서대로 검토합니다. 결과가 실제로 허용하는 범위도 함께 확인합니다.
정지 문제의 대상을 먼저 정하겠습니다. P는 유한하게 기술된 프로그램, x는 P가 받을 입력입니다. P(x)↓는 프로그램 P가 입력 x에서 유한한 계산 단계를 거쳐 종료함을 뜻합니다. P(x)↑는 정해진 계산 모델 안에서 종료 상태에 도달하지 않음을 뜻합니다. 두 화살표는 프로그램이 수행한 계산과 관련된 성질을 나타냅니다. ↓는 오류 없이 정답을 출력했다는 뜻까지 포함하지 않습니다. 오류 메시지를 출력하고 종료하더라도 계산 자체가 끝났다면 종료한 것입니다.
우리가 찾는 가상의 검사기 H는 프로그램의 부호와 입력을 받습니다. 그 뒤 반드시 실행을 마쳐서 1이나 0 중 하나를 돌려줍니다. 1은 해당 프로그램이 그 입력에서 언젠가 종료한다는 뜻, 0은 종료하지 않는다는 뜻으로 정하겠습니다. 가장 중요한 요구는 검사기 H가 모든 유효한 P와 모든 x에 대해 항상 종료하고 언제나 정답을 준다는 것입니다.
한 입력에서만 잘 작동하는 검사기를 만들 수는 있습니다. 어떤 종류의 프로그램을 대상으로 종료 증명을 자동화할 수도 있습니다. 지금 가정한 H는 훨씬 강한 도구입니다. 규칙에 맞게 기술할 수 있는 모든 프로그램과 모든 입력에 대해 답을 내야 합니다. 모르겠음이라는 세 번째 대답을 허용하지 않으며, 계속 계산하다가 응답하지 않는 경우도 허용하지 않습니다.
코드를 들여다보는 대신 실제로 실행해 보면 되지 않느냐고 생각할 수 있습니다. 프로그램이 종료한다면 언젠가 그 사실을 확인할 수 있습니다. 하지만 프로그램이 계속 실행 중일 때는 다음 단계에 끝날 가능성을 원칙적으로 배제해야 합니다. 만능 H가 실제로 가능하다면, 이런 미해결 경우를 포함해 모든 입력을 빠짐없이 다루어야 합니다.
이제부터는 H가 존재한다고 가정하는 귀류법입니다. 프로그램 P의 설명을 입력받아 P가 자신의 설명을 입력으로 받을 때 끝나는가를 묻는 것이 가능합니다. ⌜P⌝도 유한한 기호 배열이므로 정해진 부호화 규칙에 따라 데이터로 전달할 수 있습니다. 모든 프로그램이 자기 코드를 유용하게 처리한다는 뜻은 아닙니다. 잘못된 입력을 만나 바로 종료하는 프로그램도 있을 수 있습니다. 중요한 것은 정해진 입력을 넣었을 때 실행이 끝나는지라는 질문을 어떤 프로그램에도 던질 수 있다는 사실입니다.
검사기 H가 있다고 믿고 새로운 프로그램 D를 만듭니다. D는 입력 s를 받으면 먼저 H에 (s, s)를 보냅니다. 즉, s가 나타내는 프로그램을 입력 s로 실행했을 때 멈추는지 물어봅니다. 그리고 검사기의 답과 반대가 되도록 행동합니다. H가 끝난다(1)고 하면 D는 끝나지 않는 반복에 들어갑니다. H가 끝나지 않는다(0)고 하면 D는 곧바로 종료합니다.
이 규칙은 어렵지 않습니다. 예측기가 멈춘다고 하면 멈추지 않고, 멈추지 않는다고 하면 멈춥니다. 단, D가 이렇게 행동하기 전에 H가 항상 정확히 판정한다는 가정을 사용하고 있습니다. 검사기가 가끔 틀린다면 뒤의 결론은 달라집니다. 이번 논증은 어떤 실용적 검사기의 오류를 발견하려는 실험이 아니라 오류가 전혀 없는 만능 검사기를 수학적으로 가정했을 때 생기는 모순을 보여 줍니다.
D도 유한하게 기술된 프로그램입니다. 그러므로 D의 설명을 나타내는 부호 d = ⌜D⌝가 있습니다. 우리는 D의 입력 자리에 바로 이 d를 넣을 수 있습니다. 이를 D(d)라고 씁니다. 여기서 D는 실행할 프로그램의 이름, d는 그 프로그램을 설명하는 자료입니다. 같은 대상의 서로 다른 역할을 구별해야 다음 계산을 이해할 수 있습니다.
먼저 검사기 H가 H(d,d)=1이라고 대답했다고 합시다. 이 말은 D를 입력 d로 실행하면 언젠가 끝난다는 예측입니다. 하지만 D의 정의에서는 검사기가 1을 내놓으면 끝없는 반복을 하게 되어 있습니다. 따라서 H가 1이라고 말한 경우 D(d)는 종료하지 않습니다. 검사기의 예측과 실제 실행이 어긋납니다.
반대로 H가 H(d,d)=0이라고 대답했다고 합시다. 이는 D(d)가 종료하지 않는다는 예측입니다. 그런데 D의 정의에 따라 H가 0을 내놓으면 D는 즉시 종료합니다. 따라서 H가 0이라고 말한 경우 D(d)는 종료합니다. 두 번째 경우에도 예측과 실제 실행이 어긋납니다.
검사기 H가 반드시 0이나 1 중 하나를 반환해야 하고 그 답이 항상 정확해야 한다는 조건을 다시 떠올려 봅시다. D(d)가 종료하는지와 종료하지 않는지 가운데 실제 계산은 한 가지 경우에 속합니다. 그러나 H는 어느 쪽을 선택해도 자신의 조건을 어기게 됩니다. 따라서 모든 프로그램의 정지 여부를 항상 종료하며 정확하게 판정하는 알고리즘 H는 존재할 수 없습니다.
이것이 현대적인 정지 문제의 표준적인 대각선 증명입니다. 논증에서 D라는 글자를 두 번 썼다고 무조건 모순이 나온 것은 아닙니다. 모든 계산 절차를 입력 자료로 부호화할 수 있고, 그 부호를 바탕으로 다른 계산 절차를 모사할 수 있으며, H의 대답에 따라 반대 행동을 하는 프로그램도 계산 가능한 절차라는 사실이 함께 필요합니다.
앞에서 사용한 구성을 일반적인 예측표로 나타내 보겠습니다. 여러 프로그램을 P₁, P₂, P₃, … 순서로 번호 매긴 뒤, 각 프로그램과 각 입력에 대해 H가 어떤 예측을 하는지 적는다고 합시다. 표의 가로줄은 프로그램, 세로줄은 입력이 될 수 있습니다. 그러면 대각선의 칸들은 H(⌜P₁⌝,⌜P₁⌝), H(⌜P₂⌝,⌜P₂⌝)처럼 프로그램과 자기 설명이 만나는 경우입니다.
일상적인 경우에는 어떤 입력 x를 고정하고 프로그램 P 하나만 검사할 수 있습니다. 그러나 우리가 만든 D는 어떤 프로그램의 자기 입력 사례가 주어지더라도 예측과 반대로 행동하도록 구성했습니다. 그 D를 다시 자기 부호 d에서 실행했을 때, H가 대각선 칸의 자기 판정을 정확히 맞혀야 한다는 요구가 D의 반대 행동과 정면으로 충돌합니다.
칸토어의 대각선 논법은 미리 나열했다고 가정한 배열의 각 행에서 하나의 자리를 골라 값을 바꾸는 방식으로, 그 배열에 들어가지 못하는 새 대상을 구성했습니다. 제05회에서는 실수의 숫자 자리를 바꾸었습니다. 여기에서는 각 프로그램이 자기 설명을 입력으로 받을 때의 종료 여부를 대상으로, 가정한 예측의 결과를 뒤집는 프로그램을 구성합니다. 두 논증은 자기 자신과 연결된 위치를 이용한다는 점에서 비슷하지만, 구체적으로 바꾸는 대상과 얻는 결론은 다릅니다. 실수의 비가산성 자체가 정지 문제의 불가능성을 바로 증명하는 것은 아닙니다.
제11회 괴델의 불완전성 정리에서도 기호로 적힌 문장을 수로 부호화하여 그 문장이 자기 자신의 증명 가능성을 언급할 수 있게 했습니다. 튜링의 경우에는 유한한 계산 규칙표를 입력 자료로 부호화합니다. 이 부호를 읽고 계산을 모사하는 범용 기계의 성질을 이용해 알고리즘이 모든 알고리즘의 행동을 결정할 수 있는가를 묻습니다. 한 편에서는 증명과 참의 관계를, 다른 편에서는 계산과 종료의 관계를 다룹니다.
가상의 H를 실제 코드 분석 도구로 오해하면 프로그램 실행을 충분히 오래 따라가면 된다고 반론할 수 있습니다. 그러나 정지 여부를 알아보려고 H가 내부에서 프로그램을 모사하는 경우에도 H 자신이 반드시 끝나야 합니다. D는 H가 어떤 방법을 사용하는지 상관하지 않습니다. H가 먼저 천만 단계를 실행하고 판단하든, 매우 정교한 수학적 분석을 사용하든, 마지막에 정확한 0이나 1을 반드시 준다고 가정하면 D는 그 답을 뒤집습니다.
또 다른 반론은 D처럼 일부러 검사기를 속이는 프로그램은 검사 대상에서 제외하자는 것입니다. 만약 D와 같은 형태의 프로그램은 허용하지 않는다라는 제한을 두면 더 좁은 종류의 프로그램에 대한 검사기를 연구하게 됩니다. 이런 제한된 문제 중에는 결정 가능한 것도 있습니다. 다만 모든 유효한 프로그램과 모든 입력을 검사한다는 원래의 질문은 더 이상 다루지 않습니다. 정지 문제의 증명은 바로 그 무제한의 보편성을 겨냥합니다.
D는 자기 자신의 부호를 만들 수 없으니 실행할 수 없다는 반론도 나올 수 있습니다. D가 실행 중에 자기 코드를 신비하게 발견해야 할 필요는 없습니다. 외부에서 D의 유한한 설명을 먼저 작성하고, 그 설명에 붙인 부호 d를 D의 입력으로 주기만 하면 됩니다. 프로그래밍 언어가 정해져 있으면 소스 파일을 텍스트 데이터로 전달하는 일과 같습니다. 자기 입력을 허용하는 범용 계산 모델에서는 유한한 명령을 가진 D도 같은 모델에 포함됩니다.
여기서 특정한 앱이 디스크 용량을 초과해 중단되거나 전원이 꺼져 멈추는 일을 생각해 볼 수도 있습니다. 그런 사건은 정지 문제의 이론적 결론과 별도로 분석해야 합니다. 실제 컴퓨터의 자원에는 상한이 있고, 운영체제가 예외를 일으킬 수도 있습니다. 수학적 정지 문제에서 사용하는 계산은 보통 필요한 만큼 메모리를 더 사용할 수 있다고 가정하는 계산 모델의 자발적인 종료 여부입니다. 실제 하드웨어의 강제 중단을 종료라고 정의하면 원래 질문이 달라집니다.
이제 모든 프로그램의 종료를 알아내는 절차와 종료하는 프로그램이 실제로 있음을 발견하는 절차를 분리해 보겠습니다. 입력으로 프로그램 P와 데이터 x가 주어졌을 때 범용 기계 U로 P(x)를 한 단계씩 모사합니다. 계산이 멈추면 종료라고 출력합니다. 이 탐색 방법은 P(x)가 실제로 종료하는 경우 그 사실을 언젠가 발견합니다. 반면 P(x)가 종료하지 않으면 계속 모사할 뿐 답을 내놓지 못합니다.
이처럼 어떤 경우에는 정답을 확인하고 끝나지만 다른 경우에는 답을 내지 못해도 되는 절차를 반결정 절차(semidecision procedure, 성립하는 경우를 유한한 검사로 확인하는 절차)라고 부릅니다. 종료함이라는 성질에는 이 방법이 있습니다. 그러나 종료하지 않음이라는 성질까지 모든 입력에 대해 같은 식으로 반결정할 수 있다면 이야기가 달라집니다.
왜일까요? 하나의 탐색기 A는 종료하는 경우에만 끝나고, 다른 탐색기 B는 종료하지 않는 경우에만 끝난다고 가정합시다. 두 탐색기를 번갈아 한 단계씩 실행할 수 있습니다. 어느 프로그램이든 실제로는 종료하거나 종료하지 않는 두 경우 중 하나이므로, A나 B 중 하나가 언젠가 정답을 보고합니다. 그러면 어느 입력에서든 끝나며 완전한 답을 내는 검사기를 만들 수 있습니다. 앞에서 그런 검사기는 불가능하다고 증명했습니다. 따라서 종료하지 않는 모든 사례를 빠짐없이 찾아내는 일반적 반결정 절차 역시 존재하지 않습니다.
수학적 용어로 이 사실을 더 압축해 쓸 수 있습니다. 프로그램 번호를 n이라고 하고, n번 프로그램이 자기 번호 n을 입력받아 종료하는지 검사해 보겠습니다. K = {n | Mₙ(n)↓}라는 집합은 종료하는 자기 입력 사례의 번호 전체를 모읍니다. K의 원소는 차례로 실행을 모사하며 확인할 수 있으므로 계산적으로 열거 가능한 집합입니다. 그러나 앞의 대각선 구성에 따라 K에 들어가는지 모든 n에 대해 결정할 수 있는 절차는 없습니다. 이 표기는 계산 가능성과 복잡성에 관한 스탠퍼드 철학백과의 정리 방식과 대응합니다.
정지 문제의 결론은 다른 문제를 분석하는 출발점이 됩니다. 예를 들어 어떤 프로그램이 입력받은 자료를 처리하면서 특정한 글자 완료를 출력하는지 판정하는 일반적 절차가 있다고 가정해 보겠습니다. 이 판정기가 종료 문제를 해결할 수 있는지 확인하려면 원래 프로그램 P와 입력 x를 이용하여 새로운 프로그램 Q를 구성합니다. Q는 실행할 때 먼저 P(x)를 내부에서 모사합니다. P(x)가 끝나면 그때 글자 완료를 출력하고 종료합니다. P(x)가 끝나지 않으면 Q는 그 출력 명령에 도달하지 않습니다. P의 다른 출력은 Q가 바깥으로 전달하지 않는다고 정하면 혼동도 없습니다.
그러면 Q가 완료를 출력하는지 판단하는 판정기가 있다면, 그 답만으로 P(x)의 종료 여부를 알 수 있습니다. P(x)가 종료함과 Q가 완료를 출력함이 정확히 같은 조건이 되도록 Q를 설계했기 때문입니다. 그러나 모든 P와 x의 종료 여부를 판정할 수 없다는 사실을 앞에서 증명했습니다. 따라서 임의의 프로그램이 특정 출력을 할지 언제나 정확하게 판정하는 일반적인 알고리즘도 존재할 수 없습니다.
이 방법을 환원(reduction, 한 문제를 다른 문제의 입력으로 효과적으로 바꾸어 풀어 보는 방법)이라고 부릅니다. 여기서 필요한 조건은 변환 자체가 유한한 계산 절차로 수행되고, 두 문제의 답이 설명한 대로 대응한다는 것입니다. 문제 A가 문제 B보다 어렵다는 막연한 평가 대신, A의 모든 사례를 B의 사례로 바꾸는 구체적인 구성입니다.
하지만 모든 성질을 검사할 수 없다라는 말로 과도하게 일반화해서는 안 됩니다. 어떤 프로그램의 글자 수를 세거나, 파일에 특정 함수 이름이 있는지 검사하거나, 정해진 길이의 반복문이 끝나는지 분석하는 문제는 결정 가능할 수 있습니다. 프로그램의 실행 의미에 관한 비자명한 성질에 대해서는 일반적인 판정 불가능성 결과가 더 넓게 알려져 있지만, 어떤 정확한 성질을 판정하는지와 어느 계산 모델을 사용하는지에 따라 조건을 따져야 합니다. 여기서는 방금 직접 구성한 출력 사례만 결론으로 삼겠습니다.
제한된 상태 공간, 1차 논리 판정 문제, 프로그램 검증의 실질적 역할, 원전과 현대 재구성의 차이를 분리해 설명합니다.
예를 들어 프로그램이 가질 수 있는 상태가 A, B, C 세 가지이고, 내부 숫자값은 0, 1, 2, 3 네 가지 중 하나라고 합시다. 외부 입력이나 무한하게 커질 수 있는 기억장치가 없고, 같은 상태와 같은 숫자값에서는 항상 같은 다음 동작을 한다면 가능한 전체 설정은 3×4 = 12개입니다. 상태 A·숫자 2에서 출발한 계산이 종료하지 않고 열세 번째 서로 다른 설정을 만들 수 있을까요? 만들 수 없습니다. 열두 가지 설정만 허용되기 때문입니다.
계산 중 어떤 설정이 두 번째로 나타났다고 합시다. 규칙이 결정적이므로 같은 설정 뒤에는 언제나 같은 다음 설정이 이어집니다. 따라서 이미 지나간 부분을 다시 반복하며, 그 사이에 종료하지 않았다면 앞으로도 종료하지 않습니다. 최대 열두 가지 설정을 검사하는 동안 종료하거나, 그전에 동일한 설정이 반복되는 경우를 발견하면 됩니다. 이 제한된 기계에서는 유한한 상태들을 모두 기록하여 종료 여부를 판정하는 방법이 있습니다.
이 결론을 임의의 튜링 기계에 그대로 적용할 수는 없습니다. 일반 튜링 기계는 계산 과정에서 새로운 테이프 칸을 계속 사용할 수 있어 가능한 전체 설정의 수가 일정한 유한값으로 제한되지 않습니다. 프로그램과 입력을 유한하게 주더라도 계산 중 사용 가능한 기억장치가 잠재적으로 무한하다는 점이 차이를 만듭니다. 그러므로 정지 문제의 판정 불가능성은 모든 특별한 프로그램 집합에서 판정이 불가능하다는 뜻이 아닙니다.
현실의 프로그래밍에서도 반복 횟수가 정해진 코드나 종료를 보장하는 유형의 언어를 사용하면 강한 종료 보증을 얻을 수 있습니다. 정지 문제가 알려 주는 사실은 이런 방법들이 쓸모없다는 이야기가 아니라, 표현력과 입력 범위를 제한하지 않은 모든 프로그램을 한꺼번에 다루는 완전한 검사기는 만들 수 없다는 한계입니다.
튜링이 애초에 겨냥한 질문으로 돌아가겠습니다. 제09회에서는 1차 논리에서 전제들이 모든 모형에서 결론을 함축한다는 의미론적 사실과 기호 규칙으로 결론을 증명할 수 있다는 구문론적 사실을 비교했습니다. 괴델의 완전성 정리는 모든 모형에서 타당한 1차 논리식에는 형식적 증명이 존재한다고 말합니다. 그러나 주어진 식이 타당한지 임의의 경우에 유한한 계산으로 판단할 수 있다고 보장하지는 않습니다.
타당한 식을 하나 받았다면 형식적 증명 후보를 작은 것부터 큰 것으로 차례로 검사하는 방법을 사용할 수 있습니다. 언젠가 실제 증명을 찾으면 그 식이 타당하다는 사실을 확인하게 됩니다. 그러나 타당하지 않은 식을 받았을 때 후보 검사가 언제 끝나야 하는지는 이 방법으로 알 수 없습니다. 이 차이는 제10회 힐베르트의 기획과 제11회 괴델의 성과, 그리고 이번 튜링의 논증을 하나의 역사 속에 놓습니다.
튜링은 계산 절차를 형식화하고 어떤 기계의 출력 행동에 대한 일반적 판정이 불가능함을 보인 뒤, 그런 판정이 가능한 경우 1차 논리의 판정 문제도 해결할 수 있게 되는 연결을 제시했습니다. 따라서 모든 1차 논리식이 타당한지 판정하는 보편적 알고리즘은 존재하지 않습니다. 알론조 처치는 1936년에 람다 계산과 관련된 별도의 방법으로 대응하는 부정적 결론을 얻었습니다. 두 연구는 계산 가능성 개념을 수학적으로 정밀하게 만드는 데 중요한 역할을 했습니다.
여기서 기계가 할 수 있는 계산과 사람이 이해할 수 있는 모든 생각을 동일한 것으로 간주하면 안 됩니다. 처치–튜링 논제(Church–Turing thesis)는 명확한 규칙으로 수행되는 유효한 계산 절차를 튜링 계산 가능성과 연결하는 주장입니다. 이는 정지 문제의 대각선 증명 그 자체와는 논리적 지위가 다릅니다. 튜링 기계로 정의한 정지 문제의 판정 불가능성은 형식 모델 안에서 수학적으로 증명됩니다. 그 결과를 모든 직관적 계산 방법으로 해석할 때에는 계산 가능성 개념의 철학적 정당화가 함께 관여합니다.
프로그램을 만들고 시험할 때 실제로 필요한 질문은 훨씬 구체적입니다. 이 반복문은 n이 감소하므로 끝나는가?, 이 함수는 재귀 호출할 때 남은 입력 길이가 줄어드는가?, 이 반복문에서 같은 상태가 다시 나타나는가?처럼 특정한 코드와 입력 조건을 분석하는 것입니다. 이런 질문에는 수학적 증명, 정적 분석, 실행 검사, 제한된 상태 공간의 탐색 등이 큰 도움을 줍니다.
예를 들어 위에서 본 n이 0이 될 때까지 1을 빼는 프로그램에서는 매 단계의 n이 자연수이고 이전보다 엄격히 작아진다는 사실을 확인하면 종료를 증명할 수 있습니다. 자연수에는 무한히 길게 이어지는 엄격한 감소열이 없기 때문입니다. 이처럼 계산이 계속될 수 없는 이유를 보여 주는 수량을 종료 측도(termination measure, 반복할 때 일정한 순서에 따라 감소하는 값)라고 부를 수 있습니다. 모든 프로그램에 이런 측도를 기계적으로 찾아낼 수 있다는 뜻은 아니지만, 특정 프로그램의 종료 증명에는 효과적입니다.
인공지능 기반 코드 분석기도 일부 사례에서 반복문의 오류를 찾아내거나 종료 근거를 제안할 수 있습니다. 결과를 형식적인 증명이나 테스트로 확인한다면 개발 과정에서 유용합니다. 다만 어떤 도구가 모든 가능한 프로그램과 입력을 받아 반드시 끝나며 종료 여부를 항상 정확하게 알려준다고 주장한다면, 그 주장은 앞에서 증명한 정지 문제의 결론과 충돌합니다. 따라서 도구의 실제 보증 범위, 미해결 반환 가능성, 검사 시간 제한, 가정한 프로그램 언어를 확인해야 합니다.
이 정리를 인간과 인공지능 가운데 누가 더 우월한가라는 주장에 곧바로 사용해서는 안 됩니다. 정지 문제는 명확히 규정한 일반적인 계산 절차의 가능성과 불가능성에 관한 수학적 정리입니다. 인간이 모든 프로그램의 정지 여부를 알아낼 수 있다는 결론도, 기계가 어느 프로그램의 정지도 증명할 수 없다는 결론도 여기서 나오지 않습니다.
튜링의 1936–1937년 논문은 처음부터 현재 교재에서 자주 쓰는 H(P,x)를 기호로 내세우지 않았습니다. 그가 조사한 주요 대상은 계산 가능한 실수와 그 숫자를 계속 출력하는 기계였습니다. 소수 전개처럼 필요한 만큼 숫자를 출력할 수 있는 기계를 생각했기 때문에, 숫자를 무한히 계속 생산할 수 있는가라는 문제가 핵심적인 역할을 했습니다.
튜링이 서클 프리(circle-free, 원형에 빠지지 않는)라고 부른 기계는 계산 가능한 수의 숫자를 끝없이 산출할 수 있는 기계였습니다. 반대로 서큘러(circular, 원형)는 유한한 개수의 숫자만 출력하는 경우를 포함합니다. 여기에서 서큘러 기계와 현대적인 의미로 무한히 실행되는 프로그램을 단순히 일치시키면 안 됩니다. 원래의 분류는 기계가 계속 새로운 숫자를 출력하는지에 관한 것이고, 현대적인 정지 문제는 기계가 실행을 끝내는지에 관한 것입니다.
튜링은 기계의 규칙표를 부호화해 기술 번호(description number)를 붙였고, 어떤 번호가 무한한 수열을 산출하는 기계에 해당하는지 일반적으로 판단할 수 있다고 가정하면 대각선 구성을 통해 모순이 생긴다는 것을 보였습니다. 이후 이 판정 불가능성을 특정 숫자를 출력할지 결정하는 문제에 연결하고, 다시 1차 논리의 판정 문제에 연결했습니다. 이는 스탠퍼드 철학백과 「Turing Machines」의 2.4.2절에서 확인할 수 있는 역사적 단계입니다.
이번 글에서 모든 프로그램을 넣는 H와 H의 예측을 뒤집는 D를 구성한 부분은 이 성과를 현대의 프로그램 종료 문제에 맞게 다시 서술한 표준적인 논증입니다. 역사적 저술과 현대 교육용 재구성을 구별하면, 튜링이 1936년에 오늘날 교과서의 코드 그대로 증명했다는 부정확한 설명을 피할 수 있습니다. 원전의 기호표와 실제 증명 전개를 줄마다 대조해 완역한 것으로 주장하지 않습니다.
첫 번째 질문. 자연수 n을 입력받고 n > 0인 동안 n을 1씩 감소시키는 프로그램이 있습니다. 입력이 4라면 숫자값은 어떻게 바뀌나요? 이 프로그램이 모든 자연수 입력에서 종료한다는 사실을 확인할 수 있는 이유를 설명해 보세요.
풀이. n은 4, 3, 2, 1, 0으로 변합니다. 각 반복에서 n은 자연수이고 이전보다 정확히 1만큼 작아집니다. 자연수는 0 아래로 끝없이 감소할 수 없으므로 반복 횟수는 최초 입력값을 넘지 않습니다. 이 계산은 일반적 정지 판정기에 의존하지 않고 특정한 프로그램의 종료를 증명하는 예입니다.
두 번째 질문. 어떤 검사기는 임의의 프로그램을 5억 단계만 실행하고, 그 전에 끝나면 종료, 그렇지 않으면 무한 반복이라고 답합니다. 이 검사기를 모든 프로그램의 정지 여부를 결정하는 알고리즘으로 인정할 수 있을까요?
풀이. 인정할 수 없습니다. 5억 1번째 단계에 종료하는 프로그램은 검사 시간에 걸려 무한 반복이라는 잘못된 판정을 받습니다. 5억 단계에서 종료하지 않았다는 관찰과 어느 단계에서도 종료하지 않는다는 결론이 다르기 때문입니다. 검사가 틀리는 경우를 피하려면 시간 초과 또는 미확인이라는 결과를 따로 두어야 하고, 그렇게 하면 모든 입력을 0/1로 결정한다는 요구는 충족하지 못합니다.
세 번째 질문. 가상의 검사기 H가 D(d)의 종료를 예측합니다. H(d,d)=1이라고 답한 경우와 H(d,d)=0이라고 답한 경우, 각각 D(d)는 실제로 무엇을 하나요? 정지 문제의 모순이 어느 가정에서 발생했는지 설명해 보세요.
풀이. H가 1이라고 답하면 D는 종료하지 않습니다. H가 0이라고 답하면 D는 즉시 종료합니다. 두 경우 모두 H가 정확한 답을 냈다는 가정에 어긋납니다. 그러므로 모든 프로그램에 대해 언제나 종료하며 항상 정확한 답을 내놓는 H가 존재한다는 가정이 성립할 수 없습니다. 개별 프로그램에 대한 모든 검사나 특정 부류의 종료 증명을 부정하는 결과는 아닙니다.
지금까지 네 가지 구체적 프로그램의 실행을 살펴보았습니다. 일정한 입력에서 종료하는 사례에는 종료에 도달한 계산 이력을 제시할 수 있고, 간단한 반복문에서는 종료하지 않는 이유도 수학적으로 증명할 수 있었습니다. 하지만 실행 시간을 정해 두는 방법만으로는 임의의 프로그램이 앞으로 영원히 종료하지 않을지 알 수 없습니다.
이 문제를 일반적으로 해결하는 검사기 H가 있다고 가정하면, H의 예측과 반대로 행동하는 D를 만들 수 있습니다. 그다음 D 자신의 설명을 D에 입력하면, H가 어느 답을 내놓아도 정확성 조건이 깨집니다. 따라서 모든 프로그램과 입력의 정지 여부를 빠짐없이 정확히 결정하고, 검사기 자신도 항상 끝나는 하나의 알고리즘은 존재하지 않습니다. 이는 컴퓨터가 아직 충분히 빠르지 않아서 생기는 기술상의 어려움과 구분되는 수학적 결론입니다.
튜링의 성과는 바로 앞의 연재들과 연결됩니다. 칸토어는 나열한 대상의 대각선을 바꾸는 방법으로 비가산성을 증명했고, 괴델은 산술 문장이 자기 자신의 증명 가능성을 다룰 수 있도록 했습니다. 튜링은 프로그램의 실행 규칙을 부호화하고, 보편적인 종료 판정기를 가정했을 때 생기는 모순을 보여 주었습니다. 무엇을 판정하려 하는가, 입력 전체의 범위는 어디까지인가, 판정 절차가 반드시 끝나야 하는가를 정확히 밝힐 때 정지 문제의 의미가 드러납니다.
다음 제13회에서는 칸토어의 멱집합 정리로 돌아갑니다. 집합 A의 모든 부분집합을 모은 집합 P(A)가 왜 A보다 항상 더 많은 원소를 가지는지, 유한집합과 무한집합 각각에서 어떤 논증을 사용할 수 있는지 살펴볼 예정입니다.
영국 런던에서 태어나 케임브리지 킹스칼리지와 미국 프린스턴대학교에서 수학과 논리학을 연구했습니다. 1936년에 유한한 규칙으로 계산하는 기계의 개념을 정식화하고, 1937년 발행된 논문에서 판정 문제의 해결 불가능성을 밝혔습니다. 이후 암호 분석과 실제 계산 기계 연구에도 기여했습니다.
원논문의 발행 서지와 연구기관의 공개 해설을 대조하고, 현대 정지 문제의 표준 증명과 역사적 논증을 구분했습니다.
편집 범위: 본문의 H·D 구성, 학생 동아리 프로그램 네 사례, 제한된 상태 공간과 출력 문제 환원은 현대적인 교육용 설명입니다. 튜링이 1936년 논문에서 바로 이 프로그램 코드와 이 한글 서술을 사용했다고 주장하지 않습니다. 참고문헌은 공개 열람된 출판사 메타데이터, 백과사전 연구 글, 공개 설명에 근거합니다. 실제 홈페이지 통합 빌드·운영 이미지 표시·운영 배포는 집필 완료와 구분해야 합니다.