[英]Return from Prolog predicate
我有一個謂詞,這是正確的,例如,如果傳遞了這樣的對列表,例如:
translatable([(dog,perro)], [(perro,hund)], [(dog,hund)])
意思是-如果“ dog”翻譯為“ perro”,而“ perro”翻譯為“ hund”,則“ dog”翻譯為“ hund”是正確的。
下面是完整的代碼。 返回/建議該對的第一個成員-給定((a,b),a)返回true,給定((a,b),X)返回X = a:
first((First, _), First).
與“第一對”相似,但對於第二對成員:
second((_, Second), Second).
如果元組列表中存在可翻譯單詞,則返回true,並將翻譯保存為Translation:(dog,Translation,[(bed,cama),(dog,perro)]
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。 但是為什么給定可翻譯([[dog,perro)],[(perro,hund)],X)。
它不返回X = [(dog,hund)]嗎?
編輯更具體地說,實際目標是:找出LAST詞典是否具有可翻譯對(且僅限可翻譯對)。 丹尼爾(Daniel),非常感謝,我采用了您建議的成員函數-簡化了,謝謝! 這就是我現在擁有的所有代碼:
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)無限填充...也許有更好的方法來防止重復?
究其原因,主要是因為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/2
和second/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中的常規做法是使用
ab
代替(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].
產生的額外結果是因為我們都擊中了兩種極端情況,因為兩個列表都變成了[]
; 這雖然沒有吸引力,但也沒有什么可擔心的。
現在,吸引人的是,該解決方案將前兩個參數視為內部參數,而將最后一個參數視為外部參數,那么您實際上無能為力。 我不知道這是否對您有問題; translatable/1
不應有此限制,但是因為member((Spanish,German), SpanishGerman)
發生在member((English,German), EnglishGerman)
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].
但是我對您的約束了解得不夠多,無法確定這是否是一個合理的答案。 我的懷疑不是,因為語言不能那樣工作,但是誰知道呢?
無論如何,這是三種不同的方法。 希望其中之一對您有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.