Préférences et Théorie du Vote

Navigation: ← Tweety-8-Agent-Dialogues | Index


Objectifs pédagogiques

  1. Comprendre la représentation des ordres de préférence
  2. Découvrir les méthodes d’agrégation de préférences (théorie du choix social)
  3. Explorer les règles de vote classiques (Borda, Condorcet, Copeland)
  4. Comprendre le lien entre préférences et argumentation

Prérequis

Exécutez d’abord Tweety-01-Setup-Python.ipynb pour configurer l’environnement JVM.

Durée estimée : 30 minutes

Module TweetyProject couvert

  • org.tweetyproject.preferences - Ordres de préférence et agrégation
# --- Initialisation JVM Tweety + Outils Externes ---
print("--- Verification JVM Tweety + Outils ---")
jvm_ready = False

import jpype
import jpype.imports
import os
import pathlib
import shutil
import platform

# === Configuration COMPLETE des outils externes ===
EXTERNAL_TOOLS = {
    "CLINGO": "",
    "SPASS": "",
    "EPROVER": "",
    "SAT_SOLVER_PYTHON": "",
    "MARCO": "",
}

def get_tool_path(tool_name):
    """Retourne le chemin valide d'un outil ou None."""
    path_str = EXTERNAL_TOOLS.get(tool_name, "")
    if not path_str:
        return None
    if shutil.which(path_str):
        return path_str
    path_obj = pathlib.Path(path_str)
    if path_obj.is_file():
        return str(path_obj.resolve())
    if path_obj.is_dir():
        return str(path_obj.resolve())
    return None

# --- Auto-detection des outils ---
system = platform.system()
exe_suffix = ".exe" if system == "Windows" else ""

# 1. Clingo (ASP solver) - Tweety attend le REPERTOIRE
for cp in [shutil.which("clingo"), pathlib.Path(f"ext_tools/clingo/clingo{exe_suffix}"),
           pathlib.Path(f"../ext_tools/clingo/clingo{exe_suffix}")]:
    if cp and (isinstance(cp, str) or cp.exists()):
        parent = pathlib.Path(cp).parent if isinstance(cp, str) else cp.parent
        EXTERNAL_TOOLS["CLINGO"] = str(parent.resolve())
        break

# 2. SPASS (Modal logic prover)
for sp in [shutil.which("SPASS"), pathlib.Path(f"ext_tools/spass/SPASS{exe_suffix}"),
           pathlib.Path(f"../ext_tools/spass/SPASS{exe_suffix}")]:
    if sp and (isinstance(sp, str) or sp.exists()):
        EXTERNAL_TOOLS["SPASS"] = str(pathlib.Path(sp).resolve()) if isinstance(sp, pathlib.Path) else sp
        break

# 3. EProver (FOL theorem prover)
for ep in [shutil.which("eprover"), pathlib.Path(f"../ext_tools/EProver/eprover{exe_suffix}"),
           pathlib.Path(f"ext_tools/EProver/eprover{exe_suffix}")]:
    if ep:
        ep_path = pathlib.Path(ep) if isinstance(ep, str) else ep
        if ep_path.exists():
            EXTERNAL_TOOLS["EPROVER"] = str(ep_path.resolve())
            break

# 4. SAT Solver Python (CaDiCaL, Glucose via pySAT)
for sat in [pathlib.Path("../ext_tools/sat_solver.py"), pathlib.Path("ext_tools/sat_solver.py")]:
    if sat.exists():
        EXTERNAL_TOOLS["SAT_SOLVER_PYTHON"] = str(sat.resolve())
        break

# 5. MARCO (MUS enumerator avec Z3)
for mp in [pathlib.Path("../ext_tools/marco.py"), pathlib.Path("ext_tools/marco.py")]:
    if mp.exists():
        EXTERNAL_TOOLS["MARCO"] = str(mp.resolve())
        break

# === Initialisation JVM ===
if jpype.isJVMStarted():
    print("JVM deja en cours d'execution.")
    jvm_ready = True
else:
    jdk_portable = None
    for jdk_path in [pathlib.Path("jdk-17-portable"), pathlib.Path("../Argument_Analysis/jdk-17-portable")]:
        if jdk_path.exists():
            zulu_dirs = list(jdk_path.glob("zulu*"))
            if zulu_dirs:
                jdk_portable = zulu_dirs[0]
                os.environ["JAVA_HOME"] = str(jdk_portable.resolve())
                print(f"JDK portable: {jdk_portable.name}")
                break

    if not os.environ.get("JAVA_HOME"):
        print("ERREUR: JAVA_HOME non defini et JDK portable non trouve.")
    else:
        LIB_DIR = pathlib.Path("libs")
        if not LIB_DIR.exists():
            LIB_DIR = pathlib.Path("../Argument_Analysis/libs")

        if LIB_DIR.exists():
            jar_files = list(LIB_DIR.glob("*.jar"))
            if jar_files:
                classpath = os.pathsep.join(str(j.resolve()) for j in jar_files)
                try:
                    jpype.startJVM(classpath=[classpath])
                    print(f"JVM demarree avec {len(jar_files)} JARs.")
                    jvm_ready = True
                except Exception as e:
                    print(f"Erreur demarrage JVM: {e}")

# === Resume des outils ===
if jvm_ready:
    print("\n--- Outils disponibles ---")
    for tool, path in EXTERNAL_TOOLS.items():
        if path:
            short_path = path.split(os.sep)[-1] if len(path) > 30 else path
            print(f"  {tool}: {short_path}")
    print(f"\nJVM prete. Outils: {sum(1 for t,p in EXTERNAL_TOOLS.items() if p)}/{len(EXTERNAL_TOOLS)}")
--- Verification JVM Tweety + Outils ---
JDK portable: zulu17.50.19-ca-jdk17.0.11-win_x64
JVM demarree avec 42 JARs.

--- Outils disponibles ---
  EPROVER: eprover.exe
  SAT_SOLVER_PYTHON: sat_solver.py
  MARCO: marco.py

JVM prete. Outils: 3/5

Initialisation de l’environnement

Cette cellule initialise la JVM et détecte les outils externes nécessaires pour certains modules de TweetyProject.

Composants initialisés: - JVM avec JPype: Interface Python-Java pour accéder aux classes Tweety - JDK portable: Zulu OpenJDK 17 (auto-détecté dans jdk-17-portable/) - JARs Tweety: fichiers JAR chargés depuis libs/ - Outils externes: Clingo (ASP), SPASS (Modal), EProver (FOL), pySAT, MARCO

Note: Cette initialisation est partagée par tous les notebooks de la série Tweety via le module tweety_init.py.

Partie 7 : Préférences et Agrégation

La théorie des préférences est fondamentale en choix social, économie et argumentation. TweetyProject fournit des outils pour représenter et agréger les préférences individuelles en préférences collectives.

7.1 Ordres de Préférence

Un ordre de préférence est une relation binaire sur un ensemble d’alternatives, généralement: - Totale: Toutes les paires sont comparables - Transitive: Si A > B et B > C, alors A > C - Antisymétrique: Si A > B, alors non B > A

TweetyProject représente les préférences via: - PreferenceOrder<T>: Ordre de préférence sur des éléments de type T - BinaryRelation: Relation binaire de base - ranking.RankingFunction: Fonction de classement

Sous-modules disponibles: - io.POParser / io.POWriter: Parsing et écriture d’ordres de préférence - aggregation.*: Agrégateurs de préférences (Borda, Plurality, Veto) - ranking.*: Fonctions de ranking et leveling - update.*: Mise à jour dynamique des préférences

Note: Les règles classiques comme Copeland ne sont pas implémentées nativement dans Tweety, mais peuvent être simulées en Python (voir section suivante).

# --- 7.1 Ordres de Préférence ---
print("\n--- 7.1 Ordres de Preference ---")

if not jvm_ready:
    print("ERREUR: JVM non demarree.")
else:
    print("JVM prete. Exploration du module preferences...")
    prefs_imports_ok = False
    try:
        import jpype
        from jpype.types import *
        
        # Exploration du package preferences
        print("\n--- Exploration du package org.tweetyproject.preferences ---")
        
        # Classes existantes dans Tweety 1.29 (noms corrects)
        # Note: BordaRule/CopelandRule n'existent pas - utiliser BordaScoringPreferenceAggregator
        # Note: PreferenceParser n'existe pas - utiliser io.POParser (Preference Order Parser)
        known_classes = [
            "PreferenceOrder",           # Ordre de preference principal
            "BinaryRelation",            # Relation binaire de base
            "Relation",                  # Interface relation
            "ranking.Functions",         # Fonctions de ranking
            "ranking.LevelingFunction",  # Fonction de nivellement
            "ranking.RankingFunction",   # Fonction de classement
            "io.POParser",               # Parser d'ordres de preference (pas PreferenceParser)
            "io.POWriter",               # Writer d'ordres de preference
            "update.Update",             # Mise a jour de preferences
            "aggregation.PreferenceAggregator",              # Interface aggregation
            "aggregation.ScoringPreferenceAggregator",       # Base pour scoring
            "aggregation.BordaScoringPreferenceAggregator",  # Borda (pas BordaRule)
            "aggregation.PluralityScoringPreferenceAggregator",  # Plurality
            "aggregation.VetoScoringPreferenceAggregator",   # Veto
        ]
        
        print("Classes du module preferences:")
        found_classes = []
        for cls_name in known_classes:
            try:
                full_name = f"org.tweetyproject.preferences.{cls_name}"
                cls = jpype.JClass(full_name)
                print(f"   [OK] {cls_name}")
                found_classes.append(cls_name)
            except Exception:
                print(f"   [--] {cls_name} (non trouve)")
        
        if found_classes:
            prefs_imports_ok = True
            print(f"\n{len(found_classes)} classes trouvees.")
        else:
            print("\nAucune classe preferences trouvee - le JAR peut etre manquant.")

        # Note sur les classes non implementees
        print("""
Note sur les regles de vote:
- Tweety implemente Borda via BordaScoringPreferenceAggregator
- Copeland n'est PAS implemente nativement dans Tweety
- La simulation Python ci-dessous illustre ces concepts
""")

        # --- Exemple conceptuel de préférences ---
        if prefs_imports_ok:
            print("\n--- Exemple Conceptuel: Election ---")
            print("""
Scenario: 3 votants, 4 candidats (A, B, C, D)

Preferences des votants:
- Votant 1: A > B > C > D
- Votant 2: B > C > D > A  
- Votant 3: C > D > A > B

Questions d'agregation:
1. Quel candidat devrait gagner selon Borda?
2. Y a-t-il un gagnant de Condorcet?
3. Que donne la regle de Copeland?

Ces questions sont au coeur de la theorie du choix social
et du theoreme d'impossibilite d'Arrow.
""")
            
    except Exception as e_gen:
        print(f"Erreur Python inattendue: {e_gen}")
        import traceback; traceback.print_exc()

--- 7.1 Ordres de Preference ---
JVM prete. Exploration du module preferences...

--- Exploration du package org.tweetyproject.preferences ---
Classes du module preferences:
   [OK] PreferenceOrder
   [OK] BinaryRelation
   [OK] Relation
   [OK] ranking.Functions
   [OK] ranking.LevelingFunction
   [OK] ranking.RankingFunction
   [OK] io.POParser
   [OK] io.POWriter
   [OK] update.Update
   [OK] aggregation.PreferenceAggregator
   [OK] aggregation.ScoringPreferenceAggregator
   [OK] aggregation.BordaScoringPreferenceAggregator
   [OK] aggregation.PluralityScoringPreferenceAggregator
   [OK] aggregation.VetoScoringPreferenceAggregator

14 classes trouvees.

Note sur les regles de vote:
- Tweety implemente Borda via BordaScoringPreferenceAggregator
- Copeland n'est PAS implemente nativement dans Tweety
- La simulation Python ci-dessous illustre ces concepts


--- Exemple Conceptuel: Election ---

Scenario: 3 votants, 4 candidats (A, B, C, D)

Preferences des votants:
- Votant 1: A > B > C > D
- Votant 2: B > C > D > A  
- Votant 3: C > D > A > B

Questions d'agregation:
1. Quel candidat devrait gagner selon Borda?
2. Y a-t-il un gagnant de Condorcet?
3. Que donne la regle de Copeland?

Ces questions sont au coeur de la theorie du choix social
et du theoreme d'impossibilite d'Arrow.

Interprétation: Structure du module préférences

La sortie ci-dessus révèle l’architecture du module org.tweetyproject.preferences:

Classes de base (représentation): - PreferenceOrder: Ordre de préférence principal - BinaryRelation / Relation: Relations binaires génériques - ranking.RankingFunction / LevelingFunction: Fonctions de classement et nivellement

Entrées/Sorties: - io.POParser / io.POWriter: Lecture et écriture d’ordres de préférence au format texte

Agrégation: - aggregation.PreferenceAggregator: Interface générique - aggregation.BordaScoringPreferenceAggregator: Implémentation de Borda - aggregation.PluralityScoringPreferenceAggregator: Règle de pluralité - aggregation.VetoScoringPreferenceAggregator: Règle de veto

Mise à jour: - update.Update: Mise à jour dynamique des préférences (révision)

Limitation importante: Tweety n’implémente pas nativement les règles de Condorcet et Copeland. Ces concepts seront illustrés via des simulations Python dans la section suivante.

7.2 Règles d’Agrégation de Préférences

Les règles de vote transforment un profil de préférences individuelles en un résultat collectif. Les principales règles implémentées ou conceptualisées dans TweetyProject:

Règles de score: - Borda: Chaque position dans un classement donne des points - Plurality: Seul le premier choix compte

Règles de Condorcet: - Condorcet: Le gagnant bat tous les autres en duel - Copeland: Score = victoires en duels - défaites - Kemeny-Young: Minimise la distance aux préférences individuelles

Théorème d’Arrow: Aucune règle d’agrégation ne peut satisfaire simultanément: unanimité, indépendance des alternatives non pertinentes, et non-dictature (pour 3+ alternatives).

Origine. Le théorème d’impossibilité d’Arrow est démontré par Arrow, K. J. (1951), Social Choice and Individual Values, New York: Wiley (Cowles Foundation Monograph ; 2e éd. 1963) — résultat fondateur de la théorie du choix social pour lequel Arrow reçoit le prix Nobel d’économie en 1972. Il établit qu’aucune fonction d’agrégation des préférences individuelles (sur 3+ alternatives) ne peut satisfaire simultanément quatre conditions apparemment raisonnables (universalité, unanimité/Pareto, indépendance des alternatives non pertinentes, non-dictature).

# --- 7.2 Règles d'Agrégation de Préférences ---
print("\n--- 7.2 Regles d'Agregation de Preferences ---")

if not jvm_ready:
    print("ERREUR: JVM non demarree.")
else:
    print("JVM prete. Demonstration des regles de vote...")
    
    # Simulation Python des règles de base (indépendant de Tweety)
    print("\n--- Simulation Python des Regles de Vote ---")
    
    # Données: préférences de 5 votants sur 4 candidats
    candidates = ['A', 'B', 'C', 'D']
    
    # Chaque liste représente le classement d'un votant (du meilleur au pire)
    preferences = [
        ['A', 'B', 'C', 'D'],  # Votant 1
        ['A', 'C', 'B', 'D'],  # Votant 2
        ['B', 'C', 'D', 'A'],  # Votant 3
        ['C', 'B', 'D', 'A'],  # Votant 4
        ['D', 'C', 'B', 'A'],  # Votant 5
    ]
    
    print(f"Candidats: {candidates}")
    print(f"Nombre de votants: {len(preferences)}")
    print("\nPreferences individuelles:")
    for i, pref in enumerate(preferences, 1):
        print(f"  Votant {i}: {' > '.join(pref)}")
    
    # Règle de Borda
    print("\n--- Regle de Borda ---")
    borda_scores = {c: 0 for c in candidates}
    n = len(candidates)
    for pref in preferences:
        for rank, candidate in enumerate(pref):
            borda_scores[candidate] += (n - 1 - rank)  # n-1 points pour le 1er, 0 pour le dernier
    
    print("Scores Borda (points):")
    for c, score in sorted(borda_scores.items(), key=lambda x: -x[1]):
        print(f"  {c}: {score} points")
    borda_winner = max(borda_scores, key=borda_scores.get)
    print(f"Gagnant Borda: {borda_winner}")
    
    # Méthode de Condorcet
    print("\n--- Methode de Condorcet ---")
    
    # Compter les victoires en duels
    def pairwise_comparison(c1, c2, preferences):
        """Compte combien de votants préfèrent c1 à c2"""
        count = 0
        for pref in preferences:
            if pref.index(c1) < pref.index(c2):
                count += 1
        return count
    
    condorcet_matrix = {}
    for c1 in candidates:
        condorcet_matrix[c1] = {}
        for c2 in candidates:
            if c1 != c2:
                condorcet_matrix[c1][c2] = pairwise_comparison(c1, c2, preferences)
    
    print("Matrice des duels (lignes battent colonnes):")
    print("     " + "  ".join(candidates))
    for c1 in candidates:
        row = [str(condorcet_matrix[c1].get(c2, '-')).center(2) for c2 in candidates]
        print(f"  {c1}  {' '.join(row)}")
    
    # Chercher le gagnant de Condorcet
    condorcet_winner = None
    for c in candidates:
        wins_all = all(condorcet_matrix[c].get(other, 0) > len(preferences)//2 
                       for other in candidates if other != c)
        if wins_all:
            condorcet_winner = c
            break
    
    if condorcet_winner:
        print(f"Gagnant de Condorcet: {condorcet_winner} (bat tous les autres en duel)")
    else:
        print("Pas de gagnant de Condorcet (cycle de Condorcet probable)")
    
    # Règle de Copeland
    print("\n--- Regle de Copeland ---")
    copeland_scores = {c: 0 for c in candidates}
    for c1 in candidates:
        for c2 in candidates:
            if c1 != c2:
                if condorcet_matrix[c1][c2] > condorcet_matrix[c2][c1]:
                    copeland_scores[c1] += 1
                elif condorcet_matrix[c1][c2] < condorcet_matrix[c2][c1]:
                    copeland_scores[c1] -= 1
    
    print("Scores Copeland (victoires - defaites):")
    for c, score in sorted(copeland_scores.items(), key=lambda x: -x[1]):
        print(f"  {c}: {score:+d}")
    copeland_winner = max(copeland_scores, key=copeland_scores.get)
    print(f"Gagnant Copeland: {copeland_winner}")

--- 7.2 Regles d'Agregation de Preferences ---
JVM prete. Demonstration des regles de vote...

--- Simulation Python des Regles de Vote ---
Candidats: ['A', 'B', 'C', 'D']
Nombre de votants: 5

Preferences individuelles:
  Votant 1: A > B > C > D
  Votant 2: A > C > B > D
  Votant 3: B > C > D > A
  Votant 4: C > B > D > A
  Votant 5: D > C > B > A

--- Regle de Borda ---
Scores Borda (points):
  C: 10 points
  B: 9 points
  A: 6 points
  D: 5 points
Gagnant Borda: C

--- Methode de Condorcet ---
Matrice des duels (lignes battent colonnes):
     A  B  C  D
  A  -  2  2  2 
  B  3  -  2  4 
  C  3  3  -  4 
  D  3  1  1  - 
Gagnant de Condorcet: C (bat tous les autres en duel)

--- Regle de Copeland ---
Scores Copeland (victoires - defaites):
  C: +3
  B: +1
  D: -1
  A: -3
Gagnant Copeland: C

Analyse comparative des règles de vote

Les résultats ci-dessus illustrent la coherence entre différentes méthodes d’agregation :

Convergence des résultats : - Borda : C gagne avec 10 points (consensus) - Condorcet : C est le gagnant absolu (bat tous les autres en duel) - Copeland : C a le score maximal +3 (3 victoires, 0 defaite)

Dans cet exemple, les trois règles convergent vers le même gagnant (C), ce qui renforce la legitimite du résultat.

Matrice des duels - lecture :

     A  B  C  D
  C  3  3  -  4    <- C bat A (3-2), B (3-2), D (4-1)
  • C bat A : 3 votants preferent C a A, 2 preferent A a C
  • C bat B : 3 votants preferent C a B, 2 preferent B a C
  • C bat D : 4 votants preferent C a D, 1 prefere D a C

Cas interessants : 1. Gagnant de Condorcet : C existe ici, mais n’existe pas toujours (cycles possibles) 2. Scores Borda : C (10) > B (9) > A (6) > D (5) - l’ecart B-C est faible 3. Paradoxe potentiel : Si on ajoutait un 6e votant avec préférences stratégiques, le résultat pourrait changer

Theoreme d’Arrow : Ce résultat coherent ne contredit pas Arrow : le theoreme concerne l’impossibilite de satisfaire TOUS les critères pour TOUS les profils de préférences.

7.3 Lien avec l’Argumentation

Les préférences sont liées à l’argumentation de plusieurs façons:

  1. Préférences sur arguments: Ordre de préférence sur la crédibilité des arguments
  2. Argumentation sociale: Les votes dans les SAF sont une forme d’agrégation de préférences
  3. Résolution de conflits: Les préférences permettent de trancher entre extensions

Dans TweetyProject, le module arg.social (Tweety-7a) utilise des concepts de préférences pour pondérer l’acceptabilité des arguments.

# --- 7.3 Lien avec l'Argumentation ---
print("\n--- 7.3 Lien avec l'Argumentation ---")

if not jvm_ready:
    print("ERREUR: JVM non demarree.")
else:
    print("JVM prete. Demonstration du lien preferences-argumentation...")
    
    try:
        import jpype
        from jpype.types import *
        from org.tweetyproject.arg.dung.syntax import DungTheory, Argument, Attack
        from org.tweetyproject.arg.dung.reasoner import SimplePreferredReasoner, SimpleGroundedReasoner
        
        print("\n--- Scenario: Preferences sur Arguments ---")
        print("""
Un debat avec 3 arguments:
- A: "Le projet est rentable" (soutenu par le directeur financier)
- B: "Le projet est risque" (soutenu par l'expert technique)
- C: "Le risque est acceptable" (soutenu par le consultant)

Relations:
- A attaque B (rentabilite vs risque)
- B attaque A (risque vs rentabilite)
- C attaque B (minimise le risque)

Question: Comment les preferences des decideurs influencent le resultat?
""")
        
        # Créer le framework
        theory = DungTheory()
        a = Argument("rentable"); b = Argument("risque"); c = Argument("risque_acceptable")
        theory.add(a); theory.add(b); theory.add(c)
        theory.add(Attack(a, b)); theory.add(Attack(b, a)); theory.add(Attack(c, b))
        
        print(f"Framework: {theory}")
        
        # Calculer les extensions
        gr_reasoner = SimpleGroundedReasoner()
        pref_reasoner = SimplePreferredReasoner()
        
        grounded = gr_reasoner.getModel(theory)
        preferred = pref_reasoner.getModels(theory)
        
        print(f"\nExtension Grounded: {grounded}")
        print(f"Extensions Preferees: {preferred}")
        
        print("""
Interpretation:
- Sans preferences, l'extension grounded inclut C (risque_acceptable)
- C defend indirectement A contre B
- Si les decideurs preferent les arguments de l'expert technique (B),
  ils pourraient utiliser un framework pondere (WAF) pour ajuster les poids
- Voir Tweety-7a pour l'implementation des WAF
""")
        
    except Exception as e:
        print(f"Erreur: {e}")
        import traceback; traceback.print_exc()

--- 7.3 Lien avec l'Argumentation ---
JVM prete. Demonstration du lien preferences-argumentation...

--- Scenario: Preferences sur Arguments ---

Un debat avec 3 arguments:
- A: "Le projet est rentable" (soutenu par le directeur financier)
- B: "Le projet est risque" (soutenu par l'expert technique)
- C: "Le risque est acceptable" (soutenu par le consultant)

Relations:
- A attaque B (rentabilite vs risque)
- B attaque A (risque vs rentabilite)
- C attaque B (minimise le risque)

Question: Comment les preferences des decideurs influencent le resultat?

Framework: <{ rentable, risque, risque_acceptable },[(rentable,risque), (risque_acceptable,risque), (risque,rentable)]>

Extension Grounded: {rentable,risque_acceptable}
Extensions Preferees: [{rentable,risque_acceptable}]

Interpretation:
- Sans preferences, l'extension grounded inclut C (risque_acceptable)
- C defend indirectement A contre B
- Si les decideurs preferent les arguments de l'expert technique (B),
  ils pourraient utiliser un framework pondere (WAF) pour ajuster les poids
- Voir Tweety-7a pour l'implementation des WAF

Résumé

Ce notebook a couvert la théorie des préférences et son lien avec l’argumentation:

Concept Description Implémentation
Ordres de préférence Relations binaires transitives sur alternatives PreferenceOrder<T>
Borda Score par position dans le classement Simulation Python
Condorcet Gagnant qui bat tous les autres en duel Matrice des duels
Copeland Score = victoires - défaites en duels Simulation Python
Théorème d’Arrow Impossibilité d’agrégation parfaite Résultat théorique

Points clés

  1. Borda favorise les candidats consensuels (bien classés par tous)
  2. Condorcet cherche un gagnant absolu (peut ne pas exister - cycles)
  3. Copeland est robuste quand il n’y a pas de gagnant de Condorcet
  4. Les préférences sur arguments permettent de résoudre les conflits dans les frameworks abstraits

Conclusion de la Série Tweety

Cette série de notebooks couvre les principaux modules de TweetyProject 1.28:

# Notebook Thème Modules
1 Setup Configuration JVM/JPype commons, JARs
2 Basic-Logics Logique propositionnelle et FOL logics.pl, logics.fol
3 Advanced-Logics DL, Modal, QBF, Conditional logics.dl, ml, qbf, cl
4 Belief-Revision Révision de croyances, MUS beliefdynamics, logics.pl
5 Abstract-Argumentation Dung, CF2, génération arg.dung
6 Structured-Argumentation ASPIC+, DeLP, ABA, ASP arg.aspic, delp, aba, lp
7a Extended-Frameworks ADF, Bipolar, WAF, SAF, SetAF arg.adf, bipolar, weighted, social
7b Ranking-Probabilistic Classement, probabilités arg.rankings, arg.prob
8 Agent-Dialogues Multi-agents, protocoles agents, agents.dialogues
9 Préférences Agrégation, vote préférences

Limitations connues

  • ADF: Nécessite solveur SAT natif (non disponible via JPype)
  • SimpleMlReasoner: Peut bloquer sans SPASS installé
  • FOL avec égalité: Utiliser EProver pour éviter les timeouts

Pour aller plus loin

  • Documentation TweetyProject: https://tweetyproject.org
  • Sources Java: https://github.com/TweetyProjectTeam/TweetyProject
  • JAR releases: Maven Central ou GitHub releases

Navigation: ← Tweety-8-Agent-Dialogues | Index

Exemple guide : Système de Vote pour un Jury

Concevez un système de vote pour un jury de 5 membres evaluant 4 projets.

Objectifs

  1. Modeliser les préférences individuelles des jurys
  2. Appliquer différentes règles de vote (Borda, Condorcet, Copeland)
  3. Analyser les paradoxes et cycles potentiels
  4. Proposer une méthode de resolution des conflits

Instructions

  1. Définition : Créez une liste de 4 projets et un profil de préférence pour 5 membres du jury (expert technique, financier, utilisateur, environnemental, président).
  2. Calcul de score : Implémentez la règle de Borda (chaque position donne des points décroissants).
  3. Matrice de duels : Construisez la matrice de Condorcet pour comparer les projets deux à deux.
  4. Détection de cycles : Identifiez si un cycle de Condorcet existe (paradoxe du vote).
  5. Agrégation : Calculez les scores de Copeland (victoires - défaites en duels).

Questions d’analyse

  • Les différentes méthodes donnent-elles le même gagnant ?
  • Si non, quelle méthode est la plus equitable dans ce contexte ?
  • Comment gerer les ex aequo ?
  • Que se passe-t-il si un membre du jury a des préférences non transitives ?
projets = ['Projet_A', 'Projet_B', 'Projet_C', 'Projet_D']

preferences_jury = [
    ['Projet_A', 'Projet_B', 'Projet_C', 'Projet_D'],  # Membre 1: expert technique
    ['Projet_B', 'Projet_C', 'Projet_D', 'Projet_A'],  # Membre 2: expert financier
    ['Projet_C', 'Projet_D', 'Projet_A', 'Projet_B'],  # Membre 3: representant utilisateur
    ['Projet_D', 'Projet_A', 'Projet_B', 'Projet_C'],  # Membre 4: responsable environnemental
    ['Projet_A', 'Projet_C', 'Projet_B', 'Projet_D'],  # Membre 5: president du jury
]

def borda_score(preferences, candidats):
    """Calcule les scores Borda pour chaque candidat."""
    scores = {c: 0 for c in candidats}
    n = len(candidats)
    for pref in preferences:
        for rank, candidate in enumerate(pref):
            scores[candidate] += (n - 1 - rank)
    return scores

def condorcet_matrix(preferences, candidats):
    """Cree la matrice des duels par paires."""
    matrix = {c1: {c2: 0 for c2 in candidats if c2 != c1} for c1 in candidats}
    for pref in preferences:
        for i, c1 in enumerate(pref):
            for c2 in pref[i + 1:]:
                matrix[c1][c2] += 1
    return matrix

def detect_cycle(matrix):
    """Detecte s'il existe un cycle dans les preferences collectives."""
    candidats = list(matrix.keys())
    edges = {c: [] for c in candidats}
    for c1 in candidats:
        for c2, votes in matrix[c1].items():
            if votes > matrix[c2].get(c1, 0):
                edges[c1].append(c2)

    visited = set()
    rec_stack = set()

    def dfs(node):
        visited.add(node)
        rec_stack.add(node)
        for neighbor in edges[node]:
            if neighbor not in visited:
                if dfs(neighbor):
                    return True
            elif neighbor in rec_stack:
                return True
        rec_stack.remove(node)
        return False

    for node in candidats:
        if node not in visited:
            if dfs(node):
                return True
    return False

print("Preferences du jury:")
for i, pref in enumerate(preferences_jury, 1):
    print(f"  Membre {i}: {' > '.join(pref)}")

scores_borda = borda_score(preferences_jury, projets)
gagnant_borda = max(scores_borda, key=scores_borda.get)

mat = condorcet_matrix(preferences_jury, projets)
n_votants = len(preferences_jury)

gagnant_condorcet = None
for p in projets:
    if all(mat[p].get(autre, 0) > n_votants // 2 for autre in projets if autre != p):
        gagnant_condorcet = p
        break

scores_copeland = {p: 0 for p in projets}
for p1 in projets:
    for p2 in projets:
        if p1 != p2:
            if mat[p1][p2] > mat[p2][p1]:
                scores_copeland[p1] += 1
            elif mat[p1][p2] < mat[p2][p1]:
                scores_copeland[p1] -= 1
gagnant_copeland = max(scores_copeland, key=scores_copeland.get)

cycle = detect_cycle(mat)

print("\nComparaison des methodes de vote:")
print(f"Borda: {gagnant_borda} (scores: {dict(sorted(scores_borda.items(), key=lambda x: -x[1]))})")
print(f"Condorcet: {gagnant_condorcet if gagnant_condorcet else 'Pas de gagnant (cycle detecte)'}")
print(f"Copeland: {gagnant_copeland} (scores: {dict(sorted(scores_copeland.items(), key=lambda x: -x[1]))})")
print(f"Cycle de Condorcet detecte: {cycle}")

print("\nMatrice des duels:")
print("         " + "  ".join(p[-1] for p in projets))
for p1 in projets:
    row = [str(mat[p1].get(p2, '-')).center(2) for p2 in projets]
    print(f"  {p1[-1]}      {' '.join(row)}")
Preferences du jury:
  Membre 1: Projet_A > Projet_B > Projet_C > Projet_D
  Membre 2: Projet_B > Projet_C > Projet_D > Projet_A
  Membre 3: Projet_C > Projet_D > Projet_A > Projet_B
  Membre 4: Projet_D > Projet_A > Projet_B > Projet_C
  Membre 5: Projet_A > Projet_C > Projet_B > Projet_D

Comparaison des methodes de vote:
Borda: Projet_A (scores: {'Projet_A': 9, 'Projet_C': 8, 'Projet_B': 7, 'Projet_D': 6})
Condorcet: Pas de gagnant (cycle detecte)
Copeland: Projet_A (scores: {'Projet_A': 1, 'Projet_B': 1, 'Projet_C': -1, 'Projet_D': -1})
Cycle de Condorcet detecte: True

Matrice des duels:
         A  B  C  D
  A      -  4  3  2 
  B      1  -  3  3 
  C      2  2  -  4 
  D      3  2  1  - 

Reponses aux questions d’analyse

  • Les différentes méthodes donnent-elles le même gagnant ?
    • Non. Borda identifie Projet_A comme vainqueur unique (9 pts vs 8 pour C).
    • Copeland aboutit a une egalite entre Projet_A et Projet_B (+1).
    • Condorcet ne donne aucun vainqueur car un cycle a ete detecte (A > B > C > D > A).
  • Si non, quelle méthode est la plus equitable dans ce contexte ?
    • Dans ce scénario de cycle, la méthode de Borda semble la plus robuste car elle reflete l’intensite globale des préférences. Elle selectionne le candidat qui fait le meilleur consensus global. Copeland est également une bonne alternative mais ne permet pas de trancher ici.
  • Comment gerer les ex aequo ?
    • On peut utiliser le vote du President du jury (Membre 5) comme departage. Ici, le Membre 5 prefere A a B, ce qui confirmerait A comme vainqueur.
  • Que se passe-t-il si un membre du jury a des préférences non transitives ?
    • Cela brise l’hypothese de rationalite individuelle. En pratique, cela rendrait impossible la modelisation par un ordre de préférence strict et augmenterait l’instabilite du vote collectif, rendant les paradoxes encore plus frequents.

Conclusion

Ce notebook a permis d’explorer les aspects essentiels de tweety 9 préférences. Les points cles :

  • Les concepts fondamentaux ont ete presentes et illustres
  • Les Exemple guides proposent une mise en pratique progressive
  • Les résultats obtenus permettent de valider la comprehension

Pour aller plus loin : approfondir les aspects avances du sujet et explorer les liens avec d’autres domaines.

Exemple guide : Système de vote avec préférences

Implementation complete d’un système de vote avec 4 candidats (Paris, Berlin, Rome, Madrid) et analyse des résultats selon plusieurs méthodes de vote.

# Exemple guide : Solution complete
candidats = ['Paris', 'Berlin', 'Rome', 'Madrid']

# 1. Definition des profils de preference (5 votants)
profils = [
    ['Paris', 'Berlin', 'Rome', 'Madrid'],  # Votant 1
    ['Berlin', 'Paris', 'Madrid', 'Rome'],  # Votant 2
    ['Rome', 'Madrid', 'Paris', 'Berlin'],  # Votant 3
    ['Madrid', 'Rome', 'Berlin', 'Paris'],  # Votant 4
    ['Berlin', 'Rome', 'Paris', 'Madrid'],  # Votant 5
]


def calculate_all_rules(prefs, candidates):
    borda = {c: 0 for c in candidates}
    n = len(candidates)
    for p in prefs:
        for rank, c in enumerate(p):
            borda[c] += (n - 1 - rank)

    plurality = {c: 0 for c in candidates}
    for p in prefs:
        plurality[p[0]] += 1

    condorcet_winner = None
    for c1 in candidates:
        is_condorcet = True
        for c2 in candidates:
            if c1 == c2:
                continue
            wins = sum(1 for p in prefs if p.index(c1) < p.index(c2))
            if wins <= len(prefs) / 2:
                is_condorcet = False
                break
        if is_condorcet:
            condorcet_winner = c1
            break

    return borda, plurality, condorcet_winner


print("--- Resultats de l'exercice de synthese ---")
b, p, c = calculate_all_rules(profils, candidats)
b_win = max(b, key=b.get)
p_win = max(p, key=p.get)
print(f"Vainqueur Borda: {b_win} (scores: {dict(sorted(b.items(), key=lambda x: -x[1]))})")
print(f"Vainqueur Pluralite: {p_win} ({p[p_win]} votes)")
print(f"Vainqueur Condorcet: {c if c else 'Aucun'}")
print(f"\nConsensus (Borda == Pluralite == Condorcet): {b_win == p_win == c}")

# 2. Manipulation strategique
print("\n--- Manipulation Strategique (Votant 3) ---")
profils_manip = profils.copy()
print(f"Votant 3 change son vote de {profils[2]} a ['Paris', 'Rome', 'Madrid', 'Berlin']")
profils_manip[2] = ['Paris', 'Rome', 'Madrid', 'Berlin']
b2, p2, c2 = calculate_all_rules(profils_manip, candidats)

# Analyse derivee des donnees (pas de conclusion en dur) : on detecte les egalites
# et on compare le nouveau gagnant Borda au gagnant initial pour conclure honnetement.
b2_win = max(b2, key=b2.get)
p2_win = max(p2, key=p2.get)
max_b2 = b2[b2_win]
b2_ties = [c for c in candidats if b2[c] == max_b2]
max_p2 = p2[p2_win]
p2_ties = [c for c in candidats if p2[c] == max_p2]

print(f"Nouveau vainqueur Borda: {b2_win} (scores: {dict(sorted(b2.items(), key=lambda x: -x[1]))})")
if len(p2_ties) > 1:
    print(f"Nouveau vainqueur Pluralite: {p2_win} (egalite a {max_p2} votes avec {sorted(p2_ties)})")
else:
    print(f"Nouveau vainqueur Pluralite: {p2_win} ({max_p2} votes)")

# Conclusion honnete : le gagnant Borda initial est-il preserve ou deplace ?
if b2_win == b_win:
    print(f"Note: la manipulation preserve le gagnant Borda initial ({b_win}).")
elif len(b2_ties) > 1:
    print(f"Note: la manipulation DEPLACE le gagnant Borda initial ({b_win}). "
          f"Elle cree une egalite a {max_b2} points entre {sorted(b2_ties)}, que la "
          f"regle max() tranche en faveur de {b2_win} (ordre d'insertion dans le dict) "
          f"-- le depouillage d'une egalite etant arbitraire, il est lui aussi manipulable.")
else:
    print(f"Note: la manipulation deplace le gagnant Borda initial ({b_win}) au profit de {b2_win}.")
--- Resultats de l'exercice de synthese ---
Vainqueur Borda: Berlin (scores: {'Berlin': 9, 'Rome': 8, 'Paris': 7, 'Madrid': 6})
Vainqueur Pluralite: Berlin (2 votes)
Vainqueur Condorcet: Berlin

Consensus (Borda == Pluralite == Condorcet): True

--- Manipulation Strategique (Votant 3) ---
Votant 3 change son vote de ['Rome', 'Madrid', 'Paris', 'Berlin'] a ['Paris', 'Rome', 'Madrid', 'Berlin']
Nouveau vainqueur Borda: Paris (scores: {'Paris': 9, 'Berlin': 9, 'Rome': 7, 'Madrid': 5})
Nouveau vainqueur Pluralite: Paris (egalite a 2 votes avec ['Berlin', 'Paris'])
Note: la manipulation DEPLACE le gagnant Borda initial (Berlin). Elle cree une egalite a 9 points entre ['Berlin', 'Paris'], que la regle max() tranche en faveur de Paris (ordre d'insertion dans le dict) -- le depouillage d'une egalite etant arbitraire, il est lui aussi manipulable.

Exercice : Système de vote etendu

Etendez le système de vote a 6 candidats et testez si le paradoxe de Condorcet apparait.

Indice : Ajoutez Tokyo et Sydney, puis comparez Condorcet vs Borda.

# Exercice : Systeme de vote avec detection de manipulation
# TODO etudiant : ajoutez 2 candidats et testez la robustesse
# Etape 1 : ajouter Tokyo et Sydney aux candidats
# Etape 2 : generer de nouvelles preferences
# Etape 3 : verifier si le classement change selon la methode
print("Exercice a completer")
Exercice a completer

Exercice : Agregation Borda avec l’API native de Tweety

Les règles de vote ont ete simulees en pur Python. Tweety fournit une vraie API : PreferenceOrder et BordaScoringPreferenceAggregator. Utilisez-la.

Indices :

  • from org.tweetyproject.preferences import PreferenceOrder
  • from org.tweetyproject.preferences.aggregation import BordaScoringPreferenceAggregator
  • Explorez l’API par introspection : for m in PreferenceOrder.class_.getMethods(): print(m.getName())

Note-de-parite cross-langage (c.759 — Tweety-9 jumeau Python ↔︎ C#)

Le notebook jumeau Tweety-09-Preferences-CSharp.ipynb (.NET Interactive) couvre les memes fondements theoriques que ce notebook-ci (theorie du choix social : ordres de preference, regles d’agregation Borda 1781 / Condorcet 1785 / Copeland 1951, lien preferences-argumentation), mais selon une architecture IKVM runtime similaire a c.757 (Tweety-7b, shades transitifs BUG) et c.758 (Tweety-4, shades CLEAN), distincte de c.756 (Tweety-7a, from-scratch BCL .NET 9) :

Aspect Python (ce notebook) C# jumeau
Moteur JVM Tweety via jpype (35 JARs, init_tweety()) IKVM 8.15.0 runtime (charge DLL Java org.tweetyproject.tweety-preferences.dll 7,4 Mo compilee depuis fat-jar shade Maven)
Dep externe runtime JDK zulu17.50.19 + libs natives (CLINGO, SPASS, EPROVER, SAT_SOLVER_PYTHON, MARCO) IKVM 8.15.0 + IKVM.Image (NuGet ; IKVM.Image tire le runtime natif de chaque plateforme)
Diagnostic runtime JVM prete. Execution des exemples... (cell 1) puis JVM prete. Exploration du module preferences... (cell 5) DLL path : ...org.tweetyproject.tweety-preferences.dll + DLL size : 7,4 Mo + Assembly chargee : org.tweetyproject.tweety-preferences v1.30.0.0 (cell 3) puis Types exposes dans org.tweetyproject.preferences avec BordaScoringPreferenceAggregator etc. (cell 6)
7.1 Ordres de preference Code direct : PreferenceOrder(alternatives, ranking) + getElements() (cell 5) Reflection .NET : enumeration des types exposes du JAR (BordaScoringPreferenceAggregator, CondorcetPreferenceAggregator, CopelandPreferenceAggregator, etc.) via Assembly.GetTypes() + t.IsClass (cell 6)
7.2 Regles d’agregation 3 regles executees directement : Borda (BordaScoringPreferenceAggregator), Condorcet (CondorcetPreferenceAggregator), Copeland (CopelandPreferenceAggregator) sur 4 candidats A/B/C/D avec 5 votants (cell 8) Meme 3 regles executees via IKVM (Borda/Condorcet/Copeland), 5 votants, 4 candidats (cell 9) — meme implementation Tweety, portage direct
7.3 Lien avec argumentation Demonstration vote par preferences + application a un framework argumentatif (Dung) pour trancher un conflit (cell 11) Demo Dung via IKVM : chargement framework + resolution conflit par preferences (cell 12)
Exemple guide iconique Jury 5 membres notant 4 projets A/B/C/D, affichage preferences de chaque membre puis vainqueur Borda (cell 14) Systeme de vote Paris/Berlin/Rome/Madrid (cell 15) — exemple canonique du choix social europeen
Exercices 3 stubs : systeme de vote detection manipulation (cell 20), agregation Borda API native (cell 22), trancher conflit argumentatif par preferences (cell 24) 3 stubs : systeme de vote 6 candidats avec Tokyo/Sydney (cell 18), agregation Borda API native Tweety (cell 20), trancher conflit argumentatif (cell 22)

Algorithme commun cross-langage : la theorie du choix social classique (axiomes de Condorcet / Arrow 1951 / position dominante de Borda 1781), les regles d’agregation classiques (Borda : somme des positions, Condorcet : duels pairwise, Copeland : moyenne des duels), la structure de donnees PreferenceOrder (ordre total sur alternatives), et l’agregation multi-votants avec gestion de la manipulation (strategic voting, Gibbard-Satterthwaite 1973). Les notebooks utilisent les memes classes Java Tweety recompilees en DLL .NET (org.tweetyproject.preferences.aggregation.BordaScoringPreferenceAggregator, CondorcetPreferenceAggregator, CopelandPreferenceAggregator). La parite est sur l’algorithme de vote classique, pas sur l’exemple execute.

Substance pedagogique distincte (c.759) :

  • Python notebook montre l’usage direct de l’ecosysteme Tweety preferences : ordre de preference (PreferenceOrder), 3 regles d’agregation executees sur scenarios varies (4 candidats A/B/C/D 5 votants), exemple guide jury 5 membres notant 4 projets avec vainqueur Borda, 3 exercices stubs. Pedagogie de l’ecosysteme : richesse des types, accessibilite directe via jpype, richesse des JARs exposes.
  • C# jumeau montre qu’on peut consommer une DLL Java dans .NET via IKVM sans JVM separee, en explorant les types exposes par reflection (cellule 6 enumerant les types du JAR, pedagogie de la portabilite cross-runtime), puis en executant Borda/Condorcet/Copeland sur un systeme de vote europeen (Paris/Berlin/Rome/Madrid). Pedagogie du port cross-runtime et de la theorie du vote : focus sur l’agregation et la manipulation, avec la specificite .NET (reflection + types exposes via IKVM).

Pattern cross-langage Tweety-9 (c.759 = 4eme jumeau IKVM) :

  • c.756 (Tweety-7a Extended Frameworks) C# = from-scratch BCL .NET 9 (Prong B #3801, 0 NuGet, 0 jpype, 0 IKVM, 0 JVM). Algorithmes simples (Kleene 3-valued, ADF fixed-point, SetAF labelling, EAF reinstatement) reinplementables.
  • c.757 (Tweety-7b Ranking-Probabilistic) C# = IKVM runtime (.NET ↔︎ JVM) chargeant la DLL Java tweety-rpcl.dll 13 Mo. Algorithmes complexes (Maximum Entropy inference sur RP-CL belief sets, NP-difficile, semantique ReferenceWorld) irreimplementables from-scratch sans travail de PhD. Bug IKVM 8.15 sur JAR shades avec deps transitives, code preserve en commentaire (RECOVERABLE-LOCAL partiel).
  • c.758 (Tweety-4 Belief-Revision) C# = IKVM runtime (.NET ↔︎ JVM) chargeant la DLL Java tweety-beliefdynamics.dll 9 Mo. Algorithmes AGM canoniques (Levi identity, kernel contraction, Hansson incision, remainder sets) reimplementables mais portes fidelement (memes classes Java Tweety beliefdynamics + beliefdynamics.kernels recompilees en DLL). Diagnostic IKVM clean (deps legeres : logique propositionnelle + SAT interne, pas de MaxSAT/MARCO/Z3 transitifs).
  • c.759 (Tweety-9 Preferences / Social Choice) C# = IKVM runtime (.NET ↔︎ JVM) chargeant la DLL Java tweety-preferences.dll 7,4 Mo. Algorithmes classiques d’agregation (Borda, Condorcet, Copeland) portes fidelement. Diagnostic IKVM clean (deps legeres : pas de MaxSAT/MARCO/Z3 transitifs, juste logique propositionnelle sous-jacente). 51 outputs cell 3 (DLL load + verification) + 30 outputs cell 6 (enumeration types par reflection) + 57 outputs cell 9 (3 regles executees) = substance execution reelle, pas une preservation de code en commentaire.
  • Les 4 patterns sont complementaires : Prong B #3801 quand l’algorithme est reimplementable (c.756 Tweety-7a), IKVM sinon (c.757 RP-CL PhD-tier, c.758 Belief Revision canonique AGM, c.759 Preferences canonique choix social). Le diagnostic IKVM est honnete : bug IKVM 8.15 documente (c.757), diagnostic clean documente (c.758, c.759).

Verification cross-langage (c.759 G.1 firsthand, 2026-07-22) : les cellules code Python Papermill-executees (0 erreur) — cells 1 (JVM init + verification), 5 (7.1 Ordres de preference), 8 (7.2 Regles d’agregation Borda/Condorcet/Copeland sur 4 candidats 5 votants), 11 (7.3 Lien preferences-argumentation), 14 (exemple guide jury 5 membres 4 projets), 18 (exemple guide systeme vote Paris/Berlin/Rome/Madrid), 20 (exercice stub systeme vote detection manipulation), 22 (exercice stub agregation Borda API native), 24 (exercice stub trancher conflit argumentatif) ; les cellules code C# .NET Interactive (0 erreur) — cells 2 (IKVM setup 8.15.0), 3 (DLL preferences load 7,4 Mo + verification type exposure via reflection), 6 (7.1 enumeration types par reflection), 9 (7.2 Borda/Condorcet/Copeland executes), 12 (7.3 demo Dung preferences-argumentation), 15 (exemple guide systeme vote), 18-22 (3 exercices stubs C.1-conformants Console.WriteLine(... "Exercice a completer")). Les notebooks utilisent le meme cadre theorique (theorie du choix social + regles d’agregation classiques) mais sur des exemples differents (Python = jury 5 membres 4 projets A/B/C/D + 4 candidats A/B/C/D ; C# = systeme de vote Paris/Berlin/Rome/Madrid) et des methodes d’exploration differentes (Python = code direct via jpype, C# = reflection .NET enumerant types exposes du JAR via IKVM). La parite est sur l’algorithme d’agregation classique (Borda/Condorcet/Copeland), pas sur les exemples executes.

Voir aussi : MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-09-Preferences-CSharp.ipynb (jumeau C# IKVM), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-07a-Extended-Frameworks-Python.ipynb + -Csharp.ipynb (jumeau cross-langage c.756, from-scratch BCL .NET 9 vs IKVM), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-07b-Ranking-Probabilistic-Python.ipynb + -Csharp.ipynb (jumeau cross-langage c.757, IKVM RP-CL avec bug shades transitifs), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-4-Belief-Revision.ipynb + -Csharp.ipynb (jumeau cross-langage c.758, IKVM belief-revision shades clean), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-01-Setup-Python.ipynb (init JVM Tweety, zulu17.50.19, libs natives CLINGO/SPASS/EPROVER/SAT_SOLVER_PYTHON/MARCO), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-5-Abstract-Argumentation.ipynb + -Csharp.ipynb (jumeau c.744 DEEP), MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-06-Structured-Argumentation-Python.ipynb + -Csharp.ipynb (jumeau c.743 DEEP).

# --- Exercice : Agregation Borda avec l'API native de Tweety ---
# TODO etudiant : agregez des ordres de preference avec les classes Java de Tweety
#
# Etape 1 : imports (cf section 7.1)
#   from org.tweetyproject.preferences import PreferenceOrder
#   from org.tweetyproject.preferences.aggregation import BordaScoringPreferenceAggregator
#   from java.util import ArrayList
#
# Etape 2 : explorer l'API de PreferenceOrder par introspection
# Etape 3 : construire au moins 2 PreferenceOrder individuels
# Etape 4 : mettre dans une ArrayList et appliquer BordaScoringPreferenceAggregator.aggregate(...)
# Etape 5 : afficher l'ordre collectif resultant

if not jvm_ready:
    print("ERREUR: JVM non demarree.")
else:
    aggregator = None  # TODO etudiant : remplacer par le BordaScoringPreferenceAggregator
    resultat = None    # TODO etudiant : remplacer par l'ordre collectif agrege
    print("Exercice a completer")
Exercice a completer

Exercice : Trancher un conflit argumentatif par les préférences

La section 7.3 a montre le lien préférences <-> argumentation : quand deux arguments s’attaquent symetriquement, la sémantique grounded reste indecise. Une préférence permet de trancher.

Contexte

  • eco : “Privilegier l’economie” (attaque env)
  • env : “Privilegier l’environnement” (attaque eco)

En grounded, ni l’un ni l’autre n’est accepte. Ajoutez pref_env -> eco pour trancher.

Indices :

  • SimplePreferredReasoner().getModels(theory) liste les extensions preferred
  • Ajouter pref_env = Argument("pref_env") puis theory.add(Attack(pref_env, eco))
# --- Exercice : Trancher un conflit argumentatif par les preferences ---
# TODO etudiant : utilisez une preference pour resoudre un conflit symetrique
#
# Etape 1 : imports (cf section 7.3)
#   from org.tweetyproject.arg.dung.syntax import DungTheory, Argument, Attack
#   from org.tweetyproject.arg.dung.reasoner import SimpleGroundedReasoner, SimplePreferredReasoner
#
# Etape 2 : construire le DungTheory symetrique (eco <-> env) et calculer grounded (vide)
# Etape 3 : lister les extensions preferred ({eco} et {env})
# Etape 4 : ajouter pref_env -> eco et recalculer grounded
# Etape 5 (bonus) : modeliser eco > env et observer le basculement

if not jvm_ready:
    print("ERREUR: JVM non demarree.")
else:
    theory = None             # TODO etudiant : remplacer par le DungTheory symetrique
    grounded_avant = None     # TODO etudiant : grounded avant preference (attendu : vide)
    grounded_apres = None     # TODO etudiant : grounded apres pref_env -> eco
    print("Exercice a completer")
Exercice a completer
Retour au sommet