5 votes

Comment appliquer le quantificateur universel en Prolog ?

Supposons que vous ayez un programme Prolog de diagnostic des maladies qui commence avec de nombreuses relations entre les maladies et les symptômes :

causes_of(symptom1, Disease) :-
    Disease = disease1;
    Disease = disease2.
causes_of(symptom2, Disease) :-
    Disease = disease2;
    Disease = disease3.
causes_of(symptom3, Disease) :-
    Disease = disease4.

has_symptom(person1, symptom1).
has_symptom(person1, symptom2).

Comment puis-je créer une règle avec l'en-tête "has_disease(Person, Disease)" qui renverra vrai si la personne a tous les symptômes de cette maladie ? En utilisant l'exemple ci-dessus, voici un exemple de résultat :

has_disease(person1, Disease).
   Disease = disease2.

6voto

Orbling Points 13319

Il existe probablement un moyen beaucoup plus simple de faire cela, car mes compétences en Prolog sont au mieux mineures.

has_disease(Person, Disease) :- atom(Disease),
    findall(Symptom, has_symptom(Person, Symptom), PersonSymptoms),
    findall(DSymptom, causes_of(DSymptom, Disease), DiseaseSymptoms),
    subset(DiseaseSymptoms, PersonSymptoms).

has_diseases(Person, Diseases) :-
    findall(Disease, (causes_of(_, Disease), has_disease(Person, Disease)), DiseaseList),
    setof(Disease, member(Disease, DiseaseList), Diseases).

A appeler comme suit :

?- has_diseases(person1, D).
D = [disease1, disease2, disease3].

El findall/3 est utilisé d'abord pour trouver tous les symptômes d'une personne, puis à nouveau pour trouver tous les symptômes d'une maladie, puis une vérification rapide pour voir si les symptômes de la maladie sont un sous-ensemble de ceux de la personne.

La façon dont j'ai écrit le has_disease/2 l'empêche de donner une liste de maladies. J'ai donc créé has_diseases/2 qui effectue une autre findall sur toutes les maladies qu'il peut trouver, en utilisant has_disease/2 comme chèque. A setof/3 L'appel est utilisé en dernier lieu pour obtenir des résultats uniques sur la liste des maladies et les ordonner par commodité.

NB. Le site atom/1 sur le has_disease/2 est juste pour s'assurer qu'une variable n'est pas passée pour Disease car cela ne fonctionne pas dans ce cas, du moins pas pour moi.

1voto

ShiDoiSi Points 4585

Vous aurez besoin d'un moyen pour interroger tous les symptômes, par exemple avec findall(S,cause_of(S,disease),SS) , donde SS sera la liste des symptômes de cette maladie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X