2016-01-21 3 views
0
aminoseq(X) :- 
    aminoseq(X, []). 

aminoseq([], X) :- 
    print(X). 
aminoseq([A|B], X) :- 
    aminotodna(A, Y), 
    append(X, Y, Z), 
    aminoseq(B, Z). 

Этот код Пролога позволяет пользователю входить в список и объединяет этот список с предварительно заданным аминоточным списком и отображает оба результата. Я не понимаю, какая часть делает то, что ... Я хотел бы знать для будущей работы. Любая помощь приветствуется.Может кто-нибудь объяснить этот код Пролога

+2

Знаете ли вы пролог? –

ответ

2

Прежде всего, aminoseq/1 вызывает aminoseq/2, подразумевая, что второй аргумент aminoseq/2 - это своего рода переменная состояния, начальным значением которой является пустой список.

Далее, aminoseq/2 рекурсивно обрабатывает первый аргумент, который является списком. Когда список становится пустым (я предполагаю, что это список аминокислот или что-то еще), он просто печатает второй аргумент. Это первый пункт aminoseq/2.

Далее, второй пункт aminoseq/2. Он пытается преобразовать аминокислоту A (текущий первый элемент в список первых аргументов) во что-то еще (ДНК, я думаю) и называет его Y. Затем он добавляет X (текущий аргумент состояния) к Y, давая Z, который затем повторяется с остальными элементами в списке аргументов.

Я не знаю много о биологии, но могу догадаться, что здесь предполагается, что вы хотите перейти в список аминокислот и получить список оснований ДНК. Это не эффектно эффективный подход (в частности, я ненавижу, что вы печатаете в конце aminoseq/2), но он выполнит эту задачу. Я бы рекомендовал вам изучить результат с помощью trace/0, чтобы узнать, что пытается сделать Prolog по ходу дела.

Какая часть делает что? Вся реальная работа ведется в aminotodna/2, которая является фактической таблицей, которая идет от аминокислот к кодонам. Остальная часть этого кода управляет структурой данных, списками.

Я хотел бы подойти к проблеме больше, как это:

amino_dna(gly, [g,g,g]). 
amino_dna(gly, [g,g,a]). 
% ... 
amino_dna(lys, [a,a,g]). 
% ... 
amino_dna(ser, [t,c,g]). 
amino_dna(pro, [c,c,c]). 

amino_acid_dna_sequence([], []). 
amino_acid_dna_sequence([Acid|Acids], [C1,C2,C3|DNA]) :- 
    amino_dna(Acid, [C1,C2,C3]), 
    amino_acid_dna_sequence(Acids, DNA). 

я нахожу это немного более прямым: меньше append/3 стучать вокруг и не переплетения I/O с логическими отношениями. И он может приводиться в обоих направлениях:

?- amino_acid_dna_sequence([lys,ser,pro], X). 
X = [a, a, g, t, c, g, c, c, c]. 

?- amino_acid_dna_sequence([lys,gly,pro], X). 
X = [a, a, g, g, g, g, c, c, c] ; 
X = [a, a, g, g, g, a, c, c, c]. 

?- amino_acid_dna_sequence(Aminos, [a,a,g,t,c,g,c,c,c]). 
Aminos = [lys, ser, pro] ; 
false. 
2

В дополнение к тому, что Даниил писал (+1), у меня есть следующие две небольшие точки:

  1. удалить _to_ из имен отношений. Поскольку чистое отношение может использоваться во всех направлениях, нет смысла использовать имя, которое подразумевает направление.

  2. всегда учитывайте при использовании списков . Они часто делают ваш код намного легче читать, так как они требуют меньше аргументов и имен переменных.

Поэтому я предлагаю:

amino_dna(gly) --> [g,g,g]. 
amino_dna(gly) --> [g,g,a]. 
% ... 
amino_dna(lys) --> [a,a,g]. 
% ... 
amino_dna(ser) --> [t,c,g]. 
amino_dna(pro) --> [c,c,c]. 

amino_sequence([]) --> []. 
amino_sequence([Acid|Acids]) --> 
    amino_dna(Acid), 
    amino_sequence(Acids). 

Пример запроса:

?- length(Ls, _), phrase(amino_sequence(As), Ls). 
As = Ls, Ls = [] ; 
As = [gly], 
Ls = [g, g, g] ; 
As = [gly], 
Ls = [g, g, a] ; 
As = [lys], 
Ls = [a, a, g] ; 
As = [ser], 
Ls = [t, c, g] ; 
etc. 

Обратите внимание на использование length/2 для справедливого перечисления.

+0

Хотел бы я подумать об этом! –

Смежные вопросы