IFT6802 -- Competition inter-agent


Approvisionnement de restaurants

Il s'agit de concevoir deux sortes d'agents: des Grossistes et des Restaurants qui cherchent a maximiser leurs profits.

Chaque jour les Restaurants doivent s'approvisionner en viande, fruits et legumes. La preparation de 6 repas exige 1 caisse de chaque sorte d'aliment et le restaurant charge $15/repas. Les frais fixes d'un restaurant sont de $200/jour et un restaurant peut preparer un maximum de 200 repas par jour.

Les Grossistes fournissent un seul type de produit qu'ils achetent des "producteurs" au debut de la journee. Ils achetent en lot de 10 caisses au cout de $50 + $80 par lot de 10 caisses. Les grossistes ont des frais fixes de $50/jour.

Les Restaurants peuvent aussi acheter directement des producteurs; mais ca leur coute $30/caisse.

Pour la competition, chaque equipe mettra en lice un restaurant et un grossiste. Nous simulerons 10 journees de 8 heures.

Evaluation de performance

Pour 4 points, on demande un court rapport sur le projet (2-5 pages). En particulier, la strategie que vous avez adopte pour vos agents et tout autre commentaire ou observations sur le projet.

De plus, pour chaque jour ou un agent (restaurant ou grossiste) fait un profit (ou reussit mieux que la moyenne), il gagne 0.5 points. Finalement, il y a deux competitions paralleles: celle des restaurants et celle des grossistes. Nous ferons le cumulatif du profit des 10 journees pour chaque agent. Le restaurant avec le maximum de profits recevra 8 points et le grossiste le plus performant recevra 8 points. Pour les agents moins performants, il y a deux facon de calculer les points et la formule la plus favorable sera employee:

1) selon le rang: le premier recevant 8 points, le 2ieme 7.5, etc... diminuant 
    de 0.5 point par place

2) selon le profit relatif au gagnant:  8 * (profit/profit_max)  [minimum = 0]

Protocole de la competition

Dans ce qui suit, nous specifions seulement les interactions qui concernent le controleur. Pour les autres negotiations, c'est a la classe a elaborer des protocoles par le mecanisme des RFC.

La competition aura lien dans une salle de machines au 3ieme etage du pavillon AA. Nous utiliserons la version la plus recente de JADE (3.0b)

1. Demarrage de plateforme

Au debut de la competition, le "main" container de Jade sera demarre sur une machine dont le nom sera donne aux participants

2. Demarrage des agents

Chaque equipe fera demarrer UN container avec son restaurant et son grossiste. Les agents s'enregistreront dans le DF avec les services suivants puis attendront le DEPART.
    Restaurant:  sd.setType("Restaurant")
    Grossiste:   sd.setType("Grossiste")
    
    Dans chaque cas, vous devez indiquer le nom de l'equipe avec:
    
       sd.setOwnership( "..." )
Les etapes qui suivent represente le deroulement d'une journee de 8 heures simulees. Ces etapes seront repetees 10 fois.

Le rapport de temps est le suivant: 30 secondes d'execution representent 1 heure d'operation.

3) Preparation de la journee: controle d'identite

Une fois toutes les equipes pretes, nous ferons demarrer le "controleur" qui va expedier a chaque participant un QUERY_REF dont le contenu sera "ping" et s'attendra a recevoir un message INFORM avec un "Pong" dans les 30 secondes suivantes.


    class Pong:
        typeAgent:  "Restaurant" ou "Grossiste" (String)
        owner:   Nom de l'equipe (String)

    NOTE: seul les agents qui repondent pourront enregistrer des contrats avec  
         le controleur.

4) Affectation des roles

Le controleur decide quel produit va etre vendu pas chaque grossiste et l'informe avec un message INFORM dont le contenu est

class Production: produit: String [ viande, legume, fruit ]

Note: les produits de chaque grossiste seront determine de facon aleatoire a chaque jour. Jamais, un grossiste ne serz en position de monopole.

5) Information de planification

Le controleur informe tous les participants du nombre de participants:
    INFORM:  Participants(
                n_restaurants,
                n_viandes,
                n_legumes,
                n_fruits:   int  
                inscrits: Set of AID )
A partir de ce moment, les agents peuvent commencer a echanger des messages sauf avec le controleur.

6) Debut de la journee

Une minute plus tard, la competition commence avec le premier "top" d'horloge, un INFORM:
    Top {  tournoi:   int            // # du tournoi
            jour:      int  (1..10)   
            heure:     int  (0..8 )
            transactions: set of Lot
         }
Le champ "transactions" donne la liste de toutes les offres acceptees (produit, quantite et prix) qui ont eu lieu durant l'heure precedente. Par contre, la liste ne dit pas qui etaient les participants.

Neuf (8) autres tels messages seront expedies a toutes les 30 secondes (representant une heure ).

  • Les grossistes peuvent passer des commandes d'approvisionnement durant les quatre (4) premieres "heures"
  • Apres le dernier message ( 8h00 ) aucune transaction ne sera enregistree.
  • Durant la journee, les agents interagissent avec le controleur pour l'approvisionnement des grossistes et la gestion des "contrats".
  • 7) Demande d'approvisionnement

    Ceci se fait avec un REQUEST. Selon FIPA, un REQUEST doit avoir comme contenu une "Action" avec deux champs denotant QUI (champ actor fait QUOI (champ action). Ici, le QUI est redondant (c'est le controleur) et le QUOI est un "AgentAction".
        REQUEST:   Action ( actor: AID quelconque,
                            action: AgentAction Provision
                                  {  produit:   String  [ viande,legume,fruit ]
                                     quantite:  Int 
                                  }
      Acceptable si:
         1) vient d'un agent "enregistre"
         2) pour un grossiste, le produit est celui qu'il est acredite a vendre
            et la quantite est un multiple de 10
    
        dans quel cas, on repond avec AGREE:  ( Action  TRUE )
        
      Sinon REFUSE:  ( Action  Probleme )
      
    Les Problemes sont representes par le "Predicate" suivant:
    
        Probleme:
            numero:   Int
            msg:      String
      
        Les messages possibles sont:
        
            0. "Agent non enregistre"
            1. "Offre incoherente"
            2. "Mauvais produit"
            3. "Pas un multiple de 10"
            4. "Trop tot"
            5. "Trop tard"
            6. "Agent illegal"
            7. "Offre introuvable"
            8. "Offre ne correspond pas"
            
            10. "Offre existe deja"
            
            99. "Autre raison"
        
    

    8) Gestion des contrats.

    Les agents sont libres de dialoguer et negocier comme ils veulent selon les protocoles etablis par RFC; mais le controleur est le seul agent officiel authorise a faire des transferts de fonds et de biens (achat/vente).

    Pour enregistrer une offre de vente ou d'achat, un agent expedie un REQUEST au controleur [Il devrait aussi l'expedier a son interlocuteur]. Le controleur fait subir une batterie de tests a l'offre. Si l'offre est semantiquement coherente, le controleur l'enregistre et ne fait rien d'autre. S'il y a probleme, le controleur, avise le proposeur avec un message de type Probleme tel que decrit plus loin..

    L'interlocuteur qui recoit copie d'une requete peut repondre par AGREE ou un REFUSE expedie au controleur; un des effet sera d'eliminer l'offre de la BD du controleur. Le proposeur peut aussi retirer son offre avec un CANCEL.

    Voici le format d'une offre:

            REQUEST
                content:  Action 
                   ( actor: ...
                     action:  Transfert ;
                   ) 
    
        AgentAction Transfert
        {   acheteur:  AID
            vendeur:   AID
            produit:   String  [ viande, legume, fruit ]
            prix:      Float
            quantite:  Int
        }
    
    L'expediteur du message doit apparaitre comme "vendeur" ou "acheteur" et le destinataire doit etre l'autre participant. Le champ conversationId de l'offre sert de CLE a l'offre. Les messages d'acceptation, de refus ou d'annulation devront employer le meme conversationId.
    Dans ce qui suit, on denote par offre le contenu du REQUEST: 
    
    
    == Le destinataire peut repondre en expediant au controleur:
    
        AGREE:   ( offre  TRUE )
        REFUSE:  ( offre  Probleme )
        
    

    == Tant que le destinataire n'a pas reagit, le proposeur peut annuler son offre en expediant au controleur :

        CANCEL:  offre   
    

    Les messages AGREE, REFUSE, CANCEL doivent avoir le ConversationId correspondant a l'offre.

    Si le message AGREE, REFUSE, CANCEL est valide, l'offre est retiree du carnet des offre en suspend du controleur et le controleur envoie un message d'information aux deux participants:

       INFORM: 
            Event
                typeMessage:  [ "agree", "refuse", "cancel" ]
                offre: Transfert
    

    S'il y a probleme avec un de ces messages le controleurrepond a l'expediteur avec:

        INFORM:  Probleme 
      
    
    

    9) Fin de journee.

    Le controleur expedie un INFORM avec un "Resultat" qui donne les profits de chaque participant ainsi que des details sur le montant des transactions
        Predicate Resultat:
            profit_grossistes:  Set de Concept Bilan
                                   agent:  AID
                                   profit:  Float
                                end
                                
            profit_restaurants:  Set de Concept Bilan
                                   agent:  AID
                                   profit:  Float
                                end
            
    
    Si la competition n'est pas finie, apres une minute, nous retournons a l'etape 3. Autrement, un dernier Resultat est expedie ou cette fois c'est les profits cumulatifs pour toute la competition.

    Communication entre les Restaurants et Grossistes

    1/ Demande de prix de vente

    Le Restaurant peut demander le prix courant d'un Grossiste et celui ci repond en retournant son catalogue.
        Resto --> QUERY_REF( "Catalogue" ) --> Grossiste
    
        Note: le contenu d'un QUERY_REF sera toujours un String
        
    
        Grossiste --> INFORM( Catalogue ) --> Resto
    
        Predicate Catalogue 
            produit: String [legume,fruit,viande]
            prix: Float
    
    Si un Grossiste a change ses prix de base, il peut en avertir les Restaurants; mais l'expedition repetitive d'information redondante sera percue comme du SPAM.

    2/ Negotiation

    La negotiation est initiee par les restaurants avec un PROPOSE. Le contenu d'un PROPOSE est le meme que celui d'un REQUEST mais represente une discussion et non une offre ferme.
        Resto --> PROPOSE( offre ) --> Grossiste
    
    ou une offre est implantee (selon les normes FIPA) par un object de Classe Action dont le champ "action" est un objet de type Transfert
        offre =  
            Action 
              ( actor: ...
                action:  Transfert ;
              ) 
    
        AgentAction Transfert
        {   acheteur:  AID
            vendeur:   AID
            produit:   String  [ viande, legume, fruit ]
            prix:      Float
            quantite:  Int
        }
    
    Suite a la reception d'un PROPOSE, un grossiste peut faire une contre-proposition en retournant un PROPOSE a son tour et la negotiation dure tant que les interlocuteurs s'echangent des PROPOSE.
        Resto --> PROPOSE( offre ) --> Grossiste
        Resto <-- PROPOSE( offre ) <-- Grossiste
           . . . 
    
    L'echange s'arrete des qu'un participant decide d'accepter ou de refuser. Voyons maintenant le format de ces messages.

    Une contre-proposition est tout simplement un PROPOSE avec des valeurs differentes pour le prix et/ou pour la quantite. Pour assurer la coherence et le suivi de la negotiation les champs acheteur, vendeur et produit d'une contre-proposition seront les memes que ceux de la PROPOSITION mais le proposeur change. Le champ replyTo doit correspondre au champ replyWith de la proposition a laquelle on repond.

    On refuse avec un REJECT-PROPOSAL( offre ).

    L'acceptation serait normalement un ACCEPT-PROPOSAL mais comme l'acceptation doit etre suivie d'un depot d'offre ferme avec un REQUEST ( Transfert ) au controleur, il parait plus simple d'employer comme message d'acceptation un seul REQUEST expedie et a l'interlocuteur et au controleur.

    Diagramme de séquence (partiel) du protocole de negociation
    Houcine Ben Ameur
    [ndlr: il manque le CANCEL et le INFORM non-solicite]

    Problemes

            0. "Agent non enregistre"
            1. "Offre incoherente"
            2. "Mauvais produit"
            3. "Pas un multiple de 10"
            4. "Trop tot"
            5. "Trop tard"
            6. "Agent illegal"
            7. "Offre introuvable"
            8. "Offre ne correspond pas"
            
            10. "Offre existe deja"
            
            99. "Autre raison"
    

    Ontologie

    Concepts:

        Concept Bilan
             agent:  AID
             profit:  Float   
             
        Concept Lot 
            produit:   String  [ viande, legume, fruit ]
            prix:      Float
            quantite:  Int
      
    

    Predicats:

        Predicate Catalogue 
            produit: [legume,fruit,viande]
            prix: Float
      
        Predicate Event
            typeMessage:  [ "agree", "refuse", "cancel" ]
            offre: Transfert
          
        Predicate Participants:
            n_restaurants,
            n_viandes,
            n_legumes,
            n_fruits:   int  
            inscrits: Set of AID )
    
        Predicate Pong:
            typeAgent:  "Restaurant" ou "Grossiste" (String)
            owner:   Nom de l'equipe (String)
    
        Predicate Probleme:
            numero:  Int
            msg:  (String)
    
        Predicate Production:          // Utilise comme contenu de INFORM
            produit: String [ viande, legume, fruit ]
    
        Predicate Resultat:
            profit_grossistes:  Set de Concept Bilan
                                   agent:  AID
                                   profit:  Float
                                end
                                
            profit_restaurants:  Set de Concept Bilan
                                   agent:  AID
                                   profit:  Float
                                end
            
    
        Predicate Top:
            tournoi:   int            // # du tournoi
            jour:      int  ( 1..10)   
            heure:     int  ( 0..8 )
            transactions: set of Lot
    

    Actions:

        AgentAction Provision
            produit:   String  [ viande,legume,fruit ]
            quantite:  Int 
    
        AgentAction Transfert
            acheteur:  AID
            vendeur:   AID
            produit:   String  [ viande, legume, fruit ]
            prix:      Float
            quantite:  Int
    

    Competition Policies

    Beyond the rules of the game itself, competition organizers reserve the right to disqualify agents violating the spirit of fair play. In particular, the following behaviors are strictly prohibited:
  • - Trading designed to benefit some other agent at the expense of the trader's own utility.
  • - Communication with the agent during a game. Agents may obtain runtime game information only via the defined auction API.
  • - Denial-of-service attacks. Agents may not employ API operations for the purpose of occupying or loading the game servers.
  • En particulier, ceci veut dire que vos agents ne doivent pas accorder un regime special a des agents dont l'identite a ete predeterminee ni utiliser des messages "prives".

    Jean Vaucher
    23 mars 2003
    

    Echeances

    1er tour:  mardi 15 avril 2003   (14h00)   
    Finale:    mardi 22 avril 2003   (14h00)   30 points
    
      Le rapport et les programmes doivent etre remis avant la Finale.
      Pour les sources des programmes utiliser:
    
        % remise ift6802 projet [ ...]
    

    version 1.6 (17 avril)

    - La description tient compte de 3 changements: - le conversationId remplace l'usage des ReplyTo/With - Des ce soir, avec la version 1.6 du Controleur, la liste des participants aura un autre champs donnant la liste des agents reconnus par le controleur: inscrits: Set of AID La version 1.6 du controleur expediera un dernier Resultat avec les profits cumulatifs de la competition apres l'envoi du Resultat de la derniere journee. Ceci signallera la fin de la competition. De plus, la liste des messages a ete mis a jour et des incoherences corrigees entre les champs d'objets dans le texte, dans l'annexe et dans le logiciel. Finallement, la section 8 sur la gestion des contrats a ete rendue plus explicite. Mais nous avons fait un effort pour ne rien changer (sauf pour conversationId). Votre code devra tenir compte du fait que certains comportements ne sont pas specifies et pour la robustess, vous devez prevoir le fait que divers participants peuvent interpreter les choses differemment.

    version 1.5 (12 avril)

    version 1.4.1 - 7 avril 2003
    
        - Corps du texte tient compte des changements a l'ontologie