2013-04-28 49 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'來實現線性搜索。 – 2013-04-28 14:42:12

+0

它肯定會失敗,謝謝。我只是簡單地通過添加一個帶有兩個實現的助手謂詞來工作,一個會調用findAnswer,如果失敗,第二個會檢索值。 – 2013-04-28 14:53:25

+0

是的,這是可能的。這涉及搜索的後果。我指的是搜索本身。你的'findAnswer'跳過了可能的解決方案,但是當它發現一個比當前最大的解決方案長時,它會再次調用'findAnswer',它將從第一個答案開始重新開始,而不是從當前最長的答案開始。我正是這個意思。 :)嗯,我現在也注意到你必須在最後一次調用'findAnswer'之前插入一個剪輯。 – 2013-04-28 15:04:07

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). 

此產生的名稱和最佳匹配的成績。