Prolog

2013-04-28 3 views
1

에있는 술어 지식 기반에서 가장 유사한 목록 찾기 나는 요소 목록을 가지고 있고 어느 특정/2 술어의 모든 인스턴스를 거쳐서 어느 것이 가장 높은 일치 번호인지 찾는 문제가있다. 그것의 명부에있는 성분. 구현면에서 지금까지 가장 높은 매치를 어떻게 업데이트하고 더 이상 존재하지 않을 때 멈추어야 하는지를 파악할 수 없습니다.Prolog

findAnswer(MyList, HighMatchNum,_):- 
    answer(X,Y), 
    myIntersection(MyList, Y, NUM), //handles a single instance check and returns how many elements match. 
    NUM > HighMatchNum, 
    findAnswer(MyList, NUM, answer(X,Y)). 

//Knowledge base 
answer(sample1, [a,b,c,d]). 
answer(sample2, [d,c,e]). 

답변

2

라이브러리 (aggregate이)가이 :

findAnswer(MyList, HighMatchNum, K) :- 
    aggregate_all(max(N, Key), 
       ( answer(Key, List), 
        myIntersection(MyList, List, N) 
      ), 
       max(HighMatchNum, K)). 

myIntersection(MyList, List, N) :- 
    intersection(MyList, List, L), 
    length(L, N). 

% Knowledge base 
answer(sample1, [a,b,c,d]). 
answer(sample2, [d,c,e]). 

?- findAnswer([a], C, K). 
C = 1, 
K = sample1. 

?- findAnswer([d,e], C, K). 
C = 2, 
K = sample2. 
1

간단히 말해서 솔루션에서 최대 값을 전파 할 수있는 방법을 알 수 없습니다.

:- dynamic maxval/1 
:- maxval(0). 

findAnswer(MyList, HighMatchNum) :- 
    answer(X,Y), 
    myIntersection(MyList, Y, NUM), %handles a single instance check and returns how many elements match. 
    NUM > HighMatchNum,    %If this fails, try other answer 
    retract(maxval(_), assert(maxval(X)),!, %else retract the previous value and assert the new one 
    findAnswer(MyList, NUM). 

마지막으로 maxval/1의 값을 maxval (X)로 확인하십시오. 이 알고리즘은 항상 실패하여 사용자 데이터베이스에서 솔루션을 얻을 수 있습니다. 문제는 구현과 관련되어 있으므로 논리를 확인할 수 있습니다. 그러나 그것은 적절한 대답을 주장 할 것이다. 항상 재귀 프로 시저에 대한 기본 사례를 구현해야한다는 것을 기억해야합니다.

+0

은 * 확실히 * 실패를 산출하고, 그 결과를 데이터베이스에 주장한다. 또한,'findAnswer'는 항상 모든'answer' 사실의 시작부터 시작됩니다. 비표준 솔루션을 사용할 수 있다면 SWI에서'nb_setval'을 'fail'과 함께 사용하여 선형 검색을 수행하는 것이 더 좋습니다. –

+0

확실히 실패합니다. 감사합니다. 필자는 두 가지 구현이있는 도우미 조건부를 추가하여 간단히 작동하게 만들었습니다. 하나는 findAnswer를 호출하고 실패하면 두 번째 값을 검색합니다. –

+0

예, 가능합니다. 이것은 검색의 여파를 다룬다. 나는 수색 그 자체에 그러나 언급하고 있었다. 'findAnswer'는 더 짧은 해결책을 따라 건너 뛰지 만, 현재 최대 값보다 긴 것을 찾으면'findAnswer'를 다시 호출하고 현재 가장 긴 대답이 아닌 새로운 첫 번째 대답부터 시작합니다. 그것이 내가 의미했던 것입니다. :) 흠,'findAnswer'에 대한 마지막 호출 전에 커팅을 삽입해야한다는 것을 알았습니다. –

2

최고를 찾으려면 전체 목록을 끝까지 찾아야합니다. 지금까지 최선의 결과를 이끌어 내고 추가 점수로 점수를 유지할 것입니다.

best_match(MyList,R-RN):- 
    findall(X, (answer(A,L), X=A-L), ALL), 
    ALL = [A-L|T], 
    myIntersection(MyList, L, N), 
    find_best(MyList,T,A,N,R,RN). 

find_best(_,[],A,N,A,N). 
find_best(MyList,[B-H|T],A,N,R,RN):- 
    myIntersection(MyList, H, K), 
    (K>N -> find_best(MyList, T, B, K, R, RN) 
    ;  find_best(MyList, T, A, N, R, RN). 

이렇게하면 가장 일치하는 이름과 점수가 산출됩니다.