2013-09-23 53 views
0

我的程序知識庫具有原子語句和規則,如序言如何防止重複回答

store(itemName, ProductType) 

例如:商店(iPhone5的,電話)

manufacturer(itemName, Company) 

例如:製造商(iPhone5的,蘋果)

查詢是要找出是否有製造超過2個不同產品類型的公司,所以蘋果將有Macbook,iPad和iPhone

這裏是我們的查詢:

?- store(ItemID1, ProductType1), manufacturer(ItemID1, Company), store(ItemID2, ProductType2), manufacturer(ItemID2, Company), store(ItemID3, ProductType3), manufacturer(ItemID3, Company), not ProductType1 = ProductType2, not ProductType1 = ProductType3, not ProductType2 = ProductType3.

它給出了正確的答案上市3個蘋果產​​品,但更迫切一次又一次給出了相同的答案。有沒有辦法阻止它?

注:我知道其他問題的其他答案,但不知道如何實現它們,因爲我對Prolog有限的知識並不確定這些答案是否適用於此問題。

注:對於這個問題我不能使用!->;運營商

+0

這功課?!你有什麼其他未公開的限制?! –

+0

那就是全部。對不清楚 – emanyalpsid

+0

'maplist(store,[I,J,K],[T,R,S]),maplist(製造商,[I,J,K],[C,C,C]), = R,R'= S,T'= S'更短。 –

回答

0

貼現的性能問題,你的核心問題似乎是,你看不同的產品類型,但對產品本身的變量。例如,對於假設的不同產品類型T1,T2,T3和類型T1的產品P1a P1b P1c,類型T2的類型P2和類型T3的產品P3,您可以得到(P1a,P2,P3),(P1b, P2,P3)和(P1C,P2,P3),從您的觀點來看,這些都是相同的。

爲了避免這種情況,您需要將(類型,產品)對與每種類型的單個產品對融合。如果您將代碼修剪到暴露問題的最小值(例如,price謂詞似乎不必要),併爲我們提供了實際的輸出結果,那麼您會得到更好的答案。

+0

我已將您的術語更改爲問題中使用的術語。你的解決方案對我來說並不合適:例如KB'商店(a,電話)。商店(B,電話)。製造商(A,諾基亞)。製造商(b,蘋果)。「(還有另外兩家蘋果產品):爲了找到蘋果解決方案,現在必須有'a'和'b'。 –

+0

@WillNess我不太清楚'a'手機('諾基亞手機')是如何相關的。 OP的查詢非常明確地有一個「公司」變量。在不存在切割的情況下,解集與獨立於合相的順序無關,因此在普通英文中,P1,P2,P3不同的(I1,I2,I3,P1,P2,P3,C)元組集合。多重性來源{P1,P2,P3,C}集合(不是元組)是包含I_i∈P_i(我的答案)和集合/元組排序(Daniel Lyons的答案)。 –

+0

我看過你的建議,好像'(a,phone)'和'(b,phone)'必須做成一個 - 「每種類型都有一個」......我不明白你的意思。 –

1

我認爲除了JB的建議之外,還有其他一些解決方法。一個俊俏的訣竅是加入了此信息查詢結束執行了ProductTypeN排序:

ProductType1 @> ProductType2, 
ProductType2 @> ProductType3. 

這將讓你的三大產品類型中的一種排列,省去您所看到的組合爆炸。

更復雜的技術將是使用setof/3來列舉解決方案。因爲它將所有的答案都作爲一個集合來產生,所以它必須對這些值進行排序,這樣就可以按照與俗氣的技巧基本相同的方式去除重複項。

more_than_two_product_types(Manufacturer) :- 
    setof(Manufacturer, T^manufacturer(T,Manufacturer), Manufacturers), 
    member(Manufacturer, Manufacturers), 
    setof(Type, Thing^(manufacturer(Thing, Manufacturer), store(Thing, Type)), [_,_,_|_]). 

這很複雜,所以讓我們來分解它。首先,這種情況下產生的製造商的列表:

setof(Manufacturer, T^manufacturer(T,Manufacturer), Manufacturers), 

setof/3元謂詞需要一個構造函數表達式,模板表達式,並返回結果列表。這一個將收集所有manufacturer(T, Manufacturer)的解決方案,並將它們收集到一個列表中。我們只對製造商的名稱感興趣,所以模板參數只是ManufacturerT^語法告訴setof/3Tmanufacturer(T, Manufacturer)中的自由變量,因此我們不在乎它實例化的是什麼。這是必不可少的,否則本身會爲每種類型生成一個解決方案,這不是我們想要的。

此行迭代廠家的新名單:

member(Manufacturer, Manufacturers), 

這種複雜的線路找到我們由製造商生產的所有類型的產品:

setof(Type, Thing^(manufacturer(Thing, Manufacturer), store(Thing, Type)), [_,_,_|_]). 

目標表達這裏的序列(manufacturer(Thing, Manufacturer), store(Thing, Type)) 。這就是說,找到這個製造商生產的Thing,然後找到那個東西的Type。同樣,Thing^語法表示我們並不在意事情是什麼,所以立即獲得所有的解決方案。與其將這個綁定到我們要處理的列表中,模板[_,_,_|_]與任何至少包含三個項目的列表相統一。我們並不在乎這些物品是什麼,所以它們都是空白的。測試在您的控制檯,看看它與統一:

?- [1,2,3] = [_,_,_|_]. 
true. 

?- [1,2] = [_,_,_|_]. 
false. 

?- [1,2,3,4] = [_,_,_|_]. 
true. 

這將產生至少三種解決方案,然後扔掉成功,或者如果它產生較少的失敗。你可以看到,有不止一種方法可以用Prolog對一隻貓進行皮膚處理。 :)

+0

您的第一個建議,'moreThanTwo(C): - maplist(store,[I,J,K],[T,R,S]),maplist(製造商,[I,J,K],[C, C,C]),T> R,R> S'仍然可以爲同一個「C」產生倍數。但它*是*很好;並且很容易投入到「setof」中。 –

+0

@WillNess是的 - 我想如果製造商有4個或更多的產品類型。我應該有一個更全面的測試數據庫。 –