2011-09-20 4 views
1

나는이 :지식 기반에서 임의의 술어를 가져옵니다. 예를 들어 프롤로그

upred(mary, have, knife). 
upred(john, have, sword). 
upred(sam, have, bowl). 
upred(sword, is, long). 

이 어떻게 임의의 술어를받을 수 있나요?

% call this and get random predicate as Pred 
get_random_pred(Pred) :- 
+1

다음과 같이 임의로 ...?! Pred에 대한 샘플 결과를 줄 수 있습니까? 술어의 인수는 어떤 값 집합에서 취해야합니까? – ThomasH

답변

5

웃기는 것, 최근에 나는 걱정 스러웠습니다. 동적 저장소에 의존하고 무작위로 얻을 수 있도록하려는 사실을 식별하는 부분적인 솔루션이 있습니다. 동적 저장소에 의존하기 때문에 메타 데이터 제작에 의존하기 때문에 나는 그것에 매료되지 않습니다. 메타 데이터는 unsynched 될 수 있습니다. 그러나, 귀하의 목적을 위해서는 충분할 수 있습니다. 또한 API를 완벽하게 포착하지는 않습니다. 왜냐하면 관심있는 사실의 "종류"가 무엇인지 실마리를 제공해야하기 때문입니다. 실제로는 괜찮습니까? 상황이 인 경우 사실은 다음 패턴 일치시 실패 할 수 있기 때문에 사실입니다.

기본 트릭은 =..을 사용하여 술어를 분해하고 asserta을 사용하여 각 사실을 색인 값으로 지정하는 것입니다. 이것을 더 잘 수행하기를 원한다면 Prolog가 내 random_fact의 세 번째 필드까지 색인을 생성하도록 지시하기 위해 색인 생성 지시문을 사용해야 할 것입니다. 작은 데이터베이스의 경우 (WordNet이 아님) 아마도 괜찮을 것이지만 큰 데이터베이스의 경우 성능이 필요할 것입니다.

% random_fact(Head, Instantiation, Index) 
:- dynamic(random_fact/3). 

% fact_count(Head, Count) 
:- dynamic(fact_count/2). 

% one big side-effect to make it possible to query for a random predicate 
prepare_randomization_metadata(Goal) :- 
    findall(Goal, Goal, Occurrances), 
    prepare_randomization_metadata(Occurrances, 0), 
    Goal =.. [Head|_], 
    length(Occurrances, N), 
    asserta(fact_count(Head, N)). 

prepare_randomization_metadata([], _). 
prepare_randomization_metadata([Goal|Goals], N) :- 
    Goal =.. [Head|_], 
    asserta(random_fact(Head, Goal, N)), 
    N1 is N+1, 
    prepare_randomization_metadata(Goals, N1), !. 

여기서 볼 수 있듯이 엔진은 기본적으로 주어진 목표를 달성하고 약간의 메타 데이터 데이터베이스를 구축하는 것입니다. Prolog를 잘 아는 사람이 나보다 더 잘할 수 있습니다. 그것을 사용하려면, 당신은 지금처럼 드라이브 :

random_fact(upred, upred(mary, have, knife), 0). 
random_fact(upred, upred(john, have, sword), 1). 
... 

이것은 당신이 프롤로그로를 통해 추론 할 수있는 무언가이다 :

?- prepare_randomization_metadata(upred(X, Y, Z)). 
true. 

이제 이런 식의 사실이있는 데이터베이스가 있습니다.

?- random_fact(upred, X, 1) 
X = upred(mary, have, knife) ; 
false. 

지금 get_random_pred 꽤 간단하지만, 우리는 우리가 원하는 사실의 "종류"정확히 식별 할 수있는 추가 인수가 필요합니다 : 두 번째 술어를 원한다면, 당신은 지금처럼 조회 할 수

get_random_pred(Head, Pred) :- 
    fact_count(Head, N), 
    % pick a random number between 0 and the # of facts we have for this pred 
    random(0, N, I), 
    random_fact(Head, Pred, I), !. 

프롤로그 (Prolog)와 함께 나에게 아직 여러 해결책이 있다고 생각하는 이유를 알려주지는 않았지만 끝났습니다. 그래서 끝 부분에 빨간 컷을 삽입했습니다. 그러나 여러 솔루션을 원한다면 그렇게하는 버전을 작성하는 것은 쉽습니다. 예를 들어

endless_random_facts(Head, Fact) :- repeat, get_random_pred(Head, Fact). 

:

?- get_random_pred(upred, X). 
X = upred(sword, is, long) ; 
X = upred(john, have, sword) ; 
X = upred(mary, have, knife) ; 
X = upred(john, have, sword) ; 
X = upred(john, have, sword) ; 

을 어쨌든, 나는 이것이 결함에도 불구하고, 도움이되기를 바랍니다. SWI-Prolog에서만 테스트했습니다.