2017-10-20 31 views
2

J'essaie de comprendre comment utiliser la récursivité sur les règles de somme et de somme.Comment compter et additionner récursivement dans Prolog

Je le fais généralement avec des listes, en utilisant findall et length ou findall et sum_list, mais je ne suis pas sûr que ce soit ma meilleure option dans tous les cas.

Ceci est mon approche des listes:

%person(name, surname, age) 
person('A', 'H', 22). 
person('B', 'G', 24). 
person('C', 'F', 20). 
person('D', 'E', 44). 
person('E', 'D', 45). 
person('F', 'C', 51). 
person('G', 'B', 40). 
person('H', 'A', 51). 

count_person(Total_count) :-   % rule to count how many person are. 
    findall(N, person(N, _, _), List), 
    length(List, Total_count). 

sum_ages(Total_sum) :-     % rule to sum all the ages. 

    findall(Age, person(_, _, Age), List), 
    sum_list(List, Total_sum). 

ou ici: https://swish.swi-prolog.org/p/cswl.pl

Comment dois-je faire cela en utilisant récursion?

Répondre

1

Vous devriez jeter un oeil à la bibliothèque (aggregate).

Par exemple:

count_person(Total_count) :- 
    aggregate(count, A^B^C^person(A,B,C), Total_count). 

ou la forme plus simple (essayer de comprendre la différence, il est aa bon moyen d'apprendre la base sur les variables quantification)

count_person(Total_count) :- 
    aggregate_all(count, person(_,_,_), Total_count). 

La bibliothèque a augmenté de la nécessité de simplifier l'implémentation des fonctions d'agrégation typiques disponibles en SQL (puisque Prolog est de nature relationnelle):

sum_ages(Total_sum) :- 
    aggregate(sum(Age), A^B^person(A,B,Age), Total_sum). 

Vous pouvez également obtenir des agrégats combinés dans une étape. La moyenne est facilement mis en œuvre:

ave_ages(Ave) :- 
    aggregate(t(count,sum(Age)), A^B^person(A,B,Age), t(Count,Sum)), Ave is Sum/Count. 

Si vous implémentez en utilisant count_person/1 et sum_ages/1, l'interpréteur scanner deux fois le but ...

1

Je n'ai pas une solution élégante. Mais vous pouvez contrôler avec retract et assert la récursion:

:- dynamic([person/3,person1/3]). 

count_person(N) :- 
    count_person(0,N). 

count_person(Acc,N) :- 
    retract(person(A,B,C)), 
    !, 
    assert(person1(A,B,C)), 
    N1 is Acc+1, 
    count_person(N1,N). 
count_person(N,N) :- 
    clean_db. 

clean_db :- 
    retract(person1(A,B,C)), 
    assert(person(A,B,C)), 
    fail. 
clean_db.