【问题标题】:DNA Matching in PrologProlog 中的 DNA 匹配
【发布时间】:2017-04-20 20:59:46
【问题描述】:

我正在尝试学习基本的 Prolog。我已经阅读了一些关于列表、变量和 if/and 逻辑的基本结构的基本教程。我正在尝试做的一个项目是匹配 DNA 序列,以帮助了解其中的一些内容。

基本上我希望它匹配 DNA 序列的反向互补。

示例输出如下所示:

?- dnamatch([t, t, a, c],[g, t, a, a]).
true

虽然它很可能相对简单,但作为 Prolog 的新手,我目前正在弄清楚。

我首先定义了 DNA 对的基本匹配规则:

pair(a,t).
pair(g,c).
etc...

然后我将尝试以某种方式将其实现到列表中,但不确定如何使此逻辑适用于更长的序列列表。我不确定我尝试的开始是否是正确的方法。任何帮助将不胜感激。

【问题讨论】:

    标签: prolog


    【解决方案1】:

    由于您的关系是描述列表,您可以选择使用 DCG。您可以这样描述互补的核碱基:

    complementary(t) -->    % thymine is complementary to
      [a].                  % adenine
    complementary(a) -->    % adenine is complementary to
      [t].                  % thymine
    complementary(g) -->    % guanine is complementary to
      [c].                  % cytosine
    complementary(c) -->    % cytosine is complementary to
      [g].                  % guanine
    

    这对应于您的谓词对/2。要以相反的顺序描述键合序列,您可以这样进行:

    bond([]) -->            % the empty sequence
      [].                   % doesn't bond
    bond([A|As]) -->        % the sequence [A|As] bonds with
      bond(As),             % a bonding sequence to As (in reverse order)
      complementary(A).     % followed by the complementary nucleobase of A
    

    通过首先编写递归目标,然后将描述互补核碱基的目标描述到列表头部的目标,可以实现相反的顺序。您可以像这样使用短语/2 进行查询:

       ?- phrase(bond([t,t,a,c]),S).
    S = [g,t,a,a]
    

    或者您可以使用包含短语/2 的单个目标的包装谓词:

    seq_complseq(D,M) :-
      phrase(bond(D),M).
    

    然后查询它:

       ?- seq_complseq([t,t,a,c],C).
    C = [g,t,a,a]
    

    我发现带有 DCG 的列表的描述比相应的谓词版本更容易阅读。当然,以相反的顺序描述互补序列是一项相对容易的任务。但是一旦你想描述更复杂的结构,比如cloverleaf structuretRNA DCGs 就派上用场了。

    【讨论】:

    【解决方案2】:

    maplist/3 和reverse/2 的解决方案:

    dnamatch(A,B) :- reverse(B,C), maplist(pairmatch,A,C).
    

    【讨论】:

    • 感谢您的帮助,更多地查看 maplist 功能,这似乎是我所需要的,但我无法记住。
    【解决方案3】:

    如果你想避免遍历两次,你也可以这样做?

    rev_comp(DNA, RC) :-
        rev_comp(DNA, [], RC).
    
    rev_comp([], RC, RC).
    rev_comp([X|Xs], RC0, RC) :-
        pair(X, Y),
        rev_comp(Xs, [Y|RC0], RC).
    

    然后:

    ?- rev_comp([t,c,g,a], RC).
    RC = [t, c, g, a].
    

    这只是reversemaplist 的手工编码合并。这值得么?也许,也许不是。应该不会吧。

    现在我想了想,你也可以用 foldl 来反转,但现在你真的想反转,所以它比烦人更有用。

    rev_comp([], []).
    rev_comp([X|Xs], Ys) :-
        pair(X, Y),
        foldl(rc, Xs, [Y], Ys).
    
    rc(X, Ys, [Y|Ys]) :- pair(X, Y).
    

    但这比上面的解决方案更不明显,上面的解决方案仍然没有solution by @Capellic那么明显,所以也许你可以看看我写的代码,但请不要写这样的代码,除非你当然是在回答 Stackoverflow 的问题和想要看起来很聪明,或者想打动一个在大学里向你求助的女孩。

    【讨论】:

    • 我很想发布一个与您的第一个非常相似的解决方案,但我决定让它更容易。也许您可以查看 ILP(SWI 插件中的一些资源:aleph)但我还没有尝试过,抱歉(我的感觉是这在很大程度上可能是矫枉过正......)
    • @CapelliC 当然矫枉过正,我认为您的解决方案在 99 个案例中的 99 个中更好,也许只有您应该反转通常是基础的参数而不是反转逻辑变量,但这是细节。
    猜你喜欢
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 2013-04-10
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    相关资源
    最近更新 更多