返回

2016-01-12 45 views
0

我有一個謂語,這是事實,如果通過對這樣的列表,例如:返回

translatable([(dog,perro)], [(perro,hund)], [(dog,hund)]) 

手段 - 如果「狗」轉化爲「佩羅」和「佩羅」翻譯去「尋找」,那麼「狗」轉化爲「尋找」的確是事實。

以下是完整的代碼。返回/表明對第一構件 - 給定((A,B),一個)返回true,給出((A,B)中,X)返回X = A:

first((First, _), First). 

類似於 「第一」,但對於第二對成員:

second((_, Second), Second). 

如果在元組的列表中存在翻譯的單詞本返回true,並保存翻譯翻譯:(狗,翻譯,[(牀,CAMA),(狗,佩羅)

translation_exists(Word, Translation, [H|T]) :- 
    first(H, Word), second(H, Translation), !; 
    translation_exists(Word, Translation, T). 

並由此產生:

translatable(EnglishSpanish, SpanishGerman, EnglishGerman) :- 
forall(member(Pair, EnglishGerman), (
    first(Pair, Word), 
    second(Pair, ResultTranslation), 
    translation_exists(Word, Translation, EnglishSpanish), 
    translation_exists(Translation, ResultTranslation, SpanishGerman) 
)). 

該代碼正確返回true/false。 但是,爲什麼,給定 可翻譯([(狗,佩羅)],[(佩羅,hund)],X)。

它不返回X = [(dog,hund)]?


編輯 更具體的,實際的目標是: 找出如果說去年的字典裏翻譯對(並只)。 丹尼爾,非常感謝,我已經採納了你的建議成員函數 - 非常簡單,謝謝!這是我的所有代碼現在:

lastIsTranslatable(_, _, []). 

lastIsTranslatable(EngSpan, SpanGerm, [(Eng, Germ) | T]) :- 
    member((Eng, Span), EngSpan), 
    member((Span, Germ), SpanGerm), 

    % this is to protect endless [(dog,hund), (dog, hund), ...] 
    not(member((Eng, Germ), T)), 

    lastIsTranslatable(EngSpan, SpanGerm, T), 
    !. 

而且是,這個偉大的工程尋找真正的&假:

lastIsTranslatable([(a,b)], [(b,c)], [(a,c)]). 
lastIsTranslatable([(a,b)], [(b,c)], [(a,no)]). 

lastIsTranslatable([(a,b)], [(b,c)], X). 

結果是X = [],然後,擊中「;」 - 錯誤。爲什麼? 那麼,與跟蹤選項運行,我看到執行失敗的

not(member((Eng, Germ), T)) 

但除此之外,導致X將無休止地充滿(A,C),(A,C)......也許有是更好的辦法保護重複?

+0

要表示成對,請不要**使用逗號('A,B)'。相反,使用不同的函數,如「A-B」。 – repeat

+0

使用列表的'translatable/3'有什麼意義? – repeat

回答

1

的原因,主要是因爲EnglishGerman是未初始化,member/2是免費拿出可以列出它:

?- member((perro,X), List). 
member((perro,X), List). 
List = [ (perro, X)|_G18493911] ; 
List = [_G18493910, (perro, X)|_G18493914] ; 
List = [_G18493910, _G18493913, (perro, X)|_G18493917] ; 
List = [_G18493910, _G18493913, _G18493916, (perro, X)|_G18493920] 
... 

這是最直接的問題,但即使你改變的流數據我想你還是有問題:

translatable1(EnglishSpanish, SpanishGerman, EnglishGerman) :- 
    member((English,Spanish), EnglishSpanish), 
    member((Spanish,German), SpanishGerman), 
    member((English,German), EnglishGerman). 

注意,我贊成模式匹配的卻早您first/2second/2謂詞;我認爲這更清楚。

除了:如果你知道你的名單是具體的,你不希望產生多種解決方案,您可以使用memberchk/2來驗證一個元素,而不是存在的member/2;它更便宜和確定性。

這工作得更好(你得到的解決方案,反正),但你仍然得到更多的解決方案比你需要:

?- translatable1([(dog,perro)], [(perro,hund)], X). 
X = [ (dog, hund)|_G18493925] ; 
X = [_G18493924, (dog, hund)|_G18493928] ; 
X = [_G18493924, _G18493927, (dog, hund)|_G18493931] a 

一些東西,我們知道,我們的代碼不知道的是,的基數結果集應小於或等於我們輸入的最低基數;如果我有15個英語 - 西班牙語單詞和12個西班牙語 - 德語單詞,我的英語 - 德語結果中不能超過12個單詞。我們的代碼不知道的原因是因爲它試圖表現得像數學:我們的代碼基本上是說「對於英語 - 西班牙語的每個元素,如果存在西班牙語 - 德語的匹配元素,那也是英語德語「。這並不能告訴我們如何構建英語和德語!它只告訴我們一個關於英語和德語的事實,我們可以用英語 - 西班牙語和西班牙語 - 德語驗證!所以它很酷,但它不夠計算英語 - 德語。

除了:它是傳統的Prolog中使用a-b代替(a,b);如果Prolog在沒有的時候擁有元組,並且運算符的優先級可能會讓人感到困惑,那麼很容易讓人相信它。

那麼,我們該如何告訴Prolog如何計算英德?可能有很多方法,但我更願意使用select/3,因爲我們的集合基數約束(以及它將會收斂/停止的一般意義)將自然從計算中「消耗」輸入集合。

translatable2([], _, []). 
translatable2(_, [], []). 
translatable2([Eng-Span|EngSpanRem], SpanGerm, EngGerm) :- 
    (select(Span-Germ, SpanGerm, SpanGermRem) -> 
     translatable2(EngSpanRem, SpanGermRem, EngGermRem), 
     EngGerm = [Eng-Germ|EngGermRem] 
    ; 
     translatable2(EngSpanRem, SpanGerm, EngGerm) 
    ). 

基本案例應該是顯而易見的;如果我們不是英語 - 西班牙語或西班牙語 - 德語,那麼就沒有什麼可以計算的了。然後歸納案例將英語 - 西班牙語列表中的第一個項目剝離,並搜索匹配的西班牙語 - 德語翻譯。如果找到一個,就用它來建立結果;否則,它只會在剩餘的英語 - 西班牙語列表中出現。這樣,在每次迭代中,我們至少會丟棄該列表中的英文 - 西班牙文翻譯,並且我們會丟棄西班牙文 - 德文翻譯。所以看起來很直觀的可能是,這將工作和終止,而不會產生一堆額外的選擇點。

似乎這樣的伎倆:

?- translatable2([dog-perro], [perro-hund], X). 
X = [dog-hund] ; 
X = [dog-hund]. 

額外的結果存在是因爲我們打兩個終端的情況下,因爲這兩個列表成爲[];這並不具吸引力,但它也不是什麼可擔心的事情。

現在有一件事情要討論這個解決方案,它將前兩個參數視爲in-parameters,將最後一個視爲out-parameter,而對於這個參數並沒有什麼可做的。我不知道這對你是否有問題。 translatable/1不應該有此限制,但是因爲member((Spanish,German), SpanishGerman)發生在member((English,German), EnglishGerman)之前,因此它生成一個無限大的列表,實際搜索缺失的西班牙語 - 德語翻譯。

不過,感覺應該有可能提出一個通用謂詞,只要您提供這些輸入中的任意兩個就行。我能做到這一點,如果我知道,所有這三個列表是完整的,以相同的順序:

translatable3([], [], []). 
translatable3([X-Y|XYs], [Y-Z|YZs], [X-Z|XZs]) :- 
    translatable3(XYs, YZs, XZs). 

而且你可以看到它的工作就像這樣:

?- translatable3([dog-perro], [perro-hund], X). 
X = [dog-hund]. 

?- translatable3([dog-perro], X, [dog-hund]). 
X = [perro-hund]. 

?- translatable3(X, [perro-hund], [dog-hund]). 
X = [dog-perro]. 

但我不知道有足夠的瞭解你的限制知道這可能是一個合法的答案。我的懷疑是否定的,因爲語言不這樣工作,但誰知道呢?

無論如何,這是三種不同的方法;我希望他們中的一個對你有幫助!