Prolog 基于在事实内部的列表中提供元素的查询检索整个事实
我在序言中有这个事实和规则->Prolog 基于在事实内部的列表中提供元素的查询检索整个事实,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). 我要做的是从给定的密码子(列表)中搜索氨基酸的名称、单字母代码和三字母代码 当我询问 ?-amino(A,B,C,[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,[H|T]):-
amino(A,B,C,[H|T]),
amino(A,B,C,T).
我要做的是从给定的密码子(列表)中搜索氨基酸的名称、单字母代码和三字母代码
当我询问
?-amino(A,B,C,[tgc|_]).
它给
A = c
B = cys
C = cysteine
这很好,因为tgc是榜首。但当我询问
?-amino(A,B,C,[gct|_]).
它什么也不给。我试图做的是让prolog搜索事实列表中的密码子,并打印出事实中的所有内容(除了其他密码子),因此我试图创建一个递归规则,从查询中检索整个事实,该查询提供了列表尾部的一个元素,如注释中所述,在
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]).
添加剪切是因为您只对查找一个匹配项感兴趣
编辑:对不起,上面的条款有错误,现在更正。 关于切割:如果我们不添加切割,则会发生以下情况。 假设您在定义了
amino
后,试图将amino(A,B,C,[gcc| |)]
与上述4个子句进行匹配(不带切割的除外):
氨基(A,B,C,[gcg| |)]
,让我们试着找到氨基(A,B,C,L)
匹配的子句,这样L
的尾部就是T
L
为[gca | T]
,T
为[gcc | |]
L
和T
与其他子句匹配,这些子句将递归调用第4子句,直到用尽所有可能的选择。
这里没有多个解决方案,即使有,也只对返回一个感兴趣如果谓词没有切割,则调用谓词必须调用
一次(氨基(…)
,或者使用切割本身。请注意,最好将此类决定留给调用方,而不要明确地添加无用的剪切。在研究此问题时,首先想到的是:为什么要使用列表表示?也许您可以使用位位置和Prolog0b
数字符号来表示每个可能的密码子元素?然后,不用对列表进行O(n)搜索,只需使用标准的位运算符来查找给定元素是否存在于密码子中,这将提供独立于密码子大小的O(1)搜索。在实现第一个参数索引(即大多数参数)的Prolog系统中,您将使用一个辅助表在密码子元素和相应的数字之间进行转换。如有必要,您还可以使用反向表格
另外,我在这里假设密码子元素的顺序并不重要…试试
?-氨基(A,B,C,D),memberchk(gct,D)。
啊,谢谢,这很有效。你能解释一下memberchk()的作用吗?memberchk(E,L)类似于once(member(E,L)),即检查E是否是L的成员,但不“返回”多个解决方案。它是在较低的级别上实现的,以获得最大的效率[tgc|!]
只匹配第一个元素为tgc
的列表,而您恰好拥有并成功了该列表[gct| |]
,一个以gct
作为其第一个元素的列表,与您的事实或规则中的任何列表都不匹配memberchk
允许您确定元素是否在列表中的任何位置。我建议你用不同于规则的方式来命名你的事实。目前,你有一个循环引用:amino(a,B,C,[H | T]):-amino(a,B,C,[H | T]),…
我认为‘amino(a,B,C,[H | T]):-amino(a,B,C,[H | T])不是一个好的代码,但我只是想不出什么规则来避免单态错误。不管怎样,谢谢。哇,谢谢!但是你能解释一下这里的切割的用法吗?我还在学习,所以我对剪切有点问题。哦,通过添加剪切,你只需节省时间,而不是在你已经得到goali used列表“分组”密码子时,用prolog在整个数据库中搜索更多答案。另外,prolog对我来说是非常新的,所以我真的不知道它有很多可用的东西。不过,你的建议听起来很有用,我会研究一下的,谢谢!