基于查询提取事实

时间:2015-05-27 08:56:17

标签: prolog

我在prolog->

中有这个事实和规则
amino(a,ala,alanine,[gca,gcc,gcg,gct]).
amino(b,asx,asparagine,[aac,aat]).
amino(c,cys,cysteine,[tgc,tgt]).

amino(A,B,C,[H|T]):-
    amino(A,B,C,[H|T]),
    amino(A,B,C,T).
我试图做的是搜索从给定密码子(列表)中找到的氨基酸的名称,单字母代码和3个字母代码。

当我查询

?-amino(A,B,C,[tgc|_]).

它给出了

A = c
B = cys
C = cysteine

所以这很好,因为tgc是列表的头部。但当我查询

?-amino(A,B,C,[gct|_]).
它不会给任何东西。我试图做的是在事实中搜索列表中的密码子,并打印出事实中的所有内容(除了其他密码子),所以我试图制作一个递归规则,从查询中检索整个事实在列表尾部提供了一个元素

2 个答案:

答案 0 :(得分:2)

如评论中所述,您在amino中有一个左递归的情况。 如建议的那样,您应该将memberchk与不同的谓词一起使用:

amino_codon([A,B,C],Codon) :-
    amino(A,B,C,L),
    memberchk(Codon,L).

(在列表中包装结果是可选的)。

但是,您的方法的正确版本将是:

amino_codon(A,B,C,L):- amino(A,B,C,L),!.
amino_codon(A,B,C,L):- amino_codon(A,B,C,[_|L]).

这样,您的查询可以与事实匹配,或者您尝试查找与子列表T的匹配。

如果你真的只想要一个谓词,你可以这样做:

amino(a,ala,alanine,[gca,gcc,gcg,gct]):-!.
amino(b,asx,asparagine,[aac,aat]):-!.
amino(c,cys,cysteine,[tgc,tgt]):-!.

amino(A,B,C,T) :- amino(A,B,C,[_|T]).

增加了削减,因为你只想找到一个匹配。

编辑:抱歉,上述条款中有错误,现在已经更正了。 关于削减:如果我们不添加削减,则会发生以下情况。 想象一下,在您使用上面的4个子句定义amino(A,B,C,[gcc|_])之后,您尝试匹配amino :(除非没有剪切):

  1. 前3个条款失败。
  2. 第4条说:为了匹配amino(A,B,C,[gcg|_]),让我们尝试找到amino(A,B,C,L)匹配的子句,以使L的尾部为T
  3. 第一个子句匹配,L[gca|T]T[gcc|_]
  4. 但是,你还有其他3个条款要试试!您将回溯并尝试将LT与其他子句匹配,这些子句将递归调用第4个子句,直到用尽所有可能的选择。 您在这里没有多个解决方案,即使您有,也只对返回一个解决方案感兴趣。
  5. 如果你的谓词没有剪切,那么调用谓词就必须调用once(amino(...)),或者使用剪切本身。请注意,可能需要将此类决定留给调用者,而不是明确地添加无用的剪切。

答案 1 :(得分:0)

在研究这个问题时首先想到的是:为什么列表表示?也许您可以使用位位置和Prolog 0b数字表示法来表示每个可能的密码子元素?然后,您可以简单地使用标准的按位运算符来查找密码子中是否存在给定元素,而不是在列表上进行O(n)搜索,这将使您能够独立于O(1)搜索的大小。密码子。在Prolog系统中实现第一个参数索引(即大多数索引),您将使用辅助表在密码子元素和相应的数字之间进行转换。如有必要,您也可以使用反向表。

P.S。我在这里假设密码子元素的顺序无关紧要......