[英]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.