2009-11-09 21 views
1

我知道如何遍歷Prolog中的列表來查找最大值,但是如果每個東西都是單獨的子句呢?例如,如果我有一羣貓和他們的年齡,我怎麼會找到最老的貓?由prolog子句定義的值的最大值

cat(sassy, 5). 
cat(misty, 3). 
cat(princess, 2). 

我的第一個想法是「嗯,最古老的貓是沒有老年人存在的貓」。但我無法真正把它翻譯成序言。

oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y). 

這仍然錯誤地匹配「薄霧」。什麼是正確的方法來做到這一點?有沒有什麼方法可以更直接地迭代幾年來選擇最大值?

回答

4

貓是最古老的,如果它是一隻貓,並且沒有比它更老的貓。讓我們寫在序言:

oldest(X):- cat(X, _), not(thereAreOlders(X)), !. 
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N. 

如果您請教:

?- oldest(X). 
X = sassy. 
6

一種方法是

oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY). 

您還可以使用SETOF/3以獲得所有的貓的列表,並從獲得最大。

+0

'^'做什麼?當我使用這個事實時,我得到了'未定義的過程:^/2只能作爲setof/3和bagof/3的第二個參數出現。' – daniel451

+1

'^'是一個存在量詞。看起來你的Prolog系統(SWI?)將其用於'setof/3'和'bagof/3'。在這裏你並不需要'Y ^',這只是一種習慣的方式來強調'Y'在否定之內存在量化(「沒有比Y更早的貓Y」)。 – starblue

+0

是的,SWI-Prolog。感謝您的解釋。據我所知,它確實沒有'Y ^'的作品。 – daniel451

-2

我不記得太多的Prolog,但我知道你不應該像使用命令式編程語言那樣考慮解決問題。

2

下面是通過所有的解決方案循環,永遠記錄解決方案,它比以前的最好,只有更好的解決方案。最後,返回最佳解決方案。

錄製使用assert/1完成,如果您的Prolog提供(SWI-Prolog),您也可以使用不可回溯的全局變量。

該方法的好處是每個解決方案只考慮一次,即複雜性O(n)。所以,即使它比starblue的解決方案看起來醜陋,它應該運行得更好。

% Data 
cat(sassy, 5). 
cat(misty, 3). 
cat(miisu, 10). 
cat(princess, 2). 

% Interface 
oldest_cat(Name) :- 
    loop_through_cats, 
    fetch_oldest_cat(Name). 

loop_through_cats :- 
    cat(Name, Age), 
    record_cat_age(Name, Age), 
    fail ; true. 


:- dynamic current_oldest_cat/2. 

record_cat_age(Name, Age) :- 
    current_oldest_cat(_, CAge), 
    !, 
    Age > CAge, 
    retract(current_oldest_cat(_, _)), 
    assert(current_oldest_cat(Name, Age)). 

record_cat_age(Name, Age) :- 
    assert(current_oldest_cat(Name, Age)). 


fetch_oldest_cat(Name) :- 
    retract(current_oldest_cat(Name, _Age)). 

用例:

?- oldest_cat(Name). 

Name = miisu 

Miisu是一個典型的愛沙尼亞貓的名字。 ;)

+0

這太難看了,我寧願使用setof,bagof或findall來獲得O(n)的複雜性。(我的單行和Juanjo的解決方案是O(n^2)。) – starblue

+1

好吧,醜可以隱藏在接口謂詞後面。 setof對結果進行排序,所以你不會得到O(n)的複雜性。隨着findall你遍歷解決方案兩次,一次建立一個列表(如果你有數十億貓甚至可能不適合內存),然後遍歷列表。實際上,測試所有建議的解決方案的速度和內存消耗是很酷的。 – Kaarel

0

從文體上看 - 這裏有幾種不同的方法(有些非常優雅,有些則更「可讀」)。如果你是初學者,選擇你自己的,首選的方式做事 - 但效率低下。

您可以稍後學習技術以提高效率。享受Prolog--它是一種美麗的語言。

+0

應該增加:SWI-prolog有一個很好的分析器,可以幫助你專注於昂貴的條款。嘗試一下 - profile(my_goal)。 –