Get the whole fact based on a query providing an item in a list inside a fact
I have this fact and rules in the prologue →
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).
what they are trying to do is search by name, one letter code and 3 alphabetic code, they try to find amino acids from a given codon (list).
when i request
?-amino(A,B,C,[tgc|_]).
He gives
A = c
B = cys
C = cysteine
so great because tgc is the head of the list. but when i request
?-amino(A,B,C,[gct|_]).
it gives nothing. What they are trying to do is to do a search prologue for a codon in the fact list and print everything in that (except for other codons), so they try to create a rule, recursion, to recover the entire fact from the query, provides an item in the tail of the list
source to share
As said in the comments, you have a case of left recursion in amino
. As suggested, you should use memberchk
with a different predicate:
amino_codon([A,B,C],Codon) :-
amino(A,B,C,L),
memberchk(Codon,L).
(The results of wrapping the list are optional).
However, the correct version of your approach would be:
amino_codon(A,B,C,L):- amino(A,B,C,L),!.
amino_codon(A,B,C,L):- amino_codon(A,B,C,[_|L]).
So either your query matches the fact or you are trying to find a match with the sublist T.
If you really wanted to have only one predicate, you would do the following:
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]).
Abbreviations added because you're only interested in one match.
Edit: Sorry, there was an error in the above suggestions, this is now fixed. On abbreviations: if we do not add abbreviations, then the following happens. Imagine trying to match amino(A,B,C,[gcc|_])
after you defined amino
with the four sentences above (other than no cuts):
- The first 3 sentences don't work.
- 4th says: to match
amino(A,B,C,[gcg|_])
, try to find a sentence whereamino(A,B,C,L)
matches, so the tailL
is equalT
. - The first sentence is the same as
L
[gca|T]
andT
[gcc|_]
. - But you have three other suggestions! You come back and try to match
L
andT
with other proposals, which will be called recursively 4th point to exhaust all possible options. You don't have multiple solutions here, and even if you did, you're only interested in returning.
If you leave the predicates without slices, the calling predicate will have to call once(amino(...))
or use the slicing itself. Note that it may be desirable to leave such a solution to the caller rather than explicitly adding useless shortcuts.
source to share
The first thing that comes to mind when examining this problem is: why list view? Maybe you can represent every possible codon element using bit position and Prolog number notation 0b
? Then, instead of doing an O (n) search on the list, you can simply use the standard bitwise operators to determine if a given element is present in a codon, which will give you an O (1) independent search by codon size. In a Prolog system that implements indexing of the first argument (i.e. most of them), you must use a helper table to translate between codon elements and the corresponding number. You can also have a reverse table if needed.
PS I'm guessing the order of the codon elements doesn't matter ...
source to share