Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

retrieve the whole fact based on query providing an element in a list inside the fact

Tags:

prolog

i have this fact and rules in 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).

what im trying to do is to search for the name, single letter code and 3 letter code of the amino acid im trying to find from a given codon (the list).

when i query

?-amino(A,B,C,[tgc|_]).

it gives

A = c
B = cys
C = cysteine

so thats fine because tgc is the head of the list. but when i query

?-amino(A,B,C,[gct|_]).

it doesnt give anything. What im trying to do is to make prolog search for the codon in the list in the facts and print out everything in the fact (except the other codons) so im trying to make a recursion rule that would retrieve the whole fact from the query that provides an element in the tail of the list

like image 423
Dowakaday Avatar asked Nov 21 '25 13:11

Dowakaday


1 Answers

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).

(Wrapping results in a list is 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]).

That way, either your query is matched by a fact, or you try to find a match with sublist T.

If you really wanted to have only one predicate, you would do as follows:

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]).

Cuts were added because you are only interested to find one match.


Edit: sorry, there was an error in the above clauses, this is corrected now. About cuts: if we don't add cuts, then the following happens. Imagine you are trying to match amino(A,B,C,[gcc|_]) after you defined amino with the 4 clauses above (except without cuts):

  1. The first 3 clauses fail.
  2. The 4rd says: in order to match amino(A,B,C,[gcg|_]), let's try to find a clause where amino(A,B,C,L) matches, such that the tail of L is T.
  3. The first clause matches, with L being [gca|T] and T being [gcc|_].
  4. But, you have still 3 other clauses to try! You will backtrack and try to match L and T with other clauses, which will call recursively the 4rd clause until exhaustion of all possible choices. You don't have multiple solutions here, and even if you had, you are only interested in returning one.

If you left your predicates without cuts, the calling predicate would have to call once(amino(...)), or use a cut itself. Note that it might be desirable to leave this kind of decision to the caller and not explicitely add useless cuts.

like image 136
coredump Avatar answered Nov 23 '25 05:11

coredump