IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Prolog Discussion :

Savoir s'il existe au moins un élément d'un certain type


Sujet :

Prolog

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut Savoir s'il existe au moins un élément d'un certain type
    Première question :

    Comment fait-on pour savoir s'il existe au moins un élément d'un certain type.
    Ce que j'ai pensé pour savoir s'il y avait au moins un contain :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    non_empty :-
    	contain(_,_),!.
    Y a-t-il une meilleure façon de faire ?

    Autre question : si on veut l'inverse d'une règle, on met '\(règle)' ?

  2. #2
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Citation Envoyé par Boubou Balrog
    Comment fait-on pour savoir s'il existe au moins un élément d'un certain type.
    Ce que j'ai pensé pour savoir s'il y avait au moins un contain :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    non_empty :-
        contain(_,_),!.
    Oui, c'est ça.

    Citation Envoyé par Boubou Balrog
    Autre question : si on veut l'inverse d'une règle, on met '\(règle)' ?
    Non, ce n'est pas cela du tout (et ce n'est pas aussi simple). Il faudrait que tu lises quelques tutos sur Prolog, en particulier:
    • introduction à Prolog (notamment le paragraphe sur l'opérateur \+ )
    • Prolog et l'algèbre relationnelle
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    Désolé d'avoir fait le boulet... J'avais raté la partie sur le \+ et j'avais vu la commande \+/1 dans le help et j'étais pas encore assez familier avec cette notation...
    J'avais pas non plus vu l'éditeur de swi...
    Par contre j'ai une question sur les listes et plus particulièrement sur un exemple du tutorial :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    % Elimination des cas d'erreur
    genereListeZeros(N, _) :-     % Cas N<0
      N<0,  !, fail. 
     
    % Execution dirigée
    genereListeZeros(N, []) :-    % Cas N=0
      N==0,
      !.
     
    genereListeZeros(N, [0|Q]) :-   % Les autres cas (N>0)
      !,
      N1 is N-1,
      genereListeZeros(N1, Q).
    Comment on fait appel à cette fonction ? je ne comprends pas non plus comment on crée une liste de cette manière... J'ai l'impression qu'on la parcoure simplement.

    En tous cas, merci de vos réponses.

  4. #4
    Membre expert

    Profil pro
    imposteur
    Inscrit en
    Avril 2003
    Messages
    3 308
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : imposteur

    Informations forums :
    Inscription : Avril 2003
    Messages : 3 308
    Points : 3 377
    Points
    3 377
    Par défaut
    Citation Envoyé par Boubou Balrog
    Comment on fait appel à cette fonction ?
    Ce n'est pas une fonction, c'est un prédicat. Tu vas faire la requête suivante, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    genereListeZeros(5, L).
    Et tu auras comme résultat l'unification suivante (condition de succès du prédicat) :
    L=[0, 0, 0, 0, 0]
    Citation Envoyé par Boubou Balrog
    je ne comprends pas non plus comment on crée une liste de cette manière... J'ai l'impression qu'on la parcoure simplement.
    En fait voilà ce que dit le programme, pour les trois cas :
    - le premier cas dit que le prédicat doit échouer (fail) si N est négatif
    - le deuxième cas dit qu'on a un succès si N est nul et si le deuxième argument peut être unifié avec la liste vide
    - le troisième cas dit qu'on a un succès si le prédicat réussit en l'appelant avec N-1, et en ajoutant un zéro à la liste ainsi récupérée.

    C'est une construction par récurrence : si N=0 on construit (on unifie le second argument avec) une liste vide, et si N > 0, on ajoute un zéro à la liste construite avec N-1.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    Pour les deux premiers cas, je comprends facilement. le 3ème, c'est le cas par défaut : c'est ce qu'on fait si les deux premiers ne sont pas 'acceptés'.
    Dans ce cas, il n'y a plus de condition, mais seulement une action, c'est bien ça ? On fait N-1 et on appelle le prédicat avec la liste avec une liste équivalente à la queue de la précédente liste.

    Dans ton exemple, ça voudrait dire qu'on commence par unifier L à une liste qui commence par un 0 et qui a une queue Q. Ensuit, on fait
    genereListeZeros(4, Q).... On fait ça itérativement jusqu'à ce que le nombre soit égal à zéro.
    Ensuite, on aura une liste L dont la tête vaut 0 et dont la queue a une tête qui vaut 0 et dont la queue a une tête qui vaut 0.... dont la tête vaut zéro et dont la queue a une taille nulle. C'est bien ça ? On se retrouve bien avec une liste de taille N avec que des zéros, mais c'est carrément barbare !!!

    Sinon, j'ai avancé dans mes recherches et je me demandais s'il étaient possibles d'effectuer des tests (genre findall) une fois qu'un prédicat avait échoué.
    Par exemple, je veux vérifier qu'un graphe est complet par rapport à certains paramètres (certains élément doivent avoir au moins un parent, d'autres au moins un enfant...) Si le prédicat répond NO, c'est pas idéal. Y a-t-il moyen de lui dire de me pondre une liste de tous les éléments qui ne remplissent pas ces critères ? Pourrait-il encore lancer d'autres prédicats qui proposeraient des solutions pour résoudre le problème (genre : relier machin à truc) ?

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    La question d'avant tient toujours, cela dit j'ai cherché à faire un truc très basique et ça ne marche pas : je voulais écrire qu'il n'y avait pas eu de problème quand le prédicat réussissait et écrire qu'il y avait eu un problème quand le prédicatavait raté...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    correct_model :-
    	non_empty, correct_arrows,
    	!,
    	write("AZaz019Le modèle n'a pas de problème de connexion apparent."),
    	nl.
     
    correct_model :-
    	!,
    	write("Le modèle a un problème.").
    Voilà la réponse que j'obtient :
    4 ?- correct_model.
    [65, 90, 97, 122, 48, 49, 57, 76, 101, 32, 109, 111, 100, 232, 108, 101, 32, 110, 39, 97, 32, 112, 97, 115, 32, 100, 101, 32, 112, 114, 111, 98, 108, 232, 109, 101, 32, 100, 101, 32, 99, 111, 110, 110, 101, 120, 105, 111, 110, 32, 97, 112, 112, 97, 114, 101, 110, 116, 46]

    Yes

    Je me souviens plus, mais c'est du code ASCII, non ? Je voulais mettre des ' et pas des ", mais avec les ' le write n'est pas reconnu et j'obtiens un SYNTAX ERROR... Vous savez pourquoi ?

  7. #7
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    les write se font avec des ', tu doubles les ' lorsque tu veux faire une apostrophe :

    write('AZaz019Le modèle n''a pas de problème de connexion apparent.')
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    Merci bien, j'aurais du le voir moi-même... Je devais être fatigué...

    En ce moment, j'essaye de changer mon petit code pour qu'il retourne les raisons de son échec... Comme il doit valider un schéma, ce serait bien qu'il puisse lister tous les problèmes. Le truc, c'est que lorsqu'il parvient à la première erreur, il suit la marche à suivre que je lui ai donné, puis il s'arrête. J'aurais voulu qu'il fasse tous les tests sur tous les éléments afin de trouver tous ceux qui ne sont pas conformes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
     
    % list of the components
     
    :- dynamic(community/1).
    :- dynamic(mgoal/4).
    :- dynamic(agoal/4).
    :- dynamic(belief/4).
    :- dynamic(joint/3).
    :- dynamic(contain/2).
     
     
     
     
    % Communities
     
    community(pcmarket).
    community(custemers).
    community(pcsellers).
     
     
    % Beliefs, M-Goals, A-Goal : (ID, parent, child, text) 
    % Joint Relationships : (ID,[parent list], [child list])
    % -> id6 pour l'exemple correct !!!
     
    mgoal(id1,null,id2,'text M-Goal1').
    mgoal(id5,null,id3,'text M-Goal2').
    mgoal(id6,id3,null,'text M-Goal3').
    belief(id2,id1,id3,'text belief1').
    belief(id4,null,id3,'text belief2').
    belief(id8,null,null,'Je pense que je suis beau').
    joint(id3,[id5,id2,id4],[id6]).
    joint(id7,[],[]).
     
    % What is in what
     
    contain(pcmarket,custemers).
    contain(pcmarket,pcsellers).
     
    contain(custemers,id1).
    contain(pcsellers,id2).
    contain(pcsellers,id3).
    contain(pcsellers,id4).
    contain(pcsellers,id5).
    contain(pcsellers,id6).
    contain(pcsellers,id7).
    contain(pcsellers,id8).
     
    % Rules
     
    write_type(X) :- belief(X,_,_,_),!, write('Belief').
    write_type(X) :- mgoal(X,_,_,_),!, write('M-Goal').
    write_type(X) :- agoal(X,_,_,_),!, write('A-Goal').
    write_type(X) :- joint(X,_,_),!, write('Joint Relationship').
     
    write_community(X) :- contain(C,X), write(C).
     
     
    message_missing_component(X,T) :-
    	!,
    	write('  - Le '), write_type(X), write(' ('''), write(T),
    	write(''') se trouvant dans la communauté '''), write_community(X),
    	write('''').
     
    message_missing_joint(X) :-
    	!,
    	write('  - Le '), write_type(X),
    	write(' se trouvant dans la communauté '''), write_community(X),
    	write('''').
     
     
    %Un belief/mgoal/agoal est un component. 
    component(V,X,Y,Z) :- belief(V,X,Y,Z).
    component(V,X,Y,Z) :- mgoal(V,X,Y,Z).
    component(V,X,Y,Z) :- agoal(V,X,Y,Z).
     
    %Un modèle doit contenir au moins une communauté.
    %Une communauté doit contenir un élément.
    %La suite est prise en charge par correct_arrows.
    non_empty :-
    	community(X),contain(X,_),!.
     
     
    %Tous les éléments ont au moins le minimum de flèches.
    correct_arrows :-
    	\+(isolated_element),
    	\+(missing_child_element),
    	\+(missing_parent_element),!.
     
    %Un belief/mgoal/agoal ne peut pas être isolé
    %Un jointrel non plus, mais lui doit avoir
    %au moins un parent et un enfant.
    isolated_element :- component(X,null,null,T),
    	!,
    	message_missing_component(X,T),
    	write(' ne devrait pas être complétement isolé.'),
    	nl.
     
     
    %Un belief/jointrel doit avoir un enfant.
    missing_child_element :- joint(J,_,X),length(X,L),L==0,
    	!,
    	message_missing_joint(J),
    	write(' devrait avoir un fils.'),
    	nl.
     
    missing_child_element :- belief(X,_,null,T),
    	!,
    	message_missing_component(X,T),
    	write(' devrait avoir un fils.'),
    	nl.
     
    %Un jointrel doit avoir un parent.
    missing_parent_element :- joint(_,X,_),length(X,L),L==0,
    	!,
    	message_missing_joint(X),
    	write(' devrait avoir un parent.'),
    	nl.
     
     
     
     
    %Vérifier que le modèle respecte les règles de bases.
    correct_model :-
    	non_empty, correct_arrows,
    	!,
    	write('Le modèle n''a pas de problème de connexion apparent.'),
    	nl.
     
    %Si le modèle a un problème, il faut lister les éléments qui
    %posent le problèmes avec leur texte.
    correct_model :-
    	!,
    	write('Le modèle n''est pas complet.'),nl,
    	write('Veuillez régler les problèmes listés ci-dessus.').
    Je me demande si j'ai fait fausse route et si je pourrais 'upgrader' mon code pour faire ce que je veux, ou s'il me faut simplement faire un findall sur tous les éléments avant de faire les différents tests...

    Je sais que ce code est long, j'espère que c'est pas un problème...
    Si vous voyez de graves problèmes d'optimisation ou de synthaxe, dites-le-moi...

  9. #9
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Citation Envoyé par Boubou Balrog
    Je sais que ce code est long, j'espère que c'est pas un problème...
    C'est pas un problème en soi... c'est juste que ça ne donne pas envie de le lire, c'est tout.


    Citation Envoyé par Boubou Balrog
    ...ou s'il me faut simplement faire un findall sur tous les éléments avant de faire les différents tests...
    Evite les findall quand ce n'est pas nécessaire. Un findall va te construire une liste, qui sera mise en mémoire. Si tu as beaucoup d'éléments, ça consomme de la RAM inutilement.

    Si c'est pour de l'affichage, un forall est plus approprié.


    Ce que tu peux faire (et que tu as en partie fait d'ailleurs), c'est écrire un prédicat qui te relève toutes les ionconsistances du modèle et te les retourne sous forme de tuples, par exemple (que tu peux afficher comme tu veux).

    Ainsi, tu peux faire cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    check_model :-
      \+ inconsistancy(_),
      !,
      write('Le modele ne comporte pas d'inconsistance').
     
     
    check_model :-
      !,
      write('Le modele comporte les inconsistances suivantes:'), nl,
      forall(
          inconsistancy(Inc)
      ,
        (
          writeInconsistancy(Inc),
          nl
        )
      ),
     
      fail.
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    Excellent, avec quelques modifs, ça marche super !!! Merci beaucoup !

  11. #11
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Citation Envoyé par Boubou Balrog
    Excellent, avec quelques modifs, ça marche super !!! Merci beaucoup !
    Et bien c'est super alors !

    Rappel des règles: n'oublie pas le bouton "Résolu" si c'est le cas.
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2006
    Messages : 48
    Points : 24
    Points
    24
    Par défaut
    Je ne pensais pas dire que le problème était résolu, car je pensais poser d'autres questions dans ce sujet... Elles portent sur différentes choses et elles sont plutôt nombreuses, alors ça me semblait être la meilleure solution...
    Sinon, c'est pas très grave, je ferai un autre sujet en temps voulu...

    En attendant, je voulais vous demander comment fonctionnait le mode debug de swi-prolog. Pas toutes les option, bien sûr. Mais, l'autre jour, j'avais réussi à suivre le déroulement de l'exécution d'une commande et je ne me rappelle plus comment j'avais fait... Il me semble qu'il faut taper la commande debug. , mais après...

  13. #13
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Citation Envoyé par Boubou Balrog
    Je ne pensais pas dire que le problème était résolu, car je pensais poser d'autres questions dans ce sujet... Elles portent sur différentes choses et elles sont plutôt nombreuses, alors ça me semblait être la meilleure solution...
    Ce n'est pas comme cela que ça marche ici.

    Bien sûr tu as des questions bien précises sur un problème bien particulier que tu penses n'intéressera personne (donc tu décides de tout regrouper en un seul sujet, pour ne pas polluer). Erreur !

    En effet, aussi particulier soit-il, ton problème peut intéresser d'autres personnes ayant un problème similaire ou équivalent. Dans ce cas, après une recherche Google il arrive qu'ils tombent sur le sujet en question. Si tu regroupes toutes tes questions en 1 seul sujet, le visiteur occasionnel aura à chercher dans plusieurs pages l'information qui l'intéresse (si toutefois elle s'y trouve !) alors que si tu ouvres 1 sujet par problème, le visiteur occasionnel pourra se dire "ce n'est pas l'info que je cherche, mais je vais chercher parmi les autres sujets du forum et les autres ressources de DVP".

    En ouvrant 1 discussion par problème, avec un titre adéquat, il est beaucoup plus facile de retrouver l'information qui nous intéresse parmi les anciens sujet. Ensuite, cela montre que la rubrique est active: il vaut mieux plusieurs sujets marqués [Résolu] plutôt qu'un forum ne contenant qu'une seule discussion ayant tendance à s'éterniser et qui n'est jamais résolue.

    Par conséquent, ce qu'il faut faire :
    1. ouvrir une discussion par problème
    2. mettre un titre évocateur
    3. ne pas oublier de mettre le tag [Résolu], si c'est le cas
    Citation Envoyé par Boubou Balrog
    Mais, l'autre jour, j'avais réussi à suivre le déroulement de l'exécution d'une commande et je ne me rappelle plus comment j'avais fait...
    Ouvre une nouvelle discussion avec un titre adéquat et on te répondra.
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. savoir s'il existe un <a href> dans div, elle meme contenue dans une div
    Par poupouille dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 20/02/2008, 21h33
  2. Réponses: 4
    Dernier message: 04/07/2007, 15h40
  3. [MFC/C++6] Savoir si imprimante existe
    Par Mirna dans le forum Visual C++
    Réponses: 1
    Dernier message: 19/08/2006, 17h37
  4. Savoir s'il existe un champ dans un schéma définit ?
    Par shadeoner dans le forum Requêtes
    Réponses: 4
    Dernier message: 10/04/2006, 11h39
  5. Comment savoir s'il existe un index sur ma table ?
    Par CDRIK dans le forum Langage SQL
    Réponses: 3
    Dernier message: 06/10/2004, 10h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo