My database follows this format:
aminotodna (Amincoacid, [DNA sequence]).
Here are a few examples from the database:
aminotodna(a,[g,c,a]).
aminotodna(a,[g,c,c]).
aminotodna(a,[g,c,g]).
aminotodna(a,[g,c,t]).
aminotodna(c,[t,g,c]).
aminotodna(c,[t,g,t]).
aminotodna(d,[g,a,c]).
aminotodna(d,[g,a,t]).
aminotodna(e,[g,a,a]).
aminotodna(e,[g,a,g]).
aminotodna(f,[t,t,c]).
aminotodna(f,[t,t,t]).
Some aminoacids have multiple DNA sequences.
Here is my question, so in a given list of amino acids for example [d,c,e,f], how can I append their DNA sequences together and give all combinations, as some have more than one sequence.
If it was just two I could do it, it'd just be
listamino(X,Y) :-
aminotodna(X,L),
aminotodna(Y,M),
append(L,M,Z),
print(Z).
hitting ; gives all combinations.
I've tired doing it with a list, but this is my attempt, and it didnt work:
listamino([]).
listamino([H|T]) :-
aminotodna(H,L),
aminotodna(T,M),
append(L,M,X),
print(X).
listamino(T).
When describing lists with Prolog, always consider using DCG notation for convenience and clarity. For example, using a subset of your examples, I first use DCG rules to describe the correspondence (note that I am using a name that makes sense in all directions):
amino_dna(a) --> [g,c,a].
amino_dna(a) --> [g,c,c].
amino_dna(c) --> [t,g,c].
amino_dna(c) --> [t,g,t].
an then I again use DCG rules to describe the concatenation of such lists:
aminos([]) --> [].
aminos([A|As]) --> amino_dna(A), aminos(As).
Sample query:
?- phrase(aminos([a,c]), As).
As = [g, c, a, t, g, c] ;
As = [g, c, a, t, g, t] ;
As = [g, c, c, t, g, c] ;
etc.
No append/3, no additional variables, no additional arguments, no nonsense. Use dcg!
You need an extra parameter to keep track of the current combination:
; invoke a version of listamino which tracks the current combination of DNA sequences, which is initially empty
listamino(X) :-
listamino(X,[]).
; If there are no ore aminos, print the DNA seq list, and we're done
listamino([],X) :-
print(X).
; Otherwise, append the DNA for the first amino to our list, and process the rest of the mains
listamino([H|T],X) :-
aminotodna(H,L),
append(X,L,X2),
listamino(T,X2).
Related
Consider the following graph
and that it is described by the below Prolog term :
graph([connected(a,[b,c]), connected(b,[a,c]), connected(c,[a,b,d]), connected(d,[c]) ]).
I would like to define a predicate which transforms the above connections into a list of the corresponding pairs. In other words, a predicate which yields
[[a,b],[a,c],[b,c],[c,d]] for the above term-graph.
Could you please advise how to do it ?
My attempt so far is the following :
map 2-neighbor vertex to pairs :
map2ne(adjacent(H,[K|T]),Pair) :-
append([H],[K],L),
append([H],T,M),
append([L],[M],Pair).
This runs ok.
map 3-neighbor vertex to pairs :
map3n(adjacent(H,[K,L|T]),Pair) :-
append([H],[K],A1),
append([H],[L],A2),
append([A1],[A2],Z),
append([H],T,M),
append(Z,[M],Pair).
This also runs ok.
But when I try to extend it to n-neighbor vertex, then it fails :
mapmany(adjacent(H, [K|_]),Pair) :-
append([H],[K],L),
append(L,[],Pair),
mapmany(adjacent(H,[K|_]),M),
append(M,Pair,Pair).
And also the below fails, which was intented to map many n-neighbor vertices to pairs :
mapping(Map,Pairs) :-
select(X,Map,Y),
mapmany(X,PairX),
append([PairX],Pairs),
mapping(Y,Pairs).
If you're going to use a solution based on setof/3, I strongly recommend defining an auxiliary predicate. This predicate should define exactly what we want a set of. When we want to define "the set of all edges in the graph", mathematically we might say something like "Edges is the set of all Edge terms where Edge is an edge in Graph".
We can write this very directly as follows:
graph_edges(Graph, Edges) :-
setof( Edge,
graph_edge(Graph, Edge),
Edges ).
It remains to define graph_edge/2 itself. The core of this can be lifted from slago's solution:
graph_edge(Graph, Edge) :-
member(connected(V, Ns), Graph),
member(W, Ns),
edge(V, W, Edge).
The advantages of having this as a separate predicate are:
the setof call is easier to read
the predicate itself has a nice descriptive name
the predicate can be tested in isolation
the predicate can be reused
no ^ signs anywhere, which have no meaning in Prolog except for complicating setof calls that don't use an auxiliary predicate
no worrying about "existential quantification", which has no meaning in Prolog except for complicating setof calls that don't use an auxiliary predicate
There are too many flaws in your code:
The adjacency list defined by graph/1 is composed of terms of the form connected(Vertex, Neighbors); however, your code deals with an adjacency list of terms of the form adjacent(Vertex, Neighbors).
Predicate append/3 should not be used to create all lists; for example, instead of append([H], [K], L), you should use L = [H, K].
In Prolog, it is more idiomatic to represent a pair of items V and W as V-W, instead of [V,W].
By the answer you expect for the example given (i.e., [a-b,a-c,b-c,c-d]), a single term V-W (i.e., {V,W}) represents both the edges (V,W) and (W,V). So, to avoid redundancy, you must exclusively choose V-W or W-V to put in your answer (without loss of generality, you can choose the term where V precedes W).
To to create an edge, you can do the following:
edge(V, W, Edge) :-
( V #< W
-> Edge = V-W
; Edge = W-V ).
Examples:
?- edge(a, b, Edge).
Edge = a-b.
?- edge(b, a, Edge).
Edge = a-b.
To create all edges connecting a vertex V to its neighbors Ns, without duplicates, just ask:
?- V=a, Ns=[b,c,d], setof(E, W^Ns^(member(W,Ns), edge(V,W,E)), Edges).
V = a,
Ns = [b, c, d],
Edges = [a-b, a-c, a-d].
Notice that the construct Var^Goal tells setof/3 not to bind variable Var in Goal (in other words, indicates that Var is existentially quantified).
Generalizing this idea, we have:
graph_edges(Graph, Edges) :-
setof( Edge,
V^Ns^W^( member(connected(V, Ns), Graph),
member(W, Ns),
edge(V, W, Edge)),
Edges ).
graph([connected(a, [b, c]),
connected(b, [a, c]),
connected(c, [a, b, d]),
connected(d, [c])]).
Example:
?- graph(G), graph_edges(G, E).
G = [connected(a, [b, c]), connected(b, [a, c]), connected(c, [a, b, d]), connected(d, [c])],
E = [a-b, a-c, b-c, c-d].
LIBRARY UGRAPHS
In SWI-Prolog, a trivial solution would be to use the predicate edges/2 from library(ugraphs). Be careful though, because the representation of undirected graphs on which the predicate edge/2 is based is different from the one you are considering (an undirected graph in the library(ugraphs) is represented by a list of vertex pairs where the order of the vertices in these pairs matters). For example:
?- edges([a-[b,c], b-[a,c], c-[a,b,d], d-[c]], E).
E = [a-b, a-c, b-a, b-c, c-a, c-b, c-d, d-c].
So far I've done my fair amount of research and I've tried different methods, however even after reading multiple stack overflow answers and even a PDF from Addison Wesley, I can't find the way to do it. Here is the code
use_module(library(func)).
% importing library "func"
scale([c, d, e, f, g, a, b]).
scale(c, major, [c, d, e, f, g, a, b]).
scale(c, minor, [c, d, e_b, f, g, a_b, b_b]).
%1st attempt
search(note, scale):- scale(note, scale).
%2nd attempt
scaleOf(note, type_scale):- scale(note, type_scale).
on(item,[item|rest]).
on(item,[disregardHead|tail]):-
scale(tail),
on(item, tail).
%3rd attempt
fatherOf(father,type, son):- scale(father, type, sons), search(son, type, sons).
search(son, type, []):- !, fail.
search(son, type, [son|l]):- !, true.
search(son, type, [c|l]):- search(son, type, l).
What am I attempting? Simple, something that can iterate through the predicate scale(c, [c, d, e, f, g, a, b]). But I can't get it right.
Edit: I have multiple predicates because someone else suggested creating a predicate that would differentiate one scale from the other. I thought I could cram it inside any algorithm but I guess PROLOG is not that lenient :p
You can do that with member/2 [swi-doc]. This can be used to search, unify with a member, or generate a list.
So you can search with:
search(Note, Scale, Item) :-
scale(Note, Scale, Items),
member(Item, Items).
It is important that Note, Scale, Item and Items start with an Uppercase, since identifiers with a lower case are constants or functors. Identifiers with an uppercase are variables.
This will thus unify Item with the items in the list, for the given sample data we for example obtain:
?- search(c, minor, Item).
Item = c ;
Item = d ;
Item = e_b ;
Item = f ;
Item = g ;
Item = a_b ;
Item = b_b.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
aminoseq(X) :-
aminoseq(X, []).
aminoseq([], X) :-
print(X).
aminoseq([A|B], X) :-
aminotodna(A, Y),
append(X, Y, Z),
aminoseq(B, Z).
This Prolog code allows the user to enter in a list and combines that list with a preset aminotodna list and displays both of the results. I don't understand which part does what... I'd like to know for future work.
Any help is appreciated.
In addition to what Daniel wrote (+1), I have the following two minor points:
remove the _to_ from relation names. Since a pure relation can be used in all directions, it does not make sense to use a name that implies a direction.
always consider using dcg when describing lists. They often make your code a lot easier to read since they require fewer arguments and variable names.
I therefore suggest:
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).
Sample query:
?- 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.
Notice the use of length/2 for fair enumeration.
First off, aminoseq/1 invokes aminoseq/2, implying that the second argument to aminoseq/2 is some sort of state variable whose initial value is the empty list.
Next, aminoseq/2 is recursively processing the first argument, which is a list. When the list becomes empty (I assume it's a list of amino acids or something) it just prints the second argument. That's the first clause of aminoseq/2.
Next, the second clause of aminoseq/2. It tries to convert the amino acid A (the current first item in the first argument list) into something else (DNA, I guess) and calls it Y. Then it appends X (the current "state" argument) to Y giving Z, which it then recurs on with the remaining items in the list of arguments.
I don't know a lot about biology, but I can guess that what's intended to happen here is that you want to pass in a list of amino acids and get back a list of DNA bases. This is not a spectacularly efficient approach (in particular, I kind of hate that you print at the end of aminoseq/2) but it will do the task. I would recommend that you examine the output using trace/0 to see what Prolog is trying to do as you go.
What part is doing what? All of the real work is being done in aminotodna/2 which is the actual table that goes from amino acids to codons. The rest of this code is just managing the data structure, the lists.
I would approach the problem more like this:
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).
I find this a bit more direct: less append/3 banging around and no intermingling of I/O with logical relationships. And it can be driven in both directions:
?- 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.
Given the list as input (in the format mentioned below) , I need to get the output that is a simple list of lists, If the given input list is empty then the predicate should return an empty list,
Given the input
[[[a,b],[c]],[[d,e]],[[g,h],[j,k]],[[h,k,l,l]]]
I need to get the output
[[a,b],[c],[d,e],[g,h],[j,k],[h,k,l,l]]
I am having trouble performing recursion,
The code I tried is below,
function([],X):-append([],X,X).
function([Head|Tail],X):-
first(Tail,A),
append(Head,A,X),
removehead(Tail,C),
function(C,X).
where the predicates first returns first element of the list, removehead removes the first element of the list.
You make a fair attempt in the code you have shared. Here are the things that you need to improve:
The predicate name fucntion describes the fact that this predicate has one solution whenever the first argument is a list. This is typically done in the documentation, e.g. %! function(+Nested:list, -Denested:list) is det.
append([], X, X) is true by definition if X is a list, so it is superfluous here.
What are first/2, removehead/2? If you want to instantiate to the first element of a list, you can also write the clause head argument as [Head,A|C]. Then you also do not need to remove the head from Tail explicitly.
Once I make alterations based on the above I come up with the following code:
%! denest(+Nested:list, -Denested:list) is det.
denest([], []).
denest([H|T1], L):-
denest(T1, T2),
append(H, T2, L).
Example run:
?- denest([[[a,b],[c]],[[d,e]],[[g,h],[j,k]],[[h,k,l,l]]], L).
L = [[a, b], [c], [d, e], [g, h], [j, k], [h, k, l|...]].
Hope this helps!
I am working on a scenario in Prolog (eclipse) wherein I need a list structure to be reformatted.
I have a list of the form:
MyList = [a,b,c].
I was trying to see if I can flatten the list to a single element with all the commas replaced with the + operator.
So my result list would look like:
ResultList = [a+b+c]
which is a single element list. The length of the initial list is arbitrary.
I know prolog is not suited for such operations, but can this be done?
here it is, in standard Prolog. I think there should be no difference with Eclipse:
list_to_op([X,Y|T], [R]) :-
list_to_op(T, X+Y, R).
edit: bug noted by false
list_to_op([X], [X]).
list_to_op([X], R, R+X).
list_to_op([X|T], R, Q) :-
list_to_op(T, R+X, Q).
test:
?- list_to_op([a,b,c],X).
X = [a+b+c] .
The accumulator is required to give the appropriate associativity: the simpler and more intuitive definition
list_to_op1([X], X).
list_to_op1([X|R], X+T) :-
list_to_op1(R, T).
gives
?- list_to_op1([a,b,c],X).
X = a+ (b+c) .
If evaluation order is important, use list_to_op.
edit:
there is a bug: list_to_op([a,b],X) fails.
here the correction, as often happens, it's a simplification:
list_to_op([], R, R).
list_to_op([X|T], R, Q) :-
list_to_op(T, R+X, Q).
This may help
flatten_list(A,[B]) :- flatten_list_inner(A,B).
flatten_list_inner([A],A).
flatten_list_inner([H|T],H+Y) :- flatten_list_inner(T,Y).
The output is slightly different from what you wanted. It is currently [a + (b + c)]
How about this non-recursive version..
list_to_op(L, Res) :-
concat_atom(L, '+', Atom),
Res = [Atom].
?- list_to_op([a,b,c], X).
X = ['a+b+c'].
Edit: This works in Swi-prolog.. not sure about Eclipse.