Tweety-4 — Argumentation structurée ASPIC+ en C#/.NET (port natif IKVM)

Série Tweety — port C#/.NET natif (EPIC #4667). Ce notebook exploite le module arg-aspic de TweetyProject sans JVM : la librairie Java est compilée vers un fat-jar Maven shade puis exécutée sur le runtime .NET via IKVM.

Navigation : Tweety-2-Basic-Logics-Csharp (propositionnel) · Tweety-2b-Semantics-Csharp (mondes possibles) · Tweety-2c-FOL-Csharp (premier ordre) · Tweety-3-Dung-Csharp (argumentation abstraite) · Tweety-4-Aspic (ce notebook) (argumentation structurée).


Objectifs pédagogiques

Le notebook Tweety-3-Dung traitait l’argumentation abstraite de Dung : un argument y est un nœud opaque, on ne regarde que la structure d’attaque. Mais d’où viennent ces arguments ? Sont-ils bien fondés ? L’argumentation structurée ASPIC+ (Modgil & Prakken) répond à ces questions en donnant aux arguments une structure interne construite à partir d’une base de connaissances :

Composant Rôle Notation Tweety
Axiome (fait) une vérité tenue pour acquise -> p (règle sans prémisse)
Règle stricte déduction certaine (si prémisses vraies, conclusion vraie) p -> q
Règle défaisable déduction réfutable (typiquement vraie, mais des exceptions existent) p => q
Conclusion la formule déduite (ici propositionnelle) p, q, !p (négation)

Convention de notation Tweety (piège fréquent). À l’inverse de la convention mathématique usuelle (=> = implication stricte), Tweety affiche la flèche simple -> pour les règles strictes et la double flèche => pour les règles défaisables. Le drapeau booléen rule.isDefeasible() lève toute ambiguïté (false = strict, true = défaisable).

La question centrale d’ASPIC+ : étant donné une base de connaissances (faits + règles strictes + règles défaisables), quels arguments peut-on construire, quelles attaques en découlent, et finalement quelles conclusions sont acceptées ? ASPIC+ génère un cadre d’argumentation abstraite de Dung (AAF) à partir de la base structurée, puis on lui applique les sémantiques vues dans Tweety-3 (fondée, préférée, stable).

Ce notebook construit des théories ASPIC+ en C#, génère l’AAF sous-jacente, et montre sur l’exemple canonique (Tweety le pingouin) la divergence des sémantiques : prudente (fondée) vs tranchantes (préférée/stable).

1 — Runtime IKVM : charger le module arg-aspic

On installe le runtime IKVM, on fusionne l’image (base + arch), puis on charge la DLL org.tweetyproject.tweety-aspic.dll (compilée côté build à partir d’un fat-jar shade embarquant arg-aspic + ses dépendances transitives : arg-dung, arg-comparator, graphs, commons, math, logics-fol, logics-pl).

#r "nuget: IKVM, 8.15.0"
#r "nuget: IKVM.Image, 8.15.0"
Installed Packages
  • IKVM, 8.15.0
  • IKVM.Image, 8.15.0
using System.IO;
// RID de la machine courante (win-x64, linux-x64, osx-arm64...) : IKVM.Image tire l'image native de chaque plateforme.
string ikvmVer = "8.15.0", ikvmRid = (OperatingSystem.IsWindows() ? "win" : OperatingSystem.IsMacOS() ? "osx" : "linux") + "-" + System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();
string nugetRoot = Environment.GetEnvironmentVariable("NUGET_PACKAGES")
    ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
string ikvmBaseAny = Path.Combine(nugetRoot, "ikvm.image", ikvmVer, "ikvm", "any", "any");
string ikvmArchDir = Path.Combine(nugetRoot, "ikvm.image.runtime." + ikvmRid, ikvmVer, "ikvm", "any", ikvmRid);
string ikvmHome = Path.Combine(Path.GetTempPath(), "ikvm-home-" + ikvmVer + "-" + ikvmRid);
void IkvmCopyMerge(string src, string dst)
{
    foreach (var d in Directory.GetDirectories(src, "*", SearchOption.AllDirectories))
        Directory.CreateDirectory(d.Replace(src, dst));
    foreach (var f in Directory.GetFiles(src, "*", SearchOption.AllDirectories))
    {
        var t = f.Replace(src, dst);
        Directory.CreateDirectory(Path.GetDirectoryName(t));
        File.Copy(f, t, overwrite: true);
    }
}
if (Directory.Exists(ikvmBaseAny) && Directory.Exists(ikvmArchDir))
{
    Directory.CreateDirectory(ikvmHome);
    IkvmCopyMerge(ikvmBaseAny, ikvmHome);
    IkvmCopyMerge(ikvmArchDir, ikvmHome);
}
AppContext.SetData("IKVM.Home", ikvmHome);
Console.WriteLine("IKVM home=" + (File.Exists(Path.Combine(ikvmHome, "lib", "tzdb.dat")) ? "OK" : "MISSING"));
IKVM home=OK
#r "org.tweetyproject.tweety-aspic.dll"
// Constat 3 (#5039) : la directive #r est silencieuse par defaut en .NET Interactive.
// On verifie que la DLL IKVM/Tweety referencee est bien presente et lisible (metadata).
using System.Reflection;
var tweetyDll = "org.tweetyproject.tweety-aspic.dll";
var an = AssemblyName.GetAssemblyName(tweetyDll);
Console.WriteLine($"Tweety (IKVM) reference chargee : {an.Name} v{an.Version} ({new FileInfo(tweetyDll).Length / 1024 / 1024:F1} Mo).");
Tweety (IKVM) reference chargee : org.tweetyproject.tweety-aspic v1.30.0.0 (8.0 Mo).

2 — Construire une théorie ASPIC+

Une théorie ASPIC+ se construit avec AspicArgumentationTheory en lui passant un générateur de formules de règle (RuleFormulaGenerator) qui sait traduire les règles en formules logiques — pour la logique propositionnelle, c’est PlFormulaGenerator. On y ajoute ensuite :

  • des axiomes (faits) via addAxiom ;
  • des règles via addRule, instanciées comme StrictInferenceRule ou DefeasibleInferenceRule.

Détail de portage C#/.NET (IKVM). En Java, ces classes sont génériques (AspicArgumentationTheory<T extends Invertable>). Le port IKVM efface le paramètre de type : on les utilise sans argument générique (sinon erreur CS0308). Le type T est alors effacé vers sa borne Invertable ; une Proposition (logique propositionnelle) est un Invertable.

2.1 Faits et règle stricte

Construisons une petite théorie : un fait a, et une règle stricte « si a alors b ».

using org.tweetyproject.arg.aspic.syntax;
using org.tweetyproject.arg.aspic.ruleformulagenerator;
using org.tweetyproject.logics.pl.syntax;

var aat = new AspicArgumentationTheory(new PlFormulaGenerator());
var a = new Proposition("a");
var b = new Proposition("b");

aat.addAxiom(a);                 // fait : a est vrai

// regle stricte : a -> b   (a implique b avec certitude)
var strict = new StrictInferenceRule();
strict.setConclusion(b);
strict.addPremise(a);
aat.addRule(strict);

Console.WriteLine("theorie = " + aat);
Console.WriteLine("strict.isDefeasible() = " + strict.isDefeasible() + "  (false => STRICT, fleche '->')");
theorie = ArgumentationSystem [rules=[ -> a, a -> b]]
strict.isDefeasible() = False  (false => STRICT, fleche '->')

Lecture de la sortie : la théorie en une ligne, la flèche qui dit tout

theorie = ArgumentationSystem [rules=[ -> a, a -> b]] : l’objet construit s’imprime sous forme de liste de règles, et la première règle -> a est un fait (conclusion sans prémisse). La ligne suivante est le vrai signal : strict.isDefeasible() = False (false => STRICT, fleche '->') — la flèche affichée est une donnée de sortie, pas une convention visuelle. Les règles fléchées -> forment le socle strict de la théorie : la proposition a est un fait, b dérive de a par une règle totale, et aucune des deux n’est contestable. C’est cette base que la cellule 2.2 va desserrer en introduisant la première règle défaisable.

2.2 Règle défaisable

Ajoutons une règle défaisable « si a alors c » : c est typiquement dérivable, mais peut être réfuté par un argument contradictoire. On le vérifie avec isDefeasible().

var c = new Proposition("c");

// regle défaisable : a => c   (a implique c sauf exception)
var def = new DefeasibleInferenceRule();
def.setConclusion(c);
def.addPremise(a);
aat.addRule(def);

Console.WriteLine("theorie = " + aat);
Console.WriteLine("def.isDefeasible() = " + def.isDefeasible() + "  (true => DEFAISABLE, fleche '=>')");
theorie = ArgumentationSystem [rules=[ -> a, a => c, a -> b]]
def.isDefeasible() = True  (true => DEFAISABLE, fleche '=>')

Lecture du contraste : la même théorie, une flèche de plus

Comparez la liste des règles à la cellule précédente : rules=[ -> a, a => c, a -> b] — une seule différence, a => c, et la flèche double inverse le statut. La sortie le dit mot pour mot : def.isDefeasible() = True (true => DEFAISABLE, fleche '=>'). La règle « si a alors c » est une généralisation — en l’absence d’information contraire elle se tient, mais elle est attaquable : c’est exactement le matériau dont la section 3 aura besoin pour produire une vraie contradiction, et que la section 4 mettra en scène avec bird => flies contre penguin => !flies. Le couple des deux cellules pose ainsi les deux flèches de ASPIC+ par contraste de sortie avant tout discours théorique.

3 — Le pont vers Dung : asDungTheory()

ASPIC+ génère automatiquement les arguments (combinaisons de règles + faits) et les attaques entre eux, puis expose le résultat comme un cadre d’argumentation abstraite de Dung via asDungTheory(). On retrouve exactement les types de Tweety-3-Dung : DungTheory, Argument, Attack, Extension.

Sur notre théorie sans conflit (pas de conclusion contradictoire), on obtient plusieurs arguments sans aucune attaque — tous sont donc acceptés, quelle que soit la sémantique.

using org.tweetyproject.arg.dung.syntax;
using org.tweetyproject.arg.dung.semantics;
using org.tweetyproject.arg.dung.reasoner;

DungTheory dung = aat.asDungTheory();
Console.WriteLine("AAF generee = " + dung);
Console.WriteLine("nb arguments = " + dung.getNodes().size());
Console.WriteLine("attaques = " + dung.getAttacks());   // vide : pas de conflit

// Toutes les semantiques acceptent tout (zero attaque)
AbstractExtensionReasoner gr = new SimpleGroundedReasoner();
foreach (Extension ext in gr.getModels(dung).toArray(new Extension[0]))
    Console.WriteLine("extension fondee = " + ext);
AAF generee = <{  -> a, a => c [ -> a], a -> b [ -> a] },[]>
nb arguments = 3
attaques = []
extension fondee = { -> a,a => c [ -> a],a -> b [ -> a]}

Lecture du pont Dung : trois arguments, zéro attaque, une extension pleine

La génération de l’AAF est lisible ligne à ligne. AAF generee = <{ -> a, a => c [ -> a], a -> b [ -> a] },[]> : la notation Dung — un ensemble d’arguments, puis l’ensemble d’attaques (vide ici), et chaque argument affiche la règle dont il dérive avec le support entre crochets — [ -> a] rappelle que l’argument s’appuie sur le fait a. nb arguments = 3 : chaque règle de la théorie a produit exactement un argument. attaques = [] : aucun conflit — la règle défaisable n’est pas contredite par une règle adverse. Conséquence dans la sortie : extension fondee = { -> a, a => c [ -> a], a -> b [ -> a]} contient les trois arguments. Sans contradiction, les trois sémantiques de la section 3.1 coïncident — la divergence viendra de la section 4.

3.1 D’où vient une attaque ? La nécessité d’une vraie contradiction

Pour qu’une attaque naisse, deux arguments doivent conclure des formules contradictoires — par exemple flies et sa négation !flies. Deux atomes distincts comme flies et not_flies ne sont pas reconnus comme contradictoires par la logique propositionnelle : ils ne s’attaquent pas.

La négation se construit avec Negation(formula) (le complément au sens d’Invertable) : c’est elle qui déclenche les attaques de type rebuttal (un argument en concluant !p en attaque un autre concluant p).

4 — L’exemple canonique : Tweety le pingouin

Mettons tout en œuvre sur l’exemple classique du raisonnement défaisable :

  • Fait : Tweety est un pingouin (penguin) et un oiseau (bird).
  • Règle stricte : un pingouin est un oiseau (penguin -> bird), taxonomie certaine.
  • Règle défaisable : les oiseaux volent en général (bird => flies).
  • Règle défaisable : les pingouins ne volent pas (penguin => !flies).

On a donc deux arguments concluant des choses contradictoires sur le fait de voler : l’un (« Tweety vole ») depuis la règle des oiseaux, l’autre (« Tweety ne vole pas ») depuis la règle des pingouins. Ils s’attaquent mutuellement : c’est un conflit défaisable.

var aat2 = new AspicArgumentationTheory(new PlFormulaGenerator());
var bird = new Proposition("bird");
var peng = new Proposition("penguin");
var flies = new Proposition("flies");
var notFlies = new Negation(flies);   // complément reel -> declenche le rebuttal

aat2.addAxiom(bird);
aat2.addAxiom(peng);

// strict : penguin -> bird  (taxonomie certaine)
var s1 = new StrictInferenceRule(); s1.setConclusion(bird); s1.addPremise(peng);
aat2.addRule(s1);
// defaisable : bird => flies   (les oiseaux volent en general)
var d1 = new DefeasibleInferenceRule(); d1.setConclusion(flies); d1.addPremise(bird);
aat2.addRule(d1);
// defaisable : penguin => !flies   (les pingouins ne volent pas)
var d2 = new DefeasibleInferenceRule(); d2.setConclusion(notFlies); d2.addPremise(peng);
aat2.addRule(d2);

Console.WriteLine("=== Theorie ASPIC+ ===\n" + aat2);

DungTheory tweety = aat2.asDungTheory();
Console.WriteLine("\n=== AAF generee ===\n" + tweety);
Console.WriteLine("\nattaques = " + tweety.getAttacks());
=== Theorie ASPIC+ ===
ArgumentationSystem [rules=[ -> penguin,  -> bird, bird => flies, penguin => !flies, penguin -> bird]]

=== AAF generee ===
<{  -> bird, bird => flies [ -> bird], penguin => !flies [ -> penguin],  -> penguin, penguin -> bird [ -> penguin], bird => flies [penguin -> bird [ -> penguin]] },[(bird => flies [ -> bird],penguin => !flies [ -> penguin]), (penguin => !flies [ -> penguin],bird => flies [ -> bird]), (penguin => !flies [ -> penguin],bird => flies [penguin -> bird [ -> penguin]]), (bird => flies [penguin -> bird [ -> penguin]],penguin => !flies [ -> penguin])]>

attaques = [(bird => flies [ -> bird],penguin => !flies [ -> penguin]), (penguin => !flies [ -> penguin],bird => flies [ -> bird]), (penguin => !flies [ -> penguin],bird => flies [penguin -> bird [ -> penguin]]), (bird => flies [penguin -> bird [ -> penguin]],penguin => !flies [ -> penguin])]

Lecture de la génération : quatre attaques, et les paires sont symétriques

La théorie du pingouin met le pont Dung au travail. La liste des règles affichée d’abord — cinq règles, dont bird => flies et penguin => !flies — puis l’AAF générée : six arguments, parce que la règle dérivée du penguin -> bird strict donne naissance à un argument de plus (le flies dont la chaîne de prémisses passe par le fait penguin). Les attaques = [...] alignent quatre paires — et la lecture la plus instructive est leur symétrie : chaque paire d’arguments contradictoires (flies vs !flies, dans leurs deux dérivations) apparaît dans les deux sens. L’AAF imprimée est un graphe non orienté en pratique : la contradiction entre conclusions est réciproque, et c’est la sémantique qui décidera lequel des deux survivra.

4.1 Divergence des sémantiques

Les deux arguments sur le vol (flies vs !flies) s’attaquent mutuellement sans qu’aucun ne soit défendu. C’est exactement la situation d’attaque mutuelle vue dans Tweety-3, et les sémantiques divergent :

  • Fondée (sceptique) : on ne peut trancher → ni flies ni !flies ne sont acceptés. Les seuls arguments acceptés sont ceux non attaqués (bird, penguin, et penguin -> bird).
  • Préférée / Stable : deux extensions maximales — l’une accepte flies, l’autre !flies.
void Dump(string label, AbstractExtensionReasoner r, DungTheory theory)
{
    Console.WriteLine(label + " :");
    foreach (Extension ext in r.getModels(theory).toArray(new Extension[0]))
        Console.WriteLine("  " + ext);
}

Dump("Tweety fondée",   new SimpleGroundedReasoner(),  tweety);
Dump("Tweety préférée", new SimplePreferredReasoner(), tweety);
Dump("Tweety stable",   new SimpleStableReasoner(),    tweety);

Console.WriteLine("\n-- Lecture --");
Console.WriteLine("Fondee : Tweety vole-t-il ?  -> non tranche (flies ET !flies absents)");
Console.WriteLine("Preferee : deux mondes possibles (flies OU !flies), il faut choisir");
Tweety fondée :
  { -> bird, -> penguin,penguin -> bird [ -> penguin]}
Tweety préférée :
  { -> bird,bird => flies [ -> bird], -> penguin,penguin -> bird [ -> penguin],bird => flies [penguin -> bird [ -> penguin]]}
  { -> bird,penguin => !flies [ -> penguin], -> penguin,penguin -> bird [ -> penguin]}
Tweety stable :
  { -> bird,bird => flies [ -> bird], -> penguin,penguin -> bird [ -> penguin],bird => flies [penguin -> bird [ -> penguin]]}
  { -> bird,penguin => !flies [ -> penguin], -> penguin,penguin -> bird [ -> penguin]}

-- Lecture --
Fondee : Tweety vole-t-il ?  -> non tranche (flies ET !flies absents)
Preferee : deux mondes possibles (flies OU !flies), il faut choisir

Lecture des trois sémantiques : une fondée, deux préférées, deux stables

Les onze lignes de sortie comparées font la leçon de la section 4.1. Fondée : une seule extension { -> bird, -> penguin, penguin -> bird [ -> penguin]} — les faits et la taxonomie stricte, ni flies ni !flies : le scepticisme ne tranche pas sur le vol. Préférée : deux extensions — l’une avec bird => flies [ -> bird] (et sa dérivée), l’autre avec penguin => !flies [ -> penguin] — deux mondes maximaux, chacun excluant l’argument adverse. Stable : les deux mêmes ensembles — ici stable et préférée coïncident, car chaque extension attaque tout argument extérieur. Le « non tranché » de la fondée et le « il faut choisir » des préférées sont déjà imprimés par la cellule elle-même (section -- Lecture -- de la sortie) : les extensions illustrent mot pour mot ces deux verdicts.


Exercices

Stubs sans throw/raise (convention C.1) : le notebook s’exécute de bout en bout même non complété.

Exercice 1 — Lever l’indétermination par une règle stricte

Dans l’exemple Tweety ci-dessus, la sémantique fondée ne tranche pas : ni flies ni !flies ne sont acceptés (conflit défaisable symétrique). Ajoutez à aat2 une règle stricte penguin -> !flies (« les pingouins ne volent pas, c’est un fait certain ») et ré-affichez l’extension fondée.

Question : !flies est-il maintenant accepté sceptiquement ? Pourquoi une conclusion strictement dé rivable ne peut-elle pas être réfutée par un argument défaisable ?

Indice : créez un nouveau StrictInferenceRule de conclusion notFlies et de prémisse peng, ajoutez-le à aat2, régénérez le DungTheory, et relancez SimpleGroundedReasoner.

// TODO etudiant : ajouter la regle stricte penguin -> !flies, puis re-afficher la fondee
// Indice : new StrictInferenceRule(); .setConclusion(notFlies); .addPremise(peng); aat2.addRule(...)
string verdictFlies = null;   // TODO etudiant : "accepte" si !flies dans l'extension fondee, sinon "rejete"/"non tranche"
Console.WriteLine("!flies skeptiquement accepte ? " + (verdictFlies ?? "Exercice a completer"));
!flies skeptiquement accepte ? Exercice a completer

Exercice 2 — Cycle défaisable à trois

Construisez une théorie ASPIC+ avec trois faits p, q, r et trois règles défaisables formant un cycle de contradictions : p => q, q => r, r => !p (de sorte que p et !p coexistent via la chaîne). Générez l’AAF et comparez l’extension fondée et les extensions préférées.

Question : combien d’extensions préférées obtient-on ? L’extension fondée contient-elle une conclusion sur p ?

Indice : comme dans Tweety-3, un cycle d’attaques mutuelles sans argument défendu donne une fondée prudente et plusieurs préférées maximales.

// TODO etudiant : cycle defaisable p => q => r => !p, comparer fondee vs preferee
// Indice : 3 axiomes p,q,r + 3 DefeasibleInferenceRule. asDungTheory() puis Dump(...).
object nbPrefereesCycle = null;   // TODO etudiant : nombre d'extensions preferees (int)
Console.WriteLine("extensions preferees du cycle = " + (nbPrefereesCycle ?? "Exercice a completer"));
extensions preferees du cycle = Exercice a completer

Exercice 3 — Votre propre mini-théorie (débat juridique ou médical)

Construisez une théorie ASPIC+ de votre choix sur le modèle suivant : un fait initial, une règle stricte et deux règles défaisables aboutissant à des conclusions contradictoires (usage de Negation). Affichez la théorie, l’AAF générée et les attaques.

Exemple : « un patient a de la fièvre » (fever), règle stricte « infection ⇒ fièvre n’est pas une règle, plutôt : flu -> fever », défaisable « fièvre ⇒ antibiotique », défaisable « allergie ⇒ ! antibiotique ». Prédisez l’extension fondée avant de l’exécuter, puis vérifiez.

Indice : traduisez en Proposition + une Negation. La conclusion du raisonnement fondé est la même que pour Tweety : suspension tant que les deux camps défaisables s’équilibrent.

// TODO etudiant : mini-theorie (1 fait + 1 regle stricte + 2 defaisables contradictoires)
// Indice : AspicArgumentationTheory + addAxiom + StrictInferenceRule + 2 DefeasibleInferenceRule (conclusions p et Negation(p)).
string predictionVerdict = null;   // TODO etudiant : ce que vous PREDISEZ pour la fondee (puis verifiez)
Console.WriteLine("verdict fondee prédit = " + (predictionVerdict ?? "Exercice a completer"));
verdict fondee prédit = Exercice a completer

Conclusion

On a porté en C#/.NET natif (sans JVM) l’argumentation structurée ASPIC+ via le module arg-aspic et IKVM, en montrant le pont vers l’argumentation abstraite de Dung :

  1. Construction d’une base de connaissances structurée : faits (axiomes), règles strictes (->, certaines) et règles défaisables (=>, réfutables) — via AspicArgumentationTheory, addAxiom, StrictInferenceRule/DefeasibleInferenceRule.
  2. Génération automatique d’un cadre d’argumentation abstraite (AAF) : asDungTheory() produit les arguments (combinaisons de règles) et les attaques (conflits par complémentarité, Negation).
  3. Raisonnement via les sémantiques de Dung (fondée / préférée / stable), avec la divergence canonique sur l’exemple de Tweety : la fondée suspend, les préférée/stable tranchent.

Abstrait (Dung) vs Structuré (ASPIC+)

Aspect Dung (Tweety-3) ASPIC+ (Tweety-4)
Argument nœud opaque (boîte noire) structure interne (règles + prémisses → conclusion)
Origine des arguments donnée (à la main) générée depuis une base de connaissances
Origine des attaques déclarées (Attack) déduites des contradictions (compléments)
Force des arguments uniforme dépend des règles (strict / défaisable, ordres)

Références

  • Modgil, S. & Prakken, H. The ASPIC+ framework for structured argumentation: a tutorial. Argument & Computation, 2014.
  • Prakken, H. An abstract framework for argumentation with structured arguments. Argument & Computation, 2010.
  • Dung, P. M. On the Acceptability of Arguments… (sémantiques sous-jacentes). AI, 1995.
  • TweetyProject — arg-aspic module.
  • Port C#/.NET via IKVM — EPIC #4667.

Le bilan du pont Dung en chiffres de sortie : théorie simple — trois arguments, zéro attaque, une extension fondée pleine ; théorie du pingouin — six arguments, quatre attaques en paires symétriques, une fondée sceptique et deux préférées/stables. Le même mécanisme de traduction produit l’unanimité ou le conflit selon l’ontologie : c’est la quantification exacte de la phrase d’ouverture — ASPIC+ génère le débat, la sémantique le juge.

Retour au sommet