diff --git a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-02b-Semantics-CSharp.ipynb b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-02b-Semantics-CSharp.ipynb index c729f1dbf0..3d6c317895 100644 --- a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-02b-Semantics-CSharp.ipynb +++ b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-02b-Semantics-CSharp.ipynb @@ -183,6 +183,20 @@ "Console.WriteLine($\"Tweety (IKVM) reference chargee : {an.Name} v{an.Version} ({new FileInfo(tweetyDll).Length / 1024 / 1024:F1} Mo).\");" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Pourquoi un pont Java→.NET ?** Les cellules de configuration ci-dessus chargent la bibliothèque\n", + "**TweetyProject** — écrite en Java — *dans* le processus .NET, via IKVM (une réimplémentation du\n", + "runtime Java en bytecode .NET). Le choix pédagogique est assumé : TweetyProject est l'implémentation\n", + "de référence des logiques pour agents (argumentation, croyances, préférences), maintenue et testée\n", + "par la communauté ; la réécrire « pour faire C# » perdrait ce référentiel. Le pont rend les deux\n", + "mondes comparables : même signature, mêmes mondes, mêmes verdicts — et le jour où un twin C#\n", + "from-scratch existe pour un module, la parité se **mesure** contre cette référence au lieu d'être\n", + "supposée." + ] + }, { "cell_type": "markdown", "id": "m22726", @@ -290,6 +304,20 @@ "Console.WriteLine($\"=> {n} mondes pour 2 atomes (2^2 = 4).\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**La structure des mondes.** Les quatre mondes affichés ne sont pas une liste plate : ordonnés par\n", + "inclusion (`[]` ⊂ `[a]` ⊂ `[a,b]`), ils forment le **cube** B_n — l'hypercube des valuations (pour\n", + "2 atomes, un carré ; pour n, un n-cube). Deux propriétés de cette structure servent toute la suite :\n", + "\n", + "- le monde vide `[]` et le monde plein `[a,b]` sont les deux extrêmes (tout-faux / tout-vrai) ;\n", + "- les formules **monotones** (sans négation d'atome) décrivent des *up-sets* du cube — leur ensemble\n", + " de modèles est stable par ajout d'atomes. Les requêtes des sections 3-4 se lisent alors\n", + " géométriquement : intersecter des up-sets, chercher des contre-exemples en descendant." + ] + }, { "cell_type": "markdown", "id": "m33502", @@ -404,6 +432,23 @@ "Console.WriteLine($\" w satisfait a => b = {w.satisfies(fIMP)}\"); // faux (a vrai, b faux)\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**La localité de la satisfaction.** Toutes les réponses ci-dessus portent sur **un seul** monde\n", + "`w = [a]` : `satisfies` est une question *locale* (ce monde-ci, cette formule-ci). C'est la brique\n", + "atomique de toute la sémantique — les notions des sections suivantes ne sont que cette brique\n", + "*quantifiée* :\n", + "\n", + "- « modèle de F » = **il existe** un monde qui satisfait F ;\n", + "- « F valide » = **tous** les mondes satisfont F ;\n", + "- « KB |= b » = **tous** les mondes qui satisfont KB satisfont aussi b.\n", + "\n", + "Un bug de `satisfies` contamine donc toute la chaîne — d'où le soin de TweetyProject sur cette\n", + "méthode, et le test visuel facile : sur `w = [a]`, `b` doit échouer, `a||b` doit passer." + ] + }, { "cell_type": "markdown", "id": "m5545", @@ -466,6 +511,21 @@ "Console.WriteLine($\"Conjonction complete dans {{a,b,c}} = {w.getCompleteConjunction(sig)}\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Pourquoi une forme canonique ?** La sortie montre la correspondance terme à terme : chaque monde\n", + "possède **exactement une** conjonction complète (`[a, c]` ↔ `a&&c&&!b`). C'est une bijection monde ↔\n", + "formule — chaque monde de 2^n est *nommé* par une formule unique. Deux usages immédiats :\n", + "\n", + "- **non-ambiguïté** : deux formules différentes peuvent être équivalentes (`a&&b` vs `b&&a`), mais\n", + " deux conjonctions complètes distinctes désignent toujours des mondes distincts — le forme canonique\n", + " est l'identifiant du monde ;\n", + "- **passe-partout** : toute formule F s'écrit comme disjonction *exacte* des conjonctions complètes\n", + " de ses modèles (forme normale disjonctive pleine) — la base des compteurs de modèles." + ] + }, { "cell_type": "markdown", "id": "m88739", @@ -553,6 +613,21 @@ "Console.WriteLine($\"KB |= !a ? {r.query(kb, (PlFormula)p.parseFormula(\"!a\"))}\"); // faux : KB contient a\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**L'asymétrie de l'entailment.** Le verdict `KB |= b = true` ci-dessus a un coût de preuve\n", + "*dissymétrique* selon le sens :\n", + "\n", + "- **confirmer** exige de vérifier **tous** les modèles de KB (aucun contre-exemple) — coût 2^n ;\n", + "- **réfuter** suffit d'**un seul** monde contre-exemple (un modèle de KB où `b` échoue) — coût 1.\n", + "\n", + "C'est pourquoi le raisonnement automatique cherche toujours le contre-exemple d'abord : une seule\n", + "valuation réfutatrice tranche ce que l'énumération complète mettrait 2^n étapes à certifier. Le\n", + "`SatReasoner` de la cellule suit exactement cette stratégie (chercher un modèle de `KB ∧ ¬b`)." + ] + }, { "cell_type": "markdown", "id": "m72867", @@ -679,6 +754,20 @@ "Console.WriteLine($\"=> {models} modele(s) sur 8.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture des quatre survivants.** Sur les 8 mondes de `{a, b, c}`, exactement 4 restent : ceux où\n", + "l'heredité de la chaîne est respectée — jamais `a` sans `b`, jamais `b` sans `c`. Chacun des 4 mondes\n", + "exclus viole une flèche précise (`[a]`, `[a,b]` cassent `a=>b` ou `b=>c`...). Deux lectures utiles :\n", + "\n", + "- **généralisation** : énumérer les modèles de KB = filtrer la table de vérité sur les lignes qui\n", + " satisfont *toutes* les formules — la sémantique est un *filtre*, pas un calcul symbolique ;\n", + "- **comptage** : `4/8` est une mesure (le problème #SAT compte les modèles) — c'est la porte\n", + " d'entrée des sémantiques probabilistes : poser P uniforme sur les mondes et conditionner par KB." + ] + }, { "cell_type": "markdown", "id": "m96153", @@ -731,6 +820,20 @@ "Java minuscules). Rappel : les stubs doivent s'executer sans erreur (jamais `raise`/`assert`/`1/0`).\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Le protocole des exercices.** Les trois exercices rejouent les gestes des sections 2-4 en\n", + "montant en généralité : le premier classifie une formule (tautologie / contradiction / contingence) —\n", + "c'est une propriété **absolue**, indépendante de toute base ; le deuxième définit l'**équivalence\n", + "logique** comme double entailment (`F |= G` et `G |= F`) — un cas particulier de la section 4 ; le\n", + "troisième cherche une conséquence **cachée** d'une KB, là où l'intuition seule ne suffit plus. Les\n", + "squelettes sont exécutables tels quels (C.1) ; pour chacun, la stratégie gagnante est la même qu'en\n", + "cours : traduire la question en une requête sur les mondes, puis laisser l'énumérateur ou le\n", + "`SatReasoner` trancher." + ] + }, { "cell_type": "markdown", "id": "m45853", @@ -746,6 +849,24 @@ "comparer au total `2^n`.\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Attendus, pour auto-vérification.** Avec la signature `{a, b}` (4 mondes), la classification se\n", + "lit directement sur l'énumération : une **tautologie** est vraie dans les 4 mondes (ex. `a||!a`), une\n", + "**contradiction** dans aucun (ex. `a&&!a`), une **contingence** dans certains seulement. Le réflexe à\n", + "institutionnaliser : *ne pas raisonner sur la formule, raisonner sur ses modèles* — la table des 4\n", + "mondes tranche toute question de ce niveau, sans calcul symbolique. Pour l'équivalence de l'exercice 2,\n", + "la double requête d'entailment doit donner **deux fois vrai** pour une équivalence réelle (et le\n", + "contre-exemple apparaît dès qu'un seul sens échoue : exhibez le monde réfutateur, pas juste\n", + "le booléen).\n", + "\n", + "Pour l'exercice 3, un conseil de méthode : listez d'abord à la main les modèles de la KB, puis\n", + "regardez quelles formules y sont vraies *partout* — la conséquence cachée est celle qui survit à ce\n", + "filtre sans être évidente à lire sur la syntaxe." + ] + }, { "cell_type": "code", "execution_count": 10, diff --git a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-08-Agent-Dialogues-CSharp.ipynb b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-08-Agent-Dialogues-CSharp.ipynb index c1716dc545..4035a6b41c 100644 --- a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-08-Agent-Dialogues-CSharp.ipynb +++ b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-08-Agent-Dialogues-CSharp.ipynb @@ -57,7 +57,6 @@ " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n", " \r\n", " \r\n", @@ -347,6 +338,22 @@ "// Attendu : {D} (D defait C, donc C exclu ; sans C, A est attaquant ? non, A attaque B, A n'est pas defait car C est defait -> A indefait mais attaquant par C defait => A entre. Re-calculons.)\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture de l'extension grounded.** La sortie distingue acceptés (`D`, `A`) et rejetés implicitement\n", + "(`B`, `C` attaqués hors de l'extension). La sémantique **grounded** de Dung est la plus *prudente* :\n", + "elle part de l'ensemble vide et n'accepte un argument que s'il survit à toutes les attaques non\n", + "réfutées — construction par point fixe (d'abord les arguments sans attaquant, puis ceux qu'ils\n", + "défendent, etc.). Deux lectures du verdict affiché :\n", + "\n", + "- **sceptique par construction** : tout ce que grounded accepte, toutes les autres sémantiques\n", + " (préférée, stable) l'acceptent aussi — c'est le plancher commun ;\n", + "- **rejet ≠ faux** : `C` n'est pas « faux », il est *non défendable* dans cette théorie — changer une\n", + " seule attaque peut le réhabiliter (la Partie 4 le montrera en enrichissant l'AF)." + ] + }, { "cell_type": "markdown", "id": "bf497e56-3021-422c-a715-7b419c404ac1", @@ -467,6 +474,20 @@ "Show(antiAgent.Name + \" KB\", string.Join(\", \", antiAgent.Knowledge));\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ce qui fait un agent « argumentatif ».** Le modèle ci-dessus tient en trois états : une **base de\n", + "connaissances** (ce que l'agent croit), un **stock d'engagements** (ce qu'il a *dit* — et dont il devra\n", + "répondre), et les **locutions** (`Claim`, `Argue`, `Concede`, `Retract`) comme seuls gestes de parole.\n", + "La distinction croire/dit est la clé : un agent peut être forcé de `Retract` un `Claim` attaqué sans\n", + "renier sa KB — il reconnaît avoir perdu *ce point-ci*, pas la guerre. C'est ce qui distingue un dialogue\n", + "argumentatif d'un échange d'opinions : chaque locution crée une **obligation vérifiable** (justifier un\n", + "`Claim` si on l'attaque), et le protocole peut rejeter un coup illégal — la rationalité est\n", + "procédurale, pas supposée." + ] + }, { "cell_type": "markdown", "id": "a97fb4c4-6818-4cf4-ae8f-25323f477dbb", @@ -593,6 +614,22 @@ "Show(\"Verdict\", $\"{outcome} — {why}\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture de la trace — pourquoi Pro-TL gagne.** Le verdict `ProponentWins` vient d'un événement\n", + "précis : `Concede(le_teletravail_est_souhaitable)` au tour 2. Le protocole ne dit pas *comment* gagner\n", + "(il autorise les coups légaux), la stratégie de l'agent (quelle locution jouer) décide. Ici, Anti-TL\n", + "n'a pas su produire de contre-argument inattaquable — son unique attaque est contrée dans la KB adverse.\n", + "Deux observations :\n", + "\n", + "- le **résultat du dialogue** coïncide avec l'acceptation **grounded** de la thèse dans l'AF sous-jacent\n", + " — ce n'est pas un hasard : un dialogue bien formé est une *preuve interactive* de statut accepté ;\n", + "- un protocole sans règle de terminaison peut boucler (Claim/Retract indéfinis) — la limite de tours\n", + " du framework est une garde, pas un détail." + ] + }, { "cell_type": "markdown", "id": "7d355049-86c2-4a1a-a641-cc4c524fd75c", @@ -683,6 +720,19 @@ "Show(\"Verdict negociation\", $\"{o1} — {w1}\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du scénario d'achat.** L'AF `negociation` se lit comme un duel d'arguments immobiliers :\n", + "`COMP(comparables_bas)` et `UPG(travaux_prevus_deductibles)` ressortent acceptés par l'extension\n", + "grounded — le squelette de l'offre s'impose — pendant que `OVR` (prix haut vs marché) est attaqué.\n", + "Contrairement au débat télétravail, la négociation ici n'a qu'une **position initiale** de chaque côté :\n", + "la suite réelle d'une négociation (contre-offres, concessions conditionnelles) est précisément ce que\n", + "le protocole de dialogue de la Partie 3 outille — les locutions `Concede`/`Retract` sont les gestes de\n", + "la table de négociation." + ] + }, { "cell_type": "markdown", "id": "998bee6d-c4d8-4288-8831-92cfa9f4e1d5", @@ -769,6 +819,19 @@ "Show(\"Verdict teletravail\", $\"{o2} — {w2}\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ce que l'enrichissement a changé.** Avant l'attaque `CT`, l'AF de la Partie 2 donnait la parole\n", + "aux pro-télétravail ; avec `CT(le_teletravail_isole_socialement)` et sa contre-attaque `S`, l'extension\n", + "grounded affichée intègre de nouveaux acceptés — la composition du débat a changé *sans qu'aucun\n", + "argument existant ne bouge*. Leçon structurelle : l'acceptation grounded est **globale** — ajouter un\n", + "argument n'importe où peut requalifier des arguments sans lien direct avec lui (via les chaînes\n", + "d'attaques). C'est la différence avec une base de croyances classique, où ajouter un fait ne retire\n", + "rien. Dans un débat réel : introduire un nouvel argument n'est jamais une opération locale." + ] + }, { "cell_type": "markdown", "id": "0da7f67f-d0f4-441b-8e6b-d4861ad0775c", @@ -870,6 +933,19 @@ "Show(\"Decision rationnelle\", uPro >= uAnti ? \"Pro-TL soutient le teletravail\" : \"Anti-TL s'oppose au teletravail\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture de la décision.** Les espérances mesurées (`Pro-TL = 1,374` vs `Anti-TL = 0,731`) tranchent\n", + "en faveur du télétravail — mais il faut lire *ce que* la loterie évalue : chaque issue possible\n", + "(acceptation/rejet d'un argument) pondérée par sa croyance, chaque issue portant une utilité. La\n", + "décision est rationnelle **relativement aux utilités déclarées** — changez les poids (par ex. la\n", + "désutilité de l'isolement social `CT`) et le verdict peut basculer : c'est exactement le débat\n", + "politique réel, où les parties ne divergent souvent pas sur les faits mais sur les poids. Le calcul ne\n", + "remplace pas le choix de valeurs ; il le rend explicite et discutable." + ] + }, { "cell_type": "markdown", "id": "c3feac81", @@ -1131,6 +1207,19 @@ "Les exercices ci-dessous sont à compléter. Chaque stub s'exécute sans erreur (convention C.1) — remplacez le `TODO` par votre implémentation.\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Le protocole des exercices.** Les trois exercices complètent le framework dans ses directions\n", + "naturelles : les **extensions préférées** (la sémantique crédulous — tout ensemble maximal admissible —\n", + "là où `grounded` était la plus prudente), un **tour de parole multi-agents** (généraliser le dialogue à\n", + "1-contre-1 de la Partie 3 en délibération à N), et l'**utilité exacte** de la Partie 5 (remplacer\n", + "l'espérance simulée par le calcul exact sur les extensions). Les squelettes sont exécutables tels quels\n", + "(C.1) ; chaque cellule annonce ce qu'elle doit afficher quand la solution est juste — ce sont vos\n", + "critères d'acceptation." + ] + }, { "cell_type": "code", "execution_count": 9, diff --git a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-11-Causal-Csharp.ipynb b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-11-Causal-Csharp.ipynb index ca8b37b73c..a919eedd2f 100644 --- a/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-11-Causal-Csharp.ipynb +++ b/MyIA.AI.Notebooks/SymbolicAI/Tweety/Tweety-11-Causal-Csharp.ipynb @@ -398,6 +398,19 @@ "Show(\"StructuralCausalModel + parser de formules + propagation + Intervene (do-operator) prets.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ce que « from scratch » veut dire ici.** Le moteur définit ci-dessus les trois briques minimales\n", + "d'un modèle causal structural (Pearl) en C# pur : les **variables de fond** (`storm` — des faits\n", + "exogènes sans équation), les **équations structurelles** (`drops <=> storm` — chaque variable\n", + "expliquée est une fonction de ses causes), et l'**intervention** `do` (remplacer une équation par une\n", + "constante — la « chirurgie »). Pas de probabilités dans cette version : les valeurs sont booléennes et\n", + "la propagation déterministe, ce qui isole la *structure* du raisonnement causal — le squelette que la\n", + "version probabiliste habille ensuite de chiffres." + ] + }, { "cell_type": "markdown", "id": "1ad2c98d", @@ -528,6 +541,23 @@ "Show(\"CausalKnowledgeBase + InterventionalStatement + CounterfactualStatement + CausalReasoner prets.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Les trois modes d'interrogation.** Le `CausalReasoner` exposé ci-dessus distingue exactement les\n", + "trois régimes de requêtes qui structurent la suite du notebook :\n", + "\n", + "- `observe(X)` — *conditionnement* : « sachant ce que je vois, que déduire ? » (statistique) ;\n", + "- `do(X)` — *intervention* : « si je force X, que devient le système ? » (la flèche entrante de X est\n", + " coupée, son équation remplacée par la valeur forcée) ;\n", + "- contrefactuel — *rétro-mondes* : « dans le monde qui explique mon observation, si X avait différé... »\n", + "\n", + "L'API du reasoner est volontairement verbeuse sur ce point : confondre `observe` et `do` est l'erreur\n", + "n°1 du raisonnement causal, et le type (`ObservationalStatement` vs `InterventionalStatement` vs\n", + "`CounterfactualStatement`) rend la confusion impossible à écrire par accident." + ] + }, { "cell_type": "markdown", "id": "7f7d8cbd", @@ -791,6 +821,20 @@ "Show(\" Le lien storm -> drops est ROMPU : drops ne depend plus de storm.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Que lit-on dans la chirurgie ?** En comparant les deux affichages : le SCM original porte trois\n", + "équations (`drops <=> storm`, `rain <=> storm`) ; le SCM après `do(drops=True)` ne porte plus\n", + "l'équation de `drops` — remplacée par une constante. Deux conséquences immédiates :\n", + "\n", + "- l'observation `drops=True` n'informe plus sur `storm` (plus de canal) : `P(rain | do(drops))`\n", + " retombe sur la valeur de base — le baromètre cassé ne fait pas pleuvoir ;\n", + "- la *corrélation* `drops ⇔ rain` de la section 3 a disparu **par construction**, sans toucher aux\n", + " données : c'est une modification du mécanisme générateur, pas un filtrage d'échantillons." + ] + }, { "cell_type": "markdown", "id": "fa30c257", @@ -879,6 +923,21 @@ "Show(\"Base causale prete.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du réseau.** Trois différences structurelles avec le baromètre méritent d'être dites avant\n", + "de lancer les requêtes :\n", + "\n", + "- le nœud `cloudy` est la **cause commune** de deux effets indépendants (`sprinkler`, `rain`) — c'est\n", + " un *confondu* : il crée de la corrélation entre ses deux enfants sans que l'un cause l'autre ;\n", + "- `wet` est un **collier** (collider) : il a deux parents. La corrélation entre `sprinkler` et `rain`\n", + " est nulle par défaut, mais elle *apparaît* dès qu'on conditionne sur `wet` (sélection sur l'effet) ;\n", + "- les équations sont déterministes (`<=>`), la version probabiliste de Pearl remplacerait chaque\n", + " `<=>` par une table conditionnelle — le raisonnement structurel, lui, est identique. C'est le biais de sélection dans sa forme la plus pure : filtrer sur un effet fabrique de la dépendance entre ses causes." + ] + }, { "cell_type": "code", "execution_count": 8, @@ -1104,6 +1163,25 @@ "Show(\" -> Oui : sous cloudy=True, rain aurait mouille l'herbe meme sans arrosage.\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Les trois temps du contrefactuel.** Le verdict `True` ci-dessus se déroule en trois étapes, toutes\n", + "présentes dans le code de la cellule :\n", + "\n", + "1. **Abduction** — conditionner sur l'observation `wet=True` : le monde possible est reconstitué\n", + " (`cloudy=True`, donc `rain=True` a eu lieu — c'est l'inférence qui explique le fait observé) ;\n", + "2. **Action** — appliquer l'antécédent du contrefactuel *dans ce monde* : écraser l'équation\n", + " `sprinkler` avec `OFF` (la même chirurgie `do` que section 4, mais dans le monde contrefactuel) ;\n", + "3. **Prédiction** — évaluer la conséquence dans le monde modifié : `rain` reste actif, l'herbe\n", + " reste mouillée, réponse `True`.\n", + "\n", + "C'est exactement la structure du raisonnement « si Napoléon n'avait pas... » : on n'imagine pas un monde\n", + "au hasard, on imagine *le nôtre* avec une seule équation changée. Le contraste avec l'exercice 3 sera instructif : quand l'antécédent porte sur la *cause*, la\n", + "même machinerie répond l'inverse." + ] + }, { "cell_type": "markdown", "id": "a3c3afb8", @@ -1331,6 +1409,17 @@ "Show(\" coupe bien le lien cloudy -> sprinkler, exactement comme la chirurgie from-scratch du §3.\");" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du pont.** Les trois sorties ci-dessus montrent le même réseau, la même intervention et le\n", + "même contrefactuel que les sections 3-5, mais calculés par le moteur **TweetyProject** (Java) exécuté\n", + "dans le processus .NET via IKVM. L'intérêt pédagogique est la **parité** : notre implémentation\n", + "from-scratch des sections 1-2 n'est pas une simplification qualitative, elle reproduit le comportement\n", + "de la référence académique — l'écart éventuel serait un bug de notre moteur, pas une limite de méthode." + ] + }, { "cell_type": "markdown", "id": "7c9dd2d6", @@ -1405,6 +1494,34 @@ "> mais l'intervention `do(education)` coupe ce lien — l'effet direct devrait tomber à False." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Le protocole des exercices.** Les trois exercices suivants rejouent les gestes des sections 3-5 sur\n", + "des réseaux inédits, chacun ciblant une confusion classique : l'exercice 1 distingue observation et\n", + "intervention sur une chaîne `education → skill → income` ; l'exercice 2 montre qu'un `do` ne remonte\n", + "pas la flèche causale (intervenir sur un effet ne change pas la cause) ; l'exercice 3 demande le\n", + "contrefactuel *sur la cause* cette fois — le miroir de la section 5. Les squelettes sont exécutables\n", + "tels quels (C.1) : chaque cellule affiche ce qu'il faut construire, et les indices suffisent à écrire\n", + "les 3-5 lignes attendues avec l'API des sections 1-2." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Attendu de l'exercice 1, pour auto-vérification.** Si votre implémentation est juste :\n", + "`observe(skill=True)` doit propager vers `income=True` (la corrélation se lit dans les deux sens sur\n", + "la chaîne), tandis que `do(skill=True)` doit laisser `education` à sa valeur de fond — l'intervention\n", + "coupe la flèche entrante, elle ne la remonte pas. Ce couple de verdicts est le même discriminant que\n", + "le réseau Sprinkler de la section 4 : c'est la signature qu'on interroge le mécanisme, pas seulement\n", + "la corrélation.\n", + "\n", + "Un contrôle anti-piège utile : si vos deux verdicts sont identiques, vous avez probablement écrit\n", + "`observe` aux deux endroits — le `do` se reconnaît à ce que SA cible garde sa valeur de fond." + ] + }, { "cell_type": "code", "execution_count": 12, @@ -1596,6 +1713,25 @@ "Show(\" (reflechir : cloudy est la cause de rain ; si cloudy avait ete faux, rain n'aurait pas eu lieu)\");\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Synthèse — les trois barreaux de l'échelle causale\n", + "\n", + "Les sections précédentes ont gravi, dans l'ordre, les trois barreaux de l'échelle de la causalité (Pearl) :\n", + "\n", + "| Barreau | Question | Outil du notebook | Exemple mesuré |\n", + "|---|---|---|---|\n", + "| 1. **Associer** | *que voit-on ensemble ?* | `observe` sur le SCM propagé | `observe(drops)` → `rain=True` (corrélation baromètre/pluie) |\n", + "| 2. **Intervenir** | *que se passe-t-il si je force ?* | `do` = chirurgie sur l'équation | `do(rain)` n'active plus `sprinkler` dans le réseau de sec. 4 |\n", + "| 3. **Imaginer** | *qu'aurait-il fallu d'autre ?* | contrefactuel `cf` | herbe mouillée même avec `sprinkler=OFF` car `rain` suffisait |\n", + "\n", + "La coupure entre barreau 1 et barreau 2 est LA leçon du notebook : aucune quantité d'observation, aussi\n", + "grande soit-elle, ne remplace l'intervention — c'est une différence de *nature* (le modèle structural),\n", + "pas de degré (plus de données)." + ] + }, { "cell_type": "markdown", "id": "02c12c96", @@ -1610,7 +1746,7 @@ "tags": [] }, "source": [ - "---\n", + "***\n", "\n", "## Synthèse\n", "\n", diff --git a/scripts/notebook_tools/twin_pairs.d/tweety-11-causal.yaml b/scripts/notebook_tools/twin_pairs.d/tweety-11-causal.yaml index cd7ec3b426..f4c00eafa1 100644 --- a/scripts/notebook_tools/twin_pairs.d/tweety-11-causal.yaml +++ b/scripts/notebook_tools/twin_pairs.d/tweety-11-causal.yaml @@ -6,5 +6,6 @@ bridge_verdict: SOTA-OK bridge_verdict_reason: "Python = JPype vers la vraie lib Java Tweety causal-1.30 (`from org.tweetyproject.causal.reasoner import ArgumentationBasedCausalReasoner`). C# = §§1-5 from-scratch pedagogique (do-calculus reimplemente, titre 'twin C# from-scratch') + §6 (PR #10570) pont IKVM chargeant `org.tweetyproject.tweety-causal.dll` (DLL build #10566, 13/13 classes causales actives, verifie firsthand via Assembly.GetExportedTypes) : `StructuralCausalModel.intervene()` Java reel invoque sous le runtime IKVM 8.15. Verdict SOTA-OK (pas de workaround degrade) : §6 prouve la parite moteur-contre-moteur -- `do(sprinkler=True)` produit `sprinkler <=> +` (surgery Java reel) IDENTIQUE au do-calculus from-scratch §3 `do(drops=True)` -> `drops <=> +`. Les DEUX cotes executent le meme moteur Java Tweety causal (Python via JPype, C# via IKVM). parity_level reste `surface` car le mode pedagogique primaire reste §§1-5 from-scratch ; §6 est le pont de validation qui confirme la conformite du from-scratch au moteur de reference." known_differences: + - "2026-09-15 (PR #16319, myia-po-2026:CoursIA) : enrichissement markdown-only cote C# (tranche densite #13410, +9 cellules d'interpretation) ; cellules code et outputs byte-identiques (md5 avant/apres), twin Python intact." - "Socle commun : inference causale et do-calculus (Pearl) sur modeles causaux structurels." - "Asymetrie de profondeur (surface) : le Python s'appuie sur la vraie bibliotheque Java Tweety `causal-1.30.jar` via JPype (`from org.tweetyproject.causal.reasoner import ArgumentationBasedCausal`). C# §§1-5 = jumeau **from-scratch** pedagogique (titre 'twin C# from-scratch', reimplemente le do-calcul) ; §6 (PR #10570) ajoute un pont IKVM vers la meme DLL Java `tweety-causal.dll` (build #10566) -- §§1-5 from-scratch et pont §6 donnent le meme resultat surgery (`<=> +`), validant la conformite du from-scratch au moteur de reference. Parite `surface` (mode primaire = from-scratch) avec pont de validation SOTA-OK en §6." diff --git a/scripts/notebook_tools/twin_pairs.d/tweety-11-causal/0008-2026-09-15-myia-po-2026-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/tweety-11-causal/0008-2026-09-15-myia-po-2026-CoursIA.yaml new file mode 100644 index 0000000000..1b1e062471 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/tweety-11-causal/0008-2026-09-15-myia-po-2026-CoursIA.yaml @@ -0,0 +1,6 @@ +date: '2026-09-15' +by: myia-po-2026:CoursIA +python_sha: d8abf3fce2e6d71d04c160b34fd74addd24c65ef +csharp_sha: a919eedd2fb911c4425cae20225ee24206688a38 +content_python_sha: a8d04cee11f38bed81bded594d1d4330d9b700bad0589292a201ac0d67912d00 +content_csharp_sha: 319edb11d6f0c9d7cec4f6c6f0e17283588d6563f6a5f3c36afe8501d42b7d61 diff --git a/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues.yaml b/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues.yaml index 7e36b4ef88..e82a6784b1 100644 --- a/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues.yaml +++ b/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues.yaml @@ -6,5 +6,6 @@ bridge_verdict: SOTA-OK bridge_verdict_reason: 'Lib-vs-lib meme moteur Java TweetyProject (agents/dialogues/oppmodels + ExecutableExtension de Thimm 2012) : C# branche IKVM 8.14.0 avec org.tweetyproject.tweety-dialogues.dll (source-recompilee depuis agents/dialogues-1.30, Java 8 pur, javac --release 8) invoquee via Assembly.LoadFrom + GetType(''org.tweetyproject.agents.dialogues.ExecutableExtension'') ; Python branche JPype + from org.tweetyproject.agents.dialogues import ExecutableExtension, meme moteur Java runtime. Verdict SOTA-OK (flip 2026-08-22, c.1301+335, myia-po-2025:CoursIA-2, issue #10382) : le pont est LIVRE ET VERIFIE -- PR #10544 MERGED 2026-08-12 (commit e3aa1150a), DLLs trackees sur disque, kernel .NET Interactive execute le twin C# avec vraie instantiation du type ExecutableExtension et debat grounded, sorties reelles commitees. Le RECOVERABLE-LOCAL anterieur datait du moment ou il refutait l''INTRINSIC de #10537 : la livraison a eu lieu depuis, le verdict n''avait pas suivi (stale post-delivery). Residuel (known_difference) : la recompilation de la DLL depuis les sources Java exige un JDK 8+ local (javac --release 8, build documente dans dotnet-build/rebuild-dialogues.sh) -- note de maintenance, pas un gap de bridge.' known_differences: + - '2026-09-15 (PR #16319, myia-po-2026:CoursIA) : enrichissement markdown-only cote C# (tranche densite #13410, +7 cellules d''interpretation) ; cellules code et outputs byte-identiques (md5 avant/apres), twin Python intact.' - 'Socle commun : dialogues multi-agents argumentatifs (protocols, ExecutableExtension) via TweetyProject.' - 'Lib-vs-lib : C# via IKVM (helpers chargeant les DLL TweetyProject). Python via JPype (`from org.tweetyproject.agents.dialogues import ExecutableExtension`). Meme moteur Java.' diff --git a/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues/0007-2026-09-15-myia-po-2026-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues/0007-2026-09-15-myia-po-2026-CoursIA.yaml new file mode 100644 index 0000000000..fe9ac12715 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/tweety-8-agent-dialogues/0007-2026-09-15-myia-po-2026-CoursIA.yaml @@ -0,0 +1,6 @@ +date: '2026-09-15' +by: myia-po-2026:CoursIA +python_sha: 8bdb9e657a4a4c30b5d8205bde366d4877ac7722 +csharp_sha: 4035a6b41c01828d5cb1cc4caeb240b311078348 +content_python_sha: 7ddf3bee05f2f59d955cd1ffa8dc49585b4cae8c695f7b9eed75bf9638e9d73d +content_csharp_sha: 1979839cf1095d54037c338c5360afdd8524468f2833c3b524a8e74bc07a638a