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

Algorithmes et structures de données Discussion :

Voyageur de commerce ?


Sujet :

Algorithmes et structures de données

  1. #1
    Nouveau Candidat au Club
    Voyageur de commerce ?
    Bonjour à tous,

    Nouveau sur ce site qui m'a l'air vraiment très intéressant !

    J'ai besoin d'avoir un peu d'aide.

    Je cherche à résoudre le problème suivant :

    * Il y a 3 magasins dans une ville, M1, M2, M3
    * Je connais la liste des prix de tous les articles de ces magasins.
    * Je connais les coûts de transport entre les magasins et mon domicile et ceux inter magasin.
    * J'ai une liste de courses à faire.

    Quel est le circuit que je dois emprunter pour avoir la facture totale la plus basse ?

    ----

    Je pense que ce problème doit pouvoir se résoudre par un algorithme résolvant le problème du voyageur de commerce mais je n'en suis pas sur du tout car il y a le problème des prix des marchandises en plus...

    ----

    Merci de vos réponses

  2. #2
    Modérateur

    Bonjour,

    la première question est : comment souhaites tu résoudre ce problème ? De manière optimale, une heuristique, etc.

    Si tu veux que ce soit optimal, tu peux faire une recherche exhaustive. Sinon tu as tout ce qui est méta-heuristiques (taboo, recuit simulé).
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  3. #3
    Nouveau Candidat au Club
    Merci de la réponse...

    je pense que ce problème peut effectivement se résoudre par une énumération. Cependant, comme vous le savez tous très bien si le nombre de variables augmente on va vite arriver à un nombre de solutions très très important.

    Mon problème était de savoir si un algorithme de résolution du "voyageur de commerce" pouvait résoudre ce problème ou donner une valeur approchée de la solution optimale.

    En effet, il existe des différences notables entre un "voyageur de commerce" et ce problème :

    * La personne n'est pas obligée d'aller dans tous les magasins, et à mon sens l'optimal sera même plutôt souvent d'aller dans un seul.
    * Il y a des produits qui sont dans la liste de course et qui peuvent ne pas être présents dans tous les magasins.
    * Il y a le coût du trajet à prendre en compte qui vient s'ajouter au coût des articles.

  4. #4
    Rédacteur

    Etant donné que tu n'es pas obligé de passer par toutes les villes, les méthodes de résolution du voyageur de commerce ne s'appliquent pas en l'état.

    Tu peux toujours déterminer une liste de magasins à visiter par une heuristique de ton choix, puis déterminer le meilleur parcours entre ces magasins via un voyageur de commerce. Mais bien sûr le résultat sera biaisé puisque tu choisiras les magasins sans tenir compte du meilleur parcours entre ces magasins.

  5. #5
    Modérateur

    Citation Envoyé par chtrec Voir le message
    En effet, il existe des différences notables entre un "voyageur de commerce" et ce problème :
    pas tant que ça en fait. Je pense que l'on peut très facilement adapté tous les algorithmes de résolution d'un voyageur de commerce à ton problème.
    En fait, si on regarde, seul la fonction coût est légèrement différente, ainsi que la condition de fin qui ne s'intéresse pas au nombre de ville visitée, mais au nombre de vêtements en ta possession.

    Donc :
    - si le nombre de variable est raisonnable, une recherche exhaustive c'est toujours très bien.
    - sinon, les deux méta-heuristiques qui ont résolu le plus de voyageurs de commerce sont le recuit simulé (big boss de la discipline) et la méthode taboo (préférée depuis quelques année au recuit simulé pour sa plus grnade souplesse, fiabilité et sa facilité d'initialisation). Il y a aussi l'algorithme génétique, mais ce n'est pas le plus adapté au problème. Si tu es un peu joueur ou curieux, tu peux implémenter une colonie de fourmi.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  6. #6
    Nouveau Candidat au Club
    Pour khayyam90 :

    Tu peux toujours déterminer une liste de magasins à visiter par une heuristique de ton choix, puis déterminer le meilleur parcours entre ces magasins via un voyageur de commerce. Mais bien sûr le résultat sera biaisé puisque tu choisiras les magasins sans tenir compte du meilleur parcours entre ces magasins.


    Exactement... les deux choix ne sont pas indépendants mais plutôt très interdépendants. La différence de prix entre les magasins doit compenser le coût de transport entre ceux-ci.

    Pour Toto13

    pas tant que ça en fait. Je pense que l'on peut très facilement adapté tous les algorithmes de résolution d'un voyageur de commerce à ton problème.
    En fait, si on regarde, seul la fonction coût est légèrement différente, ainsi que la condition de fin qui ne s'intéresse pas au nombre de ville visitée, mais au nombre de vêtements en ta possession.
    Effectivement, la fonction coût est différente car elle doit ajouter le coût des articles à celui du transport et je retiens la condition de fin qui est le nombre d'articles...

    ----

    Si pour mes trois magasins j'ai 10 articles de sélectionnés, cela me fait 30 couples article/magasin (que l'on peut assimiler à des villes à visiter) et je peux associer des coûts entre eux, correspondant au coût de transport éventuels (0 si c'est le même magasin) plus le coût de l'article de départ (ou d'arrivée).

    J'ai fini mon parcours quand j'ai mon nombre d'articles et il ne faut pas oublier de rentrer à la maison

    ça doit le faire... Je vais donc regarder la méthode TABOO qui selon vous apparaît comme étant la plus intéressante par rapport à mon problème.

    ----

    Merci de votre aide. Je vous tiens au courant de la résolution.

    PS : bon, je sais c'est peut-être un peu trop demander mais y a t-il des TABOO libres d'utilisation et implémentés en VB ?

  7. #7
    Modérateur

    Bonjour,

    oui pour la Tabou. Il est vrai que c'est une méthode que j'affectionne, car elle est simple, efficace et particulièrement bien adapté à un problème binaire (dans un magasin tu prends ou non l'article).
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  8. #8
    Rédacteur/Modérateur

    J'arrive comme le carabinier des comédies italiennes mais ce problème se résoud aussi avec la bibliothèques de contraintes de Prolog.
    Le seul inconvénient, qui n'est pas négligeable loin de là, c'est qu'une partie du code est adaptée au cas particulier des 3 magasins et je n'ai pas encore trouvé comment le généraliser à N magasins, mais les résultats me paraissent intéressants.
    je donne le code pour ceux qui seraient intéressés.
    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
    :- use_module(library('clpfd.pl')).
    magasin :-
    	% 4 produits achetés dans 3 magasins
    	LP = [[11,  9,  1], 
    	      [10, 17, 19],
    	      [ 2, 10, 14],
    	      [30, 15, 20]
    	     ],
    	% Couts des déplacements vers les magasins
    	LD = [7, 5, 9],
    	% Couts des déplacements inter magasins
    	LC = [[0, 5, 7],
    	      [5, 0, 6],
    	      [7, 6, 0]],
    	magasin(LP, LD, LC, H, Prix),
    	writeln(H), writeln(Prix).
     
     
     
     
    % LP est une liste P listes de 3 Prix (un par magasin)
    magasin(LP, LD, LC, H, Prix) :-
    	% construction de la liste H des achats
    	% elle est de la forme
    	% [ [AM1,AM2,AM3], [BM1,BLM2, BM3]...]
    	% où les XMi valent 1 si le produit a été acheté dans ce magasin
    	% ou 0 sinon
    	length(LP, LenP),
    	length(H, LenP),
     
    	% initialisation du calcul des prix 
    	% PrixM contient le montant des achats dans chaque magasin.
    	maplist(init, LP, H, PrixM),	
    	% on calcule le prix 
    	sum(PrixM, #=, Prix1),
     
    	A #= 0,
    	% on regarde maintenant les magasins visités
    	% S contient le nombre d'articles achetés dans chaque magasin
    	add_list(H, [], A, [], S),
    	% S1 = [1,1,2],
    	maplist(recapitule, S, CS),
     
    	% on calcule mainteant le prix du trajet
    	etudie_trajet(CS, LD, LC, CT),
    	Prix #= Prix1 + CT,
    	% le labeling se fait avec une liste plate
    	flatten(H, FH),
    	labeling([min(Prix)], FH).
     
     
     
    % Calcule du nombre d'articles achetés dans un magasin
    add_list([], [], N, L, S) :-
    	reverse([N | L], S).
     
    add_list([], T, N, L,  S) :- 
    	A #= 0,
    	add_list(T, [], A, [N | L], S).
     
    add_list([[H]|T2], T3, N, L, S) :-
    	V #= N + H,
    	add_list(T2, T3, V, L, S). 
     
    add_list([[H, T0|T1]|T2], T3, N, L, S) :-
    	V #= N + H,
    	add_list(T2, [[T0|T1] | T3], V, L, S).
     
     
    % Pose une condition pour savoir si un produit
    % a été acheté dans ce magasin
    recapitule(C, CS) :-
    	C #> 0 #<==> CS.
     
    % Calcul du trajet en fonction des magasins visités
    % Rappel A, B, C valent  0 ou 1
    % C'est cette partie qui est difficilement généralisable à N magasins
    etudie_trajet([A,B,C], [C1,C2,C3], CL, PT) :-
    	PT #> 0,
    	CL = [[0, CL1, CL2],[CL1, 0, CL3], _],
    	A+10*B+100*C #= TT,
    	(   TT #= 1)   #<==> A1,
    	TT #= 10  #<==> A2,
    	TT #= 100 #<==> A3,
    	TT #= 11  #<==> A4,
    	TT #= 101 #<==> A5,
    	TT #= 110 #<==> A6,
    	TT #= 111 #<==> A7,
    	PT #= 2 * (A1 * C1 + A2 * C2 + A3 * C3) + 
    	      A4 * (C1+C2+CL1) + A5 * (C1+C3+CL2) + A6 *(C2+C3+CL3) +
    	      A7 * (C1+C2+CL2+CL3).
     
     
    % fonction d'initialisation de la liste des achats
    init(P, H, Prix) :-
    	length(P, LP),
    	length(H, LP),
    	% on achète ou pas
    	H ins 0..1,
    	% on n'effectue qu'un seul achat pour ce produit
    	sum(H, #=, 1),
    	% On calcule la somme 	
    	maplist(calcule, P, H, LPrix),
    	% on calcule la dépense
    	sum(LPrix, #=, Prix).
     
    % ici on calcule le prix
    % Si le PU = 0, celà veut dire que le 
    % produit n'est pas dans le magasin
    calcule(PU, Q, P) :-
    	PU #= 0, Q #= 0, P #= 0.
     
    calcule(PU, Q, P) :-
    	PU #\= 0, P #= PU * Q.
    Les magasins doivent être rangés du plus près au plus éloigné par rapport à l'endroit où l'on vit (calcul dans le cas où les 3 magasins doivent être visités), on doit pouvoir faire mieux là.
    "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

  9. #9
    Nouveau Candidat au Club
    Merci pour vos soutiens et vos recherches.

    En fait, mon objectif est d'implémenter une base access (ou autre, mais je sais assez bien me servir de celkle-ci ) avec les données :

    - des prix dans les différents magasins (couple article - fournisseur avec prix)
    - des distances inter-magasin

    et en fonction de la localisation de l'utilisateur et d'une liste de courses que celui-ci choisit, de lui trouver le meilleur parcours pour lui minimiser la facture. En ces temps de baisse du pouvoir d'achat, je trouve ça pas mal

    Intéressant non ... mais ça pose des tas de problèmes...

    - Le premier étant de trouver l'algoritme permettant de résoudre le problème (rapidement) avec une liste de courses "normale", c'est à dire une trentaine de références.
    - Le second de récupérer les données des supermarchés...
    - Le troisième d'implémenter un truc du type "mappy" pour trouver les distances entre le domicile de l'utilisateur et les diférents magasins, là aussi rapidement !
    - enfin le dernier d'héberger cela sur un site internet consultable et surtout actualisable (au niveau des prix) par tous.

    @++

  10. #10
    Membre actif
    Algo gé
    Salut,

    je suis un grand fan des algorithmes génétiques, mais j'avoue (et cela va signer mon manque d'objectivité) que je ne connais ni le recuit simulé ni taboo, ni même les colonies de fourmis. Je suis d'ailleurs curieux de découvrir ces méthodes.

    En tout cas avec un algorithme génétique, tu vas pouvoir résoudre ton problème quel que soit le nombre de magasin et les autres variables.

    Dans le principe le plus simple tu te fais une population de 10 candidats.
    Chaque candidat va faire un trajet compatible avec les contraintes obligatoires (faire les achats demandés).
    Au début ces trajets vont être aléatoires, ce qui va donner 10 points d'exploration dans l'espace des solutions.

    Ensuite tu évalues chaque candidat. Cette étape étant très importante, puisque la qualité des solutions dépendra directement de la qualité de ta fonction d'évaluation.

    Ensuite vient la phase de création et de modification des candidats :
    Tes 3 meilleurs candidats ne vont pas changer de solution. Appelons-les Or, Argent et Bronze.
    Les 3 suivants vont faire une mutation de leur solution, de faible pour le meilleur à forte pour le moins bon.
    Les solutions des 4 derniers candidats vont être renouvelées selon les propositions suivantes :
    - Une solution issue du croisement de Or avec Or
    - Une solution issue du croisement de Or avec Argent
    - Une solution issue du croisement de Or avec Bronze
    - Une solution issue de l'espace des solutions

    Cet algorithme génétique n'est pas le seul algorithme génétique disponible mais il est très efficace. Je l'ai développé spécifiquement pour un projet de création graphique où il sert à résoudre l'équation de la subjectivité de l'utilisateur.

    L'intérêt est qu'il grimpe régulièrement vers le sommet trouvé tout en veillant constamment à ne pas être sur un sommet local en recherchant toujours dans l'espace des solutions un meilleur sommet.

    Si la solution te semble intéressante, je la détaillerai. Tu peux l'observer fonctionnant dans la démo de mon projet sur mon site. C'est un algorithme très efficace qui supporte les changements d'espace de solutions.
    Il se mettra automatiquement à jour si les prix des magasins changent, si le cours de l'essence varie ou si un nouveau magasin apparait.

    Par contre, comme je le disais au début du message, je ne connais pas les autres algorithmes qui sont peut-être plus adaptés à tes besoins.
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle
    |
    | sylv.tournois.free.fr
    |

  11. #11
    Nouveau Candidat au Club
    Merci de ton aide

    Je suis en train de coder ce programme. Et j'ai choisi de le programmer avec un algorithme génétique.

    Mes données de base sont :

    * une liste de couples (Article/Magasin) avec les prix
    * les couts entre les différents magasins
    * Les couts Domicile / Magasins

    Le tout est stocké dans des tables ACCESS

    Il y a bien sur, une table ARTICLE et une table MAGASIN

    J'ai fini la première partie du programme qui est la création des individus de la population.

    l'algorithme est le suivant :

    Je crée N individus (N étant le nombre de couples) ayant chacun M gènes correspondant à un article.

    Le premier gène est un couple et les autres gènes sont sélectionnés au fur et à mesure en cherchant le couple le plus proche (avec le cout déplacement + prix article le plus faible).

    Je suis en train de programmer leur "reproduction" afin de faire évoluer... mais il me semble que la création de la population a déjà trouvé l'optimum... Il faut que je revois mes données pour ne pas avoir une solution trop évidente...

    Cela dit, J'ai sélectionné 10% de la population que je garderai, histoire de ne pas diverger et je fait reproduire tous les autres...

    L'idée de la reprodution étant la suivante :

    je prends un "pere" et une "mere", je cherche l'ordre des articles du père que je garde comme étant la base et à partir d'un indice défini, je copie les génes du père puis ceux de la mère.

    Ceci donne un hybride PereMere et je crée de la même manière un hybride MerePere.

    Je n'ai pas introduit de mutation, mais je compte bien le faire...

    Voilà j'en suis là. La reproduction fonctionne mais je n'ai pas encore programmé une succession de reproduction afin d'améliorer la population.

    Qu'en pensez vous ?

    ----

    Je vous tiens au courant quand ce sera plus avancé

    @++

  12. #12
    Inactif  
    De mémoire ça ressemble au multi-depot routing problem => programmation dynamique il me semble. Si tu as besoin de plus d'infos je me creuserai les méninges.

  13. #13
    Membre actif
    Salut,

    tu as l'air bien parti !
    Les algorithmes génétiques trouvent une solution acceptable très rapidement, c'est pourquoi ton algo trouve une solution aussi vite. Plus la population est grande, plus ça va vite, mais plus les calculs sont longs.

    L'intérêt de la mutation est de faire évoluer un chromosome qui approche de la solution mais n'y est pas.

    Tu as plusieurs types de mutations :
    - La mutation verticale fait muter un gène dans l'espace des gènes possibles
    - La mutation horizontale fait muter légèrement tous les gènes
    - La mutation en croix est une combinaison des deux précédentes

    Pour les algorithmes de croisement, je suppose que tu choisis alternativement un gène du Père et un gène de la mère. Comme tes gènes ont des valeurs définies et précises, tu ne pourras pas utiliser le croisement par moyenne de valeurs, qui apporte un mouvement génétique supplémentaire. En attendant, avec tes données tu as plein de façon de créer des enfants : première moitié père, seconde moitié mère ou l'inverse et tout type de croisement mélangeant judicieusement les gènes.

    Un exercice simple pour expérimenter les algo gé est de trouver ta couleur préférée ou de faire trouver au programme un nombre que tu as choisi.

    Si tu veux que les populations aient plus de difficultés à trouver la solution, augmente le nombre de magasin et ne les aide pas à optimiser leur trajet.

    Dans l'idéal tu devrais pouvoir obtenir un individu qui achète un article dans un magasin, puis le suivant à l'autre bout de la ville. Certes cet individu ne sera probablement sélectionné comme mère ou père de la génération suivante mais tu pourras avoir la surprise de voir des solutions qui optimisent les prix au point de sélectionner les bons magasins pour les prix et le trajet optimal entre eux.

    Tu fais quand même un problème difficile et deux étapes seraient peut-être nécessaires pour avoir des facilités de croisement génétiques tout en évitant les individus achetant deux fois le même article dans deux magasins différents ou autres erreurs de croisements.

    La façon de coder les données dans ton gène est ce qu'il y a de plus important. Si tu veux bénéficier de la puissance de croisement des gènes linéaires, tu devrais avoir un chromosome homogène dont chaque gène est interprété de la même façon au niveau des croisements et mutations. L'algorithme que j'ai codé dans mon projet est basé sur un chromosome décrit sous forme d'un tableau de nombres doubles.
    Du coup les croisement et mutations sont des calculs très simples et rapides.
    J'interprète ensuite ces nombres en fonction de leur position dans le chromosome de telle façon que toute valeur ait une signification.
    Il existe d'autres systèmes (chromosomes arborescents) mais je ne saurais pas t'en parler car je les trouve très complexes et je ne les connais pas.

    Dans ton cas chaque gène pourrait être un couple magasin/article comme tu le décris mais tu dois faire attention au codage des croisements et au chromosome résultat afin que ce dernier soit viable pour la pression environnementale que tu lui fais vivre. Renseignes-toi sur la théorie de Darwin et en particulier l'exemple de l'évolution de la girafe.

    Grosso-modo la girafe ressemblait au début à un cheval mais elle s'est retrouvée dans un environnement dont les arbres étaient grands. Les partisans de la génération spontanée (religieux pour la plupart) disent que la girafe est apparue avec un long cou spontanément. Darwin propose que les girafes les mieux adaptées à leur environnement étaient celles qui avaient le coup le plus long. Mangeant mieux que les autres, ces girafes étaient plus fertiles et leur descendance avaient un cou plus long. Petit à petit, les girafes au cou court n'eurent plus de descendance et celles dont le cou était plus long se reproduisaient, jusqu'à ce que le cou des girafes ait atteint la longueur optimale, solution de leur problème de nourriture. Note que la variation de longueur de cou va au-delà de l'écart entre les longueurs de cous des parents (comme la taille des enfants par rapport à la taille des parents pour nous humains). C'est à dire que la nature explore les solution au-delà des écarts proposés, pour trouver et expérimenter de nouvelles solutions.

    a+
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle
    |
    | sylv.tournois.free.fr
    |

  14. #14
    Inactif  
    [Hors sujet]
    Sauf que Darwin c'est plus trop à la mode hein...
    [/Hors sujet]

  15. #15
    Nouveau Candidat au Club
    Merci pour tous vos conseils.

    J'ai suivi la méthode "Or,Argent,Bronze" et ça marche...

    L'algorithme fonctionne. J'ai fait un test avec 5 articles et 4 magasins... ce qui donne quand même 20 couples et la solution est donnée assez rapidement, en moins de 20 itérations.

    Je vais concevoir un exemple un peu plus conséquent afin de voir le temps et le nombres d'itérations.

    @++

  16. #16
    Membre actif
    Citation Envoyé par Furikawari
    [Hors sujet]
    Sauf que Darwin c'est plus trop à la mode hein...
    [/Hors sujet]
    Je ne sais pas si Darwin est à la mode ou non, mais les algorithlmes génétiques sont un pur développement informatique autour de sa théorie sur l'évolution des espèces. J'ignore quelle théorie est actuellement à la mode dans ce domaine...

    Citation Envoyé par chtrec
    L'algorithme fonctionne. J'ai fait un test avec 5 articles et 4 magasins... ce qui donne quand même 20 couples et la solution est donnée assez rapidement, en moins de 20 itérations.
    bravo !

    J'ai une question : comment fais-tu le croisement des gènes ? Je me suis limité de mon côté à des gènes numériques pour la facilité de croisement, mais j'aimerais avoir d'autres points de vue.
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle
    |
    | sylv.tournois.free.fr
    |

###raw>template_hook.ano_emploi###