繁体   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