- Vue d'Ensemble
- Architecture du Système
- Fonctionnalités Clés
- Installation
- Guide d'Utilisation
- Processus de Négociation
- Calcul des Scores
- API Backend
- Technologies Utilisées
- Structure du Projet
GDSS PROMETHEE est un système complet d'aide à la décision de groupe basé sur la méthode multicritère PROMETHEE II. Il permet à plusieurs décideurs de collaborer pour évaluer et sélectionner des actions/alternatives selon leurs propres critères et préférences.
- Faciliter la prise de décision collective dans des environnements multi-critères
- Agréger les préférences individuelles en une décision de groupe consensuelle
- Supporter un processus de négociation structuré avec mécanisme de renonciation
- Fournir une assistance IA pour l'analyse et les recommandations
┌─────────────────────────────────────────────────────────────┐
│ GDSS PROMETHEE SYSTEM │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ ┌──────────────┐ │
│ │ COORDINATEUR │ │ DÉCIDEURS │ │
│ │ (Streamlit) │ │ (Streamlit) │ │
│ └───────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ └─────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ BACKEND FLASK │ │
│ │ (API REST) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌─────────────┐ │
│ │ PROMETHEE │ │ CHATBOT │ │
│ │ ENGINE │ │ EXPERT IA │ │
│ └──────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
| Composant | Technologie | Rôle |
|---|---|---|
| Backend API | Flask + Flask-CORS | Serveur REST, gestion des projets, calculs PROMETHEE |
| Interface Coordinateur | Streamlit | Création de projets, gestion des matrices, supervision négociation |
| Interface Décideur | Streamlit | Évaluation des actions, participation à la négociation |
| Moteur PROMETHEE | NumPy + Pandas | Calculs multicritères (flux nets, agrégation) |
| Chatbot IA | Anthropic Claude API | Assistance contextuelle, analyse des classements |
| Stockage | JSON + CSV | Persistance des projets, matrices, résultats |
graph LR
A[Créer Projet] --> B[Charger Matrice]
B --> C[Configurer Décideurs]
C --> D[Lancer Analyse]
D --> E[Superviser Négociation]
E --> F[Résultats Finaux]
- Gestion Multi-Projets : Créer, modifier, supprimer des projets
- Import de Matrices : CSV/Excel ou création interactive
- Configuration Décideurs : Pondération normalisée automatique
- Processus de Négociation : Tours structurés avec seuil d'acceptation
- Agrégation des Scores : Formule GDSS pondérée
- Export de Résultats : CSV, JSON, historique complet
graph TD
A[Authentification] --> B[Charger Matrice]
B --> C[Configurer Préférences]
C --> D[Calcul PROMETHEE]
D --> E[Classement Personnel]
E --> F[Négociation]
F --> G{Consensus?}
G -->|Oui| H[Validation]
G -->|Non| I[Renonciation]
I --> H
- Accès Sécurisé : Authentification par nom unique
- Configuration Personnelle : Poids, seuils, directions des critères
- Classement PROMETHEE : Calcul automatique des flux nets
- Sauvegarde Auto : Classement persistant entre sessions
- Négociation Collaborative : Acceptation/refus des propositions
- Assistance IA : Analyse du classement, suggestions de décision
- Python 3.8 ou supérieur
- pip (gestionnaire de paquets Python)
- Navigateur web moderne
# 1. Cloner le dépôt
git clone https://github.com/votre-username/gdss-promethee.git
cd gdss-promethee
# 2. Créer un environnement virtuel
python -m venv venv
# 3. Activer l'environnement
# Windows
venv\Scripts\activate
# Linux/Mac
source venv/bin/activate
# 4. Installer les dépendances
pip install -r requirements.txt
# 5. Configuration (optionnel)
# Créer un fichier .env avec votre clé API Anthropic
echo "ANTHROPIC_API_KEY=your_key_here" > .envflask==2.3.0
flask-cors==4.0.0
flask-limiter==3.5.0
streamlit==1.28.0
pandas==2.0.0
numpy==1.24.0
plotly==5.18.0
requests==2.31.0
anthropic==0.7.0
# Terminal 1 - Démarrer le serveur Flask
cd backend
python backend.py
# Le serveur démarre sur http://127.0.0.1:5000Vérification : Accédez à http://127.0.0.1:5000/health → Status: healthy
# Terminal 2 - Interface Coordinateur
streamlit run frontend/coordinator_interface.py --server.port 8501
# Accès : http://localhost:8501┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 1 : CRÉER UN PROJET │
├─────────────────────────────────────────────────────────┤
│ • Nom du projet (unique) │
│ • Description (optionnelle) │
│ → Génération automatique d'un ID │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 2 : CHARGER LA MATRICE DE PERFORMANCE │
├─────────────────────────────────────────────────────────┤
│ Option A : Import CSV/Excel │
│ • 1ère colonne = Actions │
│ • Colonnes suivantes = Critères (numériques) │
│ │
│ Option B : Création Interactive │
│ • Nombre d'actions/critères │
│ • Saisie directe des valeurs │
│ • Modèles prédéfinis disponibles │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 3 : CONFIGURER LES DÉCIDEURS │
├─────────────────────────────────────────────────────────┤
│ Pour chaque décideur : │
│ • Nom unique (sensible à la casse) │
│ • Poids (normalisé auto pour Σwₖ = 1) │
│ │
│ Exemple : │
│ Marc_Dubois → w = 0.30 (30%) │
│ Sophie_Martin → w = 0.45 (45%) │
│ Paul_Durand → w = 0.25 (25%) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 4 : LANCER LA NÉGOCIATION (Optionnel) │
├─────────────────────────────────────────────────────────┤
│ • Seuil d'acceptation (ex: 75%) │
│ • Nombre max de tours (ex: 5) │
│ → Proposition automatique de la meilleure action │
└─────────────────────────────────────────────────────────┘
# Terminal 3 - Interface Décideur
streamlit run frontend/decider_interface.py --server.port 8502
# Accès : http://localhost:8502┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 1 : AUTHENTIFICATION │
├─────────────────────────────────────────────────────────┤
│ • URL Backend : http://127.0.0.1:5000 │
│ • ID Projet : fourni par le coordinateur │
│ • Nom Décideur : exact (sensible à la casse) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 2 : RÉCUPÉRATION MATRICE │
├─────────────────────────────────────────────────────────┤
│ • Chargement automatique depuis le coordinateur │
│ • Vérification des données │
│ → Matrice affichée │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 3 : CONFIGURATION PRÉFÉRENCES │
├─────────────────────────────────────────────────────────┤
│ Pour chaque critère : │
│ │
│ a) Direction │
│ • Maximize (Benefit) : plus = mieux │
│ • Minimize (Cost) : moins = mieux │
│ │
│ b) Poids wⱼ │
│ • Importance relative (0-10) │
│ • Auto-normalisé pour Σwⱼ = 1 │
│ │
│ c) Seuils │
│ • q (indifférence) : |Δ| ≤ q → indifférent │
│ • p (préférence) : |Δ| ≥ p → préférence stricte │
│ • Contrainte : p > q │
│ │
│ Import/Export CSV possible │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 4 : CALCUL PROMETHEE II │
├─────────────────────────────────────────────────────────┤
│ Calculs automatiques : │
│ │
│ 1. Préférences partielles πⱼ(a,b) │
│ • Fonction de préférence quasi-linéaire │
│ │
│ 2. Indice de préférence global π(a,b) │
│ π(a,b) = Σⱼ wⱼ × πⱼ(a,b) │
│ │
│ 3. Flux positif Φ⁺(a) │
│ Φ⁺(a) = 1/(n-1) × Σ_b π(a,b) │
│ │
│ 4. Flux négatif Φ⁻(a) │
│ Φ⁻(a) = 1/(n-1) × Σ_b π(b,a) │
│ │
│ 5. Flux net Φ(a) = Φ⁺(a) - Φ⁻(a) │
│ │
│ 6. Classement : tri décroissant par Φ(a) │
│ │
│ Sauvegarde automatique du classement │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 5 : RÉSULTATS & ANALYSE │
├─────────────────────────────────────────────────────────┤
│ Onglets disponibles : │
│ │
│ AGRÉGATION │
│ • Matrice P(i,j) des préférences globales │
│ • Heatmap interactive │
│ │
│ EXPLOITATION │
│ • Graphiques Φ⁺ et Φ⁻ │
│ • Plan (Φ⁺, Φ⁻) │
│ │
│ RANGEMENT │
│ • Podium (🥇🥈🥉) │
│ • Classement complet │
│ • Graphiques de distribution │
│ │
│ ANALYSE IA (optionnel) │
│ • Insights sur le classement │
│ • Alertes et recommandations │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ÉTAPE 6 : SOUMISSION │
├─────────────────────────────────────────────────────────┤
│ • Envoi du classement au coordinateur │
│ • Stockage des préférences individuelles │
│ → Prêt pour l'agrégation de groupe │
└─────────────────────────────────────────────────────────┘
Le module de négociation implémente un protocole structuré en tours avec mécanisme de renonciation.
graph TD
A[Démarrage Négociation] --> B{Proposer Action N°1}
B --> C[Recueillir Réponses]
C --> D{Seuil Atteint?}
D -->|Oui ≥ threshold| E[ SUCCÈS]
D -->|Non| F{Max Tours?}
F -->|Non| G[Action Suivante]
G --> B
F -->|Oui| H[ RENONCIATION]
H --> I[Identifier Meilleure Action]
I --> J[Calculer Manque]
J --> K[Solliciter Décideurs]
K --> L[Recueillir Renonciations]
L --> M{Seuil Atteint?}
M -->|Oui| E
M -->|Non| N{Décideurs Restants?}
N -->|Oui| O[Vague Suivante]
O --> K
N -->|Non| P[ ÉCHEC]
negotiation_config = {
"threshold": 75, # % minimum d'acceptation requis
"max_rounds": 5, # Nombre maximum de tours avant renonciation
"auto_evaluate": True # Évaluation automatique des réponses
}POUR chaque tour t = 1 à max_rounds :
1. PROPOSER action[t] (selon classement agrégé)
2. POUR chaque décideur Dₖ :
• Comparer action[t] avec son classement personnel
• Calculer position_pct = (1 - (rang - 1) / total) × 100
• DÉCISION :
- Automatique : IF position_pct ≥ seuil_auto → ACCEPTER
- Manuelle : décision libre
3. COMPTABILISER :
acceptations = count(décisions = "accept")
taux = acceptations / total_décideurs
4. SI taux ≥ threshold :
RETOURNER SUCCÈS (action[t])
5. SINON SI t = max_rounds :
PASSER À Phase 2 (Renonciation)
6. SINON :
t = t + 1
CONTINUER
ENTRÉE :
• best_action = action avec meilleur taux
• best_rate = taux d'acceptation de best_action
• required = ⌈threshold × total_décideurs / 100⌉
• current = nombre d'acceptations pour best_action
• missing = required - current
ÉTAPE 1 : Identifier Décideurs Cibles
rejecters = [D | D a refusé best_action]
wave_1 = rejecters[0:missing] # Première vague
remaining = rejecters[missing:]
ÉTAPE 2 : Solliciter Renonciations
POUR chaque décideur D dans wave_1 :
DEMANDER : "Acceptez-vous de changer votre refus en acceptation ?"
CHOIX :
• ACCEPTER → renonciation
• REFUSER → maintien position
ÉTAPE 3 : Évaluation Automatique
SI tous(wave_1) ont répondu :
new_acceptations = current + count(renonciations acceptées)
SI new_acceptations ≥ required :
RETOURNER SUCCÈS (best_action par renonciation)
SINON SI len(remaining) < (required - new_acceptations) :
RETOURNER ÉCHEC (décideurs insuffisants)
SINON :
# Vague suivante
still_missing = required - new_acceptations
wave_2 = remaining[0:still_missing]
RÉPÉTER ÉTAPE 2 avec wave_2
Configuration :
- 5 décideurs (D₁, D₂, D₃, D₄, D₅)
- Seuil = 80% → 4 acceptations requises
- Max rounds = 3
Tour 1 : Action A₁
- Acceptations : D₁, D₂ → 2/5 = 40% < 80% NO
Tour 2 : Action A₂
- Acceptations : D₁, D₃, D₄ → 3/5 = 60% < 80% NO
Tour 3 : Action A₃ (meilleure)
- Acceptations : D₁, D₂, D₄ → 3/5 = 60% < 80% NO
- Max rounds atteint → RENONCIATION
Renonciation - Vague 1 :
- Manque : 4 - 3 = 1 acceptation
- Rejecters : D₃, D₅
- Sollicités : D₃ (vague 1)
- Réponse D₃ : ACCEPTE YES
- Nouveau total : 3 + 1 = 4 ≥ 4 → SUCCÈS
Le score GDSS (Group Decision Support System) agrège les évaluations individuelles :
S(Aᵢ) = Σₖ₌₁ᵖ wₖ × φₖ(Aᵢ)
Où :
- S(Aᵢ) = Score GDSS global de l'action Aᵢ
- wₖ = Poids du décideur Dₖ (avec Σwₖ = 1)
- φₖ(Aᵢ) = Flux net calculé par Dₖ pour Aᵢ
- p = Nombre total de décideurs
Projet : Sélection de Fournisseur
Décideurs :
- Marc (w = 0.40)
- Sophie (w = 0.35)
- Paul (w = 0.25)
Actions : Fournisseur_A, Fournisseur_B, Fournisseur_C
Flux Nets Individuels :
| Action | Marc (φ₁) | Sophie (φ₂) | Paul (φ₃) |
|---|---|---|---|
| Fournisseur_A | 0.350 | 0.280 | 0.420 |
| Fournisseur_B | 0.180 | 0.410 | 0.210 |
| Fournisseur_C | -0.530 | -0.690 | -0.630 |
Calcul Score GDSS :
S(Fournisseur_A) = 0.40 × 0.350 + 0.35 × 0.280 + 0.25 × 0.420
= 0.140 + 0.098 + 0.105
= 0.343
S(Fournisseur_B) = 0.40 × 0.180 + 0.35 × 0.410 + 0.25 × 0.210
= 0.072 + 0.1435 + 0.0525
= 0.268
S(Fournisseur_C) = 0.40 × (-0.530) + 0.35 × (-0.690) + 0.25 × (-0.630)
= -0.212 - 0.2415 - 0.1575
= -0.611
Classement Final :
- Fournisseur_A (Score = 0.343)
- Fournisseur_B (Score = 0.268)
- Fournisseur_C (Score = -0.611)
Le coordinateur accède à un tableau détaillé montrant :
- Score GDSS par action
- Contributions individuelles (wₖ × φₖ)
- Graphiques : barres, distributions, box plots
- Export CSV avec détails complets
POST /projectsBody :
{
"name": "Supply Chain Analysis",
"description": "Sélection fournisseur Q4 2024"
}Response :
{
"status": "project_created",
"project_id": "abc123-def456",
"project": { ... }
}GET /projectsQuery Params : ?page=1&per_page=50&active=true
Response :
{
"projects": [ ... ],
"pagination": {
"page": 1,
"per_page": 50,
"total": 120,
"pages": 3
}
}GET /projects/{project_id}Response :
{
"id": "abc123",
"name": "Supply Chain Analysis",
"deciders_count": 5,
"submissions_count": 3,
"completion_rate": 60,
"matrix_exists": true
}POST /projects/{project_id}/matrixBody :
[
{ "action": "Supplier_A", "Price": 15000, "Quality": 8.5 },
{ "action": "Supplier_B", "Price": 18000, "Quality": 9.2 }
]GET /projects/{project_id}/matrixResponse :
{
"matrix": [ ... ],
"actions": ["Supplier_A", "Supplier_B"],
"criteria": ["Price", "Quality"],
"shape": [2, 2]
}POST /projects/{project_id}/config/decidersBody :
{
"deciders": [
{ "name": "Marc_Dubois", "weight": 1.5 },
{ "name": "Sophie_Martin", "weight": 2.0 }
]
}POST /projects/{project_id}/accessBody :
{
"decider_name": "Marc_Dubois"
}Response :
{
"access_granted": true,
"project_name": "Supply Chain",
"weight": 1.5
}POST /projects/{project_id}/submit_resultsBody :
{
"decider": "Marc_Dubois",
"weight": 1.5,
"preferences": { ... },
"results": {
"actions": ["A1", "A2"],
"results": [
{"action": "A1", "phi": 0.35, "phi_plus": 0.5, "phi_minus": 0.15},
{"action": "A2", "phi": 0.18, "phi_plus": 0.3, "phi_minus": 0.12}
]
}
}GET /projects/{project_id}/resultsResponse :
{
"submissions": [ ... ],
"aggregated": [
{"action": "A1", "phi_aggregated": 0.343, "rank": 1},
{"action": "A2", "phi_aggregated": 0.268, "rank": 2}
],
"summary": {
"total_submissions": 5,
"weights": { "Marc": 0.4, "Sophie": 0.35, "Paul": 0.25 }
}
}POST /projects/{project_id}/negotiation/startBody :
{
"threshold": 75,
"max_rounds": 5
}GET /projects/{project_id}/negotiation/statusResponse :
{
"status": "active",
"current_round": 2,
"proposed_action": "Supplier_A",
"current_responses": {
"Marc": { "decision": "accept", "decider_percentage": 85.5 }
}
}POST /projects/{project_id}/negotiation/responseBody :
{
"decider": "Marc_Dubois",
"decision": "accept",
"decider_percentage": 85.5,
"auto_threshold_used": 75
}POST /projects/{project_id}/negotiation/evaluateResponse :
{
"status": "success",
"selected_action": "Supplier_A",
"acceptance_rate": 80.0
}