Prolog Language

FrontPage|FindPage|TitleIndex|RecentChanges| UserPreferences P RSS


1. 개요

1973년 프랑스의 컴퓨터 과학자 Alain Colmerauer와 논리학자 Phillipe Roussel이 개발한, 인공 지능 분야에서 많이 쓰이는 논리학을 기초로 한 고급 프로그램 작성 언어. 단어(symbol)와 그들 사이에 있는 관계를 이용하여 문제를 해결한다. 단어로 표현되는 사실(fact)과 규칙(rule)으로 프로그램을 표현하며, 논리학에서의 first-order logic의 규칙을 그대로 따르고 있다. 주로 숫자 계산보다는 인공 지능 분야에서의 논리적인 추론이나 패턴 매칭, 리스트 처리 등에 적합하다.

http://wkddngur7800.mytripod.co.kr/_temp_16.htm 이 페이지의 표현을 다소 다듬었습니다.

2. 특징

PrologLanguagedeclarative language (iterative language와 대비하여) 혹은 logical language (functional language와 대비하여) 로 분류된다.

  • PrologLanguage의 syntax는 first-order logic (위 사이트에서 1차 서술 논리라고 한 것이 아마 이것을 의미하는듯?) 의 문법을 조금 더 타이핑하기 쉽고 심볼릭하게 정제한 형태의 문법을 사용한다. 가독성은 조금 떨어지지만. 이 logic algebra의 domain은 거의 항상 symbol(문자열)이고 숫자 연산을 지원한다.
  • PrologLanguage의 semantics는 몇 개의 명제를 선언 하는 의미를 갖게 된다.

즉, PrologLanguage는 first-order logic의 문법으로 쓰여진 유한한 개수의 명제를 선언하여, 그 명제들로부터 연역 추리 deductive inference 를 하는 형태로 사용된다.

  • example : (가장 흔한 버전)
    father(john, mary).
    father(bob, john).
    grandfa(A, B) :- father(A, C), father(C, B).
    
    ?- grandfa(bob, mary).
     yes.
    ?- grandfa(mary, john).
     no.
    ?- grandfa(A, mary).
     A = bob? ;
     no.
      

  • PrologLanguage는 아주 지능적인 back tracking과 unification을 통해 이같은 기능을 구현한다. 주어진 query (앞의 예에서 ?- 뒤에 쓴 것들) 를 만족시키기 위해 필요한 명제들을 차례로 평가하면서, 각 변수들은 최대한 늦게 평가함으로써 각 변수들이 항상 필요한만큼만의 값을 가지도록 한다. 만약 하나의 명제가 실패한다면, 강력한 back tracking 기능으로 그 명제를 참으로 만들 수 있는 다른 명제들을 순차적으로 평가한다.
    이와 같은 특징으로 인해 종종 변수의 값을 평가하기 위해 무한 루프에 빠지는 일을 방지하기 위해, back tracking을 막기 위한 cut 이라는 언어 스펙을 지원한다.

  • PrologLanguage는 symbol 처리를 위한 강력한 도구들을 제공한다. 문자들은 어떤 식으로든 구조화될 수 있으며, 각 symbol들은 개개의 문자를 list로 떼어내거나 구조 자체가 변수와 unification 될 수 있는 기능을 지원한다. list는 . (period) 라는 특수한 symbol을 통해 구현된다.
    ex : [1,2,3] = .(1,.(2,.(3,[])))

  • 타입 체크가 아주 약하다. 모든 값들은 functional structure (단일 symbol은 0-ary function이다.)이거나 숫자이기 때문에, 실제 domain에 따른 타입 체크를 지원하지 않는다. 그러나 무한대에 가까운 fuctional structure 지원으로, 타입 체크는 얼마든지 할 수 있다.
    DeleteMe 학부 강의시간에 어느 조에서 typed-prolog에 대한 가능성을 타진해봤으나 결론은 필요없다였습니다. --Sequoia

3. 활용 분야

  • 강력한 symbol 처리 능력으로 인해, 자연어 처리(NaturalLanguageProcessing, NLP) 분야에서 가장 활발하게 이용되고 있다. (자연어 검색 엔진 등)
  • symbolic AI 분야에서 많이 사용된다.
  • 연구용이 아닌 실제 개발에서 사용하기 위해서는 CppLanguage이나 JavaLanguage에 embed하는 방식으로 사용하면 효과적일 것 같다.

4. 예시 프로그램

  • list 합치기. 이것은 한 list의 뒤에 다른 list를 잇는 concat 연산의 정의선언한 것이다.
    concat([],A,A).  // 빈 list [] 와 A를 합치면 A이다.
    concat([H|T],A,[H|R]) :- concat(T,A,R).  // T와 A를 합쳐서 R이 된다면, [H|T]와 A를 합쳐서 [H|R] 이 된다.
     
    PrologLanguage에서 별도의 명시 없이 사용한 단어는 소문자로 시작하면 symbol 또는 predicate, 대문자로 시작하면 variable이 된다. first-order logic 이므로 predicate 위치에는 variable이 올 수 없다. (즉 variable은 symbol들로 이루어진 functional structure만을 가질 수 있다.)

    위 프로그램에 concat([a,b],[c,d],R0). 이라고 query를 주면, 다음과 같은 순서대로 연산이 일어난다.

    1. 첫번째 선언과 query를 unify 해본다. [a,b][] 와 unify 될 수 없으므로 실패한다.
    2. 두번째 선언과 query를 unify 해본다. H=a, T=[b], A=[c,d], R0=[a|R1] 이고 concat([b],[c,d],R1) 이 만족해야 한다.
    3. concat([b],[c,d],R1)과 첫번째 선언을 unify할 수 없으므로 다시 두번째 선언과 unify 한다. H=b, T=[], A=[c,d], R1=[b|R2] 이고 concat([],[c,d],R2) 가 만족해야 한다.
    4. 첫번째 선언에 의해 R2=[c,d] 이다. R1=[b,c,d] 이고 R0=[a,b,c,d] 이다. 원래 query에서 모든 변수가 instantiate 되었으므로 query의 결과를 낸다. <!> R0=[a,b,c,d] ?
    5. 여기에서 ; 을 입력하여 더 원하는 값이 있는지 찾게 하면, PrologLanguage는 마지막으로 성공한 unification을 실패로 간주하고 다른 가능성이 있는지 찾는다. 이 경우 concat([],[c,d],R2) 를 첫번째 선언과 unify한 것을 실패로 간주하고 두 번째 선언과 unification을 시도한다. [H|T][]는 서로 unify 될 수 없으므로 실패. 그 이전 단계들도 이미 모든 concat/3 (3개의 인자를 받는 concat predicate)과 unification을 시도해보았기 때문에, 더 이상의 가능성이 없다고 보고 no. 를 답으로 낸다. (즉, query 문장이 거짓이라는 의미이다.)

  • 다음과 같은 query 도 가능하다.

    ?- concat(A,[c,d],[a,b,c,d]).
     A = [a,b]?
     

    모든 프로그램에서 이러한 역 query 가 가능한 것은 아니지만 교수님의 표현을 빌려 이런 것이 prolog의 beauty 이다 -_-;

    이 프로그램은 time complexity 가 O(n) (n은 앞쪽 list의 길이) 라는 단점이 있다. 이것을 constant time 에 해내기 위한 몇 가지 꽁수가 있다. -_-;

  • negation. 이것은 주어진 functional structure를 하나의 statement로 보고 평가하여 이 statement가 참이면 실패하고, 거짓이면 성공한다.
    not(A) :- A, !, fail.
    not(_).
     
    ! 은 cut이라는 스펙으로, 강제로 backtracking을 중단시킬 때 사용한다.
    위 선언을 아까 저~~위의 example 과 함께 선언한 뒤 not(father(bob, mary)). 를 query로 주면 다음과 같은 순서대로 연산이 일어난다.

    1. 첫번째 선언과 query를 unify 해본다. A=grandfa(bob, mary)이다.
      1. A는 grandfa(bob,mary)이고 위에서 봤듯 이 명제는 참이다.
      2. !은 cut으로, 명제 자체는 참값을 가진다.
      3. fail은 무조건 실패한다. 실패했으므로 앞의 명제를 다르게 unify해서 성공할 가능성이 있는지 backtracking을 시도한다.
      4. 앞의 명제 !은 두번째로 평가될 때에는 스스로 실패할 뿐 아니라 더 이상의 backtracking도 모두 금지한다. 즉 이 query는 무조건 실패한다. (명제의 참값이 거짓이 되며, 인터프리터는 no.라고 표시해준다.)

  • 반면 not(grandfa(mary,john)). 을 query로 주면 다음과 같이 연산이 일어난다.

    1. 첫번째 선언과 query를 unify 해본다. A=grandfa(mary,john).
      1. A는 grandfa(mary,john)이고 이 명제는 거짓이므로 첫 번째 선언은 실패한다.
    2. 두번째 선언과 query를 unify 해본다. _는 anonymous variable로, 모든 structure와 unify될 수 있다. _=grandfa(mary, john). 이 명제에는 필요조건명제가 없으므로 성공한다. 즉 이 query는 참이다.

5. 인터프리터 및 개발도구

  • [http]SICSTUS Prolog prolog의 표준을 선도하는 대표주자(?). 단지 위에서 예시한 not이나 concat등을 모듈로 제공하지 않아서 일일이 구현해서 써야 한다는 불편함이 있다.
  • [http]SWIProlog 오픈소스와 Lesser GNU Public License를 채택한 인터프리터. 리눅스와 윈도우, Mac 등의 플랫폼에 포팅되어있다는 장점이 있다.
  • [http]swiprolog-c++ CppLanguage 와 prolog 를 함께 사용할 수 있게 만든 환경. 안써봐서 뭔지는 모르겠다 @_@
  • [http]JLog JavaLanguage안에서 사용할 수 있는 PrologLanguage인터프리터. Java Applet으로 된 예제를 제공한다.
  • [http]GNU Prolog GNU Prolog is a free Prolog compiler with constraint solving over finite domains developed by Daniel Diaz.



"; if (isset($options[timer])) print $menu.$banner."
".$options[timer]->Write()."
"; else print $menu.$banner."
".$timer; ?> # # ?>