// Exercice 1 : Construisez la formule (a => b) && (b => a) et affichez sa forme DNF.
// Indice : PlParser + .toNnf() ou construction manuelle.
// TODO etudiant : completez ici
Console.WriteLine("Exercice 1 a completer");Exercice 1 a completer
Navigation : <- Tweety-1-Setup | Index serie | Tweety-3-Advanced-Logics ->
Ce notebook est le port C# / .NET de Tweety-02-Basic-Logics-Python.ipynb. Au lieu d’appeler Tweety depuis Python via JPype + JVM, on execute directement les classes Tweety recompilees en bytecode .NET via IKVM - aucune JVM, aucun JDK requis au runtime. Voir le notebook Python pour le contexte théorique complet.
pl) recompilee via IKVM 8.15Proposition, Negation, Conjunction, Disjunction, Implication)PlParserPlBeliefSet) et explorer les mondes possibles (PossibleWorld)Tweety-02-Basic-Logics-Python.ipynb pour les notions (logique propositionnelle, mondes possibles)Plan de route : cinq étapes balisées, toutes exécutées et committées — (1) le runtime IKVM 8.15.0 restauré et vérifié, (2) la DLL Tweety chargée (org.tweetyproject.tweety-pl v1.30.0.0, 7,0 Mo), (3) la construction manuelle de cinq formules propositionnelles par constructeurs, (4) le parsing de la même syntaxe infixée via PlParser, (5) une base de croyances PlBeliefSet de quatre formules — dont vous montrerez qu’elle est involontairement inconsistante. Trois exercices closent le notebook, du DNF à la conséquence logique via SimplePlReasoner. Le fil rouge : le même arbre de formule se construit par l’API C# ou se lit par le DSL texte — deux portes, un AST.
Ce notebook demontre le port .NET fonctionnel de Tweety pour la logique propositionnelle :
| Concept | Classe Tweety (C#) | Statut |
|---|---|---|
| Atome propositionnel | Proposition |
OK |
| Connecteurs | Negation, Conjunction, Disjunction, Implication |
OK |
| Parsing | PlParser.parseFormula |
OK |
| Base de croyances | PlBeliefSet (.add(), .size()) |
OK |
Avantage du port .NET : aucune JVM ni JDK a installer, exécution native dans le kernel .net-csharp. Limitation : seule la logique propositionnelle (cluster pl) est portee dans ce pilote ; les notebooks Python restent canoniques pour la FOL complete, l’argumentation (notebooks 5-7), les MLN (notebook 10), etc. La sémantique via PossibleWorld + SatReasoner.query fera l’objet d’un notebook suivant.
Reprenez ceux du notebook Python, adaptes a l’API C# (méthodes Java minuscules).
Note de parite cross-langage (EPIC #4956) : Le jumeau Python de ce notebook (voir Tweety-02-Basic-Logics-Python.ipynb) utilise jpype pour demarrer une JVM in-process et appeler directement les classes Java de Tweety. Ce notebook C# utilise IKVM pour transpiler statiquement le bytecode Java de Tweety en DLL .NET native (7 Mo charges a l’init, voir cellule 7). Les deux strategies donnent acces au meme API Tweety. Particularite : ce notebook utilise le vrai outil SOTA (IKVM recompilation), contrairement a certains jumeaux Tweety-6/8 (cf PR #7913 c.736) qui reimplementaient Monte-Carlo from-scratch en BCL .NET suite a une DLL IKVM defectueuse. Audit c.739 (2026-07-22) : 0 doc-honesty finding corrigible des deux cotes.
Les chiffres du parcours : un runtime IKVM 8.15.0 vérifié sain (tzdb=True), une DLL org.tweetyproject.tweety-pl v1.30.0.0 de 7,0 Mo chargée et lue, cinq constructions manuelles, deux parses round-trip, une KB de quatre formules — involontairement inconsistante, comme la lecture de la section 5 l’a établi. La chaîne .NET est complète : de la restauration NuGet à la requête logique, chaque maillon a sa preuve d’exécution committée. Les exercices suivants font franchir le dernier palier : de la construction de formules à l’interrogation d’une base.
Exercice 1 (DNF de l’équivalence) : la cible est (a => b) && (b => a) — l’équivalence matérielle. Sa forme normale disjonctive attendue est (a && b) || (!a && !b) : les deux lignes de la table de vérité où a et b coïncident. Deux voies, au choix : construction manuelle puis conversion (new Implication(...) pour chaque flèche, puis la méthode de conversion de la bibliothèque), ou PlParser direct — vérifiez dans les deux cas que le résultat affiché est bien la disjonction des deux cas favorables, pas la simple réécriture des implications ((¬a∨b)∧(a∨¬b) est la CNF, pas la DNF : les deux ne se ressemblent pas et ne sont pas interchangeables à l’affichage près).
Exercice 2 (KB de 4 formules) : reprenez le squelette de la section 5 — PlBeliefSet + PlParser.parseFormula quatre fois. Critère de réussite : la sortie affiche exactement 4 au compteur et l’itération de la collection rend chaque formule. La subtilité de l’exercice n’est pas le code mais le contenu : choisissez vos quatre formules de sorte que la base soit cohérente cette fois (contrairement à celle de la section 5) — vous vérifierez au passage que vous avez identifié pourquoi l’originale ne l’était pas.
Exercice 1 a completer
Progression pédagogique : les exercices 1 et 2 ont introduit PlParser (parsing de formules) et PlBeliefSet (base de croyances). Cet exercice ajoute le raisonneur : etant donne une KB, determiner si une formule est consequence logique (model-theoretic entailment).
Question : soit la KB = {a, a => b, b => c}. La formule c est-elle consequence logique de KB ? Verifiez avec SimplePlReasoner.query(KB, c) (renvoie true/false). Commentez le résultat en termes de chainage modus ponens (a -> b -> c).
Indice : var reasoner = new SimplePlReasoner(); puis bool entailed = reasoner.query(kb, formula); — formula etant un objet PlFormula obtenu via PlParser.parse("c").
Critère de validation détaillé : la question posée est « la formule c est-elle conséquence de KB = {a, a=>b, b=>c} ? » — la réponse attendue est oui, par double modus ponens : a avec a=>b donne b, puis b avec b=>c donne c. Concrètement, SimplePlReasoner.query(kb, f) parcourt les interpretations et vérifie que chaque modèle de la KB satisfait f ; sur une KB de trois formules à trois propositions, l’espace est de 2³ = 8 interpretations — exhaustif et instantané. L’erreur classique à éviter : conclure « non » parce que c n’est pas syntaxiquement dans la KB — la conséquence est sémantique (vérité dans tous les modèles), pas de l’appartenance. Test de bord utile en passant : query(kb, new Negation(new Proposition("a"))) doit retourner faux (a est dans la KB).
// Exercice 3 : Conséquence logique via SimplePlReasoner.
//
// Paysage : KB propositionnelle = { a, a => b, b => c }.
// Question : la formule `c` est-elle consequence logique de KB ?
// Verdict attendu : true (chainage modus ponens : a, a=>b |- b ; b, b=>c |- c).
//
// AIDE : la cellule peut reutiliser `PlParser`, `PlBeliefSet` vus dans les exos 1/2,
// et instancier `SimplePlReasoner` pour le test d'inference.
// Pattern :
// var parser = new PlParser();
// var kb = new PlBeliefSet();
// kb.add(parser.parseFormula("a"));
// kb.add(parser.parseFormula("a => b"));
// kb.add(parser.parseFormula("b => c"));
// var reasoner = new SimplePlReasoner();
// var query = parser.parseFormula("c");
// bool entailed = reasoner.query(kb, query);
// Console.WriteLine($"KB entail c : {entailed}");
//
// NOTE kernel : ce notebook est gated #r "nuget: IKVM, 8.15.0" + #r "org.tweetyproject.tweety-pl.dll"
// (cf. C171 leçon sœur PR #5147). L'execution reelle necessite VS Code Interactive (RECOVERABLE-MACHINE).
// Commit préserve execution_count=null + outputs=[] conformément à Stop & Repair (sota-not-workaround.md).
Console.WriteLine("Exercice 3 a completer — SimplePlReasoner.query(KB, c) sur {a, a=>b, b=>c}");
// TODO etudiant :
// var parser = new PlParser();
// var kb = new PlBeliefSet();
// kb.add(parser.parseFormula("a"));
// kb.add(parser.parseFormula("a => b"));
// kb.add(parser.parseFormula("b => c"));
// var reasoner = new SimplePlReasoner();
// var query = parser.parseFormula("c");
// bool entailed = reasoner.query(kb, query);
// Console.WriteLine($"KB entail c : {entailed}");
//
// Variante : tester aussi KB entail (a & b) → false (KB ne dit pas que a et b sont vrais simultanement).Exercice 3 a completer — SimplePlReasoner.query(KB, c) sur {a, a=>b, b=>c}
Comment Tweety tourne en .NET (sans JVM)
Tweety est une bibliotheque Java. Pour l’utiliser depuis C#, on recompile son bytecode Java en bytecode .NET grace a IKVM :
<IkvmReference>.pl+ ses dependances transitives (fol,logics-commons,math,commons,commons-math3,ojalgo,sat4j) en un unique fat-jar Maven coheren, qui preserve les metadonnees cross-module (un zip-merge artisanal les casserait).org.tweetyproject.tweety-pl.dll(placee a cote de ce notebook) est referencee via#r; IKVM fournit l’exécution de la JVM en .NET. La recette de build complete (POM shade + csproj) est dansdotnet-build/.La cellule suivante configure ce runtime - a executer avant toute utilisation de Tweety.
Ce que « tzdb=True » confirme : la sortie du setup affiche
IKVM 8.15.0 pret (home=ikvm-home-8.15.0-<rid>, tzdb=True), où<rid>désigne la plateforme de la machine (win-x64,linux-x64,osx-arm64…) — la base de données des fuseaux horaires IANA est embarquée et indexée, signe que la couche d’exécution Java est complète et pas seulementCompilee au strict minimum. Ce détail compte pour Tweety : certaines fonctionnalités des librairies Java (sérialisation, localisation) exigent des ressources embarquées que IKVM doit exposer. Le pont n’est pas gratuit pour autant : chaque appel traverse la frontière CLR/JVM — invisible sur des formules unitaires comme ici, mais à garder en tête avant de lancer un solveur sur des milliers d’instances.1. Configuration du runtime IKVM
Lecture de la sortie committée : la ligne
IKVM 8.15.0 pret (home=ikvm-home-8.15.0-<rid>, tzdb=True)est le signal de santé du runtime — version résolue, domicile d’exécution dédié (ikvm-home-8.15.0-<rid>, ce qui évite les collisions entre versions cohabitantes), fuseaux disponibles. C’est la première chose à vérifier quand une cellule Tweety échoue : un IKVM à moitié restauré produit des erreurs trompeuses (types introuvables) qui n’ont rien à voir avec votre logique.2. Chargement de la DLL Tweety
On reference la DLL recompilee. Le cluster
plexpose les espaces de nomsorg.tweetyproject.logics.pl.syntax,org.tweetyproject.logics.pl.parser, etc.Pourquoi la cellule suivante vérifie ce que
#rne dit pas : le commentaire du code invoque le constat #5039 — en .NET Interactive, la directive#rest silencieuse par défaut : elle n’affiche ni succès ni échec de chargement. Une référence cassée (chemin faux, DLL absente) ne se manifeste qu’à la première utilisation, parfois plusieurs cellules plus loin, avec un message d’erreur éloigné de la cause. D’où la cellule de vérification explicite : la sortieTweety (IKVM) reference chargee : org.tweetyproject.tweety-pl v1.30.0.0 (7,0 Mo)prouve que l’assemblage est présent et lisible — vérifier tôt plutôt que diagnostiquer tard.3. Logique propositionnelle - construction manuelle de formules
On construit des formules comme dans le notebook Python, via l’API des classes
Proposition,Negation,Conjunction,Disjunction,Implication.Lecture des cinq constructions committées : la sortie affiche le round-trip
saisie → toString()—a,!b,a&&!c,a||b,(a=>b). Deux observations. D’abord le mécanisme : en C#,&&et||ne sont pas surchargeables — les formules se construisent donc par constructeurs explicites (new Negation(b),new Conjunction(a, new Negation(c)),new Disjunction(a, b),new Implication(a, b)), et c’est letoString()de Tweety qui restitue la syntaxe infixée. Ensuite la normalisation : l’implication seule garde ses parenthèses ((a=>b)) — la précédence de=>étant la plus faible, Tweety les conserve par sécurité ; une conjonction au sein d’une conjon n’aurait pas besoin. Ces cinq formules forment l’alphabet structuré du notebook : chaque construction ultérieure (parse, KB, requêtes) les réutilise.4. Parsing de formules avec
PlParserLe
PlParserlit des formules depuis une chaîne :!(negation),&&(conjonction),||(disjonction),=>(implication),<=>(equivalence),^^(XOR).Lecture du round-trip du parseur :
(a || b) && !csaisie avec espaces et majuscules de lisibilité ressort(a||b)&&!c— le parseur produit exactement le même AST que la construction manuelle de la section précédente (new Conjunction(new Disjunction(a,b), new Negation(c))), seul le rendu textuel diffère. C’est la démonstration qu’il existe deux portes d’entrée vers le même objet : l’API C# typée (verrue : verbeuse) et le DSL texte (concis mais faillible — une parenthèse oubliée devient une exception au lieu d’une erreur de compilation). La seconde ligne introduit l’opérateura^^b: le XOR exclusif, signature syntaxique propre à Tweety (^^), que la logique propositionnelle classique exprime sinon par(a||b)&&!(a&&b). Retenez la règle pratique : constructions manuelles pour les exemples pédagogiques, parseur pour tout ce qui vient d’une source texte (fichier, saisie utilisateur).5. Base de croyances (
PlBeliefSet)Une
PlBeliefSetest un ensemble de formules (base de connaissances). On reproduit la KB du notebook Python. Note d’API : IKVM expose les méthodes Java en minuscules (kb.add(...),kb.size()) - c’est la convention Java, pas les wrappers .NET.Lecture de la KB committée — et son piège : la sortie affiche
KB = { a&&!c, (a=>b), a, !b }, quatre formules. Regardez-la de près : elle est inconsistante, et probablement à l’insu de l’auteur. Deaet(a=>b)le modus ponens tireb; or!best présent — la base affirmebetnon-bà la fois. Ce n’est pas un bug du code mais une propriété logique de la base : en logique classique, une KB inconsistante entraîne n’importe quelle formule (ex falso quodlibet). C’est précisément le problème que Tweety-4 (révision de croyances) et Tweety-3 (mesure d’inconsistance) outillent : détecter, mesurer, réparer. Notez aussi l’ordre d’affichage{ a&&!c, (a=>b), a, !b }— celui de l’insertion, unPlBeliefSetest un ensemble, pas une séquence : aucune sémantique d’ordre à lui prêter.