簡體   English   中英

從Prolog謂詞返回

[英]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/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中的常規做法是使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM